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
NINJA_VERSION: 1.10.2
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
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
respective tests.
\QC integrates the \l{Qt Test} framework,
\l{https://github.com/google/googletest}{Google C++ Testing Framework},
\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}
{Catch2 test framework} for unit testing applications and libraries.
\QC integrates the following testing frameworks for unit testing
applications and libraries:
\list
\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
\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
projects.
@@ -332,16 +339,23 @@
in the file currently open in the code editor.
\endlist
\note By default, \QC builds a project before deploying and running
it.
\endlist
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,
you may run tests twice when using \uicontrol {Run All Tests} or
\uicontrol {Run Selected Tests}. This happens if the tests can be
found by the code based test frameworks and are registered as test
with the build system.
\endlist
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 >
\uicontrol Options > \uicontrol {Testing} > \uicontrol General.
@@ -369,7 +383,8 @@
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,
select \inlineimage leafsort.png (\uicontrol {Sort Naturally}).
select \inlineimage leafsort.png
(\uicontrol {Sort Naturally}).
\section2 Running and Debugging Tests from Code Editor
@@ -511,7 +526,7 @@
\li To specify settings for running Catch2 tests, select
\uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
\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
expressions as well. By default Catch2 will print only fails.
\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
\uicontrol Tools > \uicontrol Options > \uicontrol {Testing} >
\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
specific output if a test fails. Contrary to the CTest 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/
**
** 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
\uicontrol Tools > \uicontrol Options > \uicontrol {Version Control} >
\uicontrol Common.
\uicontrol General.
For more information about the supported functions, see
\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/
**
** This file is part of the Qt Creator documentation.
@@ -65,7 +65,7 @@
\li \b {\l{Designing User Interfaces}}
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
structured and enforces a platform look and feel, you can use
the integrated \QD. For more information, see
@@ -114,9 +114,10 @@
execution. In addition, the QML Profiler enables you to profile
Qt Quick applications.
\QC is integrated to the \l{Qt Test}, Google C++ Testing, and
Boost.Test frameworks for unit testing applications and
libraries. You can use \QC to create, build, and run autotests.
\QC is integrated to the \l{Qt Test}, Boost.Test, Catch 2 test,
and Google C++ Testing frameworks for unit testing applications
and libraries. You can use \QC to create, build, and run
autotests.
For more information, see \l{Testing}.
\li \b {Publishing}

View File

@@ -51,7 +51,8 @@
\l{http://doc.qt.io/QtForDeviceCreation/index.html}{Qt for Device Creation}
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

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/
**
** This file is part of the Qt Creator documentation.
@@ -29,8 +29,8 @@
\section2 Creating Widget-Based Qt for Python Applications
\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
gain access to individual Qt modules, such as \l {Qt Core}, \l {Qt GUI},
to use Qt 6 API in Python applications. You can use the PySide6 modules
to gain access to individual Qt modules, such as \l {Qt Core}, \l {Qt GUI},
and \l {Qt Widgets}.
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
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"
@@ -55,21 +56,22 @@
Widgets module, and Qt UI tools:
\badcode
import sys
import os
from pathlib import Path
import sys
from PySide2.QtWidgets import QApplication, QWidget
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtCore import QFile
from PySide6.QtUiTools import QUiLoader
\endcode
The wizard also adds a main class with the specified name that
inherits from the specified base class:
\badcode
class MyWidget(QWidget):
class Widget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
super(Widget, self).__init__()
self.load_ui()
...
\endcode
@@ -79,12 +81,12 @@
\badcode
def load_ui(self):
loader = QUiLoader()
path = os.path.join(os.path.dirname(__file__), "form.ui")
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
loader.load(ui_file, self)
ui_file.close()
loader = QUiLoader()
path = os.fspath(Path(__file__).resolve().parent / "form.ui")
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
loader.load(ui_file, self)
ui_file.close()
\endcode
Next, the wizard adds a main function, where it creates a
@@ -100,8 +102,8 @@
Next, the wizard instantiates the \c MainWindow class and shows it:
\badcode
window = MyWidget()
window.show()
widget = Widget()
widget.show()
...
\endcode
@@ -153,12 +155,12 @@
to QGuiApplication and QQmlApplicationEngine:
\badcode
import sys
import os
from pathlib import Path
import sys
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
\endcode
The wizard also adds a main function, where it creates a QGuiApplication
@@ -175,7 +177,7 @@
\badcode
engine = QQmlApplicationEngine()
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
engine.load(os.fspath(Path(__file__).resolve().parent / "main.qml"))
\endcode
Finally, the wizard adds code that checks whether the file was successfully
@@ -190,7 +192,7 @@
\endcode
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]
*/

View File

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

View File

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

View File

@@ -97,12 +97,14 @@
\list
\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
\inlineimage sort_alphabetically.png
(\uicontrol {Sort Alphabetically}).
\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
\section1 Viewing the Class Hierarchy
@@ -144,5 +146,6 @@
\image qtcreator-include-hierarchy-view.png "Include Hierarchy view"
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 <qmlprivategate.h>
#include "qmlpropertychangesnodeinstance.h"
#include <qmlprivategate.h>
#include <designersupportdelegate.h>
namespace QmlDesigner {
namespace Internal {
@@ -53,12 +54,28 @@ QmlStateNodeInstance::Pointer
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()
{
if (!QmlPrivateGate::States::isStateActive(object(), context())
&& nodeInstanceServer()->hasInstanceForObject(object())) {
nodeInstanceServer()->setStateInstance(nodeInstanceServer()->instanceForObject(object()));
QmlPrivateGate::States::activateState(object(), context());
setAllNodesDirtyRecursive(nodeInstanceServer()->rootItem());
}
}

View File

@@ -1858,7 +1858,11 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
#ifdef QUICK3D_MODULE
if (qobject_cast<QQuick3DModel *>(object)
|| qobject_cast<QQuick3DCamera *>(object)
|| qobject_cast<QQuick3DAbstractLight *>(object)) {
|| qobject_cast<QQuick3DAbstractLight *>(object)
#ifdef QUICK3D_PARTICLES_MODULE
|| qobject_cast<QQuick3DParticleSystem *>(object)
#endif
) {
return true;
}
// 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);
var r = screenSizeModel.screenSizes(index);
widthTextField.text = r.width;
heightTextField.text = r.height;
widthField.realValue = r.width;
heightField.realValue = r.height;
}
Connections {
@@ -252,19 +252,20 @@ Item {
}
// content items
SC.TextField {
id: widthTextField
SC.RealSpinBox {
id: widthField
actionIndicatorVisible: false
translationIndicatorVisible: false
implicitWidth: 50
color: DialogValues.textColor
selectByMouse: true
validator: IntValidator { bottom: 1; top: 100000; }
implicitWidth: 70
labelColor: DialogValues.textColor
realFrom: 100
realTo: 100000
realValue: 100
realStepSize: 10
font.pixelSize: DialogValues.defaultPixelSize
onTextChanged: {
var height = heightTextField.text ? parseInt(heightTextField.text) : 0
var width = text ? parseInt(text) : 0
onRealValueChanged: {
var height = heightField.realValue
var width = realValue
if (width >= height)
orientationButton.setHorizontal()
@@ -276,22 +277,23 @@ Item {
Binding {
target: dialogBox
property: "customWidth"
value: widthTextField.text
value: widthField.realValue
}
SC.TextField {
id: heightTextField
SC.RealSpinBox {
id: heightField
actionIndicatorVisible: false
translationIndicatorVisible: false
implicitWidth: 50
color: DialogValues.textColor
selectByMouse: true
validator: IntValidator { bottom: 1; top: 100000; }
implicitWidth: 70
labelColor: DialogValues.textColor
realFrom: 100
realTo: 100000
realValue: 100
realStepSize: 10
font.pixelSize: DialogValues.defaultPixelSize
onTextChanged: {
var height = text ? parseInt(text) : 0
var width = widthTextField.text ? parseInt(widthTextField.text) : 0
onRealValueChanged: {
var height = realValue
var width = widthField.realValue
if (width >= height)
orientationButton.setHorizontal()
@@ -303,7 +305,7 @@ Item {
Binding {
target: dialogBox
property: "customHeight"
value: heightTextField.text
value: heightField.realValue
}
Item { Layout.fillWidth: true }
@@ -348,9 +350,8 @@ Item {
}
onClicked: {
if (widthTextField.text && heightTextField.text) {
[widthTextField.text, heightTextField.text] = [heightTextField.text, widthTextField.text];
if (widthField.realValue && heightField.realValue) {
[widthField.realValue, heightField.realValue] = [heightField.realValue, widthField.realValue];
checked = !checked
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -251,6 +251,10 @@ StaticAnalysisMessages::StaticAnalysisMessages()
tr("Type cannot be instantiated recursively (%1)."), 1);
newMsg(WarnLogicalValueDoesNotDependOnValues, Warning,
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

View File

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

View File

@@ -37,7 +37,10 @@
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/devicesupport/idevicewidget.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/session.h>
#include <projectexplorer/target.h>
#include <utils/qtcprocess.h>
#include <utils/runextensions.h>
@@ -418,11 +421,19 @@ QUrl AndroidDevice::toolControlChannel(const ControlChannelHint &) const
void AndroidDeviceManager::updateDevicesList()
{
connect(&m_devicesUpdaterTimer, &QTimer::timeout, this, [this]() {
updateDevicesListOnce();
});
// 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();
m_devicesUpdaterTimer.start(deviceUpdaterMsInterval);
}
void AndroidDeviceManager::updateDevicesListOnce()
@@ -537,11 +548,17 @@ void AndroidDeviceManager::setEmulatorArguments(QWidget *parent)
void AndroidDeviceManager::setupDevicesWatcher()
{
// The call to avdmanager is always slower than the call to adb devices,
// so connecting the slot to the slower call should be enough.
connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished,
this, &AndroidDeviceManager::devicesListUpdated);
updateDevicesList();
if (!m_devicesUpdaterTimer.isActive()) {
// The call to avdmanager is always slower than the call to adb devices,
// so connecting the slot to the slower call should be enough.
connect(&m_avdsFutureWatcher, &QFutureWatcherBase::finished,
this, &AndroidDeviceManager::devicesListUpdated);
connect(&m_devicesUpdaterTimer, &QTimer::timeout, this, [this]() {
updateDevicesList();
});
m_devicesUpdaterTimer.start(deviceUpdaterMsInterval);
}
updateDevicesListOnce();
}
void AndroidDeviceManager::devicesListUpdated()

View File

@@ -83,21 +83,9 @@ FilePath ITestConfiguration::executableFilePath() const
if (!hasExecutable())
return {};
if (m_runnable.command.executable().isExecutableFile() && m_runnable.command.executable().path() != ".") {
return m_runnable.command.executable().absoluteFilePath();
} else if (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 {};
const Environment env = m_runnable.environment.size() == 0 ? Environment::systemEnvironment()
: m_runnable.environment;
return env.searchInPath(m_runnable.command.executable().path());
}
Environment ITestConfiguration::filteredEnvironment(const Environment &original) const

View File

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

View File

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

View File

@@ -25,6 +25,7 @@
#include "clangdclient.h"
#include "clangcompletionassistprocessor.h"
#include "clangcompletioncontextanalyzer.h"
#include "clangdiagnosticmanager.h"
#include "clangmodelmanagersupport.h"
@@ -66,6 +67,7 @@
#include <texteditor/texteditor.h>
#include <utils/algorithm.h>
#include <utils/runextensions.h>
#include <utils/utilsicons.h>
#include <QCheckBox>
#include <QDateTime>
@@ -810,14 +812,15 @@ public:
};
enum class CustomAssistMode { Doxygen, Preprocessor };
enum class CustomAssistMode { Doxygen, Preprocessor, IncludePath };
class CustomAssistProcessor : public IAssistProcessor
{
public:
CustomAssistProcessor(ClangdClient *client, int position, unsigned completionOperator,
CustomAssistMode mode)
CustomAssistProcessor(ClangdClient *client, int position, int endPos,
unsigned completionOperator, CustomAssistMode mode)
: m_client(client)
, m_position(position)
, m_endPos(endPos)
, m_completionOperator(completionOperator)
, m_mode(mode)
{}
@@ -833,7 +836,7 @@ private:
CPlusPlus::Icons::keywordIcon());
}
break;
case CustomAssistMode::Preprocessor:
case CustomAssistMode::Preprocessor: {
static QIcon macroIcon = Utils::CodeModelIcon::iconForType(Utils::CodeModelIcon::Macro);
for (const QString &completion
: CppEditor::CppCompletionAssistProcessor::preprocessorCompletions()) {
@@ -843,6 +846,17 @@ private:
completions << createItem("import", macroIcon);
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);
model->loadContent(completions);
const auto proposal = new GenericProposal(m_position, model);
@@ -864,6 +878,7 @@ private:
ClangdClient * const m_client;
const int m_position;
const int m_endPos;
const unsigned m_completionOperator;
const CustomAssistMode m_mode;
};
@@ -1110,6 +1125,12 @@ public:
using LanguageClientCompletionItem::LanguageClientCompletionItem;
void apply(TextDocumentManipulatorInterface &manipulator,
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
@@ -1155,15 +1176,7 @@ ClangdClient::ClangdCompletionAssistProcessor::generateCompletionItems(
// 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.
static const auto criterion = [](const CompletionItem &ci) {
const Utils::optional<MarkupOrString> doc = ci.documentation();
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");
return ClangdCompletionItem::getQtType(ci) == ClangdCompletionItem::SpecialQtType::Signal;
};
const QTextDocument *doc = document();
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)
{
const auto refData = runningFindUsages.find(key);
@@ -2817,14 +2854,26 @@ IAssistProcessor *ClangdClient::ClangdCompletionAssistProvider::createProcessor(
qCDebug(clangdLogCompletion) << "creating doxygen processor";
return new CustomAssistProcessor(m_client,
contextAnalyzer.positionForProposal(),
contextAnalyzer.positionEndOfExpression(),
contextAnalyzer.completionOperator(),
CustomAssistMode::Doxygen);
case ClangCompletionContextAnalyzer::CompletePreprocessorDirective:
qCDebug(clangdLogCompletion) << "creating macro processor";
return new CustomAssistProcessor(m_client,
contextAnalyzer.positionForProposal(),
contextAnalyzer.positionEndOfExpression(),
contextAnalyzer.completionOperator(),
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:
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,
const AstHandler &astHandler,
AstCallbackMode callbackMode, const Range &range)

View File

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

View File

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

View File

@@ -608,6 +608,7 @@ void ClangModelManagerSupport::onAbstractEditorSupportContentsUpdated(const QStr
const QString mappedPath = m_uiHeaderOnDiskManager.write(filePath, content);
m_communicator.unsavedFilesUpdated(mappedPath, content, 0);
ClangdClient::handleUiHeaderChange(Utils::FilePath::fromString(filePath).fileName());
}
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 projectPartId = projectPartIdForFile(filePath);
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);
QVERIFY(proposal);
QVERIFY(hasItem(proposal, " file.h>"));
QVERIFY(hasItem(proposal, " otherFile.h>"));
QVERIFY(hasItem(proposal, " mylib/"));
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, " otherFile.h>"));
QVERIFY(hasItem(proposal, " mylib/"));
}
QVERIFY(!hasSnippet(proposal, "class "));
}

View File

@@ -64,7 +64,7 @@ public:
Utils::Id id() const { return m_id; }
WizardKind kind() const { return m_supportedProjectTypes.isEmpty() ? FileWizard : ProjectWizard; }
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 displayName() const { return m_displayName; }
QString category() const { return m_category; }
@@ -79,7 +79,7 @@ public:
void setId(const Utils::Id id) { m_id = id; }
void setSupportedProjectTypes(const QSet<Utils::Id> &projectTypes) { m_supportedProjectTypes = projectTypes; }
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 setDisplayName(const QString &displayName) { m_displayName = displayName; }
void setCategory(const QString &category) { m_category = category; }
@@ -137,7 +137,7 @@ private:
QAction *m_action = nullptr;
QIcon m_icon;
QString m_fontIconCode;
QString m_fontIconName;
QString m_description;
QString m_displayName;
QString m_category;

View File

@@ -57,7 +57,7 @@ QString ProjectPart::projectFileLocation() 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)

View File

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

View File

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

View File

@@ -341,13 +341,13 @@ struct McuTargetDescription
} platform;
struct {
QString id;
QVector<QString> versions;
QStringList versions;
} toolchain;
struct {
QString name;
QString defaultPath;
QString envVar;
QVector<QString> versions;
QStringList versions;
} boardSdk;
struct {
QString envVar;
@@ -658,10 +658,10 @@ static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion
const QJsonObject freeRTOS = target.value("freeRTOS").toObject();
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(); });
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(); });
return {
@@ -670,13 +670,13 @@ static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion
{},
{
toolchain.value("id").toString(),
toolchainVersionsVector,
toolchainVersionsList,
},
{
boardSdk.value("name").toString(),
boardSdk.value("defaultPath").toString(),
boardSdk.value("envVar").toString(),
boardSdkVersionsVector,
boardSdkVersionsList,
},
{
freeRTOS.value("envVar").toString(),

View File

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

View File

@@ -1,5 +1,10 @@
<RCC>
<qresource prefix="/boilerplatetemplates">
<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>
</RCC>

View File

@@ -186,6 +186,11 @@ QString Theme::getIconUnicode(Theme::Icon i)
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
{
return getColor(QmlDesigner_BackgroundColorDarker);

View File

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

View File

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

View File

@@ -160,40 +160,65 @@ void ComponentTextModifier::handleOriginalTextChanged()
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 newLen = currentText.size();
int newSpace = 0;
int oldSpace = 0;
int newIdx = 0;
for (int oldIdx = 0; oldIdx < oldLen; ++oldIdx) {
const QChar oldChar = m_originalText[oldIdx];
if (oldIdx == m_componentStartOffset)
m_componentStartOffset += newSpace - oldSpace;
if (oldIdx == m_componentEndOffset) {
m_componentEndOffset += newSpace - oldSpace;
break;
if (oldLen != newLen) {
int newSpace = 0;
int oldSpace = 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) {
const QChar oldChar = m_originalText[oldIdx];
if (oldIdx == m_componentStartOffset)
newStartOffset += newSpace - oldSpace;
if (oldIdx == m_componentEndOffset) {
m_componentEndOffset += newSpace - oldSpace;
m_componentStartOffset = newStartOffset;
m_originalText = currentText;
break;
}
while (newIdx < newLen && currentText[newIdx].isSpace()) {
++newSpace;
++newIdx;
}
if (oldChar.isSpace()) {
++oldSpace;
continue;
}
if (currentText[newIdx] != oldChar) {
nonWhiteSpaceChangeIdx = oldIdx;
// 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;
} else {
++newIdx;
}
}
while (newIdx < newLen && currentText[newIdx].isSpace()) {
++newSpace;
++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;
}
if (oldChar.isSpace()) {
++oldSpace;
continue;
}
if (currentText[newIdx] != oldChar) {
// Non-whitespace difference, we can't determine a valid offset in this case
// TODO: Needs proper handling to deal with undo/redo/arbitrary edits somehow (QDS-5392)
break;
} else {
++newIdx;
}
}
m_originalText = currentText;
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 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 SHOW_DEBUG_SETTINGS[] = "ShowDebugSettings";
const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView";
const char COLOR_PALETTE_RECENT[] = "ColorPaletteRecent";
const char COLOR_PALETTE_FAVORITE[] = "ColorPaletteFavorite";

View File

@@ -78,7 +78,7 @@ void onGenerateCmakeLists()
{
queuedFiles.clear();
FilePath rootDir = ProjectExplorer::SessionManager::startupProject()->projectDirectory();
GenerateCmakeLists::generateMainCmake(rootDir);
GenerateCmakeLists::generateCmakes(rootDir);
GenerateEntryPoints::generateMainCpp(rootDir);
GenerateEntryPoints::generateMainQml(rootDir);
if (showConfirmationDialog(rootDir))
@@ -139,138 +139,125 @@ bool writeFile(const GeneratableFile &file)
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 {
QStringList moduleNames;
const QDir::Filters FILES_ONLY = QDir::Files;
const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
const char CMAKEFILENAME[] = "CMakeLists.txt";
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);
for (FilePath &file : files) {
if (!file.fileName().compare(CMAKEFILENAME))
files.removeAll(file);
}
FilePath contentDir = rootDir.pathAppended("content");
FilePath importDir = rootDir.pathAppended("imports");
if (files.isEmpty()) {
generateSubdirCmake(dir);
FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
for (FilePath &subDir : subDirs) {
QStringList subDirModules = processDirectory(subDir);
moduleNames.append(subDirModules);
}
}
else {
QString moduleName = generateModuleCmake(dir);
if (!moduleName.isEmpty()) {
moduleNames.append(moduleName);
}
}
generateModuleCmake(contentDir);
generateImportCmake(importDir);
generateMainCmake(rootDir);
return moduleNames;
return true;
}
const char MAINFILE_REQUIRED_VERSION[] = "cmake_minimum_required(VERSION 3.18)\n\n";
const char MAINFILE_PROJECT[] = "project(%1 LANGUAGES CXX)\n\n";
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";
const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl";
const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl";
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.
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;
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) {
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));
createCmakeFile(rootDir, fileContent);
queueCmakeFile(dir, fileContent);
}
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_CREATE_MODULE[] = "qt6_add_qml_module(%1\n\tURI \"%1\"\n\tVERSION 1.0\n%2)\n\n";
const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n";
const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl";
QString generateModuleCmake(const FilePath &dir)
void generateModuleCmake(const FilePath &dir)
{
QString fileContent;
QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH);
const QStringList qmldirFilesOnly(QMLDIRFILENAME);
QString singletonContent;
FilePaths qmldirFileList = dir.dirEntries(qmldirFilesOnly, FILES_ONLY);
if (!qmldirFileList.isEmpty()) {
QStringList singletons = getSingletonsFromQmldirFile(qmldirFileList.first());
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);
QString qmlFiles;
for (QString &qmlFile : qmlFileList)
qmlFiles.append(QString("\t\t%1\n").arg(qmlFile));
qmlFiles.append(QString(" %1\n").arg(qmlFile));
QStringList resourceFileList = getDirectoryTreeResources(dir);
QString resourceFiles;
for (QString &resourceFile : resourceFileList)
resourceFiles.append(QString("\t\t%1\n").arg(resourceFile));
resourceFiles.append(QString(" %1\n").arg(resourceFile));
QString moduleContent;
if (!qmlFiles.isEmpty()) {
moduleContent.append(QString("\tQML_FILES\n%1").arg(qmlFiles));
moduleContent.append(QString(" QML_FILES\n%1").arg(qmlFiles));
}
if (!resourceFiles.isEmpty()) {
moduleContent.append(QString("\tRESOURCES\n%1").arg(resourceFiles));
moduleContent.append(QString(" RESOURCES\n%1").arg(resourceFiles));
}
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;
FilePaths subDirs = dir.dirEntries(DIRS_ONLY);
for (FilePath &subDir : subDirs) {
fileContent.append(QString(ADD_SUBDIR).arg(subDir.fileName()));
}
createCmakeFile(dir, fileContent);
fileContent.append(fileTemplate.arg(singletonContent).arg(moduleName).arg(moduleContent));
queueCmakeFile(dir, fileContent);
}
QStringList getSingletonsFromQmldirFile(const FilePath &filePath)
@@ -347,7 +334,7 @@ QStringList getDirectoryTreeResources(const FilePath &dir)
return resourceFileList;
}
void createCmakeFile(const FilePath &dir, const QString &content)
void queueCmakeFile(const FilePath &dir, const QString &content)
{
FilePath filePath = dir.pathAppended(CMAKEFILENAME);
GenerateCmake::queueFile(filePath, content);
@@ -370,35 +357,42 @@ bool generateEntryPointFiles(const FilePath &dir)
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_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)
{
QFile templatefile(MAIN_CPPFILE_CONTENT);
templatefile.open(QIODevice::ReadOnly);
QTextStream stream(&templatefile);
QString content = stream.readAll();
templatefile.close();
FilePath srcDir = dir.pathAppended(MAIN_CPPFILE_DIR);
FilePath filePath = dir.pathAppended(MAIN_CPPFILE_NAME);
return GenerateCmake::queueFile(filePath, content);
QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH);
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";
bool generateMainQml(const FilePath &dir)
{
QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_PATH);
FilePath filePath = dir.pathAppended(MAIN_QMLFILE_NAME);
QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName();
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));
return GenerateCmake::queueFile(filePath, content);
}
}

View File

@@ -45,16 +45,17 @@ bool showConfirmationDialog(const Utils::FilePath &rootDir);
bool queueFile(const Utils::FilePath &filePath, const QString &fileContent);
bool writeFile(const GeneratableFile &file);
bool writeQueuedFiles();
QString readTemplate(const QString &templatePath);
}
namespace GenerateCmakeLists {
bool generateCmakes(const Utils::FilePath &rootDir);
void generateMainCmake(const Utils::FilePath &rootDir);
void generateSubdirCmake(const Utils::FilePath &dir);
QString generateModuleCmake(const Utils::FilePath &dir);
QStringList processDirectory(const Utils::FilePath &dir);
void generateImportCmake(const Utils::FilePath &dir);
void generateModuleCmake(const Utils::FilePath &dir);
QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath);
QStringList getDirectoryTreeQmls(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);
}
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(
DesignerSettingsKey::ASK_BEFORE_DELETING_ASSET).toBool());
if (settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool()) {
m_ui.debugGroupBox->hide();
m_ui.featureTimelineEditorCheckBox->hide();
}
const auto standaloneMode = settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool();
#ifdef QT_DEBUG
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()

View File

@@ -199,7 +199,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
info(openInQDSAppSetting,
description + tr(" Learn more about Qt Design Studio here: ")
+ "<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);
}
return;
@@ -209,7 +209,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
Utils::InfoBarEntry
info(openInQDSAppSetting,
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] {
Core::ICore::infoBar()->removeInfo(openInQDSAppSetting);

View File

@@ -353,6 +353,10 @@ bool StudioWelcomePlugin::initialize(const QStringList &arguments, QString *erro
void StudioWelcomePlugin::extensionsInitialized()
{
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(),
DO_NOT_SHOW_SPLASHSCREEN_AGAIN_KEY)) {
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"));
#endif
// disabled by default
Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); });
QTC_ASSERT(s_view->rootObject(),
qWarning() << "The StudioWelcomePlugin has a runtime depdendency on "

View File

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

View File

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

View File

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

View File

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