From 624df6ec4414df8738c753bb0bc8968f7a09a391 Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Thu, 23 Sep 2021 14:40:44 +0200 Subject: [PATCH 01/15] Doc: Add Qt-Bridge plugin docs for adobe XD Task-number: QDS-4615 Change-Id: Ie3c7d814fbf59841f112315cf71553076ec7e0d7 Reviewed-by: Leena Miettinen --- doc/config/macros.qdocconf | 1 + .../images/qt-bridge-xd-home.png | Bin 0 -> 10288 bytes .../images/qt-bridge-xd-menu.png | Bin 0 -> 5971 bytes .../images/qt-bridge-xd-settings.png | Bin 0 -> 10100 bytes .../images/qt-bridge-xd-warn.png | Bin 0 -> 22311 bytes doc/qtdesignstudio/images/qt-bridge-xd.png | Bin 0 -> 43730 bytes doc/qtdesignstudio/images/xd-logo.png | Bin 0 -> 4636 bytes .../src/qtbridge/qtbridge-overview.qdoc | 2 + .../src/qtbridge/qtbridge-ps-using.qdoc | 2 +- .../qtbridge/qtbridge-sketch-overview.qdoc | 2 +- .../src/qtbridge/qtbridge-xd-overview.qdoc | 58 +++++ .../src/qtbridge/qtbridge-xd-setup.qdoc | 57 +++++ .../src/qtbridge/qtbridge-xd-using.qdoc | 219 ++++++++++++++++++ .../src/qtdesignstudio-toc.qdoc | 5 + 14 files changed, 344 insertions(+), 2 deletions(-) create mode 100644 doc/qtdesignstudio/images/qt-bridge-xd-home.png create mode 100644 doc/qtdesignstudio/images/qt-bridge-xd-menu.png create mode 100644 doc/qtdesignstudio/images/qt-bridge-xd-settings.png create mode 100644 doc/qtdesignstudio/images/qt-bridge-xd-warn.png create mode 100644 doc/qtdesignstudio/images/qt-bridge-xd.png create mode 100644 doc/qtdesignstudio/images/xd-logo.png create mode 100644 doc/qtdesignstudio/src/qtbridge/qtbridge-xd-overview.qdoc create mode 100644 doc/qtdesignstudio/src/qtbridge/qtbridge-xd-setup.qdoc create mode 100644 doc/qtdesignstudio/src/qtbridge/qtbridge-xd-using.qdoc diff --git a/doc/config/macros.qdocconf b/doc/config/macros.qdocconf index 22c0c182ccf..4ae4dc16177 100644 --- a/doc/config/macros.qdocconf +++ b/doc/config/macros.qdocconf @@ -20,6 +20,7 @@ macro.Q3DS = "Qt 3D Studio" macro.QA = "Qt Assistant" macro.QB = "Qt Bridge" macro.QBPS = "Qt Bridge for Adobe Photoshop" +macro.QBXD = "Qt Bridge for Adobe XD" macro.QBSK = "Qt Bridge for Sketch" macro.QBF = "Qt Bridge for Figma" macro.QC = "$IDE_DISPLAY_NAME" diff --git a/doc/qtdesignstudio/images/qt-bridge-xd-home.png b/doc/qtdesignstudio/images/qt-bridge-xd-home.png new file mode 100644 index 0000000000000000000000000000000000000000..2d4dfa20db025e13ae4c14ea4e157cd32e067eec GIT binary patch literal 10288 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 b<$vbSJ0Hrf+VnyYG&1h#>gTe~DWM4f_c?Pw literal 0 HcmV?d00001 diff --git a/doc/qtdesignstudio/images/qt-bridge-xd-settings.png b/doc/qtdesignstudio/images/qt-bridge-xd-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..6c16f50f408b0d907d71cf7f72f91ef6963aed51 GIT binary patch literal 10100 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 literal 0 HcmV?d00001 diff --git a/doc/qtdesignstudio/images/qt-bridge-xd-warn.png b/doc/qtdesignstudio/images/qt-bridge-xd-warn.png new file mode 100644 index 0000000000000000000000000000000000000000..18a79320d493e4c2358698ecb227d35414eec97d GIT binary patch literal 22311 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 AEC2ui literal 0 HcmV?d00001 diff --git a/doc/qtdesignstudio/images/qt-bridge-xd.png b/doc/qtdesignstudio/images/qt-bridge-xd.png new file mode 100644 index 0000000000000000000000000000000000000000..c9a0b72676d17898f8de27967092f245ea4668f1 GIT binary patch literal 43730 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 literal 0 HcmV?d00001 diff --git a/doc/qtdesignstudio/images/xd-logo.png b/doc/qtdesignstudio/images/xd-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..07a189bc0fa3dadad350d810ffe109a5e368bf78 GIT binary patch literal 4636 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 \uicontrol {\QB}. +*/ diff --git a/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-using.qdoc b/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-using.qdoc new file mode 100644 index 00000000000..2988954af91 --- /dev/null +++ b/doc/qtdesignstudio/src/qtbridge/qtbridge-xd-using.qdoc @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Bridge documentation. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** +****************************************************************************/ + +/*! + \previouspage qtbridge-xd-setup.html + \page qtbridge-xd-using.html + \nextpage sketchqtbridge.html + + \title Using \QBXD + + \section1 Organizing Assets + + To get the best results when you use \QBXD to export designs from Adobe XD + to \QDS, follow these guidelines when working with Adobe XD: + + \list + \li Arrange your design into \e artboards and organize it into groups and + layers that are imported into \QDS as separate files. + \li Use descriptive and unique IDs to avoid duplicate asset names and IDs + in the generated UI. + \endlist + + + To use the fonts that you use in Adobe XD also in \QDS, you need to import + them to \QDS as assets. \QDS deploys them to devices when you preview the + UI. For more information, see \l{Using Custom Fonts}. + + + \section2 Supported Design Elements + + You can export the following parts of your design using \QBXD: + \list + \li Artboard + \li Group + \li Shapes (Rectangle, Ellipse, Polygon, Line, Pen) + \li Text + \endlist + + The following design elements might not be exported as expected. + \list + \li Components + \li Prototype + \li Repeat Grid + \endlist + + + \section2 Using Artboards + + The hierarchical relationships between artboards and layers are preserved + when you export designs from Adobe XD and import them into \QDS. The + relationships are the basis of how the Items are organized in the generated + code in \QDS. + + An artboard can only be exported as a component or skipped. A component will + be imported as a separate file that contains the artwork and text on the + artboard. + + \section2 Annotate Layers for Export + + With \QBXD, layers can be annotated to hint how each layer or group must be + exported. \uicontrol The {Home} panel displays and allows layer annotation for + export: + + \image qt-bridge-xd-home.png + + \list 1 + \li \QBXD automatically proposes identifiers for all groups and layers + that you can change in the \uicontrol {ID} field. Use unique and + descriptive IDs to avoid duplicate IDs when the layer and the + respective artwork is imported into \QDS. Even though the importer + in \QDS is capable of fixing duplicate IDs, doing so will generate + warnings. It is recommend that you should manually check all the + IDs to make them unique and descriptive. + + \li In the \uicontrol {Export As} field, select the export type for the + group or layer: + \list + \li \uicontrol Component exports the layer as a separate UI file + that contains all the exportable artwork and text in it. Only + Artboards can be exported as components. + \li \uicontrol Child exports each asset of the selected group + or layer a separate PNG file, with references + to the images in the component file. + \li \uicontrol Merged merges the rendition of the selected groups + and layers into the rendition of parent artboard or group as + one item. + \li \uicontrol Skipped completely skips the selected layer. + \endlist + \li In the \uicontrol {Component} field, specify the component or + \l {Shapes}{Qt Quick Studio Component} to morph this + layer into. The component that is generated during import will be + of this type. For example, if you drew a rectangle, you can export + it as a \l {basic-rectangle}{Rectangle} component. + You can provide the import statement of the module where the + component is defined in the \uicontrol {Imports} field. + \note The implicit properties except position and size are not + applied when the \uicontrol {Component} is defined. For example, all text + properties will be ignored if \uicontrol {Component} is defined + for a text layer, but explicit properties defined in the \uicontrol + {Properties} field will be applied. + \li In the \uicontrol {Imports} field, enter additional import statements + to have them added to the generated code file. For example, to use + Qt Quick Controls 2.3, you need the import statement + \c {QtQuick.Controls 2.3} and to use Qt Quick Studio Components 1.0, + you need the import statement \c {QtQuick.Studio.Components 1.0}. + You can also import a module as an alias. + \li In the \uicontrol {Properties} field, specify properties for the + component. You can add and modify properties in \QDS. + \li Select the \uicontrol Clip check box to enable clipping in the + component generated from the layer. The generated component will clip + its own painting, as well as the painting of its children, to its + bounding rectangle. + \li Select the \uicontrol Visible check box to determine the visibility + of the layer in the generated UI in \QDS. + \li Select \uicontrol Export to export the document into a .qtbridge + archive. + \endlist + + + \section2 Export Defaults + + \QBXD assigns the following defaults to the layers: + + By default: + \list + \li Artboards are exported as \e components. + \li Immediate children of an Artboard and Text layers are exported as + \e child. + \li Any layer not falling under the aforementioned criteria is exported + as \e merged. + \li Images are exported as PNGs by default with no Hi-DPI images. + \li \uicontrol Visible is set to \c true. + \endlist + + All the assets and metadata are copied to the directory you specified. This + might take a little while depending on the complexity of your project. + + You can now create a project in \QDS and import the assets to it, as + described in \l {Creating Projects} and \l{Importing Designs}. + + \section1 \QBXD Settings + + Select \uicontrol Settings to change the export settings. + + \image qt-bridge-xd-menu.png + + \image qt-bridge-xd-settings.png + + + \list 1 + \li Select \uicontrol {Reset All} to remove all of the \QB data + stored in the document. Use \uicontrol {Edit} > \uicontrol {Undo} + to restore the data if you accidentally removed it. + \li You can export images into PNG, JPG or SVG format. In the section + \uicontrol {Export Formats}, select the image format to + export. + \li Depending on the image format selected for export, the + \uicontrol {Format Options} allows fine tuning the exported + image. + \list + \li Select \uicontrol {Hi-DPI Assets} to generate Hi-DPI + images alongside normal scale images. Being a vector format, + this option is not available for SVG format. + \li Select \uicontrol {SVG Minify} to minify the SVG. + \li Select \uicontrol {JPG Quality} to specify the JPG + compression quality in the range [1, 100]. + \endlist + \endlist + + \section1 Suggestions and Tips + + You can export assets using the default settings and make all the changes + later in \QDS. If you are familiar with the \l{QML Syntax Basics} + {QML syntax}, you can modify the settings to tailor the generated code to + a certain degree. For example, you can specify the component or + \l {Shapes}{Qt Quick Studio Component} to use for a component or + layer. If you have drawn an arc that you mean to animate, you can export it + as an \l Arc component to avoid having to replace the arc image with an Arc + component in \QDS. Or you could export a button as a Qt Quick Controls + \l Button component. + + \list + \li Name the layers in exactly the same way as your IDs, to be able to + find artwork later, especially as the export files can grow very + large and complicated as they approach the level of a complete UI + project. + \li Make sure to skip all artboards that you don't want to be part of + the final UI to avoid cluttering the \QDS project. You can select + multiple artboards on a page and then select \uicontrol Skip in \QBXD + to skip them. + \li Store all assets in the scalable vector graphics (SVG) format to be + able to easily rescale them for different screen sizes and resolutions. + You can export assets into JPG, PNG, or SVG format and select options + for optimizing them during the export. + \endlist + +*/ diff --git a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc index 12bae906f41..f917223dfc4 100644 --- a/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc +++ b/doc/qtdesignstudio/src/qtdesignstudio-toc.qdoc @@ -153,6 +153,11 @@ \li \l{Setting Up Qt Bridge for Adobe Photoshop} \li \l{Using Qt Bridge for Adobe Photoshop} \endlist + \li \l{Exporting Designs from Adobe XD} + \list + \li \l{Setting Up Qt Bridge for Adobe XD} + \li \l{Using Qt Bridge for Adobe XD} + \endlist \li \l{Exporting Designs from Sketch} \list \li \l{Setting Up Qt Bridge for Sketch} From eedf02e40f471fdef41a9f9fce0160e5681c3dc9 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 28 Sep 2021 12:29:29 +0200 Subject: [PATCH 02/15] Incredibuild: Use more FilePath in CommandBuilder Change-Id: I31e2be7cbd8f5ac58db4bead1fa3266bb80df868 Reviewed-by: Christian Stenger --- .../incredibuild/cmakecommandbuilder.cpp | 5 +++-- .../incredibuild/cmakecommandbuilder.h | 2 +- src/plugins/incredibuild/commandbuilder.cpp | 18 +++++++-------- src/plugins/incredibuild/commandbuilder.h | 10 ++++----- .../incredibuild/commandbuilderaspect.cpp | 10 ++++----- .../incredibuild/makecommandbuilder.cpp | 22 +++++++++---------- src/plugins/incredibuild/makecommandbuilder.h | 2 +- 7 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/plugins/incredibuild/cmakecommandbuilder.cpp b/src/plugins/incredibuild/cmakecommandbuilder.cpp index b505c4b5ef6..a158aa9798b 100644 --- a/src/plugins/incredibuild/cmakecommandbuilder.cpp +++ b/src/plugins/incredibuild/cmakecommandbuilder.cpp @@ -36,6 +36,7 @@ #include using namespace ProjectExplorer; +using namespace Utils; namespace IncrediBuild { namespace Internal { @@ -45,11 +46,11 @@ QList CMakeCommandBuilder::migratableSteps() const return {CMakeProjectManager::Constants::CMAKE_BUILD_STEP_ID}; } -QString CMakeCommandBuilder::defaultCommand() const +FilePath CMakeCommandBuilder::defaultCommand() const { const QString defaultCMake = "cmake"; const QString cmake = QStandardPaths::findExecutable(defaultCMake); - return cmake.isEmpty() ? defaultCMake : cmake; + return FilePath::fromString(cmake.isEmpty() ? defaultCMake : cmake); } QString CMakeCommandBuilder::defaultArguments() const diff --git a/src/plugins/incredibuild/cmakecommandbuilder.h b/src/plugins/incredibuild/cmakecommandbuilder.h index 2fdeaa757cb..76c66b5beaf 100644 --- a/src/plugins/incredibuild/cmakecommandbuilder.h +++ b/src/plugins/incredibuild/cmakecommandbuilder.h @@ -41,7 +41,7 @@ private: QList migratableSteps() const final; QString id() const final { return "CMakeCommandBuilder"; } QString displayName() const final { return tr("CMake"); } - QString defaultCommand() const final; + Utils::FilePath defaultCommand() const final; QString defaultArguments() const final; QString setMultiProcessArg(QString args) final; }; diff --git a/src/plugins/incredibuild/commandbuilder.cpp b/src/plugins/incredibuild/commandbuilder.cpp index b7ae39a2664..d4b6ee42864 100644 --- a/src/plugins/incredibuild/commandbuilder.cpp +++ b/src/plugins/incredibuild/commandbuilder.cpp @@ -25,27 +25,27 @@ #include "commandbuilder.h" +using namespace Utils; + namespace IncrediBuild { namespace Internal { -namespace Constants { -const QLatin1String CUSTOMCOMMANDBUILDER_COMMAND("IncrediBuild.BuildConsole.%1.Command"); -const QLatin1String CUSTOMCOMMANDBUILDER_ARGS("IncrediBuild.BuildConsole.%1.Arguments"); -} // namespace Constants +const char CUSTOMCOMMANDBUILDER_COMMAND[] = "IncrediBuild.BuildConsole.%1.Command"; +const char CUSTOMCOMMANDBUILDER_ARGS[] = "IncrediBuild.BuildConsole.%1.Arguments"; void CommandBuilder::fromMap(const QVariantMap &map) { - m_command = map.value(QString(Constants::CUSTOMCOMMANDBUILDER_COMMAND).arg(id())).toString(); - m_args = map.value(QString(Constants::CUSTOMCOMMANDBUILDER_ARGS).arg(id())).toString(); + m_command = FilePath::fromVariant(map.value(QString(CUSTOMCOMMANDBUILDER_COMMAND).arg(id()))); + m_args = map.value(QString(CUSTOMCOMMANDBUILDER_ARGS).arg(id())).toString(); } void CommandBuilder::toMap(QVariantMap *map) const { - (*map)[QString(Constants::CUSTOMCOMMANDBUILDER_COMMAND).arg(id())] = QVariant(m_command); - (*map)[QString(Constants::CUSTOMCOMMANDBUILDER_ARGS).arg(id())] = QVariant(m_args); + (*map)[QString(CUSTOMCOMMANDBUILDER_COMMAND).arg(id())] = m_command.toVariant(); + (*map)[QString(CUSTOMCOMMANDBUILDER_ARGS).arg(id())] = QVariant(m_args); } -void CommandBuilder::setCommand(const QString &command) +void CommandBuilder::setCommand(const FilePath &command) { m_command = command; } diff --git a/src/plugins/incredibuild/commandbuilder.h b/src/plugins/incredibuild/commandbuilder.h index 2e8df6af612..83bae1d2b30 100644 --- a/src/plugins/incredibuild/commandbuilder.h +++ b/src/plugins/incredibuild/commandbuilder.h @@ -50,20 +50,20 @@ public: virtual void fromMap(const QVariantMap &map); virtual void toMap(QVariantMap *map) const; - virtual QString defaultCommand() const { return QString(); } + virtual Utils::FilePath defaultCommand() const { return {}; } virtual QString defaultArguments() const { return QString(); } virtual QString setMultiProcessArg(QString args) { return args; } - QString command() const { return m_command; } - void setCommand(const QString &command); - QString effectiveCommand() const { return m_command.isEmpty() ? defaultCommand() : m_command; } + Utils::FilePath command() const { return m_command; } + void setCommand(const Utils::FilePath &command); + Utils::FilePath effectiveCommand() const { return m_command.isEmpty() ? defaultCommand() : m_command; } QString arguments() { return m_args.isEmpty() ? defaultArguments() : m_args; } void setArguments(const QString &arguments); private: ProjectExplorer::BuildStep *m_buildStep{}; - QString m_command; + Utils::FilePath m_command; QString m_args; }; diff --git a/src/plugins/incredibuild/commandbuilderaspect.cpp b/src/plugins/incredibuild/commandbuilderaspect.cpp index 82abefa6339..c5550cab156 100644 --- a/src/plugins/incredibuild/commandbuilderaspect.cpp +++ b/src/plugins/incredibuild/commandbuilderaspect.cpp @@ -101,7 +101,7 @@ QString CommandBuilderAspect::fullCommandFlag(bool keepJobNum) const argsLine = d->m_activeCommandBuilder->setMultiProcessArg(argsLine); QString fullCommand("\"%1\" %2"); - fullCommand = fullCommand.arg(d->m_activeCommandBuilder->effectiveCommand(), argsLine); + fullCommand = fullCommand.arg(d->m_activeCommandBuilder->effectiveCommand().toUserOutput(), argsLine); return fullCommand; } @@ -153,7 +153,7 @@ void CommandBuilderAspect::addToLayout(LayoutBuilder &builder) d->makePathChooser->setBaseDirectory(PathChooser::homePath()); d->makePathChooser->setHistoryCompleter("IncrediBuild.BuildConsole.MakeCommand.History"); connect(d->makePathChooser, &PathChooser::rawPathChanged, this, [this] { - d->m_activeCommandBuilder->setCommand(d->makePathChooser->rawPath()); + d->m_activeCommandBuilder->setCommand(d->makePathChooser->rawFilePath()); updateGui(); }); } @@ -212,9 +212,9 @@ void CommandBuilderAspect::updateGui() d->commandBuilder->setCurrentText(d->m_activeCommandBuilder->displayName()); - const QString defaultCommand = d->m_activeCommandBuilder->defaultCommand(); - d->makePathChooser->setPath(d->m_activeCommandBuilder->command()); - d->makePathChooser->setDefaultValue(defaultCommand); + const FilePath defaultCommand = d->m_activeCommandBuilder->defaultCommand(); + d->makePathChooser->setFilePath(d->m_activeCommandBuilder->command()); + d->makePathChooser->setDefaultValue(defaultCommand.toUserOutput()); const QString defaultArgs = d->m_activeCommandBuilder->defaultArguments(); d->makeArgumentsLineEdit->setPlaceholderText(defaultArgs); diff --git a/src/plugins/incredibuild/makecommandbuilder.cpp b/src/plugins/incredibuild/makecommandbuilder.cpp index a758b4949df..0a5fd38ca90 100644 --- a/src/plugins/incredibuild/makecommandbuilder.cpp +++ b/src/plugins/incredibuild/makecommandbuilder.cpp @@ -41,6 +41,7 @@ #include using namespace ProjectExplorer; +using namespace Utils; namespace IncrediBuild { namespace Internal { @@ -50,35 +51,32 @@ QList MakeCommandBuilder::migratableSteps() const return {QmakeProjectManager::Constants::MAKESTEP_BS_ID}; } -QString MakeCommandBuilder::defaultCommand() const +Utils::FilePath MakeCommandBuilder::defaultCommand() const { BuildConfiguration *buildConfig = buildStep()->buildConfiguration(); if (buildConfig) { - Target *target = buildStep()->target(); - if (target) { - ToolChain *toolChain = ToolChainKitAspect::toolChain(target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID); - if (toolChain) - return toolChain->makeCommand(buildConfig->environment()).toUserOutput(); + if (Target *target = buildStep()->target()) { + if (ToolChain *toolChain = ToolChainKitAspect::cxxToolChain(target->kit())) + return toolChain->makeCommand(buildConfig->environment()); } } - return QString(); + return {}; } QString MakeCommandBuilder::setMultiProcessArg(QString args) { - QString cmd = command(); - QFileInfo fileInfo(cmd); + const FilePath cmd = command(); // jom -j 200 - if (fileInfo.baseName().compare("jom", Qt::CaseSensitivity::CaseInsensitive) == 0) { + if (cmd.baseName().compare("jom", Qt::CaseSensitivity::CaseInsensitive) == 0) { QRegularExpression regExp("\\s*\\-j\\s+\\d+"); args.remove(regExp); args.append(" -j 200"); } // make -j200 - else if ((fileInfo.baseName().compare("make", Qt::CaseSensitivity::CaseInsensitive) == 0) - || (fileInfo.baseName().compare("gmake", Qt::CaseSensitivity::CaseInsensitive) == 0)) { + else if ((cmd.baseName().compare("make", Qt::CaseSensitivity::CaseInsensitive) == 0) + || (cmd.baseName().compare("gmake", Qt::CaseSensitivity::CaseInsensitive) == 0)) { QRegularExpression regExp("\\s*\\-j\\d+"); args.remove(regExp); args.append(" -j200"); diff --git a/src/plugins/incredibuild/makecommandbuilder.h b/src/plugins/incredibuild/makecommandbuilder.h index 9fad53a1031..10754c8577e 100644 --- a/src/plugins/incredibuild/makecommandbuilder.h +++ b/src/plugins/incredibuild/makecommandbuilder.h @@ -41,7 +41,7 @@ private: QList migratableSteps() const final; QString id() const final { return "MakeCommandBuilder"; } QString displayName() const final { return tr("Make"); } - QString defaultCommand() const final; + Utils::FilePath defaultCommand() const final; QString setMultiProcessArg(QString args) final; }; From 34cdffa89b5640f1184b7c1becf6228fdcd23649 Mon Sep 17 00:00:00 2001 From: Johanna Vanhatapio Date: Mon, 27 Sep 2021 18:05:34 +0300 Subject: [PATCH 03/15] Doc: Update info about camera components Task-number: QDS-4888 Change-Id: I7fe351d34953d3a5a59397818b92d93139aa81c6 Reviewed-by: Miikka Heikkinen Reviewed-by: Leena Miettinen Reviewed-by: Mahmoud Badri --- .../studio-qtquick-camera-properties.png | Bin 11078 -> 51403 bytes .../qtdesignstudio-3d-camera.qdoc | 49 ++++++++++++------ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/doc/qtdesignstudio/images/studio-qtquick-camera-properties.png b/doc/qtdesignstudio/images/studio-qtquick-camera-properties.png index 8209b39fd701ec229232949293f7c740ea5625b5..61c91a86071aa4f6ceb1ae806c48e4d1b65b16be 100644 GIT binary patch literal 51403 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

Naj`YHCVh`VQU z8^fAyC4Ti*vDGL49{=3v9=G}b75TrL+u!edar6J51OFen{(HH8-jB}h|4!N0|5|2g zp1DBlt;o{I4;GwH?mOOQnQ>#$qU@F3Z@w&@vSr1C-lPeBt+yi>6ix+g-x2o6k4Lsj zlrQ`GWBicRqpF z_gQ*gG6+2LvHShrTECvMC%f(K9)8+iTeMtFWo1>d`<4Zo2fjs5H+vnmz%u>*ld|lz z{qFp>l_g21Za?4g>cq{tHv^xE&$Fs~uu_)I_Vc{6PjVLDxa7#9*)vCXir|irjq|z! zrcQsdZcoILjmO@9J*UYoursqzWKM97UTvCqXXV_Tvt6W5A84~Yulk}&g0DVn+TSxF zc6$%#`UbuJlmC!iYDuZHN^)VEt8tRR-L7suZ~Og?albFes?Ljf`s{wT<G7bUvGZFVJ>QXa?!osTDm&`G?A$rY^6}c%8HfITN%7p%wy|iF zx!i>Fo0l7WuDy43JA;e)aklSQ7;moUywSS-#f`4FrC)j199ps_u>TD2C*P|+&!45X zo;u`gdA-nSPoN z`!!qd-tX-H*I&N&cg@cdmFpham%c2tTzpSw-p|wB`#w(kE<3*?b;pm|^0(FRKPE~k zoZItl(Wy}VUuAA%VPAR@m|w-D%+s!XAG?`dME^m^92;)g z4G)$*z4UGRTD@682TUyu&qv&yb!Ye79AiDlzYPbptY4<@&$}69C|dtDeXX{s&-LR! z&vYxyIks-bUY<2|twP@4LLZzgYB+h|>4oL>pJn?#?>rp+@8qwybF&{bwuK$YQm;v4 zG?1>lR+q(C3a6;+( zeE*mb;cr(T>DS#pzHZO2m2n7%M{_E`S@fe^Dh zr*BVIocgxrVCr_E zy32<0%xPCPIL+2k2;B4S?&DP=sxkh@m$H2Q@~^)9a?M}wx>~;_=1-2U|9^A&tb*@< zf4yA)|D}o8?<0PvSCs!c)BIiL$C+~lUzeBj&Hr~z_r2ZU1GD!RK=WT5R_Q$^nBrw6wU+7tLtn`V!7t@Rg;JQV|n?r2|6=&@5l;GXq>$E2~VfW#1*ra-r+Omd3T$8!n4NIlt;YZ zwq|mdaqN(|*kQ&k=D*|cxs%)PZPHh?Qkd;H;ik8fuGH*_ezP@-wLGrAKO4qa_E)Yu zG3UzLSczKk|6Kg8SG;+qYFZxTdZ+c5IVJ9eYxnH+W?T&(VOz?6N=$je-@f;K&9dvO zrpGROyML+w`|9=@#$D4Hv>TF^MlW-VR%DvHBh>ZOC%q5z9ab;+y)`S+O{|6Si^dYJ zuk*fE&UaB-bGUWS6j5bYl@JB@_$vN~t2L(Txg1!b^QHR5m9wIEKmRYiVIMW;k(i4& zVrBA7crnMR z{FVvX$FpBeev^D*j@x_{-)+$;dHh{38CVsWUU)m*isRoT#CB!XbMKt)$=2T(-Z2EI zu2d7PIX#j8LCw!Y=1zy&eoRm(QFYVd65|Tc&^qH_JZZm|h>O#Nb1OB~-Y%Jw6{gwe zrK-gHp{?pW6SL(})v%1aU-CO0bQ?V`2A;k=b#dC99hp-vI2Z~3h+8VUz}vldg#yFu zb!Rfdy!X8ET3_C@bl1tUiynI&Wwtz-{lqG=E%Kl5+ao^{bk?cGPP+5OaB+FyhK$7? z7cX2=6AQ86e|ku%hC{hTeV1P6&To@)wl3Odlc%7^6s6J2aGx(YieVPRRB_2P57xKS zeaoJ2dU#$aA%rtD?O|e@DOdcieJPRsTsHy~n39VNyE=bLCfb!OiI^3>>{06{u`%5X@;BCWC>Qm-r*7(i=6CK#2kwG{_UJ4uvj&Bx$Ir7nwAS+-MBu#6HdJ_ zV?yvG>m0p3JYRTkr36N33m2vaEEQOupcEJ)s>tZ`uiA(CaM8g^#}|x&eFdRbXIgHG z@h?ky-Nh<5r@P%T!v3d%78<(!Ln3p@(;b>HutydFRU{?e#RlT-EzvT zJ!j_c`=;`AZb7i{;x+dz)2H0|vh@CsJuh#vI!&@Vn=M}S=4Ly$?(#;pMb5`;yz36w zRMc@;ewwj({plmiJ2@i^Hebv1v)krXZ}#W=F}L{0>8kn6^1J69J7jLYYny@Z{O8dt zI2C7ncigo}^3**2BRb5}8>%gyWz15aG=0+_*FQ6lhB_^2P3PUQHRoB@2mU25&snOP zYc9xCoKdvCDdU*$o|HYZXYb`Zc4-ub-}8FaWaJ^&7#q`jFR%QI`CGBT^()UWPWW#x zQo8QBNz|pdo9$ueju?Jf_gieQXzN?;e?5=ynBG+8ylB9AU2TzVUg-w~&T_XcdM`5P z|Bzm{^-{(sfrTs#mqZ_aeb2&sDtF=X2CGfM*Em*KF1h&9Zffk|Nna1$f2}@u@s8MS zoB!4SeO@!G*ZbVgwQHhJ#?|Yx7foVOTDjtSF3-W|4Kvl<`2W1LH}zPSd^+Nia>hrF zg(+)(Yo4vmzLVfsbm^Ib&ZQGgwXe-*ygTJv&ADTNX*I`}Inh1m{|4{c|GfVAXZxLP zSs#kmwKl8PC@oyg7L&rLaV}2o*UvSFY9^++ZoXcgQ4;+sXpTz3!ul94n@N+qek8OV zVV#&DbE*2ll)}=N0=I5;|N1U=LC=1xTiwSSdE&Y}wRJu*3;M0zUgqc9cUMaA)!oNZ zKO^@?>v)_!x@XyL62nD5^6XwsD9=>}P2QQAan_g9A2{=-qTiK#k z-J_~g^NpSFt(E$@wr<~33r{Tnb-&HtBV3I8ZhY^RO@iy=?=48)y^^KZMw`bgTl-Vg zlq-)#j%N$Xs%q`JaC(ta(35g?pF3KY-f>MV-caLX%%^+4>28Fy)AgVN`CXBJZnk>+ zpZ*rfV1MXO=!|0~j{RNpM4st(iOX}IyBDrHIg`^>LV2Yh$IhNd4UJ{Wd#}aq{I=t) z$0{A2;19b0rsfL!8O_!!+PT;zuYfhMu#chY4dd#VQ(mlh&#&M=!0I+Z_r>m(uDjwh zM4Ki*Rp+ZvacEpSf&J>%BL;KRUfQ{4EL%DG^6lhj){htuRlR&M!)@aV<>a|uZrRW6 zlRqB4e(96pfxZ%Vk>Y(fKHidhm!>l{W6P!Iw=U1$7A~+&qv>NIr^6C?=2=I>HS-(J zvb|$aHjv$L&yeHl zUn;R3(K}vvPu)Bu_R$$uaj^M;7@Vie9v@(Di4=G>iXN;u)SOeR-J2(IL6i z!R4Oa$8Y;`$cHYz?FuwBF{d2#18|7q4jF`~{lmrde*zt7xdil$P* znv=~Q`K3jQrk_j@+Um2;rXYz zX7Ab9Y1=dmVlwN^S%WGTCB#SbwS9;;VBfGUA)>dBi7}?rYhlpFX-cU|4;g;^x)91E>|brsO^CsZk<~N>VGyo&E?*bYNoNFyl|o5oommw zCw1@HuU(uV#GEU+ak-k*2BwH!y%}qEug;vct?EYVrBh#3;y=y1CDJ;J^O@4VGjd%j zlQP6ko%&UGvFyV1pOshRBm^c;6?*Qia(m6JS?~YO+iJRIO9-Q#Uf(ps1DdAuG=%0w zdfzJbo^qw;(WVr^HWQ{xvf1DGa;j4<`s&(k-mvEr*XGv1nTKy#C#+sD!*LRuD9>5r zd|9u)+=F62FL*7PvOfCuN57BPuBo1OH9WSs;C0f4P@id!8M{|aTJMy1VzY~O9%tix zLks4~kC?wzF0u-hDPa0Fx%nJ_l5*DXYizq&s&lsa+ZR8ZnSVd$*Y@3?Dh_K)W?F>$ z*t6Sx+MB+=G&}cEqkEt1k5?O=@7qLWL~K0}e12Z#vzLz}HqUtWCD{7%^Oso@+x0Fl zTfQ{!E%);!MLB0m>btL9{&DR2zM|s2d!KD+QZ?NzJw3e*iel#x0`RtsZC;G1~Xcx8L!WZB#KgIQU z%Im2vGD>@P)<$f;u;~To+N-CYy^*+cfmylwq5J-tlA4=-e{C9{98k9YfA*`^q@VX= z9*Bl-YMfkocBbH^Ior>~PAOkt@W=3X&Sr |yPFu5zf6TCulk*PGqncRc+!Gn<3u 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 Mp00i_>zopr0J5>OQvd(} literal 11078 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 M)78&qol`;+09`=)I{*Lx diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-camera.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-camera.qdoc index 6f546839ab7..77bc928da80 100644 --- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-camera.qdoc +++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-camera.qdoc @@ -40,10 +40,10 @@ \image studio-qtquick-3d-components.png "Qt Quick 3D components in Library" - You can add a camera to your scene by dragging-and-dropping one from + Add a camera by dragging-and-dropping one of the camera components from \l Library > \uicontrol Components > \uicontrol {Qt Quick 3D} > \uicontrol {Qt Quick 3D} to \l {3D Editor} or to a 3D view in \l Navigator. - If the cameras are not displayed in \uicontrol Library, you should add the + If the cameras are not displayed in \uicontrol Library, add the \uicontrol QtQuick3D module to your project, as described in \l {Adding and Removing Modules}. @@ -51,20 +51,21 @@ projection: \list - \li \l{PerspectiveCamera}{Camera Perspective} - is the standard camera - type, which uses field of view and near and far clip planes to - specify the projection. - \li \l{OrthographicCamera}{Camera Orthographic} - renders all contents - with no perspective. It is ideal for rendering 2D elements, because + \li \l{PerspectiveCamera}{Camera Perspective} is the standard camera + type, which gives a realistic projection of the scene since distant + objects are perceived as smaller. It uses field of view and near and + far clip planes to specify the projection. + \li \l{OrthographicCamera}{Camera Orthographic} renders all contents + with no perspective. It is ideal for rendering 2D elements because your images are guaranteed to be the right size on the screen, and you can use the z position of components to bring them closer to or take them farther from the camera (\e z-sorting) with no foreshortening artifacts. - \li \l{FrustumCamera}{Camera Frustum} - enables finer grain control of + \li \l{FrustumCamera}{Camera Frustum} enables finer grain control of how the frustum is defined, by setting the number of degrees between the top and bottom or left and right edges of the camera frustum. This is useful when creating asymmetrical frustums. - \li \l{CustomCamera}{Camera Custom} - provides full control over how + \li \l{CustomCamera}{Camera Custom} provides full control over how the projection matrix is created. \endlist @@ -84,6 +85,10 @@ \section1 Setting Camera Field of View + \note If you select \uicontrol {Qt 5} as the \uicontrol {Target Qt Version} + when \l {Creating Projects}{creating your project}, the camera properties + will be slightly different. + The camera frustum can be obtained by taking a frustum (that is, a truncation with parallel planes) of the cone of vision that a camera or eye would have to the rectangular viewports typically used in computer graphics. @@ -108,12 +113,26 @@ This value is the number of degrees between the top and bottom edges of the camera frustum. - The horizontal FOV determines the number of degrees between the left and - right edges of the camera frustum. It is automatically calculated based on - the aspect ratio of the scene when the FOV orientation is set to vertical. - You can set the orientation to horizontal to translate FOV values from - graphics tools such as Maya and Blender, which use horizontal FOV by - default. + The \uicontrol {FOV orientation} property specifies either a + \uicontrol Vertical (the default setting) or a \uicontrol Horizontal + orientation for the field of view. The horizontal FOV determines the number + of degrees between the left and right edges of the camera frustum. It is + automatically calculated based on the aspect ratio of the scene when the + FOV orientation is set to vertical. You can set the orientation to horizontal + to translate FOV values from graphics tools such as Maya and Blender, which + use horizontal FOV by default. + + The \uicontrol {Horizontal magnification} and \uicontrol {Vertical magnification} + properties determine the horizontal and vertical magnification of the camera + frustum. + \note The \uicontrol {Horizontal magnification} and + \uicontrol {Vertical magnification} properties are not available in Qt 5. + + The \uicontrol {Frustum culling enabled} property determines whether the + objects outside the camera frustum will be culled, which means they will not + be passed to the renderer. + \note The \uicontrol {Frustum culling enabled} property is not available in + Qt 5. The default values are intended to cause anything within the view of the camera to be rendered. Aside from special clipping effects, you From b2e4930d879a04593930b82c7997d8359f064070 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Mon, 27 Sep 2021 22:36:28 +0200 Subject: [PATCH 04/15] McuSupport: Small virtual/final cleanup Change-Id: I5a187a6b573326685fb471dc7e31e9731760602d Reviewed-by: hjk --- src/plugins/mcusupport/mcusupportversiondetection.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/plugins/mcusupport/mcusupportversiondetection.h b/src/plugins/mcusupport/mcusupportversiondetection.h index b32406f013c..5aa2c799b0e 100644 --- a/src/plugins/mcusupport/mcusupportversiondetection.h +++ b/src/plugins/mcusupport/mcusupportversiondetection.h @@ -23,8 +23,7 @@ ** ****************************************************************************/ -#ifndef MCUSUPPORTVERSIONDETECTION_H -#define MCUSUPPORTVERSIONDETECTION_H +#pragma once #include @@ -47,7 +46,7 @@ public: McuPackageExecutableVersionDetector(const QString &detectionPath, const QStringList &detectionArgs, const QString &detectionRegExp); - virtual QString parseVersion(const QString &packagePath) const; + QString parseVersion(const QString &packagePath) const final; private: const QString m_detectionPath; const QStringList m_detectionArgs; @@ -62,7 +61,7 @@ public: const QString &elementName, const QString &versionAttribute, const QString &versionRegExp); - QString parseVersion(const QString &packagePath) const; + QString parseVersion(const QString &packagePath) const final; private: const QString m_filePattern; const QString m_versionElement; @@ -75,7 +74,7 @@ class McuPackageDirectoryVersionDetector : public McuPackageVersionDetector { public: McuPackageDirectoryVersionDetector(const QString &filePattern, const QString &versionRegExp, const bool isFile); - QString parseVersion(const QString &packagePath) const; + QString parseVersion(const QString &packagePath) const final; private: const QString m_filePattern; const QString m_versionRegExp; @@ -87,12 +86,10 @@ class McuPackagePathVersionDetector : public McuPackageVersionDetector { public: McuPackagePathVersionDetector(const QString &versionRegExp); - QString parseVersion(const QString &packagePath) const; + QString parseVersion(const QString &packagePath) const final; private: const QString m_versionRegExp; }; } // Internal } // McuSupport - -#endif // MCUSUPPORTVERSIONDETECTION_H From b798fce4654739b59b2ca11e5d30123bfb2ca209 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 29 Sep 2021 11:42:07 +0200 Subject: [PATCH 05/15] Don't call TaskHub::addTask() directly from non-main thread Fixes: QTCREATORBUG-26335 Change-Id: I23323edd32fa1f8d5d49943e3b4c37a305e53dd2 Reviewed-by: Qt CI Bot Reviewed-by: Eike Ziller --- src/plugins/projectexplorer/taskhub.cpp | 1 + src/plugins/qtsupport/profilereader.cpp | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/plugins/projectexplorer/taskhub.cpp b/src/plugins/projectexplorer/taskhub.cpp index 856959ed0a2..1912264bb5f 100644 --- a/src/plugins/projectexplorer/taskhub.cpp +++ b/src/plugins/projectexplorer/taskhub.cpp @@ -155,6 +155,7 @@ void TaskHub::addTask(Task task) QTC_ASSERT(!task.description().isEmpty(), return); QTC_ASSERT(!task.isNull(), return); QTC_ASSERT(task.m_mark.isNull(), return); + QTC_ASSERT(QThread::currentThread() == qApp->thread(), return); if (task.file.isEmpty() || task.line <= 0) task.line = -1; diff --git a/src/plugins/qtsupport/profilereader.cpp b/src/plugins/qtsupport/profilereader.cpp index cdc77c2d9b8..905ad413eaf 100644 --- a/src/plugins/qtsupport/profilereader.cpp +++ b/src/plugins/qtsupport/profilereader.cpp @@ -58,15 +58,22 @@ ProMessageHandler::~ProMessageHandler() Core::MessageManager::writeFlashing(m_messages); } - +static void addTask(Task::TaskType type, + const QString &description, + const Utils::FilePath &file = {}, + int line = -1) +{ + QMetaObject::invokeMethod(TaskHub::instance(), [=]() { + TaskHub::addTask(BuildSystemTask(type, description, file, line)); + }); +} void ProMessageHandler::message(int type, const QString &msg, const QString &fileName, int lineNo) { if ((type & CategoryMask) == ErrorMessage && ((type & SourceMask) == SourceParser || m_verbose)) { // parse error in qmake files if (m_exact) { - TaskHub::addTask( - BuildSystemTask(Task::Error, msg, Utils::FilePath::fromString(fileName), lineNo)); + addTask(Task::Error, msg, Utils::FilePath::fromString(fileName), lineNo); } else { appendMessage(format(fileName, lineNo, msg)); } @@ -79,9 +86,9 @@ void ProMessageHandler::fileMessage(int type, const QString &msg) if (!m_verbose) return; if (m_exact && type == QMakeHandler::ErrorMessage) - TaskHub::addTask(BuildSystemTask(Task::Error, msg)); + addTask(Task::Error, msg); else if (m_exact && type == QMakeHandler::WarningMessage) - TaskHub::addTask(BuildSystemTask(Task::Warning, msg)); + addTask(Task::Warning, msg); else appendMessage(msg); } From 324105febeb8108a08797c716368b5c2b1e5a588 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 29 Sep 2021 12:22:58 +0200 Subject: [PATCH 06/15] ClangCodeModel: Fix a test The missing header file threw off parsing for some of the code below. Change-Id: I29f7895b4d88856cc39fd8e33742a37734953b9e Reviewed-by: David Schulz --- src/plugins/clangcodemodel/test/clangdtests.cpp | 5 ----- src/plugins/clangcodemodel/test/data/clangtestdata.qrc | 1 + .../test/data/highlighting/highlightingmarks.h | 0 3 files changed, 1 insertion(+), 5 deletions(-) create mode 100644 src/plugins/clangcodemodel/test/data/highlighting/highlightingmarks.h diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index 4622db96a69..c71bd2d3644 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -1298,11 +1298,6 @@ void ClangdTestHighlighting::test() "check if and how we want to support this", Abort); QEXPECT_FAIL("old-style signal with complex parameter (signal parameter part 3)", "check if and how we want to support this", Abort); - QEXPECT_FAIL("alias template instantiation (type)", "FIXME: clangd doesn't report this", Abort); - QEXPECT_FAIL("alias template instantiation (opening angle bracket)", - "FIXME: This construct does not appear in the AST", Abort); - QEXPECT_FAIL("alias template instantiation (closing angle bracket)", - "FIXME: This construct does not appear in the AST", Abort); QEXPECT_FAIL("function template specialization (opening angle bracket 1)", "specialization appears as a normal function in the AST", Abort); QEXPECT_FAIL("function template specialization (closing angle bracket 1)", diff --git a/src/plugins/clangcodemodel/test/data/clangtestdata.qrc b/src/plugins/clangcodemodel/test/data/clangtestdata.qrc index b006e3832ff..9dcc3fbae15 100644 --- a/src/plugins/clangcodemodel/test/data/clangtestdata.qrc +++ b/src/plugins/clangcodemodel/test/data/clangtestdata.qrc @@ -54,5 +54,6 @@ completion/preprocessorKeywordsCompletion2.cpp completion/preprocessorKeywordsCompletion3.cpp completion/privateFuncDefCompletion.cpp + highlighting/highlightingmarks.h diff --git a/src/plugins/clangcodemodel/test/data/highlighting/highlightingmarks.h b/src/plugins/clangcodemodel/test/data/highlighting/highlightingmarks.h new file mode 100644 index 00000000000..e69de29bb2d From 4bbab394671f106bc799703ab17cc70fd322f5d9 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 27 Sep 2021 18:06:38 +0200 Subject: [PATCH 07/15] Use FilePath in several file wizards Change-Id: I9bab9d602096a3872f73fb16d901b8aedcd82516 Reviewed-by: Christian Stenger --- src/libs/utils/filewizardpage.cpp | 12 +++++- src/libs/utils/filewizardpage.h | 8 +++- .../coreplugin/basefilewizardfactory.cpp | 28 ++++++-------- .../coreplugin/basefilewizardfactory.h | 27 +++++--------- src/plugins/designer/cpp/formclasswizard.cpp | 14 ++++--- .../designer/cpp/formclasswizarddialog.cpp | 12 ++++-- .../designer/cpp/formclasswizarddialog.h | 4 +- .../designer/cpp/formclasswizardpage.cpp | 13 +++---- .../designer/cpp/formclasswizardpage.h | 6 ++- .../designer/cpp/formclasswizardparameters.h | 5 ++- src/plugins/designer/cpp/newclasswidget.cpp | 30 ++++++++------- src/plugins/designer/cpp/newclasswidget.h | 8 ++-- .../filesselectionwizardpage.cpp | 3 +- .../genericprojectwizard.cpp | 37 ++++++++++--------- .../genericprojectwizard.h | 4 +- .../baseprojectwizarddialog.cpp | 8 ++-- .../projectexplorer/baseprojectwizarddialog.h | 2 +- .../customwizard/customwizard.cpp | 6 +-- .../customwizard/customwizard.h | 2 +- .../customwizard/customwizardpage.cpp | 4 +- .../customwizard/customwizardpage.h | 2 +- .../jsonwizard/jsonfilepage.cpp | 6 +-- .../projectexplorer/simpleprojectwizard.cpp | 14 +++---- .../wizards/qtprojectparameters.cpp | 10 ++--- .../wizards/qtprojectparameters.h | 9 +++-- .../wizards/subdirsprojectwizard.cpp | 14 ++++--- .../wizards/subdirsprojectwizarddialog.cpp | 2 +- 27 files changed, 153 insertions(+), 137 deletions(-) diff --git a/src/libs/utils/filewizardpage.cpp b/src/libs/utils/filewizardpage.cpp index 130c40395e8..6b5bdf28989 100644 --- a/src/libs/utils/filewizardpage.cpp +++ b/src/libs/utils/filewizardpage.cpp @@ -80,6 +80,16 @@ QString FileWizardPage::fileName() const return d->m_ui.nameLineEdit->text(); } +FilePath FileWizardPage::filePath() const +{ + return d->m_ui.pathChooser->filePath(); +} + +void FileWizardPage::setFilePath(const FilePath &filePath) +{ + d->m_ui.pathChooser->setFilePath(filePath); +} + QString FileWizardPage::path() const { return d->m_ui.pathChooser->filePath().toString(); @@ -87,7 +97,7 @@ QString FileWizardPage::path() const void FileWizardPage::setPath(const QString &path) { - d->m_ui.pathChooser->setPath(path); + d->m_ui.pathChooser->setFilePath(FilePath::fromString(path)); } void FileWizardPage::setFileName(const QString &name) diff --git a/src/libs/utils/filewizardpage.h b/src/libs/utils/filewizardpage.h index 26ab0ee9443..b763afa2f85 100644 --- a/src/libs/utils/filewizardpage.h +++ b/src/libs/utils/filewizardpage.h @@ -27,6 +27,7 @@ #include "utils_global.h" +#include "filepath.h" #include "wizardpage.h" namespace Utils { @@ -44,7 +45,9 @@ public: ~FileWizardPage() override; QString fileName() const; - QString path() const; + QString path() const; // Deprecated: Use filePath() + + Utils::FilePath filePath() const; bool isComplete() const override; @@ -64,8 +67,9 @@ signals: void pathChanged(); public slots: - void setPath(const QString &path); + void setPath(const QString &path); // Deprecated: Use setFilePath void setFileName(const QString &name); + void setFilePath(const Utils::FilePath &filePath); private: void slotValidChanged(); diff --git a/src/plugins/coreplugin/basefilewizardfactory.cpp b/src/plugins/coreplugin/basefilewizardfactory.cpp index 23c93160443..e29054accfb 100644 --- a/src/plugins/coreplugin/basefilewizardfactory.cpp +++ b/src/plugins/coreplugin/basefilewizardfactory.cpp @@ -86,11 +86,11 @@ Utils::Wizard *BaseFileWizardFactory::runWizardImpl(const FilePath &path, QWidge if (flags().testFlag(ForceCapitalLetterForFileName)) dialogParameterFlags |= WizardDialogParameters::ForceCapitalLetterForFileName; - Utils::Wizard *wizard = create(parent, WizardDialogParameters(path.toString(), - platform, - requiredFeatures(), - dialogParameterFlags, - extraValues)); + Wizard *wizard = create(parent, WizardDialogParameters(path, + platform, + requiredFeatures(), + dialogParameterFlags, + extraValues)); QTC_CHECK(wizard); return wizard; } @@ -287,21 +287,17 @@ BaseFileWizardFactory::OverwriteResult BaseFileWizardFactory::promptOverwrite(Ge \a baseName already has one. */ -QString BaseFileWizardFactory::buildFileName(const QString &path, - const QString &baseName, - const QString &extension) +FilePath BaseFileWizardFactory::buildFileName(const FilePath &path, + const QString &baseName, + const QString &extension) { - QString rc = path; - const QChar slash = QLatin1Char('/'); - if (!rc.isEmpty() && !rc.endsWith(slash)) - rc += slash; - rc += baseName; + FilePath rc = path.pathAppended(baseName); // Add extension unless user specified something else - const QChar dot = QLatin1Char('.'); + const QChar dot = '.'; if (!extension.isEmpty() && !baseName.contains(dot)) { if (!extension.startsWith(dot)) - rc += dot; - rc += extension; + rc = rc.stringAppended(dot); + rc = rc.stringAppended(extension); } if (debugWizard) qDebug() << Q_FUNC_INFO << rc; diff --git a/src/plugins/coreplugin/basefilewizardfactory.h b/src/plugins/coreplugin/basefilewizardfactory.h index 6b7c6488954..14eac78d0db 100644 --- a/src/plugins/coreplugin/basefilewizardfactory.h +++ b/src/plugins/coreplugin/basefilewizardfactory.h @@ -30,6 +30,8 @@ #include +#include + #include #include @@ -54,7 +56,7 @@ public: }; Q_DECLARE_FLAGS(DialogParameterFlags, DialogParameterEnum) - explicit WizardDialogParameters(const QString &defaultPath, Utils::Id platform, + explicit WizardDialogParameters(const Utils::FilePath &defaultPath, Utils::Id platform, const QSet &requiredFeatures, DialogParameterFlags flags, const QVariantMap &extraValues) : m_defaultPath(defaultPath), @@ -64,23 +66,14 @@ public: m_extraValues(extraValues) {} - QString defaultPath() const - { return m_defaultPath; } - - Utils::Id selectedPlatform() const - { return m_selectedPlatform; } - - QSet requiredFeatures() const - { return m_requiredFeatures; } - - DialogParameterFlags flags() const - { return m_parameterFlags; } - - QVariantMap extraValues() const - { return m_extraValues; } + Utils::FilePath defaultPath() const { return m_defaultPath; } + Utils::Id selectedPlatform() const { return m_selectedPlatform; } + QSet requiredFeatures() const { return m_requiredFeatures; } + DialogParameterFlags flags() const { return m_parameterFlags; } + QVariantMap extraValues() const { return m_extraValues; } private: - QString m_defaultPath; + Utils::FilePath m_defaultPath; Utils::Id m_selectedPlatform; QSet m_requiredFeatures; DialogParameterFlags m_parameterFlags; @@ -94,7 +87,7 @@ class CORE_EXPORT BaseFileWizardFactory : public IWizardFactory friend class BaseFileWizard; public: - static QString buildFileName(const QString &path, const QString &baseName, const QString &extension); + static Utils::FilePath buildFileName(const Utils::FilePath &path, const QString &baseName, const QString &extension); protected: virtual BaseFileWizard *create(QWidget *parent, const WizardDialogParameters ¶meters) const = 0; diff --git a/src/plugins/designer/cpp/formclasswizard.cpp b/src/plugins/designer/cpp/formclasswizard.cpp index feae7e33d55..143d812cb7c 100644 --- a/src/plugins/designer/cpp/formclasswizard.cpp +++ b/src/plugins/designer/cpp/formclasswizard.cpp @@ -32,6 +32,8 @@ #include +using namespace Utils; + namespace Designer { namespace Internal { @@ -58,7 +60,7 @@ QString FormClassWizard::formSuffix() const Core::BaseFileWizard *FormClassWizard::create(QWidget *parent, const Core::WizardDialogParameters ¶meters) const { auto wizardDialog = new FormClassWizardDialog(this, parent); - wizardDialog->setPath(parameters.defaultPath()); + wizardDialog->setFilePath(parameters.defaultPath()); return wizardDialog; } @@ -73,9 +75,9 @@ Core::GeneratedFiles FormClassWizard::generateFiles(const QWizard *w, QString *e } // header - const QString formFileName = buildFileName(params.path, params.uiFile, formSuffix()); - const QString headerFileName = buildFileName(params.path, params.headerFile, headerSuffix()); - const QString sourceFileName = buildFileName(params.path, params.sourceFile, sourceSuffix()); + const FilePath formFileName = buildFileName(params.path, params.uiFile, formSuffix()); + const FilePath headerFileName = buildFileName(params.path, params.headerFile, headerSuffix()); + const FilePath sourceFileName = buildFileName(params.path, params.sourceFile, sourceSuffix()); Core::GeneratedFile headerFile(headerFileName); headerFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute); @@ -102,5 +104,5 @@ Core::GeneratedFiles FormClassWizard::generateFiles(const QWizard *w, QString *e return Core::GeneratedFiles() << headerFile << sourceFile << uiFile; } -} -} +} // Internal +} // Designer diff --git a/src/plugins/designer/cpp/formclasswizarddialog.cpp b/src/plugins/designer/cpp/formclasswizarddialog.cpp index 0998cf4727f..64e2e5ed251 100644 --- a/src/plugins/designer/cpp/formclasswizarddialog.cpp +++ b/src/plugins/designer/cpp/formclasswizarddialog.cpp @@ -26,9 +26,13 @@ #include "formclasswizarddialog.h" #include "formclasswizardpage.h" #include "formclasswizardparameters.h" + #include #include #include +#include + +using namespace Utils; enum { FormPageId, ClassPageId }; @@ -52,14 +56,14 @@ FormClassWizardDialog::FormClassWizardDialog(const Core::BaseFileWizardFactory * addPage(p); } -QString FormClassWizardDialog::path() const +FilePath FormClassWizardDialog::filePath() const { - return m_classPage->path(); + return m_classPage->filePath(); } -void FormClassWizardDialog::setPath(const QString &p) +void FormClassWizardDialog::setFilePath(const FilePath &p) { - m_classPage->setPath(p); + m_classPage->setFilePath(p); } void FormClassWizardDialog::initializePage(int id) diff --git a/src/plugins/designer/cpp/formclasswizarddialog.h b/src/plugins/designer/cpp/formclasswizarddialog.h index cc5f83b8188..2f728eaa046 100644 --- a/src/plugins/designer/cpp/formclasswizarddialog.h +++ b/src/plugins/designer/cpp/formclasswizarddialog.h @@ -45,8 +45,8 @@ public: explicit FormClassWizardDialog(const Core::BaseFileWizardFactory *factory, QWidget *parent = nullptr); - QString path() const; - void setPath(const QString &); + Utils::FilePath filePath() const; + void setFilePath(const Utils::FilePath &); Designer::FormClassWizardParameters parameters() const; diff --git a/src/plugins/designer/cpp/formclasswizardpage.cpp b/src/plugins/designer/cpp/formclasswizardpage.cpp index 4a3a1faaace..6f7e244eb59 100644 --- a/src/plugins/designer/cpp/formclasswizardpage.cpp +++ b/src/plugins/designer/cpp/formclasswizardpage.cpp @@ -32,9 +32,8 @@ #include #include #include -# -#include +#include #include namespace Designer { @@ -88,20 +87,20 @@ void FormClassWizardPage::setClassName(const QString &suggestedClassName) slotValidChanged(); } -QString FormClassWizardPage::path() const +Utils::FilePath FormClassWizardPage::filePath() const { - return m_ui->newClassWidget->path(); + return m_ui->newClassWidget->filePath(); } -void FormClassWizardPage::setPath(const QString &p) +void FormClassWizardPage::setFilePath(const Utils::FilePath &p) { - m_ui->newClassWidget->setPath(p); + m_ui->newClassWidget->setFilePath(p); } void FormClassWizardPage::getParameters(FormClassWizardParameters *p) const { p->className = m_ui->newClassWidget->className(); - p->path = path(); + p->path = filePath(); p->sourceFile = m_ui->newClassWidget->sourceFileName(); p->headerFile = m_ui->newClassWidget->headerFileName(); p->uiFile = m_ui->newClassWidget-> formFileName(); diff --git a/src/plugins/designer/cpp/formclasswizardpage.h b/src/plugins/designer/cpp/formclasswizardpage.h index 8b337085957..60e848433e1 100644 --- a/src/plugins/designer/cpp/formclasswizardpage.h +++ b/src/plugins/designer/cpp/formclasswizardpage.h @@ -27,6 +27,8 @@ #include +namespace Utils { class FilePath; } + namespace Designer { class FormClassWizardParameters; @@ -49,8 +51,8 @@ public: bool validatePage() override; void setClassName(const QString &suggestedClassName); - void setPath(const QString &); - QString path() const; + void setFilePath(const Utils::FilePath &); + Utils::FilePath filePath() const; // Fill out applicable parameters void getParameters(FormClassWizardParameters *) const; diff --git a/src/plugins/designer/cpp/formclasswizardparameters.h b/src/plugins/designer/cpp/formclasswizardparameters.h index 1396c9052ca..c16d2bff785 100644 --- a/src/plugins/designer/cpp/formclasswizardparameters.h +++ b/src/plugins/designer/cpp/formclasswizardparameters.h @@ -25,7 +25,8 @@ #pragma once -#include +#include + #include namespace Designer { @@ -39,7 +40,7 @@ class FormClassWizardParameters public: QString uiTemplate; QString className; - QString path; + Utils::FilePath path; QString sourceFile; QString headerFile; QString uiFile; diff --git a/src/plugins/designer/cpp/newclasswidget.cpp b/src/plugins/designer/cpp/newclasswidget.cpp index 2f42e743226..ab2475f12b1 100644 --- a/src/plugins/designer/cpp/newclasswidget.cpp +++ b/src/plugins/designer/cpp/newclasswidget.cpp @@ -29,6 +29,8 @@ #include #include +using namespace Utils; + enum { debugNewClassWidget = 0 }; /*! \class Utils::NewClassWidget @@ -171,14 +173,14 @@ QString NewClassWidget::formFileName() const return d->m_ui.formFileLineEdit->text(); } -QString NewClassWidget::path() const +FilePath NewClassWidget::filePath() const { - return d->m_ui.pathChooser->filePath().toString(); + return d->m_ui.pathChooser->filePath(); } -void NewClassWidget::setPath(const QString &path) +void NewClassWidget::setFilePath(const FilePath &path) { - d->m_ui.pathChooser->setPath(path); + d->m_ui.pathChooser->setFilePath(path); } QString NewClassWidget::sourceExtension() const @@ -305,21 +307,21 @@ static QString ensureSuffix(QString f, const QString &extension) } // If a non-empty name was passed, expand to directory and suffix -static QString expandFileName(const QDir &dir, const QString &name, const QString &extension) +static FilePath expandFileName(const FilePath &dir, const QString &name, const QString &extension) { if (name.isEmpty()) - return QString(); - return dir.absoluteFilePath(ensureSuffix(name, extension)); + return {}; + return dir / ensureSuffix(name, extension); } -QStringList NewClassWidget::files() const +Utils::FilePaths NewClassWidget::files() const { - QStringList rc; - const QDir dir = QDir(path()); - rc.push_back(expandFileName(dir, headerFileName(), headerExtension())); - rc.push_back(expandFileName(dir, sourceFileName(), sourceExtension())); - rc.push_back(expandFileName(dir, formFileName(), formExtension())); - return rc; + const FilePath dir = filePath(); + return { + expandFileName(dir, headerFileName(), headerExtension()), + expandFileName(dir, sourceFileName(), sourceExtension()), + expandFileName(dir, formFileName(), formExtension()), + }; } } // namespace Internal diff --git a/src/plugins/designer/cpp/newclasswidget.h b/src/plugins/designer/cpp/newclasswidget.h index 69ff987063e..4877bcaa1aa 100644 --- a/src/plugins/designer/cpp/newclasswidget.h +++ b/src/plugins/designer/cpp/newclasswidget.h @@ -25,6 +25,8 @@ #pragma once +#include + #include namespace Designer { @@ -52,14 +54,14 @@ public: QString sourceFileName() const; QString headerFileName() const; QString formFileName() const; - QString path() const; + Utils::FilePath filePath() const; QString sourceExtension() const; QString headerExtension() const; QString formExtension() const; bool isValid(QString *error = nullptr) const; - QStringList files() const; + Utils::FilePaths files() const; signals: void validChanged(); @@ -72,7 +74,7 @@ public slots: * valid class name. */ void setClassName(const QString &suggestedName); - void setPath(const QString &path); + void setFilePath(const Utils::FilePath &filePath); void setSourceExtension(const QString &e); void setHeaderExtension(const QString &e); void setLowerCaseFiles(bool v); diff --git a/src/plugins/genericprojectmanager/filesselectionwizardpage.cpp b/src/plugins/genericprojectmanager/filesselectionwizardpage.cpp index d4c802785c9..99faae34f25 100644 --- a/src/plugins/genericprojectmanager/filesselectionwizardpage.cpp +++ b/src/plugins/genericprojectmanager/filesselectionwizardpage.cpp @@ -59,8 +59,7 @@ FilesSelectionWizardPage::FilesSelectionWizardPage(GenericProjectWizardDialog *g void FilesSelectionWizardPage::initializePage() { - m_filesWidget->resetModel(Utils::FilePath::fromString(m_genericProjectWizardDialog->path()), - Utils::FilePaths()); + m_filesWidget->resetModel(m_genericProjectWizardDialog->filePath(), Utils::FilePaths()); } void FilesSelectionWizardPage::cleanupPage() diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.cpp b/src/plugins/genericprojectmanager/genericprojectwizard.cpp index 6fff20d13ec..af9b4343d4b 100644 --- a/src/plugins/genericprojectmanager/genericprojectwizard.cpp +++ b/src/plugins/genericprojectmanager/genericprojectwizard.cpp @@ -46,13 +46,14 @@ #include #include +using namespace Utils; + namespace GenericProjectManager { namespace Internal { -static const char *const ConfigFileTemplate = +const char ConfigFileTemplate[] = "// Add predefined macros for your project here. For example:\n" - "// #define THE_ANSWER 42\n" - ; + "// #define THE_ANSWER 42\n"; ////////////////////////////////////////////////////////////////////////////// // @@ -79,24 +80,24 @@ GenericProjectWizardDialog::GenericProjectWizardDialog(const Core::BaseFileWizar addPage(m_secondPage); } -QString GenericProjectWizardDialog::path() const +FilePath GenericProjectWizardDialog::filePath() const { - return m_firstPage->path(); + return m_firstPage->filePath(); } -Utils::FilePaths GenericProjectWizardDialog::selectedPaths() const +FilePaths GenericProjectWizardDialog::selectedPaths() const { return m_secondPage->selectedPaths(); } -Utils::FilePaths GenericProjectWizardDialog::selectedFiles() const +FilePaths GenericProjectWizardDialog::selectedFiles() const { return m_secondPage->selectedFiles(); } -void GenericProjectWizardDialog::setPath(const QString &path) +void GenericProjectWizardDialog::setFilePath(const FilePath &path) { - m_firstPage->setPath(path); + m_firstPage->setFilePath(path); } QString GenericProjectWizardDialog::projectName() const @@ -129,7 +130,7 @@ Core::BaseFileWizard *GenericProjectWizard::create(QWidget *parent, { auto wizard = new GenericProjectWizardDialog(this, parent); - wizard->setPath(parameters.defaultPath()); + wizard->setFilePath(parameters.defaultPath()); foreach (QWizardPage *p, wizard->extensionPages()) wizard->addPage(p); @@ -143,15 +144,14 @@ Core::GeneratedFiles GenericProjectWizard::generateFiles(const QWizard *w, Q_UNUSED(errorMessage) auto wizard = qobject_cast(w); - const QString projectPath = wizard->path(); - const QDir dir(projectPath); + const FilePath projectPath = wizard->filePath(); const QString projectName = wizard->projectName(); - const QString creatorFileName = QFileInfo(dir, projectName + QLatin1String(".creator")).absoluteFilePath(); - const QString filesFileName = QFileInfo(dir, projectName + QLatin1String(".files")).absoluteFilePath(); - const QString includesFileName = QFileInfo(dir, projectName + QLatin1String(".includes")).absoluteFilePath(); - const QString configFileName = QFileInfo(dir, projectName + QLatin1String(".config")).absoluteFilePath(); - const QString cxxflagsFileName = QFileInfo(dir, projectName + QLatin1String(".cxxflags")).absoluteFilePath(); - const QString cflagsFileName = QFileInfo(dir, projectName + QLatin1String(".cflags")).absoluteFilePath(); + const FilePath creatorFileName = projectPath.pathAppended(projectName + ".creator"); + const FilePath filesFileName = projectPath.pathAppended(projectName + ".files"); + const FilePath includesFileName = projectPath.pathAppended(projectName + ".includes"); + const FilePath configFileName = projectPath.pathAppended(projectName + ".config"); + const FilePath cxxflagsFileName = projectPath.pathAppended(projectName + ".cxxflags"); + const FilePath cflagsFileName = projectPath.pathAppended(projectName + ".cflags"); const QStringList paths = Utils::transform(wizard->selectedPaths(), &Utils::FilePath::toString); Utils::MimeType headerTy = Utils::mimeTypeForName(QLatin1String("text/x-chdr")); @@ -159,6 +159,7 @@ Core::GeneratedFiles GenericProjectWizard::generateFiles(const QWizard *w, QStringList nameFilters = headerTy.globPatterns(); QStringList includePaths; + const QDir dir(projectPath.toString()); foreach (const QString &path, paths) { QFileInfo fileInfo(path); QDir thisDir(fileInfo.absoluteFilePath()); diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.h b/src/plugins/genericprojectmanager/genericprojectwizard.h index 97c2b3c91a8..67a0b136406 100644 --- a/src/plugins/genericprojectmanager/genericprojectwizard.h +++ b/src/plugins/genericprojectmanager/genericprojectwizard.h @@ -44,8 +44,8 @@ class GenericProjectWizardDialog : public Core::BaseFileWizard public: explicit GenericProjectWizardDialog(const Core::BaseFileWizardFactory *factory, QWidget *parent = nullptr); - QString path() const; - void setPath(const QString &path); + Utils::FilePath filePath() const; + void setFilePath(const Utils::FilePath &path); Utils::FilePaths selectedFiles() const; Utils::FilePaths selectedPaths() const; diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp index b173688623f..789366b9302 100644 --- a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp +++ b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp @@ -68,7 +68,7 @@ BaseProjectWizardDialog::BaseProjectWizardDialog(const Core::BaseFileWizardFacto Core::BaseFileWizard(factory, parameters.extraValues(), parent), d(std::make_unique(new Utils::ProjectIntroPage)) { - setFilePath(FilePath::fromString(parameters.defaultPath())); + setFilePath(parameters.defaultPath()); setSelectedPlatform(parameters.selectedPlatform()); setRequiredFeatures(parameters.requiredFeatures()); init(); @@ -81,7 +81,7 @@ BaseProjectWizardDialog::BaseProjectWizardDialog(const Core::BaseFileWizardFacto Core::BaseFileWizard(factory, parameters.extraValues(), parent), d(std::make_unique(introPage, introId)) { - setFilePath(FilePath::fromString(parameters.defaultPath())); + setFilePath(parameters.defaultPath()); setSelectedPlatform(parameters.selectedPlatform()); setRequiredFeatures(parameters.requiredFeatures()); init(); @@ -161,9 +161,9 @@ Utils::ProjectIntroPage *BaseProjectWizardDialog::introPage() const return d->introPage; } -QString BaseProjectWizardDialog::uniqueProjectName(const QString &path) +QString BaseProjectWizardDialog::uniqueProjectName(const FilePath &path) { - const QDir pathDir(path); + const QDir pathDir(path.toString()); //: File path suggestion for a new project. If you choose //: to translate it, make sure it is a valid path name without blanks //: and using only ascii chars. diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.h b/src/plugins/projectexplorer/baseprojectwizarddialog.h index 19306600114..995b4c7facf 100644 --- a/src/plugins/projectexplorer/baseprojectwizarddialog.h +++ b/src/plugins/projectexplorer/baseprojectwizarddialog.h @@ -61,7 +61,7 @@ public: Utils::FilePath filePath() const; // Generate a new project name (untitled) in path. - static QString uniqueProjectName(const QString &path); + static QString uniqueProjectName(const Utils::FilePath &path); void addExtensionPages(const QList &wizardPageList); void setIntroDescription(const QString &d); diff --git a/src/plugins/projectexplorer/customwizard/customwizard.cpp b/src/plugins/projectexplorer/customwizard/customwizard.cpp index 8f85f26d600..b6fb74e0e79 100644 --- a/src/plugins/projectexplorer/customwizard/customwizard.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizard.cpp @@ -166,7 +166,7 @@ BaseFileWizard *CustomWizard::create(QWidget *parent, const WizardDialogParamete d->m_context->reset(); auto customPage = new CustomWizardPage(d->m_context, parameters()); - customPage->setPath(p.defaultPath()); + customPage->setFilePath(p.defaultPath()); if (parameters()->firstPageId >= 0) wizard->setPage(parameters()->firstPageId, customPage); else @@ -506,7 +506,7 @@ BaseFileWizard *CustomProjectWizard::create(QWidget *parent, } void CustomProjectWizard::initProjectWizardDialog(BaseProjectWizardDialog *w, - const QString &defaultPath, + const FilePath &defaultPath, const QList &extensionPages) const { const CustomWizardParametersPtr pa = parameters(); @@ -526,7 +526,7 @@ void CustomProjectWizard::initProjectWizardDialog(BaseProjectWizardDialog *w, } for (QWizardPage *ep : extensionPages) w->addPage(ep); - w->setFilePath(FilePath::fromString(defaultPath)); + w->setFilePath(defaultPath); w->setProjectName(BaseProjectWizardDialog::uniqueProjectName(defaultPath)); connect(w, &BaseProjectWizardDialog::projectParametersChanged, diff --git a/src/plugins/projectexplorer/customwizard/customwizard.h b/src/plugins/projectexplorer/customwizard/customwizard.h index e883a738e4d..3ea3a928771 100644 --- a/src/plugins/projectexplorer/customwizard/customwizard.h +++ b/src/plugins/projectexplorer/customwizard/customwizard.h @@ -141,7 +141,7 @@ protected: bool postGenerateFiles(const QWizard *w, const Core::GeneratedFiles &l, QString *errorMessage) const override; - void initProjectWizardDialog(BaseProjectWizardDialog *w, const QString &defaultPath, + void initProjectWizardDialog(BaseProjectWizardDialog *w, const Utils::FilePath &defaultPath, const QList &extensionPages) const; private: diff --git a/src/plugins/projectexplorer/customwizard/customwizardpage.cpp b/src/plugins/projectexplorer/customwizard/customwizardpage.cpp index 4348b0f72e3..aac22467508 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardpage.cpp +++ b/src/plugins/projectexplorer/customwizard/customwizardpage.cpp @@ -437,9 +437,9 @@ FilePath CustomWizardPage::filePath() const return m_pathChooser->filePath(); } -void CustomWizardPage::setPath(const QString &path) +void CustomWizardPage::setFilePath(const FilePath &path) { - m_pathChooser->setPath(path); + m_pathChooser->setFilePath(path); } bool CustomWizardPage::isComplete() const diff --git a/src/plugins/projectexplorer/customwizard/customwizardpage.h b/src/plugins/projectexplorer/customwizard/customwizardpage.h index 47d60f47d32..5a33011a7dd 100644 --- a/src/plugins/projectexplorer/customwizard/customwizardpage.h +++ b/src/plugins/projectexplorer/customwizard/customwizardpage.h @@ -127,7 +127,7 @@ public: QWidget *parent = nullptr); Utils::FilePath filePath() const; - void setPath(const QString &path); + void setFilePath(const Utils::FilePath &path); bool isComplete() const override; diff --git a/src/plugins/projectexplorer/jsonwizard/jsonfilepage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonfilepage.cpp index 0b4c93649e8..0e1755515e8 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonfilepage.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonfilepage.cpp @@ -47,17 +47,17 @@ void JsonFilePage::initializePage() if (fileName().isEmpty()) setFileName(wiz->stringValue(QLatin1String("InitialFileName"))); - if (path().isEmpty()) + if (filePath().isEmpty()) setPath(wiz->stringValue(QLatin1String("InitialPath"))); setDefaultSuffix(wiz->stringValue("DefaultSuffix")); } bool JsonFilePage::validatePage() { - if (path().isEmpty() || fileName().isEmpty()) + if (filePath().isEmpty() || fileName().isEmpty()) return false; - const FilePath dir = FilePath::fromString(path()); + const FilePath dir = filePath(); if (!dir.isDir()) return false; diff --git a/src/plugins/projectexplorer/simpleprojectwizard.cpp b/src/plugins/projectexplorer/simpleprojectwizard.cpp index 91cc18ab3f4..82a30658aa3 100644 --- a/src/plugins/projectexplorer/simpleprojectwizard.cpp +++ b/src/plugins/projectexplorer/simpleprojectwizard.cpp @@ -148,8 +148,8 @@ public: addPage(m_secondPage); } - QString path() const { return m_firstPage->path(); } - void setPath(const QString &path) { m_firstPage->setPath(path); } + Utils::FilePath projectDir() const { return m_firstPage->filePath(); } + void setProjectDir(const Utils::FilePath &path) { m_firstPage->setFilePath(path); } FilePaths selectedFiles() const { return m_secondPage->selectedFiles(); } FilePaths selectedPaths() const { return m_secondPage->selectedPaths(); } QString qtModules() const { return m_secondPage->qtModules(); } @@ -162,8 +162,7 @@ public: void FilesSelectionWizardPage::initializePage() { - m_filesWidget->resetModel(FilePath::fromString(m_simpleProjectWizardDialog->path()), - FilePaths()); + m_filesWidget->resetModel(m_simpleProjectWizardDialog->projectDir(), FilePaths()); } SimpleProjectWizard::SimpleProjectWizard() @@ -187,7 +186,7 @@ BaseFileWizard *SimpleProjectWizard::create(QWidget *parent, const WizardDialogParameters ¶meters) const { auto wizard = new SimpleProjectWizardDialog(this, parent); - wizard->setPath(parameters.defaultPath()); + wizard->setProjectDir(parameters.defaultPath()); for (QWizardPage *p : wizard->extensionPages()) wizard->addPage(p); @@ -199,7 +198,7 @@ GeneratedFiles generateQmakeFiles(const SimpleProjectWizardDialog *wizard, QString *errorMessage) { Q_UNUSED(errorMessage) - const QString projectPath = wizard->path(); + const QString projectPath = wizard->projectDir().toString(); const QDir dir(projectPath); const QString projectName = wizard->projectName(); const FilePath proFileName = Utils::FilePath::fromString(QFileInfo(dir, projectName + ".pro").absoluteFilePath()); @@ -257,8 +256,7 @@ GeneratedFiles generateCmakeFiles(const SimpleProjectWizardDialog *wizard, QString *errorMessage) { Q_UNUSED(errorMessage) - const QString projectPath = wizard->path(); - const QDir dir(projectPath); + const QDir dir(wizard->projectDir().toString()); const QString projectName = wizard->projectName(); const FilePath projectFileName = Utils::FilePath::fromString(QFileInfo(dir, "CMakeLists.txt").absoluteFilePath()); const QStringList paths = Utils::transform(wizard->selectedPaths(), &FilePath::toString); diff --git a/src/plugins/qmakeprojectmanager/wizards/qtprojectparameters.cpp b/src/plugins/qmakeprojectmanager/wizards/qtprojectparameters.cpp index c5a66d9470e..1d4afbd9363 100644 --- a/src/plugins/qmakeprojectmanager/wizards/qtprojectparameters.cpp +++ b/src/plugins/qmakeprojectmanager/wizards/qtprojectparameters.cpp @@ -32,19 +32,17 @@ #include #include +using namespace Utils; + namespace QmakeProjectManager { namespace Internal { // ----------- QtProjectParameters QtProjectParameters::QtProjectParameters() = default; -QString QtProjectParameters::projectPath() const +FilePath QtProjectParameters::projectPath() const { - QString rc = path; - if (!rc.isEmpty()) - rc += QLatin1Char('/'); - rc += fileName; - return rc; + return path / fileName; } // Write out a QT module line. diff --git a/src/plugins/qmakeprojectmanager/wizards/qtprojectparameters.h b/src/plugins/qmakeprojectmanager/wizards/qtprojectparameters.h index 2a260adf705..c754b766027 100644 --- a/src/plugins/qmakeprojectmanager/wizards/qtprojectparameters.h +++ b/src/plugins/qmakeprojectmanager/wizards/qtprojectparameters.h @@ -25,6 +25,8 @@ #pragma once +#include + #include QT_BEGIN_NAMESPACE @@ -41,14 +43,15 @@ QString createMacro(const QString &name, const QString &suffix); // Base parameters for application project generation with functionality to // write a .pro-file section. -struct QtProjectParameters { +struct QtProjectParameters +{ enum Type { ConsoleApp, GuiApp, StaticLibrary, SharedLibrary, QtPlugin, EmptyProject }; enum QtVersionSupport { SupportQt4And5, SupportQt4Only, SupportQt5Only }; enum Flags { WidgetsRequiredFlag = 0x1 }; QtProjectParameters(); // Return project path as "path/name" - QString projectPath() const; + Utils::FilePath projectPath() const; void writeProFile(QTextStream &) const; static void writeProFileHeader(QTextStream &); @@ -62,7 +65,7 @@ struct QtProjectParameters { QtVersionSupport qtVersionSupport = SupportQt4And5; QString fileName; QString target; - QString path; + Utils::FilePath path; QStringList selectedModules; QStringList deselectedModules; QString targetDirectory; diff --git a/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizard.cpp b/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizard.cpp index ca63700cd62..176117881a9 100644 --- a/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizard.cpp +++ b/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizard.cpp @@ -36,6 +36,8 @@ #include +using namespace Utils; + namespace QmakeProjectManager { namespace Internal { @@ -70,8 +72,8 @@ Core::GeneratedFiles SubdirsProjectWizard::generateFiles(const QWizard *w, { const auto *wizard = qobject_cast< const SubdirsProjectWizardDialog *>(w); const QtProjectParameters params = wizard->parameters(); - const QString projectPath = params.projectPath(); - const QString profileName = Core::BaseFileWizardFactory::buildFileName(projectPath, params.fileName, profileSuffix()); + const FilePath projectPath = params.projectPath(); + const FilePath profileName = Core::BaseFileWizardFactory::buildFileName(projectPath, params.fileName, profileSuffix()); Core::GeneratedFile profile(profileName); profile.setAttributes(Core::GeneratedFile::OpenProjectAttribute | Core::GeneratedFile::OpenEditorAttribute); @@ -85,10 +87,10 @@ bool SubdirsProjectWizard::postGenerateFiles(const QWizard *w, const Core::Gener const auto *wizard = qobject_cast< const SubdirsProjectWizardDialog *>(w); if (QtWizard::qt4ProjectPostGenerateFiles(wizard, files, errorMessage)) { const QtProjectParameters params = wizard->parameters(); - const QString projectPath = params.projectPath(); - const QString profileName = Core::BaseFileWizardFactory::buildFileName(projectPath, params.fileName, profileSuffix()); + const FilePath projectPath = params.projectPath(); + const FilePath profileName = Core::BaseFileWizardFactory::buildFileName(projectPath, params.fileName, profileSuffix()); QVariantMap map; - map.insert(QLatin1String(ProjectExplorer::Constants::PREFERRED_PROJECT_NODE), profileName); + map.insert(QLatin1String(ProjectExplorer::Constants::PREFERRED_PROJECT_NODE), profileName.toVariant()); map.insert(QLatin1String(ProjectExplorer::Constants::PROJECT_KIT_IDS), Utils::transform(wizard->selectedKits(), &Utils::Id::toString)); IWizardFactory::requestNewItemDialog(tr("New Subproject", "Title of dialog"), @@ -96,7 +98,7 @@ bool SubdirsProjectWizard::postGenerateFiles(const QWizard *w, const Core::Gener [](Core::IWizardFactory *f) { return f->supportedProjectTypes().contains(Constants::QMAKEPROJECT_ID); }), - Utils::FilePath::fromString(wizard->parameters().projectPath()), + wizard->parameters().projectPath(), map); } else { return false; diff --git a/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizarddialog.cpp b/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizarddialog.cpp index d292ab8568e..092f98129f1 100644 --- a/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizarddialog.cpp +++ b/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizarddialog.cpp @@ -55,7 +55,7 @@ QtProjectParameters SubdirsProjectWizardDialog::parameters() const QtProjectParameters rc; rc.type = QtProjectParameters::EmptyProject; rc.fileName = projectName(); - rc.path = filePath().toString(); + rc.path = filePath(); return rc; } From bb9bfa1cd4345cfc5bc0a22166b075e7a1ccccf8 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 29 Sep 2021 13:58:45 +0200 Subject: [PATCH 08/15] ProjectExplorer: Allow devices to report tasks in validate And use it to report a hard error when docker devices don't have a shared directory set. While this is possibly too harsh in the long run it fits the current situation where we want to use the container for building projects. Change-Id: I1430716b5722fba537bb964463ce25c7001be6a4 Reviewed-by: Christian Stenger --- src/plugins/docker/dockerdevice.cpp | 12 ++++++++++++ src/plugins/docker/dockerdevice.h | 1 + .../projectexplorer/devicesupport/idevice.cpp | 5 +++++ src/plugins/projectexplorer/devicesupport/idevice.h | 2 ++ src/plugins/projectexplorer/kitinformation.cpp | 3 +++ 5 files changed, 23 insertions(+) diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index e3a97214d3b..40efac7f541 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -473,6 +473,18 @@ IDeviceWidget *DockerDevice::createWidget() return new DockerDeviceWidget(sharedFromThis()); } +Tasks DockerDevice::validate() const +{ + Tasks result; + if (d->m_data.mounts.isEmpty()) { + result << Task(Task::Error, + tr("The Docker device has not set up shared directories." + "This will not work for building."), + {}, -1, {}); + } + return result; +} + // DockerDevice diff --git a/src/plugins/docker/dockerdevice.h b/src/plugins/docker/dockerdevice.h index 64d5bb17ac3..ded9a93b063 100644 --- a/src/plugins/docker/dockerdevice.h +++ b/src/plugins/docker/dockerdevice.h @@ -62,6 +62,7 @@ public: static Ptr create(const DockerDeviceData &data) { return Ptr(new DockerDevice(data)); } ProjectExplorer::IDeviceWidget *createWidget() override; + QVector validate() const override; bool canCreateProcess() const override { return true; } ProjectExplorer::DeviceProcess *createProcess(QObject *parent) const override; diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index 03f7e8b281c..5fae1d38631 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -532,6 +532,11 @@ bool IDevice::isCompatibleWith(const Kit *k) const return DeviceTypeKitAspect::deviceTypeId(k) == type(); } +QVector IDevice::validate() const +{ + return {}; +} + void IDevice::addDeviceAction(const DeviceAction &deviceAction) { d->deviceActions.append(deviceAction); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index e9d488667f0..873eb380bb3 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -65,6 +65,7 @@ class DeviceProcess; class DeviceProcessList; class Kit; class Runnable; +class Task; namespace Internal { class IDevicePrivate; } @@ -159,6 +160,7 @@ public: Utils::Id id() const; virtual bool isCompatibleWith(const Kit *k) const; + virtual QVector validate() const; QString displayType() const; Utils::OsType osType() const; diff --git a/src/plugins/projectexplorer/kitinformation.cpp b/src/plugins/projectexplorer/kitinformation.cpp index eb02496a326..91a90a65981 100644 --- a/src/plugins/projectexplorer/kitinformation.cpp +++ b/src/plugins/projectexplorer/kitinformation.cpp @@ -1005,6 +1005,9 @@ Tasks DeviceKitAspect::validate(const Kit *k) const else if (!dev->isCompatibleWith(k)) result.append(BuildSystemTask(Task::Error, tr("Device is incompatible with this kit."))); + if (dev) + result.append(dev->validate()); + return result; } From b5a4d38022122c19744745ccc7ee32d1edfbeae3 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 29 Sep 2021 14:31:31 +0200 Subject: [PATCH 09/15] Git: Take Prepend to PATH into account again Task-number: QTCREATORBUG-26329 Change-Id: If4ac35cc95a47e4f82c6205ad24d8bdc69ddf1af Reviewed-by: Orgad Shaneh --- src/plugins/git/gitclient.cpp | 2 +- src/plugins/git/gitsettings.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index c1bbeec724c..d3e88b71d30 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -981,7 +981,7 @@ void GitClient::requestReload(const QString &documentId, const QString &source, QTC_ASSERT(document, return); GitBaseDiffEditorController *controller = factory(document); QTC_ASSERT(controller, return); - controller->setVcsBinary(settings().binaryPath.filePath()); + controller->setVcsBinary(settings().gitExecutable()); controller->setVcsTimeoutS(settings().timeout.value()); controller->setProcessEnvironment(processEnvironment()); controller->setWorkingDirectory(workingDirectory); diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp index a8e4a97785c..bf431abe57e 100644 --- a/src/plugins/git/gitsettings.cpp +++ b/src/plugins/git/gitsettings.cpp @@ -25,6 +25,7 @@ #include "gitsettings.h" +#include #include #include @@ -140,6 +141,12 @@ FilePath GitSettings::gitExecutable(bool *ok, QString *errorMessage) const errorMessage->clear(); FilePath binPath = binaryPath.filePath(); + if (!binPath.isAbsolutePath()) { + FilePaths searchPath = binPath.deviceEnvironment().path(); + if (!path.filePath().isEmpty()) + searchPath.prepend(path.filePath()); + binPath = binPath.searchInPath(searchPath); + } if (binPath.isEmpty()) { if (ok) *ok = false; From 3ad9c6497798adeac883495014f7afd83ec2aa04 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 29 Sep 2021 18:13:39 +0200 Subject: [PATCH 10/15] ProjectExplorer: Clean up some #includes Change-Id: Id5a826ff0681a1990f4eeebf1bfc7573e162e861 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/kit.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/plugins/projectexplorer/kit.cpp b/src/plugins/projectexplorer/kit.cpp index 0791987c01d..b509c5bc62f 100644 --- a/src/plugins/projectexplorer/kit.cpp +++ b/src/plugins/projectexplorer/kit.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include #include #include #include @@ -42,10 +42,7 @@ #include #include -#include -#include #include -#include #include #include From faba85a2c331b0af984050c79655a7d7236d439f Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 29 Sep 2021 18:41:31 +0200 Subject: [PATCH 11/15] TaskHub: Add #include Change-Id: I395252692fedb547bc0927f2c2838d674bbd56ee Reviewed-by: Jarek Kobus --- src/plugins/projectexplorer/taskhub.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/projectexplorer/taskhub.cpp b/src/plugins/projectexplorer/taskhub.cpp index 1912264bb5f..0db4b7073a7 100644 --- a/src/plugins/projectexplorer/taskhub.cpp +++ b/src/plugins/projectexplorer/taskhub.cpp @@ -34,6 +34,7 @@ #include #include +#include using namespace Utils; From 67c0104b8e56a3d3089a309e1e09c6380639249b Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 29 Sep 2021 14:31:31 +0200 Subject: [PATCH 12/15] Git: Take Prepend to PATH into account again, take #2 Amends b5a4d38022, which uses FilePath::searchInPath which does not exist in 5.0. Task-number: QTCREATORBUG-26329 Change-Id: I94ac35cc95a47e4f82c6205ad24d8bdc69ddf1af Reviewed-by: Orgad Shaneh Reviewed-by: Qt CI Bot --- src/plugins/git/gitsettings.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/git/gitsettings.cpp b/src/plugins/git/gitsettings.cpp index bf431abe57e..00270a1d425 100644 --- a/src/plugins/git/gitsettings.cpp +++ b/src/plugins/git/gitsettings.cpp @@ -142,10 +142,10 @@ FilePath GitSettings::gitExecutable(bool *ok, QString *errorMessage) const FilePath binPath = binaryPath.filePath(); if (!binPath.isAbsolutePath()) { - FilePaths searchPath = binPath.deviceEnvironment().path(); + Environment env = Environment::systemEnvironment(); if (!path.filePath().isEmpty()) - searchPath.prepend(path.filePath()); - binPath = binPath.searchInPath(searchPath); + env.prependOrSetPath(path.filePath().toString()); + binPath = env.searchInPath(binPath.toString()); } if (binPath.isEmpty()) { if (ok) From 525039daebe783560d2ba7f12db573f25d745852 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Mon, 27 Sep 2021 15:28:36 +0200 Subject: [PATCH 13/15] QmlProject: port changes from QtForMcus Task-number: QTCREATORBUG-26041 Change-Id: I5068381fb2c4c901d8621e0b8358db77d2cb0b21 Reviewed-by: Thomas Hartmann --- src/libs/qmljs/qmljssimplereader.cpp | 555 +++++++++--------- src/libs/qmljs/qmljssimplereader.h | 63 +- .../propertyeditorqmlbackend.cpp | 10 +- .../designercore/include/metainforeader.h | 7 +- .../designercore/metainfo/metainforeader.cpp | 7 +- .../designercore/model/rewriterview.cpp | 4 +- .../qmldesigner/designermcumanager.cpp | 41 +- .../fileformat/qmlprojectfileformat.cpp | 60 +- .../qmldesigner/coretests/tst_testcore.cpp | 4 +- .../tst_qmljssimplereader.cpp | 16 +- 10 files changed, 424 insertions(+), 343 deletions(-) diff --git a/src/libs/qmljs/qmljssimplereader.cpp b/src/libs/qmljs/qmljssimplereader.cpp index d0d43b4098e..92d0761656a 100644 --- a/src/libs/qmljs/qmljssimplereader.cpp +++ b/src/libs/qmljs/qmljssimplereader.cpp @@ -25,9 +25,15 @@ #include "qmljssimplereader.h" -#include "parser/qmljsparser_p.h" -#include "parser/qmljslexer_p.h" +#ifdef QT_CREATOR #include "parser/qmljsengine_p.h" +#include "parser/qmljslexer_p.h" +#include "parser/qmljsparser_p.h" +#else +#include "parser/qqmljsengine_p.h" +#include "parser/qqmljslexer_p.h" +#include "qqmljsparser_p.h" +#endif #include "qmljsutils.h" @@ -37,308 +43,331 @@ static Q_LOGGING_CATEGORY(simpleReaderLog, "qtc.qmljs.simpleReader", QtWarningMsg) -namespace QmlJS{ - -QVariant SimpleReaderNode::property(const QString &name) const + namespace QmlJS { - return m_properties.value(name); -} +#ifdef QT_CREATOR + using UiQualifiedId = QmlJS::AST::UiQualifiedId; +#else + using UiQualifiedId = QQmlJS::AST::UiQualifiedId; +#endif -QStringList SimpleReaderNode::propertyNames() const -{ - return m_properties.keys(); -} - -SimpleReaderNode::PropertyHash SimpleReaderNode::properties() const -{ - return m_properties; -} - -bool SimpleReaderNode::isRoot() const -{ - return m_parentNode.isNull(); -} - -bool SimpleReaderNode::isValid() const -{ - return !m_name.isEmpty(); -} - -SimpleReaderNode::Ptr SimpleReaderNode::invalidNode() -{ - return Ptr(new SimpleReaderNode); -} - -SimpleReaderNode::WeakPtr SimpleReaderNode::parent() const -{ - return m_parentNode; -} - -QString SimpleReaderNode::name() const -{ - return m_name; -} - -SimpleReaderNode::SimpleReaderNode() -{ -} - -SimpleReaderNode::SimpleReaderNode(const QString &name, WeakPtr parent) - : m_name(name), m_parentNode(parent) -{ -} - -SimpleReaderNode::Ptr SimpleReaderNode::create(const QString &name, WeakPtr parent) -{ - Ptr newNode(new SimpleReaderNode(name, parent)); - newNode->m_weakThis = newNode; - if (parent) - parent.toStrongRef().data()->m_children.append(newNode); - return newNode; -} - -const SimpleReaderNode::List SimpleReaderNode::children() const -{ - return m_children; -} - -void SimpleReaderNode::setProperty(const QString &name, const QVariant &value) -{ - m_properties.insert(name, value); -} - -SimpleAbstractStreamReader::SimpleAbstractStreamReader() -{ -} - -bool SimpleAbstractStreamReader::readFile(const QString &fileName) -{ - QFile file(fileName); - if (file.open(QIODevice::ReadOnly)) { - QByteArray source = file.readAll(); - file.close(); - return readFromSource(QString::fromLocal8Bit(source)); + static SourceLocation toSourceLocation(SourceLocation first, SourceLocation last) + { + first.length = last.end() - first.begin(); + return first; } - addError(tr("Cannot find file %1.").arg(fileName)); - return false; -} -bool SimpleAbstractStreamReader::readFromSource(const QString &source) -{ - m_errors.clear(); - m_currentSourceLocation = SourceLocation(); - - m_source = source; - - Engine engine; - Lexer lexer(&engine); - Parser parser(&engine); - - lexer.setCode(source, /*line = */ 1, /*qmlMode = */true); - - if (!parser.parse()) { - QString errorMessage = QString::fromLatin1("%1:%2: %3").arg( - QString::number(parser.errorLineNumber()), - QString::number(parser.errorColumnNumber()), - parser.errorMessage()); - addError(errorMessage); - return false; + static SourceLocation toSourceLocation(UiQualifiedId * qualifiedId) + { + SourceLocation first = qualifiedId->firstSourceLocation(); + SourceLocation last; + for (UiQualifiedId *iter = qualifiedId; iter; iter = iter->next) { + if (iter->lastSourceLocation().isValid()) + last = iter->lastSourceLocation(); + } + return toSourceLocation(first, last); } - return readDocument(parser.ast()); -} -QStringList SimpleAbstractStreamReader::errors() const -{ - return m_errors; -} + SimpleReaderNode::Property SimpleReaderNode::property(const QString &name) const + { + return m_properties.value(name); + } -void SimpleAbstractStreamReader::addError(const QString &error, const SourceLocation &sourceLocation) -{ - m_errors << QString::fromLatin1("%1:%2: %3\n").arg( - QString::number(sourceLocation.startLine), - QString::number(sourceLocation.startColumn), - error); -} + QStringList SimpleReaderNode::propertyNames() const { return m_properties.keys(); } -SourceLocation SimpleAbstractStreamReader::currentSourceLocation() const -{ - return m_currentSourceLocation; -} + SimpleReaderNode::PropertyHash SimpleReaderNode::properties() const { return m_properties; } -bool SimpleAbstractStreamReader::readDocument(AST::UiProgram *ast) -{ - if (!ast) { - addError(tr("Could not parse document.")); + bool SimpleReaderNode::isRoot() const { return m_parentNode.isNull(); } + + bool SimpleReaderNode::isValid() const { return !m_name.isEmpty(); } + + SimpleReaderNode::Ptr SimpleReaderNode::invalidNode() { return Ptr(new SimpleReaderNode); } + + SimpleReaderNode::WeakPtr SimpleReaderNode::parent() const { return m_parentNode; } + + QString SimpleReaderNode::name() const { return m_name; } + + SourceLocation SimpleReaderNode::nameLocation() const { return m_nameLocation; } + + SimpleReaderNode::SimpleReaderNode() {} + + SimpleReaderNode::SimpleReaderNode(const QString &name, + const SourceLocation &nameLocation, + WeakPtr parent) + : m_name(name) + , m_nameLocation(nameLocation) + , m_parentNode(parent) + {} + + SimpleReaderNode::Ptr SimpleReaderNode::create(const QString &name, + const SourceLocation &nameLocation, + WeakPtr parent) + { + Ptr newNode(new SimpleReaderNode(name, nameLocation, parent)); + newNode->m_weakThis = newNode; + if (parent) + parent.toStrongRef().data()->m_children.append(newNode); + return newNode; + } + + const SimpleReaderNode::List SimpleReaderNode::children() const { return m_children; } + + void SimpleReaderNode::setProperty(const QString &name, + const SourceLocation &nameLocation, + const QVariant &value, + const SourceLocation &valueLocation) + { + m_properties.insert(name, {value, nameLocation, valueLocation}); + } + + SimpleAbstractStreamReader::SimpleAbstractStreamReader() {} + + SimpleAbstractStreamReader::~SimpleAbstractStreamReader() {} + + bool SimpleAbstractStreamReader::readFile(const QString &fileName) + { + QFile file(fileName); + if (file.open(QIODevice::ReadOnly)) { + QByteArray source = file.readAll(); + file.close(); + return readFromSource(QString::fromLocal8Bit(source)); + } + addError(tr("Cannot find file %1.").arg(fileName)); return false; } - AST::UiObjectDefinition *uiObjectDefinition = AST::cast(ast->members->member); - if (!uiObjectDefinition) { - addError(tr("Expected document to contain a single object definition.")); - return false; - } - readChild(uiObjectDefinition); + bool SimpleAbstractStreamReader::readFromSource(const QString &source) + { + m_errors.clear(); + m_currentSourceLocation = SourceLocation(); - m_source.clear(); + m_source = source; - return errors().isEmpty(); -} + Engine engine; + Lexer lexer(&engine); + Parser parser(&engine); -void SimpleAbstractStreamReader::readChildren(AST::UiObjectDefinition *uiObjectDefinition) -{ - Q_ASSERT(uiObjectDefinition); + lexer.setCode(source, /*line = */ 1, /*qmlMode = */ true); - for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it; it = it->next) { - AST::UiObjectMember *member = it->member; - AST::UiObjectDefinition *uiObjectDefinition = AST::cast(member); - if (uiObjectDefinition) - readChild(uiObjectDefinition); - } -} - -void SimpleAbstractStreamReader::readChild(AST::UiObjectDefinition *uiObjectDefinition) -{ - Q_ASSERT(uiObjectDefinition); - - setSourceLocation(uiObjectDefinition->firstSourceLocation()); - - elementStart(toString(uiObjectDefinition->qualifiedTypeNameId)); - - readProperties(uiObjectDefinition); - readChildren(uiObjectDefinition); - - elementEnd(); -} - -void SimpleAbstractStreamReader::readProperties(AST::UiObjectDefinition *uiObjectDefinition) -{ - Q_ASSERT(uiObjectDefinition); - - for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it; it = it->next) { - AST::UiObjectMember *member = it->member; - AST::UiScriptBinding *scriptBinding = AST::cast(member); - if (scriptBinding) - readProperty(scriptBinding); - } -} - -void SimpleAbstractStreamReader::readProperty(AST::UiScriptBinding *uiScriptBinding) -{ - Q_ASSERT(uiScriptBinding); - - setSourceLocation(uiScriptBinding->firstSourceLocation()); - - const QString name = toString(uiScriptBinding->qualifiedId); - const QVariant value = parsePropertyScriptBinding(uiScriptBinding); - - propertyDefinition(name, value); -} - -QVariant SimpleAbstractStreamReader::parsePropertyScriptBinding(AST::UiScriptBinding *uiScriptBinding) -{ - Q_ASSERT(uiScriptBinding); - - AST::ExpressionStatement *expStmt = AST::cast(uiScriptBinding->statement); - if (!expStmt) { - addError(tr("Expected expression statement after colon."), uiScriptBinding->statement->firstSourceLocation()); - return QVariant(); + if (!parser.parse()) { + QString errorMessage = QString::fromLatin1("%1:%2: %3") + .arg(QString::number(parser.errorLineNumber()), + QString::number(parser.errorColumnNumber()), + parser.errorMessage()); + addError(errorMessage); + return false; + } + return readDocument(parser.ast()); } - return parsePropertyExpression(expStmt->expression); -} + QStringList SimpleAbstractStreamReader::errors() const { return m_errors; } -QVariant SimpleAbstractStreamReader::parsePropertyExpression(AST::ExpressionNode *expressionNode) -{ - Q_ASSERT(expressionNode); - - AST::ArrayPattern *arrayLiteral = AST::cast(expressionNode); - - if (arrayLiteral) { - QList variantList; - for (AST::PatternElementList *it = arrayLiteral->elements; it; it = it->next) - variantList << parsePropertyExpression(it->element->initializer); - return variantList; + void SimpleAbstractStreamReader::addError(const QString &error, + const SourceLocation &sourceLocation) + { + m_errors << QString::fromLatin1("%1:%2: %3\n") + .arg(QString::number(sourceLocation.startLine), + QString::number(sourceLocation.startColumn), + error); } - AST::StringLiteral *stringLiteral = AST::cast(expressionNode); - if (stringLiteral) - return stringLiteral->value.toString(); + SourceLocation SimpleAbstractStreamReader::currentSourceLocation() const + { + return m_currentSourceLocation; + } - AST::TrueLiteral *trueLiteral = AST::cast(expressionNode); - if (trueLiteral) - return true; + bool SimpleAbstractStreamReader::readDocument(AST::UiProgram * ast) + { + if (!ast) { + addError(tr("Could not parse document.")); + return false; + } - AST::FalseLiteral *falseLiteral = AST::cast(expressionNode); - if (falseLiteral) - return false; + AST::UiObjectDefinition *uiObjectDefinition = AST::cast( + ast->members->member); + if (!uiObjectDefinition) { + addError(tr("Expected document to contain a single object definition.")); + return false; + } + readChild(uiObjectDefinition); - AST::NumericLiteral *numericLiteral = AST::cast(expressionNode); - if (numericLiteral) - return numericLiteral->value; + m_source.clear(); - return textAt(expressionNode->firstSourceLocation(), expressionNode->lastSourceLocation()); -} + return errors().isEmpty(); + } -void SimpleAbstractStreamReader::setSourceLocation(const SourceLocation &sourceLocation) -{ - m_currentSourceLocation = sourceLocation; -} + void SimpleAbstractStreamReader::readChildren(AST::UiObjectDefinition * uiObjectDefinition) + { + Q_ASSERT(uiObjectDefinition); -QString SimpleAbstractStreamReader::textAt(const SourceLocation &from, - const SourceLocation &to) -{ - return m_source.mid(from.offset, to.end() - from.begin()); -} + for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it; + it = it->next) { + AST::UiObjectMember *member = it->member; + AST::UiObjectDefinition *uiObjectDefinition = AST::cast( + member); + if (uiObjectDefinition) + readChild(uiObjectDefinition); + } + } -SimpleReader::SimpleReader() -{ -} + void SimpleAbstractStreamReader::readChild(AST::UiObjectDefinition * uiObjectDefinition) + { + Q_ASSERT(uiObjectDefinition); -SimpleReaderNode::Ptr SimpleReader::readFile(const QString &fileName) -{ - SimpleAbstractStreamReader::readFile(fileName); - return m_rootNode; -} + setSourceLocation(uiObjectDefinition->firstSourceLocation()); -SimpleReaderNode::Ptr SimpleReader::readFromSource(const QString &source) -{ - SimpleAbstractStreamReader::readFromSource(source); - return m_rootNode; -} + elementStart(toString(uiObjectDefinition->qualifiedTypeNameId), + toSourceLocation(uiObjectDefinition->qualifiedTypeNameId)); -void SimpleReader::elementStart(const QString &name) -{ - qCDebug(simpleReaderLog) << "elementStart()" << name; + readProperties(uiObjectDefinition); + readChildren(uiObjectDefinition); - SimpleReaderNode::Ptr newNode = SimpleReaderNode::create(name, m_currentNode); + elementEnd(); + } - if (newNode->isRoot()) - m_rootNode = newNode; + void SimpleAbstractStreamReader::readProperties(AST::UiObjectDefinition * uiObjectDefinition) + { + Q_ASSERT(uiObjectDefinition); - Q_ASSERT(newNode->isValid()); + for (AST::UiObjectMemberList *it = uiObjectDefinition->initializer->members; it; + it = it->next) { + AST::UiObjectMember *member = it->member; + AST::UiScriptBinding *scriptBinding = AST::cast(member); + if (scriptBinding) + readProperty(scriptBinding); + } + } - m_currentNode = newNode; -} + void SimpleAbstractStreamReader::readProperty(AST::UiScriptBinding * uiScriptBinding) + { + Q_ASSERT(uiScriptBinding); -void SimpleReader::elementEnd() -{ - Q_ASSERT(m_currentNode); + setSourceLocation(uiScriptBinding->firstSourceLocation()); - qCDebug(simpleReaderLog) << "elementEnd()" << m_currentNode.toStrongRef().data()->name(); + const QString name = toString(uiScriptBinding->qualifiedId); + auto nameLoc = toSourceLocation(uiScriptBinding->qualifiedId); + auto value = parsePropertyScriptBinding(uiScriptBinding); - m_currentNode = m_currentNode.toStrongRef().data()->parent(); -} + propertyDefinition(name, nameLoc, value.first, value.second); + } -void SimpleReader::propertyDefinition(const QString &name, const QVariant &value) -{ - Q_ASSERT(m_currentNode); + std::pair SimpleAbstractStreamReader::parsePropertyScriptBinding( + AST::UiScriptBinding * uiScriptBinding) + { + Q_ASSERT(uiScriptBinding); - qCDebug(simpleReaderLog) << "propertyDefinition()" << m_currentNode.toStrongRef().data()->name() << name << value; + AST::ExpressionStatement *expStmt = AST::cast( + uiScriptBinding->statement); + if (!expStmt) { + addError(tr("Expected expression statement after colon."), + uiScriptBinding->statement->firstSourceLocation()); + return std::make_pair(QVariant(), SourceLocation()); + } - if (m_currentNode.toStrongRef().data()->propertyNames().contains(name)) - addError(tr("Property is defined twice."), currentSourceLocation()); + return std::make_pair(parsePropertyExpression(expStmt->expression), + toSourceLocation(expStmt->firstSourceLocation(), + expStmt->lastSourceLocation())); + } - m_currentNode.toStrongRef().data()->setProperty(name, value); -} + QVariant SimpleAbstractStreamReader::parsePropertyExpression(AST::ExpressionNode + * expressionNode) + { + Q_ASSERT(expressionNode); + + AST::ArrayPattern *arrayLiteral = AST::cast(expressionNode); + + if (arrayLiteral) { + QList variantList; + for (AST::PatternElementList *it = arrayLiteral->elements; it; it = it->next) + variantList << parsePropertyExpression(it->element->initializer); + return variantList; + } + + AST::StringLiteral *stringLiteral = AST::cast(expressionNode); + if (stringLiteral) + return stringLiteral->value.toString(); + + AST::TrueLiteral *trueLiteral = AST::cast(expressionNode); + if (trueLiteral) + return true; + + AST::FalseLiteral *falseLiteral = AST::cast(expressionNode); + if (falseLiteral) + return false; + + AST::NumericLiteral *numericLiteral = AST::cast(expressionNode); + if (numericLiteral) + return numericLiteral->value; + + return textAt(expressionNode->firstSourceLocation(), expressionNode->lastSourceLocation()); + } + + void SimpleAbstractStreamReader::setSourceLocation(const SourceLocation &sourceLocation) + { + m_currentSourceLocation = sourceLocation; + } + + QString SimpleAbstractStreamReader::textAt(const SourceLocation &from, const SourceLocation &to) + { + return m_source.mid(from.offset, to.end() - from.begin()); + } + + SimpleReader::SimpleReader() {} + + SimpleReaderNode::Ptr SimpleReader::readFile(const QString &fileName) + { + SimpleAbstractStreamReader::readFile(fileName); + return m_rootNode; + } + + SimpleReaderNode::Ptr SimpleReader::readFromSource(const QString &source) + { + SimpleAbstractStreamReader::readFromSource(source); + return m_rootNode; + } + + void SimpleReader::elementStart(const QString &name, const SourceLocation &nameLocation) + { + qCDebug(simpleReaderLog) << "elementStart()" << name; + + SimpleReaderNode::Ptr newNode = SimpleReaderNode::create(name, nameLocation, m_currentNode); + + if (newNode->isRoot()) + m_rootNode = newNode; + + Q_ASSERT(newNode->isValid()); + + m_currentNode = newNode; + } + + void SimpleReader::elementEnd() + { + Q_ASSERT(m_currentNode); + + qCDebug(simpleReaderLog) << "elementEnd()" << m_currentNode.toStrongRef().data()->name(); + + m_currentNode = m_currentNode.toStrongRef().data()->parent(); + } + + void SimpleReader::propertyDefinition(const QString &name, + const SourceLocation &nameLocation, + const QVariant &value, + const SourceLocation &valueLocation) + { + Q_ASSERT(m_currentNode); + + qCDebug(simpleReaderLog) << "propertyDefinition()" + << m_currentNode.toStrongRef().data()->name() << name << value; + + if (m_currentNode.toStrongRef().data()->propertyNames().contains(name)) { + auto previousSourceLoc = m_currentNode.toStrongRef().data()->property(name).nameLocation; + addError(tr("Property is defined twice, previous definition at %1:%2") + .arg(QString::number(previousSourceLoc.startLine), + QString::number(previousSourceLoc.startColumn)), + currentSourceLocation()); + } + + m_currentNode.toStrongRef().data()->setProperty(name, nameLocation, value, valueLocation); + } } // namespace QmlJS diff --git a/src/libs/qmljs/qmljssimplereader.h b/src/libs/qmljs/qmljssimplereader.h index 2d5bad3e095..4713c1b67a8 100644 --- a/src/libs/qmljs/qmljssimplereader.h +++ b/src/libs/qmljs/qmljssimplereader.h @@ -26,13 +26,18 @@ #pragma once #include -#include +#ifdef QT_CREATOR +#include +#else +#include +#endif #include #include -#include #include +#include +#include #include // for Q_DECLARE_TR_FUNCTIONS @@ -40,15 +45,31 @@ namespace QmlJS { +#ifndef QT_CREATOR +using SourceLocation = QQmlJS::SourceLocation; +#endif + class QMLJS_EXPORT SimpleReaderNode { public: + struct Property + { + QVariant value; + SourceLocation nameLocation; + SourceLocation valueLocation; + + bool isValid() const { return !value.isNull() && value.isValid(); } + bool isDefaultValue() const + { + return !value.isNull() && !nameLocation.isValid() && !valueLocation.isValid(); + } + }; typedef QSharedPointer Ptr; typedef QWeakPointer WeakPtr; - typedef QHash PropertyHash; + typedef QHash PropertyHash; typedef QList List; - QVariant property(const QString &name) const; + Property property(const QString &name) const; QStringList propertyNames() const; PropertyHash properties() const; bool isRoot() const; @@ -56,16 +77,21 @@ public: static Ptr invalidNode(); WeakPtr parent() const; QString name() const; + SourceLocation nameLocation() const; const List children() const; protected: SimpleReaderNode(); - SimpleReaderNode(const QString &name, WeakPtr parent); - static Ptr create(const QString &name, WeakPtr parent); - void setProperty(const QString &name, const QVariant &value); + SimpleReaderNode(const QString &name, const SourceLocation &nameLocation, WeakPtr parent); + static Ptr create(const QString &name, const SourceLocation &nameLocation, WeakPtr parent); + void setProperty(const QString &name, + const SourceLocation &nameLocation, + const QVariant &value, + const SourceLocation &valueLocation); private: const QString m_name; + const SourceLocation m_nameLocation; PropertyHash m_properties; const WeakPtr m_parentNode; List m_children; @@ -74,12 +100,17 @@ private: friend class SimpleReader; }; +#ifndef QT_CREATOR +using namespace QQmlJS; +#endif + class QMLJS_EXPORT SimpleAbstractStreamReader { Q_DECLARE_TR_FUNCTIONS(QmlJS::SimpleAbstractStreamReader) public: SimpleAbstractStreamReader(); + virtual ~SimpleAbstractStreamReader(); bool readFile(const QString &fileName); bool readFromSource(const QString &source); QStringList errors() const; @@ -88,9 +119,13 @@ protected: void addError(const QString &error, const SourceLocation &sourceLocation = SourceLocation()); SourceLocation currentSourceLocation() const; - virtual void elementStart(const QString &name) = 0; + virtual void elementStart(const QString &name, const SourceLocation &nameLocation) = 0; virtual void elementEnd() = 0; - virtual void propertyDefinition(const QString &name, const QVariant &value) = 0; + virtual void propertyDefinition(const QString &name, + const SourceLocation &nameLocation, + const QVariant &value, + const SourceLocation &valueLocation) + = 0; private: bool readDocument(AST::UiProgram *ast); @@ -98,7 +133,8 @@ private: void readChild(AST::UiObjectDefinition *uiObjectDefinition); void readProperties(AST::UiObjectDefinition *ast); void readProperty(AST::UiScriptBinding *uiScriptBinding); - QVariant parsePropertyScriptBinding(AST::UiScriptBinding *ExpressionNode); + std::pair parsePropertyScriptBinding( + AST::UiScriptBinding *ExpressionNode); QVariant parsePropertyExpression(AST::ExpressionNode *expressionNode); void setSourceLocation(const SourceLocation &sourceLocation); QString textAt(const SourceLocation &from, const SourceLocation &to); @@ -118,9 +154,12 @@ public: SimpleReaderNode::Ptr readFromSource(const QString &source); protected: - void elementStart(const QString &name) override; + void elementStart(const QString &name, const SourceLocation &nameLocation) override; void elementEnd() override; - void propertyDefinition(const QString &name, const QVariant &value) override; + void propertyDefinition(const QString &name, + const SourceLocation &nameLocation, + const QVariant &value, + const SourceLocation &valueLocation) override; private: SimpleReaderNode::Ptr m_rootNode; diff --git a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp index 5adce7e9328..b9c2ce67684 100644 --- a/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp +++ b/src/plugins/qmldesigner/components/propertyeditor/propertyeditorqmlbackend.cpp @@ -595,9 +595,9 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, for (const QmlJS::SimpleReaderNode::Ptr &node : nodes) { if (node->propertyNames().contains("separateSection")) - separateSectionTypes.append(variantToStringList(node->property("typeNames"))); + separateSectionTypes.append(variantToStringList(node->property("typeNames").value)); - allTypes.append(variantToStringList(node->property("typeNames"))); + allTypes.append(variantToStringList(node->property("typeNames").value)); } const QList allProperties = type.propertyNames(); @@ -666,8 +666,8 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, QString filledTemplate; for (const QmlJS::SimpleReaderNode::Ptr &n : nodes) { // Check if we have a template for the type - if (variantToStringList(n->property(QStringLiteral("typeNames"))).contains(QString::fromLatin1(typeName))) { - const QString fileName = propertyTemplatesPath() + n->property(QStringLiteral("sourceFile")).toString(); + if (variantToStringList(n->property(QStringLiteral("typeNames")).value).contains(QString::fromLatin1(typeName))) { + const QString fileName = propertyTemplatesPath() + n->property(QStringLiteral("sourceFile")).value.toString(); QFile file(fileName); if (file.open(QIODevice::ReadOnly)) { QString source = QString::fromUtf8(file.readAll()); @@ -682,7 +682,7 @@ QString PropertyEditorQmlBackend::templateGeneration(const NodeMetaInfo &type, }; // QML specfics preparation - QStringList imports = variantToStringList(templateConfiguration()->property(QStringLiteral("imports"))); + QStringList imports = variantToStringList(templateConfiguration()->property(QStringLiteral("imports")).value); QString qmlTemplate = imports.join(QLatin1Char('\n')) + QLatin1Char('\n'); bool emptyTemplate = true; diff --git a/src/plugins/qmldesigner/designercore/include/metainforeader.h b/src/plugins/qmldesigner/designercore/include/metainforeader.h index f14336b4a17..64047444f3e 100644 --- a/src/plugins/qmldesigner/designercore/include/metainforeader.h +++ b/src/plugins/qmldesigner/designercore/include/metainforeader.h @@ -54,9 +54,12 @@ public: void setQualifcation(const TypeName &qualification); protected: - void elementStart(const QString &name) override; + void elementStart(const QString &name, const QmlJS::SourceLocation &nameLocation) override; void elementEnd() override; - void propertyDefinition(const QString &name, const QVariant &value) override; + void propertyDefinition(const QString &name, + const QmlJS::SourceLocation &nameLocation, + const QVariant &value, + const QmlJS::SourceLocation &valueLocation) override; private: enum ParserSate { Error, diff --git a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp index 5baf856dce9..28d8e028260 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/metainforeader.cpp @@ -87,7 +87,7 @@ void MetaInfoReader::setQualifcation(const TypeName &qualification) m_qualication = qualification; } -void MetaInfoReader::elementStart(const QString &name) +void MetaInfoReader::elementStart(const QString &name, const QmlJS::SourceLocation &nameLocation) { switch (parserState()) { case ParsingDocument: setParserState(readDocument(name)); break; @@ -128,7 +128,10 @@ void MetaInfoReader::elementEnd() } } -void MetaInfoReader::propertyDefinition(const QString &name, const QVariant &value) +void MetaInfoReader::propertyDefinition(const QString &name, + const QmlJS::SourceLocation &nameLocation, + const QVariant &value, + const QmlJS::SourceLocation &valueLocation) { switch (parserState()) { case ParsingType: readTypeProperty(name, value); break; diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp index a1107504533..56a54a0071b 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp @@ -1161,7 +1161,7 @@ void checkNode(const QmlJS::SimpleReaderNode::Ptr &node, RewriterView *view) if (!node->propertyNames().contains("i")) return; - const int index = node->property("i").toInt(); + const int index = node->property("i").value.toInt(); const ModelNode modelNode = view->getNodeForCanonicalIndex(index); @@ -1174,7 +1174,7 @@ void checkNode(const QmlJS::SimpleReaderNode::Ptr &node, RewriterView *view) if (i.key() != "i") { const PropertyName name = fixUpIllegalChars(i.key()).toUtf8(); if (!modelNode.hasAuxiliaryData(name)) - modelNode.setAuxiliaryData(name, i.value()); + modelNode.setAuxiliaryData(name, i.value().value); } } diff --git a/src/plugins/qmldesigner/designermcumanager.cpp b/src/plugins/qmldesigner/designermcumanager.cpp index b7b9ef2fadf..369d4f1dad8 100644 --- a/src/plugins/qmldesigner/designermcumanager.cpp +++ b/src/plugins/qmldesigner/designermcumanager.cpp @@ -37,20 +37,20 @@ namespace QmlDesigner { static QString readProperty(const QString property, const QmlJS::SimpleReaderNode::Ptr &node) { - const QVariant propertyVar = node->property(property); + const auto propertyVar = node->property(property); - if (!propertyVar.isNull() && propertyVar.isValid()) - return propertyVar.value(); + if (propertyVar.isValid()) + return propertyVar.value.value(); return {}; } static QStringList readPropertyList(const QString &property, const QmlJS::SimpleReaderNode::Ptr &node) { - const QVariant propertyVar = node->property(property); + const auto propertyVar = node->property(property); - if (!propertyVar.isNull() && propertyVar.isValid()) - return propertyVar.value(); + if (propertyVar.isValid()) + return propertyVar.value.value(); return {}; } @@ -99,30 +99,31 @@ void DesignerMcuManager::readMetadata() return; } - const QVariant defaultVersion = metadata->property("defaultVersion"); - if (!defaultVersion.isNull() && defaultVersion.isValid()) { + const QmlJS::SimpleReaderNode::Property defaultVersion = metadata->property("defaultVersion"); + + if (defaultVersion.isValid()) { for (const auto& version : versions) { Version newVersion; - const QVariant vId = version->property("id"); - if (vId.isNull() || !vId.isValid()) + const auto vId = version->property("id"); + if (!vId.isValid()) continue; - const QVariant vName = version->property("name"); - if (!vName.isNull() && vName.isValid()) - newVersion.name = vName.value(); + const auto vName = version->property("name"); + if (vName.isValid()) + newVersion.name = vName.value.value(); else continue; - const QVariant vPath = version->property("path"); - if (!vPath.isNull() && vPath.isValid()) - newVersion.fileName = vPath.value(); + const auto vPath = version->property("path"); + if (vPath.isValid()) + newVersion.fileName = vPath.value.value(); else continue; m_versionsList.push_back(newVersion); - if (vId == defaultVersion) + if (vId.value == defaultVersion.value) m_defaultVersion = newVersion; } } @@ -172,10 +173,10 @@ void DesignerMcuManager::readVersionData(const DesignerMcuManager::Version &vers if (child->propertyNames().contains("allowedProperties")) { ItemProperties allowedProperties; - const QVariant childrenPropertyVar = child->property("allowChildren"); + const auto childrenPropertyVar = child->property("allowChildren"); - if (!childrenPropertyVar.isNull() && childrenPropertyVar.isValid()) - allowedProperties.allowChildren = childrenPropertyVar.toBool(); + if (childrenPropertyVar.isValid()) + allowedProperties.allowChildren = childrenPropertyVar.value.toBool(); allowedProperties.properties = readPropertyList("allowedProperties", child); diff --git a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp index 546e9120003..53c76263a2f 100644 --- a/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/qmlprojectfileformat.cpp @@ -39,24 +39,30 @@ namespace { QmlProjectManager::FileFilterBaseItem *setupFileFilterItem(QmlProjectManager::FileFilterBaseItem *fileFilterItem, const QmlJS::SimpleReaderNode::Ptr &node) { - const QVariant directoryProperty = node->property(QLatin1String("directory")); + const auto directoryProperty = node->property(QLatin1String("directory")); if (directoryProperty.isValid()) - fileFilterItem->setDirectory(directoryProperty.toString()); + fileFilterItem->setDirectory(directoryProperty.value.toString()); - const QVariant recursiveProperty = node->property(QLatin1String("recursive")); + const auto recursiveProperty = node->property(QLatin1String("recursive")); if (recursiveProperty.isValid()) - fileFilterItem->setRecursive(recursiveProperty.toBool()); + fileFilterItem->setRecursive(recursiveProperty.value.toBool()); - const QVariant pathsProperty = node->property(QLatin1String("paths")); + const auto pathsProperty = node->property(QLatin1String("paths")); if (pathsProperty.isValid()) - fileFilterItem->setPathsProperty(pathsProperty.toStringList()); + fileFilterItem->setPathsProperty(pathsProperty.value.toStringList()); - const QVariant filterProperty = node->property(QLatin1String("filter")); + // "paths" and "files" have the same functionality + const auto filesProperty = node->property(QLatin1String("files")); + if (filesProperty.isValid()) + fileFilterItem->setPathsProperty(filesProperty.value.toStringList()); + + const auto filterProperty = node->property(QLatin1String("filter")); if (filterProperty.isValid()) - fileFilterItem->setFilter(filterProperty.toString()); + fileFilterItem->setFilter(filterProperty.value.toString()); if (debug) - qDebug() << "directory:" << directoryProperty << "recursive" << recursiveProperty << "paths" << pathsProperty; + qDebug() << "directory:" << directoryProperty.value << "recursive" << recursiveProperty.value + << "paths" << pathsProperty.value << "files" << filesProperty.value; return fileFilterItem; } @@ -81,36 +87,36 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi if (rootNode->name() == QLatin1String("Project")) { auto projectItem = new QmlProjectItem; - const QVariant mainFileProperty = rootNode->property(QLatin1String("mainFile")); + const auto mainFileProperty = rootNode->property(QLatin1String("mainFile")); if (mainFileProperty.isValid()) - projectItem->setMainFile(mainFileProperty.toString()); + projectItem->setMainFile(mainFileProperty.value.toString()); - const QVariant importPathsProperty = rootNode->property(QLatin1String("importPaths")); + const auto importPathsProperty = rootNode->property(QLatin1String("importPaths")); if (importPathsProperty.isValid()) - projectItem->setImportPaths(importPathsProperty.toStringList()); + projectItem->setImportPaths(importPathsProperty.value.toStringList()); - const QVariant fileSelectorsProperty = rootNode->property(QLatin1String("fileSelectors")); + const auto fileSelectorsProperty = rootNode->property(QLatin1String("fileSelectors")); if (fileSelectorsProperty.isValid()) - projectItem->setFileSelectors(fileSelectorsProperty.toStringList()); + projectItem->setFileSelectors(fileSelectorsProperty.value.toStringList()); - const QVariant forceFreeTypeProperty = rootNode->property("forceFreeType"); + const auto forceFreeTypeProperty = rootNode->property("forceFreeType"); if (forceFreeTypeProperty.isValid()) - projectItem->setForceFreeType(forceFreeTypeProperty.toBool()); + projectItem->setForceFreeType(forceFreeTypeProperty.value.toBool()); - const QVariant targetDirectoryPropery = rootNode->property("targetDirectory"); + const auto targetDirectoryPropery = rootNode->property("targetDirectory"); if (targetDirectoryPropery.isValid()) - projectItem->setTargetDirectory(targetDirectoryPropery.toString()); + projectItem->setTargetDirectory(targetDirectoryPropery.value.toString()); - const QVariant qtForMCUProperty = rootNode->property("qtForMCUs"); - if (qtForMCUProperty.isValid() && qtForMCUProperty.toBool()) - projectItem->setQtForMCUs(qtForMCUProperty.toBool()); + const auto qtForMCUProperty = rootNode->property("qtForMCUs"); + if (qtForMCUProperty.isValid() && qtForMCUProperty.value.toBool()) + projectItem->setQtForMCUs(qtForMCUProperty.value.toBool()); - const QVariant qt6ProjectProperty = rootNode->property("qt6Project"); - if (qt6ProjectProperty.isValid() && qt6ProjectProperty.toBool()) - projectItem->setQt6Project(qt6ProjectProperty.toBool()); + const auto qt6ProjectProperty = rootNode->property("qt6Project"); + if (qt6ProjectProperty.isValid() && qt6ProjectProperty.value.toBool()) + projectItem->setQt6Project(qt6ProjectProperty.value.toBool()); if (debug) - qDebug() << "importPath:" << importPathsProperty << "mainFile:" << mainFileProperty; + qDebug() << "importPath:" << importPathsProperty.value << "mainFile:" << mainFileProperty.value; foreach (const QmlJS::SimpleReaderNode::Ptr &childNode, rootNode->children()) { if (debug) @@ -132,7 +138,7 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi const auto properties = childNode->properties(); auto i = properties.constBegin(); while (i != properties.constEnd()) { - projectItem->addToEnviroment(i.key(), i.value().toString()); + projectItem->addToEnviroment(i.key(), i.value().value.toString()); ++i; } } else { diff --git a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp index 084a750258c..c8c81453197 100644 --- a/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp +++ b/tests/auto/qml/qmldesigner/coretests/tst_testcore.cpp @@ -8546,14 +8546,14 @@ static void checkNode(QmlJS::SimpleReaderNode::Ptr node, TestRewriterView *view) { QVERIFY(node); QVERIFY(node->propertyNames().contains("i")); - const int internalId = node->property("i").toInt(); + const int internalId = node->property("i").value.toInt(); const ModelNode modelNode = view->modelNodeForInternalId(internalId); QVERIFY(modelNode.isValid()); auto properties = node->properties(); for (auto i = properties.begin(); i != properties.end(); ++i) { if (i.key() != "i") - QCOMPARE(i.value(), modelNode.auxiliaryData(i.key().toUtf8())); + QCOMPARE(i.value().value, modelNode.auxiliaryData(i.key().toUtf8())); } checkChildNodes(node, view); diff --git a/tests/auto/qml/qmljssimplereader/tst_qmljssimplereader.cpp b/tests/auto/qml/qmljssimplereader/tst_qmljssimplereader.cpp index a17ef2d993e..128bc14c6bc 100644 --- a/tests/auto/qml/qmljssimplereader/tst_qmljssimplereader.cpp +++ b/tests/auto/qml/qmljssimplereader/tst_qmljssimplereader.cpp @@ -77,13 +77,13 @@ void tst_SimpleReader::testWellFormed() QCOMPARE(rootNode->properties().count(), 1); QVERIFY(rootNode->properties().contains("propertyBlah")); - QCOMPARE(rootNode->property("property01").toBool(), false); + QCOMPARE(rootNode->property("property01").value.toBool(), false); QVERIFY(rootNode->children().first()->isValid()); QVERIFY(!rootNode->children().first()->isRoot()); QVERIFY(rootNode->children().first()->properties().contains("property01")); - QCOMPARE(rootNode->children().first()->property("property01").toInt(), 10); + QCOMPARE(rootNode->children().first()->property("property01").value.toInt(), 10); SimpleReaderNode::Ptr secondChild = rootNode->children().at(1); @@ -93,7 +93,7 @@ void tst_SimpleReader::testWellFormed() QCOMPARE(secondChild->name(), QLatin1String("ChildNode")); QVERIFY(secondChild->properties().contains("propertyString")); - QCOMPARE(secondChild->property("propertyString").toString(), QLatin1String("str")); + QCOMPARE(secondChild->property("propertyString").value.toString(), QLatin1String("str")); QCOMPARE(secondChild->children().count(), 1); @@ -105,7 +105,7 @@ void tst_SimpleReader::testWellFormed() QCOMPARE(innerChild->name(), QLatin1String("InnerChild")); QVERIFY(innerChild->properties().contains("test")); - QCOMPARE(innerChild->property("test").toString(), QLatin1String("test")); + QCOMPARE(innerChild->property("test").value.toString(), QLatin1String("test")); weak01 = rootNode; weak02 = secondChild; @@ -170,7 +170,7 @@ void tst_SimpleReader::testIllFormed02() QCOMPARE(firstChild->properties().count(), 1); QVERIFY(firstChild->properties().contains("property01")); - QCOMPARE(firstChild->property("property01").toString(), QLatin1String("20")); + QCOMPARE(firstChild->property("property01").value.toString(), QLatin1String("20")); } void tst_SimpleReader::testArrays() @@ -194,7 +194,7 @@ void tst_SimpleReader::testArrays() QVERIFY(rootNode->isValid()); QVERIFY(rootNode->isRoot()); - QCOMPARE(rootNode->property("propertyArray"), variant); + QCOMPARE(rootNode->property("propertyArray").value, variant); SimpleReaderNode::Ptr firstChild = rootNode->children().at(0); @@ -202,13 +202,13 @@ void tst_SimpleReader::testArrays() QVERIFY(firstChild); QVERIFY(firstChild->isValid()); QVERIFY(!firstChild->isRoot()); - QCOMPARE(firstChild->property("propertyArray"), variant); + QCOMPARE(firstChild->property("propertyArray").value, variant); QList variantList2; variantList2 << QVariant(QLatin1String("string03")) << variant; const QVariant variant2 = variantList2; - QCOMPARE(firstChild->property("propertyArrayMixed"), variant2); + QCOMPARE(firstChild->property("propertyArrayMixed").value, variant2); } void tst_SimpleReader::testBug01() From 258b4f7c23d8fc8ec8a30d05a7a9f0a2e34392e2 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 29 Sep 2021 12:07:22 +0200 Subject: [PATCH 14/15] Show useful root directory when opening File System view Show the active project's root directory. Fixes: QTCREATORBUG-26297 Change-Id: Id66131582484e6d8d58ee67226bc1123609e5a7c Reviewed-by: Cristian Adam --- src/plugins/projectexplorer/foldernavigationwidget.cpp | 8 ++++++++ src/plugins/projectexplorer/foldernavigationwidget.h | 5 +++++ src/plugins/projectexplorer/session.cpp | 2 ++ 3 files changed, 15 insertions(+) diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 93c7f03265b..ee9a53cb90d 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -98,6 +98,7 @@ static FolderNavigationWidgetFactory *m_instance = nullptr; QVector FolderNavigationWidgetFactory::m_rootDirectories; +Utils::FilePath FolderNavigationWidgetFactory::m_fallbackSyncFilePath; static QWidget *createHLine() { @@ -893,6 +894,8 @@ Core::NavigationView FolderNavigationWidgetFactory::createWidget() &FolderNavigationWidgetFactory::rootDirectoryRemoved, fnw, &FolderNavigationWidget::removeRootDirectory); + if (!Core::EditorManager::currentDocument() && !m_fallbackSyncFilePath.isEmpty()) + fnw->syncWithFilePath(m_fallbackSyncFilePath); Core::NavigationView n; n.widget = fnw; @@ -965,6 +968,11 @@ void FolderNavigationWidgetFactory::removeRootDirectory(const QString &id) emit m_instance->rootDirectoryRemoved(id); } +void FolderNavigationWidgetFactory::setFallbackSyncFilePath(const FilePath &filePath) +{ + m_fallbackSyncFilePath = filePath; +} + int FolderNavigationWidgetFactory::rootIndex(const QString &id) { return Utils::indexOf(m_rootDirectories, diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h index b39f073b4b8..06fef602256 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.h +++ b/src/plugins/projectexplorer/foldernavigationwidget.h @@ -77,6 +77,10 @@ public: static void insertRootDirectory(const RootDirectory &directory); static void removeRootDirectory(const QString &id); + static void setFallbackSyncFilePath(const Utils::FilePath &filePath); + + static const Utils::FilePath &fallbackSyncFilePath(); + signals: void rootDirectoryAdded(const RootDirectory &directory); void rootDirectoryRemoved(const QString &id); @@ -87,6 +91,7 @@ private: void registerActions(); static QVector m_rootDirectories; + static Utils::FilePath m_fallbackSyncFilePath; }; class FolderNavigationWidget : public QWidget diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 1c7f33d6e5a..32b72b8508d 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -386,6 +386,8 @@ void SessionManager::setStartupProject(Project *startupProject) ModeManager::activateMode(Constants::MODE_SESSION); ModeManager::setFocusToCurrentMode(); } + FolderNavigationWidgetFactory::setFallbackSyncFilePath( + startupProject ? startupProject->projectFilePath().parentDir() : FilePath()); emit m_instance->startupProjectChanged(startupProject); } From 19ce3e91bb8c723a3a9f9f94c1f7ad3aa2ce662e Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 29 Sep 2021 09:50:29 +0200 Subject: [PATCH 15/15] Select project root when opening File System tree with project directory When choosing "Show in File System View" from the context menu of a project root node in Projects view, the File System view should show the project root directly, not the project directory as a child in the "Home" or "Computer" directories. Change-Id: Id2d5794cf747fd6b52289f6d08ef14ef18cd2dd4 Reviewed-by: Cristian Adam --- src/plugins/projectexplorer/foldernavigationwidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index ee9a53cb90d..988d77eba57 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -654,7 +654,8 @@ int FolderNavigationWidget::bestRootForFile(const Utils::FilePath &filePath) int commonLength = 0; for (int i = 1; i < m_rootSelector->count(); ++i) { const auto root = m_rootSelector->itemData(i).value(); - if (filePath.isChildOf(root) && root.toString().size() > commonLength) { + if ((filePath == root || filePath.isChildOf(root)) + && root.toString().size() > commonLength) { index = i; commonLength = root.toString().size(); }