From c780151aece1ca31dfe4a283058295469832d56a Mon Sep 17 00:00:00 2001 From: Jussi Witick Date: Tue, 29 Nov 2022 10:42:51 +0200 Subject: [PATCH 01/12] Add Qt Safe Renderer helper plugin Initially this plugin will include Qt Creator project wizards for Qt Safe Renderer Task-number: QSR-1874 Change-Id: I3831c875469439ae9576aabd51af050b6af959cf Reviewed-by: hjk Reviewed-by: Reviewed-by: Christian Stenger Reviewed-by: Alessandro Portale --- src/plugins/CMakeLists.txt | 1 + src/plugins/plugins.qbs | 1 + src/plugins/saferenderer/CMakeLists.txt | 8 ++ src/plugins/saferenderer/SafeRenderer.json.in | 20 ++++ src/plugins/saferenderer/saferenderer.cpp | 29 +++++ src/plugins/saferenderer/saferenderer.h | 22 ++++ src/plugins/saferenderer/saferenderer.qbs | 14 +++ src/plugins/saferenderer/saferenderer.qrc | 12 ++ src/plugins/saferenderer/wizards/icon.png | Bin 0 -> 1677 bytes src/plugins/saferenderer/wizards/icon@2x.png | Bin 0 -> 3050 bytes .../saferenderer/wizards/qsrapp/file.pro | 52 +++++++++ .../saferenderer/wizards/qsrapp/main.cpp.tpl | 66 +++++++++++ .../saferenderer/wizards/qsrapp/main.qml.tpl | 26 +++++ .../saferenderer/wizards/qsrapp/qml.qrc.tpl | 5 + .../wizards/qsrapp/safeasset.qrc.tpl | 2 + .../saferenderer/wizards/qsrapp/wizard.json | 103 ++++++++++++++++++ 16 files changed, 361 insertions(+) create mode 100644 src/plugins/saferenderer/CMakeLists.txt create mode 100644 src/plugins/saferenderer/SafeRenderer.json.in create mode 100644 src/plugins/saferenderer/saferenderer.cpp create mode 100644 src/plugins/saferenderer/saferenderer.h create mode 100644 src/plugins/saferenderer/saferenderer.qbs create mode 100644 src/plugins/saferenderer/saferenderer.qrc create mode 100644 src/plugins/saferenderer/wizards/icon.png create mode 100644 src/plugins/saferenderer/wizards/icon@2x.png create mode 100644 src/plugins/saferenderer/wizards/qsrapp/file.pro create mode 100644 src/plugins/saferenderer/wizards/qsrapp/main.cpp.tpl create mode 100644 src/plugins/saferenderer/wizards/qsrapp/main.qml.tpl create mode 100644 src/plugins/saferenderer/wizards/qsrapp/qml.qrc.tpl create mode 100644 src/plugins/saferenderer/wizards/qsrapp/safeasset.qrc.tpl create mode 100644 src/plugins/saferenderer/wizards/qsrapp/wizard.json diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 1f5c2e8342a..ebcab57a361 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -98,3 +98,4 @@ add_subdirectory(studiowelcome) add_subdirectory(qnx) add_subdirectory(webassembly) add_subdirectory(mcusupport) +add_subdirectory(saferenderer) diff --git a/src/plugins/plugins.qbs b/src/plugins/plugins.qbs index 72484ef4f0a..69ed458bfa4 100644 --- a/src/plugins/plugins.qbs +++ b/src/plugins/plugins.qbs @@ -70,6 +70,7 @@ Project { "qtsupport/qtsupport.qbs", "remotelinux/remotelinux.qbs", "resourceeditor/resourceeditor.qbs", + "saferenderer/saferenderer.qbs", "scxmleditor/scxmleditor.qbs", "serialterminal/serialterminal.qbs", "silversearcher/silversearcher.qbs", diff --git a/src/plugins/saferenderer/CMakeLists.txt b/src/plugins/saferenderer/CMakeLists.txt new file mode 100644 index 00000000000..739332de42d --- /dev/null +++ b/src/plugins/saferenderer/CMakeLists.txt @@ -0,0 +1,8 @@ +add_qtc_plugin(SafeRenderer + DEPENDS + QtCreator::Core QtCreator::ProjectExplorer + SOURCES + saferenderer.qrc + saferenderer.cpp + saferenderer.h +) diff --git a/src/plugins/saferenderer/SafeRenderer.json.in b/src/plugins/saferenderer/SafeRenderer.json.in new file mode 100644 index 00000000000..c8a6e3ee795 --- /dev/null +++ b/src/plugins/saferenderer/SafeRenderer.json.in @@ -0,0 +1,20 @@ +{ + \"Name\" : \"SafeRenderer\", + \"Version\" : \"$$QTCREATOR_VERSION\", + \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", + \"DisabledByDefault\" : true, + \"Vendor\" : \"The Qt Company Ltd\", + \"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\", + \"License\" : [ \"Commercial Usage\", + \"\", + \"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt 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.\", + \"\", + \"GNU General Public License Usage\", + \"\", + \"Alternatively, this plugin may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT included in the packaging of this plugin. Please review the following information to ensure the GNU General Public License requirements will be met: https://www.gnu.org/licenses/gpl-3.0.html.\" + ], + \"Category\" : \"Device Support\", + \"Description\" : \"Helper plugin for Qt Safe Renderer projects.\", + \"Url\" : \"https://www.qt.io\", + $$dependencyList +} diff --git a/src/plugins/saferenderer/saferenderer.cpp b/src/plugins/saferenderer/saferenderer.cpp new file mode 100644 index 00000000000..115b7c8728b --- /dev/null +++ b/src/plugins/saferenderer/saferenderer.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "saferenderer.h" + +#include + +namespace SafeRenderer::Internal { + +SafeRendererPlugin::SafeRendererPlugin() +{ +} + +SafeRendererPlugin::~SafeRendererPlugin() +{ +} + +bool SafeRendererPlugin::initialize(const QStringList &arguments, QString *errorString) +{ + Q_UNUSED(arguments) + Q_UNUSED(errorString) + + // Add Qt Creator project wizard path + ProjectExplorer::JsonWizardFactory::addWizardPath(":/saferenderer/wizards/"); + + return true; +} + +} // namespace SafeRenderer::Internal diff --git a/src/plugins/saferenderer/saferenderer.h b/src/plugins/saferenderer/saferenderer.h new file mode 100644 index 00000000000..1fabbff9ee1 --- /dev/null +++ b/src/plugins/saferenderer/saferenderer.h @@ -0,0 +1,22 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +namespace SafeRenderer::Internal { + +class SafeRendererPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "SafeRenderer.json") + +public: + SafeRendererPlugin(); + ~SafeRendererPlugin() override; + + bool initialize(const QStringList &arguments, QString *errorString) override; +}; + +} // namespace SafeRenderer::Internal diff --git a/src/plugins/saferenderer/saferenderer.qbs b/src/plugins/saferenderer/saferenderer.qbs new file mode 100644 index 00000000000..7945054eaec --- /dev/null +++ b/src/plugins/saferenderer/saferenderer.qbs @@ -0,0 +1,14 @@ +import qbs + +QtcPlugin { + name: "SafeRenderer" + + Depends { name: "Core" } + Depends { name: "ProjectExplorer" } + + files: [ + "saferenderer.cpp", + "saferenderer.h", + "saferenderer.qrc", + ] +} diff --git a/src/plugins/saferenderer/saferenderer.qrc b/src/plugins/saferenderer/saferenderer.qrc new file mode 100644 index 00000000000..28baa346473 --- /dev/null +++ b/src/plugins/saferenderer/saferenderer.qrc @@ -0,0 +1,12 @@ + + + wizards/icon.png + wizards/icon@2x.png + wizards/qsrapp/file.pro + wizards/qsrapp/main.cpp.tpl + wizards/qsrapp/main.qml.tpl + wizards/qsrapp/qml.qrc.tpl + wizards/qsrapp/safeasset.qrc.tpl + wizards/qsrapp/wizard.json + + diff --git a/src/plugins/saferenderer/wizards/icon.png b/src/plugins/saferenderer/wizards/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..88826ce9fb0a21ff29cbd3b240b0b04bfdc7bfbf GIT binary patch literal 1677 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?FGw{YnYAd}`g?Om`P-S+ z>HA{d^Uu@&|M~a)&%fVVp8q+&_?RM>iPYKkx3}e9KAB=9)VupafrZST6t$+PwcBK^ z%hv2zu;4*^tI*Mo?Si}+TW{T}{rzpKe$qz5&z;jla6j_{PE+*mN#$Sn9V*r?bzo< z#@T^MUYU#H*1yll%ll_&XE#sl;`7h0Pg$BBdwP3apZ50k1@&sO$u;<_zy81Q;h|QY zRwu`)U!I;8m*8QWGJX2vqut_*=7g`0JD6eOwEXhJe}8{3n&Us;?qJqdC1qvi^YiWd z&o+jwF5PuE&xw2geSa@+Z_b97$5V_ZzP`R*c=~DAynA~*SFKvbalBA*&ZJ2~MQ?AJ zUb=eKH7Yv#Fs5 zt(k29KoKPD!te3kwY!Jd5uyUca7S z=J>$`gMj|Rr>8{4JagD?-M)P|NmEmkLCrk>{^Ps5%NZJadU#^?R*728&5K&%we-+L zW%olxyLRpR@bhzemhTldH8r&h*RP9maV$+c9k2d|Nb)Fx?tupA?B@(9_@Ye=E*S}*j4)a(5+>!8V)~P zAjXnVw=7^u?CYc5;(|PEfq{X7*V0U+42_JM9zINDIMB{7&rnlsJW*ldnTlA^Q%hCV zR8>2VaVqYp`Dx^%CM?3m8lxv(G0#0PP|!q*S4Yg7qr9X<#BH%))>f&xbLXyDvu250 zb{Lxo7we_VmmhwtICSgVySv@&{BjF6Z4%1bD%I$~;OXfpAtTdrHjVq?yIWhiOG`^9 zoPJvI>&wa)5i@7byuvm^>*GS__7(o&+wQWZP}CO&yP=%Yx?q~+;K;Q?B<$Cpy1$67bV55Tem)WdU|^Cwf_eW zI3&Ejwst>r$82%tUG^n6;14X zG6F1)1`Hew#UBLqMQr5w&!l~x-=y$|Cm~7e-+qG!A1gN0|NkfFDDdf{{>KA0{tI^= z*qnYo!EAOltK)^o)*lZj)icMf7f;*#Q{PdbL_m;VCkezC6&2m9H(i_G;mH3)RlfFS v_77zbmt1^!ZmxBGc}d9&gXRi`AMBYA=eDujyjR7*z`)??>gTe~DWM4fWKI}b literal 0 HcmV?d00001 diff --git a/src/plugins/saferenderer/wizards/icon@2x.png b/src/plugins/saferenderer/wizards/icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1838ac95117f17e6b2eff3939c359fc87490068c GIT binary patch literal 3050 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^RWI14-?iy0WWg+Z8+Vb&Z8 z1_tgqo-U3d6?5Ls&GiwvE_HnV&C>W3NwMo+y`~7UtX4g;f~ChvIX5V0dr;T4BN9ck zXJ{LG9dS9^yX~9v{uMJ4daiHTx>RDz!Rgxs4VPSSF^}vj%HH7Mut;OIlE%BBgI8m} zr9Rs!|Ki-;&>M4S&fV;sT7S~B@3iH4%jf^+TN})IypHxEqS<1RK&GWX%a)!+HdzcIXVAlWo2DDazvb6b=#t#m4B9ptzP@; z#fyOD%a?oKT%PHyQti+fv~o>WUS40PykZj1iJ;Y2zw+|(zIu9ky7#?>FWUl`FI~;r z`t!=l;9KACRrhw%%G% zlCw+T8pEt*|0hqI7M8U!B8gj?>JYy@Zax{(9)ag9R!Z+1S_) zJpSk*@M9vnE(u;5?J{yN$Fwcqb9uxRI(7qim2_=ESt%dfxY z-Q8XO+r!Mv#H1yE-_K_)<*kz@P1>+&lhE3**Gs;(x3_QHwM$A|KhEamUDc&Qoz>so z9Q^j}o9E*_6(5;izj{^h_SV+P$1Ka=$uP3Uu`*2X^6|;}_u(*q_#C_1SvRzzk1rEc_RP)AJ@Q2{k3lIZIC%0Kr7mA-vmAw0ybKGQ3lx6-{J9`(wWqmr zi@)8^mI~=3ycaS|j;vofLCM&7a)q>@{k(JSOO~hve(iBnUK6uZ=+dQ22i}%B=jZE3 z=!kvzStInlAc=>K`J>sQqywLypRb%Ax-z8T-=E5e&1t+xjvn=mIF`5FIW$!C&F$^} ztMvRjZogHNy3c=+nO7+(D@$vAbDW}19JF32}dSI2L@XF}^(TE3oU%Y#lXClEfd0On& ztk4UORxDVMaHz;_@kH&*7cVMS@O$|By3X&v)9a+Lm+!;RnjHlXo#L9m`rGQ9PV)2f zyYcDw_xI0lW#;CpCNT)iYwM6sFq>V;TXc0*XpHQ>;?kHH8LPQ|E-ocja~21oO$~Dw{M^F9v^IGkFm41o_$(eT>S9u{QbPGt*v+R&GYZI zSQbBHQQdv_-0Hb)ZEW{yg}64h-k7Q#UNN1w=KX^G`{$SMRrjA)@H29AT4Cktt6X8L zMSI+ozt2AZ{ITwj(|`VaKL6ljMMunKrETn6wr%^Qw>oI$jz2G6XuPj#te!FBbIm>j z9_H#UXAOE~gy=~tOP4jRf~S7c1S9;9O#a7+V z_>t+FA1~!UkPObt(|cd_Z+nG+pkB-lflY7D%rrh)`c9wedywW#AvPI{f`;mpJ1Iu2 zb47jK;^O3f?7xz<`KDUT7goPksa~~3c5L&syg3D#Tl6Aqymd_jpDkuE| zMP#f>I(~nDd3m|I&T#{t4LaNm48_mSiC$SgePO26qF)Oq{874mcD6Zd{I|b99{2D3 zrE@yT*Y|8o{^2!od!_1szcpX?=EH}A6FZcZm1Az&|NFsw`t<3-=jZ1BxS2kmv#PH2 z{k^@DUb8G&*Vfn5)3NJY-KQrf7g*?=ezdpx`-Zh^d2ipoU6_%f@#4MSbnfXokwQjk zE3Ws3t%*3eJ3qeu@75<)g2oJjhPt}GQ#hYKed-wfHpPIa`SbJh{L=l4G)!inJz?Mz zP`mzm_v-NV&+h7PzNxd*jiKR6JX_1GMJ^jtPmBHd_xru;_4B7sH~Y>ubIi)pIy28! zI$~ODJHLF>$&^RW9(RlDI~5ihzMt{=+1ciu#m}Am{rewW_S$`yZ*%&2u@H5cJJv}m zE7q#i)7-^l;k2a;A?${zc~slt`trzbkxX*hPwEosr8ACLQA6z$xwYnPNL z7wg8dYwP3vedHgp{iv~v*;S$`n5fa^)U~K1?B9S^8I zl5^9@(Lb|WbrqWdPqVaH&V<-I1)fWT1pj-q&tDcqv%Q zEO0!0UE}#ezojK_ZfsnUrP$5b(J^=K-1Rj@KJQ9CJUF=GwZd%1jt*N}+u$_+6>HW^ zab=F=bg_ha7yN3GiLcgr{R#+NY*2eVq@ptIn15pCDmZDFUzj@8PBV)Rh~!mb#+~L-_`rRp{ZbJOz?FEd$ZZP zi;|to%FN8n%}?9*gct0L`Ek)*zE_f`?R4-h2K(69*d2Lyt?nIKzGTURmBGs|y#9LX z?$>Y*f%`lRulBbx)n(AX%VIvo_J#Vi2`s>@77`_)Z z-}x)#6CN&}cX!v+-KsO^&h34Ee!lzm+q&h~)s8;?nBeKzX>Dluaew2Z|GK;%K0i4r zyr=N7Tgd*O`fUM^gsYA8j#_-8yl0` zw=Z1yunSMJ{QLQQpM2eqh4&v8tYK-eue{bRsHt=M(Z1T> zd#d*C<7arrVWQ`z^5f|8%wPKgJ|?qy9GD(ock)HaE=L9rzSU)C7&2F`Sdox1t4<~C z&kROEh1MU2%q~HJfd@0TMpZ9)beu=vV0e7((N`tA>=_*<{eK_+?&F`e7KM*mmONq> os9}0o>Qh))cvxZKkN?b*WVliV4u_p$U|?YIboFyt=akR{0Oh68(*OVf literal 0 HcmV?d00001 diff --git a/src/plugins/saferenderer/wizards/qsrapp/file.pro b/src/plugins/saferenderer/wizards/qsrapp/file.pro new file mode 100644 index 00000000000..0302daad207 --- /dev/null +++ b/src/plugins/saferenderer/wizards/qsrapp/file.pro @@ -0,0 +1,52 @@ +QT = qtsaferenderer qsrplatformadaptation + +CONFIG += c++17 + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which as been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \\ + %{CppFileName} + + +# List of language codes that your application supports. For example, SAFE_LANGUAGES = en fi. +#SAFE_LANGUAGES = en + +# List of translation file names excluding the language code. For example, SAFE_TRANSLATION = $$PWD/safeui. +#SAFE_TRANSLATION = $$PWD/safeui + +# List of translation file names including the language code. There must be one file +# for each language listed in SAFE_LANGUAGES. For example, TRANSLATIONS += safeui_en.ts safeui_fi.ts. +#TRANSLATIONS += safeui_en.ts + +# You can use an lupdate_only{...} conditional statement to specify the QML files that contain texts. +#lupdate_only { +# SOURCES += main.qml +#} + + +RESOURCES += qml.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = $$PWD/imports + +# Additional import path used to resolve QML modules just for Qt Quick Designer +QML_DESIGNER_IMPORT_PATH = + + +CONFIG += qtsaferenderer exceptions +SAFE_QML = $$PWD/main.qml +SAFE_LAYOUT_PATH = $$PWD/layoutData +SAFE_RESOURCES += safeasset.qrc + +!cross_compile: DEFINES += HOST_BUILD +!cross_compile: QT += widgets quick svg + +DISTFILES += main.qml diff --git a/src/plugins/saferenderer/wizards/qsrapp/main.cpp.tpl b/src/plugins/saferenderer/wizards/qsrapp/main.cpp.tpl new file mode 100644 index 00000000000..4f36c6f6fa3 --- /dev/null +++ b/src/plugins/saferenderer/wizards/qsrapp/main.cpp.tpl @@ -0,0 +1,66 @@ +%{Cpp:LicenseTemplate}\ +%{JS: QtSupport.qtIncludes([ 'QtCore/QCoreApplication' ], + [ 'QtCore/QCoreApplication' ]) }\ + +#include +#include +#include + +#if defined(HOST_BUILD) +#include +#include +#include +#endif + +#if defined(USE_OUTPUTVERIFIER) +#include +#include "testverifier.h" +#endif + +#include "safewindow.h" +#include "eventhandler.h" + +int main(int argc, char *argv[]) +{ + Q_UNUSED(argc); + Q_UNUSED(argv); + + static SafeRenderer::QSafeLayoutResourceReader layout("/layoutData/main/main.srl"); + +#if defined(USE_OUTPUTVERIFIER) + static OutputVerifier outputVerifier; +#if defined(HOST_BUILD) + //In host environment the TestVerifier must be explicitly created. + //In OpeWFD adaptation the MISRVerifier instance is created in the SafeWindow adaptation. + static TestVerifier testVerifier(outputVerifier); +#endif + SafeWindow telltaleWindow(layout.size(), QSafePoint(0U, 0U), outputVerifier); +#else + SafeWindow telltaleWindow(layout.size(), QSafePoint(0U, 0U)); +#endif + static SafeRenderer::StateManager stateManager(telltaleWindow, layout); + telltaleWindow.requestUpdate(); //Request is required because eventHandler is not running yet. + +#if defined(USE_OUTPUTVERIFIER) + EventHandler msgHandler(stateManager, telltaleWindow, outputVerifier); +#else + EventHandler msgHandler(stateManager, telltaleWindow); +#endif + +#if defined(HOST_BUILD) + //Mixing the Qt and Qt Safe Renderer renderers is done here only for demonstration purposes on host, not for production purposes of any kind. + QQmlApplicationEngine engine; + const QUrl url(QStringLiteral("qrc:/main.qml")); + QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, qApp, + [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) + qDebug() << "Failed to start the main.qml"; + }, Qt::QueuedConnection); + engine.addImportPath(":/imports"); + engine.load(url); +#endif + + msgHandler.handleEvents(); + + return 0; +} diff --git a/src/plugins/saferenderer/wizards/qsrapp/main.qml.tpl b/src/plugins/saferenderer/wizards/qsrapp/main.qml.tpl new file mode 100644 index 00000000000..94fccebcb2a --- /dev/null +++ b/src/plugins/saferenderer/wizards/qsrapp/main.qml.tpl @@ -0,0 +1,26 @@ +import Qt.SafeRenderer 2.0 +import QtQuick.Window 2.15 + +Window { + id: window + width: 640 + height: 480 + visible: true + title: qsTr("Hello QSR") + + SafeText { + id: safeText + objectName: "safetextitem" + x: 206 + y: 208 + width: 340 + height: 34 + color: "#8ae234" + fillColor: "black" + text: "Hello Qt Safe Renderer!" + font.family: "Lato" + horizontalAlignment: Text.AlignLeft + font.pixelSize: 32 + runtimeEditable: true + } +} diff --git a/src/plugins/saferenderer/wizards/qsrapp/qml.qrc.tpl b/src/plugins/saferenderer/wizards/qsrapp/qml.qrc.tpl new file mode 100644 index 00000000000..5f6483ac33f --- /dev/null +++ b/src/plugins/saferenderer/wizards/qsrapp/qml.qrc.tpl @@ -0,0 +1,5 @@ + + + main.qml + + diff --git a/src/plugins/saferenderer/wizards/qsrapp/safeasset.qrc.tpl b/src/plugins/saferenderer/wizards/qsrapp/safeasset.qrc.tpl new file mode 100644 index 00000000000..601b61fc4c2 --- /dev/null +++ b/src/plugins/saferenderer/wizards/qsrapp/safeasset.qrc.tpl @@ -0,0 +1,2 @@ + + diff --git a/src/plugins/saferenderer/wizards/qsrapp/wizard.json b/src/plugins/saferenderer/wizards/qsrapp/wizard.json new file mode 100644 index 00000000000..e05e5f7971a --- /dev/null +++ b/src/plugins/saferenderer/wizards/qsrapp/wizard.json @@ -0,0 +1,103 @@ +{ + "version": 1, + "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ], + "id": "E.QSRApp", + "category": "D.QtSafeRendererApplication", + "trDescription": "Creates a Qt Safe Renderer project with simple UI and project setup.", + "trDisplayName": "Qt Safe Renderer Application", + "trDisplayCategory": "Application (Qt Safe Renderer)", + "icon": "../icon.png", + "iconKind": "Themed", + "featuresRequired": [ "QtSupport.Wizards.FeatureQt" ], + "enabled": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0 || value('Plugins').indexOf('CMakeProjectManager') >= 0}", + + "options": + [ + { "key": "ProjectFile", "value": "%{JS: value('BuildSystem') == 'qmake' ? value('ProFile') : value('CMakeFile')}" }, + { "key": "ProFile", "value": "%{JS: Util.fileName(value('ProjectDirectory') + '/' + value('ProjectName'), 'pro')}" }, + { "key": "HasTranslation", "value": "%{JS: value('TsFileName') !== ''}" }, + { "key": "CppFileName", "value": "%{JS: 'main.' + Util.preferredSuffix('text/x-c++src')}" } + ], + + "pages": + [ + { + "trDisplayName": "Project Location", + "trShortTitle": "Location", + "typeId": "Project", + "data": { "trDescription": "This wizard creates a simple Qt Safe Renderer application." } + }, + { + "trDisplayName": "Define Build System", + "trShortTitle": "Build System", + "typeId": "Fields", + "enabled": "%{JS: !value('IsSubproject')}", + "data": + [ + { + "name": "BuildSystem", + "trDisplayName": "Build system:", + "type": "ComboBox", + "persistenceKey": "BuildSystemType", + "data": + { + "index": 0, + "items": + [ + { + "trKey": "qmake", + "value": "qmake", + "condition": "%{JS: value('Plugins').indexOf('QmakeProjectManager') >= 0}" + } + ] + } + } + ] + }, + { + "trDisplayName": "Kit Selection", + "trShortTitle": "Kits", + "typeId": "Kits", + "enabled": "%{JS: !value('IsSubproject')}", + "data": { "projectFilePath": "%{ProjectFile}" } + }, + { + "trDisplayName": "Project Management", + "trShortTitle": "Summary", + "typeId": "Summary" + } + ], + "generators": + [ + { + "typeId": "File", + "data": + [ + { + "source": "file.pro", + "target": "%{ProFile}", + "openAsProject": true, + "condition": "%{JS: value('BuildSystem') === 'qmake'}" + }, + { + "source": "main.cpp.tpl", + "target": "%{CppFileName}", + "openInEditor": false + }, + { + "source": "safeasset.qrc.tpl", + "target": "safeasset.qrc" + }, + { + "source": "qml.qrc.tpl", + "target": "qml.qrc" + }, + { + "source": "main.qml.tpl", + "target": "main.qml", + "openInEditor": true + } + ] + } + ] +} From 4e8b7eee9ddf2feb8f7ced24bb9425539059e698 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 20 Oct 2022 13:43:10 +0200 Subject: [PATCH 02/12] Cpp: support space ship operator in lexer Fixes: QTCREATORBUG-27503 Change-Id: Idbff5a9b5b2e6e841e298ca6f706ef3c6aa1622b Reviewed-by: Christian Kandeler --- src/libs/3rdparty/cplusplus/Bind.cpp | 4 + src/libs/3rdparty/cplusplus/Lexer.cpp | 7 +- src/libs/3rdparty/cplusplus/Names.h | 5 +- src/libs/3rdparty/cplusplus/Parser.cpp | 39 +++++----- src/libs/3rdparty/cplusplus/Token.cpp | 1 + src/libs/3rdparty/cplusplus/Token.h | 2 + src/libs/cplusplus/NamePrettyPrinter.cpp | 3 + src/libs/cplusplus/pp-engine.cpp | 77 ++++++++++++------- .../cppeditor/cppcodemodelinspectordumper.cpp | 1 + src/plugins/cppeditor/projectpart.cpp | 1 + tests/auto/cplusplus/lexer/tst_lexer.cpp | 2 + 11 files changed, 93 insertions(+), 49 deletions(-) diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index effaac4b65a..7f10c79428c 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -915,6 +915,10 @@ OperatorNameId::Kind Bind::cppOperator(OperatorAST *ast) kind = OperatorNameId::ArrayAccessOp; break; + case T_LESS_EQUAL_GREATER: + kind = OperatorNameId::SpaceShipOp; + break; + default: kind = OperatorNameId::InvalidOp; } // switch diff --git a/src/libs/3rdparty/cplusplus/Lexer.cpp b/src/libs/3rdparty/cplusplus/Lexer.cpp index 8e1f7e2899e..e2f1b4e0e6b 100644 --- a/src/libs/3rdparty/cplusplus/Lexer.cpp +++ b/src/libs/3rdparty/cplusplus/Lexer.cpp @@ -612,7 +612,12 @@ void Lexer::scan_helper(Token *tok) tok->f.kind = T_LESS_LESS; } else if (_yychar == '=') { yyinp(); - tok->f.kind = T_LESS_EQUAL; + if (_languageFeatures.cxx20Enabled && _yychar == '>') { + yyinp(); + tok->f.kind = T_LESS_EQUAL_GREATER; + } else { + tok->f.kind = T_LESS_EQUAL; + } } else if (_yychar == ':') { if (*(_currentChar+1) != ':' || *(_currentChar+2) == ':' || *(_currentChar+2) == '>') { yyinp(); diff --git a/src/libs/3rdparty/cplusplus/Names.h b/src/libs/3rdparty/cplusplus/Names.h index 7913c9b0bc2..ede94eb7814 100644 --- a/src/libs/3rdparty/cplusplus/Names.h +++ b/src/libs/3rdparty/cplusplus/Names.h @@ -180,7 +180,7 @@ public: ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* -> - () [] + () [] <=> */ enum Kind { InvalidOp, @@ -225,7 +225,8 @@ public: ArrowStarOp, ArrowOp, FunctionCallOp, - ArrayAccessOp + ArrayAccessOp, + SpaceShipOp }; public: diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 430b19efbe4..cb7bfa3a1b6 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -98,10 +98,11 @@ enum { And = 8, Equality = 9, Relational = 10, - Shift = 11, - Additive = 12, - Multiplicative = 13, - PointerToMember = 14 + ThreeWayComp = 11, + Shift = 12, + Additive = 13, + Multiplicative = 14, + PointerToMember = 15 }; } // namespace Precedece @@ -116,29 +117,30 @@ inline int precedence(int tokenKind, bool templateArguments) return Prec::Assignment; switch (tokenKind) { - case T_COMMA: return Prec::Comma; - case T_QUESTION: return Prec::Conditional; - case T_PIPE_PIPE: return Prec::LogicalOr; - case T_AMPER_AMPER: return Prec::LogicalAnd; - case T_PIPE: return Prec::InclusiveOr; - case T_CARET: return Prec::ExclusiveOr; - case T_AMPER: return Prec::And; + case T_COMMA: return Prec::Comma; + case T_QUESTION: return Prec::Conditional; + case T_PIPE_PIPE: return Prec::LogicalOr; + case T_AMPER_AMPER: return Prec::LogicalAnd; + case T_PIPE: return Prec::InclusiveOr; + case T_CARET: return Prec::ExclusiveOr; + case T_AMPER: return Prec::And; case T_EQUAL_EQUAL: - case T_EXCLAIM_EQUAL: return Prec::Equality; + case T_EXCLAIM_EQUAL: return Prec::Equality; case T_GREATER: case T_LESS: case T_LESS_EQUAL: - case T_GREATER_EQUAL: return Prec::Relational; + case T_GREATER_EQUAL: return Prec::Relational; + case T_LESS_EQUAL_GREATER: return Prec::ThreeWayComp; case T_LESS_LESS: - case T_GREATER_GREATER: return Prec::ExclusiveOr; + case T_GREATER_GREATER: return Prec::ExclusiveOr; case T_PLUS: - case T_MINUS: return Prec::Additive; + case T_MINUS: return Prec::Additive; case T_STAR: case T_SLASH: - case T_PERCENT: return Prec::Multiplicative; + case T_PERCENT: return Prec::Multiplicative; case T_ARROW_STAR: - case T_DOT_STAR: return Prec::PointerToMember; - default: return Prec::Unknown; + case T_DOT_STAR: return Prec::PointerToMember; + default: return Prec::Unknown; } } @@ -1300,6 +1302,7 @@ bool Parser::parseOperator(OperatorAST *&node) // ### FIXME case T_GREATER_EQUAL: case T_GREATER_GREATER_EQUAL: case T_LESS_EQUAL: + case T_LESS_EQUAL_GREATER: case T_LESS_LESS_EQUAL: case T_MINUS_EQUAL: case T_PERCENT_EQUAL: diff --git a/src/libs/3rdparty/cplusplus/Token.cpp b/src/libs/3rdparty/cplusplus/Token.cpp index 1d9127b2dda..31fdb2036c2 100644 --- a/src/libs/3rdparty/cplusplus/Token.cpp +++ b/src/libs/3rdparty/cplusplus/Token.cpp @@ -91,6 +91,7 @@ const char *token_names[] = { ("<="), ("<<"), ("<<="), + ("<=>"), ("-"), ("-="), ("--"), diff --git a/src/libs/3rdparty/cplusplus/Token.h b/src/libs/3rdparty/cplusplus/Token.h index f5459786694..3a04a44a86a 100644 --- a/src/libs/3rdparty/cplusplus/Token.h +++ b/src/libs/3rdparty/cplusplus/Token.h @@ -99,6 +99,7 @@ enum Kind { T_LESS_EQUAL, T_LESS_LESS, T_LESS_LESS_EQUAL, + T_LESS_EQUAL_GREATER, T_MINUS, T_MINUS_EQUAL, T_MINUS_MINUS, @@ -446,6 +447,7 @@ struct LanguageFeatures unsigned int cxxEnabled : 1; unsigned int cxx11Enabled : 1; unsigned int cxx14Enabled : 1; + unsigned int cxx20Enabled : 1; unsigned int objCEnabled : 1; unsigned int c99Enabled : 1; }; diff --git a/src/libs/cplusplus/NamePrettyPrinter.cpp b/src/libs/cplusplus/NamePrettyPrinter.cpp index 8a2ff8d6f3c..9685cdf2a1b 100644 --- a/src/libs/cplusplus/NamePrettyPrinter.cpp +++ b/src/libs/cplusplus/NamePrettyPrinter.cpp @@ -222,6 +222,9 @@ void NamePrettyPrinter::visit(const OperatorNameId *name) case OperatorNameId::ArrayAccessOp: _name += QLatin1String("[]"); break; + case OperatorNameId::SpaceShipOp: + _name += QLatin1String("<=>"); + break; } // switch } diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 40b7d44e66e..50cd1241de8 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -202,6 +202,24 @@ struct Value inline bool is_zero () const { return l == 0; } + template static bool cmpImpl(T v1, T v2) + { + if (v1 < v2) + return -1; + if (v1 > v2) + return 1; + return 0; + } + Value cmp(const Value &other) const + { + Value v = *this; + if (v.is_ulong() || other.is_ulong()) + v.set_long(cmpImpl(v.ul, other.ul)); + else + v.set_long(cmpImpl(v.l, other.l)); + return v; + } + #define PP_DEFINE_BIN_OP(name, op) \ inline Value operator op(const Value &other) const \ { \ @@ -488,24 +506,25 @@ private: inline int precedence(int tokenKind) const { switch (tokenKind) { - case T_PIPE_PIPE: return 0; - case T_AMPER_AMPER: return 1; - case T_PIPE: return 2; - case T_CARET: return 3; - case T_AMPER: return 4; + case T_PIPE_PIPE: return 0; + case T_AMPER_AMPER: return 1; + case T_PIPE: return 2; + case T_CARET: return 3; + case T_AMPER: return 4; case T_EQUAL_EQUAL: - case T_EXCLAIM_EQUAL: return 5; + case T_EXCLAIM_EQUAL: return 5; case T_GREATER: case T_LESS: case T_LESS_EQUAL: - case T_GREATER_EQUAL: return 6; + case T_GREATER_EQUAL: return 6; + case T_LESS_EQUAL_GREATER: return 7; case T_LESS_LESS: - case T_GREATER_GREATER: return 7; + case T_GREATER_GREATER: return 8; case T_PLUS: - case T_MINUS: return 8; + case T_MINUS: return 9; case T_STAR: case T_SLASH: - case T_PERCENT: return 9; + case T_PERCENT: return 10; default: return -1; @@ -525,6 +544,7 @@ private: case T_GREATER: case T_LESS: case T_LESS_EQUAL: + case T_LESS_EQUAL_GREATER: case T_GREATER_EQUAL: case T_LESS_LESS: case T_GREATER_GREATER: @@ -543,24 +563,25 @@ private: static inline Value evaluate_expression(int tokenKind, const Value &lhs, const Value &rhs) { switch (tokenKind) { - case T_PIPE_PIPE: return lhs || rhs; - case T_AMPER_AMPER: return lhs && rhs; - case T_PIPE: return lhs | rhs; - case T_CARET: return lhs ^ rhs; - case T_AMPER: return lhs & rhs; - case T_EQUAL_EQUAL: return lhs == rhs; - case T_EXCLAIM_EQUAL: return lhs != rhs; - case T_GREATER: return lhs > rhs; - case T_LESS: return lhs < rhs; - case T_LESS_EQUAL: return lhs <= rhs; - case T_GREATER_EQUAL: return lhs >= rhs; - case T_LESS_LESS: return lhs << rhs; - case T_GREATER_GREATER: return lhs >> rhs; - case T_PLUS: return lhs + rhs; - case T_MINUS: return lhs - rhs; - case T_STAR: return lhs * rhs; - case T_SLASH: return rhs.is_zero() ? Value() : lhs / rhs; - case T_PERCENT: return rhs.is_zero() ? Value() : lhs % rhs; + case T_PIPE_PIPE: return lhs || rhs; + case T_AMPER_AMPER: return lhs && rhs; + case T_PIPE: return lhs | rhs; + case T_CARET: return lhs ^ rhs; + case T_AMPER: return lhs & rhs; + case T_EQUAL_EQUAL: return lhs == rhs; + case T_EXCLAIM_EQUAL: return lhs != rhs; + case T_GREATER: return lhs > rhs; + case T_LESS: return lhs < rhs; + case T_LESS_EQUAL: return lhs <= rhs; + case T_LESS_EQUAL_GREATER: return lhs.cmp(rhs); + case T_GREATER_EQUAL: return lhs >= rhs; + case T_LESS_LESS: return lhs << rhs; + case T_GREATER_GREATER: return lhs >> rhs; + case T_PLUS: return lhs + rhs; + case T_MINUS: return lhs - rhs; + case T_STAR: return lhs * rhs; + case T_SLASH: return rhs.is_zero() ? Value() : lhs / rhs; + case T_PERCENT: return rhs.is_zero() ? Value() : lhs % rhs; default: return Value(); diff --git a/src/plugins/cppeditor/cppcodemodelinspectordumper.cpp b/src/plugins/cppeditor/cppcodemodelinspectordumper.cpp index 8d77db098bd..45de8f30539 100644 --- a/src/plugins/cppeditor/cppcodemodelinspectordumper.cpp +++ b/src/plugins/cppeditor/cppcodemodelinspectordumper.cpp @@ -219,6 +219,7 @@ QString Utils::toString(CPlusPlus::Kind kind) TOKEN(T_LBRACKET); TOKEN(T_LESS); TOKEN(T_LESS_EQUAL); + TOKEN(T_LESS_EQUAL_GREATER); TOKEN(T_LESS_LESS); TOKEN(T_LESS_LESS_EQUAL); TOKEN(T_LPAREN); diff --git a/src/plugins/cppeditor/projectpart.cpp b/src/plugins/cppeditor/projectpart.cpp index 7660499bc9c..9cab9a6df2b 100644 --- a/src/plugins/cppeditor/projectpart.cpp +++ b/src/plugins/cppeditor/projectpart.cpp @@ -163,6 +163,7 @@ CPlusPlus::LanguageFeatures ProjectPart::deriveLanguageFeatures() const CPlusPlus::LanguageFeatures features; features.cxx11Enabled = languageVersion >= Utils::LanguageVersion::CXX11; features.cxx14Enabled = languageVersion >= Utils::LanguageVersion::CXX14; + features.cxx20Enabled = languageVersion >= Utils::LanguageVersion::CXX20; features.cxxEnabled = hasCxx; features.c99Enabled = languageVersion >= Utils::LanguageVersion::C99; features.objCEnabled = languageExtensions.testFlag(Utils::LanguageExtension::ObjectiveC); diff --git a/tests/auto/cplusplus/lexer/tst_lexer.cpp b/tests/auto/cplusplus/lexer/tst_lexer.cpp index a4c16bc8b07..641b62f248c 100644 --- a/tests/auto/cplusplus/lexer/tst_lexer.cpp +++ b/tests/auto/cplusplus/lexer/tst_lexer.cpp @@ -442,6 +442,7 @@ void tst_SimpleLexer::ppOpOrPunc() const QByteArray source = QTest::currentDataTag(); LanguageFeatures languageFeatures; languageFeatures.cxxEnabled = true; + languageFeatures.cxx20Enabled = true; run(source, toTokens({unsigned(expectedTokenKind)}), false, CompareKind, true, languageFeatures); } @@ -492,6 +493,7 @@ void tst_SimpleLexer::ppOpOrPunc_data() QTest::newRow("==") << T_EQUAL_EQUAL; QTest::newRow("!=") << T_EXCLAIM_EQUAL; QTest::newRow("<=") << T_LESS_EQUAL; + QTest::newRow("<=>") << T_LESS_EQUAL_GREATER; QTest::newRow(">=") << T_GREATER_EQUAL; QTest::newRow("&&") << T_AMPER_AMPER; QTest::newRow("||") << T_PIPE_PIPE; From 06390f5b5342b32825e1cf2c90e10a6082d58867 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Wed, 25 Jan 2023 13:46:32 +0100 Subject: [PATCH 03/12] CppEditor: Warn against renaming in generated files Task-number: QTCREATORBUG-7044 Change-Id: I3ab2bafb1a7333d8c1a49dcd795696085ac6f666 Reviewed-by: Christian Stenger --- src/plugins/cppeditor/cppeditorwidget.cpp | 59 +++++++++++++++++++-- src/plugins/cppeditor/cppeditorwidget.h | 1 + src/plugins/projectexplorer/buildsystem.cpp | 7 +++ src/plugins/projectexplorer/buildsystem.h | 1 + 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index fe693bbbfc9..20fe8e6254b 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -26,10 +26,14 @@ #include #include #include +#include +#include +#include #include #include #include +#include #include #include @@ -614,9 +618,19 @@ void CppEditorWidget::renameUsages(const QString &replacement, QTextCursor curso { if (cursor.isNull()) cursor = textCursor(); - CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this, textDocument()}; - QPointer cppEditorWidget = this; - d->m_modelManager->globalRename(cursorInEditor, replacement); + + // First check if the symbol to be renamed comes from a generated file. + LinkHandler continuation = [=, self = QPointer(this)](const Link &link) { + if (!self) + return; + showRenameWarningIfFileIsGenerated(link.targetFilePath); + CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this, textDocument()}; + QPointer cppEditorWidget = this; + d->m_modelManager->globalRename(cursorInEditor, replacement); + }; + CppModelManager::followSymbol( + CursorInEditor{cursor, textDocument()->filePath(), this, textDocument()}, + continuation, true, false); } void CppEditorWidget::renameUsages(const Utils::FilePath &filePath, const QString &replacement, @@ -737,6 +751,45 @@ void CppEditorWidget::handleOutlineChanged(const QWidget *newOutline) } } +void CppEditorWidget::showRenameWarningIfFileIsGenerated(const Utils::FilePath &filePath) +{ + if (filePath.isEmpty()) + return; + for (const Project * const project : SessionManager::projects()) { + const Node * const node = project->nodeForFilePath(filePath); + if (!node) + continue; + if (!node->isGenerated()) + return; + ExtraCompiler *ec = nullptr; + QString warning = CppEditor::Tr::tr( + "You are trying to rename a symbol declared in the generated file \"%1\".\n" + "This is normally not a good idea, as the file will likely get " + "overwritten during the build process.") + .arg(filePath.toUserOutput()); + if (const Target * const target = project->activeTarget()) { + if (const BuildSystem * const bs = target->buildSystem()) + ec = bs->extraCompilerForTarget(filePath); + } + if (ec) { + warning.append('\n').append(CppEditor::Tr::tr( + "Do you want to edit \"%1\" instead?") + .arg(ec->source().toUserOutput())); + } + static const Id infoId("cppeditor.renameWarning"); + InfoBarEntry info(infoId, warning); + if (ec) { + info.addCustomButton(CppEditor::Tr::tr("Open %1").arg(ec->source().fileName()), + [source = ec->source()] { + EditorManager::openEditor(source); + ICore::infoBar()->removeInfo(infoId); + }); + } + ICore::infoBar()->addInfo(info); + return; + } +} + namespace { using Utils::Text::selectAt; diff --git a/src/plugins/cppeditor/cppeditorwidget.h b/src/plugins/cppeditor/cppeditorwidget.h index a42d786ead9..e9c0d11275c 100644 --- a/src/plugins/cppeditor/cppeditorwidget.h +++ b/src/plugins/cppeditor/cppeditorwidget.h @@ -136,6 +136,7 @@ private: const ProjectPart *projectPart() const; void handleOutlineChanged(const QWidget* newOutline); + void showRenameWarningIfFileIsGenerated(const Utils::FilePath &filePath); private: QScopedPointer d; diff --git a/src/plugins/projectexplorer/buildsystem.cpp b/src/plugins/projectexplorer/buildsystem.cpp index b103d974683..0a2c2f3a85d 100644 --- a/src/plugins/projectexplorer/buildsystem.cpp +++ b/src/plugins/projectexplorer/buildsystem.cpp @@ -248,6 +248,13 @@ ExtraCompiler *BuildSystem::extraCompilerForSource(const Utils::FilePath &source return findExtraCompiler([source](const ExtraCompiler *ec) { return ec->source() == source; }); } +ExtraCompiler *BuildSystem::extraCompilerForTarget(const Utils::FilePath &target) const +{ + return findExtraCompiler([target](const ExtraCompiler *ec) { + return ec->targets().contains(target); + }); +} + MakeInstallCommand BuildSystem::makeInstallCommand(const FilePath &installRoot) const { QTC_ASSERT(target()->project()->hasMakeInstallEquivalent(), return {}); diff --git a/src/plugins/projectexplorer/buildsystem.h b/src/plugins/projectexplorer/buildsystem.h index 1fcbdbff18f..0d19c9110ec 100644 --- a/src/plugins/projectexplorer/buildsystem.h +++ b/src/plugins/projectexplorer/buildsystem.h @@ -85,6 +85,7 @@ public: // Owned by the build system. Use only in main thread. Can go away at any time. ExtraCompiler *extraCompilerForSource(const Utils::FilePath &source) const; + ExtraCompiler *extraCompilerForTarget(const Utils::FilePath &target) const; virtual MakeInstallCommand makeInstallCommand(const Utils::FilePath &installRoot) const; From 803ecca075f3a627a97e3eef56d6ad60ca0a1849 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Mon, 30 Jan 2023 11:53:16 +0100 Subject: [PATCH 04/12] ClangCodeModel: Fix soft assert Amends 0d909c353c54ecf2fee2d13b7d2fe19eee01591d. Change-Id: Icb0c7245825fc7e8c4ce1ac3fae1bc585e857ace Reviewed-by: Qt CI Bot Reviewed-by: David Schulz --- src/plugins/clangcodemodel/clangdfindreferences.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/clangcodemodel/clangdfindreferences.cpp b/src/plugins/clangcodemodel/clangdfindreferences.cpp index f2102325f06..8a2d3faaeff 100644 --- a/src/plugins/clangcodemodel/clangdfindreferences.cpp +++ b/src/plugins/clangcodemodel/clangdfindreferences.cpp @@ -131,7 +131,8 @@ ClangdFindReferences::ClangdFindReferences(ClangdClient *client, TextDocument *d replacement ? SearchResultWindow::SearchAndReplace : SearchResultWindow::SearchOnly, SearchResultWindow::PreserveCaseDisabled, "CppEditor"); - d->search->makeNonInteractive(callback); + if (callback) + d->search->makeNonInteractive(callback); if (categorize) d->search->setFilter(new CppSearchResultFilter); if (d->replacementData) { From 04f521abcfbf68fc45ffcfc38557431914e744d8 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 26 Jan 2023 13:52:11 +0100 Subject: [PATCH 05/12] CompilationDBPM: Adapt to FilePath change Change-Id: Idc2987e0568d34cf024cb170aa604f47053c9617 Reviewed-by: Christian Kandeler --- .../compilationdatabaseproject.cpp | 2 +- .../compilationdbparser.cpp | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp index d53c50b5fa2..f479bdcb355 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp @@ -109,7 +109,7 @@ ToolChain *toolchainFromFlags(const Kit *kit, const QStringList &flags, const Ut return ToolChainKitAspect::toolChain(kit, language); // Try exact compiler match. - const Utils::FilePath compiler = Utils::FilePath::fromString(compilerPath(flags.front())); + const Utils::FilePath compiler = Utils::FilePath::fromUserInput(compilerPath(flags.front())); ToolChain *toolchain = ToolChainManager::toolChain([&compiler, &language](const ToolChain *tc) { return tc->isValid() && tc->language() == language && tc->compilerCommand() == compiler; }); diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp index 01ec506c27a..bf5ff01e2ae 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdbparser.cpp @@ -157,11 +157,8 @@ static QStringList jsonObjectFlags(const QJsonObject &object, QSet &fla static FilePath jsonObjectFilePath(const QJsonObject &object) { - const QString workingDir = QDir::cleanPath(object["directory"].toString()); - FilePath fileName = FilePath::fromString(QDir::cleanPath(object["file"].toString())); - if (fileName.toFileInfo().isRelative()) - fileName = FilePath::fromString(QDir::cleanPath(workingDir + "/" + fileName.toString())); - return fileName; + const FilePath workingDir = FilePath::fromUserInput(object["directory"].toString()); + return workingDir.resolvePath(object["file"].toString()); } std::vector CompilationDbParser::readJsonObjects() const From 2f94e93334af366589fb2c5dcbff33a0694b6074 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Sat, 28 Jan 2023 15:40:34 +0900 Subject: [PATCH 06/12] "New Class" wizard: Add QML_ELEMENT checkbox Change-Id: I219b539ba5f36c895be1042a74571e54a0c67ec6 Reviewed-by: Reviewed-by: Christian Kandeler --- share/qtcreator/templates/wizards/classes/cpp/file.h | 3 +++ .../templates/wizards/classes/cpp/wizard.json | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/share/qtcreator/templates/wizards/classes/cpp/file.h b/share/qtcreator/templates/wizards/classes/cpp/file.h index df35bd553c2..77f1b213516 100644 --- a/share/qtcreator/templates/wizards/classes/cpp/file.h +++ b/share/qtcreator/templates/wizards/classes/cpp/file.h @@ -32,6 +32,9 @@ class %{CN} @if '%{AddQObjectMacro}' Q_OBJECT @endif +@if '%{AddQmlElementMacro}' + QML_ELEMENT +@endif public: @if '%{Base}' === 'QObject' || %{JS: Cpp.hasQObjectParent('%{Base}')} explicit %{CN}(QObject *parent = nullptr); diff --git a/share/qtcreator/templates/wizards/classes/cpp/wizard.json b/share/qtcreator/templates/wizards/classes/cpp/wizard.json index 33ba82355a9..9317c175981 100644 --- a/share/qtcreator/templates/wizards/classes/cpp/wizard.json +++ b/share/qtcreator/templates/wizards/classes/cpp/wizard.json @@ -146,6 +146,17 @@ "checked": "%{JS: [ 'QObject', 'QWidget', 'QMainWindow', 'QDeclarativeItem', 'QQuickItem'].indexOf(value('Base')) >= 0 }" } }, + { + "name": "AddQmlElementMacro", + "trDisplayName": "Add QML_ELEMENT", + "type": "CheckBox", + "data": + { + "checkedValue": "AddQmlElementMacro", + "uncheckedValue": "", + "checked": "%{JS: ['QQuickItem'].indexOf(value('Base')) >= 0 }" + } + }, { "name": "Sp2", "type": "Spacer" From 8cb0858574d3daef69105af87234149ade7d4d4d Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Sat, 28 Jan 2023 14:53:27 +0900 Subject: [PATCH 07/12] Improve console app template Set QtCore explicitly instead of removing QtGui from default modules. Update CONFIG with the new feature introduced in QTBUG-27079 Change-Id: Id2b5cc7c9534618b88c4683253af6c2a8fd90816 Reviewed-by: Christian Kandeler Reviewed-by: --- .../qtcreator/templates/wizards/projects/consoleapp/file.pro | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/share/qtcreator/templates/wizards/projects/consoleapp/file.pro b/share/qtcreator/templates/wizards/projects/consoleapp/file.pro index 8cafd79b8b8..d86283e2dfb 100644 --- a/share/qtcreator/templates/wizards/projects/consoleapp/file.pro +++ b/share/qtcreator/templates/wizards/projects/consoleapp/file.pro @@ -1,7 +1,6 @@ -QT -= gui +QT = core -CONFIG += c++17 console -CONFIG -= app_bundle +CONFIG += c++17 cmdline # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. From 92b23cb8274459a3977b2f66d45c814e997f6045 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 24 Jan 2023 15:25:50 +0100 Subject: [PATCH 08/12] Nim: Use simple wrapper classes for project generation This allows a setup similar to the run and build related items and a slimmer header file. Change-Id: I76c722fb2a3022b11ecbc13456be39288fce868b Reviewed-by: Christian Stenger Reviewed-by: --- src/plugins/nim/nimplugin.cpp | 7 +++-- src/plugins/nim/project/nimbleproject.cpp | 10 +++++++ src/plugins/nim/project/nimbleproject.h | 6 +++++ src/plugins/nim/project/nimproject.cpp | 33 +++++++++++++++++++++-- src/plugins/nim/project/nimproject.h | 30 +++------------------ 5 files changed, 53 insertions(+), 33 deletions(-) diff --git a/src/plugins/nim/nimplugin.cpp b/src/plugins/nim/nimplugin.cpp index 9d46835ef03..fcca3ef8d38 100644 --- a/src/plugins/nim/nimplugin.cpp +++ b/src/plugins/nim/nimplugin.cpp @@ -23,7 +23,6 @@ #include "suggest/nimsuggestcache.h" #include -#include #include #include #include @@ -66,6 +65,9 @@ public: NimToolsSettingsPage toolsSettingsPage{&settings}; NimCodeStylePreferencesFactory codeStylePreferencesPage; NimToolChainFactory toolChainFactory; + + NimProjectFactory nimProjectFactory; + NimbleProjectFactory nimbleProjectFactory; }; NimPlugin::~NimPlugin() @@ -82,9 +84,6 @@ void NimPlugin::initialize() TextEditor::SnippetProvider::registerGroup(Constants::C_NIMSNIPPETSGROUP_ID, Tr::tr("Nim", "SnippetProvider"), &NimEditorFactory::decorateEditor); - - ProjectManager::registerProjectType(Constants::C_NIM_PROJECT_MIMETYPE); - ProjectManager::registerProjectType(Constants::C_NIMBLE_MIMETYPE); } void NimPlugin::extensionsInitialized() diff --git a/src/plugins/nim/project/nimbleproject.cpp b/src/plugins/nim/project/nimbleproject.cpp index 428db0b1135..5777724afbd 100644 --- a/src/plugins/nim/project/nimbleproject.cpp +++ b/src/plugins/nim/project/nimbleproject.cpp @@ -6,7 +6,10 @@ #include "nimblebuildsystem.h" #include + #include +#include + #include using namespace ProjectExplorer; @@ -47,4 +50,11 @@ void NimbleProject::setExcludedFiles(const QStringList &excludedFiles) m_excludedFiles = excludedFiles; } +// Factory + +NimbleProjectFactory::NimbleProjectFactory() +{ + ProjectManager::registerProjectType(Constants::C_NIMBLE_MIMETYPE); +} + } // Nim diff --git a/src/plugins/nim/project/nimbleproject.h b/src/plugins/nim/project/nimbleproject.h index c7b759c50a7..9abbc90dcc4 100644 --- a/src/plugins/nim/project/nimbleproject.h +++ b/src/plugins/nim/project/nimbleproject.h @@ -28,4 +28,10 @@ protected: QStringList m_excludedFiles; }; +class NimbleProjectFactory +{ +public: + NimbleProjectFactory(); +}; + } // Nim diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp index a5d36425426..4a2bc060260 100644 --- a/src/plugins/nim/project/nimproject.cpp +++ b/src/plugins/nim/project/nimproject.cpp @@ -9,18 +9,40 @@ #include "nimtoolchain.h" #include + #include #include +#include using namespace ProjectExplorer; using namespace Utils; namespace Nim { -NimProject::NimProject(const FilePath &fileName) : Project(Constants::C_NIM_MIMETYPE, fileName) +class NimProject : public Project +{ +public: + explicit NimProject(const FilePath &filePath); + + Tasks projectIssues(const Kit *k) const final; + + // Keep for compatibility with Qt Creator 4.10 + QVariantMap toMap() const final; + + QStringList excludedFiles() const; + void setExcludedFiles(const QStringList &excludedFiles); + +protected: + // Keep for compatibility with Qt Creator 4.10 + RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) final; + + QStringList m_excludedFiles; +}; + +NimProject::NimProject(const FilePath &filePath) : Project(Constants::C_NIM_MIMETYPE, filePath) { setId(Constants::C_NIMPROJECT_ID); - setDisplayName(fileName.completeBaseName()); + setDisplayName(filePath.completeBaseName()); // ensure debugging is enabled (Nim plugin translates nim code to C code) setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID)); @@ -65,4 +87,11 @@ void NimProject::setExcludedFiles(const QStringList &excludedFiles) m_excludedFiles = excludedFiles; } +// Factory + +NimProjectFactory::NimProjectFactory() +{ + ProjectManager::registerProjectType(Constants::C_NIM_PROJECT_MIMETYPE); +} + } // Nim diff --git a/src/plugins/nim/project/nimproject.h b/src/plugins/nim/project/nimproject.h index 7b8e74a53b6..5bdc12f1d58 100644 --- a/src/plugins/nim/project/nimproject.h +++ b/src/plugins/nim/project/nimproject.h @@ -3,36 +3,12 @@ #pragma once -#include -#include - -#include -#include - namespace Nim { -class NimBuildSystem; - -class NimProject : public ProjectExplorer::Project +class NimProjectFactory { - Q_OBJECT - public: - explicit NimProject(const Utils::FilePath &fileName); - - ProjectExplorer::Tasks projectIssues(const ProjectExplorer::Kit *k) const final; - - // Keep for compatibility with Qt Creator 4.10 - QVariantMap toMap() const final; - - QStringList excludedFiles() const; - void setExcludedFiles(const QStringList &excludedFiles); - -protected: - // Keep for compatibility with Qt Creator 4.10 - RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) final; - - QStringList m_excludedFiles; + NimProjectFactory(); }; -} // namespace Nim +} // Nim From ec43a6c005cd719e80305f9f1666c1a7f1be7bd1 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 6 Jan 2023 09:47:53 +0100 Subject: [PATCH 09/12] QmlProjectManager: FilePathify further Change-Id: I8d83cc93778f8786c30e0aaef459c51005139b19 Reviewed-by: Alessandro Portale Reviewed-by: Artem Sokolovskii Reviewed-by: --- .../qmlpreview/qmlpreviewruncontrol.cpp | 9 ++-- .../qmlprojectmanager/qmlmainfileaspect.cpp | 54 +++++++++---------- .../qmlprojectmanager/qmlmainfileaspect.h | 14 ++--- src/plugins/qmlprojectmanager/qmlproject.cpp | 37 ++++++------- src/plugins/qmlprojectmanager/qmlproject.h | 6 +-- .../qmlprojectrunconfiguration.cpp | 6 +-- 6 files changed, 61 insertions(+), 65 deletions(-) diff --git a/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp b/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp index dab9af41364..57088ad19bf 100644 --- a/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp +++ b/src/plugins/qmlpreview/qmlpreviewruncontrol.cpp @@ -173,18 +173,17 @@ public: runControl->target()->buildSystem()); QTC_ASSERT(qmlBuildSystem, return); - const QString mainScript = aspect->mainScript; - const QString currentFile = aspect->currentFile; + const FilePath mainScript = aspect->mainScript; + const FilePath currentFile = aspect->currentFile; - const QString mainScriptFromProject = qmlBuildSystem->targetFile( - FilePath::fromString(mainScript)).path(); + const QString mainScriptFromProject = qmlBuildSystem->targetFile(mainScript).path(); QStringList qmlProjectRunConfigurationArguments = cmd.splitArguments(); if (!currentFile.isEmpty() && qmlProjectRunConfigurationArguments.last().contains(mainScriptFromProject)) { qmlProjectRunConfigurationArguments.removeLast(); cmd = CommandLine(cmd.executable(), qmlProjectRunConfigurationArguments); - cmd.addArg(currentFile); + cmd.addArg(currentFile.path()); } } diff --git a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp index 820f85085cf..08e236504d7 100644 --- a/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp +++ b/src/plugins/qmlprojectmanager/qmlmainfileaspect.cpp @@ -32,9 +32,9 @@ namespace QmlProjectManager { const char M_CURRENT_FILE[] = "CurrentFile"; const char CURRENT_FILE[] = QT_TRANSLATE_NOOP("::QmlProjectManager", ""); -static bool caseInsensitiveLessThan(const QString &s1, const QString &s2) +static bool caseInsensitiveLessThan(const FilePath &s1, const FilePath &s2) { - return s1.toLower() < s2.toLower(); + return s1.toString().toCaseFolded() < s2.toString().toCaseFolded(); } QmlMainFileAspect::QmlMainFileAspect(Target *target) @@ -89,12 +89,12 @@ void QmlMainFileAspect::fromMap(const QVariantMap &map) void QmlMainFileAspect::updateFileComboBox() { - QDir projectDir(m_target->project()->projectDirectory().toString()); + const FilePath projectDir = m_target->project()->projectDirectory(); if (mainScriptSource() == FileInProjectFile) { - const QString mainScriptInFilePath = projectDir.relativeFilePath(mainScript()); + const FilePath mainScriptInFilePath = projectDir.relativeChildPath(mainScript()); m_fileListModel.clear(); - m_fileListModel.appendRow(new QStandardItem(mainScriptInFilePath)); + m_fileListModel.appendRow(new QStandardItem(mainScriptInFilePath.toString())); if (m_fileListCombo) m_fileListCombo->setEnabled(false); return; @@ -106,27 +106,25 @@ void QmlMainFileAspect::updateFileComboBox() m_fileListModel.appendRow(new QStandardItem(CURRENT_FILE)); QModelIndex currentIndex; - QStringList sortedFiles = Utils::transform(m_target->project()->files(Project::SourceFiles), - &Utils::FilePath::toString); + FilePaths sortedFiles = m_target->project()->files(Project::SourceFiles); // make paths relative to project directory - QStringList relativeFiles; - for (const QString &fn : std::as_const(sortedFiles)) - relativeFiles += projectDir.relativeFilePath(fn); + FilePaths relativeFiles; + for (const FilePath &fn : std::as_const(sortedFiles)) + relativeFiles += projectDir.relativeChildPath(fn); sortedFiles = relativeFiles; std::stable_sort(sortedFiles.begin(), sortedFiles.end(), caseInsensitiveLessThan); - QString mainScriptPath; + FilePath mainScriptPath; if (mainScriptSource() != FileInEditor) - mainScriptPath = projectDir.relativeFilePath(mainScript()); + mainScriptPath = projectDir.relativeChildPath(mainScript()); - for (const QString &fn : std::as_const(sortedFiles)) { - QFileInfo fileInfo(fn); - if (fileInfo.suffix() != "qml") + for (const FilePath &fn : std::as_const(sortedFiles)) { + if (fn.suffixView() != u"qml") continue; - auto item = new QStandardItem(fn); + auto item = new QStandardItem(fn.toString()); m_fileListModel.appendRow(item); if (mainScriptPath == fn) @@ -170,7 +168,7 @@ void QmlMainFileAspect::setScriptSource(MainScriptSource source, const QString & m_mainScriptFilename.clear(); } else { // FileInSettings m_scriptFile = settingsPath; - m_mainScriptFilename = m_target->project()->projectDirectory().toString() + '/' + m_scriptFile; + m_mainScriptFilename = m_target->project()->projectDirectory() / m_scriptFile; } emit changed(); @@ -180,14 +178,11 @@ void QmlMainFileAspect::setScriptSource(MainScriptSource source, const QString & /** Returns absolute path to main script file. */ -QString QmlMainFileAspect::mainScript() const +FilePath QmlMainFileAspect::mainScript() const { if (!qmlBuildSystem()->mainFile().isEmpty()) { - const QString pathInProject = qmlBuildSystem()->mainFile(); - if (QFileInfo(pathInProject).isAbsolute()) - return pathInProject; - else - return QDir(qmlBuildSystem()->canonicalProjectDir().toString()).absoluteFilePath(pathInProject); + const FilePath pathInProject = qmlBuildSystem()->mainFile(); + return qmlBuildSystem()->canonicalProjectDir().resolvePath(pathInProject); } if (!m_mainScriptFilename.isEmpty()) @@ -196,7 +191,7 @@ QString QmlMainFileAspect::mainScript() const return m_currentFileFilename; } -QString QmlMainFileAspect::currentFile() const +FilePath QmlMainFileAspect::currentFile() const { return m_currentFileFilename; } @@ -207,7 +202,7 @@ void QmlMainFileAspect::changeCurrentFile(Core::IEditor *editor) editor = EditorManager::currentEditor(); if (editor) - m_currentFileFilename = editor->document()->filePath().toString(); + m_currentFileFilename = editor->document()->filePath(); emit changed(); } @@ -219,7 +214,7 @@ bool QmlMainFileAspect::isQmlFilePresent() IDocument *document = EditorManager::currentDocument(); const MimeType mainScriptMimeType = mimeTypeForFile(mainScript()); if (document) { - m_currentFileFilename = document->filePath().toString(); + m_currentFileFilename = document->filePath(); if (mainScriptMimeType.matchesName(ProjectExplorer::Constants::QML_MIMETYPE) || mainScriptMimeType.matchesName(ProjectExplorer::Constants::QMLUI_MIMETYPE)) { qmlFileFound = true; @@ -229,13 +224,13 @@ bool QmlMainFileAspect::isQmlFilePresent() || mainScriptMimeType.matchesName(QmlJSTools::Constants::QMLPROJECT_MIMETYPE)) { // find a qml file with lowercase filename. This is slow, but only done // in initialization/other border cases. - const auto files = m_target->project()->files(Project::SourceFiles); + const FilePaths files = m_target->project()->files(Project::SourceFiles); for (const FilePath &filename : files) { if (!filename.isEmpty() && filename.baseName().at(0).isLower()) { const MimeType type = mimeTypeForFile(filename); if (type.matchesName(ProjectExplorer::Constants::QML_MIMETYPE) || type.matchesName(ProjectExplorer::Constants::QMLUI_MIMETYPE)) { - m_currentFileFilename = filename.toString(); + m_currentFileFilename = filename; qmlFileFound = true; break; } @@ -252,4 +247,5 @@ QmlBuildSystem *QmlMainFileAspect::qmlBuildSystem() const { return static_cast(m_target->buildSystem()); } -} // namespace QmlProjectManager + +} // QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlmainfileaspect.h b/src/plugins/qmlprojectmanager/qmlmainfileaspect.h index 4ec23dc2cd5..b71fa6784b8 100644 --- a/src/plugins/qmlprojectmanager/qmlmainfileaspect.h +++ b/src/plugins/qmlprojectmanager/qmlmainfileaspect.h @@ -38,8 +38,8 @@ public: struct Data : BaseAspect::Data { - QString mainScript; - QString currentFile; + Utils::FilePath mainScript; + Utils::FilePath currentFile; }; void addToLayout(Utils::Layouting::LayoutBuilder &builder) final; @@ -52,8 +52,8 @@ public: void setScriptSource(MainScriptSource source, const QString &settingsPath = QString()); - QString mainScript() const; - QString currentFile() const; + Utils::FilePath mainScript() const; + Utils::FilePath currentFile() const; void changeCurrentFile(Core::IEditor *editor = nullptr); bool isQmlFilePresent(); QmlBuildSystem *qmlBuildSystem() const; @@ -64,9 +64,9 @@ public: QStandardItemModel m_fileListModel; QString m_scriptFile; // absolute path to current file (if being used) - QString m_currentFileFilename; + Utils::FilePath m_currentFileFilename; // absolute path to selected main script (if being used) - QString m_mainScriptFilename; + Utils::FilePath m_mainScriptFilename; }; -} // namespace QmlProjectManager +} // QmlProjectManager diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 6ce64397796..c283ec73e31 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -250,7 +250,9 @@ void QmlBuildSystem::parseProject(RefreshOptions options) } } -bool QmlBuildSystem::setFileSettingInProjectFile(const QString &setting, const Utils::FilePath &mainFilePath, const QString &oldFile) +bool QmlBuildSystem::setFileSettingInProjectFile(const QString &setting, + const FilePath &mainFilePath, + const FilePath &oldFile) { // make sure to change it also in the qmlproject file const Utils::FilePath qmlProjectFilePath = project()->projectFilePath(); @@ -283,7 +285,7 @@ bool QmlBuildSystem::setFileSettingInProjectFile(const QString &setting, const U auto index = fileContent.lastIndexOf("}"); fileContent.insert(index, addedText); } else { - QString originalFileName = oldFile; + QString originalFileName = oldFile.path(); originalFileName.replace(".", "\\."); const QRegularExpression expression(QString("%1\\s*\"(%2)\"").arg(settingQmlCode).arg(originalFileName)); @@ -328,43 +330,42 @@ void QmlBuildSystem::refresh(RefreshOptions options) emit projectChanged(); } -QString QmlBuildSystem::mainFile() const +FilePath QmlBuildSystem::mainFile() const { if (m_projectItem) - return m_projectItem->mainFile(); - return QString(); + return FilePath::fromString(m_projectItem->mainFile()); + return {}; } -QString QmlBuildSystem::mainUiFile() const +FilePath QmlBuildSystem::mainUiFile() const { if (m_projectItem) - return m_projectItem->mainUiFile(); - return QString(); + return FilePath::fromString(m_projectItem->mainUiFile()); + return {}; } -Utils::FilePath QmlBuildSystem::mainFilePath() const +FilePath QmlBuildSystem::mainFilePath() const { - return projectDirectory().pathAppended(mainFile()); + return projectDirectory().resolvePath(mainFile()); } -Utils::FilePath QmlBuildSystem::mainUiFilePath() const +FilePath QmlBuildSystem::mainUiFilePath() const { - return projectDirectory().pathAppended(mainUiFile()); + return projectDirectory().resolvePath(mainUiFile()); } -bool QmlBuildSystem::setMainFileInProjectFile(const Utils::FilePath &newMainFilePath) +bool QmlBuildSystem::setMainFileInProjectFile(const FilePath &newMainFilePath) { - return setFileSettingInProjectFile("mainFile", newMainFilePath, mainFile()); } -bool QmlBuildSystem::setMainUiFileInProjectFile(const Utils::FilePath &newMainUiFilePath) +bool QmlBuildSystem::setMainUiFileInProjectFile(const FilePath &newMainUiFilePath) { return setMainUiFileInMainFile(newMainUiFilePath) && setFileSettingInProjectFile("mainUiFile", newMainUiFilePath, mainUiFile()); } -bool QmlBuildSystem::setMainUiFileInMainFile(const Utils::FilePath &newMainUiFilePath) +bool QmlBuildSystem::setMainUiFileInMainFile(const FilePath &newMainUiFilePath) { Core::FileChangeBlocker fileChangeBlocker(mainFilePath()); const QList editors = Core::DocumentModel::editorsForFilePath(mainFilePath()); @@ -793,9 +794,9 @@ bool QmlBuildSystem::deleteFiles(Node *context, const FilePaths &filePaths) bool QmlBuildSystem::renameFile(Node * context, const FilePath &oldFilePath, const FilePath &newFilePath) { if (dynamic_cast(context)) { - if (oldFilePath.endsWith(mainFile())) + if (oldFilePath.endsWith(mainFile().path())) return setMainFileInProjectFile(newFilePath); - if (oldFilePath.endsWith(mainUiFile())) + if (oldFilePath.endsWith(mainUiFile().path())) return setMainUiFileInProjectFile(newFilePath); return true; diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index ed52764f0a0..e7387e030ae 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -53,8 +53,8 @@ public: void refresh(RefreshOptions options); Utils::FilePath canonicalProjectDir() const; - QString mainFile() const; - QString mainUiFile() const; + Utils::FilePath mainFile() const; + Utils::FilePath mainUiFile() const; Utils::FilePath mainFilePath() const; Utils::FilePath mainUiFilePath() const; @@ -106,7 +106,7 @@ signals: private: bool setFileSettingInProjectFile(const QString &setting, const Utils::FilePath &mainFilePath, - const QString &oldFile); + const Utils::FilePath &oldFile); std::unique_ptr m_projectItem; Utils::FilePath m_canonicalProjectDir; diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 081a0bec574..8e8527b32c0 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -54,7 +54,7 @@ private: QString disabledReason() const final; bool isEnabled() const final; - QString mainScript() const; + FilePath mainScript() const; FilePath qmlRuntimeFilePath() const; void createQtVersionAspect(); @@ -108,7 +108,7 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(Target *target, Id id) cmd.addArg("widget"); } - const FilePath main = bs->targetFile(FilePath::fromString(mainScript())); + const FilePath main = bs->targetFile(mainScript()); if (!main.isEmpty()) cmd.addArg(main.nativePath()); @@ -292,7 +292,7 @@ bool QmlProjectRunConfiguration::isEnabled() const && activeBuildSystem()->hasParsingData(); } -QString QmlProjectRunConfiguration::mainScript() const +FilePath QmlProjectRunConfiguration::mainScript() const { return m_qmlMainFileAspect->mainScript(); } From 53696ee71e8b0b06d9c71d14fa581abbb5d7cab4 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Sat, 28 Jan 2023 15:23:22 +0900 Subject: [PATCH 10/12] SessionNameInputDialog: disable accept buttons when name is empty Change-Id: I2a12d7b6e130adaed5bf724a27828feca72f0512 Reviewed-by: Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/sessiondialog.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/projectexplorer/sessiondialog.cpp b/src/plugins/projectexplorer/sessiondialog.cpp index cef6f34b06e..53edd115511 100644 --- a/src/plugins/projectexplorer/sessiondialog.cpp +++ b/src/plugins/projectexplorer/sessiondialog.cpp @@ -83,6 +83,13 @@ SessionNameInputDialog::SessionNameInputDialog(QWidget *parent) buttons, }.attachTo(this); + connect(m_newSessionLineEdit, &QLineEdit::textChanged, [this](const QString &text) { + m_okButton->setEnabled(!text.isEmpty()); + m_switchToButton->setEnabled(!text.isEmpty()); + }); + m_okButton->setEnabled(false); + m_switchToButton->setEnabled(false); + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); } From 3d79244dd5d1ab375faa61f4d96b180985ff06f4 Mon Sep 17 00:00:00 2001 From: Tasuku Suzuki Date: Sat, 28 Jan 2023 15:17:41 +0900 Subject: [PATCH 11/12] SessionNameInputDialog: change default button to "... and Open" When one create/rename/clone a sesion, they will likely use the session. Change-Id: I41d4e3c24833009a42385146fd2bb5a719465eba Reviewed-by: Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/sessiondialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/projectexplorer/sessiondialog.cpp b/src/plugins/projectexplorer/sessiondialog.cpp index 53edd115511..745a876230a 100644 --- a/src/plugins/projectexplorer/sessiondialog.cpp +++ b/src/plugins/projectexplorer/sessiondialog.cpp @@ -71,6 +71,7 @@ SessionNameInputDialog::SessionNameInputDialog(QWidget *parent) auto buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this); m_okButton = buttons->button(QDialogButtonBox::Ok); m_switchToButton = new QPushButton; + m_switchToButton->setDefault(true); buttons->addButton(m_switchToButton, QDialogButtonBox::AcceptRole); connect(m_switchToButton, &QPushButton::clicked, this, [this] { m_usedSwitchTo = true; From 862f484af59cea06b99a743316c2ffcc0a252686 Mon Sep 17 00:00:00 2001 From: Yasser Grimes Date: Thu, 19 Jan 2023 10:17:21 +0200 Subject: [PATCH 12/12] McuSupport: Extend CMake targets tree for QtMCUs QmlProject projects CMake project relies on the CMake's file-api to fill the Project View, QtMCUs 2.4 will be using a different method to read input files (Qml, Fonts, Images, Headers...) using qmlprojectexporter process, that process is still called from CMake thus a CMakeProject is still used in QtMCUs kits, but unlike previous versions add_sources is not called on QtMCUs target making the list of input files read by the file-api empty and as a result an empty Project Tree. This commit extend uses the SessionManager to listen to when the the projects are loaded and then use input.json file to populate QtMCUs projects trees for projects using qmlprojectexporter the same tool generating input.json . Task-number: QTCREATORBUG-28516 Change-Id: I30a9daf1032e727692b8d71d01ab65634d0ae2a6 Reviewed-by: Christian Kandeler Reviewed-by: Reviewed-by: hjk --- .../cmakeprojectconstants.h | 2 + .../cmakeprojectmanager/cmakeprojectnodes.cpp | 3 + src/plugins/mcusupport/CMakeLists.txt | 1 + src/plugins/mcusupport/mcuqmlprojectnode.cpp | 96 +++++++++++++++++++ src/plugins/mcusupport/mcuqmlprojectnode.h | 47 +++++++++ src/plugins/mcusupport/mcusupport.qbs | 2 + src/plugins/mcusupport/mcusupportplugin.cpp | 48 ++++++++++ 7 files changed, 199 insertions(+) create mode 100644 src/plugins/mcusupport/mcuqmlprojectnode.cpp create mode 100644 src/plugins/mcusupport/mcuqmlprojectnode.h diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h index 0f01cc69c5d..2d4cd089a0c 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h @@ -62,6 +62,8 @@ const char CMAKE_FEATURE_ID[] = "CMakeProjectManager.Wizard.FeatureCMake"; // Tool const char TOOL_ID[] = "CMakeProjectManager.CMakeKitInformation"; +// Data +const char BUILD_FOLDER_ROLE[] = "CMakeProjectManager.data.buildFolder"; } // namespace Constants } // namespace CMakeProjectManager diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp index cd300916253..36016aa0c94 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp @@ -108,6 +108,9 @@ QVariant CMakeTargetNode::data(Id role) const return {}; }; + if (role == Constants::BUILD_FOLDER_ROLE) + return m_buildDirectory.toVariant(); + if (role == Android::Constants::AndroidAbi) return value(Android::Constants::ANDROID_ABI); diff --git a/src/plugins/mcusupport/CMakeLists.txt b/src/plugins/mcusupport/CMakeLists.txt index 57b12dd1b04..778f0a70394 100644 --- a/src/plugins/mcusupport/CMakeLists.txt +++ b/src/plugins/mcusupport/CMakeLists.txt @@ -22,6 +22,7 @@ add_qtc_plugin(McuSupport mcutargetdescription.h mcuhelpers.cpp mcuhelpers.h settingshandler.cpp settingshandler.h + mcuqmlprojectnode.cpp mcuqmlprojectnode.h ) add_subdirectory(test) diff --git a/src/plugins/mcusupport/mcuqmlprojectnode.cpp b/src/plugins/mcusupport/mcuqmlprojectnode.cpp new file mode 100644 index 00000000000..9b1c1caf89d --- /dev/null +++ b/src/plugins/mcusupport/mcuqmlprojectnode.cpp @@ -0,0 +1,96 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "mcuqmlprojectnode.h" + +#include + +namespace McuSupport::Internal { + +using namespace ProjectExplorer; +using namespace Utils; + +McuQmlProjectNode::McuQmlProjectNode(const FilePath &projectFolder, const FilePath &inputsJsonFile) + : FolderNode(projectFolder) +{ + setDisplayName("QmlProject"); + setIcon(DirectoryIcon(":/projectexplorer/images/fileoverlay_qml.png")); + setIsGenerated(false); + setPriority(Node::DefaultProjectPriority); + setFilePath(projectFolder); + setListInProject(true); + + const expected_str expectedJsonContent = inputsJsonFile.fileContents(); + if (!expectedJsonContent) + return; + + const QJsonDocument inputDoc = QJsonDocument::fromJson(*expectedJsonContent); + const QVariantMap mainProjectObject = inputDoc.object().toVariantMap(); + const FilePath mainProjectFilePath = FilePath::fromUserInput( + mainProjectObject.value("qmlProjectFile", "").toString()); + + auto mainFileNode = std::make_unique(mainProjectFilePath, + FileNode::fileTypeForFileName( + mainProjectFilePath)); + mainFileNode->setPriority(100); + addNestedNode(std::move(mainFileNode)); + + this->populateModuleNode(this, mainProjectObject); + + auto modulesNode = std::make_unique(filePath()); + modulesNode->setDisplayName("QmlProject Modules"); + modulesNode->setIcon(DirectoryIcon(":/projectexplorer/images/fileoverlay_modules.png")); + modulesNode->setPriority(10); + for (QVariant moduleVariant : mainProjectObject.value("modulesDependencies", {}).toList()) { + const QVariantMap moduleObject = moduleVariant.toMap(); + auto moduleNode = std::make_unique(filePath()); + moduleNode->setIcon(DirectoryIcon(":/projectexplorer/images/fileoverlay_qml.png")); + moduleNode->setDisplayName( + FilePath::fromUserInput(moduleObject.value("qmlProjectFile", "module").toString()) + .baseName()); + populateModuleNode(moduleNode.get(), moduleObject); + modulesNode->addNode(std::move(moduleNode)); + } + addNode(std::move(modulesNode)); +} + +bool McuQmlProjectNode::populateModuleNode(FolderNode *moduleNode, const QVariantMap &moduleObject) +{ + if (!moduleNode) + return false; + + const static int NODES_COUNT = 6; + const static QString nodes[NODES_COUNT] = {"QmlFiles", + "ImageFiles", + "InterfaceFiles", + "FontFiles", + "TranslationFiles", + "ModuleFiles"}; + const static QString icons[NODES_COUNT] = {":/projectexplorer/images/fileoverlay_qml.png", + ":/projectexplorer/images/fileoverlay_qrc.png", + ":/projectexplorer/images/fileoverlay_h.png", + ":/projectexplorer/images/fileoverlay_qrc.png", + ":/projectexplorer/images/fileoverlay_qrc.png", + ":/projectexplorer/images/fileoverlay_qml.png"}; + const static int priorities[NODES_COUNT] = {70, 60, 50, 40, 30, 20}; + + for (int i = 0; i < NODES_COUNT; i++) { + const QString &node = nodes[i]; + const QString &icon = icons[i]; + const int &p = priorities[i]; + auto foldernode = std::make_unique(filePath()); + foldernode->setShowWhenEmpty(false); + foldernode->setDisplayName(node); + foldernode->setIcon(DirectoryIcon(icon)); + foldernode->setPriority(p); + const auto nodeFiles = moduleObject.value(node, {}).toStringList(); + for (auto p : nodeFiles) { + const FilePath nodePath = FilePath::fromUserInput(p); + foldernode->addNestedNode( + std::make_unique(nodePath, FileNode::fileTypeForFileName(nodePath))); + } + moduleNode->addNode(std::move(foldernode)); + } + return true; +} +} // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/mcuqmlprojectnode.h b/src/plugins/mcusupport/mcuqmlprojectnode.h new file mode 100644 index 00000000000..2a06e5cde55 --- /dev/null +++ b/src/plugins/mcusupport/mcuqmlprojectnode.h @@ -0,0 +1,47 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "mcuqmlprojectnode.h" +#include "mcusupport_global.h" +#include "mcusupportplugin.h" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace McuSupport::Internal { + +using namespace ProjectExplorer; +using namespace Utils; + +class McuQmlProjectFolderNode : public FolderNode +{ +public: + explicit McuQmlProjectFolderNode(const FilePath &path) + : FolderNode(path) + {} + bool showInSimpleTree() const override { return true; } +}; + +class McuQmlProjectNode : public FolderNode +{ +public: + explicit McuQmlProjectNode(const FilePath &projectFolder, const FilePath &inputsJsonFile); + bool showInSimpleTree() const override { return true; } + bool populateModuleNode(FolderNode *moduleNode, const QVariantMap &moduleObject); +}; +}; // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/mcusupport.qbs b/src/plugins/mcusupport/mcusupport.qbs index efd14b453b0..e6aec151a06 100644 --- a/src/plugins/mcusupport/mcusupport.qbs +++ b/src/plugins/mcusupport/mcusupport.qbs @@ -37,6 +37,8 @@ QtcPlugin { "mcusupportoptions.h", "mcukitmanager.cpp", "mcukitmanager.h", + "mcuqmlprojectnode.cpp", + "mcuqmlprojectnode.h", "mcusupportoptionspage.cpp", "mcusupportoptionspage.h", "mcusupportplugin.cpp", diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp index 835e619a3ce..8e873785916 100644 --- a/src/plugins/mcusupport/mcusupportplugin.cpp +++ b/src/plugins/mcusupport/mcusupportplugin.cpp @@ -5,6 +5,7 @@ #include "mcukitinformation.h" #include "mcukitmanager.h" +#include "mcuqmlprojectnode.h" #include "mcusupportconstants.h" #include "mcusupportdevice.h" #include "mcusupportoptions.h" @@ -24,8 +25,15 @@ #include #include #include +#include #include +#include +#include +#include +#include + +#include #include #include @@ -49,6 +57,42 @@ void printMessage(const QString &message, bool important) Core::MessageManager::writeSilently(displayMessage); } +void updateMCUProjectTree(ProjectExplorer::Project *p) +{ + if (!p || !p->rootProjectNode()) + return; + ProjectExplorer::Target *target = p->activeTarget(); + if (!target || !target->kit() + || !target->kit()->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY)) + return; + + p->rootProjectNode()->forEachProjectNode([](const ProjectNode *node) { + if (!node) + return; + + const FilePath projectBuildFolder = FilePath::fromVariant( + node->data(CMakeProjectManager::Constants::BUILD_FOLDER_ROLE)); + const QString targetName = node->displayName(); + if (targetName.isEmpty()) + return; + + const FilePath inputsJsonFile = projectBuildFolder / "CMakeFiles" / (targetName + ".dir") + / "config/input.json"; + + printMessage("found Input json file " + inputsJsonFile.absoluteFilePath().toString(), true); + + if (!inputsJsonFile.exists()) + return; + + auto qmlProjectNode = std::make_unique(FilePath(node->filePath()), + inputsJsonFile); + + auto qmlProjectNodePtr = qmlProjectNode.get(); + const_cast(node)->addNode(std::move(qmlProjectNode)); + ProjectExplorer::ProjectTree::emitSubtreeChanged(qmlProjectNodePtr); + }); +}; + class McuSupportPluginPrivate { public: @@ -74,6 +118,10 @@ void McuSupportPlugin::initialize() setObjectName("McuSupportPlugin"); dd = new McuSupportPluginPrivate; + connect(SessionManager::instance(), + &SessionManager::projectFinishedParsing, + updateMCUProjectTree); + dd->m_options.registerQchFiles(); dd->m_options.registerExamples(); ProjectExplorer::JsonWizardFactory::addWizardPath(":/mcusupport/wizards/");