From 391e7ae34abcffb792a15d0938132eec348326fa Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 29 May 2024 12:25:31 +0200 Subject: [PATCH] Wizards: Redo sub project handling If the user tries to add a sub project the decision for the parent project must happen directly on the intro page to avoid asking for build system or kit information later on. Any of these information are provided by the parent project and can therefore be skipped in case of having a sub project. So, move this decision to the first page and on the last page only let the user decide to which sub node of the chosen project the new project will be added to. The old approach set the IsSubproject marker quite too late to handle this appropriate, so explicitly set this already on the first page. For now there should be only qmake based projects which are capable of adding sub projects at all, but this patch should be a generalized preparation for having similar functionality in other build systems. Fixes: QTCREATORBUG-30281 Change-Id: I8f1de4fa05f46d68ac2ddec788840d473adb015e Reviewed-by: Marcus Tillmanns --- ...eator-projects-custom-wizards-json.qdocinc | 20 ++- .../wizards/autotest/boosttest/wizard.json | 7 +- .../wizards/autotest/catch/wizard.json | 7 +- .../wizards/autotest/gtest/wizard.json | 7 +- .../wizards/autotest/qttest/wizard.json | 7 +- .../wizards/autotest/quicktest/wizard.json | 7 +- .../templates/wizards/codesnippet/wizard.json | 1 - .../wizards/projects/consoleapp/wizard.json | 3 +- .../wizards/projects/cpplibrary/wizard.json | 3 +- .../wizards/projects/nim/wizard.json | 1 - .../wizards/projects/nimble/wizard.json | 1 - .../wizards/projects/plainc/wizard.json | 5 +- .../wizards/projects/plaincpp/wizard.json | 5 +- .../wizards/projects/qmake/empty/wizard.json | 4 +- .../projects/qtquick2-extension/wizard.json | 5 +- .../projects/qtquickapplication/wizard.json | 1 - .../empty/wizard.json | 3 +- .../projects/qtquickuiprototype/wizard.json | 1 - .../projects/qtwidgetsapplication/wizard.json | 3 +- .../wizards/qtcreatorplugin/wizard.json | 3 +- src/libs/utils/projectintropage.cpp | 76 +++++++---- src/libs/utils/projectintropage.h | 16 ++- src/libs/utils/wizard.cpp | 1 - src/plugins/lua/wizards/plugin/wizard.json | 1 - .../wizards/application/wizard.json | 1 - .../wizards/qmlproject-empty/wizard.json | 1 - .../mcusupport/wizards/qmlproject/wizard.json | 1 - .../baseprojectwizarddialog.cpp | 15 --- .../projectexplorer/baseprojectwizarddialog.h | 3 - .../jsonwizard/jsonprojectpage.cpp | 123 +++++++++++++++++- .../jsonwizard/jsonprojectpage.h | 3 + .../jsonwizard/jsonsummarypage.cpp | 12 +- .../jsonwizard/jsonwizardfactory.cpp | 6 + .../jsonwizard/jsonwizardfactory.h | 1 + .../jsonwizard/jsonwizardpagefactory.h | 1 + .../jsonwizard/jsonwizardpagefactory_p.cpp | 1 + .../projectexplorer/projectexplorer.cpp | 2 + .../projectexplorerconstants.h | 2 + .../projectfilewizardextension.cpp | 4 +- .../projectexplorer/projectwizardpage.cpp | 14 +- .../projectexplorer/projectwizardpage.h | 3 +- .../wizards/subdirsprojectwizard.cpp | 1 + .../saferenderer/wizards/qsrapp/wizard.json | 3 +- .../wizards/qsrapp2_1/wizard.json | 5 +- 44 files changed, 262 insertions(+), 128 deletions(-) diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards-json.qdocinc b/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards-json.qdocinc index f2d8d254249..eacf816822d 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards-json.qdocinc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-custom-wizards-json.qdocinc @@ -299,7 +299,13 @@ It is automatically assigned if you do not set it. \li \c enabled is set to \c true to show the page and to - \c false to hide it. + \c false to hide it. This is evaluated only once at + the time of creating the respective wizard. + + \li \c skipForSubprojects can be used to skip a page of the + wizard. Useful for e.g. handling of build information. + This is evaluated only once at the time of creating the + respective wizard page. \li \c data specifies the wizard pages. In the C++ wizard, it specifies a \c Fields page and a \c Summary page. The @@ -482,7 +488,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{IsTopLevelProject}", "data": { "projectFilePath": "%{ProFileName}" } }, \endcode @@ -490,7 +495,9 @@ The page evaluates \c {%\{Platform\}} to set the platform selected in \uicontrol File > \uicontrol {New Project} or \uicontrol {New File}. - + \note This page sets \c skipForSubprojects to \c true to suppress + the page in case it is not needed, as sub projects derive this information + from their parent project. \section2 Project @@ -511,6 +518,9 @@ The page evaluates \c InitialPath to set the initial project path. The page sets \c ProjectDirectory and \c TargetPath to the project directory. + Furthermore the page sets \c IsSubproject to true if the project is + explicitly added to another project. In this case \c BuildSystem will be set + to the build system of the parent project. \section2 Summary @@ -525,8 +535,8 @@ } \endcode - The page sets \c IsSubproject to an empty string if this is a top-level - project and to \c yes otherwise. It sets \c VersionControl to the ID of the + The page sets \c IsSubproject to \c false if this is a top-level + project and to \c true otherwise. It sets \c VersionControl to the ID of the version control system in use. \section2 VcsCommand diff --git a/share/qtcreator/templates/wizards/autotest/boosttest/wizard.json b/share/qtcreator/templates/wizards/autotest/boosttest/wizard.json index 01b79081268..525752701e5 100644 --- a/share/qtcreator/templates/wizards/autotest/boosttest/wizard.json +++ b/share/qtcreator/templates/wizards/autotest/boosttest/wizard.json @@ -26,9 +26,6 @@ "key": "CMakeFileName", "value": "%{ProjectDirectory}/CMakeLists.txt" }, - { "key": "IsTopLevelProject", - "value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}' }" - }, { "key": "MainCppName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src') }" }, @@ -118,6 +115,7 @@ "trDisplayName": "Build system:", "type": "ComboBox", "persistenceKey": "BuildSystemType", + "visible": "%{JS: !value('IsSubproject')}", "data": { "index": 1, @@ -147,7 +145,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{IsTopLevelProject}", "data": { "projectFilePath": "%{ProjectFilePath}", "requiredFeatures": [ "%{JS: value('BuildSystem') === 'qmake' ? 'QtSupport.Wizards.FeatureQt' : 'DeviceType.Desktop' }" ] @@ -199,7 +196,7 @@ { "source": "../../projects/git.ignore", "target": ".gitignore", - "condition": "%{JS: ( %{IsTopLevelProject} && value('VersionControl') === 'G.Git' )}" + "condition": "%{JS: ( !value('IsSubproject') && value('VersionControl') === 'G.Git' )}" } ] } diff --git a/share/qtcreator/templates/wizards/autotest/catch/wizard.json b/share/qtcreator/templates/wizards/autotest/catch/wizard.json index 1aa35ed0ec3..03ee5ff68ff 100644 --- a/share/qtcreator/templates/wizards/autotest/catch/wizard.json +++ b/share/qtcreator/templates/wizards/autotest/catch/wizard.json @@ -26,9 +26,6 @@ "key": "CMakeFileName", "value": "%{ProjectDirectory}/CMakeLists.txt" }, - { "key": "IsTopLevelProject", - "value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}' }" - }, { "key": "MainCppName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src') }" }, @@ -128,6 +125,7 @@ "trDisplayName": "Build system:", "type": "ComboBox", "persistenceKey": "BuildSystemType", + "visible": "%{JS: !value('IsSubproject')}", "data": { "index": 1, @@ -157,7 +155,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{IsTopLevelProject}", "data": { "projectFilePath": "%{ProjectFilePath}", "requiredFeatures": [ "%{JS: (value('Catch2NeedsQt') == 'true' || value('BuildSystem') === 'qmake') ? 'QtSupport.Wizards.FeatureQt' : 'DeviceType.Desktop' }" ] @@ -222,7 +219,7 @@ { "source": "../../projects/git.ignore", "target": ".gitignore", - "condition": "%{JS: ( %{IsTopLevelProject} && value('VersionControl') === 'G.Git' )}" + "condition": "%{JS: ( !value('IsSubproject') && value('VersionControl') === 'G.Git' )}" } ] } diff --git a/share/qtcreator/templates/wizards/autotest/gtest/wizard.json b/share/qtcreator/templates/wizards/autotest/gtest/wizard.json index 7d8b88b552e..643dd95f0ab 100644 --- a/share/qtcreator/templates/wizards/autotest/gtest/wizard.json +++ b/share/qtcreator/templates/wizards/autotest/gtest/wizard.json @@ -26,9 +26,6 @@ "key": "CMakeFileName", "value": "%{ProjectDirectory}/CMakeLists.txt" }, - { "key": "IsTopLevelProject", - "value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}' }" - }, { "key": "MainCppName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src') }" }, @@ -122,6 +119,7 @@ "trDisplayName": "Build system:", "type": "ComboBox", "persistenceKey": "BuildSystemType", + "visible": "%{JS: !value('IsSubproject')}", "data": { "index": 1, @@ -151,7 +149,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{IsTopLevelProject}", "data": { "projectFilePath": "%{ProjectFilePath}", "requiredFeatures": [ "%{JS: value('BuildSystem') === 'qmake' ? 'QtSupport.Wizards.FeatureQt' : 'DeviceType.Desktop' }" ] @@ -215,7 +212,7 @@ { "source": "../../projects/git.ignore", "target": ".gitignore", - "condition": "%{JS: ( %{IsTopLevelProject} && value('VersionControl') === 'G.Git' )}" + "condition": "%{JS: ( !value('IsSubproject') && value('VersionControl') === 'G.Git' )}" } ] } diff --git a/share/qtcreator/templates/wizards/autotest/qttest/wizard.json b/share/qtcreator/templates/wizards/autotest/qttest/wizard.json index 0236a24a5ab..e9b0a782c47 100644 --- a/share/qtcreator/templates/wizards/autotest/qttest/wizard.json +++ b/share/qtcreator/templates/wizards/autotest/qttest/wizard.json @@ -29,9 +29,6 @@ "key": "CMakeFileName", "value": "%{ProjectDirectory}/CMakeLists.txt" }, - { "key": "IsTopLevelProject", - "value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}' }" - }, { "key": "GUARD", "value": "%{JS: value('TestCaseFileWithHeaderSuffix').toUpperCase().replace('.', '_') }" @@ -95,6 +92,7 @@ "trDisplayName": "Build system:", "type": "ComboBox", "persistenceKey": "BuildSystemType", + "visible": "%{JS: !value('IsSubproject')}", "data": { "index": 1, @@ -124,7 +122,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{IsTopLevelProject}", "data": { "projectFilePath": "%{ProjectFilePath}", "requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "DeviceType.Desktop" ] @@ -171,7 +168,7 @@ { "source": "../../projects/git.ignore", "target": ".gitignore", - "condition": "%{JS: ( %{IsTopLevelProject} && value('VersionControl') === 'G.Git' )}" + "condition": "%{JS: ( !value('IsSubproject') && value('VersionControl') === 'G.Git' )}" } ] } diff --git a/share/qtcreator/templates/wizards/autotest/quicktest/wizard.json b/share/qtcreator/templates/wizards/autotest/quicktest/wizard.json index bbcf7c41479..a5411c61b1b 100644 --- a/share/qtcreator/templates/wizards/autotest/quicktest/wizard.json +++ b/share/qtcreator/templates/wizards/autotest/quicktest/wizard.json @@ -29,9 +29,6 @@ "key": "CMakeFileName", "value": "%{ProjectDirectory}/CMakeLists.txt" }, - { "key": "IsTopLevelProject", - "value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}' }" - }, { "key": "MainCppName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src') }" }, @@ -90,6 +87,7 @@ "trDisplayName": "Build system:", "type": "ComboBox", "persistenceKey": "BuildSystemType", + "visible": "%{JS: !value('IsSubproject')}", "data": { "index": 1, @@ -119,7 +117,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{IsTopLevelProject}", "data": { "projectFilePath": "%{ProjectFilePath}", "requiredFeatures": [ "QtSupport.Wizards.FeatureQtQuick.2", "DeviceType.Desktop" ] @@ -183,7 +180,7 @@ { "source": "../../projects/git.ignore", "target": ".gitignore", - "condition": "%{JS: ( %{IsTopLevelProject} && value('VersionControl') === 'G.Git' )}" + "condition": "%{JS: ( !value('IsSubproject') && value('VersionControl') === 'G.Git' )}" } ] } diff --git a/share/qtcreator/templates/wizards/codesnippet/wizard.json b/share/qtcreator/templates/wizards/codesnippet/wizard.json index ddcd41295fc..e5ba8bbdc73 100644 --- a/share/qtcreator/templates/wizards/codesnippet/wizard.json +++ b/share/qtcreator/templates/wizards/codesnippet/wizard.json @@ -78,7 +78,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" diff --git a/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json b/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json index 1817b79d938..5e99f262b19 100644 --- a/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json +++ b/share/qtcreator/templates/wizards/projects/consoleapp/wizard.json @@ -34,7 +34,7 @@ "trDisplayName": "Define Build System", "trShortTitle": "Build System", "typeId": "Fields", - "enabled": "%{JS: !value('IsSubproject')}", + "skipForSubprojects": true, "data": [ { @@ -81,7 +81,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" } }, { diff --git a/share/qtcreator/templates/wizards/projects/cpplibrary/wizard.json b/share/qtcreator/templates/wizards/projects/cpplibrary/wizard.json index 39a25fa2f63..5bb6749fee6 100644 --- a/share/qtcreator/templates/wizards/projects/cpplibrary/wizard.json +++ b/share/qtcreator/templates/wizards/projects/cpplibrary/wizard.json @@ -49,7 +49,7 @@ "trDisplayName": "Define Build System", "trShortTitle": "Build System", "typeId": "Fields", - "enabled": "%{JS: !value('IsSubproject')}", + "skipForSubprojects": true, "data": [ { @@ -290,7 +290,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" } }, { diff --git a/share/qtcreator/templates/wizards/projects/nim/wizard.json b/share/qtcreator/templates/wizards/projects/nim/wizard.json index 68970d4d9ac..6a84ca3d463 100644 --- a/share/qtcreator/templates/wizards/projects/nim/wizard.json +++ b/share/qtcreator/templates/wizards/projects/nim/wizard.json @@ -29,7 +29,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" } }, { diff --git a/share/qtcreator/templates/wizards/projects/nimble/wizard.json b/share/qtcreator/templates/wizards/projects/nimble/wizard.json index 8a0a14b8304..657aad71bb7 100644 --- a/share/qtcreator/templates/wizards/projects/nimble/wizard.json +++ b/share/qtcreator/templates/wizards/projects/nimble/wizard.json @@ -177,7 +177,6 @@ "trDisplayName":"Kit Selection", "trShortTitle":"Kits", "typeId":"Kits", - "enabled":"%{JS: !value('IsSubproject')}", "data":{ "projectFilePath":"%{ProjectFile}" } diff --git a/share/qtcreator/templates/wizards/projects/plainc/wizard.json b/share/qtcreator/templates/wizards/projects/plainc/wizard.json index c2814ac9473..a0d3bf3ec20 100644 --- a/share/qtcreator/templates/wizards/projects/plainc/wizard.json +++ b/share/qtcreator/templates/wizards/projects/plainc/wizard.json @@ -1,6 +1,6 @@ { "version": 1, - "supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ], + "supportedProjectTypes": [ "MesonProjectManager.MesonProject", "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ], "id": "A.Plain C Application", "category": "I.Projects", "trDescription": "Creates a simple C application with no dependencies.", @@ -31,7 +31,7 @@ "trDisplayName": "Define Build System", "trShortTitle": "Build System", "typeId": "Fields", - "enabled": "%{JS: !value('IsSubproject')}", + "skipForSubprojects": true, "data": [ { @@ -73,7 +73,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" } }, { diff --git a/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json b/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json index 0e1ca061dc8..cffdb7bb78d 100644 --- a/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json +++ b/share/qtcreator/templates/wizards/projects/plaincpp/wizard.json @@ -1,6 +1,6 @@ { "version": 1, - "supportedProjectTypes": [ "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ], + "supportedProjectTypes": [ "MesonProjectManager.MesonProject", "CMakeProjectManager.CMakeProject", "Qbs.QbsProject", "Qt4ProjectManager.Qt4Project" ], "id": "R.Plain Cpp Application", "category": "I.Projects", "trDescription": "Creates a simple C++ application with no dependencies.", @@ -31,7 +31,7 @@ "trDisplayName": "Define Build System", "trShortTitle": "Build System", "typeId": "Fields", - "enabled": "%{JS: ! %{IsSubproject}}", + "skipForSubprojects": true, "data": [ { @@ -73,7 +73,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: ! %{IsSubproject}}", "data": { "projectFilePath": "%{ProjectFile}" } }, { diff --git a/share/qtcreator/templates/wizards/projects/qmake/empty/wizard.json b/share/qtcreator/templates/wizards/projects/qmake/empty/wizard.json index 1c449e0c0d3..c43a6deffc5 100644 --- a/share/qtcreator/templates/wizards/projects/qmake/empty/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qmake/empty/wizard.json @@ -13,7 +13,6 @@ "options": [ { "key": "ProFileName", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" }, - { "key": "IsTopLevelProject", "value": "%{JS: !value('Exists:ProjectExplorer.Profile.Ids')}" } ], "pages": @@ -28,7 +27,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{IsTopLevelProject}", "data": { "projectFilePath": "%{ProFileName}" } }, { @@ -52,7 +50,7 @@ { "source": "../../git.ignore", "target": "%{ProjectDirectory}/.gitignore", - "condition": "%{JS: value('IsTopLevelProject') && value('VersionControl') === 'G.Git'}" + "condition": "%{JS: !value('IsSubproject') && value('VersionControl') === 'G.Git'}" } ] } diff --git a/share/qtcreator/templates/wizards/projects/qtquick2-extension/wizard.json b/share/qtcreator/templates/wizards/projects/qtquick2-extension/wizard.json index d12edc4576d..c2692ee641e 100644 --- a/share/qtcreator/templates/wizards/projects/qtquick2-extension/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtquick2-extension/wizard.json @@ -1,6 +1,6 @@ { "version": 1, - "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ], + "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project", "CMakeProjectManager.CMakeProject" ], "id": "M.QtQuick2ExtensionPlugin", "category": "G.Library", "trDescription": "Creates a C++ plugin to load Qt Quick extensions dynamically into applications using the QQmlEngine class.", @@ -43,7 +43,7 @@ "trDisplayName": "Define Build System", "trShortTitle": "Build System", "typeId": "Fields", - "enabled": "%{JS: !value('IsSubproject')}", + "skipForSubprojects": true, "data": [ { @@ -173,7 +173,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}", "requiredFeatures": [ "QtSupport.Wizards.FeatureQtQuick", "%{QtQuickFeature}" ] diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json index 2e885c2bb63..ac1d5dec91e 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json @@ -96,7 +96,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}", "requiredFeatures": [ "QtSupport.Wizards.FeatureQtQmlCMakeApi", "%{FeatureQt}" ] diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication_compat/empty/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication_compat/empty/wizard.json index c2365108daa..d721e0e6191 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication_compat/empty/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication_compat/empty/wizard.json @@ -42,7 +42,7 @@ "trDisplayName": "Define Build System", "trShortTitle": "Build System", "typeId": "Fields", - "enabled": "%{JS: !value('IsSubproject')}", + "skipForSubprojects": true, "data": [ { @@ -165,7 +165,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}", "requiredFeatures": [ "QtSupport.Wizards.FeatureQt", "%{QtQuickFeature}" ] diff --git a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json index 251500b4949..f8d9373e69d 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtquickuiprototype/wizard.json @@ -46,7 +46,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: ! %{IsSubproject}}", "data": { "projectFilePath": "%{QmlProjectFileName}", "requiredFeatures": [ "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQtQuick.6" ] diff --git a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json index 48791e4fd87..b2b0528fd5f 100644 --- a/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtwidgetsapplication/wizard.json @@ -37,7 +37,7 @@ "trDisplayName": "Define Build System", "trShortTitle": "Build System", "typeId": "Fields", - "enabled": "%{JS: !value('IsSubproject')}", + "skipForSubprojects": true, "data": [ { @@ -157,7 +157,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" } }, { diff --git a/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.json b/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.json index e1feaa53bbb..5b4c6cec604 100644 --- a/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.json +++ b/share/qtcreator/templates/wizards/qtcreatorplugin/wizard.json @@ -1,6 +1,6 @@ { "version": 1, - "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ], + "supportedProjectTypes": [ "CMakeProjectManager.CMakeProject" ], "id": "R.QtCreatorPlugin", "category": "G.Library", "trDescription": "Creates a custom Qt Creator plugin.", @@ -135,7 +135,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" } }, { diff --git a/src/libs/utils/projectintropage.cpp b/src/libs/utils/projectintropage.cpp index 2c8b43b66a4..abe00c9d487 100644 --- a/src/libs/utils/projectintropage.cpp +++ b/src/libs/utils/projectintropage.cpp @@ -3,6 +3,7 @@ #include "projectintropage.h" +#include "algorithm.h" #include "fancylineedit.h" #include "filenamevalidatinglineedit.h" #include "fileutils.h" @@ -52,7 +53,7 @@ public: QRegularExpressionValidator m_projectNameValidator; QString m_projectNameValidatorUserMessage; bool m_forceSubProject = false; - FilePaths m_projectDirectories; + QList m_projectInfos; QLabel *m_descriptionLabel; FancyLineEdit *m_nameLineEdit; @@ -81,12 +82,10 @@ ProjectIntroPage::ProjectIntroPage(QWidget *parent) : d->m_pathChooser = new Utils::PathChooser(frame); d->m_pathChooser->setObjectName("baseFolder"); // used by Squish d->m_pathChooser->setExpectedKind(PathChooser::Directory); - d->m_pathChooser->setDisabled(d->m_forceSubProject); d->m_pathChooser->setAllowPathFromDevice(true); d->m_projectsDirectoryCheckBox = new QCheckBox(Tr::tr("Use as default project location")); d->m_projectsDirectoryCheckBox->setObjectName("projectsDirectoryCheckBox"); - d->m_projectsDirectoryCheckBox->setDisabled(d->m_forceSubProject); d->m_projectComboBox = new QComboBox; d->m_projectComboBox->setVisible(d->m_forceSubProject); @@ -104,7 +103,7 @@ ProjectIntroPage::ProjectIntroPage(QWidget *parent) : return validateProjectName(edit->text(), errorString); }); - d->m_projectLabel = new QLabel("Project:"); + d->m_projectLabel = new QLabel(Tr::tr("Add to project:")); d->m_projectLabel->setVisible(d->m_forceSubProject); using namespace Layouting; @@ -200,6 +199,21 @@ bool ProjectIntroPage::validate() return false; } + // build system valid? + const QVariant bsVariant = property("BuildSystem"); + if (bsVariant.isValid()) { + const QStringList supportedProjectTypes = wizard()->property("SupportedProjectTypes").toStringList(); + if (!supportedProjectTypes.isEmpty()) { + const QVariant currentProjectsId = wizard()->property("NodeProjectId"); + if (currentProjectsId.isValid() + && !supportedProjectTypes.contains(currentProjectsId.toString())) { + displayStatusMessage(InfoLabel::Error, Tr::tr("Chosen project wizard does not " + "support the build system.")); + return false; + } + } + } + // Name valid? switch (d->m_nameLineEdit->state()) { case FancyLineEdit::Invalid: @@ -257,21 +271,29 @@ void ProjectIntroPage::slotActivated() void ProjectIntroPage::onCurrentProjectIndexChanged(int index) { - if (d->m_forceSubProject) { - const int available = d->m_projectDirectories.size(); - if (available == 0) - return; - QTC_ASSERT(index < available, return); - if (index < 0) - return; + const int available = d->m_projectInfos.size(); + if (available == 0) + return; + QTC_ASSERT(index < available, return); + if (index < 0) + return; - const FilePath current = d->m_projectDirectories.at(index); - const FilePath visible = d->m_pathChooser->filePath(); - if (visible != current && !visible.isChildOf(current)) - d->m_pathChooser->setFilePath(current); + d->m_forceSubProject = (index > 0); + const ProjectInfo info = d->m_projectInfos.at(index); + const FilePath current = info.projectDirectory; + const FilePath visible = d->m_pathChooser->filePath(); + if (visible != current && !visible.isChildOf(current)) + d->m_pathChooser->setFilePath(current); - fieldsUpdated(); - } + if (info.buildSystem.isEmpty()) + setProperty("BuildSystem", QVariant()); + else + setProperty("BuildSystem", info.buildSystem); + if (info.projectId.isValid()) + setProperty("NodeProjectId", info.projectId.toString()); + else + setProperty("NodeProjectId", QVariant()); + fieldsUpdated(); } bool ProjectIntroPage::forceSubProject() const @@ -284,24 +306,28 @@ void ProjectIntroPage::setForceSubProject(bool force) d->m_forceSubProject = force; d->m_projectLabel->setVisible(d->m_forceSubProject); d->m_projectComboBox->setVisible(d->m_forceSubProject); - d->m_pathChooser->setDisabled(d->m_forceSubProject); - d->m_projectsDirectoryCheckBox->setDisabled(d->m_forceSubProject); } -void ProjectIntroPage::setProjectList(const QStringList &projectList) +void ProjectIntroPage::setProjectInfos(const QList &projectInfos) { + // FIXME the current impl assumes a None item as first project info + d->m_projectInfos = projectInfos; d->m_projectComboBox->clear(); - d->m_projectComboBox->addItems(projectList); + d->m_projectComboBox->addItems(Utils::transform(projectInfos, &ProjectInfo::display)); } -void ProjectIntroPage::setProjectDirectories(const FilePaths &directoryList) +void ProjectIntroPage::setProjectIndex(int index) { - d->m_projectDirectories = directoryList; + d->m_projectComboBox->setCurrentIndex( + (index > d->m_projectComboBox->count() || index < 0) ? -1 : index); } -int ProjectIntroPage::projectIndex() const +ProjectIntroPage::ProjectInfo ProjectIntroPage::currentProjectInfo() const { - return d->m_projectComboBox->currentIndex(); + const int index = d->m_projectComboBox->currentIndex(); + if (index < 0 || index > d->m_projectInfos.size()) + return {}; + return d->m_projectInfos.at(index); } bool ProjectIntroPage::validateProjectName(const QString &name, QString *errorMessage) diff --git a/src/libs/utils/projectintropage.h b/src/libs/utils/projectintropage.h index 562b5b06e42..a43aee75406 100644 --- a/src/libs/utils/projectintropage.h +++ b/src/libs/utils/projectintropage.h @@ -6,6 +6,7 @@ #include "utils_global.h" #include "filepath.h" +#include "id.h" #include "infolabel.h" #include "wizardpage.h" @@ -33,9 +34,18 @@ public: bool forceSubProject() const; void setForceSubProject(bool force); - void setProjectList(const QStringList &projectList); - void setProjectDirectories(const FilePaths &directoryList); - int projectIndex() const; + + struct ProjectInfo + { + QString display; + FilePath projectDirectory; + FilePath projectFile; + QString buildSystem; + Utils::Id projectId; + }; + void setProjectInfos(const QList &projectInfos); + void setProjectIndex(int index); + ProjectInfo currentProjectInfo() const; bool validateProjectName(const QString &name, QString *errorMessage); diff --git a/src/libs/utils/wizard.cpp b/src/libs/utils/wizard.cpp index 29bfb787a6a..41e61ec2760 100644 --- a/src/libs/utils/wizard.cpp +++ b/src/libs/utils/wizard.cpp @@ -550,7 +550,6 @@ int Wizard::nextId() const return index; } } - QTC_CHECK(false); // should not happen return QWizard::nextId(); } diff --git a/src/plugins/lua/wizards/plugin/wizard.json b/src/plugins/lua/wizards/plugin/wizard.json index a295dc27d45..4846fdfccb3 100644 --- a/src/plugins/lua/wizards/plugin/wizard.json +++ b/src/plugins/lua/wizards/plugin/wizard.json @@ -109,7 +109,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" } diff --git a/src/plugins/mcusupport/wizards/application/wizard.json b/src/plugins/mcusupport/wizards/application/wizard.json index 370b88ce74d..7af2613943d 100644 --- a/src/plugins/mcusupport/wizards/application/wizard.json +++ b/src/plugins/mcusupport/wizards/application/wizard.json @@ -29,7 +29,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{CMakeFile}" } diff --git a/src/plugins/mcusupport/wizards/qmlproject-empty/wizard.json b/src/plugins/mcusupport/wizards/qmlproject-empty/wizard.json index 80f6439f4cd..44e5620d50a 100644 --- a/src/plugins/mcusupport/wizards/qmlproject-empty/wizard.json +++ b/src/plugins/mcusupport/wizards/qmlproject-empty/wizard.json @@ -29,7 +29,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{CMakeFile}" } diff --git a/src/plugins/mcusupport/wizards/qmlproject/wizard.json b/src/plugins/mcusupport/wizards/qmlproject/wizard.json index 4a5f582d432..ecdd45d9b87 100644 --- a/src/plugins/mcusupport/wizards/qmlproject/wizard.json +++ b/src/plugins/mcusupport/wizards/qmlproject/wizard.json @@ -35,7 +35,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{CMakeFile}" } diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp index ffd2e6def20..733034b28c9 100644 --- a/src/plugins/projectexplorer/baseprojectwizarddialog.cpp +++ b/src/plugins/projectexplorer/baseprojectwizarddialog.cpp @@ -101,21 +101,6 @@ void BaseProjectWizardDialog::setProjectName(const QString &name) d->introPage->setProjectName(name); } -void BaseProjectWizardDialog::setProjectList(const QStringList &projectList) -{ - d->introPage->setProjectList(projectList); -} - -void BaseProjectWizardDialog::setProjectDirectories(const FilePaths &directories) -{ - d->introPage->setProjectDirectories(directories); -} - -void BaseProjectWizardDialog::setForceSubProject(bool force) -{ - introPage()->setForceSubProject(force); -} - void BaseProjectWizardDialog::slotAccepted() { if (d->introPage->useAsDefaultPath()) { diff --git a/src/plugins/projectexplorer/baseprojectwizarddialog.h b/src/plugins/projectexplorer/baseprojectwizarddialog.h index 3d4fc2793b5..8cee34db556 100644 --- a/src/plugins/projectexplorer/baseprojectwizarddialog.h +++ b/src/plugins/projectexplorer/baseprojectwizarddialog.h @@ -44,9 +44,6 @@ public: void setIntroDescription(const QString &d); void setFilePath(const Utils::FilePath &path); void setProjectName(const QString &name); - void setProjectList(const QStringList &projectList); - void setProjectDirectories(const Utils::FilePaths &directories); - void setForceSubProject(bool force); signals: void projectParametersChanged(const QString &projectName, const Utils::FilePath &path); diff --git a/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp index a42833b6674..e2f2f1cf74a 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.cpp @@ -4,10 +4,18 @@ #include "jsonprojectpage.h" #include "jsonwizard.h" +#include "../buildsystem.h" +#include "../project.h" +#include "../projectexplorerconstants.h" #include "../projectexplorertr.h" +#include "../projectnodes.h" +#include "../projectmanager.h" +#include "../projecttree.h" +#include "../target.h" #include +#include #include #include @@ -18,6 +26,11 @@ using namespace Utils; namespace ProjectExplorer { +namespace { +constexpr char UserPreferredPath[] = "UserPreferredPath"; +constexpr char UserPreferredNode[] = "UserPreferredNode"; +} // anon namespace + JsonProjectPage::JsonProjectPage(QWidget *parent) : ProjectIntroPage(parent) { } @@ -26,7 +39,11 @@ void JsonProjectPage::initializePage() auto wiz = qobject_cast(wizard()); QTC_ASSERT(wiz, return); setFilePath(FilePath::fromString(wiz->stringValue(QLatin1String("InitialPath")))); - + if (wiz->value(QLatin1String(Constants::PROJECT_ENABLESUBPROJECT)).toBool()) { + initUiForSubProject(); + connect(ProjectTree::instance(), &ProjectTree::treeChanged, + this, &JsonProjectPage::initUiForSubProject); + } setProjectName(uniqueProjectName(filePath().toString())); } @@ -38,10 +55,40 @@ bool JsonProjectPage::validatePage() Core::DocumentManager::setUseProjectsDirectory(true); } + Wizard *wiz = qobject_cast(wizard()); + QTC_ASSERT(wiz, return ProjectIntroPage::validatePage()); + if (!forceSubProject()) { + wiz->setProperty(Constants::PROJECT_ISSUBPROJECT, false); + wiz->setProperty("BuildSystem", QVariant()); + wiz->setProperty(Constants::PROJECT_POINTER, QVariant()); + wiz->setProperty(Constants::PREFERRED_PROJECT_NODE, QVariant()); + wiz->setProperty(Constants::PREFERRED_PROJECT_NODE_PATH, QVariant()); + wiz->setSkipForSubprojects(false); + } else { + wiz->setProperty(Constants::PROJECT_ISSUBPROJECT, true); + const FilePath preferred = FilePath::fromVariant(property(UserPreferredPath)); + + ProjectIntroPage::ProjectInfo info = currentProjectInfo(); + Project *project = ProjectManager::projectWithProjectFilePath(info.projectFile); + wiz->setProperty("BuildSystem", info.buildSystem); + wiz->setProperty(Constants::PROJECT_POINTER, QVariant::fromValue(static_cast(project))); + // only if destination path and parent project hasn't changed keep original preferred + if (!preferred.isEmpty() && preferred == filePath()) { + wiz->setProperty(Constants::PREFERRED_PROJECT_NODE, property(UserPreferredNode)); + wiz->setProperty(Constants::PREFERRED_PROJECT_NODE_PATH, preferred.toVariant()); + } else { + wiz->setProperty(Constants::PREFERRED_PROJECT_NODE, + project ? QVariant::fromValue(static_cast(project->rootProjectNode())) + : QVariant()); + wiz->setProperty(Constants::PREFERRED_PROJECT_NODE_PATH, info.projectFile.toVariant()); + } + wiz->setSkipForSubprojects(true); + } + const FilePath target = filePath().pathAppended(projectName()); - wizard()->setProperty("ProjectDirectory", target.toString()); - wizard()->setProperty("TargetPath", target.toString()); + wiz->setProperty("ProjectDirectory", target.toString()); + wiz->setProperty("TargetPath", target.toString()); return Utils::ProjectIntroPage::validatePage(); } @@ -62,4 +109,74 @@ QString JsonProjectPage::uniqueProjectName(const QString &path) } } +// populate "Add to project" combo, gather build system info +void JsonProjectPage::initUiForSubProject() +{ + auto wiz = qobject_cast(wizard()); + QTC_ASSERT(wiz, return); + Node * contextNode = nullptr; + if (void *storedNode = property(UserPreferredNode).value()) { + // fixup stored contextNode / node path + Node *node = static_cast(storedNode); + if (auto p = ProjectManager::projectWithProjectFilePath(node->filePath())) + contextNode = p->rootProjectNode(); + } else { + contextNode = static_cast(wiz->value(Constants::PREFERRED_PROJECT_NODE).value()); + if (!contextNode) { + const QVariant prefProjPath = wiz->value(Constants::PREFERRED_PROJECT_NODE_PATH); + if (prefProjPath.isValid()) { + if (auto project = ProjectManager::projectWithProjectFilePath(FilePath::fromVariant(prefProjPath))) + contextNode = project->rootProjectNode(); + } + } + } + if (contextNode) { + const FilePath preferredPath = contextNode->filePath().parentDir(); + setProperty(UserPreferredPath, preferredPath.toVariant()); + setProperty(UserPreferredNode, QVariant::fromValue(static_cast(contextNode))); + setFilePath(preferredPath); + } + + const QList currentProjects = ProjectManager::projects(); + QList projectInfos; + projectInfos.append({Tr::tr("None"), Core::DocumentManager::projectsDirectory()}); + int index = -1; + int counter = 1; // we've added None already + for (const Project *proj : currentProjects) { + ProjectNode *rootNode = proj->rootProjectNode(); + if (!rootNode) + continue; + + const QList targets = proj->targets(); + const BuildSystem *bs = targets.isEmpty() ? nullptr : targets.first()->buildSystem(); + if (!bs) + continue; + if (bs->isParsing()) { + connect(bs, &BuildSystem::parsingFinished, this, &JsonProjectPage::initUiForSubProject, + Qt::UniqueConnection); + } + if (!rootNode->supportsAction(AddSubProject, rootNode)) + continue; + + ProjectInfo info; + info.projectFile = proj->projectFilePath(); + info.projectId = proj->id(); + info.projectDirectory = proj->rootProjectDirectory(); + info.display = rootNode->displayName() + " - " + proj->projectFilePath().toUserOutput(); + info.buildSystem = (bs ? bs->name() : ""); + if (contextNode && contextNode->getProject() == proj) + index = counter; + projectInfos.append(info); + ++counter; + } + + setProjectInfos(projectInfos); + if (index == -1) // if we fail to get a valid preferred parent project, avoid illegal access + index = 0; + wiz->setValue(QLatin1String("BuildSystem"), projectInfos.at(index).buildSystem); + wiz->setValue(QLatin1String("NodeProjectId"), projectInfos.at(index).projectId.toString()); + setProjectIndex(index); + setForceSubProject(true); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.h b/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.h index 2668b6e2702..e751594b74c 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.h +++ b/src/plugins/projectexplorer/jsonwizard/jsonprojectpage.h @@ -20,6 +20,9 @@ public: bool validatePage() override; static QString uniqueProjectName(const QString &path); + +private: + void initUiForSubProject(); }; } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp index 07d71f62a2a..592f79dd281 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonsummarypage.cpp @@ -28,7 +28,6 @@ using namespace Utils; static char KEY_SELECTED_PROJECT[] = "SelectedProject"; static char KEY_SELECTED_NODE[] = "SelectedFolderNode"; -static char KEY_IS_SUBPROJECT[] = "IsSubproject"; static char KEY_VERSIONCONTROL[] = "VersionControl"; static char KEY_QT_KEYWORDS_ENABLED[] = "QtKeywordsEnabled"; @@ -103,7 +102,6 @@ void JsonSummaryPage::initializePage() m_wizard->setValue(QLatin1String(KEY_SELECTED_PROJECT), QVariant()); m_wizard->setValue(QLatin1String(KEY_SELECTED_NODE), QVariant()); - m_wizard->setValue(QLatin1String(KEY_IS_SUBPROJECT), false); m_wizard->setValue(QLatin1String(KEY_VERSIONCONTROL), QString()); m_wizard->setValue(QLatin1String(KEY_QT_KEYWORDS_ENABLED), false); @@ -133,6 +131,7 @@ void JsonSummaryPage::initializePage() const FilePath preferredNodePath = preferredNode ? preferredNode->filePath() : FilePath{}; auto contextNode = findWizardContextNode(preferredNode); const ProjectAction currentAction = isProject ? AddSubProject : AddNewFile; + const bool isSubproject = m_wizard->value(Constants::PROJECT_ISSUBPROJECT).toBool(); auto updateProjectTree = [this, files, kind, currentAction, preferredNodePath]() { Node *node = currentNode(); @@ -140,7 +139,8 @@ void JsonSummaryPage::initializePage() if (auto p = ProjectManager::projectWithProjectFilePath(preferredNodePath)) node = p->rootProjectNode(); } - initializeProjectTree(findWizardContextNode(node), files, kind, currentAction); + initializeProjectTree(findWizardContextNode(node), files, kind, currentAction, + m_wizard->value(Constants::PROJECT_ISSUBPROJECT).toBool()); if (m_bsConnection && sender() != ProjectTree::instance()) disconnect(m_bsConnection); }; @@ -157,16 +157,16 @@ void JsonSummaryPage::initializePage() } } } - initializeProjectTree(contextNode, files, kind, currentAction); + initializeProjectTree(contextNode, files, kind, currentAction, isSubproject); // Refresh combobox on project tree changes: connect(ProjectTree::instance(), &ProjectTree::treeChanged, this, updateProjectTree); - bool hideProjectUi = JsonWizard::boolFromVariant(m_hideProjectUiValue, m_wizard->expander()); setProjectUiVisible(!hideProjectUi); + setVersionControlUiElementsVisible(!isSubproject); initializeVersionControls(); // Do a new try at initialization, now that we have real values set up: @@ -275,7 +275,7 @@ void JsonSummaryPage::updateProjectData(FolderNode *node) m_wizard->setValue(QLatin1String(KEY_SELECTED_PROJECT), QVariant::fromValue(project)); m_wizard->setValue(QLatin1String(KEY_SELECTED_NODE), QVariant::fromValue(node)); - m_wizard->setValue(QLatin1String(KEY_IS_SUBPROJECT), node ? true : false); + m_wizard->setValue(QLatin1String(Constants::PROJECT_ISSUBPROJECT), node ? true : false); bool qtKeyWordsEnabled = true; if (ProjectTree::hasNode(node)) { const ProjectNode *projectNode = node->asProjectNode(); diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp index 4e8d4964169..570dd8eda81 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.cpp @@ -45,6 +45,7 @@ const char WIZARD_PATH[] = "templates/wizards"; const char VERSION_KEY[] = "version"; const char ENABLED_EXPRESSION_KEY[] = "enabled"; +const char SKIP_FOR_SUBPROJECTS_KEY[] = "skipForSubprojects"; const char KIND_KEY[] = "kind"; const char SUPPORTED_PROJECTS[] = "supportedProjectTypes"; @@ -416,6 +417,8 @@ JsonWizardFactory::Page JsonWizardFactory::parsePage(const QVariant &value, QStr } QVariant enabled = getDataValue(QLatin1String(ENABLED_EXPRESSION_KEY), data, defaultData, true); + QVariant skippable = getDataValue(QLatin1String(SKIP_FOR_SUBPROJECTS_KEY), data, defaultData, + factory->defaultSkipForSubprojects()); QVariant specifiedSubData = data.value(QLatin1String(DATA_KEY)); QVariant defaultSubData = defaultData.value(QLatin1String(DATA_KEY)); @@ -438,6 +441,7 @@ JsonWizardFactory::Page JsonWizardFactory::parsePage(const QVariant &value, QStr p.index = index; p.data = subData; p.enabled = enabled; + p.skipForSubprojects = skippable; return p; } @@ -703,6 +707,8 @@ Wizard *JsonWizardFactory::runWizardImpl(const FilePath &path, QWidget *parent, page->setTitle(data.title); page->setSubTitle(data.subTitle); page->setProperty(Utils::SHORT_TITLE_PROPERTY, data.shortTitle); + page->setSkipForSubprojects(JsonWizard::boolFromVariant(data.skipForSubprojects, + wizard->expander())); if (data.index >= 0) { wizard->setPage(data.index, page); diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.h b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.h index 1ab133d5bd3..490f58b99f3 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.h +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardfactory.h @@ -47,6 +47,7 @@ public: int index = -1; // page index in the wizard Utils::Id typeId; QVariant enabled; + QVariant skipForSubprojects; QVariant data; }; diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory.h b/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory.h index b6374772461..d378a3a7b85 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory.h +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory.h @@ -28,6 +28,7 @@ public: // Basic syntax check for the data taken from the wizard.json file: virtual bool validateData(Utils::Id typeId, const QVariant &data, QString *errorMessage) = 0; + virtual bool defaultSkipForSubprojects() const { return false; } protected: // This will add "PE.Wizard.Page." in front of the suffixes and set those as supported typeIds diff --git a/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp b/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp index 45b2a4aa780..ad04a42c5b1 100644 --- a/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp +++ b/src/plugins/projectexplorer/jsonwizard/jsonwizardpagefactory_p.cpp @@ -137,6 +137,7 @@ public: WizardPage *create(JsonWizard *wizard, Id typeId, const QVariant &data) override; bool validateData(Id typeId, const QVariant &data, QString *errorMessage) override; + bool defaultSkipForSubprojects() const override { return true; } }; KitsPageFactory::KitsPageFactory() diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index ecb636ba0be..fd2f33c2e58 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -3544,8 +3544,10 @@ void ProjectExplorerPluginPrivate::addNewSubproject() }); map.insert(QLatin1String(Constants::PROJECT_KIT_IDS), profileIds); projectType = project->id(); + map.insert(Constants::PROJECT_POINTER, QVariant::fromValue(static_cast(project))); } + map.insert(QLatin1String(Constants::PROJECT_ENABLESUBPROJECT), true); ICore::showNewItemDialog(Tr::tr("New Subproject", "Title of dialog"), Utils::filtered(IWizardFactory::allWizardFactories(), [projectType](IWizardFactory *f) { diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h index 8a053c243d8..659c74991ab 100644 --- a/src/plugins/projectexplorer/projectexplorerconstants.h +++ b/src/plugins/projectexplorer/projectexplorerconstants.h @@ -115,6 +115,8 @@ const char PREFERRED_PROJECT_NODE_PATH[] = "ProjectExplorer.PreferredProjectPath const char PROJECT_POINTER[] = "ProjectExplorer.Project"; const char PROJECT_KIT_IDS[] = "ProjectExplorer.Profile.Ids"; const char QT_KEYWORDS_ENABLED[] = "ProjectExplorer.QtKeywordsEnabled"; +const char PROJECT_ISSUBPROJECT[] = "IsSubproject"; // Used inside wizard, no prefix! +const char PROJECT_ENABLESUBPROJECT[] = "ProjectExplorer.EnableSubproject"; // Build step lists ids: const char BUILDSTEPS_CLEAN[] = "ProjectExplorer.BuildSteps.Clean"; diff --git a/src/plugins/projectexplorer/projectfilewizardextension.cpp b/src/plugins/projectexplorer/projectfilewizardextension.cpp index 74a767cc989..2f964fe9895 100644 --- a/src/plugins/projectexplorer/projectfilewizardextension.cpp +++ b/src/plugins/projectexplorer/projectfilewizardextension.cpp @@ -117,13 +117,13 @@ void ProjectFileWizardExtension::firstExtensionPageShown( m_context->page->initializeProjectTree(findWizardContextNode(contextNode, project, path), filePaths, m_context->wizard->kind(), - projectAction); + projectAction, false); // Refresh combobox on project tree changes: connect(ProjectTree::instance(), &ProjectTree::treeChanged, m_context->page, [this, project, path, filePaths, kind, projectAction]() { m_context->page->initializeProjectTree( findWizardContextNode(m_context->page->currentNode(), project, path), filePaths, - kind, projectAction); + kind, projectAction, false); }); m_context->page->initializeVersionControls(); diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp index c71d762aaae..4fb82d1f0ba 100644 --- a/src/plugins/projectexplorer/projectwizardpage.cpp +++ b/src/plugins/projectexplorer/projectwizardpage.cpp @@ -4,6 +4,7 @@ #include "projectwizardpage.h" #include "project.h" +#include "projectexplorerconstants.h" #include "projectexplorertr.h" #include "projectmanager.h" #include "projectmodels.h" @@ -457,14 +458,18 @@ bool ProjectWizardPage::runVersionControl(const QList &files, QSt void ProjectWizardPage::initializeProjectTree(Node *context, const FilePaths &paths, IWizardFactory::WizardKind kind, - ProjectAction action) + ProjectAction action, bool limitToSubproject) { m_projectComboBox->disconnect(); Internal::BestNodeSelector selector(m_commonDirectory, paths); + Project *parentProject = static_cast( + wizard()->property(Constants::PROJECT_POINTER).value()); TreeItem *root = m_model.rootItem(); root->removeChildren(); for (Project *project : ProjectManager::projects()) { + if (limitToSubproject && project != parentProject) + continue; if (ProjectNode *pn = project->rootProjectNode()) { if (kind == IWizardFactory::ProjectWizard) { if (Internal::AddNewTree *child = buildAddProjectTree(pn, paths.first(), context, &selector)) @@ -479,7 +484,8 @@ void ProjectWizardPage::initializeProjectTree(Node *context, const FilePaths &pa return Internal::compareNodes(static_cast(ti1)->node(), static_cast(ti2)->node()); }); - root->prependChild(createNoneNode(&selector)); + if (!limitToSubproject) + root->prependChild(createNoneNode(&selector)); // Set combobox to context node if that appears in the tree: auto predicate = [context](TreeItem *ti) { return static_cast(ti)->node() == context; }; @@ -491,7 +497,9 @@ void ProjectWizardPage::initializeProjectTree(Node *context, const FilePaths &pa setBestNode(selector.bestChoice()); setAddingSubProject(action == AddSubProject); - m_projectComboBox->setEnabled(m_model.rowCount(QModelIndex()) > 1); + const bool enabled = m_model.rowCount(QModelIndex()) > 1 + || m_model.findItemAtLevel<1>([](TreeItem *it){ return it->hasChildren(); }); + m_projectComboBox->setEnabled(enabled); connect(m_projectComboBox, &QComboBox::currentIndexChanged, this, &ProjectWizardPage::projectChanged); } diff --git a/src/plugins/projectexplorer/projectwizardpage.h b/src/plugins/projectexplorer/projectwizardpage.h index 835547e2619..c111b7d8f71 100644 --- a/src/plugins/projectexplorer/projectwizardpage.h +++ b/src/plugins/projectexplorer/projectwizardpage.h @@ -52,7 +52,8 @@ public: void initializeProjectTree(Node *context, const Utils::FilePaths &paths, Core::IWizardFactory::WizardKind kind, - ProjectAction action); + ProjectAction action, + bool limitToSubproject); void initializeVersionControls(); void setProjectUiVisible(bool visible); diff --git a/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizard.cpp b/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizard.cpp index 9093b70a864..bba91520493 100644 --- a/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizard.cpp +++ b/src/plugins/qmakeprojectmanager/wizards/subdirsprojectwizard.cpp @@ -73,6 +73,7 @@ bool SubdirsProjectWizard::postGenerateFiles(const QWizard *w, const Core::Gener map.insert(QLatin1String(ProjectExplorer::Constants::PREFERRED_PROJECT_NODE_PATH), profileName.toVariant()); map.insert(QLatin1String(ProjectExplorer::Constants::PROJECT_KIT_IDS), Utils::transform(wizard->selectedKits(), &Utils::Id::toString)); + map.insert(QLatin1String(ProjectExplorer::Constants::PROJECT_ENABLESUBPROJECT), true); IWizardFactory::requestNewItemDialog(Tr::tr("New Subproject", "Title of dialog"), Utils::filtered(Core::IWizardFactory::allWizardFactories(), [](Core::IWizardFactory *f) { diff --git a/src/plugins/saferenderer/wizards/qsrapp/wizard.json b/src/plugins/saferenderer/wizards/qsrapp/wizard.json index 6a05c4e1d0b..0f1aa508293 100644 --- a/src/plugins/saferenderer/wizards/qsrapp/wizard.json +++ b/src/plugins/saferenderer/wizards/qsrapp/wizard.json @@ -31,7 +31,7 @@ "trDisplayName": "Define Build System", "trShortTitle": "Build System", "typeId": "Fields", - "enabled": "%{JS: !value('IsSubproject')}", + "skipForSubprojects": true, "data": [ { @@ -58,7 +58,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" } }, { diff --git a/src/plugins/saferenderer/wizards/qsrapp2_1/wizard.json b/src/plugins/saferenderer/wizards/qsrapp2_1/wizard.json index 9f493b9a212..e3f25810e69 100644 --- a/src/plugins/saferenderer/wizards/qsrapp2_1/wizard.json +++ b/src/plugins/saferenderer/wizards/qsrapp2_1/wizard.json @@ -1,6 +1,6 @@ { "version": 1, - "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ], + "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project", "CMakeProjectManager.CMakeProject" ], "id": "E.QSRApp2_1", "category": "D.QtSafeRendererApplication", "trDescription": "Creates a Qt Safe Renderer 2.1 (and newer) project with a simple UI and project setup.\n\nSupports both qmake and CMake.", @@ -33,7 +33,7 @@ "trDisplayName": "Define Build System", "trShortTitle": "Build System", "typeId": "Fields", - "enabled": "%{JS: !value('IsSubproject')}", + "skipForSubprojects": true, "data": [ { @@ -65,7 +65,6 @@ "trDisplayName": "Kit Selection", "trShortTitle": "Kits", "typeId": "Kits", - "enabled": "%{JS: !value('IsSubproject')}", "data": { "projectFilePath": "%{ProjectFile}" } }, {