Merge remote-tracking branch 'origin/6.0'

Conflicts:
	cmake/QtCreatorIDEBranding.cmake
	qbs/modules/qtc/qtc.qbs
	qtcreator_ide_branding.pri

Change-Id: I366a1a0e378811dfc9b4e6f42ec96426dbb15356
This commit is contained in:
Eike Ziller
2021-11-15 13:14:24 +01:00
81 changed files with 653 additions and 372 deletions

View File

@@ -9,7 +9,7 @@ env:
CMAKE_VERSION: 3.21.1 CMAKE_VERSION: 3.21.1
NINJA_VERSION: 1.10.2 NINJA_VERSION: 1.10.2
BUILD_TYPE: Release BUILD_TYPE: Release
CCACHE_VERSION: 4.4 CCACHE_VERSION: 4.5
QT_MIRRORS: download.qt.io;mirrors.ocf.berkeley.edu/qt;ftp.fau.de/qtproject;mirror.bit.edu.cn/qtproject QT_MIRRORS: download.qt.io;mirrors.ocf.berkeley.edu/qt;ftp.fau.de/qtproject;mirror.bit.edu.cn/qtproject
jobs: jobs:

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@@ -38,13 +38,20 @@
build system and uses it or even the build system as such to execute the build system and uses it or even the build system as such to execute the
respective tests. respective tests.
\QC integrates the \l{Qt Test} framework, \QC integrates the following testing frameworks for unit testing
\l{https://github.com/google/googletest}{Google C++ Testing Framework}, applications and libraries:
\l{https://www.boost.org/doc/libs/1_70_0/libs/test/doc/html/index.html}
{Boost.Test}, and \l{https://github.com/catchorg/Catch2} \list
{Catch2 test framework} for unit testing applications and libraries. \li \l{https://www.boost.org/doc/libs/1_70_0/libs/test/doc/html/index.html}
{Boost.Test}
\li \l{https://github.com/catchorg/Catch2}{Catch2 test framework}
\li \l{https://github.com/google/googletest}{Google C++ Testing Framework}
\li \l{Qt Test} framework
\endlist
Additional build system based support is provided for Additional build system based support is provided for
\l{https://cmake.org/cmake/help/latest/manual/ctest.1.html}{CTest}. \l{https://cmake.org/cmake/help/latest/manual/ctest.1.html}{CTest}.
You can use \QC to create, build, and run code based tests for your You can use \QC to create, build, and run code based tests for your
projects. projects.
@@ -332,16 +339,23 @@
in the file currently open in the code editor. in the file currently open in the code editor.
\endlist \endlist
\note By default, \QC builds a project before deploying and running \endlist
it.
By default, \QC builds a project before deploying and running it.
To run all tests without building and deploying them again, select
\uicontrol {Run All Tests Without Deployment} in the context menu.
To run the selected tests without deployment, select
\uicontrol {Run Selected Tests Without Deployment}.
The functions to run tests are also available in the context menu in the
\uicontrol Tests view and in \uicontrol Tools > \uicontrol Tests.
\note If you have enabled build system based and code based tests, \note If you have enabled build system based and code based tests,
you may run tests twice when using \uicontrol {Run All Tests} or you may run tests twice when using \uicontrol {Run All Tests} or
\uicontrol {Run Selected Tests}. This happens if the tests can be \uicontrol {Run Selected Tests}. This happens if the tests can be
found by the code based test frameworks and are registered as test found by the code based test frameworks and are registered as test
with the build system. with the build system.
\endlist
If a test takes more than a minute to execute, the default timeout might If a test takes more than a minute to execute, the default timeout might
stop the test execution. To increase the timeout, select \uicontrol Tools > stop the test execution. To increase the timeout, select \uicontrol Tools >
\uicontrol Options > \uicontrol {Testing} > \uicontrol General. \uicontrol Options > \uicontrol {Testing} > \uicontrol General.
@@ -369,7 +383,8 @@
The test cases are listed in alphabetic, case insensitive order. To list The test cases are listed in alphabetic, case insensitive order. To list
them in the order in which they are defined in the source code, them in the order in which they are defined in the source code,
select \inlineimage leafsort.png (\uicontrol {Sort Naturally}). select \inlineimage leafsort.png
(\uicontrol {Sort Naturally}).
\section2 Running and Debugging Tests from Code Editor \section2 Running and Debugging Tests from Code Editor
@@ -511,7 +526,7 @@
\li To specify settings for running Catch2 tests, select \li To specify settings for running Catch2 tests, select
\uicontrol Tools > \uicontrol Options > \uicontrol {Testing} > \uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
\uicontrol {Catch Test}. \uicontrol {Catch Test}.
\image qtcreator-autotests-options-catch2.png \image qtcreator-autotests-options-catch2.png "Catch Test options"
\li Select the \uicontrol {Show success} check box to show succeeding \li Select the \uicontrol {Show success} check box to show succeeding
expressions as well. By default Catch2 will print only fails. expressions as well. By default Catch2 will print only fails.
\li Select the \uicontrol {Break on failure while debugging} check box \li Select the \uicontrol {Break on failure while debugging} check box
@@ -543,7 +558,7 @@
\li To specify settings for running CTest-based tests, select \li To specify settings for running CTest-based tests, select
\uicontrol Tools > \uicontrol Options > \uicontrol {Testing} > \uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
\uicontrol {CTest}. \uicontrol {CTest}.
//! insert image here \image qtcreator-autotests-options-ctest.png "CTest options"
\li Select the \uicontrol {Output on failure} check box to show test \li Select the \uicontrol {Output on failure} check box to show test
specific output if a test fails. Contrary to the CTest default specific output if a test fails. Contrary to the CTest default
this is enabled by default. this is enabled by default.

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -158,7 +158,7 @@
However, some configuration options are available and you can set them in However, some configuration options are available and you can set them in
\uicontrol Tools > \uicontrol Options > \uicontrol {Version Control} > \uicontrol Tools > \uicontrol Options > \uicontrol {Version Control} >
\uicontrol Common. \uicontrol General.
For more information about the supported functions, see For more information about the supported functions, see
\l{Using Version Control Systems}. \l{Using Version Control Systems}.

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -65,7 +65,7 @@
\li \b {\l{Designing User Interfaces}} \li \b {\l{Designing User Interfaces}}
To create intuitive, modern-looking, fluid user interfaces, you To create intuitive, modern-looking, fluid user interfaces, you
can use \l{Qt Quick} and \QDS. can use \l{Qt Quick} and \l{Qt Design Studio Manual}{\QDS}.
If you need a traditional user interface that is clearly If you need a traditional user interface that is clearly
structured and enforces a platform look and feel, you can use structured and enforces a platform look and feel, you can use
the integrated \QD. For more information, see the integrated \QD. For more information, see
@@ -114,9 +114,10 @@
execution. In addition, the QML Profiler enables you to profile execution. In addition, the QML Profiler enables you to profile
Qt Quick applications. Qt Quick applications.
\QC is integrated to the \l{Qt Test}, Google C++ Testing, and \QC is integrated to the \l{Qt Test}, Boost.Test, Catch 2 test,
Boost.Test frameworks for unit testing applications and and Google C++ Testing frameworks for unit testing applications
libraries. You can use \QC to create, build, and run autotests. and libraries. You can use \QC to create, build, and run
autotests.
For more information, see \l{Testing}. For more information, see \l{Testing}.
\li \b {Publishing} \li \b {Publishing}

View File

@@ -51,7 +51,8 @@
\l{http://doc.qt.io/QtForDeviceCreation/index.html}{Qt for Device Creation} \l{http://doc.qt.io/QtForDeviceCreation/index.html}{Qt for Device Creation}
documentation. documentation.
If you have \QDS installed, you can open \QDS examples from \QC in \QDS. If you have \l{Qt Design Studio Manual}{\QDS} installed, you can open
\QDS examples from \QC in \QDS.
\list 1 \list 1

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of the Qt Creator documentation. ** This file is part of the Qt Creator documentation.
@@ -29,8 +29,8 @@
\section2 Creating Widget-Based Qt for Python Applications \section2 Creating Widget-Based Qt for Python Applications
\l {https://doc.qt.io/qtforpython/index.html}{Qt for Python} enables you \l {https://doc.qt.io/qtforpython/index.html}{Qt for Python} enables you
to use Qt 5 API in Python applications. You can use the PySide2 module to to use Qt 6 API in Python applications. You can use the PySide6 modules
gain access to individual Qt modules, such as \l {Qt Core}, \l {Qt GUI}, to gain access to individual Qt modules, such as \l {Qt Core}, \l {Qt GUI},
and \l {Qt Widgets}. and \l {Qt Widgets}.
The Qt for Python Application wizards generate a \c {.pyproject} file that The Qt for Python Application wizards generate a \c {.pyproject} file that
@@ -46,7 +46,8 @@
The \uicontrol {Qt for Python - Window (UI file)} wizard enables you to The \uicontrol {Qt for Python - Window (UI file)} wizard enables you to
create a Python project that contains the source file for a class. Specify create a Python project that contains the source file for a class. Specify
the class name, base class, and and source file for the class. the PySide version, class name, base class, and and source file for the
class.
\image qtcreator-python-wizard-app-window.png "Qt for Python wizard for creating a widget-based UI" \image qtcreator-python-wizard-app-window.png "Qt for Python wizard for creating a widget-based UI"
@@ -55,21 +56,22 @@
Widgets module, and Qt UI tools: Widgets module, and Qt UI tools:
\badcode \badcode
import sys
import os import os
from pathlib import Path
import sys
from PySide2.QtWidgets import QApplication, QWidget from PySide6.QtWidgets import QApplication, QWidget
from PySide2.QtCore import QFile from PySide6.QtCore import QFile
from PySide2.QtUiTools import QUiLoader from PySide6.QtUiTools import QUiLoader
\endcode \endcode
The wizard also adds a main class with the specified name that The wizard also adds a main class with the specified name that
inherits from the specified base class: inherits from the specified base class:
\badcode \badcode
class MyWidget(QWidget): class Widget(QWidget):
def __init__(self): def __init__(self):
super(MyWidget, self).__init__() super(Widget, self).__init__()
self.load_ui() self.load_ui()
... ...
\endcode \endcode
@@ -80,7 +82,7 @@
\badcode \badcode
def load_ui(self): def load_ui(self):
loader = QUiLoader() loader = QUiLoader()
path = os.path.join(os.path.dirname(__file__), "form.ui") path = os.fspath(Path(__file__).resolve().parent / "form.ui")
ui_file = QFile(path) ui_file = QFile(path)
ui_file.open(QFile.ReadOnly) ui_file.open(QFile.ReadOnly)
loader.load(ui_file, self) loader.load(ui_file, self)
@@ -100,8 +102,8 @@
Next, the wizard instantiates the \c MainWindow class and shows it: Next, the wizard instantiates the \c MainWindow class and shows it:
\badcode \badcode
window = MyWidget() widget = Widget()
window.show() widget.show()
... ...
\endcode \endcode
@@ -153,12 +155,12 @@
to QGuiApplication and QQmlApplicationEngine: to QGuiApplication and QQmlApplicationEngine:
\badcode \badcode
import sys
import os import os
from pathlib import Path
import sys
from PySide2.QtGui import QGuiApplication from PySide6.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine from PySide6.QtQml import QQmlApplicationEngine
\endcode \endcode
The wizard also adds a main function, where it creates a QGuiApplication The wizard also adds a main function, where it creates a QGuiApplication
@@ -175,7 +177,7 @@
\badcode \badcode
engine = QQmlApplicationEngine() engine = QQmlApplicationEngine()
engine.load(os.path.join(os.path.dirname(__file__), "main.qml")) engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
\endcode \endcode
Finally, the wizard adds code that checks whether the file was successfully Finally, the wizard adds code that checks whether the file was successfully
@@ -190,7 +192,7 @@
\endcode \endcode
Open the .qml file in the \uicontrol Edit mode to design a Qt Quick UI, or Open the .qml file in the \uicontrol Edit mode to design a Qt Quick UI, or
use \QDS. use \l{Qt Design Studio Manual}{\QDS}.
//! [python qml project wizards] //! [python qml project wizards]
*/ */

View File

@@ -35,13 +35,8 @@
\image qtcreator-open-documents-view.png "Open Documents view" \image qtcreator-open-documents-view.png "Open Documents view"
You can use the context menu to apply some of the functions also available You can use the context menu to apply some of the functions also available
in the \uicontrol File menu in the \uicontrol File menu and in the \l {File System Context Menu}
\if defined(qtcreator) {File System} view to the file that is selected in the view.
.
\else
and in the \l {File System Context Menu} {File System} view to the file
that is selected in the view.
\endif
In addition, you can: In addition, you can:

View File

@@ -293,6 +293,7 @@
style. style.
\endif \endif
You can use \QC in the following modes: You can use \QC in the following modes:
\list \list
@@ -487,8 +488,8 @@
The pane filters out irrelevant output from the build tools and presents the The pane filters out irrelevant output from the build tools and presents the
issues in an organized way. To further filter the output by type, select issues in an organized way. To further filter the output by type, select
\uicontrol {Filter Tree} \inlineimage filtericon.png
and then select a filter. (\uicontrol {Filter Tree}) and then select a filter.
\image qtcreator-issues.png "Issues output pane" \image qtcreator-issues.png "Issues output pane"
@@ -550,9 +551,10 @@
To specify settings for displaying application output, select To specify settings for displaying application output, select
\uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} > \uicontrol Tools > \uicontrol Options > \uicontrol {Build & Run} >
\uicontrol {Application Output}, or click the \uicontrol {Open Settings Page} \uicontrol {Application Output}, or click the \inlineimage settings.png
button. You can select whether to open the \uicontrol{Application Output} pane (\uicontrol {Open Settings Page}) button. You can select whether to open
on output when running or debugging applications, to clear old output on a new run, the \uicontrol{Application Output} pane on output when running or debugging
applications, to clear old output on a new run,
to word-wrap output, and to limit output to the specified number of lines. to word-wrap output, and to limit output to the specified number of lines.
\section1 Compile Output \section1 Compile Output
@@ -575,8 +577,8 @@
In the \uicontrol {Limit output to} field, you can specify the maximum In the \uicontrol {Limit output to} field, you can specify the maximum
amount of build output lines to display in the pane. amount of build output lines to display in the pane.
You can also reach the options page by clicking the \uicontrol {Open Settings Page} You can also reach the options page by clicking \inlineimage settings.png
button. (\uicontrol {Open Settings Page}).
To copy the output from the pane to the clipboard, select To copy the output from the pane to the clipboard, select
\uicontrol {Select All} in the context menu, and then select \uicontrol {Select All} in the context menu, and then select

View File

@@ -97,12 +97,14 @@
\list \list
\li To see a complete list of all bindings, select \li To see a complete list of all bindings, select
\uicontrol {Filter Tree} > \uicontrol {Show All Bindings}. \inlineimage filtericon.png
(\uicontrol {Filter Tree}) > \uicontrol {Show All Bindings}.
\li To sort types or symbols alphabetically, select \li To sort types or symbols alphabetically, select
\inlineimage sort_alphabetically.png \inlineimage sort_alphabetically.png
(\uicontrol {Sort Alphabetically}). (\uicontrol {Sort Alphabetically}).
\li To stop the synchronization with the type or symbol selected in the \li To stop the synchronization with the type or symbol selected in the
editor, deselect \uicontrol {Synchronize with Editor}. editor, deselect \inlineimage linkicon.png
(\uicontrol {Synchronize with Editor}).
\endlist \endlist
\section1 Viewing the Class Hierarchy \section1 Viewing the Class Hierarchy
@@ -144,5 +146,6 @@
\image qtcreator-include-hierarchy-view.png "Include Hierarchy view" \image qtcreator-include-hierarchy-view.png "Include Hierarchy view"
To keep the view synchronized with the file currently opened in the editor, To keep the view synchronized with the file currently opened in the editor,
select \uicontrol {Synchronize with Editor}. select \inlineimage linkicon.png
(\uicontrol {Synchronize with Editor}).
*/ */

View File

@@ -25,10 +25,11 @@
#include "qmlstatenodeinstance.h" #include "qmlstatenodeinstance.h"
#include <qmlprivategate.h>
#include "qmlpropertychangesnodeinstance.h" #include "qmlpropertychangesnodeinstance.h"
#include <qmlprivategate.h>
#include <designersupportdelegate.h>
namespace QmlDesigner { namespace QmlDesigner {
namespace Internal { namespace Internal {
@@ -53,12 +54,28 @@ QmlStateNodeInstance::Pointer
return instance; return instance;
} }
void setAllNodesDirtyRecursive(QQuickItem *parentItem)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
Q_UNUSED(parentItem)
#else
if (!parentItem)
return;
const QList<QQuickItem *> children = parentItem->childItems();
for (QQuickItem *childItem : children)
setAllNodesDirtyRecursive(childItem);
DesignerSupport::addDirty(parentItem, QQuickDesignerSupport::Content);
#endif
}
void QmlStateNodeInstance::activateState() void QmlStateNodeInstance::activateState()
{ {
if (!QmlPrivateGate::States::isStateActive(object(), context()) if (!QmlPrivateGate::States::isStateActive(object(), context())
&& nodeInstanceServer()->hasInstanceForObject(object())) { && nodeInstanceServer()->hasInstanceForObject(object())) {
nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object())); nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object()));
QmlPrivateGate::States::activateState(object(), context()); QmlPrivateGate::States::activateState(object(), context());
setAllNodesDirtyRecursive(nodeInstanceServer()->rootItem());
} }
} }

View File

@@ -1858,7 +1858,11 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
#ifdef QUICK3D_MODULE #ifdef QUICK3D_MODULE
if (qobject_cast<QQuick3DModel *>(object) if (qobject_cast<QQuick3DModel *>(object)
|| qobject_cast<QQuick3DCamera *>(object) || qobject_cast<QQuick3DCamera *>(object)
|| qobject_cast<QQuick3DAbstractLight *>(object)) { || qobject_cast<QQuick3DAbstractLight *>(object)
#ifdef QUICK3D_PARTICLES_MODULE
|| qobject_cast<QQuick3DParticleSystem *>(object)
#endif
) {
return true; return true;
} }
// Node is a component if it has node children that have no instances // Node is a component if it has node children that have no instances

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -202,8 +202,8 @@ Item {
dialogBox.setScreenSizeIndex(index); dialogBox.setScreenSizeIndex(index);
var r = screenSizeModel.screenSizes(index); var r = screenSizeModel.screenSizes(index);
widthTextField.text = r.width; widthField.realValue = r.width;
heightTextField.text = r.height; heightField.realValue = r.height;
} }
Connections { Connections {
@@ -252,19 +252,20 @@ Item {
} }
// content items // content items
SC.TextField { SC.RealSpinBox {
id: widthTextField id: widthField
actionIndicatorVisible: false actionIndicatorVisible: false
translationIndicatorVisible: false implicitWidth: 70
implicitWidth: 50 labelColor: DialogValues.textColor
color: DialogValues.textColor realFrom: 100
selectByMouse: true realTo: 100000
validator: IntValidator { bottom: 1; top: 100000; } realValue: 100
realStepSize: 10
font.pixelSize: DialogValues.defaultPixelSize font.pixelSize: DialogValues.defaultPixelSize
onTextChanged: { onRealValueChanged: {
var height = heightTextField.text ? parseInt(heightTextField.text) : 0 var height = heightField.realValue
var width = text ? parseInt(text) : 0 var width = realValue
if (width >= height) if (width >= height)
orientationButton.setHorizontal() orientationButton.setHorizontal()
@@ -276,22 +277,23 @@ Item {
Binding { Binding {
target: dialogBox target: dialogBox
property: "customWidth" property: "customWidth"
value: widthTextField.text value: widthField.realValue
} }
SC.TextField { SC.RealSpinBox {
id: heightTextField id: heightField
actionIndicatorVisible: false actionIndicatorVisible: false
translationIndicatorVisible: false implicitWidth: 70
implicitWidth: 50 labelColor: DialogValues.textColor
color: DialogValues.textColor realFrom: 100
selectByMouse: true realTo: 100000
validator: IntValidator { bottom: 1; top: 100000; } realValue: 100
realStepSize: 10
font.pixelSize: DialogValues.defaultPixelSize font.pixelSize: DialogValues.defaultPixelSize
onTextChanged: { onRealValueChanged: {
var height = text ? parseInt(text) : 0 var height = realValue
var width = widthTextField.text ? parseInt(widthTextField.text) : 0 var width = widthField.realValue
if (width >= height) if (width >= height)
orientationButton.setHorizontal() orientationButton.setHorizontal()
@@ -303,7 +305,7 @@ Item {
Binding { Binding {
target: dialogBox target: dialogBox
property: "customHeight" property: "customHeight"
value: heightTextField.text value: heightField.realValue
} }
Item { Layout.fillWidth: true } Item { Layout.fillWidth: true }
@@ -348,9 +350,8 @@ Item {
} }
onClicked: { onClicked: {
if (widthTextField.text && heightTextField.text) { if (widthField.realValue && heightField.realValue) {
[widthTextField.text, heightTextField.text] = [heightTextField.text, widthTextField.text]; [widthField.realValue, heightField.realValue] = [heightField.realValue, widthField.realValue];
checked = !checked checked = !checked
} }
} }

View File

@@ -29,7 +29,7 @@ import QtQuick.Controls
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import newprojectdialog import NewProjectDialog
Item { Item {
anchors.fill: parent anchors.fill: parent

View File

@@ -158,16 +158,15 @@ QtObject {
readonly property string transparent: "\u0099" readonly property string transparent: "\u0099"
readonly property string triState: "\u009A" readonly property string triState: "\u009A"
readonly property string triangleArcA: "\u009B" readonly property string triangleArcA: "\u009B"
readonly property string triangleArcB: "\u009C" readonly property string triangleArcB: "\u009D"
readonly property string triangleCornerA: "\u009D" readonly property string triangleCornerA: "\u009E"
readonly property string triangleCornerB: "\u009E" readonly property string triangleCornerB: "\u009F"
readonly property string unLinked: "\u009F" readonly property string unLinked: "\u00A0"
readonly property string undo: "\u00A0" readonly property string undo: "\u00A1"
readonly property string unpin: "\u00A1" readonly property string unpin: "\u00A2"
readonly property string upDownIcon: "\u00A2" readonly property string upDownIcon: "\u00A3"
readonly property string upDownSquare2: "\u00A3" readonly property string upDownSquare2: "\u00A4"
readonly property string visibilityOffBroken: "\u00A4" // visibilityOff readonly property string visibilityOff: "\u00A5"
readonly property string visibilityOff: "\u00A5" // visibilityOff2
readonly property string visibilityOn: "\u00A6" readonly property string visibilityOn: "\u00A6"
readonly property string wildcard: "\u00A7" readonly property string wildcard: "\u00A7"
readonly property string wizardsAutomotive: "\u00A8" readonly property string wizardsAutomotive: "\u00A8"
@@ -175,12 +174,12 @@ QtObject {
readonly property string wizardsGeneric: "\u00AA" readonly property string wizardsGeneric: "\u00AA"
readonly property string wizardsMcuEmpty: "\u00AB" readonly property string wizardsMcuEmpty: "\u00AB"
readonly property string wizardsMcuGraph: "\u00AC" readonly property string wizardsMcuGraph: "\u00AC"
readonly property string wizardsMobile: "\u00AD" readonly property string wizardsMobile: "\u00AE"
readonly property string wizardsUnknown: "\u00AE" readonly property string wizardsUnknown: "\u00AF"
readonly property string zoomAll: "\u00AF" readonly property string zoomAll: "\u00B0"
readonly property string zoomIn: "\u00B0" readonly property string zoomIn: "\u00B1"
readonly property string zoomOut: "\u00B1" readonly property string zoomOut: "\u00B2"
readonly property string zoomSelection: "\u00B2" readonly property string zoomSelection: "\u00B3"
readonly property font iconFont: Qt.font({ readonly property font iconFont: Qt.font({
"family": controlIcons.name, "family": controlIcons.name,

View File

@@ -794,8 +794,10 @@ bool Check::visit(UiObjectInitializer *)
UiQualifiedId *qualifiedTypeId = qualifiedTypeNameId(parent()); UiQualifiedId *qualifiedTypeId = qualifiedTypeNameId(parent());
if (qualifiedTypeId) { if (qualifiedTypeId) {
typeName = qualifiedTypeId->name.toString(); typeName = qualifiedTypeId->name.toString();
if (typeName == "Component") if (typeName == "Component") {
m_idStack.push(StringSet()); m_idStack.push(StringSet());
_componentChildCount = 0;
}
} }
m_typeStack.push(typeName); m_typeStack.push(typeName);
@@ -806,10 +808,23 @@ bool Check::visit(UiObjectInitializer *)
return true; return true;
} }
void Check::endVisit(UiObjectInitializer *) void Check::endVisit(UiObjectInitializer *uiObjectInitializer)
{ {
m_propertyStack.pop(); m_propertyStack.pop();
m_typeStack.pop();
const QString type = m_typeStack.pop();
if (type == "Component" && _componentChildCount == 0) {
SourceLocation loc;
UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(parent());
if (objectDefinition)
loc = objectDefinition->qualifiedTypeNameId->identifierToken;
UiObjectBinding *objectBinding = cast<UiObjectBinding *>(parent());
if (objectBinding)
loc = objectBinding->qualifiedTypeNameId->identifierToken;
addMessage(WarnComponentRequiresChildren, loc);
}
UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(parent()); UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(parent());
if (objectDefinition && objectDefinition->qualifiedTypeNameId->name == QLatin1String("Component")) if (objectDefinition && objectDefinition->qualifiedTypeNameId->name == QLatin1String("Component"))
m_idStack.pop(); m_idStack.pop();
@@ -962,6 +977,12 @@ void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
addMessage(ErrUnsupportedRootTypeInQmlUi, addMessage(ErrUnsupportedRootTypeInQmlUi,
locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation()), typeName); locationFromRange(ast->firstSourceLocation(), ast->lastSourceLocation()), typeName);
if (!m_typeStack.isEmpty() && m_typeStack.last() == "Component") {
_componentChildCount++;
if (_componentChildCount > 1)
addMessage(ErrToManyComponentChildren, typeErrorLocation);
}
bool typeError = false; bool typeError = false;
if (_importsOk) { if (_importsOk) {
const ObjectValue *prototype = _context->lookupType(_doc.data(), typeId); const ObjectValue *prototype = _context->lookupType(_doc.data(), typeId);

View File

@@ -158,6 +158,7 @@ private:
bool _importsOk; bool _importsOk;
bool _inStatementBinding; bool _inStatementBinding;
int _componentChildCount = 0;
const Imports *_imports; const Imports *_imports;
TranslationFunction lastTransLationfunction = noTranslationfunction; TranslationFunction lastTransLationfunction = noTranslationfunction;
}; };

View File

@@ -251,6 +251,10 @@ StaticAnalysisMessages::StaticAnalysisMessages()
tr("Type cannot be instantiated recursively (%1)."), 1); tr("Type cannot be instantiated recursively (%1)."), 1);
newMsg(WarnLogicalValueDoesNotDependOnValues, Warning, newMsg(WarnLogicalValueDoesNotDependOnValues, Warning,
tr("Logical value does not depend on actual values")); tr("Logical value does not depend on actual values"));
newMsg(ErrToManyComponentChildren, Error,
tr("Components are only allowed to have a single child element."));
newMsg(WarnComponentRequiresChildren, Warning,
tr("Components require a child element."));
} }
} // anonymous namespace } // anonymous namespace

View File

@@ -132,6 +132,8 @@ enum Type {
ErrInvalidArrayValueLength = 323, ErrInvalidArrayValueLength = 323,
ErrHitMaximumRecursion = 324, ErrHitMaximumRecursion = 324,
WarnLogicalValueDoesNotDependOnValues = 325, WarnLogicalValueDoesNotDependOnValues = 325,
ErrToManyComponentChildren = 326,
WarnComponentRequiresChildren = 327,
WarnDuplicateImport = 400 WarnDuplicateImport = 400
}; };

View File

@@ -37,7 +37,10 @@
#include <projectexplorer/devicesupport/devicemanager.h> #include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/devicesupport/idevicewidget.h> #include <projectexplorer/devicesupport/idevicewidget.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/runconfiguration.h> #include <projectexplorer/runconfiguration.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
#include <utils/runextensions.h> #include <utils/runextensions.h>
@@ -418,11 +421,19 @@ QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const
void AndroidDeviceManager::updateDevicesList() void AndroidDeviceManager::updateDevicesList()
{ {
connect(&m_devicesUpdaterTimer, &QTimer::timeout, this, [this]() { // If a non-Android Kit is currently active, skip the device list update
const Target *startupTarget = SessionManager::startupTarget();
if (!startupTarget)
return;
const Kit *kit = startupTarget->kit();
if (!kit)
return;
if (DeviceTypeKitAspect::deviceTypeId(kit) != Constants::ANDROID_DEVICE_TYPE)
return;
updateDevicesListOnce(); updateDevicesListOnce();
});
updateDevicesListOnce();
m_devicesUpdaterTimer.start(deviceUpdaterMsInterval);
} }
void AndroidDeviceManager::updateDevicesListOnce() void AndroidDeviceManager::updateDevicesListOnce()
@@ -537,11 +548,17 @@ void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
void AndroidDeviceManager::setupDevicesWatcher() void AndroidDeviceManager::setupDevicesWatcher()
{ {
if (!m_devicesUpdaterTimer.isActive()) {
// The call to avdmanager is always slower than the call to adb devices, // The call to avdmanager is always slower than the call to adb devices,
// so connecting the slot to the slower call should be enough. // so connecting the slot to the slower call should be enough.
connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished, connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished,
this, &AndroidDeviceManager::devicesListUpdated); this, &AndroidDeviceManager::devicesListUpdated);
connect(&m_devicesUpdaterTimer, &QTimer::timeout, this, [this]() {
updateDevicesList(); updateDevicesList();
});
m_devicesUpdaterTimer.start(deviceUpdaterMsInterval);
}
updateDevicesListOnce();
} }
void AndroidDeviceManager::devicesListUpdated() void AndroidDeviceManager::devicesListUpdated()

View File

@@ -83,21 +83,9 @@ FilePath ITestConfiguration::executableFilePath() const
if (!hasExecutable()) if (!hasExecutable())
return {}; return {};
if (m_runnable.command.executable().isExecutableFile() && m_runnable.command.executable().path() != ".") { const Environment env = m_runnable.environment.size() == 0 ? Environment::systemEnvironment()
return m_runnable.command.executable().absoluteFilePath(); : m_runnable.environment;
} else if (m_runnable.command.executable().path() == "."){ return env.searchInPath(m_runnable.command.executable().path());
QString fullCommandFileName = m_runnable.command.executable().toString();
// TODO: check if we can use searchInPath() from Utils::Environment
const QStringList &pathList = m_runnable.environment.toProcessEnvironment().value("PATH")
.split(HostOsInfo::pathListSeparator());
for (const QString &path : pathList) {
QString filePath(path + QDir::separator() + fullCommandFileName);
if (QFileInfo(filePath).isExecutable())
return m_runnable.command.executable().absoluteFilePath();
}
}
return {};
} }
Environment ITestConfiguration::filteredEnvironment(const Environment &original) const Environment ITestConfiguration::filteredEnvironment(const Environment &original) const

View File

@@ -338,7 +338,9 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper()
return createProposal(); return createProposal();
break; break;
case ClangCompletionContextAnalyzer::CompleteIncludePath: case ClangCompletionContextAnalyzer::CompleteIncludePath:
if (completeInclude(analyzer.positionEndOfExpression())) m_completions = completeInclude(analyzer.positionEndOfExpression(), m_completionOperator,
m_interface.data(), m_interface->headerPaths());
if (!m_completions.isEmpty())
return createProposal(); return createProposal();
break; break;
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective: case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
@@ -441,38 +443,46 @@ bool ClangCompletionAssistProcessor::accepts() const
/** /**
* @brief Creates completion proposals for #include and given cursor * @brief Creates completion proposals for #include and given cursor
* @param cursor - cursor placed after opening bracked or quote * @param position - cursor placed after opening bracked or quote
* @return false if completions list is empty * @param completionOperator - the type of token
* @param interface - relevant document data
* @param headerPaths - the include paths
* @return the list of completion items
*/ */
bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor) QList<AssistProposalItemInterface *> ClangCompletionAssistProcessor::completeInclude(
int position, unsigned completionOperator, const TextEditor::AssistInterface *interface,
const ProjectExplorer::HeaderPaths &headerPaths)
{ {
QTextCursor cursor(interface->textDocument());
cursor.setPosition(position);
QString directoryPrefix; QString directoryPrefix;
if (m_completionOperator == T_SLASH) { if (completionOperator == T_SLASH) {
QTextCursor c = cursor; QTextCursor c = cursor;
c.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); c.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
QString sel = c.selectedText(); QString sel = c.selectedText();
int startCharPos = sel.indexOf(QLatin1Char('"')); int startCharPos = sel.indexOf(QLatin1Char('"'));
if (startCharPos == -1) { if (startCharPos == -1) {
startCharPos = sel.indexOf(QLatin1Char('<')); startCharPos = sel.indexOf(QLatin1Char('<'));
m_completionOperator = T_ANGLE_STRING_LITERAL; completionOperator = T_ANGLE_STRING_LITERAL;
} else { } else {
m_completionOperator = T_STRING_LITERAL; completionOperator = T_STRING_LITERAL;
} }
if (startCharPos != -1) if (startCharPos != -1)
directoryPrefix = sel.mid(startCharPos + 1, sel.length() - 1); directoryPrefix = sel.mid(startCharPos + 1, sel.length() - 1);
} }
// Make completion for all relevant includes // Make completion for all relevant includes
ProjectExplorer::HeaderPaths headerPaths = m_interface->headerPaths(); ProjectExplorer::HeaderPaths allHeaderPaths = headerPaths;
const auto currentFilePath = ProjectExplorer::HeaderPath::makeUser( const auto currentFilePath = ProjectExplorer::HeaderPath::makeUser(
m_interface->filePath().toFileInfo().path()); interface->filePath().toFileInfo().path());
if (!headerPaths.contains(currentFilePath)) if (!allHeaderPaths.contains(currentFilePath))
headerPaths.append(currentFilePath); allHeaderPaths.append(currentFilePath);
const ::Utils::MimeType mimeType = ::Utils::mimeTypeForName("text/x-c++hdr"); const ::Utils::MimeType mimeType = ::Utils::mimeTypeForName("text/x-c++hdr");
const QStringList suffixes = mimeType.suffixes(); const QStringList suffixes = mimeType.suffixes();
foreach (const ProjectExplorer::HeaderPath &headerPath, headerPaths) { QList<AssistProposalItemInterface *> completions;
foreach (const ProjectExplorer::HeaderPath &headerPath, allHeaderPaths) {
QString realPath = headerPath.path; QString realPath = headerPath.path;
if (!directoryPrefix.isEmpty()) { if (!directoryPrefix.isEmpty()) {
realPath += QLatin1Char('/'); realPath += QLatin1Char('/');
@@ -480,11 +490,11 @@ bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor)
if (headerPath.type == ProjectExplorer::HeaderPathType::Framework) if (headerPath.type == ProjectExplorer::HeaderPathType::Framework)
realPath += QLatin1String(".framework/Headers"); realPath += QLatin1String(".framework/Headers");
} }
completeIncludePath(realPath, suffixes); completions << completeIncludePath(realPath, suffixes, completionOperator);
} }
QList<QPair<AssistProposalItemInterface *, QString>> completionsForSorting; QList<QPair<AssistProposalItemInterface *, QString>> completionsForSorting;
for (AssistProposalItemInterface * const item : qAsConst(m_completions)) { for (AssistProposalItemInterface * const item : qAsConst(completions)) {
QString s = item->text(); QString s = item->text();
s.replace('/', QChar(0)); // The dir separator should compare less than anything else. s.replace('/', QChar(0)); // The dir separator should compare less than anything else.
completionsForSorting << qMakePair(item, s); completionsForSorting << qMakePair(item, s);
@@ -493,26 +503,21 @@ bool ClangCompletionAssistProcessor::completeInclude(const QTextCursor &cursor)
return left.second < right.second; return left.second < right.second;
}); });
for (int i = 0; i < completionsForSorting.count(); ++i) for (int i = 0; i < completionsForSorting.count(); ++i)
m_completions[i] = completionsForSorting[i].first; completions[i] = completionsForSorting[i].first;
return !m_completions.isEmpty(); return completions;
}
bool ClangCompletionAssistProcessor::completeInclude(int position)
{
QTextCursor textCursor(m_interface->textDocument()); // TODO: Simplify, move into function
textCursor.setPosition(position);
return completeInclude(textCursor);
} }
/** /**
* @brief Adds #include completion proposals using given include path * @brief Finds #include completion proposals using given include path
* @param realPath - one of directories where compiler searches includes * @param realPath - one of directories where compiler searches includes
* @param suffixes - file suffixes for C/C++ header files * @param suffixes - file suffixes for C/C++ header files
* @return a list of matching completion items
*/ */
void ClangCompletionAssistProcessor::completeIncludePath(const QString &realPath, QList<AssistProposalItemInterface *> ClangCompletionAssistProcessor::completeIncludePath(
const QStringList &suffixes) const QString &realPath, const QStringList &suffixes, unsigned completionOperator)
{ {
QList<AssistProposalItemInterface *> completions;
QDirIterator i(realPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); QDirIterator i(realPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
//: Parent folder for proposed #include completion //: Parent folder for proposed #include completion
const QString hint = tr("Location: %1").arg(QDir::toNativeSeparators(QDir::cleanPath(realPath))); const QString hint = tr("Location: %1").arg(QDir::toNativeSeparators(QDir::cleanPath(realPath)));
@@ -529,10 +534,11 @@ void ClangCompletionAssistProcessor::completeIncludePath(const QString &realPath
item->setText(text); item->setText(text);
item->setDetail(hint); item->setDetail(hint);
item->setIcon(CPlusPlus::Icons::keywordIcon()); item->setIcon(CPlusPlus::Icons::keywordIcon());
item->setCompletionOperator(m_completionOperator); item->setCompletionOperator(completionOperator);
m_completions.append(item); completions.append(item);
} }
} }
return completions;
} }
bool ClangCompletionAssistProcessor::completePreprocessorDirectives() bool ClangCompletionAssistProcessor::completePreprocessorDirectives()

View File

@@ -34,6 +34,11 @@
#include <QCoreApplication> #include <QCoreApplication>
#include <QTextCursor> #include <QTextCursor>
namespace TextEditor {
class AssistInterface;
class AssistProposalItemInterface;
}
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
@@ -48,6 +53,11 @@ public:
ClangCompletionAssistProcessor(); ClangCompletionAssistProcessor();
~ClangCompletionAssistProcessor() override; ~ClangCompletionAssistProcessor() override;
static QList<TextEditor::AssistProposalItemInterface *> completeInclude(
int position, unsigned completionOperator,
const TextEditor::AssistInterface *interface,
const ProjectExplorer::HeaderPaths &headerPaths);
TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override; TextEditor::IAssistProposal *perform(const TextEditor::AssistInterface *interface) override;
void handleAvailableCompletions(const CodeCompletions &completions); void handleAvailableCompletions(const CodeCompletions &completions);
@@ -65,12 +75,10 @@ private:
TextEditor::IAssistProposal *createProposal(); TextEditor::IAssistProposal *createProposal();
TextEditor::IAssistProposal *createFunctionHintProposal( TextEditor::IAssistProposal *createFunctionHintProposal(
const CodeCompletions &completions); const CodeCompletions &completions);
QList<TextEditor::AssistProposalItemInterface *> toAssistProposalItems( QList<TextEditor::AssistProposalItemInterface *> toAssistProposalItems(
const CodeCompletions &completions) const; const CodeCompletions &completions) const;
bool completeInclude(const QTextCursor &cursor); static QList<TextEditor::AssistProposalItemInterface *> completeIncludePath(
bool completeInclude(int position); const QString &realPath, const QStringList &suffixes, unsigned completionOperator);
void completeIncludePath(const QString &realPath, const QStringList &suffixes);
bool completePreprocessorDirectives(); bool completePreprocessorDirectives();
bool completeDoxygenKeywords(); bool completeDoxygenKeywords();
void addCompletionItem(const QString &text, void addCompletionItem(const QString &text,

View File

@@ -25,6 +25,7 @@
#include "clangdclient.h" #include "clangdclient.h"
#include "clangcompletionassistprocessor.h"
#include "clangcompletioncontextanalyzer.h" #include "clangcompletioncontextanalyzer.h"
#include "clangdiagnosticmanager.h" #include "clangdiagnosticmanager.h"
#include "clangmodelmanagersupport.h" #include "clangmodelmanagersupport.h"
@@ -66,6 +67,7 @@
#include <texteditor/texteditor.h> #include <texteditor/texteditor.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/runextensions.h> #include <utils/runextensions.h>
#include <utils/utilsicons.h>
#include <QCheckBox> #include <QCheckBox>
#include <QDateTime> #include <QDateTime>
@@ -810,14 +812,15 @@ public:
}; };
enum class CustomAssistMode { Doxygen, Preprocessor }; enum class CustomAssistMode { Doxygen, Preprocessor, IncludePath };
class CustomAssistProcessor : public IAssistProcessor class CustomAssistProcessor : public IAssistProcessor
{ {
public: public:
CustomAssistProcessor(ClangdClient *client, int position, unsigned completionOperator, CustomAssistProcessor(ClangdClient *client, int position, int endPos,
CustomAssistMode mode) unsigned completionOperator, CustomAssistMode mode)
: m_client(client) : m_client(client)
, m_position(position) , m_position(position)
, m_endPos(endPos)
, m_completionOperator(completionOperator) , m_completionOperator(completionOperator)
, m_mode(mode) , m_mode(mode)
{} {}
@@ -833,7 +836,7 @@ private:
CPlusPlus::Icons::keywordIcon()); CPlusPlus::Icons::keywordIcon());
} }
break; break;
case CustomAssistMode::Preprocessor: case CustomAssistMode::Preprocessor: {
static QIcon macroIcon = Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro); static QIcon macroIcon = Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro);
for (const QString &completion for (const QString &completion
: CppEditor::CppCompletionAssistProcessor::preprocessorCompletions()) { : CppEditor::CppCompletionAssistProcessor::preprocessorCompletions()) {
@@ -843,6 +846,17 @@ private:
completions << createItem("import", macroIcon); completions << createItem("import", macroIcon);
break; break;
} }
case ClangCodeModel::Internal::CustomAssistMode::IncludePath: {
HeaderPaths headerPaths;
const CppEditor::ProjectPart::ConstPtr projectPart
= projectPartForFile(interface->filePath().toString());
if (projectPart)
headerPaths = projectPart->headerPaths;
completions = ClangCompletionAssistProcessor::completeInclude(
m_endPos, m_completionOperator, interface, headerPaths);
break;
}
}
GenericProposalModelPtr model(new GenericProposalModel); GenericProposalModelPtr model(new GenericProposalModel);
model->loadContent(completions); model->loadContent(completions);
const auto proposal = new GenericProposal(m_position, model); const auto proposal = new GenericProposal(m_position, model);
@@ -864,6 +878,7 @@ private:
ClangdClient * const m_client; ClangdClient * const m_client;
const int m_position; const int m_position;
const int m_endPos;
const unsigned m_completionOperator; const unsigned m_completionOperator;
const CustomAssistMode m_mode; const CustomAssistMode m_mode;
}; };
@@ -1110,6 +1125,12 @@ public:
using LanguageClientCompletionItem::LanguageClientCompletionItem; using LanguageClientCompletionItem::LanguageClientCompletionItem;
void apply(TextDocumentManipulatorInterface &manipulator, void apply(TextDocumentManipulatorInterface &manipulator,
int basePosition) const override; int basePosition) const override;
enum class SpecialQtType { Signal, Slot, None };
static SpecialQtType getQtType(const CompletionItem &item);
private:
QIcon icon() const override;
}; };
class ClangdClient::ClangdCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor class ClangdClient::ClangdCompletionAssistProcessor : public LanguageClientCompletionAssistProcessor
@@ -1155,15 +1176,7 @@ ClangdClient::ClangdCompletionAssistProcessor::generateCompletionItems(
// whether the cursor was on the second argument of a (dis)connect() call. // whether the cursor was on the second argument of a (dis)connect() call.
// If so, we offer only signals, as nothing else makes sense in that context. // If so, we offer only signals, as nothing else makes sense in that context.
static const auto criterion = [](const CompletionItem &ci) { static const auto criterion = [](const CompletionItem &ci) {
const Utils::optional<MarkupOrString> doc = ci.documentation(); return ClangdCompletionItem::getQtType(ci) == ClangdCompletionItem::SpecialQtType::Signal;
if (!doc)
return false;
QString docText;
if (Utils::holds_alternative<QString>(*doc))
docText = Utils::get<QString>(*doc);
else if (Utils::holds_alternative<MarkupContent>(*doc))
docText = Utils::get<MarkupContent>(*doc).content();
return docText.contains("Annotation: qt_signal");
}; };
const QTextDocument *doc = document(); const QTextDocument *doc = document();
const int pos = basePos(); const int pos = basePos();
@@ -1526,6 +1539,30 @@ QString ClangdClient::displayNameFromDocumentSymbol(SymbolKind kind, const QStri
} }
} }
// Force re-parse of all open files that include the changed ui header.
// Otherwise, we potentially have stale diagnostics.
void ClangdClient::handleUiHeaderChange(const QString &fileName)
{
const QRegularExpression includeRex("#include.*" + fileName + R"([>"])");
const QVector<Client *> &allClients = LanguageClientManager::clients();
for (Client * const client : allClients) {
if (!client->reachable() || !qobject_cast<ClangdClient *>(client))
continue;
for (IDocument * const doc : DocumentModel::openedDocuments()) {
const auto textDoc = qobject_cast<TextDocument *>(doc);
if (!textDoc || !client->documentOpen(textDoc))
continue;
const QTextCursor includePos = textDoc->document()->find(includeRex);
if (includePos.isNull())
continue;
qCDebug(clangdLog) << "updating" << textDoc->filePath() << "due to change in UI header"
<< fileName;
client->documentContentsChanged(textDoc, 0, 0, 0);
break; // No sane project includes the same UI header twice.
}
}
}
void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations) void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations)
{ {
const auto refData = runningFindUsages.find(key); const auto refData = runningFindUsages.find(key);
@@ -2817,14 +2854,26 @@ IAssistProcessor *ClangdClient::ClangdCompletionAssistProvider::createProcessor(
qCDebug(clangdLogCompletion) << "creating doxygen processor"; qCDebug(clangdLogCompletion) << "creating doxygen processor";
return new CustomAssistProcessor(m_client, return new CustomAssistProcessor(m_client,
contextAnalyzer.positionForProposal(), contextAnalyzer.positionForProposal(),
contextAnalyzer.positionEndOfExpression(),
contextAnalyzer.completionOperator(), contextAnalyzer.completionOperator(),
CustomAssistMode::Doxygen); CustomAssistMode::Doxygen);
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective: case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
qCDebug(clangdLogCompletion) << "creating macro processor"; qCDebug(clangdLogCompletion) << "creating macro processor";
return new CustomAssistProcessor(m_client, return new CustomAssistProcessor(m_client,
contextAnalyzer.positionForProposal(), contextAnalyzer.positionForProposal(),
contextAnalyzer.positionEndOfExpression(),
contextAnalyzer.completionOperator(), contextAnalyzer.completionOperator(),
CustomAssistMode::Preprocessor); CustomAssistMode::Preprocessor);
case ClangCompletionContextAnalyzer::CompleteIncludePath:
if (m_client->versionNumber() < QVersionNumber(14)) { // https://reviews.llvm.org/D112996
qCDebug(clangdLogCompletion) << "creating include processor";
return new CustomAssistProcessor(m_client,
contextAnalyzer.positionForProposal(),
contextAnalyzer.positionEndOfExpression(),
contextAnalyzer.completionOperator(),
CustomAssistMode::IncludePath);
}
[[fallthrough]];
default: default:
break; break;
} }
@@ -3009,6 +3058,38 @@ void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,
} }
} }
ClangdCompletionItem::SpecialQtType ClangdCompletionItem::getQtType(const CompletionItem &item)
{
const Utils::optional<MarkupOrString> doc = item.documentation();
if (!doc)
return SpecialQtType::None;
QString docText;
if (Utils::holds_alternative<QString>(*doc))
docText = Utils::get<QString>(*doc);
else if (Utils::holds_alternative<MarkupContent>(*doc))
docText = Utils::get<MarkupContent>(*doc).content();
if (docText.contains("Annotation: qt_signal"))
return SpecialQtType::Signal;
if (docText.contains("Annotation: qt_slot"))
return SpecialQtType::Slot;
return SpecialQtType::None;
}
QIcon ClangdCompletionItem::icon() const
{
const SpecialQtType qtType = getQtType(item());
switch (qtType) {
case SpecialQtType::Signal:
return Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Signal);
case SpecialQtType::Slot:
// FIXME: Add visibility info to completion item tags in clangd?
return Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::SlotPublic);
case SpecialQtType::None:
break;
}
return LanguageClientCompletionItem::icon();
}
MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc, MessageId ClangdClient::Private::getAndHandleAst(const TextDocOrFile &doc,
const AstHandler &astHandler, const AstHandler &astHandler,
AstCallbackMode callbackMode, const Range &range) AstCallbackMode callbackMode, const Range &range)

View File

@@ -86,6 +86,8 @@ public:
static QString displayNameFromDocumentSymbol(LanguageServerProtocol::SymbolKind kind, static QString displayNameFromDocumentSymbol(LanguageServerProtocol::SymbolKind kind,
const QString &name, const QString &detail); const QString &name, const QString &detail);
static void handleUiHeaderChange(const QString &fileName);
signals: signals:
void indexingFinished(); void indexingFinished();
void foundReferences(const QList<Core::SearchResultItem> &items); void foundReferences(const QList<Core::SearchResultItem> &items);

View File

@@ -155,7 +155,8 @@ static ::Utils::ProcessLinkCallback extendedCallback(::Utils::ProcessLinkCallbac
// If globalFollowSymbol finds nothing follow to the declaration. // If globalFollowSymbol finds nothing follow to the declaration.
return [original_callback = std::move(callback), result](const ::Utils::Link &link) { return [original_callback = std::move(callback), result](const ::Utils::Link &link) {
if (link.linkTextStart < 0 && result.isResultOnlyForFallBack) { if (link.linkTextStart < 0 && result.isResultOnlyForFallBack) {
return original_callback(::Utils::Link(::Utils::FilePath::fromString(result.fileName), return original_callback(Utils::Link(
Utils::FilePath::fromString(result.fileName).cleanPath(),
result.startLine, result.startLine,
result.startColumn - 1)); result.startColumn - 1));
} }
@@ -242,7 +243,7 @@ void ClangFollowSymbol::findLink(const CppEditor::CursorInEditor &data,
symbolFinder, symbolFinder,
inNextSplit); inNextSplit);
} else { } else {
callback(Link(Utils::FilePath::fromString(result.fileName), callback(Link(Utils::FilePath::fromString(result.fileName).cleanPath(),
result.startLine, result.startLine,
result.startColumn - 1)); result.startColumn - 1));
} }

View File

@@ -608,6 +608,7 @@ void ClangModelManagerSupport::onAbstractEditorSupportContentsUpdated(const QStr
const QString mappedPath = m_uiHeaderOnDiskManager.write(filePath, content); const QString mappedPath = m_uiHeaderOnDiskManager.write(filePath, content);
m_communicator.unsavedFilesUpdated(mappedPath, content, 0); m_communicator.unsavedFilesUpdated(mappedPath, content, 0);
ClangdClient::handleUiHeaderChange(Utils::FilePath::fromString(filePath).fileName());
} }
void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &filePath) void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &filePath)
@@ -618,6 +619,7 @@ void ClangModelManagerSupport::onAbstractEditorSupportRemoved(const QString &fil
const QString mappedPath = m_uiHeaderOnDiskManager.remove(filePath); const QString mappedPath = m_uiHeaderOnDiskManager.remove(filePath);
const QString projectPartId = projectPartIdForFile(filePath); const QString projectPartId = projectPartIdForFile(filePath);
m_communicator.unsavedFilesRemoved({{mappedPath, projectPartId}}); m_communicator.unsavedFilesRemoved({{mappedPath, projectPartId}});
ClangdClient::handleUiHeaderChange(Utils::FilePath::fromString(filePath).fileName());
} }
} }

View File

@@ -1488,9 +1488,15 @@ void ClangdTestCompletion::testCompleteIncludeDirective()
getProposal("includeDirectiveCompletion.cpp", proposal); getProposal("includeDirectiveCompletion.cpp", proposal);
QVERIFY(proposal); QVERIFY(proposal);
if (client()->versionNumber() < QVersionNumber(14)) {
QVERIFY(hasItem(proposal, "file.h"));
QVERIFY(hasItem(proposal, "otherFile.h"));
QVERIFY(hasItem(proposal, "mylib/"));
} else {
QVERIFY(hasItem(proposal, " file.h>")); QVERIFY(hasItem(proposal, " file.h>"));
QVERIFY(hasItem(proposal, " otherFile.h>")); QVERIFY(hasItem(proposal, " otherFile.h>"));
QVERIFY(hasItem(proposal, " mylib/")); QVERIFY(hasItem(proposal, " mylib/"));
}
QVERIFY(!hasSnippet(proposal, "class ")); QVERIFY(!hasSnippet(proposal, "class "));
} }

View File

@@ -64,7 +64,7 @@ public:
Utils::Id id() const { return m_id; } Utils::Id id() const { return m_id; }
WizardKind kind() const { return m_supportedProjectTypes.isEmpty() ? FileWizard : ProjectWizard; } WizardKind kind() const { return m_supportedProjectTypes.isEmpty() ? FileWizard : ProjectWizard; }
QIcon icon() const { return m_icon; } QIcon icon() const { return m_icon; }
QString fontIcondCode() const { return m_fontIconCode; } QString fontIconName() const { return m_fontIconName; }
QString description() const { return m_description; } QString description() const { return m_description; }
QString displayName() const { return m_displayName; } QString displayName() const { return m_displayName; }
QString category() const { return m_category; } QString category() const { return m_category; }
@@ -79,7 +79,7 @@ public:
void setId(const Utils::Id id) { m_id = id; } void setId(const Utils::Id id) { m_id = id; }
void setSupportedProjectTypes(const QSet<Utils::Id> &projectTypes) { m_supportedProjectTypes = projectTypes; } void setSupportedProjectTypes(const QSet<Utils::Id> &projectTypes) { m_supportedProjectTypes = projectTypes; }
void setIcon(const QIcon &icon, const QString &iconText = {}); void setIcon(const QIcon &icon, const QString &iconText = {});
void setFontIconCode(const QString &code) { m_fontIconCode = code; } void setFontIconName(const QString &code) { m_fontIconName = code; }
void setDescription(const QString &description) { m_description = description; } void setDescription(const QString &description) { m_description = description; }
void setDisplayName(const QString &displayName) { m_displayName = displayName; } void setDisplayName(const QString &displayName) { m_displayName = displayName; }
void setCategory(const QString &category) { m_category = category; } void setCategory(const QString &category) { m_category = category; }
@@ -137,7 +137,7 @@ private:
QAction *m_action = nullptr; QAction *m_action = nullptr;
QIcon m_icon; QIcon m_icon;
QString m_fontIconCode; QString m_fontIconName;
QString m_description; QString m_description;
QString m_displayName; QString m_displayName;
QString m_category; QString m_category;

View File

@@ -57,7 +57,7 @@ QString ProjectPart::projectFileLocation() const
bool ProjectPart::belongsToProject(const ProjectExplorer::Project *project) const bool ProjectPart::belongsToProject(const ProjectExplorer::Project *project) const
{ {
return project && topLevelProject == project->projectFilePath(); return project ? topLevelProject == project->projectFilePath() : !hasProject();
} }
QByteArray ProjectPart::readProjectConfigFile(const QString &projectConfigFile) QByteArray ProjectPart::readProjectConfigFile(const QString &projectConfigFile)

View File

@@ -258,7 +258,7 @@ void McuPackage::setRelativePathModifier(const QString &path)
m_relativePathModifier = path; m_relativePathModifier = path;
} }
void McuPackage::setVersions(const QVector<QString> &versions) void McuPackage::setVersions(const QStringList &versions)
{ {
m_versions = versions; m_versions = versions;
} }
@@ -312,13 +312,14 @@ void McuPackage::updateStatusUi()
QString McuPackage::statusText() const QString McuPackage::statusText() const
{ {
const QString displayPackagePath = m_path.toUserOutput(); const QString displayPackagePath = m_path.toUserOutput();
const QString displayVersions = QStringList(m_versions.toList()).join(" or "); const QString displayVersions = m_versions.join(" or ");
const QString displayRequiredPath = QString("%1 %2").arg( const QString outDetectionPath = FilePath::fromString(m_detectionPath).toUserOutput();
FilePath::fromString(m_detectionPath).toUserOutput(), const QString displayRequiredPath = m_versions.empty() ?
displayVersions); outDetectionPath :
const QString displayDetectedPath = QString("%1 %2").arg( QString("%1 %2").arg(outDetectionPath, displayVersions);
FilePath::fromString(m_detectionPath).toUserOutput(), const QString displayDetectedPath = m_versions.empty() ?
m_detectedVersion); outDetectionPath :
QString("%1 %2").arg(outDetectionPath, m_detectedVersion);
QString response; QString response;
switch (m_status) { switch (m_status) {

View File

@@ -88,7 +88,7 @@ public:
void writeGeneralSettings() const; void writeGeneralSettings() const;
bool writeToSettings() const; bool writeToSettings() const;
void setRelativePathModifier(const QString &path); void setRelativePathModifier(const QString &path);
void setVersions(const QVector<QString> &versions); void setVersions(const QStringList &versions);
bool automaticKitCreationEnabled() const; bool automaticKitCreationEnabled() const;
void setAutomaticKitCreationEnabled(const bool enabled); void setAutomaticKitCreationEnabled(const bool enabled);
@@ -118,7 +118,7 @@ private:
Utils::FilePath m_path; Utils::FilePath m_path;
QString m_relativePathModifier; // relative path to m_path to be returned by path() QString m_relativePathModifier; // relative path to m_path to be returned by path()
QString m_detectedVersion; QString m_detectedVersion;
QVector<QString> m_versions; QStringList m_versions;
QString m_downloadUrl; QString m_downloadUrl;
QString m_environmentVariableName; QString m_environmentVariableName;
bool m_addToPath = false; bool m_addToPath = false;

View File

@@ -341,13 +341,13 @@ struct McuTargetDescription
} platform; } platform;
struct { struct {
QString id; QString id;
QVector<QString> versions; QStringList versions;
} toolchain; } toolchain;
struct { struct {
QString name; QString name;
QString defaultPath; QString defaultPath;
QString envVar; QString envVar;
QVector<QString> versions; QStringList versions;
} boardSdk; } boardSdk;
struct { struct {
QString envVar; QString envVar;
@@ -658,10 +658,10 @@ static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion
const QJsonObject freeRTOS = target.value("freeRTOS").toObject(); const QJsonObject freeRTOS = target.value("freeRTOS").toObject();
const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList(); const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList();
const auto toolchainVersionsVector = Utils::transform<QVector<QString> >( const auto toolchainVersionsList = Utils::transform<QStringList>(
toolchainVersions, [&](const QVariant &version) { return version.toString(); }); toolchainVersions, [&](const QVariant &version) { return version.toString(); });
const QVariantList boardSdkVersions = boardSdk.value("versions").toArray().toVariantList(); const QVariantList boardSdkVersions = boardSdk.value("versions").toArray().toVariantList();
const auto boardSdkVersionsVector = Utils::transform<QVector<QString> >( const auto boardSdkVersionsList = Utils::transform<QStringList>(
boardSdkVersions, [&](const QVariant &version) { return version.toString(); }); boardSdkVersions, [&](const QVariant &version) { return version.toString(); });
return { return {
@@ -670,13 +670,13 @@ static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion
{}, {},
{ {
toolchain.value("id").toString(), toolchain.value("id").toString(),
toolchainVersionsVector, toolchainVersionsList,
}, },
{ {
boardSdk.value("name").toString(), boardSdk.value("name").toString(),
boardSdk.value("defaultPath").toString(), boardSdk.value("defaultPath").toString(),
boardSdk.value("envVar").toString(), boardSdk.value("envVar").toString(),
boardSdkVersionsVector, boardSdkVersionsList,
}, },
{ {
freeRTOS.value("envVar").toString(), freeRTOS.value("envVar").toString(),

View File

@@ -72,7 +72,7 @@ const char CATEGORY_NAME_KEY[] = "trDisplayCategory";
const char DISPLAY_NAME_KEY[] = "trDisplayName"; const char DISPLAY_NAME_KEY[] = "trDisplayName";
const char ICON_KEY[] = "icon"; const char ICON_KEY[] = "icon";
const char ICON_TEXT_KEY[] = "iconText"; const char ICON_TEXT_KEY[] = "iconText";
const char FONT_ICON_CODE_KEY[] = "fontIconCode"; const char FONT_ICON_NAME_KEY[] = "fontIconName";
const char IMAGE_KEY[] = "image"; const char IMAGE_KEY[] = "image";
const char ICON_KIND_KEY[] = "iconKind"; const char ICON_KIND_KEY[] = "iconKind";
const char DESCRIPTION_KEY[] = "trDescription"; const char DESCRIPTION_KEY[] = "trDescription";
@@ -743,8 +743,8 @@ bool JsonWizardFactory::initialize(const QVariantMap &data, const FilePath &base
: QIcon(iconPath.toString()), : QIcon(iconPath.toString()),
iconText); iconText);
const QString fontIconCode = data.value(QLatin1String(FONT_ICON_CODE_KEY)).toString(); const QString fontIconName = data.value(QLatin1String(FONT_ICON_NAME_KEY)).toString();
setFontIconCode(fontIconCode); setFontIconName(fontIconName);
strVal = data.value(QLatin1String(IMAGE_KEY)).toString(); strVal = data.value(QLatin1String(IMAGE_KEY)).toString();
if (!strVal.isEmpty()) { if (!strVal.isEmpty()) {

View File

@@ -1,5 +1,10 @@
<RCC> <RCC>
<qresource prefix="/boilerplatetemplates"> <qresource prefix="/boilerplatetemplates">
<file>qmlprojectmaincpp.tpl</file> <file>qmlprojectmaincpp.tpl</file>
<file>qmlprojectmaincppheader.tpl</file>
<file>qmlprojectmodules.tpl</file>
<file>qmlprojectmaincmakelists.tpl</file>
<file>qmlprojectmodulecmakelists.tpl</file>
<file>qmlprojectmainqml.tpl</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -186,6 +186,11 @@ QString Theme::getIconUnicode(Theme::Icon i)
return instance()->m_constants->property(e.valueToKey(i)).toString(); return instance()->m_constants->property(e.valueToKey(i)).toString();
} }
QString Theme::getIconUnicode(const QString &name)
{
return instance()->m_constants->property(name.toStdString().data()).toString();
}
QColor Theme::qmlDesignerBackgroundColorDarker() const QColor Theme::qmlDesignerBackgroundColorDarker() const
{ {
return getColor(QmlDesigner_BackgroundColorDarker); return getColor(QmlDesigner_BackgroundColorDarker);

View File

@@ -174,8 +174,7 @@ public:
unpin, unpin,
upDownIcon, upDownIcon,
upDownSquare2, upDownSquare2,
visibilityOffBroken, // visibilityOff visibilityOff,
visibilityOff, // visibilityOff2
visibilityOn, visibilityOn,
wildcard, wildcard,
wizardsAutomotive, wizardsAutomotive,
@@ -198,6 +197,7 @@ public:
static QColor getColor(Color role); static QColor getColor(Color role);
static QPixmap getPixmap(const QString &id); static QPixmap getPixmap(const QString &id);
static QString getIconUnicode(Theme::Icon i); static QString getIconUnicode(Theme::Icon i);
static QString getIconUnicode(const QString &name);
Q_INVOKABLE QColor qmlDesignerBackgroundColorDarker() const; Q_INVOKABLE QColor qmlDesignerBackgroundColorDarker() const;
Q_INVOKABLE QColor qmlDesignerBackgroundColorDarkAlternate() const; Q_INVOKABLE QColor qmlDesignerBackgroundColorDarkAlternate() const;

View File

@@ -279,6 +279,7 @@ bool DesignDocument::isDocumentLoaded() const
void DesignDocument::resetToDocumentModel() void DesignDocument::resetToDocumentModel()
{ {
plainTextEdit()->document()->clearUndoRedoStacks();
m_inFileComponentModel.reset(); m_inFileComponentModel.reset();
} }
@@ -310,6 +311,8 @@ void DesignDocument::changeToDocumentModel()
viewManager().detachRewriterView(); viewManager().detachRewriterView();
viewManager().detachViewsExceptRewriterAndComponetView(); viewManager().detachViewsExceptRewriterAndComponetView();
plainTextEdit()->document()->clearUndoRedoStacks();
m_inFileComponentModel.reset(); m_inFileComponentModel.reset();
m_inFileComponentTextModifier.reset(); m_inFileComponentTextModifier.reset();
@@ -345,6 +348,8 @@ void DesignDocument::changeToInFileComponentModel(ComponentTextModifier *textMod
viewManager().detachRewriterView(); viewManager().detachRewriterView();
viewManager().detachViewsExceptRewriterAndComponetView(); viewManager().detachViewsExceptRewriterAndComponetView();
plainTextEdit()->document()->clearUndoRedoStacks();
m_inFileComponentModel.reset(createInFileComponentModel()); m_inFileComponentModel.reset(createInFileComponentModel());
m_inFileComponentModel->setTextModifier(m_inFileComponentTextModifier.data()); m_inFileComponentModel->setTextModifier(m_inFileComponentTextModifier.data());

View File

@@ -160,19 +160,28 @@ void ComponentTextModifier::handleOriginalTextChanged()
const QString currentText = m_originalModifier->text(); const QString currentText = m_originalModifier->text();
// Adjust for removal/addition of whitespace in the document
// Check that non-whitespace portion of the text is the same and count the whitespace diff
const int oldLen = m_originalText.size(); const int oldLen = m_originalText.size();
const int newLen = currentText.size(); const int newLen = currentText.size();
if (oldLen != newLen) {
int newSpace = 0; int newSpace = 0;
int oldSpace = 0; int oldSpace = 0;
int newIdx = 0; int newIdx = 0;
int nonWhiteSpaceChangeIdx = -1;
int newStartOffset = m_componentStartOffset;
// Adjust for removal/addition of whitespace in the document.
// Whitespace changes that happen when document is saved can be spread around throughout
// the entire document in multiple places.
// Check that non-whitespace portion of the text is the same and count the whitespace diff
for (int oldIdx = 0; oldIdx < oldLen; ++oldIdx) { for (int oldIdx = 0; oldIdx < oldLen; ++oldIdx) {
const QChar oldChar = m_originalText[oldIdx]; const QChar oldChar = m_originalText[oldIdx];
if (oldIdx == m_componentStartOffset) if (oldIdx == m_componentStartOffset)
m_componentStartOffset += newSpace - oldSpace; newStartOffset += newSpace - oldSpace;
if (oldIdx == m_componentEndOffset) { if (oldIdx == m_componentEndOffset) {
m_componentEndOffset += newSpace - oldSpace; m_componentEndOffset += newSpace - oldSpace;
m_componentStartOffset = newStartOffset;
m_originalText = currentText;
break; break;
} }
@@ -187,13 +196,29 @@ void ComponentTextModifier::handleOriginalTextChanged()
} }
if (currentText[newIdx] != oldChar) { if (currentText[newIdx] != oldChar) {
// Non-whitespace difference, we can't determine a valid offset in this case nonWhiteSpaceChangeIdx = oldIdx;
// TODO: Needs proper handling to deal with undo/redo/arbitrary edits somehow (QDS-5392) // A non-whitespace change is a result of manual text edit or undo/redo operation.
// Assumption is that separate whitespace changes and a non-whitespace change can't
// both happen simultaneously, so break out of whitespace check loop.
break; break;
} else { } else {
++newIdx; ++newIdx;
} }
} }
if (nonWhiteSpaceChangeIdx >= 0) {
// For non-whitespace change, we assume the whole change is either before the component
// or inside the component. If the change spans both, it's likely the change is
// invalid anyway, and we don't care about trying to keep offsets up to date.
int diff = newLen - oldLen;
if (nonWhiteSpaceChangeIdx < m_componentEndOffset)
m_componentEndOffset += diff;
if (nonWhiteSpaceChangeIdx < m_componentStartOffset)
m_componentStartOffset += diff;
m_originalText = currentText; m_originalText = currentText;
}
}
emit textChanged(); emit textChanged();
} }

View File

@@ -66,6 +66,7 @@ const char NAVIGATOR_REVERSE_ITEM_ORDER[] = "NavigatorReverseItemOrder";
const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */ const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These settings are not exposed in ui. */
const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */ const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */
const char STANDALONE_MODE[] = "StandAloneMode"; const char STANDALONE_MODE[] = "StandAloneMode";
const char SHOW_DEBUG_SETTINGS[] = "ShowDebugSettings";
const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView"; const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView";
const char COLOR_PALETTE_RECENT[] = "ColorPaletteRecent"; const char COLOR_PALETTE_RECENT[] = "ColorPaletteRecent";
const char COLOR_PALETTE_FAVORITE[] = "ColorPaletteFavorite"; const char COLOR_PALETTE_FAVORITE[] = "ColorPaletteFavorite";

View File

@@ -78,7 +78,7 @@ void onGenerateCmakeLists()
{ {
queuedFiles.clear(); queuedFiles.clear();
FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory(); FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory();
GenerateCmakeLists::generateMainCmake(rootDir); GenerateCmakeLists::generateCmakes(rootDir);
GenerateEntryPoints::generateMainCpp(rootDir); GenerateEntryPoints::generateMainCpp(rootDir);
GenerateEntryPoints::generateMainQml(rootDir); GenerateEntryPoints::generateMainQml(rootDir);
if (showConfirmationDialog(rootDir)) if (showConfirmationDialog(rootDir))
@@ -139,138 +139,125 @@ bool writeFile(const GeneratableFile &file)
return true; return true;
} }
QString readTemplate(const QString &templatePath)
{
QFile templatefile(templatePath);
templatefile.open(QIODevice::ReadOnly);
QTextStream stream(&templatefile);
QString content = stream.readAll();
templatefile.close();
return content;
}
} }
namespace GenerateCmakeLists { namespace GenerateCmakeLists {
QStringList moduleNames;
const QDir::Filters FILES_ONLY = QDir::Files; const QDir::Filters FILES_ONLY = QDir::Files;
const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot; const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
const char CMAKEFILENAME[] = "CMakeLists.txt"; const char CMAKEFILENAME[] = "CMakeLists.txt";
const char QMLDIRFILENAME[] = "qmldir"; const char QMLDIRFILENAME[] = "qmldir";
const char MODULEFILENAME[] = "qmlmodules";
QStringList processDirectory(const FilePath &dir) bool generateCmakes(const FilePath &rootDir)
{ {
QStringList moduleNames; moduleNames.clear();
FilePaths files = dir.dirEntries(FILES_ONLY); FilePath contentDir = rootDir.pathAppended("content");
for (FilePath &file : files) { FilePath importDir = rootDir.pathAppended("imports");
if (!file.fileName().compare(CMAKEFILENAME))
files.removeAll(file);
}
if (files.isEmpty()) { generateModuleCmake(contentDir);
generateSubdirCmake(dir); generateImportCmake(importDir);
FilePaths subDirs = dir.dirEntries(DIRS_ONLY); generateMainCmake(rootDir);
for (FilePath &subDir : subDirs) {
QStringList subDirModules = processDirectory(subDir);
moduleNames.append(subDirModules);
}
}
else {
QString moduleName = generateModuleCmake(dir);
if (!moduleName.isEmpty()) {
moduleNames.append(moduleName);
}
}
return moduleNames; return true;
} }
const char MAINFILE_REQUIRED_VERSION[] = "cmake_minimum_required(VERSION 3.18)\n\n"; const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl";
const char MAINFILE_PROJECT[] = "project(%1 LANGUAGES CXX)\n\n"; const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl";
const char MAINFILE_CMAKE_OPTIONS[] = "set(CMAKE_INCLUDE_CURRENT_DIR ON)\nset(CMAKE_AUTOMOC ON)\n\n";
const char MAINFILE_PACKAGES[] = "find_package(Qt6 COMPONENTS Gui Qml Quick)\n";
const char MAINFILE_LIBRARIES[] = "set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)\n\n";
const char MAINFILE_CPP[] = "add_executable(%1 main.cpp)\n\n";
const char MAINFILE_MAINMODULE[] = "qt6_add_qml_module(%1\n\tURI \"Main\"\n\tVERSION 1.0\n\tNO_PLUGIN\n\tQML_FILES main.qml\n)\n\n";
const char MAINFILE_LINK_LIBRARIES[] = "target_link_libraries(%1 PRIVATE\n\tQt${QT_VERSION_MAJOR}::Core\n\tQt${QT_VERSION_MAJOR}::Gui\n\tQt${QT_VERSION_MAJOR}::Quick\n\tQt${QT_VERSION_MAJOR}::Qml\n)\n\n";
const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
void generateMainCmake(const FilePath &rootDir) void generateMainCmake(const FilePath &rootDir)
{ {
//TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all. //TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all.
QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName(); QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
QString appName = projectName + "App";
FilePaths subDirs = rootDir.dirEntries(DIRS_ONLY); QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH).arg(appName);
queueCmakeFile(rootDir, cmakeFileContent);
QString modulesAsPlugins;
for (const QString &moduleName : moduleNames)
modulesAsPlugins.append(" " + moduleName + "plugin\n");
QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH).arg(appName).arg(modulesAsPlugins);
GenerateCmake::queueFile(rootDir.pathAppended(MODULEFILENAME), moduleFileContent);
}
const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n";
const char ADD_SUBDIR[] = "add_subdirectory(%1)\n";
void generateImportCmake(const FilePath &dir)
{
QString fileContent; QString fileContent;
fileContent.append(MAINFILE_REQUIRED_VERSION);
fileContent.append(QString(MAINFILE_PROJECT).arg(projectName));
fileContent.append(MAINFILE_CMAKE_OPTIONS);
fileContent.append(MAINFILE_PACKAGES);
fileContent.append(QString(MAINFILE_CPP).arg(projectName));
fileContent.append(QString(MAINFILE_MAINMODULE).arg(projectName));
fileContent.append(MAINFILE_LIBRARIES);
fileContent.append(DO_NOT_EDIT_FILE_COMMENT);
FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
for (FilePath &subDir : subDirs) { for (FilePath &subDir : subDirs) {
QStringList subDirModules = processDirectory(subDir);
if (!subDirModules.isEmpty())
fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName())); fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
generateModuleCmake(subDir);
} }
fileContent.append("\n");
fileContent.append(QString(MAINFILE_LINK_LIBRARIES).arg(projectName)); queueCmakeFile(dir, fileContent);
createCmakeFile(rootDir, fileContent);
} }
const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE"; const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE";
const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n\tPROPERTIES\n\t\t%2 %3\n)\n\n"; const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n";
const char MODULEFILE_CREATE_MODULE[] = "qt6_add_qml_module(%1\n\tURI \"%1\"\n\tVERSION 1.0\n%2)\n\n"; const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl";
void generateModuleCmake(const FilePath &dir)
QString generateModuleCmake(const FilePath &dir)
{ {
QString fileContent; QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
const QStringList qmldirFilesOnly(QMLDIRFILENAME); const QStringList qmldirFilesOnly(QMLDIRFILENAME);
QString singletonContent;
FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY); FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY);
if (!qmldirFileList.isEmpty()) { if (!qmldirFileList.isEmpty()) {
QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first()); QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
for (QString &singleton : singletons) { for (QString &singleton : singletons) {
fileContent.append(QString(MODULEFILE_PROPERTY_SET).arg(singleton).arg(MODULEFILE_PROPERTY_SINGLETON).arg("true")); singletonContent.append(QString(MODULEFILE_PROPERTY_SET).arg(singleton).arg(MODULEFILE_PROPERTY_SINGLETON).arg("true"));
} }
} }
QStringList qmlFileList = getDirectoryTreeQmls(dir); QStringList qmlFileList = getDirectoryTreeQmls(dir);
QString qmlFiles; QString qmlFiles;
for (QString &qmlFile : qmlFileList) for (QString &qmlFile : qmlFileList)
qmlFiles.append(QString("\t\t%1\n").arg(qmlFile)); qmlFiles.append(QString(" %1\n").arg(qmlFile));
QStringList resourceFileList = getDirectoryTreeResources(dir); QStringList resourceFileList = getDirectoryTreeResources(dir);
QString resourceFiles; QString resourceFiles;
for (QString &resourceFile : resourceFileList) for (QString &resourceFile : resourceFileList)
resourceFiles.append(QString("\t\t%1\n").arg(resourceFile)); resourceFiles.append(QString(" %1\n").arg(resourceFile));
QString moduleContent; QString moduleContent;
if (!qmlFiles.isEmpty()) { if (!qmlFiles.isEmpty()) {
moduleContent.append(QString("\tQML_FILES\n%1").arg(qmlFiles)); moduleContent.append(QString(" QML_FILES\n%1").arg(qmlFiles));
} }
if (!resourceFiles.isEmpty()) { if (!resourceFiles.isEmpty()) {
moduleContent.append(QString("\tRESOURCES\n%1").arg(resourceFiles)); moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
} }
QString moduleName = dir.fileName(); QString moduleName = dir.fileName();
fileContent.append(QString(MODULEFILE_CREATE_MODULE).arg(moduleName).arg(moduleContent)); moduleNames.append(moduleName);
createCmakeFile(dir, fileContent);
return moduleName;
}
void generateSubdirCmake(const FilePath &dir)
{
QString fileContent; QString fileContent;
FilePaths subDirs = dir.dirEntries(DIRS_ONLY); fileContent.append(fileTemplate.arg(singletonContent).arg(moduleName).arg(moduleContent));
queueCmakeFile(dir, fileContent);
for (FilePath &subDir : subDirs) {
fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
}
createCmakeFile(dir, fileContent);
} }
QStringList getSingletonsFromQmldirFile(const FilePath &filePath) QStringList getSingletonsFromQmldirFile(const FilePath &filePath)
@@ -347,7 +334,7 @@ QStringList getDirectoryTreeResources(const FilePath &dir)
return resourceFileList; return resourceFileList;
} }
void createCmakeFile(const FilePath &dir, const QString &content) void queueCmakeFile(const FilePath &dir, const QString &content)
{ {
FilePath filePath = dir.pathAppended(CMAKEFILENAME); FilePath filePath = dir.pathAppended(CMAKEFILENAME);
GenerateCmake::queueFile(filePath, content); GenerateCmake::queueFile(filePath, content);
@@ -370,35 +357,42 @@ bool generateEntryPointFiles(const FilePath &dir)
return cppOk && qmlOk; return cppOk && qmlOk;
} }
const char MAIN_CPPFILE_CONTENT[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl"; const char MAIN_CPPFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincpp.tpl";
const char MAIN_CPPFILE_DIR[] = "src";
const char MAIN_CPPFILE_NAME[] = "main.cpp"; const char MAIN_CPPFILE_NAME[] = "main.cpp";
const char MAIN_CPPFILE_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincppheader.tpl";
const char MAIN_CPPFILE_HEADER_NAME[] = "import_qml_plugins.h";
const char MAIN_CPPFILE_HEADER_PLUGIN_LINE[] = "Q_IMPORT_QML_PLUGIN(%1)\n";
bool generateMainCpp(const FilePath &dir) bool generateMainCpp(const FilePath &dir)
{ {
QFile templatefile(MAIN_CPPFILE_CONTENT); FilePath srcDir = dir.pathAppended(MAIN_CPPFILE_DIR);
templatefile.open(QIODevice::ReadOnly);
QTextStream stream(&templatefile);
QString content = stream.readAll();
templatefile.close();
FilePath filePath = dir.pathAppended(MAIN_CPPFILE_NAME); QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH);
return GenerateCmake::queueFile(filePath, content); FilePath cppFilePath = srcDir.pathAppended(MAIN_CPPFILE_NAME);
bool cppOk = GenerateCmake::queueFile(cppFilePath, cppContent);
QString modulesAsPlugins;
for (const QString &moduleName : GenerateCmakeLists::moduleNames)
modulesAsPlugins.append(
QString(MAIN_CPPFILE_HEADER_PLUGIN_LINE).arg(moduleName + "plugin"));
QString headerContent = GenerateCmake::readTemplate(MAIN_CPPFILE_HEADER_TEMPLATE_PATH)
.arg(modulesAsPlugins);
FilePath headerFilePath = srcDir.pathAppended(MAIN_CPPFILE_HEADER_NAME);
bool headerOk = GenerateCmake::queueFile(headerFilePath, headerContent);
return cppOk && headerOk;
} }
const char MAIN_QMLFILE_CONTENT[] = "import %1Qml\n\n%2 {\n}\n"; const char MAIN_QMLFILE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl";
const char MAIN_QMLFILE_NAME[] = "main.qml"; const char MAIN_QMLFILE_NAME[] = "main.qml";
bool generateMainQml(const FilePath &dir) bool generateMainQml(const FilePath &dir)
{ {
QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_PATH);
FilePath filePath = dir.pathAppended(MAIN_QMLFILE_NAME); FilePath filePath = dir.pathAppended(MAIN_QMLFILE_NAME);
QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName(); return GenerateCmake::queueFile(filePath, content);
ProjectExplorer::RunConfiguration *runConfiguration = ProjectExplorer::SessionManager::startupRunConfiguration();
QString mainClass;
if (const auto aspect = runConfiguration->aspect<QmlProjectManager::QmlMainFileAspect>())
mainClass = FilePath::fromString(aspect->mainScript()).baseName();
return GenerateCmake::queueFile(filePath, QString(MAIN_QMLFILE_CONTENT).arg(projectName).arg(mainClass));
} }
} }

View File

@@ -45,16 +45,17 @@ bool showConfirmationDialog(const Utils::FilePath &rootDir);
bool queueFile(const Utils::FilePath &filePath, const QString &fileContent); bool queueFile(const Utils::FilePath &filePath, const QString &fileContent);
bool writeFile(const GeneratableFile &file); bool writeFile(const GeneratableFile &file);
bool writeQueuedFiles(); bool writeQueuedFiles();
QString readTemplate(const QString &templatePath);
} }
namespace GenerateCmakeLists { namespace GenerateCmakeLists {
bool generateCmakes(const Utils::FilePath &rootDir);
void generateMainCmake(const Utils::FilePath &rootDir); void generateMainCmake(const Utils::FilePath &rootDir);
void generateSubdirCmake(const Utils::FilePath &dir); void generateImportCmake(const Utils::FilePath &dir);
QString generateModuleCmake(const Utils::FilePath &dir); void generateModuleCmake(const Utils::FilePath &dir);
QStringList processDirectory(const Utils::FilePath &dir);
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath); QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
QStringList getDirectoryTreeQmls(const Utils::FilePath &dir); QStringList getDirectoryTreeQmls(const Utils::FilePath &dir);
QStringList getDirectoryTreeResources(const Utils::FilePath &dir); QStringList getDirectoryTreeResources(const Utils::FilePath &dir);
void createCmakeFile(const Utils::FilePath &filePath, const QString &content); void queueCmakeFile(const Utils::FilePath &filePath, const QString &content);
bool isFileBlacklisted(const QString &fileName); bool isFileBlacklisted(const QString &fileName);
} }
namespace GenerateEntryPoints { namespace GenerateEntryPoints {

View File

@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.18)
project(%1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
find_package(Qt6 COMPONENTS Gui Qml Quick)
add_executable(%1 src/main.cpp)
target_link_libraries(%1 PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Qml
)
include(${CMAKE_CURRENT_SOURCE_DIR}/qmlmodules)

View File

@@ -0,0 +1,8 @@
/*
* This file is automatically generated by Qt Design Studio.
* Do not change.
*/
#include <QtQml/qqmlextensionplugin.h>
%1

View File

@@ -0,0 +1,6 @@
import QtQuick
import content
App {
}

View File

@@ -0,0 +1,11 @@
### This file is automatically generated by Qt Design Studio.
### Do not change
%1
qt_add_library(%2 STATIC)
qt6_add_qml_module(%2
URI "%2"
VERSION 1.0
%3
)

View File

@@ -0,0 +1,16 @@
### This file is automatically generated by Qt Design Studio.
### Do not change
qt6_add_qml_module(%1
URI "Main"
VERSION 1.0
NO_PLUGIN
QML_FILES main.qml
)
add_subdirectory(content)
add_subdirectory(imports)
target_link_libraries(%1 PRIVATE
%2
)

View File

@@ -252,10 +252,14 @@ void SettingsPageWidget::setSettings(const DesignerSettings &settings)
m_ui.askBeforeDeletingAssetCheckBox->setChecked(settings.value( m_ui.askBeforeDeletingAssetCheckBox->setChecked(settings.value(
DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET).toBool()); DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET).toBool());
if (settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool()) { const auto standaloneMode = settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool();
m_ui.debugGroupBox->hide(); #ifdef QT_DEBUG
m_ui.featureTimelineEditorCheckBox->hide(); const auto showDebugSettings = true;
} #else
const auto showDebugSettings = settings.value(DesignerSettingsKey::SHOW_DEBUG_SETTINGS).toBool();
#endif
m_ui.debugGroupBox->setVisible(!standaloneMode || showDebugSettings);
m_ui.featureTimelineEditorCheckBox->setVisible(standaloneMode);
} }
void SettingsPageWidget::apply() void SettingsPageWidget::apply()

View File

@@ -199,7 +199,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
info(openInQDSAppSetting, info(openInQDSAppSetting,
description + tr(" Learn more about Qt Design Studio here: ") description + tr(" Learn more about Qt Design Studio here: ")
+ "<a href='https://www.qt.io/product/ui-design-tools'>Qt Design Studio</a>", + "<a href='https://www.qt.io/product/ui-design-tools'>Qt Design Studio</a>",
Utils::InfoBarEntry::GlobalSuppression::Enabled); Utils::InfoBarEntry::GlobalSuppression::Disabled);
Core::ICore::infoBar()->addInfo(info); Core::ICore::infoBar()->addInfo(info);
} }
return; return;
@@ -209,7 +209,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
Utils::InfoBarEntry Utils::InfoBarEntry
info(openInQDSAppSetting, info(openInQDSAppSetting,
description + "\n" + tr("Do you want to open this file in Qt Design Studio?"), description + "\n" + tr("Do you want to open this file in Qt Design Studio?"),
Utils::InfoBarEntry::GlobalSuppression::Enabled); Utils::InfoBarEntry::GlobalSuppression::Disabled);
info.setCustomButtonInfo(tr("Open in Qt Design Studio"), [filePath] { info.setCustomButtonInfo(tr("Open in Qt Design Studio"), [filePath] {
Core::ICore::infoBar()->removeInfo(openInQDSAppSetting); Core::ICore::infoBar()->removeInfo(openInQDSAppSetting);

View File

@@ -353,6 +353,10 @@ bool StudioWelcomePlugin::initialize(const QStringList &arguments, QString *erro
void StudioWelcomePlugin::extensionsInitialized() void StudioWelcomePlugin::extensionsInitialized()
{ {
Core::ModeManager::activateMode(m_welcomeMode->id()); Core::ModeManager::activateMode(m_welcomeMode->id());
// Enable QDS new project dialog
Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); });
if (Utils::CheckableMessageBox::shouldAskAgain(Core::ICore::settings(), if (Utils::CheckableMessageBox::shouldAskAgain(Core::ICore::settings(),
DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY)) { DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY)) {
connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] { connect(Core::ICore::instance(), &Core::ICore::coreOpened, this, [this] {
@@ -370,8 +374,6 @@ void StudioWelcomePlugin::extensionsInitialized()
s_view->setSource(QUrl("qrc:/qml/splashscreen/main.qml")); s_view->setSource(QUrl("qrc:/qml/splashscreen/main.qml"));
#endif #endif
// disabled by default
Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); });
QTC_ASSERT(s_view->rootObject(), QTC_ASSERT(s_view->rootObject(),
qWarning() << "The StudioWelcomePlugin has a runtime depdendency on " qWarning() << "The StudioWelcomePlugin has a runtime depdendency on "

View File

@@ -28,11 +28,7 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include "wizardfactories.h" #include "wizardfactories.h"
#include <qmldesigner/components/componentcore/theme.h>
namespace {
// TODO: should be extern, check coreplugin/dialogs/newdialogwidget.cpp
const char BLACKLISTED_CATEGORIES_KEY[] = "Core/NewDialog/BlacklistedCategories";
}
using namespace StudioWelcome; using namespace StudioWelcome;
@@ -41,9 +37,6 @@ WizardFactories::WizardFactories(QList<Core::IWizardFactory *> &factories, QWidg
, m_platform{platform} , m_platform{platform}
, m_factories{factories} , m_factories{factories}
{ {
QVariant value = Core::ICore::settings()->value(BLACKLISTED_CATEGORIES_KEY);
m_blacklist = Utils::Id::fromStringList(value.toStringList());
sortByCategoryAndId(); sortByCategoryAndId();
filter(); filter();
m_projectItems = makeProjectItemsGroupedByCategory(); m_projectItems = makeProjectItemsGroupedByCategory();
@@ -67,7 +60,7 @@ void WizardFactories::filter()
[&](auto *wizard) { [&](auto *wizard) {
return wizard->isAvailable(m_platform) return wizard->isAvailable(m_platform)
&& wizard->kind() == Core::IWizardFactory::ProjectWizard && wizard->kind() == Core::IWizardFactory::ProjectWizard
&& !m_blacklist.contains(Utils::Id::fromString(wizard->category())); && wizard->requiredFeatures().contains("QtStudio");
}); });
m_factories = acceptedFactories; m_factories = acceptedFactories;
@@ -83,7 +76,7 @@ ProjectItem WizardFactories::makeProjectItem(Core::IWizardFactory *f, QWidget *p
/*.categoryId =*/f->category(), /*.categoryId =*/f->category(),
/*. description =*/f->description(), /*. description =*/f->description(),
/*.qmlPath =*/f->detailsPageQmlPath(), /*.qmlPath =*/f->detailsPageQmlPath(),
/*.fontIconCode =*/f->fontIcondCode(), /*.fontIconCode =*/QmlDesigner::Theme::getIconUnicode(f->fontIconName()),
/*.create =*/ std::bind(&Core::IWizardFactory::runWizard, f, _1, parent, platform, /*.create =*/ std::bind(&Core::IWizardFactory::runWizard, f, _1, parent, platform,
QVariantMap(), false), QVariantMap(), false),
}; };

View File

@@ -55,7 +55,6 @@ private:
std::map<QString, ProjectCategory> makeProjectItemsGroupedByCategory(); std::map<QString, ProjectCategory> makeProjectItemsGroupedByCategory();
private: private:
QSet<Utils::Id> m_blacklist;
QWidget *m_wizardParent; QWidget *m_wizardParent;
Utils::Id m_platform; Utils::Id m_platform;

View File

@@ -651,7 +651,7 @@ void TextDocument::setFilePath(const Utils::FilePath &newName)
{ {
if (newName == filePath()) if (newName == filePath())
return; return;
IDocument::setFilePath(newName.absoluteFilePath()); IDocument::setFilePath(newName.absoluteFilePath().cleanPath());
} }
IDocument::ReloadBehavior TextDocument::reloadBehavior(ChangeTrigger state, ChangeType type) const IDocument::ReloadBehavior TextDocument::reloadBehavior(ChangeTrigger state, ChangeType type) const

View File

@@ -189,14 +189,14 @@ public:
// Navigation // Navigation
QAction *m_goBack = nullptr; QAction *m_goBack = nullptr;
QAction *m_goNext = nullptr; QAction *m_goNext = nullptr;
QLineEdit *m_searchFilter = nullptr; QPointer<QLineEdit> m_searchFilter = nullptr;
// Cost formatting // Cost formatting
QAction *m_filterProjectCosts = nullptr; QAction *m_filterProjectCosts = nullptr;
QAction *m_costAbsolute = nullptr; QAction *m_costAbsolute = nullptr;
QAction *m_costRelative = nullptr; QAction *m_costRelative = nullptr;
QAction *m_costRelativeToParent = nullptr; QAction *m_costRelativeToParent = nullptr;
QComboBox *m_eventCombo = nullptr; QPointer<QComboBox> m_eventCombo;
QTimer m_updateTimer; QTimer m_updateTimer;
@@ -546,7 +546,9 @@ void CallgrindToolPrivate::setBusyCursor(bool busy)
void CallgrindToolPrivate::selectFunction(const Function *func) void CallgrindToolPrivate::selectFunction(const Function *func)
{ {
if (!func) { if (!func) {
if (m_flatView)
m_flatView->clearSelection(); m_flatView->clearSelection();
if (m_visualization)
m_visualization->setFunction(nullptr); m_visualization->setFunction(nullptr);
m_callersModel.clear(); m_callersModel.clear();
m_calleesModel.clear(); m_calleesModel.clear();
@@ -555,14 +557,17 @@ void CallgrindToolPrivate::selectFunction(const Function *func)
const QModelIndex index = m_dataModel.indexForObject(func); const QModelIndex index = m_dataModel.indexForObject(func);
const QModelIndex proxyIndex = m_proxyModel.mapFromSource(index); const QModelIndex proxyIndex = m_proxyModel.mapFromSource(index);
if (m_flatView) {
m_flatView->selectionModel()->clearSelection(); m_flatView->selectionModel()->clearSelection();
m_flatView->selectionModel()->setCurrentIndex(proxyIndex, m_flatView->selectionModel()->setCurrentIndex(proxyIndex,
QItemSelectionModel::ClearAndSelect | QItemSelectionModel::ClearAndSelect |
QItemSelectionModel::Rows); QItemSelectionModel::Rows);
m_flatView->scrollTo(proxyIndex); m_flatView->scrollTo(proxyIndex);
}
m_callersModel.setCalls(func->incomingCalls(), func); m_callersModel.setCalls(func->incomingCalls(), func);
m_calleesModel.setCalls(func->outgoingCalls(), func); m_calleesModel.setCalls(func->outgoingCalls(), func);
if (m_visualization)
m_visualization->setFunction(func); m_visualization->setFunction(func);
const Function *item = m_stackBrowser.current(); const Function *item = m_stackBrowser.current();
@@ -689,6 +694,7 @@ void CallgrindToolPrivate::visualisationFunctionSelected(const Function *functio
void CallgrindToolPrivate::setParseData(ParseData *data) void CallgrindToolPrivate::setParseData(ParseData *data)
{ {
// we have new parse data, invalidate filters in the proxy model // we have new parse data, invalidate filters in the proxy model
if (m_visualization)
m_visualization->setFunction(nullptr); m_visualization->setFunction(nullptr);
// invalidate parse data in the data model // invalidate parse data in the data model
@@ -705,6 +711,7 @@ void CallgrindToolPrivate::setParseData(ParseData *data)
m_calleesModel.setParseData(data); m_calleesModel.setParseData(data);
m_callersModel.setParseData(data); m_callersModel.setParseData(data);
if (m_eventCombo)
updateEventCombo(); updateEventCombo();
// clear history for new data // clear history for new data