From 3f0cf6d6ac56049745968554376e6e5e6b17e691 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 15 Feb 2022 14:56:48 +0100 Subject: [PATCH 01/76] CppEditor: Do not consider generated access specifiers ... when looking for places to insert class members. Apparently, these can come from other translation units and thus have invalid offsets. Fixes: QTCREATORBUG-27063 Change-Id: Ia9a318284c0a8f4dd280315a5b47eac7ffd96a30 Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Christian Stenger --- src/plugins/cppeditor/insertionpointlocator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/cppeditor/insertionpointlocator.cpp b/src/plugins/cppeditor/insertionpointlocator.cpp index 7d657bacc3b..fceb9a96055 100644 --- a/src/plugins/cppeditor/insertionpointlocator.cpp +++ b/src/plugins/cppeditor/insertionpointlocator.cpp @@ -177,6 +177,8 @@ QList collectAccessRanges(const CPlusPlus::TranslationUnit *tu, if (AccessDeclarationAST *xsDecl = decl->asAccessDeclaration()) { const unsigned token = xsDecl->access_specifier_token; + if (tu->tokenAt(token).generated()) + continue; InsertionPointLocator::AccessSpec newXsSpec = initialXs; bool isSlot = xsDecl->slots_token && tu->tokenKind(xsDecl->slots_token) == T_Q_SLOTS; From 76453511cc3b914dfd4c192fdcbce9c66313bcf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Mu=C4=87ko?= Date: Tue, 15 Feb 2022 11:18:56 +0100 Subject: [PATCH 02/76] McuSupport: plugin code formatting Change-Id: I2d1c3dfad3fddce7706056997d284292e13d3ad2 Reviewed-by: hjk (cherry picked from commit 27cadc86ba0ba7ae50c70f0930df8a96d210d7ed) --- src/plugins/mcusupport/mcukitinformation.cpp | 28 +- src/plugins/mcusupport/mcupackage.cpp | 116 +++--- src/plugins/mcusupport/mcupackage.h | 14 +- src/plugins/mcusupport/mcusupport_global.h | 4 +- .../mcusupport/mcusupportcmakemapper.cpp | 36 +- src/plugins/mcusupport/mcusupportconstants.h | 2 +- src/plugins/mcusupport/mcusupportdevice.cpp | 2 +- src/plugins/mcusupport/mcusupportoptions.cpp | 389 +++++++++--------- src/plugins/mcusupport/mcusupportoptions.h | 32 +- .../mcusupport/mcusupportoptionspage.cpp | 82 ++-- src/plugins/mcusupport/mcusupportplugin.cpp | 21 +- .../mcusupport/mcusupportrunconfiguration.cpp | 10 +- src/plugins/mcusupport/mcusupportsdk.cpp | 357 +++++++++------- src/plugins/mcusupport/mcusupportsdk.h | 5 +- .../mcusupport/mcusupportversiondetection.cpp | 50 +-- .../mcusupport/mcusupportversiondetection.h | 12 +- src/plugins/mcusupport/test/packagemock.h | 4 +- src/plugins/mcusupport/test/unittest.cpp | 2 +- src/plugins/mcusupport/test/unittest.h | 2 +- 19 files changed, 618 insertions(+), 550 deletions(-) diff --git a/src/plugins/mcusupport/mcukitinformation.cpp b/src/plugins/mcusupport/mcukitinformation.cpp index f72fef1f2e7..2ab9af35d30 100644 --- a/src/plugins/mcusupport/mcukitinformation.cpp +++ b/src/plugins/mcusupport/mcukitinformation.cpp @@ -64,21 +64,24 @@ Tasks McuDependenciesKitAspect::validate(const Kit *k) const const QVariant checkFormat = k->value(McuDependenciesKitAspect::id()); if (!checkFormat.isNull() && !checkFormat.canConvert(QVariant::List)) - return { BuildSystemTask(Task::Error, tr("The MCU dependencies setting value is invalid.")) }; + return {BuildSystemTask(Task::Error, tr("The MCU dependencies setting value is invalid."))}; const QVariant envStringList = k->value(EnvironmentKitAspect::id()); if (!envStringList.isNull() && !envStringList.canConvert(QVariant::List)) - return { BuildSystemTask(Task::Error, tr("The environment setting value is invalid.")) }; + return {BuildSystemTask(Task::Error, tr("The environment setting value is invalid."))}; const auto environment = Utils::NameValueDictionary(envStringList.toStringList()); - for (const auto &dependency: dependencies(k)) { + for (const auto &dependency : dependencies(k)) { if (!environment.hasKey(dependency.name)) { - result << BuildSystemTask(Task::Warning, tr("Environment variable %1 not defined.").arg(dependency.name)); + result << BuildSystemTask(Task::Warning, + tr("Environment variable %1 not defined.") + .arg(dependency.name)); } else { - const auto path = Utils::FilePath::fromUserInput( - environment.value(dependency.name) + "/" + dependency.value); + const auto path = Utils::FilePath::fromUserInput(environment.value(dependency.name) + + "/" + dependency.value); if (!path.exists()) { - result << BuildSystemTask(Task::Warning, tr("%1 not found.").arg(path.toUserOutput())); + result << BuildSystemTask(Task::Warning, + tr("%1 not found.").arg(path.toUserOutput())); } } } @@ -115,18 +118,19 @@ Utils::Id McuDependenciesKitAspect::id() return "PE.Profile.McuDependencies"; } - Utils::NameValueItems McuDependenciesKitAspect::dependencies(const Kit *k) { - if (k) - return Utils::NameValueItem::fromStringList(k->value(McuDependenciesKitAspect::id()).toStringList()); - return Utils::NameValueItems(); + if (k) + return Utils::NameValueItem::fromStringList( + k->value(McuDependenciesKitAspect::id()).toStringList()); + return Utils::NameValueItems(); } void McuDependenciesKitAspect::setDependencies(Kit *k, const Utils::NameValueItems &dependencies) { if (k) - k->setValue(McuDependenciesKitAspect::id(), Utils::NameValueItem::toStringList(dependencies)); + k->setValue(McuDependenciesKitAspect::id(), + Utils::NameValueItem::toStringList(dependencies)); } } // namespace Internal diff --git a/src/plugins/mcusupport/mcupackage.cpp b/src/plugins/mcusupport/mcupackage.cpp index bf797e0aa5b..b27752e79e2 100644 --- a/src/plugins/mcusupport/mcupackage.cpp +++ b/src/plugins/mcusupport/mcupackage.cpp @@ -43,15 +43,18 @@ namespace McuSupport::Internal { static bool automaticKitCreationFromSettings(QSettings::Scope scope = QSettings::UserScope) { QSettings *settings = Core::ICore::settings(scope); - const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + - QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION); + const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + + QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION); bool automaticKitCreation = settings->value(key, true).toBool(); return automaticKitCreation; } -McuPackage::McuPackage(const QString &label, const FilePath &defaultPath, - const QString &detectionPath, const QString &settingsKey, - const QString &envVarName, const QString &downloadUrl, +McuPackage::McuPackage(const QString &label, + const FilePath &defaultPath, + const QString &detectionPath, + const QString &settingsKey, + const QString &envVarName, + const QString &downloadUrl, const McuPackageVersionDetector *versionDetector) : m_label(label) , m_defaultPath(Sdk::packagePathFromSettings(settingsKey, QSettings::SystemScope, defaultPath)) @@ -97,8 +100,7 @@ QWidget *McuPackage::widget() m_widget = new QWidget; m_fileChooser = new PathChooser; - m_fileChooser->lineEdit()->setButtonIcon(FancyLineEdit::Right, - Icons::RESET.icon()); + m_fileChooser->lineEdit()->setButtonIcon(FancyLineEdit::Right, Icons::RESET.icon()); m_fileChooser->lineEdit()->setButtonVisible(FancyLineEdit::Right, true); connect(m_fileChooser->lineEdit(), &FancyLineEdit::rightButtonClicked, this, [&] { m_fileChooser->setFilePath(m_defaultPath); @@ -123,9 +125,7 @@ QWidget *McuPackage::widget() m_fileChooser->setFilePath(m_path); - QObject::connect(this, &McuPackage::statusChanged, this, [this] { - updateStatusUi(); - }); + QObject::connect(this, &McuPackage::statusChanged, this, [this] { updateStatusUi(); }); QObject::connect(m_fileChooser, &PathChooser::pathChanged, this, [this] { updatePath(); @@ -163,17 +163,19 @@ bool McuPackage::addToPath() const void McuPackage::writeGeneralSettings() const { - const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + - QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION); + const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + + QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION); QSettings *settings = Core::ICore::settings(); settings->setValue(key, m_automaticKitCreation); } bool McuPackage::writeToSettings() const { - const FilePath savedPath = Sdk::packagePathFromSettings(m_settingsKey, QSettings::UserScope, m_defaultPath); - const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + - QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey; + const FilePath savedPath = Sdk::packagePathFromSettings(m_settingsKey, + QSettings::UserScope, + m_defaultPath); + const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + + QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey; Core::ICore::settings()->setValueWithDefault(key, m_path.toString(), m_defaultPath.toString()); return savedPath != m_path; @@ -201,9 +203,9 @@ void McuPackage::setAutomaticKitCreationEnabled(const bool enabled) void McuPackage::updatePath() { - m_path = m_fileChooser->rawFilePath(); - m_fileChooser->lineEdit()->button(FancyLineEdit::Right)->setEnabled(m_path != m_defaultPath); - updateStatus(); + m_path = m_fileChooser->rawFilePath(); + m_fileChooser->lineEdit()->button(FancyLineEdit::Right)->setEnabled(m_path != m_defaultPath); + updateStatus(); } void McuPackage::updateStatus() @@ -212,15 +214,16 @@ void McuPackage::updateStatus() const FilePath detectionPath = basePath() / m_detectionPath; const bool validPackage = m_detectionPath.isEmpty() || detectionPath.exists(); m_detectedVersion = validPath && validPackage && m_versionDetector - ? m_versionDetector->parseVersion(basePath().toString()) : QString(); - const bool validVersion = m_detectedVersion.isEmpty() || - m_versions.isEmpty() || m_versions.contains(m_detectedVersion); + ? m_versionDetector->parseVersion(basePath().toString()) + : QString(); + const bool validVersion = m_detectedVersion.isEmpty() || m_versions.isEmpty() + || m_versions.contains(m_detectedVersion); - m_status = validPath ? - ( validPackage ? - (validVersion ? Status::ValidPackage : Status::ValidPackageMismatchedVersion) - : Status::ValidPathInvalidPackage ) - : m_path.isEmpty() ? Status::EmptyPath : Status::InvalidPath; + m_status = validPath ? (validPackage ? (validVersion ? Status::ValidPackage + : Status::ValidPackageMismatchedVersion) + : Status::ValidPathInvalidPackage) + : m_path.isEmpty() ? Status::EmptyPath + : Status::InvalidPath; emit statusChanged(); } @@ -228,9 +231,15 @@ void McuPackage::updateStatus() void McuPackage::updateStatusUi() { switch (m_status) { - case Status::ValidPackage: m_infoLabel->setType(InfoLabel::Ok); break; - case Status::ValidPackageMismatchedVersion: m_infoLabel->setType(InfoLabel::Warning); break; - default: m_infoLabel->setType(InfoLabel::NotOk); break; + case Status::ValidPackage: + m_infoLabel->setType(InfoLabel::Ok); + break; + case Status::ValidPackageMismatchedVersion: + m_infoLabel->setType(InfoLabel::Warning); + break; + default: + m_infoLabel->setType(InfoLabel::NotOk); + break; } m_infoLabel->setText(statusText()); } @@ -240,44 +249,45 @@ QString McuPackage::statusText() const const QString displayPackagePath = m_path.toUserOutput(); const QString displayVersions = m_versions.join(" or "); const QString outDetectionPath = FilePath::fromString(m_detectionPath).toUserOutput(); - const QString displayRequiredPath = m_versions.empty() ? - outDetectionPath : - QString("%1 %2").arg(outDetectionPath, displayVersions); - const QString displayDetectedPath = m_versions.empty() ? - outDetectionPath : - QString("%1 %2").arg(outDetectionPath, m_detectedVersion); + const QString displayRequiredPath = m_versions.empty() ? outDetectionPath + : QString("%1 %2").arg(outDetectionPath, + displayVersions); + const QString displayDetectedPath = m_versions.empty() + ? outDetectionPath + : QString("%1 %2").arg(outDetectionPath, + m_detectedVersion); QString response; switch (m_status) { case Status::ValidPackage: response = m_detectionPath.isEmpty() - ? ( m_detectedVersion.isEmpty() - ? tr("Path %1 exists.").arg(displayPackagePath) - : tr("Path %1 exists. Version %2 was found.") - .arg(displayPackagePath, m_detectedVersion) ) - : tr("Path %1 is valid, %2 was found.") - .arg(displayPackagePath, displayDetectedPath); + ? (m_detectedVersion.isEmpty() + ? tr("Path %1 exists.").arg(displayPackagePath) + : tr("Path %1 exists. Version %2 was found.") + .arg(displayPackagePath, m_detectedVersion)) + : tr("Path %1 is valid, %2 was found.") + .arg(displayPackagePath, displayDetectedPath); break; case Status::ValidPackageMismatchedVersion: { - const QString versionWarning = m_versions.size() == 1 ? - tr("but only version %1 is supported").arg(m_versions.first()) : - tr("but only versions %1 are supported").arg(displayVersions); + const QString versionWarning + = m_versions.size() == 1 + ? tr("but only version %1 is supported").arg(m_versions.first()) + : tr("but only versions %1 are supported").arg(displayVersions); response = tr("Path %1 is valid, %2 was found, %3.") - .arg(displayPackagePath, displayDetectedPath, versionWarning); + .arg(displayPackagePath, displayDetectedPath, versionWarning); break; } case Status::ValidPathInvalidPackage: response = tr("Path %1 exists, but does not contain %2.") - .arg(displayPackagePath, displayRequiredPath); + .arg(displayPackagePath, displayRequiredPath); break; case Status::InvalidPath: response = tr("Path %1 does not exist.").arg(displayPackagePath); break; case Status::EmptyPath: response = m_detectionPath.isEmpty() - ? tr("Path is empty.") - : tr("Path is empty, %1 not found.") - .arg(displayRequiredPath); + ? tr("Path is empty.") + : tr("Path is empty, %1 not found.").arg(displayRequiredPath); break; } return response; @@ -287,12 +297,12 @@ McuToolChainPackage::McuToolChainPackage(const QString &label, const FilePath &defaultPath, const QString &detectionPath, const QString &settingsKey, - McuToolChainPackage::Type type, const QString &envVarName, + McuToolChainPackage::Type type, + const QString &envVarName, const McuPackageVersionDetector *versionDetector) : McuPackage(label, defaultPath, detectionPath, settingsKey, envVarName, {}, versionDetector) , m_type(type) -{ -} +{} McuToolChainPackage::Type McuToolChainPackage::type() const { @@ -304,4 +314,4 @@ bool McuToolChainPackage::isDesktopToolchain() const return m_type == Type::MSVC || m_type == Type::GCC; } -} // namespace McuSupport::Internal +} // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/mcupackage.h b/src/plugins/mcusupport/mcupackage.h index dc933920af9..b7d415fd3f3 100644 --- a/src/plugins/mcusupport/mcupackage.h +++ b/src/plugins/mcusupport/mcupackage.h @@ -119,16 +119,7 @@ private: class McuToolChainPackage : public McuPackage { public: - enum class Type { - IAR, - KEIL, - MSVC, - GCC, - ArmGcc, - GHS, - GHSArm, - Unsupported - }; + enum class Type { IAR, KEIL, MSVC, GCC, ArmGcc, GHS, GHSArm, Unsupported }; McuToolChainPackage(const QString &label, const Utils::FilePath &defaultPath, @@ -136,8 +127,7 @@ public: const QString &settingsKey, Type type, const QString &envVarName = {}, - const McuPackageVersionDetector *versionDetector = nullptr - ); + const McuPackageVersionDetector *versionDetector = nullptr); Type type() const; bool isDesktopToolchain() const; diff --git a/src/plugins/mcusupport/mcusupport_global.h b/src/plugins/mcusupport/mcusupport_global.h index a436f3cf0df..fd92f43c9c6 100644 --- a/src/plugins/mcusupport/mcusupport_global.h +++ b/src/plugins/mcusupport/mcusupport_global.h @@ -28,7 +28,7 @@ #include #if defined(MCUSUPPORT_LIBRARY) -# define MCUSUPPORTSHARED_EXPORT Q_DECL_EXPORT +#define MCUSUPPORTSHARED_EXPORT Q_DECL_EXPORT #else -# define MCUSUPPORTSHARED_EXPORT Q_DECL_IMPORT +#define MCUSUPPORTSHARED_EXPORT Q_DECL_IMPORT #endif diff --git a/src/plugins/mcusupport/mcusupportcmakemapper.cpp b/src/plugins/mcusupport/mcusupportcmakemapper.cpp index 2541cd6d25a..7f69f4f6716 100644 --- a/src/plugins/mcusupport/mcusupportcmakemapper.cpp +++ b/src/plugins/mcusupport/mcusupportcmakemapper.cpp @@ -31,15 +31,15 @@ namespace { static const QHash &envVarToCMakeVarMapping() { static const QHash mapping = { - {"EVK_MIMXRT1060_SDK_PATH","QUL_BOARD_SDK_DIR"}, - {"EVK_MIMXRT1064_SDK_PATH","QUL_BOARD_SDK_DIR"}, - {"EVK_MIMXRT595_SDK_PATH","QUL_BOARD_SDK_DIR"}, - {"EVK_MIMXRT1170_SDK_PATH","QUL_BOARD_SDK_DIR"}, - {"EVKB_IMXRT1050_SDK_PATH","QUL_BOARD_SDK_DIR"}, - {"STM32Cube_FW_F7_SDK_PATH","QUL_BOARD_SDK_DIR"}, - {"STM32Cube_FW_F4_SDK_PATH","QUL_BOARD_SDK_DIR"}, - {"STM32Cube_FW_L4_SDK_PATH","QUL_BOARD_SDK_DIR"}, - {"STM32Cube_FW_H7_SDK_PATH","QUL_BOARD_SDK_DIR"}, + {"EVK_MIMXRT1060_SDK_PATH", "QUL_BOARD_SDK_DIR"}, + {"EVK_MIMXRT1064_SDK_PATH", "QUL_BOARD_SDK_DIR"}, + {"EVK_MIMXRT595_SDK_PATH", "QUL_BOARD_SDK_DIR"}, + {"EVK_MIMXRT1170_SDK_PATH", "QUL_BOARD_SDK_DIR"}, + {"EVKB_IMXRT1050_SDK_PATH", "QUL_BOARD_SDK_DIR"}, + {"STM32Cube_FW_F7_SDK_PATH", "QUL_BOARD_SDK_DIR"}, + {"STM32Cube_FW_F4_SDK_PATH", "QUL_BOARD_SDK_DIR"}, + {"STM32Cube_FW_L4_SDK_PATH", "QUL_BOARD_SDK_DIR"}, + {"STM32Cube_FW_H7_SDK_PATH", "QUL_BOARD_SDK_DIR"}, {"RGL_DIR", "QUL_BOARD_SDK_DIR"}, {"TVII_GRAPHICS_DRIVER_DIR", "QUL_BOARD_SDK_DIR"}, {"EK_RA6M3G_FSP_PATH", "QUL_BOARD_SDK_DIR"}, @@ -47,12 +47,12 @@ static const QHash &envVarToCMakeVarMapping() {"IAR_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"}, {"GHS_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"}, {"GHS_ARM_COMPILER_DIR", "QUL_TARGET_TOOLCHAIN_DIR"}, - {"EVK_MIMXRT1170_FREERTOS_PATH","FREERTOS_DIR"}, - {"IMXRT1050_FREERTOS_DIR","FREERTOS_DIR"}, - {"IMXRT1064_FREERTOS_DIR","FREERTOS_DIR"}, - {"IMXRT595_FREERTOS_DIR","FREERTOS_DIR"}, + {"EVK_MIMXRT1170_FREERTOS_PATH", "FREERTOS_DIR"}, + {"IMXRT1050_FREERTOS_DIR", "FREERTOS_DIR"}, + {"IMXRT1064_FREERTOS_DIR", "FREERTOS_DIR"}, + {"IMXRT595_FREERTOS_DIR", "FREERTOS_DIR"}, {"STM32F7_FREERTOS_DIR", "FREERTOS_DIR"}, - {"eFlashLoad_PATH","eFlashLoad_PATH"}, + {"eFlashLoad_PATH", "eFlashLoad_PATH"}, {"RenesasFlashProgrammer_PATH", "RENESAS_FLASH_PROGRAMMER_PATH"}, {"MCUXpressoIDE_PATH", "MCUXPRESSO_IDE_PATH"}, {"JLINK_PATH", "JLINK_PATH"}, @@ -67,9 +67,11 @@ QList McuSupport::Internal::mapEnvVarsToQu const Utils::EnvironmentItems &envVars) { const auto &mapping = envVarToCMakeVarMapping(); - auto cmakeVars = Utils::transform(envVars, [mapping](const Utils::EnvironmentItem &envVar) { - return CMakeProjectManager::CMakeConfigItem(mapping.value(envVar.name, "").toUtf8(), envVar.value.toUtf8()); - }).toList(); + auto cmakeVars + = Utils::transform(envVars, [mapping](const Utils::EnvironmentItem &envVar) { + return CMakeProjectManager::CMakeConfigItem(mapping.value(envVar.name, "").toUtf8(), + envVar.value.toUtf8()); + }).toList(); return Utils::filtered(cmakeVars, [](const CMakeProjectManager::CMakeConfigItem &item) { return !item.key.isEmpty(); diff --git a/src/plugins/mcusupport/mcusupportconstants.h b/src/plugins/mcusupport/mcusupportconstants.h index 130d645674a..ec46414fb7f 100644 --- a/src/plugins/mcusupport/mcusupportconstants.h +++ b/src/plugins/mcusupport/mcusupportconstants.h @@ -46,5 +46,5 @@ const char SETTINGS_KEY_PACKAGE_PREFIX[] = "Package_"; const char SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK[] = "QtForMCUsSdk"; // Key known by SDK installer const char SETTINGS_KEY_AUTOMATIC_KIT_CREATION[] = "AutomaticKitCreation"; -} // namespace McuSupport } // namespace Constants +} // namespace McuSupport diff --git a/src/plugins/mcusupport/mcusupportdevice.cpp b/src/plugins/mcusupport/mcusupportdevice.cpp index b1198303771..46fb430ac22 100644 --- a/src/plugins/mcusupport/mcusupportdevice.cpp +++ b/src/plugins/mcusupport/mcusupportdevice.cpp @@ -23,8 +23,8 @@ ** ****************************************************************************/ -#include "mcusupportconstants.h" #include "mcusupportdevice.h" +#include "mcusupportconstants.h" #include #include diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index edddf4e2f8a..5e35257903e 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -23,39 +23,39 @@ ** ****************************************************************************/ +#include "mcusupportoptions.h" + #include "mcukitinformation.h" #include "mcupackage.h" -#include "mcusupportconstants.h" -#include "mcusupportoptions.h" -#include "mcusupportsdk.h" -#include "mcusupportplugin.h" #include "mcusupportcmakemapper.h" +#include "mcusupportconstants.h" +#include "mcusupportplugin.h" +#include "mcusupportsdk.h" #include +#include #include -#include -#include #include +#include #include -#include #include #include #include #include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include #include #include #include #include #include #include +#include +#include #include #include @@ -84,16 +84,15 @@ static bool kitNeedsQtVersion() return !HostOsInfo::isWindowsHost(); } - static ToolChain *msvcToolChain(Id language) { ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { const Abi abi = t->targetAbi(); // TODO: Should Abi::WindowsMsvc2022Flavor be added too? - return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor || abi.osFlavor() == Abi::WindowsMsvc2019Flavor) - && abi.architecture() == Abi::X86Architecture - && abi.wordWidth() == 64 - && t->language() == language; + return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor + || abi.osFlavor() == Abi::WindowsMsvc2019Flavor) + && abi.architecture() == Abi::X86Architecture && abi.wordWidth() == 64 + && t->language() == language; }); return toolChain; } @@ -102,26 +101,26 @@ static ToolChain *gccToolChain(Id language) { ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { const Abi abi = t->targetAbi(); - return abi.os() != Abi::WindowsOS - && abi.architecture() == Abi::X86Architecture - && abi.wordWidth() == 64 - && t->language() == language; + return abi.os() != Abi::WindowsOS && abi.architecture() == Abi::X86Architecture + && abi.wordWidth() == 64 && t->language() == language; }); return toolChain; } static ToolChain *armGccToolChain(const FilePath &path, Id language) { - ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t){ + ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t) { return t->compilerCommand() == path && t->language() == language; }); if (!toolChain) { - ToolChainFactory *gccFactory = - Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){ - return f->supportedToolChainType() == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; - }); + ToolChainFactory *gccFactory + = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), + [](ToolChainFactory *f) { + return f->supportedToolChainType() + == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; + }); if (gccFactory) { - const QList detected = gccFactory->detectForImport({path, language}); + const QList detected = gccFactory->detectForImport({path, language}); if (!detected.isEmpty()) { toolChain = detected.first(); toolChain->setDetection(ToolChain::ManualDetection); @@ -136,20 +135,22 @@ static ToolChain *armGccToolChain(const FilePath &path, Id language) static ToolChain *iarToolChain(const FilePath &path, Id language) { - ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t){ + ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID && t->language() == language; }); if (!toolChain) { - ToolChainFactory *iarFactory = - Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), [](ToolChainFactory *f){ - return f->supportedToolChainType() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID; - }); + ToolChainFactory *iarFactory + = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), + [](ToolChainFactory *f) { + return f->supportedToolChainType() + == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID; + }); if (iarFactory) { Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {})); if (detected.isEmpty()) detected = iarFactory->detectForImport({path, language}); - for (auto tc: detected) { + for (auto tc : detected) { if (tc->language() == language) { toolChain = tc; toolChain->setDetection(ToolChain::ManualDetection); @@ -196,12 +197,18 @@ ToolChain *McuToolChainPackage::toolChain(Id language) const QString McuToolChainPackage::toolChainName() const { switch (m_type) { - case Type::ArmGcc: return QLatin1String("armgcc"); - case Type::IAR: return QLatin1String("iar"); - case Type::KEIL: return QLatin1String("keil"); - case Type::GHS: return QLatin1String("ghs"); - case Type::GHSArm: return QLatin1String("ghs-arm"); - default: return QLatin1String("unsupported"); + case Type::ArmGcc: + return QLatin1String("armgcc"); + case Type::IAR: + return QLatin1String("iar"); + case Type::KEIL: + return QLatin1String("keil"); + case Type::GHS: + return QLatin1String("ghs"); + case Type::GHSArm: + return QLatin1String("ghs-arm"); + default: + return QLatin1String("unsupported"); } } @@ -264,8 +271,7 @@ McuTarget::McuTarget(const QVersionNumber &qulVersion, , m_packages(packages) , m_toolChainPackage(toolChainPackage) , m_colorDepth(colorDepth) -{ -} +{} const QVector &McuTarget::packages() const { @@ -297,19 +303,19 @@ bool McuTarget::isValid() const void McuTarget::printPackageProblems() const { - for (auto package: packages()) { + for (auto package : packages()) { package->updateStatus(); if (!package->validStatus()) - printMessage(tr("Error creating kit for target %1, package %2: %3").arg( - McuSupportOptions::kitName(this), - package->label(), - package->statusText()), + printMessage(tr("Error creating kit for target %1, package %2: %3") + .arg(McuSupportOptions::kitName(this), + package->label(), + package->statusText()), true); if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion) - printMessage(tr("Warning creating kit for target %1, package %2: %3").arg( - McuSupportOptions::kitName(this), - package->label(), - package->statusText()), + printMessage(tr("Warning creating kit for target %1, package %2: %3") + .arg(McuSupportOptions::kitName(this), + package->label(), + package->statusText()), false); } } @@ -336,8 +342,10 @@ McuSupportOptions::McuSupportOptions(QObject *parent) : QObject(parent) , qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage()) { - connect(qtForMCUsSdkPackage, &McuAbstractPackage::changed, - this, &McuSupportOptions::populatePackagesAndTargets); + connect(qtForMCUsSdkPackage, + &McuAbstractPackage::changed, + this, + &McuSupportOptions::populatePackagesAndTargets); } McuSupportOptions::~McuSupportOptions() @@ -368,9 +376,8 @@ void McuSupportOptions::registerQchFiles() const QFileInfoList qchFiles = QDir(docsDir, "*.qch").entryInfoList(); Core::HelpManager::registerDocumentation( - Utils::transform(qchFiles, [](const QFileInfo &fi){ - return fi.absoluteFilePath(); - })); + Utils::transform(qchFiles, + [](const QFileInfo &fi) { return fi.absoluteFilePath(); })); } void McuSupportOptions::registerExamples() @@ -379,17 +386,15 @@ void McuSupportOptions::registerExamples() if (docsDir.isEmpty()) return; - auto examples = { - std::make_pair(QStringLiteral("demos"), tr("Qt for MCUs Demos")), - std::make_pair(QStringLiteral("examples"), tr("Qt for MCUs Examples")) - }; + auto examples = {std::make_pair(QStringLiteral("demos"), tr("Qt for MCUs Demos")), + std::make_pair(QStringLiteral("examples"), tr("Qt for MCUs Examples"))}; for (const auto &dir : examples) { - const FilePath examplesDir = - McuSupportOptions::qulDirFromSettings().pathAppended(dir.first); + const FilePath examplesDir = McuSupportOptions::qulDirFromSettings().pathAppended(dir.first); if (!examplesDir.exists()) continue; - QtSupport::QtVersionManager::registerExampleSet(dir.second, docsDir.toString(), + QtSupport::QtVersionManager::registerExampleSet(dir.second, + docsDir.toString(), examplesDir.toString()); } } @@ -418,7 +423,9 @@ FilePath McuSupportOptions::qulDirFromSettings() QSettings::UserScope); } -static void setKitProperties(const QString &kitName, Kit *k, const McuTarget *mcuTarget, +static void setKitProperties(const QString &kitName, + Kit *k, + const McuTarget *mcuTarget, const FilePath &sdkPath) { using namespace Constants; @@ -457,14 +464,13 @@ void McuSupportOptions::remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &en // First filter out all Qul2.x CMake vars auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit), [&](const auto &configItem) { - return !cmakeVarNames.contains(configItem.key); - }); + return !cmakeVarNames.contains(configItem.key); + }); // Then append them with new values config.append(cmakeVars); CMakeConfigurationKitAspect::setConfiguration(kit, config); } - static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage) { switch (tcPackage->type()) { @@ -523,7 +529,7 @@ static void setKitDebugger(Kit *k, const McuToolChainPackage *tcPackage) } } -static void setKitDevice(Kit *k, const McuTarget* mcuTarget) +static void setKitDevice(Kit *k, const McuTarget *mcuTarget) { // "Device Type" Desktop is the default. We use that for the Qt for MCUs Desktop Kit if (mcuTarget->toolChainPackage()->isDesktopToolchain()) @@ -534,11 +540,12 @@ static void setKitDevice(Kit *k, const McuTarget* mcuTarget) static bool expectsCmakeVars(const McuTarget *mcuTarget) { - return mcuTarget->qulVersion() >= QVersionNumber{2,0}; + return mcuTarget->qulVersion() >= QVersionNumber{2, 0}; } -void McuSupportOptions::setKitEnvironment(Kit *k, const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage) +void McuSupportOptions::setKitEnvironment(Kit *k, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) { EnvironmentItems changes; QStringList pathAdditions; @@ -547,7 +554,7 @@ void McuSupportOptions::setKitEnvironment(Kit *k, const McuTarget *mcuTarget, // If CMake's fileApi is avaialble, we can rely on the "Add library search path to PATH" // feature of the run configuration. Otherwise, we just prepend the path, here. if (mcuTarget->toolChainPackage()->isDesktopToolchain() - && !CMakeProjectManager::CMakeToolManager::defaultCMakeTool()->hasFileApi()) + && !CMakeProjectManager::CMakeToolManager::defaultCMakeTool()->hasFileApi()) pathAdditions.append(qtForMCUsSdkPackage->path().pathAppended("bin").toUserOutput()); auto processPackage = [&pathAdditions, &changes](const McuAbstractPackage *package) { @@ -561,7 +568,7 @@ void McuSupportOptions::setKitEnvironment(Kit *k, const McuTarget *mcuTarget, processPackage(qtForMCUsSdkPackage); // Clang not needed in version 1.7+ - if (mcuTarget->qulVersion() < QVersionNumber{1,7}) { + if (mcuTarget->qulVersion() < QVersionNumber{1, 7}) { const QString path = QLatin1String(HostOsInfo::isWindowsHost() ? "Path" : "PATH"); pathAdditions.append("${" + path + "}"); pathAdditions.append(Core::ICore::libexecPath("clang/bin").toUserOutput()); @@ -579,15 +586,16 @@ void McuSupportOptions::setKitEnvironment(Kit *k, const McuTarget *mcuTarget, EnvironmentKitAspect::setEnvironmentChanges(k, changes); } -static void setKitDependencies(Kit *k, const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage) +static void setKitDependencies(Kit *k, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) { NameValueItems dependencies; auto processPackage = [&dependencies](const McuAbstractPackage *package) { if (!package->environmentVariableName().isEmpty()) dependencies.append({package->environmentVariableName(), - QDir::toNativeSeparators(package->detectionPath())}); + QDir::toNativeSeparators(package->detectionPath())}); }; for (auto package : mcuTarget->packages()) processPackage(package); @@ -626,43 +634,44 @@ void McuSupportOptions::updateKitEnvironment(Kit *k, const McuTarget *mcuTarget) EnvironmentKitAspect::setEnvironmentChanges(k, changes); } -static void setKitCMakeOptions(Kit *k, const McuTarget* mcuTarget, const FilePath &qulDir) +static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePath &qulDir) { using namespace CMakeProjectManager; CMakeConfig config = CMakeConfigurationKitAspect::configuration(k); // CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously - if (mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHS && - mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHSArm) { + if (mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHS + && mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHSArm) { config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}")); config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}")); } if (!mcuTarget->toolChainPackage()->isDesktopToolchain()) { - const FilePath cMakeToolchainFile = qulDir.pathAppended("lib/cmake/Qul/toolchain/" - + mcuTarget->toolChainPackage()->cmakeToolChainFileName()); + const FilePath cMakeToolchainFile = qulDir.pathAppended( + "lib/cmake/Qul/toolchain/" + mcuTarget->toolChainPackage()->cmakeToolChainFileName()); - config.append(CMakeConfigItem( - "CMAKE_TOOLCHAIN_FILE", - cMakeToolchainFile.toString().toUtf8())); + config.append( + CMakeConfigItem("CMAKE_TOOLCHAIN_FILE", cMakeToolchainFile.toString().toUtf8())); if (!cMakeToolchainFile.exists()) { - printMessage(McuTarget::tr("Warning for target %1: missing CMake toolchain file expected at %2.") - .arg(McuSupportOptions::kitName(mcuTarget), cMakeToolchainFile.toUserOutput()), false); + printMessage(McuTarget::tr( + "Warning for target %1: missing CMake toolchain file expected at %2.") + .arg(McuSupportOptions::kitName(mcuTarget), + cMakeToolchainFile.toUserOutput()), + false); } } const FilePath generatorsPath = qulDir.pathAppended("/lib/cmake/Qul/QulGenerators.cmake"); - config.append(CMakeConfigItem("QUL_GENERATORS", - generatorsPath.toString().toUtf8())); + config.append(CMakeConfigItem("QUL_GENERATORS", generatorsPath.toString().toUtf8())); if (!generatorsPath.exists()) { printMessage(McuTarget::tr("Warning for target %1: missing QulGenerators expected at %2.") - .arg(McuSupportOptions::kitName(mcuTarget), generatorsPath.toUserOutput()), false); + .arg(McuSupportOptions::kitName(mcuTarget), generatorsPath.toUserOutput()), + false); } - config.append(CMakeConfigItem("QUL_PLATFORM", - mcuTarget->platform().name.toUtf8())); + config.append(CMakeConfigItem("QUL_PLATFORM", mcuTarget->platform().name.toUtf8())); - if (mcuTarget->qulVersion() <= QVersionNumber{1,3} // OS variable was removed in Qul 1.4 + if (mcuTarget->qulVersion() <= QVersionNumber{1, 3} // OS variable was removed in Qul 1.4 && mcuTarget->os() == McuTarget::OS::FreeRTOS) config.append(CMakeConfigItem("OS", "FreeRTOS")); if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth) @@ -692,27 +701,29 @@ static void setKitQtVersionOptions(Kit *k) QString McuSupportOptions::kitName(const McuTarget *mcuTarget) { QString os; - if (mcuTarget->qulVersion() <= QVersionNumber{1,3} && mcuTarget->os() == McuTarget::OS::FreeRTOS) + if (mcuTarget->qulVersion() <= QVersionNumber{1, 3} + && mcuTarget->os() == McuTarget::OS::FreeRTOS) // Starting from Qul 1.4 each OS is a separate platform os = QLatin1String(" FreeRTOS"); const McuToolChainPackage *tcPkg = mcuTarget->toolChainPackage(); const QString compilerName = tcPkg && !tcPkg->isDesktopToolchain() - ? QString::fromLatin1(" (%1)").arg(tcPkg->toolChainName().toUpper()) - : ""; + ? QString::fromLatin1(" (%1)").arg( + tcPkg->toolChainName().toUpper()) + : ""; const QString colorDepth = mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth - ? QString::fromLatin1(" %1bpp").arg(mcuTarget->colorDepth()) - : ""; + ? QString::fromLatin1(" %1bpp").arg(mcuTarget->colorDepth()) + : ""; const QString targetName = mcuTarget->platform().displayName.isEmpty() - ? mcuTarget->platform().name - : mcuTarget->platform().displayName; + ? mcuTarget->platform().name + : mcuTarget->platform().displayName; return QString::fromLatin1("Qt for MCUs %1.%2 - %3%4%5%6") - .arg(QString::number(mcuTarget->qulVersion().majorVersion()), - QString::number(mcuTarget->qulVersion().minorVersion()), - targetName, - os, - colorDepth, - compilerName); + .arg(QString::number(mcuTarget->qulVersion().majorVersion()), + QString::number(mcuTarget->qulVersion().minorVersion()), + targetName, + os, + colorDepth, + compilerName); } QList McuSupportOptions::existingKits(const McuTarget *mcuTarget) @@ -720,26 +731,27 @@ QList McuSupportOptions::existingKits(const McuTarget *mcuTarget) using namespace Constants; return Utils::filtered(KitManager::kits(), [mcuTarget](Kit *kit) { return kit->value(KIT_MCUTARGET_KITVERSION_KEY) == KIT_VERSION - && (!mcuTarget || ( - kit->value(KIT_MCUTARGET_VENDOR_KEY) == mcuTarget->platform().vendor - && kit->value(KIT_MCUTARGET_MODEL_KEY) == mcuTarget->platform().name - && kit->value(KIT_MCUTARGET_COLORDEPTH_KEY) == mcuTarget->colorDepth() - && kit->value(KIT_MCUTARGET_OS_KEY).toInt() - == static_cast(mcuTarget->os()) - && kit->value(KIT_MCUTARGET_TOOCHAIN_KEY) - == mcuTarget->toolChainPackage()->toolChainName() - )); + && (!mcuTarget + || (kit->value(KIT_MCUTARGET_VENDOR_KEY) == mcuTarget->platform().vendor + && kit->value(KIT_MCUTARGET_MODEL_KEY) == mcuTarget->platform().name + && kit->value(KIT_MCUTARGET_COLORDEPTH_KEY) == mcuTarget->colorDepth() + && kit->value(KIT_MCUTARGET_OS_KEY).toInt() + == static_cast(mcuTarget->os()) + && kit->value(KIT_MCUTARGET_TOOCHAIN_KEY) + == mcuTarget->toolChainPackage()->toolChainName())); }); } -QList McuSupportOptions::matchingKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage) +QList McuSupportOptions::matchingKits(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) { return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { return kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); }); } -QList McuSupportOptions::upgradeableKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage) +QList McuSupportOptions::upgradeableKits(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) { return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { return !kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); @@ -750,12 +762,13 @@ QList McuSupportOptions::kitsWithMismatchedDependencies(const McuTarget * { return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) { const auto environment = Utils::NameValueDictionary( - Utils::NameValueItem::toStringList( - EnvironmentKitAspect::environmentChanges(kit))); - return Utils::anyOf(mcuTarget->packages(), [&environment](const McuAbstractPackage *package) { - return !package->environmentVariableName().isEmpty() && - environment.value(package->environmentVariableName()) != package->path().toUserOutput(); - }); + Utils::NameValueItem::toStringList(EnvironmentKitAspect::environmentChanges(kit))); + return Utils::anyOf(mcuTarget->packages(), + [&environment](const McuAbstractPackage *package) { + return !package->environmentVariableName().isEmpty() + && environment.value(package->environmentVariableName()) + != package->path().toUserOutput(); + }); }); } @@ -763,7 +776,7 @@ QList McuSupportOptions::outdatedKits() { return Utils::filtered(KitManager::kits(), [](Kit *kit) { return !kit->value(Constants::KIT_MCUTARGET_VENDOR_KEY).isNull() - && kit->value(Constants::KIT_MCUTARGET_KITVERSION_KEY) != KIT_VERSION; + && kit->value(Constants::KIT_MCUTARGET_KITVERSION_KEY) != KIT_VERSION; }); } @@ -796,7 +809,8 @@ Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuAbstractPack void printMessage(const QString &message, bool important) { - const QString displayMessage = QCoreApplication::translate("QtForMCUs", "Qt for MCUs: %1").arg(message); + const QString displayMessage = QCoreApplication::translate("QtForMCUs", "Qt for MCUs: %1") + .arg(message); if (important) Core::MessageManager::writeFlashing(displayMessage); else @@ -806,8 +820,7 @@ void printMessage(const QString &message, bool important) QVersionNumber McuSupportOptions::kitQulVersion(const Kit *kit) { return QVersionNumber::fromString( - kit->value(McuSupport::Constants::KIT_MCUTARGET_SDKVERSION_KEY) - .toString()); + kit->value(McuSupport::Constants::KIT_MCUTARGET_SDKVERSION_KEY).toString()); } static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) @@ -819,11 +832,13 @@ static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) return FilePath(); } -bool McuSupportOptions::kitUpToDate(const Kit *kit, const McuTarget *mcuTarget, +bool McuSupportOptions::kitUpToDate(const Kit *kit, + const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage) { - return kitQulVersion(kit) == mcuTarget->qulVersion() && - kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput() == qtForMCUsSdkPackage->path().toUserOutput(); + return kitQulVersion(kit) == mcuTarget->qulVersion() + && kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput() + == qtForMCUsSdkPackage->path().toUserOutput(); } void McuSupportOptions::deletePackagesAndTargets() @@ -835,8 +850,9 @@ McuSupportOptions::UpgradeOption McuSupportOptions::askForKitUpgrades() { QMessageBox upgradePopup(Core::ICore::dialogParent()); upgradePopup.setStandardButtons(QMessageBox::Cancel); - QPushButton *replaceButton = upgradePopup.addButton(tr("Replace Existing Kits"),QMessageBox::NoRole); - QPushButton *keepButton = upgradePopup.addButton(tr("Create New Kits"),QMessageBox::NoRole); + QPushButton *replaceButton = upgradePopup.addButton(tr("Replace Existing Kits"), + QMessageBox::NoRole); + QPushButton *keepButton = upgradePopup.addButton(tr("Create New Kits"), QMessageBox::NoRole); upgradePopup.setWindowTitle(tr("Qt for MCUs")); upgradePopup.setText(tr("New version of Qt for MCUs detected. Upgrade existing kits?")); @@ -856,67 +872,70 @@ void McuSupportOptions::createAutomaticKits() auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); const auto createKits = [qtForMCUsPackage]() { - if (qtForMCUsPackage->automaticKitCreationEnabled()) { - qtForMCUsPackage->updateStatus(); - if (!qtForMCUsPackage->validStatus()) { - switch (qtForMCUsPackage->status()) { + if (qtForMCUsPackage->automaticKitCreationEnabled()) { + qtForMCUsPackage->updateStatus(); + if (!qtForMCUsPackage->validStatus()) { + switch (qtForMCUsPackage->status()) { case McuAbstractPackage::Status::ValidPathInvalidPackage: { - const QString displayPath = FilePath::fromString(qtForMCUsPackage->detectionPath()) - .toUserOutput(); + const QString displayPath + = FilePath::fromString(qtForMCUsPackage->detectionPath()).toUserOutput(); printMessage(tr("Path %1 exists, but does not contain %2.") - .arg(qtForMCUsPackage->path().toUserOutput(), displayPath), + .arg(qtForMCUsPackage->path().toUserOutput(), displayPath), true); break; } case McuAbstractPackage::Status::InvalidPath: { - printMessage(tr("Path %1 does not exist. Add the path in Tools > Options > Devices > MCU.") - .arg(qtForMCUsPackage->path().toUserOutput()), + printMessage(tr("Path %1 does not exist. Add the path in Tools > Options > " + "Devices > MCU.") + .arg(qtForMCUsPackage->path().toUserOutput()), true); break; } case McuAbstractPackage::Status::EmptyPath: { printMessage(tr("Missing %1. Add the path in Tools > Options > Devices > MCU.") - .arg(qtForMCUsPackage->detectionPath()), + .arg(qtForMCUsPackage->detectionPath()), true); return; } - default: break; + default: + break; + } + return; } - return; - } - if (CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty()) { - printMessage(tr("No CMake tool was detected. Add a CMake tool in Tools > Options > Kits > CMake."), - true); - return; - } - - FilePath dir = qtForMCUsPackage->path(); - McuSdkRepository repo; - Sdk::targetsAndPackages(dir, &repo); - - bool needsUpgrade = false; - for (const auto &target: qAsConst(repo.mcuTargets)) { - // if kit already exists, skip - if (!matchingKits(target, qtForMCUsPackage).empty()) - continue; - if (!upgradeableKits(target, qtForMCUsPackage).empty()) { - // if kit exists but wrong version/path - needsUpgrade = true; - } else { - // if no kits for this target, create - if (target->isValid()) - newKit(target, qtForMCUsPackage); - target->printPackageProblems(); + if (CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty()) { + printMessage(tr("No CMake tool was detected. Add a CMake tool in Tools > Options > " + "Kits > CMake."), + true); + return; } + + FilePath dir = qtForMCUsPackage->path(); + McuSdkRepository repo; + Sdk::targetsAndPackages(dir, &repo); + + bool needsUpgrade = false; + for (const auto &target : qAsConst(repo.mcuTargets)) { + // if kit already exists, skip + if (!matchingKits(target, qtForMCUsPackage).empty()) + continue; + if (!upgradeableKits(target, qtForMCUsPackage).empty()) { + // if kit exists but wrong version/path + needsUpgrade = true; + } else { + // if no kits for this target, create + if (target->isValid()) + newKit(target, qtForMCUsPackage); + target->printPackageProblems(); + } + } + + repo.deletePackagesAndTargets(); + + if (needsUpgrade) + McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade(); } - - repo.deletePackagesAndTargets(); - - if (needsUpgrade) - McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade(); - } - }; + }; createKits(); delete qtForMCUsPackage; @@ -928,8 +947,8 @@ void McuSupportOptions::checkUpgradeableKits() return; if (Utils::anyOf(sdkRepository.mcuTargets, [this](const McuTarget *target) { - return !upgradeableKits(target, this->qtForMCUsSdkPackage).empty() && - matchingKits(target, this->qtForMCUsSdkPackage).empty(); + return !upgradeableKits(target, this->qtForMCUsSdkPackage).empty() + && matchingKits(target, this->qtForMCUsSdkPackage).empty(); })) upgradeKits(askForKitUpgrades()); } @@ -945,7 +964,7 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption) McuSdkRepository repo; Sdk::targetsAndPackages(dir, &repo); - for (const auto &target: qAsConst(repo.mcuTargets)) { + for (const auto &target : qAsConst(repo.mcuTargets)) { if (!matchingKits(target, qtForMCUsPackage).empty()) // already up-to-date continue; @@ -966,7 +985,9 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption) delete qtForMCUsPackage; } -void McuSupportOptions::upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) +void McuSupportOptions::upgradeKitInPlace(ProjectExplorer::Kit *kit, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdk) { setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path()); setKitEnvironment(kit, mcuTarget, qtForMCUsSdk); @@ -980,9 +1001,9 @@ void McuSupportOptions::fixKitsDependencies() FilePath dir = qtForMCUsPackage->path(); McuSdkRepository repo; Sdk::targetsAndPackages(dir, &repo); - for (const auto &target: qAsConst(repo.mcuTargets)) { + for (const auto &target : qAsConst(repo.mcuTargets)) { if (target->isValid()) { - for (auto* kit : kitsWithMismatchedDependencies(target)) { + for (auto *kit : kitsWithMismatchedDependencies(target)) { updateKitEnvironment(kit, target); } } @@ -998,7 +1019,7 @@ void McuSupportOptions::fixKitsDependencies() void McuSupportOptions::fixExistingKits() { for (Kit *kit : KitManager::kits()) { - if (!kit->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY) ) + if (!kit->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY)) continue; if (kit->isAutoDetected()) { @@ -1054,8 +1075,8 @@ void McuSupportOptions::fixExistingKits() FilePath dir = qtForMCUsPackage->path(); McuSdkRepository repo; Sdk::targetsAndPackages(dir, &repo); - for (const auto &target: qAsConst(repo.mcuTargets)) - for (auto kit: existingKits(target)) { + for (const auto &target : qAsConst(repo.mcuTargets)) + for (auto kit : existingKits(target)) { if (McuDependenciesKitAspect::dependencies(kit).isEmpty()) { setKitDependencies(kit, target, qtForMCUsPackage); } @@ -1066,5 +1087,5 @@ void McuSupportOptions::fixExistingKits() delete qtForMCUsPackage; } -} // Internal -} // McuSupport +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/mcusupportoptions.h b/src/plugins/mcusupport/mcusupportoptions.h index 662a80bf759..20e046384d7 100644 --- a/src/plugins/mcusupport/mcusupportoptions.h +++ b/src/plugins/mcusupport/mcusupportoptions.h @@ -36,7 +36,7 @@ namespace Utils { class FilePath; class PathChooser; class InfoLabel; -} +} // namespace Utils namespace ProjectExplorer { class Kit; @@ -56,13 +56,10 @@ class McuTarget : public QObject Q_OBJECT public: - enum class OS { - Desktop, - BareMetal, - FreeRTOS - }; + enum class OS { Desktop, BareMetal, FreeRTOS }; - struct Platform { + struct Platform + { QString name; QString displayName; QString vendor; @@ -109,11 +106,7 @@ class McuSupportOptions : public QObject Q_OBJECT public: - enum UpgradeOption { - Ignore, - Keep, - Replace - }; + enum UpgradeOption { Ignore, Keep, Replace }; explicit McuSupportOptions(QObject *parent = nullptr); ~McuSupportOptions() override; @@ -122,20 +115,25 @@ public: McuSdkRepository sdkRepository; void setQulDir(const Utils::FilePath &dir); - static void setKitEnvironment(ProjectExplorer::Kit *, const McuTarget *, const McuAbstractPackage *); + static void setKitEnvironment(ProjectExplorer::Kit *, + const McuTarget *, + const McuAbstractPackage *); static void updateKitEnvironment(ProjectExplorer::Kit *, const McuTarget *); static void remapQul2xCmakeVars(ProjectExplorer::Kit *, const Utils::EnvironmentItems &); static Utils::FilePath qulDirFromSettings(); - static QString kitName(const McuTarget* mcuTarget); + static QString kitName(const McuTarget *mcuTarget); static QList existingKits(const McuTarget *mcuTarget); - static QList matchingKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); - static QList upgradeableKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); + static QList matchingKits(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage); + static QList upgradeableKits( + const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); static QList kitsWithMismatchedDependencies(const McuTarget *mcuTarget); static QList outdatedKits(); static void removeOutdatedKits(); - static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); + static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdk); static void createAutomaticKits(); static UpgradeOption askForKitUpgrades(); static void upgradeKits(UpgradeOption upgradeOption); diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp index 914869448c5..243caaff1ed 100644 --- a/src/plugins/mcusupport/mcusupportoptionspage.cpp +++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp @@ -23,9 +23,9 @@ ** ****************************************************************************/ +#include "mcusupportoptionspage.h" #include "mcupackage.h" #include "mcusupportconstants.h" -#include "mcusupportoptionspage.h" #include "mcusupportoptions.h" #include "mcusupportsdk.h" @@ -42,9 +42,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -71,8 +71,8 @@ private: QString m_armGccPath; McuSupportOptions m_options; - QMap m_packageWidgets; - QMap m_mcuTargetPacketWidgets; + QMap m_packageWidgets; + QMap m_mcuTargetPacketWidgets; QFormLayout *m_packagesLayout = nullptr; QGroupBox *m_qtForMCUsSdkGroupBox = nullptr; QGroupBox *m_packagesGroupBox = nullptr; @@ -110,17 +110,21 @@ McuSupportOptionsWidget::McuSupportOptionsWidget() } { - m_mcuTargetsGroupBox = new QGroupBox(tr("Targets supported by the %1") - .arg(m_qtForMCUsSdkGroupBox->title())); + m_mcuTargetsGroupBox = new QGroupBox( + tr("Targets supported by the %1").arg(m_qtForMCUsSdkGroupBox->title())); m_mcuTargetsGroupBox->setFlat(true); mainLayout->addWidget(m_mcuTargetsGroupBox); m_mcuTargetsComboBox = new QComboBox; auto layout = new QVBoxLayout(m_mcuTargetsGroupBox); layout->addWidget(m_mcuTargetsComboBox); - connect(m_mcuTargetsComboBox, &QComboBox::currentTextChanged, - this, &McuSupportOptionsWidget::showMcuTargetPackages); - connect(m_options.qtForMCUsSdkPackage, &McuAbstractPackage::changed, - this, &McuSupportOptionsWidget::populateMcuTargetsComboBox); + connect(m_mcuTargetsComboBox, + &QComboBox::currentTextChanged, + this, + &McuSupportOptionsWidget::showMcuTargetPackages); + connect(m_options.qtForMCUsSdkPackage, + &McuAbstractPackage::changed, + this, + &McuSupportOptionsWidget::populateMcuTargetsComboBox); } { @@ -137,9 +141,11 @@ McuSupportOptionsWidget::McuSupportOptionsWidget() } { - m_kitAutomaticCreationCheckBox = new QCheckBox(tr("Automatically create kits for all available targets on start")); - connect(m_kitAutomaticCreationCheckBox, &QCheckBox::stateChanged, this, [this] (int state) { - m_options.qtForMCUsSdkPackage->setAutomaticKitCreationEnabled(state == Qt::CheckState::Checked); + m_kitAutomaticCreationCheckBox = new QCheckBox( + tr("Automatically create kits for all available targets on start")); + connect(m_kitAutomaticCreationCheckBox, &QCheckBox::stateChanged, this, [this](int state) { + m_options.qtForMCUsSdkPackage->setAutomaticKitCreationEnabled( + state == Qt::CheckState::Checked); }); mainLayout->addWidget(m_kitAutomaticCreationCheckBox); } @@ -161,7 +167,8 @@ McuSupportOptionsWidget::McuSupportOptionsWidget() m_kitUpdatePushButton = new QPushButton(tr("Update Kit")); m_kitUpdatePushButton->setSizePolicy(m_kitCreationPushButton->sizePolicy()); connect(m_kitUpdatePushButton, &QPushButton::clicked, this, [this] { - for (auto kit: McuSupportOptions::upgradeableKits(currentMcuTarget(), m_options.qtForMCUsSdkPackage)) + for (auto kit : McuSupportOptions::upgradeableKits(currentMcuTarget(), + m_options.qtForMCUsSdkPackage)) m_options.upgradeKitInPlace(kit, currentMcuTarget(), m_options.qtForMCUsSdkPackage); updateStatus(); }); @@ -185,8 +192,7 @@ void McuSupportOptionsWidget::updateStatus() // Page elements { m_qtForMCUsSdkGroupBox->setVisible(cMakeAvailable); - const bool valid = cMakeAvailable && - m_options.qtForMCUsSdkPackage->validStatus(); + const bool valid = cMakeAvailable && m_options.qtForMCUsSdkPackage->validStatus(); const bool ready = valid && mcuTarget; m_mcuTargetsGroupBox->setVisible(ready); m_packagesGroupBox->setVisible(ready && !mcuTarget->packages().isEmpty()); @@ -200,7 +206,7 @@ void McuSupportOptionsWidget::updateStatus() m_mcuTargetsInfoLabel->setText(deprecationMessage); else m_mcuTargetsInfoLabel->setText(tr("No valid kit descriptions found at %1.") - .arg(Sdk::kitsPath(sdkPath).toUserOutput())); + .arg(Sdk::kitsPath(sdkPath).toUserOutput())); } } @@ -210,25 +216,25 @@ void McuSupportOptionsWidget::updateStatus() m_kitCreationPushButton->setVisible(mcuTargetValid); m_kitUpdatePushButton->setVisible(mcuTargetValid); if (mcuTargetValid) { - const bool hasMatchingKits = !McuSupportOptions::matchingKits( - mcuTarget, m_options.qtForMCUsSdkPackage).isEmpty(); - const bool hasUpgradeableKits = !hasMatchingKits && - !McuSupportOptions::upgradeableKits( - mcuTarget, m_options.qtForMCUsSdkPackage).isEmpty(); + const bool hasMatchingKits + = !McuSupportOptions::matchingKits(mcuTarget, m_options.qtForMCUsSdkPackage) + .isEmpty(); + const bool hasUpgradeableKits + = !hasMatchingKits + && !McuSupportOptions::upgradeableKits(mcuTarget, m_options.qtForMCUsSdkPackage) + .isEmpty(); m_kitCreationPushButton->setEnabled(!hasMatchingKits); m_kitUpdatePushButton->setEnabled(hasUpgradeableKits); - m_kitCreationInfoLabel->setType(!hasMatchingKits - ? Utils::InfoLabel::Information - : Utils::InfoLabel::Ok); + m_kitCreationInfoLabel->setType(!hasMatchingKits ? Utils::InfoLabel::Information + : Utils::InfoLabel::Ok); m_kitCreationInfoLabel->setText( - hasMatchingKits ? - tr("A kit for the selected target and SDK version already exists.") - : hasUpgradeableKits ? - tr("Kits for a different SDK version exist.") - : tr("A kit for the selected target can be created.")); + hasMatchingKits + ? tr("A kit for the selected target and SDK version already exists.") + : hasUpgradeableKits ? tr("Kits for a different SDK version exist.") + : tr("A kit for the selected target can be created.")); } else { m_kitCreationInfoLabel->setType(Utils::InfoLabel::NotOk); m_kitCreationInfoLabel->setText("Provide the package paths in order to create a kit " @@ -237,7 +243,8 @@ void McuSupportOptionsWidget::updateStatus() } // Automatic Kit creation - m_kitAutomaticCreationCheckBox->setChecked(m_options.qtForMCUsSdkPackage->automaticKitCreationEnabled()); + m_kitAutomaticCreationCheckBox->setChecked( + m_options.qtForMCUsSdkPackage->automaticKitCreationEnabled()); // Status label in the bottom { @@ -277,8 +284,8 @@ McuTarget *McuSupportOptionsWidget::currentMcuTarget() const { const int mcuTargetIndex = m_mcuTargetsComboBox->currentIndex(); return (mcuTargetIndex == -1 || m_options.sdkRepository.mcuTargets.isEmpty()) - ? nullptr - : m_options.sdkRepository.mcuTargets.at(mcuTargetIndex); + ? nullptr + : m_options.sdkRepository.mcuTargets.at(mcuTargetIndex); } void McuSupportOptionsWidget::showEvent(QShowEvent *event) @@ -307,9 +314,8 @@ void McuSupportOptionsWidget::populateMcuTargetsComboBox() m_options.populatePackagesAndTargets(); m_mcuTargetsComboBox->clear(); m_mcuTargetsComboBox->addItems( - Utils::transform(m_options.sdkRepository.mcuTargets, [](McuTarget *t) { - return McuSupportOptions::kitName(t); - })); + Utils::transform(m_options.sdkRepository.mcuTargets, + [](McuTarget *t) { return McuSupportOptions::kitName(t); })); updateStatus(); } @@ -321,5 +327,5 @@ McuSupportOptionsPage::McuSupportOptionsPage() setWidgetCreator([] { return new McuSupportOptionsWidget; }); } -} // Internal -} // McuSupport +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp index 86fd2ee37f5..6e0d2d20b2f 100644 --- a/src/plugins/mcusupport/mcusupportplugin.cpp +++ b/src/plugins/mcusupport/mcusupportplugin.cpp @@ -23,8 +23,8 @@ ** ****************************************************************************/ -#include "mcukitinformation.h" #include "mcusupportplugin.h" +#include "mcukitinformation.h" #include "mcusupportconstants.h" #include "mcusupportdevice.h" #include "mcusupportoptions.h" @@ -58,16 +58,14 @@ class McuSupportPluginPrivate public: McuSupportDeviceFactory deviceFactory; McuSupportRunConfigurationFactory runConfigurationFactory; - RunWorkerFactory runWorkerFactory{ - makeFlashAndRunWorker(), - {ProjectExplorer::Constants::NORMAL_RUN_MODE}, - {Constants::RUNCONFIGURATION} - }; + RunWorkerFactory runWorkerFactory{makeFlashAndRunWorker(), + {ProjectExplorer::Constants::NORMAL_RUN_MODE}, + {Constants::RUNCONFIGURATION}}; McuSupportOptionsPage optionsPage; McuDependenciesKitAspect environmentPathsKitAspect; }; // class McuSupportPluginPrivate -static McuSupportPluginPrivate* dd{nullptr}; +static McuSupportPluginPrivate *dd{nullptr}; McuSupportPlugin::~McuSupportPlugin() { @@ -94,7 +92,7 @@ void McuSupportPlugin::extensionsInitialized() { ProjectExplorer::DeviceManager::instance()->addDevice(McuSupportDevice::create()); - connect(KitManager::instance(), &KitManager::kitsLoaded, [](){ + connect(KitManager::instance(), &KitManager::kitsLoaded, []() { McuSupportOptions::removeOutdatedKits(); McuSupportOptions::createAutomaticKits(); McuSupportOptions::fixExistingKits(); @@ -134,12 +132,11 @@ void McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade() Utils::InfoBarEntry::GlobalSuppression::Enabled); static McuSupportOptions::UpgradeOption selectedOption; - const QStringList options = { tr("Create new kits"), tr("Replace existing kits") }; + const QStringList options = {tr("Create new kits"), tr("Replace existing kits")}; selectedOption = McuSupportOptions::UpgradeOption::Keep; info.setComboInfo(options, [options](const QString &selected) { - selectedOption = options.indexOf(selected) == 0 ? - McuSupportOptions::UpgradeOption::Keep : - McuSupportOptions::UpgradeOption::Replace; + selectedOption = options.indexOf(selected) == 0 ? McuSupportOptions::UpgradeOption::Keep + : McuSupportOptions::UpgradeOption::Replace; }); info.addCustomButton(tr("Proceed"), [upgradeMcuSupportKits] { diff --git a/src/plugins/mcusupport/mcusupportrunconfiguration.cpp b/src/plugins/mcusupport/mcusupportrunconfiguration.cpp index 21b3f182689..361fb09b899 100644 --- a/src/plugins/mcusupport/mcusupportrunconfiguration.cpp +++ b/src/plugins/mcusupport/mcusupportrunconfiguration.cpp @@ -46,16 +46,18 @@ namespace Internal { static FilePath cmakeFilePath(const Target *target) { - const CMakeProjectManager::CMakeTool *tool = - CMakeProjectManager::CMakeKitAspect::cmakeTool(target->kit()); + const CMakeProjectManager::CMakeTool *tool = CMakeProjectManager::CMakeKitAspect::cmakeTool( + target->kit()); return tool->filePath(); } static QStringList flashAndRunArgs(const RunConfiguration *rc, const Target *target) { // Use buildKey if provided, fallback to projectName - const QString targetName = QLatin1String("flash_%1").arg( - !rc->buildKey().isEmpty() ? rc->buildKey() : target->project()->displayName()); + const QString targetName = QLatin1String("flash_%1") + .arg(!rc->buildKey().isEmpty() + ? rc->buildKey() + : target->project()->displayName()); return {"--build", ".", "--target", targetName}; } diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index 8ba6fcb0ec0..74d5ccedc33 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -23,10 +23,10 @@ ** ****************************************************************************/ +#include "mcusupportsdk.h" #include "mcupackage.h" #include "mcusupportconstants.h" #include "mcusupportoptions.h" -#include "mcusupportsdk.h" #include "mcusupportversiondetection.h" #include "mcutargetdescription.h" @@ -107,11 +107,10 @@ static McuToolChainPackage *createArmGccPackage() } const QString detectionPath = Utils::HostOsInfo::withExecutableSuffix("bin/arm-none-eabi-g++"); - const auto versionDetector = new McuPackageExecutableVersionDetector( - detectionPath, - { "--version" }, - "\\b(\\d+\\.\\d+\\.\\d+)\\b" - ); + const auto versionDetector + = new McuPackageExecutableVersionDetector(detectionPath, + {"--version"}, + "\\b(\\d+\\.\\d+\\.\\d+)\\b"); return new McuToolChainPackage(McuPackage::tr("GNU Arm Embedded Toolchain"), defaultPath, @@ -128,11 +127,10 @@ static McuToolChainPackage *createGhsToolchainPackage() const FilePath defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar)); - const auto versionDetector = new McuPackageExecutableVersionDetector( - Utils::HostOsInfo::withExecutableSuffix("as850"), - {"-V"}, - "\\bv(\\d+\\.\\d+\\.\\d+)\\b" - ); + const auto versionDetector + = new McuPackageExecutableVersionDetector(Utils::HostOsInfo::withExecutableSuffix("as850"), + {"-V"}, + "\\bv(\\d+\\.\\d+\\.\\d+)\\b"); return new McuToolChainPackage("Green Hills Compiler", defaultPath, @@ -150,11 +148,10 @@ static McuToolChainPackage *createGhsArmToolchainPackage() const FilePath defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar)); - const auto versionDetector = new McuPackageExecutableVersionDetector( - Utils::HostOsInfo::withExecutableSuffix("asarm"), - {"-V"}, - "\\bv(\\d+\\.\\d+\\.\\d+)\\b" - ); + const auto versionDetector + = new McuPackageExecutableVersionDetector(Utils::HostOsInfo::withExecutableSuffix("asarm"), + {"-V"}, + "\\bv(\\d+\\.\\d+\\.\\d+)\\b"); return new McuToolChainPackage("Green Hills Compiler for ARM", defaultPath, @@ -173,10 +170,10 @@ static McuToolChainPackage *createIarToolChainPackage() if (qEnvironmentVariableIsSet(envVar)) defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar)); else { - const ProjectExplorer::ToolChain *tc = - ProjectExplorer::ToolChainManager::toolChain([](const ProjectExplorer::ToolChain *t) { - return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID; - }); + const ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainManager::toolChain( + [](const ProjectExplorer::ToolChain *t) { + return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID; + }); if (tc) { const FilePath compilerExecPath = tc->compilerCommand(); defaultPath = compilerExecPath.parentDir().parentDir(); @@ -184,11 +181,10 @@ static McuToolChainPackage *createIarToolChainPackage() } const QString detectionPath = Utils::HostOsInfo::withExecutableSuffix("bin/iccarm"); - const auto versionDetector = new McuPackageExecutableVersionDetector( - detectionPath, - {"--version"}, - "\\bV(\\d+\\.\\d+\\.\\d+)\\.\\d+\\b" - ); + const auto versionDetector + = new McuPackageExecutableVersionDetector(detectionPath, + {"--version"}, + "\\bV(\\d+\\.\\d+\\.\\d+)\\.\\d+\\b"); return new McuToolChainPackage("IAR ARM Compiler", defaultPath, @@ -207,11 +203,12 @@ static McuPackage *createRGLPackage() if (qEnvironmentVariableIsSet(envVar)) { defaultPath = FilePath::fromUserInput(qEnvironmentVariable(envVar)); } else if (Utils::HostOsInfo::isWindowsHost()) { - const FilePath rglPath = FilePath::fromString(QDir::rootPath()) / "Renesas_Electronics/D1x_RGL"; + const FilePath rglPath = FilePath::fromString(QDir::rootPath()) + / "Renesas_Electronics/D1x_RGL"; if (rglPath.exists()) { defaultPath = rglPath; - const FilePaths subDirs = - defaultPath.dirEntries({{"rgl_ghs_D1Mx_*"}, QDir::Dirs | QDir::NoDotAndDotDot}); + const FilePaths subDirs = defaultPath.dirEntries( + {{"rgl_ghs_D1Mx_*"}, QDir::Dirs | QDir::NoDotAndDotDot}); if (subDirs.count() == 1) defaultPath = subDirs.first(); } @@ -263,8 +260,8 @@ static McuPackage *createMcuXpressoIdePackage() if (programPath.exists()) { defaultPath = programPath; // If default dir has exactly one sub dir that could be the IDE path, pre-select that. - const FilePaths subDirs = - defaultPath.dirEntries({{"MCUXpressoIDE*"}, QDir::Dirs | QDir::NoDotAndDotDot}); + const FilePaths subDirs = defaultPath.dirEntries( + {{"MCUXpressoIDE*"}, QDir::Dirs | QDir::NoDotAndDotDot}); if (subDirs.count() == 1) defaultPath = subDirs.first(); } @@ -301,12 +298,11 @@ static McuPackage *createCypressProgrammerPackage() } } - auto result = new McuPackage( - "Cypress Auto Flash Utility", - defaultPath, - Utils::HostOsInfo::withExecutableSuffix("/bin/openocd"), - "CypressAutoFlashUtil", - envVar); + auto result = new McuPackage("Cypress Auto Flash Utility", + defaultPath, + Utils::HostOsInfo::withExecutableSuffix("/bin/openocd"), + "CypressAutoFlashUtil", + envVar); return result; } @@ -328,12 +324,11 @@ static McuPackage *createRenesasProgrammerPackage() } } - auto result = new McuPackage( - "Renesas Flash Programmer", - defaultPath, - Utils::HostOsInfo::withExecutableSuffix("rfp-cli"), - "RenesasFlashProgrammer", - envVar); + auto result = new McuPackage("Renesas Flash Programmer", + defaultPath, + Utils::HostOsInfo::withExecutableSuffix("rfp-cli"), + "RenesasFlashProgrammer", + envVar); return result; } static McuPackageVersionDetector *generatePackageVersionDetector(QString envVar) @@ -342,7 +337,10 @@ static McuPackageVersionDetector *generatePackageVersionDetector(QString envVar) return new McuPackageXmlVersionDetector("*_manifest_*.xml", "ksdk", "version", ".*"); if (envVar.startsWith("STM32")) - return new McuPackageXmlVersionDetector("package.xml", "PackDescription", "Release", "\\b(\\d+\\.\\d+\\.\\d+)\\b"); + return new McuPackageXmlVersionDetector("package.xml", + "PackDescription", + "Release", + "\\b(\\d+\\.\\d+\\.\\d+)\\b"); if (envVar.startsWith("RGL")) return new McuPackageDirectoryVersionDetector("rgl_*_obj_*", "\\d+\\.\\d+\\.\\w+", false); @@ -353,9 +351,9 @@ static McuPackageVersionDetector *generatePackageVersionDetector(QString envVar) /// Create the McuPackage by checking the "boardSdk" property in the JSON file for the board. /// The name of the environment variable pointing to the the SDK for the board will be defined in the "envVar" property /// inside the "boardSdk". -static McuPackage *createBoardSdkPackage(const McuTargetDescription& desc) +static McuPackage *createBoardSdkPackage(const McuTargetDescription &desc) { - const auto generateSdkName = [](const QString& envVar) { + const auto generateSdkName = [](const QString &envVar) { auto postfixPos = envVar.indexOf("_SDK_PATH"); if (postfixPos < 0) { postfixPos = envVar.indexOf("_DIR"); @@ -363,14 +361,16 @@ static McuPackage *createBoardSdkPackage(const McuTargetDescription& desc) auto sdkName = postfixPos > 0 ? envVar.left(postfixPos) : envVar; return QString::fromLatin1("MCU SDK (%1)").arg(sdkName); }; - const QString sdkName = desc.boardSdk.name.isEmpty() ? generateSdkName(desc.boardSdk.envVar) : desc.boardSdk.name; + const QString sdkName = desc.boardSdk.name.isEmpty() ? generateSdkName(desc.boardSdk.envVar) + : desc.boardSdk.name; const FilePath defaultPath = [&] { const auto envVar = desc.boardSdk.envVar.toLatin1(); if (qEnvironmentVariableIsSet(envVar)) return FilePath::fromUserInput(qEnvironmentVariable(envVar)); if (!desc.boardSdk.defaultPath.isEmpty()) { - FilePath defaultPath = FilePath::fromUserInput(QDir::rootPath() + desc.boardSdk.defaultPath); + FilePath defaultPath = FilePath::fromUserInput(QDir::rootPath() + + desc.boardSdk.defaultPath); if (defaultPath.exists()) return defaultPath; } @@ -388,7 +388,8 @@ static McuPackage *createBoardSdkPackage(const McuTargetDescription& desc) versionDetector); } -static McuPackage *createFreeRTOSSourcesPackage(const QString &envVar, const FilePath &boardSdkDir, +static McuPackage *createFreeRTOSSourcesPackage(const QString &envVar, + const FilePath &boardSdkDir, const QString &freeRTOSBoardSdkSubDir) { const QString envVarPrefix = envVar.chopped(int(strlen("_FREERTOS_DIR"))); @@ -415,10 +416,10 @@ struct McuTargetFactory , vendorPkgs(vendorPkgs) {} - QVector createTargets(const McuTargetDescription& description) + QVector createTargets(const McuTargetDescription &description) { auto qulVersion = QVersionNumber::fromString(description.qulVersion); - if (qulVersion <= QVersionNumber({1,3})) { + if (qulVersion <= QVersionNumber({1, 3})) { if (description.platform.type == McuTargetDescription::TargetType::Desktop) return createDesktopTargetsLegacy(description); @@ -449,16 +450,16 @@ protected: tcPkg = createUnsupportedToolChainPackage(); for (auto os : {McuTarget::OS::BareMetal, McuTarget::OS::FreeRTOS}) { for (int colorDepth : desc.platform.colorDepths) { - QVector required3rdPartyPkgs = { tcPkg }; + QVector required3rdPartyPkgs = {tcPkg}; if (vendorPkgs.contains(desc.platform.vendor)) - required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor)); + required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor)); FilePath boardSdkDefaultPath; if (!desc.boardSdk.envVar.isEmpty()) { if (!boardSdkPkgs.contains(desc.boardSdk.envVar)) { auto boardSdkPkg = desc.boardSdk.envVar != "RGL_DIR" - ? createBoardSdkPackage(desc) - : createRGLPackage(); + ? createBoardSdkPackage(desc) + : createRGLPackage(); boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg); } auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdk.envVar); @@ -470,15 +471,19 @@ protected: continue; } else { if (!freeRTOSPkgs.contains(desc.freeRTOS.envVar)) { - freeRTOSPkgs.insert(desc.freeRTOS.envVar, createFreeRTOSSourcesPackage( - desc.freeRTOS.envVar, boardSdkDefaultPath, - desc.freeRTOS.boardSdkSubDir)); + freeRTOSPkgs + .insert(desc.freeRTOS.envVar, + createFreeRTOSSourcesPackage(desc.freeRTOS.envVar, + boardSdkDefaultPath, + desc.freeRTOS.boardSdkSubDir)); } required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOS.envVar)); } } - const auto platform = McuTarget::Platform{ desc.platform.id, desc.platform.name, desc.platform.vendor }; + const auto platform = McuTarget::Platform{desc.platform.id, + desc.platform.name, + desc.platform.vendor}; auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion), platform, os, @@ -493,18 +498,23 @@ protected: return mcuTargets; } - QVector createDesktopTargetsLegacy(const McuTargetDescription& desc) + QVector createDesktopTargetsLegacy(const McuTargetDescription &desc) { McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id); if (!tcPkg) tcPkg = createUnsupportedToolChainPackage(); - const auto platform = McuTarget::Platform{ desc.platform.id, desc.platform.name, desc.platform.vendor }; + const auto platform = McuTarget::Platform{desc.platform.id, + desc.platform.name, + desc.platform.vendor}; auto desktopTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion), - platform, McuTarget::OS::Desktop, {}, tcPkg); - return { desktopTarget }; + platform, + McuTarget::OS::Desktop, + {}, + tcPkg); + return {desktopTarget}; } - QVector createTargetsImpl(const McuTargetDescription& desc) + QVector createTargetsImpl(const McuTargetDescription &desc) { // OS deduction const auto os = [&] { @@ -518,15 +528,14 @@ protected: QVector mcuTargets; McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id); if (tcPkg) { - if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1,8})) + if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1, 8})) tcPkg->setVersions(desc.toolchain.versions); } else tcPkg = createUnsupportedToolChainPackage(); for (int colorDepth : desc.platform.colorDepths) { - QVector required3rdPartyPkgs; + QVector required3rdPartyPkgs; // Desktop toolchains don't need any additional settings - if (tcPkg - && !tcPkg->isDesktopToolchain() + if (tcPkg && !tcPkg->isDesktopToolchain() && tcPkg->type() != McuToolChainPackage::Type::Unsupported) required3rdPartyPkgs.append(tcPkg); @@ -542,7 +551,7 @@ protected: boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg); } auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdk.envVar); - if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1,8})) + if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1, 8})) boardSdkPkg->setVersions(desc.boardSdk.versions); boardSdkDefaultPath = boardSdkPkg->defaultPath(); required3rdPartyPkgs.append(boardSdkPkg); @@ -551,14 +560,16 @@ protected: // Free RTOS specific settings if (!desc.freeRTOS.envVar.isEmpty()) { if (!freeRTOSPkgs.contains(desc.freeRTOS.envVar)) { - freeRTOSPkgs.insert(desc.freeRTOS.envVar, createFreeRTOSSourcesPackage( - desc.freeRTOS.envVar, boardSdkDefaultPath, - desc.freeRTOS.boardSdkSubDir)); + freeRTOSPkgs.insert(desc.freeRTOS.envVar, + createFreeRTOSSourcesPackage(desc.freeRTOS.envVar, + boardSdkDefaultPath, + desc.freeRTOS.boardSdkSubDir)); } required3rdPartyPkgs.append(freeRTOSPkgs.value(desc.freeRTOS.envVar)); } - const McuTarget::Platform platform({ desc.platform.id, desc.platform.name, desc.platform.vendor }); + const McuTarget::Platform platform( + {desc.platform.id, desc.platform.name, desc.platform.vendor}); auto mcuTarget = new McuTarget(QVersionNumber::fromString(desc.qulVersion), platform, os, @@ -607,13 +618,16 @@ QVector targetsFromDescriptions(const QList & mcuTargets.append(newTargets); } - packages->append(Utils::transform >( - tcPkgs.values(), [&](McuToolChainPackage *tcPkg) { return tcPkg; })); + packages->append( + Utils::transform>(tcPkgs.values(), + [&](McuToolChainPackage *tcPkg) { + return tcPkg; + })); for (auto *package : vendorPkgs) packages->append(package); packages->append(targetFactory.getMcuPackages()); - return mcuTargets; + return mcuTargets; } Utils::FilePath kitsPath(const Utils::FilePath &dir) @@ -627,7 +641,8 @@ static QFileInfoList targetDescriptionFiles(const Utils::FilePath &dir) return kitsDir.entryInfoList(); } -static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion, const QJsonObject &target) +static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion, + const QJsonObject &target) { const QString compatVersion = target.value("compatVersion").toString(); const QJsonObject toolchain = target.value("toolchain").toObject(); @@ -635,58 +650,66 @@ static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion const QJsonObject freeRTOS = target.value("freeRTOS").toObject(); const QVariantList toolchainVersions = toolchain.value("versions").toArray().toVariantList(); - const auto toolchainVersionsList = Utils::transform( - toolchainVersions, [&](const QVariant &version) { return version.toString(); }); + const auto toolchainVersionsList = Utils::transform(toolchainVersions, + [&](const QVariant &version) { + return version.toString(); + }); const QVariantList boardSdkVersions = boardSdk.value("versions").toArray().toVariantList(); - const auto boardSdkVersionsList = Utils::transform( - boardSdkVersions, [&](const QVariant &version) { return version.toString(); }); + const auto boardSdkVersionsList = Utils::transform(boardSdkVersions, + [&](const QVariant &version) { + return version.toString(); + }); - return { - qulVersion, - compatVersion, - {}, - { - toolchain.value("id").toString(), - toolchainVersionsList, - }, - { - boardSdk.value("name").toString(), - boardSdk.value("defaultPath").toString(), - boardSdk.value("envVar").toString(), - boardSdkVersionsList, - }, - { - freeRTOS.value("envVar").toString(), - freeRTOS.value("boardSdkSubDir").toString(), - } - }; + return {qulVersion, + compatVersion, + {}, + { + toolchain.value("id").toString(), + toolchainVersionsList, + }, + { + boardSdk.value("name").toString(), + boardSdk.value("defaultPath").toString(), + boardSdk.value("envVar").toString(), + boardSdkVersionsList, + }, + { + freeRTOS.value("envVar").toString(), + freeRTOS.value("boardSdkSubDir").toString(), + }}; } -static McuTargetDescription parseDescriptionJsonV1x(const QString &qulVersion, const QJsonObject &target) +static McuTargetDescription parseDescriptionJsonV1x(const QString &qulVersion, + const QJsonObject &target) { auto description = parseDescriptionJsonCommon(qulVersion, target); const QVariantList colorDepths = target.value("colorDepths").toArray().toVariantList(); - const auto colorDepthsVector = Utils::transform >( - colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); }); + const auto colorDepthsVector = Utils::transform>(colorDepths, + [&](const QVariant &colorDepth) { + return colorDepth.toInt(); + }); - description.platform = { - target.value("platform").toString(), - target.value("platformName").toString(), - target.value("platformVendor").toString(), - colorDepthsVector, - description.boardSdk.envVar.isEmpty() ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU - }; + description.platform = {target.value("platform").toString(), + target.value("platformName").toString(), + target.value("platformVendor").toString(), + colorDepthsVector, + description.boardSdk.envVar.isEmpty() + ? McuTargetDescription::TargetType::Desktop + : McuTargetDescription::TargetType::MCU}; return description; } -static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion, const QJsonObject &target) +static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion, + const QJsonObject &target) { const QJsonObject platform = target.value("platform").toObject(); const QVariantList colorDepths = platform.value("colorDepths").toArray().toVariantList(); - const auto colorDepthsVector = Utils::transform >( - colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); }); + const auto colorDepthsVector = Utils::transform>(colorDepths, + [&](const QVariant &colorDepth) { + return colorDepth.toInt(); + }); const QString platformName = platform.value("platformName").toString(); McuTargetDescription description = parseDescriptionJsonCommon(qulVersion, target); description.platform = { @@ -694,7 +717,8 @@ static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion, c platformName, platform.value("vendor").toString(), colorDepthsVector, - platformName == "Desktop" ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU, + platformName == "Desktop" ? McuTargetDescription::TargetType::Desktop + : McuTargetDescription::TargetType::MCU, }; return description; @@ -708,9 +732,12 @@ McuTargetDescription parseDescriptionJson(const QByteArray &data) const QString qulVersion = target.value("qulVersion").toString(); switch (QVersionNumber::fromString(qulVersion).majorVersion()) { - case 1: return parseDescriptionJsonV1x(qulVersion, target); - case 2: return parseDescriptionJsonV2x(qulVersion, target); - default: return { qulVersion }; + case 1: + return parseDescriptionJsonV1x(qulVersion, target); + case 2: + return parseDescriptionJsonV2x(qulVersion, target); + default: + return {qulVersion}; } } @@ -729,10 +756,10 @@ bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message) if (oldSdkQtcRequiredVersion.contains(sdkDetectedVersion)) { message = McuTarget::tr("Qt for MCUs SDK version %1 detected, " "only supported by Qt Creator version %2. " - "This version of Qt Creator requires Qt for MCUs %3 or greater." - ).arg(sdkDetectedVersion, - oldSdkQtcRequiredVersion.value(sdkDetectedVersion), - McuSupportOptions::minimalQulVersion().toString()); + "This version of Qt Creator requires Qt for MCUs %3 or greater.") + .arg(sdkDetectedVersion, + oldSdkQtcRequiredVersion.value(sdkDetectedVersion), + McuSupportOptions::minimalQulVersion().toString()); return true; } @@ -751,26 +778,25 @@ void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo) const McuTargetDescription desc = parseDescriptionJson(file.readAll()); const auto pth = Utils::FilePath::fromString(fileInfo.filePath()); bool ok = false; - const int compatVersion = desc.compatVersion.toInt(&ok); + const int compatVersion = desc.compatVersion.toInt(&ok); if (!desc.compatVersion.isEmpty() && ok && compatVersion > MAX_COMPATIBILITY_VERSION) { - printMessage(McuTarget::tr("Skipped %1. Unsupported version \"%2\".").arg( - QDir::toNativeSeparators(pth.fileNameWithPathComponents(1)), - desc.qulVersion), + printMessage(McuTarget::tr("Skipped %1. Unsupported version \"%2\".") + .arg(QDir::toNativeSeparators(pth.fileNameWithPathComponents(1)), + desc.qulVersion), false); continue; } if (QVersionNumber::fromString(desc.qulVersion) < McuSupportOptions::minimalQulVersion()) { - const QString qtcSupportText = oldSdkQtcRequiredVersion.contains(desc.qulVersion) ? - McuTarget::tr("Detected version \"%1\", only supported by Qt Creator %2.") - .arg(desc.qulVersion, oldSdkQtcRequiredVersion.value(desc.qulVersion)) - : McuTarget::tr("Unsupported version \"%1\".") - .arg(desc.qulVersion); + const QString qtcSupportText + = oldSdkQtcRequiredVersion.contains(desc.qulVersion) + ? McuTarget::tr("Detected version \"%1\", only supported by Qt Creator %2.") + .arg(desc.qulVersion, oldSdkQtcRequiredVersion.value(desc.qulVersion)) + : McuTarget::tr("Unsupported version \"%1\".").arg(desc.qulVersion); printMessage(McuTarget::tr("Skipped %1. %2 Qt for MCUs version >= %3 required.") - .arg( - QDir::toNativeSeparators(pth.fileNameWithPathComponents(1)), - qtcSupportText, - McuSupportOptions::minimalQulVersion().toString()), - false); + .arg(QDir::toNativeSeparators(pth.fileNameWithPathComponents(1)), + qtcSupportText, + McuSupportOptions::minimalQulVersion().toString()), + false); continue; } descriptions.append(desc); @@ -780,7 +806,8 @@ void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo) if (descriptions.empty()) { if (kitsPath(dir).exists()) { printMessage(McuTarget::tr("No valid kit descriptions found at %1.") - .arg(kitsPath(dir).toUserOutput()), true); + .arg(kitsPath(dir).toUserOutput()), + true); return; } else { QString deprecationMessage; @@ -795,45 +822,53 @@ void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo) // Desktop JSON file is shipped starting from Qul 1.5. // This whole section could be removed when minimalQulVersion will reach 1.5 or above { - const bool hasDesktopDescription = contains(descriptions, [](const McuTargetDescription &desc) { - return desc.platform.type == McuTargetDescription::TargetType::Desktop; - }); + const bool hasDesktopDescription + = contains(descriptions, [](const McuTargetDescription &desc) { + return desc.platform.type == McuTargetDescription::TargetType::Desktop; + }); if (!hasDesktopDescription) { QVector desktopLibs; if (HostOsInfo::isWindowsHost()) { desktopLibs << dir / "lib/QulQuickUltralite_QT_32bpp_Windows_Release.lib"; // older versions of QUL (<1.5?) - desktopLibs << dir / "lib/QulQuickUltralitePlatform_QT_32bpp_Windows_msvc_Release.lib"; // newer versions of QUL + desktopLibs + << dir / "lib/QulQuickUltralitePlatform_QT_32bpp_Windows_msvc_Release.lib"; // newer versions of QUL } else { desktopLibs << dir / "lib/libQulQuickUltralite_QT_32bpp_Linux_Debug.a"; // older versions of QUL (<1.5?) desktopLibs << dir / "lib/libQulQuickUltralitePlatform_QT_32bpp_Linux_gnu_Debug.a"; // newer versions of QUL } - if (anyOf(desktopLibs, [](const FilePath &desktopLib) { - return desktopLib.exists(); }) - ) { + if (anyOf(desktopLibs, [](const FilePath &desktopLib) { return desktopLib.exists(); })) { McuTargetDescription desktopDescription; - desktopDescription.qulVersion = descriptions.empty() ? - McuSupportOptions::minimalQulVersion().toString() - : descriptions.first().qulVersion; + desktopDescription.qulVersion + = descriptions.empty() ? McuSupportOptions::minimalQulVersion().toString() + : descriptions.first().qulVersion; desktopDescription.platform.id = "Qt"; desktopDescription.platform.name = "Desktop"; desktopDescription.platform.vendor = "Qt"; desktopDescription.platform.colorDepths = {32}; - desktopDescription.toolchain.id = HostOsInfo::isWindowsHost() ? QString("msvc") : QString("gcc"); + desktopDescription.toolchain.id = HostOsInfo::isWindowsHost() ? QString("msvc") + : QString("gcc"); desktopDescription.platform.type = McuTargetDescription::TargetType::Desktop; descriptions.prepend(desktopDescription); } else { // show error only on 1.x SDKs, but skip on 2.x - const FilePath desktopLibV2 = HostOsInfo::isWindowsHost() ? - dir / "lib/QulPlatform_qt_32bpp_Windows_msvc_Release.lib" + const FilePath desktopLibV2 + = HostOsInfo::isWindowsHost() + ? dir / "lib/QulPlatform_qt_32bpp_Windows_msvc_Release.lib" : dir / "lib/libQulPlatform_qt_32bpp_Linux_gnu_Release.a"; if (dir.exists() && !desktopLibV2.exists()) - printMessage(McuTarget::tr("Skipped creating fallback desktop kit: Could not find any of %1.") - .arg(transform(desktopLibs, [](const auto &path) { - return QDir::toNativeSeparators(path.fileNameWithPathComponents(1)); - }).toList().join(" or ")), - false); + printMessage( + McuTarget::tr( + "Skipped creating fallback desktop kit: Could not find any of %1.") + .arg(transform(desktopLibs, + [](const auto &path) { + return QDir::toNativeSeparators( + path.fileNameWithPathComponents(1)); + }) + .toList() + .join(" or ")), + false); } } } @@ -841,16 +876,20 @@ void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo) repo->mcuTargets.append(targetsFromDescriptions(descriptions, &(repo->packages))); // Keep targets sorted lexicographically - std::sort(repo->mcuTargets.begin(), repo->mcuTargets.end(), [] (const McuTarget* lhs, const McuTarget* rhs) { - return McuSupportOptions::kitName(lhs) < McuSupportOptions::kitName(rhs); - }); + std::sort(repo->mcuTargets.begin(), + repo->mcuTargets.end(), + [](const McuTarget *lhs, const McuTarget *rhs) { + return McuSupportOptions::kitName(lhs) < McuSupportOptions::kitName(rhs); + }); } -FilePath packagePathFromSettings(const QString &settingsKey, QSettings::Scope scope, const FilePath &defaultPath) +FilePath packagePathFromSettings(const QString &settingsKey, + QSettings::Scope scope, + const FilePath &defaultPath) { QSettings *settings = Core::ICore::settings(scope); - const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + - QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + settingsKey; + const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + + QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + settingsKey; const QString path = settings->value(key, defaultPath.toString()).toString(); return FilePath::fromUserInput(path); } diff --git a/src/plugins/mcusupport/mcusupportsdk.h b/src/plugins/mcusupport/mcusupportsdk.h index 486f0d49eaa..5063768d2a7 100644 --- a/src/plugins/mcusupport/mcusupportsdk.h +++ b/src/plugins/mcusupport/mcusupportsdk.h @@ -33,7 +33,7 @@ namespace McuSupport { namespace Internal { -constexpr int MAX_COMPATIBILITY_VERSION {1}; +constexpr int MAX_COMPATIBILITY_VERSION{1}; class McuSdkRepository; class McuAbstractPackage; @@ -51,7 +51,8 @@ bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message); void targetsAndPackages(const Utils::FilePath &qulDir, McuSdkRepository *repo); McuTargetDescription parseDescriptionJson(const QByteArray &); -QVector targetsFromDescriptions(const QList &, QVector *); +QVector targetsFromDescriptions(const QList &, + QVector *); Utils::FilePath kitsPath(const Utils::FilePath &dir); diff --git a/src/plugins/mcusupport/mcusupportversiondetection.cpp b/src/plugins/mcusupport/mcusupportversiondetection.cpp index 2b6b76ef825..b3f1a3cd003 100644 --- a/src/plugins/mcusupport/mcusupportversiondetection.cpp +++ b/src/plugins/mcusupport/mcusupportversiondetection.cpp @@ -43,20 +43,15 @@ QString matchRegExp(const QString &text, const QString ®Exp) return QString(); } -McuPackageVersionDetector::McuPackageVersionDetector() -{ -} +McuPackageVersionDetector::McuPackageVersionDetector() {} McuPackageExecutableVersionDetector::McuPackageExecutableVersionDetector( - const QString &detectionPath, - const QStringList &detectionArgs, - const QString &detectionRegExp) + const QString &detectionPath, const QStringList &detectionArgs, const QString &detectionRegExp) : McuPackageVersionDetector() , m_detectionPath(detectionPath) , m_detectionArgs(detectionArgs) , m_detectionRegExp(detectionRegExp) -{ -} +{} QString McuPackageExecutableVersionDetector::parseVersion(const QString &packagePath) const { @@ -76,8 +71,7 @@ QString McuPackageExecutableVersionDetector::parseVersion(const QString &package binaryProcess.waitForFinished(execTimeout); if (binaryProcess.exitCode() == QProcess::ExitStatus::NormalExit) { const QString processOutput = QString::fromUtf8( - binaryProcess.readAllStandardOutput().append( - binaryProcess.readAllStandardError())); + binaryProcess.readAllStandardOutput().append(binaryProcess.readAllStandardError())); return matchRegExp(processOutput, m_detectionRegExp); } @@ -89,23 +83,23 @@ McuPackageXmlVersionDetector::McuPackageXmlVersionDetector(const QString &filePa const QString &versionElement, const QString &versionAttribute, const QString &versionRegExp) - : m_filePattern(filePattern), - m_versionElement(versionElement), - m_versionAttribute(versionAttribute), - m_versionRegExp(versionRegExp) -{ -} + : m_filePattern(filePattern) + , m_versionElement(versionElement) + , m_versionAttribute(versionAttribute) + , m_versionRegExp(versionRegExp) +{} QString McuPackageXmlVersionDetector::parseVersion(const QString &packagePath) const { const auto files = QDir(packagePath, m_filePattern).entryInfoList(); - for (const auto &xmlFile: files) { + for (const auto &xmlFile : files) { QFile sdkXmlFile = QFile(xmlFile.absoluteFilePath()); sdkXmlFile.open(QFile::OpenModeFlag::ReadOnly); QXmlStreamReader xmlReader(&sdkXmlFile); while (xmlReader.readNext()) { if (xmlReader.name() == m_versionElement) { - const QString versionString = xmlReader.attributes().value(m_versionAttribute).toString(); + const QString versionString + = xmlReader.attributes().value(m_versionAttribute).toString(); const QString matched = matchRegExp(versionString, m_versionRegExp); return !matched.isEmpty() ? matched : versionString; } @@ -118,17 +112,16 @@ QString McuPackageXmlVersionDetector::parseVersion(const QString &packagePath) c McuPackageDirectoryVersionDetector::McuPackageDirectoryVersionDetector(const QString &filePattern, const QString &versionRegExp, const bool isFile) - : m_filePattern(filePattern), - m_versionRegExp(versionRegExp), - m_isFile(isFile) -{ -} + : m_filePattern(filePattern) + , m_versionRegExp(versionRegExp) + , m_isFile(isFile) +{} QString McuPackageDirectoryVersionDetector::parseVersion(const QString &packagePath) const { const auto files = QDir(packagePath, m_filePattern) - .entryInfoList(m_isFile ? QDir::Filter::Files : QDir::Filter::Dirs); - for (const auto &entry: files) { + .entryInfoList(m_isFile ? QDir::Filter::Files : QDir::Filter::Dirs); + for (const auto &entry : files) { const QString matched = matchRegExp(entry.fileName(), m_versionRegExp); if (!matched.isEmpty()) return matched; @@ -138,8 +131,7 @@ QString McuPackageDirectoryVersionDetector::parseVersion(const QString &packageP McuPackagePathVersionDetector::McuPackagePathVersionDetector(const QString &versionRegExp) : m_versionRegExp(versionRegExp) -{ -} +{} QString McuPackagePathVersionDetector::parseVersion(const QString &packagePath) const { @@ -148,5 +140,5 @@ QString McuPackagePathVersionDetector::parseVersion(const QString &packagePath) return matchRegExp(packagePath, m_versionRegExp); } -} // Internal -} // McuSupport +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/mcusupportversiondetection.h b/src/plugins/mcusupport/mcusupportversiondetection.h index 5aa2c799b0e..a5599591562 100644 --- a/src/plugins/mcusupport/mcusupportversiondetection.h +++ b/src/plugins/mcusupport/mcusupportversiondetection.h @@ -47,6 +47,7 @@ public: const QStringList &detectionArgs, const QString &detectionRegExp); QString parseVersion(const QString &packagePath) const final; + private: const QString m_detectionPath; const QStringList m_detectionArgs; @@ -62,6 +63,7 @@ public: const QString &versionAttribute, const QString &versionRegExp); QString parseVersion(const QString &packagePath) const final; + private: const QString m_filePattern; const QString m_versionElement; @@ -73,8 +75,11 @@ private: class McuPackageDirectoryVersionDetector : public McuPackageVersionDetector { public: - McuPackageDirectoryVersionDetector(const QString &filePattern, const QString &versionRegExp, const bool isFile); + McuPackageDirectoryVersionDetector(const QString &filePattern, + const QString &versionRegExp, + const bool isFile); QString parseVersion(const QString &packagePath) const final; + private: const QString m_filePattern; const QString m_versionRegExp; @@ -87,9 +92,10 @@ class McuPackagePathVersionDetector : public McuPackageVersionDetector public: McuPackagePathVersionDetector(const QString &versionRegExp); QString parseVersion(const QString &packagePath) const final; + private: const QString m_versionRegExp; }; -} // Internal -} // McuSupport +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/test/packagemock.h b/src/plugins/mcusupport/test/packagemock.h index 45a23947bee..b7e2f54351c 100644 --- a/src/plugins/mcusupport/test/packagemock.h +++ b/src/plugins/mcusupport/test/packagemock.h @@ -27,8 +27,8 @@ #include "mcuabstractpackage.h" -#include #include +#include namespace McuSupport::Internal { @@ -47,7 +47,7 @@ public: MOCK_METHOD(bool, validStatus, (), (const)); MOCK_METHOD(void, setDownloadUrl, (const QString &) ); MOCK_METHOD(void, setEnvironmentVariableName, (const QString &) ); - MOCK_METHOD(const QString&, environmentVariableName, (), (const)); + MOCK_METHOD(const QString &, environmentVariableName, (), (const)); MOCK_METHOD(void, setAddToPath, (bool) ); MOCK_METHOD(bool, addToPath, (), (const)); MOCK_METHOD(void, writeGeneralSettings, (), (const)); diff --git a/src/plugins/mcusupport/test/unittest.cpp b/src/plugins/mcusupport/test/unittest.cpp index 45b5cdc76d3..57671caaf41 100644 --- a/src/plugins/mcusupport/test/unittest.cpp +++ b/src/plugins/mcusupport/test/unittest.cpp @@ -23,9 +23,9 @@ ** ****************************************************************************/ +#include "unittest.h" #include "mcutargetdescription.h" #include "nxp_1064_json.h" -#include "unittest.h" #include "utils/filepath.h" #include #include diff --git a/src/plugins/mcusupport/test/unittest.h b/src/plugins/mcusupport/test/unittest.h index 738e4d45cea..0f2235afa19 100644 --- a/src/plugins/mcusupport/test/unittest.h +++ b/src/plugins/mcusupport/test/unittest.h @@ -25,10 +25,10 @@ #pragma once +#include "mcupackage.h" #include "mcusupportoptions.h" #include "mcusupportplugin.h" #include "mcusupportsdk.h" -#include "mcupackage.h" #include "packagemock.h" #include From 282c3d0dab0df69e36587a69b2995ecfaeea6435 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 16 Feb 2022 11:27:14 +0100 Subject: [PATCH 03/76] LanguageClient: Do not send initializing request twice Amends dc268e31577. Change-Id: I6ca81ec336f09c02b26f47b5e00bebbc54882ed6 Reviewed-by: David Schulz --- src/plugins/languageclient/client.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 503256c4607..e4923f3bc84 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -312,7 +312,6 @@ void Client::initialize() // directly send message otherwise the state check of sendContent would fail sendMessage(initRequest.toBaseMessage()); - m_clientInterface->sendMessage(initRequest.toBaseMessage()); m_state = InitializeRequested; } From 209ecc91a0119bbac6f5fa685c70dbdb072c810f Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 15 Feb 2022 10:41:13 +0100 Subject: [PATCH 04/76] CMake: Fix configurations tab bar appearance A tab bar should span completely above the group that it "tabs", and have no spacing to it. Otherwise there are funny visual artifacts, and the visual correspondance is not clear. Add an option for spacing to LayoutBuilder for that. Change-Id: I5ca9dc713fff95599c9ec1cf90abe8473bc67c2a Reviewed-by: Reviewed-by: hjk Reviewed-by: Alessandro Portale --- src/libs/utils/layoutbuilder.cpp | 33 +++++++++++++------ src/libs/utils/layoutbuilder.h | 6 ++++ .../cmakebuildconfiguration.cpp | 22 +++++++------ 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/libs/utils/layoutbuilder.cpp b/src/libs/utils/layoutbuilder.cpp index d82617ea463..9a2c067cb29 100644 --- a/src/libs/utils/layoutbuilder.cpp +++ b/src/libs/utils/layoutbuilder.cpp @@ -106,29 +106,36 @@ LayoutBuilder::LayoutItem::LayoutItem(const QString &text) : text(text) {} -static QLayout *createLayoutFromType(LayoutBuilder::LayoutType layoutType) +QLayout *LayoutBuilder::createLayout() const { - switch (layoutType) { + QLayout *layout = nullptr; + switch (m_layoutType) { case LayoutBuilder::FormLayout: { auto formLayout = new QFormLayout; formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); - return formLayout; + layout = formLayout; + break; } case LayoutBuilder::GridLayout: { auto gridLayout = new QGridLayout; - return gridLayout; + layout = gridLayout; + break; } case LayoutBuilder::HBoxLayout: { auto hboxLayout = new QHBoxLayout; - return hboxLayout; + layout = hboxLayout; + break; } case LayoutBuilder::VBoxLayout: { auto vboxLayout = new QVBoxLayout; - return vboxLayout; + layout = vboxLayout; + break; } } - QTC_CHECK(false); - return nullptr; + QTC_ASSERT(layout, return nullptr); + if (m_spacing) + layout->setSpacing(*m_spacing); + return layout; } static void setMargins(bool on, QLayout *layout) @@ -246,7 +253,7 @@ static void doLayoutHelper(QLayout *layout, */ LayoutBuilder::LayoutItem::LayoutItem(const LayoutBuilder &builder) { - layout = createLayoutFromType(builder.m_layoutType); + layout = builder.createLayout(); doLayoutHelper(layout, builder.m_items); setMargins(builder.m_withMargins, layout); } @@ -287,6 +294,12 @@ LayoutBuilder::LayoutBuilder(LayoutType layoutType, const LayoutItems &items) addItem(item); } +LayoutBuilder &LayoutBuilder::setSpacing(int spacing) +{ + m_spacing = spacing; + return *this; +} + LayoutBuilder::LayoutBuilder() = default; /*! @@ -343,7 +356,7 @@ LayoutBuilder &LayoutBuilder::addItem(const LayoutItem &item) void LayoutBuilder::doLayout(QWidget *parent) { - QLayout *layout = createLayoutFromType(m_layoutType); + QLayout *layout = createLayout(); parent->setLayout(layout); doLayoutHelper(layout, m_items); diff --git a/src/libs/utils/layoutbuilder.h b/src/libs/utils/layoutbuilder.h index a258690416e..5953fa09f95 100644 --- a/src/libs/utils/layoutbuilder.h +++ b/src/libs/utils/layoutbuilder.h @@ -27,6 +27,8 @@ #include "utils_global.h" +#include "optional.h" + #include #include #include @@ -97,6 +99,8 @@ public: ~LayoutBuilder(); + LayoutBuilder &setSpacing(int spacing); + LayoutBuilder &addItem(const LayoutItem &item); LayoutBuilder &addItems(const LayoutItems &items); @@ -148,10 +152,12 @@ public: protected: explicit LayoutBuilder(); // Adds to existing layout. + QLayout *createLayout() const; void doLayout(QWidget *parent); LayoutItems m_items; LayoutType m_layoutType; + Utils::optional m_spacing; bool m_withMargins = false; }; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 69e4d01dd09..abf3d4f552d 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -339,16 +339,18 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc) qmlDebugAspect }, m_warningMessageLabel, - Space(10), - Row{m_kitConfiguration, m_configurationStates}, - Group { - cmakeConfiguration, - Row { - bc->aspect(), - bc->aspect() - }, - m_reconfigureButton, - } + m_kitConfiguration, + Column { + m_configurationStates, + Group { + cmakeConfiguration, + Row { + bc->aspect(), + bc->aspect() + }, + m_reconfigureButton, + } + }.setSpacing(0) }.attachTo(details, false); updateAdvancedCheckBox(); From 6e9648015438495f980326d5358f52d44585d252 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Tue, 15 Feb 2022 12:20:44 +0100 Subject: [PATCH 05/76] McuSupport: remove legacy support for 1.x SDKs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTCREATORBUG-26891 Change-Id: I011649b051c6c4c9b954b1c782685e404c3796fe Reviewed-by: Piotr Mućko Reviewed-by: hjk Reviewed-by: Alessandro Portale Reviewed-by: --- src/plugins/mcusupport/mcusupportoptions.cpp | 24 +-- src/plugins/mcusupport/mcusupportsdk.cpp | 200 +++++------------- src/plugins/mcusupport/mcusupportsdk.h | 4 +- .../wizards/application/CMakeLists.txt | 17 +- 4 files changed, 63 insertions(+), 182 deletions(-) diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index 5e35257903e..93de54c47b8 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -401,7 +401,7 @@ void McuSupportOptions::registerExamples() const QVersionNumber &McuSupportOptions::minimalQulVersion() { - static const QVersionNumber v({1, 3}); + static const QVersionNumber v({2, 0}); return v; } @@ -420,7 +420,7 @@ void McuSupportOptions::setQulDir(const FilePath &dir) FilePath McuSupportOptions::qulDirFromSettings() { return Sdk::packagePathFromSettings(Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK, - QSettings::UserScope); + QSettings::UserScope, {}); } static void setKitProperties(const QString &kitName, @@ -567,14 +567,6 @@ void McuSupportOptions::setKitEnvironment(Kit *k, processPackage(package); processPackage(qtForMCUsSdkPackage); - // Clang not needed in version 1.7+ - if (mcuTarget->qulVersion() < QVersionNumber{1, 7}) { - const QString path = QLatin1String(HostOsInfo::isWindowsHost() ? "Path" : "PATH"); - pathAdditions.append("${" + path + "}"); - pathAdditions.append(Core::ICore::libexecPath("clang/bin").toUserOutput()); - changes.append({path, pathAdditions.join(HostOsInfo::pathListSeparator())}); - } - if (kitNeedsQtVersion()) changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"}); @@ -671,9 +663,6 @@ static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePat config.append(CMakeConfigItem("QUL_PLATFORM", mcuTarget->platform().name.toUtf8())); - if (mcuTarget->qulVersion() <= QVersionNumber{1, 3} // OS variable was removed in Qul 1.4 - && mcuTarget->os() == McuTarget::OS::FreeRTOS) - config.append(CMakeConfigItem("OS", "FreeRTOS")); if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth) config.append(CMakeConfigItem("QUL_COLOR_DEPTH", QString::number(mcuTarget->colorDepth()).toLatin1())); @@ -700,12 +689,6 @@ static void setKitQtVersionOptions(Kit *k) QString McuSupportOptions::kitName(const McuTarget *mcuTarget) { - QString os; - if (mcuTarget->qulVersion() <= QVersionNumber{1, 3} - && mcuTarget->os() == McuTarget::OS::FreeRTOS) - // Starting from Qul 1.4 each OS is a separate platform - os = QLatin1String(" FreeRTOS"); - const McuToolChainPackage *tcPkg = mcuTarget->toolChainPackage(); const QString compilerName = tcPkg && !tcPkg->isDesktopToolchain() ? QString::fromLatin1(" (%1)").arg( @@ -717,11 +700,10 @@ QString McuSupportOptions::kitName(const McuTarget *mcuTarget) const QString targetName = mcuTarget->platform().displayName.isEmpty() ? mcuTarget->platform().name : mcuTarget->platform().displayName; - return QString::fromLatin1("Qt for MCUs %1.%2 - %3%4%5%6") + return QString::fromLatin1("Qt for MCUs %1.%2 - %3%4%5") .arg(QString::number(mcuTarget->qulVersion().majorVersion()), QString::number(mcuTarget->qulVersion().minorVersion()), targetName, - os, colorDepth, compilerName); } diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index 74d5ccedc33..a3a041dfd76 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -527,10 +527,9 @@ protected: QVector mcuTargets; McuToolChainPackage *tcPkg = tcPkgs.value(desc.toolchain.id); - if (tcPkg) { - if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1, 8})) - tcPkg->setVersions(desc.toolchain.versions); - } else + if (tcPkg) + tcPkg->setVersions(desc.toolchain.versions); + else tcPkg = createUnsupportedToolChainPackage(); for (int colorDepth : desc.platform.colorDepths) { QVector required3rdPartyPkgs; @@ -551,8 +550,7 @@ protected: boardSdkPkgs.insert(desc.boardSdk.envVar, boardSdkPkg); } auto boardSdkPkg = boardSdkPkgs.value(desc.boardSdk.envVar); - if (QVersionNumber::fromString(desc.qulVersion) >= QVersionNumber({1, 8})) - boardSdkPkg->setVersions(desc.boardSdk.versions); + boardSdkPkg->setVersions(desc.boardSdk.versions); boardSdkDefaultPath = boardSdkPkg->defaultPath(); required3rdPartyPkgs.append(boardSdkPkg); } @@ -641,9 +639,12 @@ static QFileInfoList targetDescriptionFiles(const Utils::FilePath &dir) return kitsDir.entryInfoList(); } -static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion, - const QJsonObject &target) +McuTargetDescription parseDescriptionJson(const QByteArray &data) { + const QJsonDocument document = QJsonDocument::fromJson(data); + const QJsonObject target = document.object(); + const QString qulVersion = target.value("qulVersion").toString(); + const QJsonObject platform = target.value("platform").toObject(); const QString compatVersion = target.value("compatVersion").toString(); const QJsonObject toolchain = target.value("toolchain").toObject(); const QJsonObject boardSdk = target.value("boardSdk").toObject(); @@ -660,105 +661,70 @@ static McuTargetDescription parseDescriptionJsonCommon(const QString &qulVersion return version.toString(); }); - return {qulVersion, - compatVersion, - {}, - { - toolchain.value("id").toString(), - toolchainVersionsList, - }, - { - boardSdk.value("name").toString(), - boardSdk.value("defaultPath").toString(), - boardSdk.value("envVar").toString(), - boardSdkVersionsList, - }, - { - freeRTOS.value("envVar").toString(), - freeRTOS.value("boardSdkSubDir").toString(), - }}; -} - -static McuTargetDescription parseDescriptionJsonV1x(const QString &qulVersion, - const QJsonObject &target) -{ - auto description = parseDescriptionJsonCommon(qulVersion, target); - - const QVariantList colorDepths = target.value("colorDepths").toArray().toVariantList(); - const auto colorDepthsVector = Utils::transform>(colorDepths, - [&](const QVariant &colorDepth) { - return colorDepth.toInt(); - }); - - description.platform = {target.value("platform").toString(), - target.value("platformName").toString(), - target.value("platformVendor").toString(), - colorDepthsVector, - description.boardSdk.envVar.isEmpty() - ? McuTargetDescription::TargetType::Desktop - : McuTargetDescription::TargetType::MCU}; - return description; -} - -static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion, - const QJsonObject &target) -{ - const QJsonObject platform = target.value("platform").toObject(); - const QVariantList colorDepths = platform.value("colorDepths").toArray().toVariantList(); const auto colorDepthsVector = Utils::transform>(colorDepths, [&](const QVariant &colorDepth) { return colorDepth.toInt(); }); const QString platformName = platform.value("platformName").toString(); - McuTargetDescription description = parseDescriptionJsonCommon(qulVersion, target); - description.platform = { - platform.value("id").toString(), - platformName, - platform.value("vendor").toString(), - colorDepthsVector, - platformName == "Desktop" ? McuTargetDescription::TargetType::Desktop - : McuTargetDescription::TargetType::MCU, + + return { + qulVersion, + compatVersion, + { + platform.value("id").toString(), + platformName, + platform.value("vendor").toString(), + colorDepthsVector, + platformName == "Desktop" ? McuTargetDescription::TargetType::Desktop : McuTargetDescription::TargetType::MCU, + }, + { + toolchain.value("id").toString(), + toolchainVersionsList, + }, + { + boardSdk.value("name").toString(), + boardSdk.value("defaultPath").toString(), + boardSdk.value("envVar").toString(), + boardSdkVersionsList, + }, + { + freeRTOS.value("envVar").toString(), + freeRTOS.value("boardSdkSubDir").toString(), + } }; - - return description; -} - -McuTargetDescription parseDescriptionJson(const QByteArray &data) -{ - const QJsonDocument document = QJsonDocument::fromJson(data); - const QJsonObject target = document.object(); - - const QString qulVersion = target.value("qulVersion").toString(); - - switch (QVersionNumber::fromString(qulVersion).majorVersion()) { - case 1: - return parseDescriptionJsonV1x(qulVersion, target); - case 2: - return parseDescriptionJsonV2x(qulVersion, target); - default: - return {qulVersion}; - } } // https://doc.qt.io/qtcreator/creator-developing-mcu.html#supported-qt-for-mcus-sdks -const QHash oldSdkQtcRequiredVersion = { - {{"1.0"}, {"4.11.x"}}, - {{"1.1"}, {"4.12.0 or 4.12.1"}}, - {{"1.2"}, {"4.12.2 or 4.12.3"}}, -}; +static const QString legacySupportVersionFor(const QString &sdkVersion) +{ + static const QHash oldSdkQtcRequiredVersion = { + {{"1.0"}, {"4.11.x"}}, + {{"1.1"}, {"4.12.0 or 4.12.1"}}, + {{"1.2"}, {"4.12.2 or 4.12.3"}} + }; + if (oldSdkQtcRequiredVersion.contains(sdkVersion)) + return oldSdkQtcRequiredVersion.value(sdkVersion); + + if (QVersionNumber::fromString(sdkVersion).majorVersion() == 1) + return "4.12.4 up to 6.0"; + + return QString(); +} + bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message) { const McuPackagePathVersionDetector versionDetector("(?<=\\bQtMCUs.)(\\d+\\.\\d+)"); const QString sdkDetectedVersion = versionDetector.parseVersion(qulDir.toString()); + const QString legacyVersion = legacySupportVersionFor(sdkDetectedVersion); - if (oldSdkQtcRequiredVersion.contains(sdkDetectedVersion)) { + if (!legacyVersion.isEmpty()) { message = McuTarget::tr("Qt for MCUs SDK version %1 detected, " "only supported by Qt Creator version %2. " "This version of Qt Creator requires Qt for MCUs %3 or greater.") .arg(sdkDetectedVersion, - oldSdkQtcRequiredVersion.value(sdkDetectedVersion), + legacyVersion, McuSupportOptions::minimalQulVersion().toString()); return true; } @@ -787,10 +753,11 @@ void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo) continue; } if (QVersionNumber::fromString(desc.qulVersion) < McuSupportOptions::minimalQulVersion()) { + const QString legacyVersion = legacySupportVersionFor(desc.qulVersion); const QString qtcSupportText - = oldSdkQtcRequiredVersion.contains(desc.qulVersion) + = !legacyVersion.isEmpty() ? McuTarget::tr("Detected version \"%1\", only supported by Qt Creator %2.") - .arg(desc.qulVersion, oldSdkQtcRequiredVersion.value(desc.qulVersion)) + .arg(desc.qulVersion, legacyVersion) : McuTarget::tr("Unsupported version \"%1\".").arg(desc.qulVersion); printMessage(McuTarget::tr("Skipped %1. %2 Qt for MCUs version >= %3 required.") .arg(QDir::toNativeSeparators(pth.fileNameWithPathComponents(1)), @@ -818,61 +785,6 @@ void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo) } } - // Workaround for missing JSON file for Desktop target. - // Desktop JSON file is shipped starting from Qul 1.5. - // This whole section could be removed when minimalQulVersion will reach 1.5 or above - { - const bool hasDesktopDescription - = contains(descriptions, [](const McuTargetDescription &desc) { - return desc.platform.type == McuTargetDescription::TargetType::Desktop; - }); - - if (!hasDesktopDescription) { - QVector desktopLibs; - if (HostOsInfo::isWindowsHost()) { - desktopLibs << dir / "lib/QulQuickUltralite_QT_32bpp_Windows_Release.lib"; // older versions of QUL (<1.5?) - desktopLibs - << dir / "lib/QulQuickUltralitePlatform_QT_32bpp_Windows_msvc_Release.lib"; // newer versions of QUL - } else { - desktopLibs << dir / "lib/libQulQuickUltralite_QT_32bpp_Linux_Debug.a"; // older versions of QUL (<1.5?) - desktopLibs << dir / "lib/libQulQuickUltralitePlatform_QT_32bpp_Linux_gnu_Debug.a"; // newer versions of QUL - } - - if (anyOf(desktopLibs, [](const FilePath &desktopLib) { return desktopLib.exists(); })) { - McuTargetDescription desktopDescription; - desktopDescription.qulVersion - = descriptions.empty() ? McuSupportOptions::minimalQulVersion().toString() - : descriptions.first().qulVersion; - desktopDescription.platform.id = "Qt"; - desktopDescription.platform.name = "Desktop"; - desktopDescription.platform.vendor = "Qt"; - desktopDescription.platform.colorDepths = {32}; - desktopDescription.toolchain.id = HostOsInfo::isWindowsHost() ? QString("msvc") - : QString("gcc"); - desktopDescription.platform.type = McuTargetDescription::TargetType::Desktop; - descriptions.prepend(desktopDescription); - } else { - // show error only on 1.x SDKs, but skip on 2.x - const FilePath desktopLibV2 - = HostOsInfo::isWindowsHost() - ? dir / "lib/QulPlatform_qt_32bpp_Windows_msvc_Release.lib" - : dir / "lib/libQulPlatform_qt_32bpp_Linux_gnu_Release.a"; - if (dir.exists() && !desktopLibV2.exists()) - printMessage( - McuTarget::tr( - "Skipped creating fallback desktop kit: Could not find any of %1.") - .arg(transform(desktopLibs, - [](const auto &path) { - return QDir::toNativeSeparators( - path.fileNameWithPathComponents(1)); - }) - .toList() - .join(" or ")), - false); - } - } - } - repo->mcuTargets.append(targetsFromDescriptions(descriptions, &(repo->packages))); // Keep targets sorted lexicographically diff --git a/src/plugins/mcusupport/mcusupportsdk.h b/src/plugins/mcusupport/mcusupportsdk.h index 5063768d2a7..a79a7d90f10 100644 --- a/src/plugins/mcusupport/mcusupportsdk.h +++ b/src/plugins/mcusupport/mcusupportsdk.h @@ -57,8 +57,8 @@ QVector targetsFromDescriptions(const QList & Utils::FilePath kitsPath(const Utils::FilePath &dir); Utils::FilePath packagePathFromSettings(const QString &settingsKey, - QSettings::Scope scope = QSettings::UserScope, - const Utils::FilePath &defaultPath = {}); + QSettings::Scope scope, + const Utils::FilePath &defaultPath); } // namespace Sdk } // namespace Internal } // namespace McuSupport diff --git a/src/plugins/mcusupport/wizards/application/CMakeLists.txt b/src/plugins/mcusupport/wizards/application/CMakeLists.txt index 74c1c8357ba..4b384653be1 100644 --- a/src/plugins/mcusupport/wizards/application/CMakeLists.txt +++ b/src/plugins/mcusupport/wizards/application/CMakeLists.txt @@ -4,20 +4,7 @@ project(%{ProjectName} VERSION 0.0.1 LANGUAGES C CXX ASM ASM_MASM) find_package(Qul) -if(Qul_VERSION VERSION_GREATER_EQUAL "1.7") - qul_add_target(%{ProjectName}) -else() - add_executable(%{ProjectName}) - target_link_libraries(%{ProjectName} - Qul::QuickUltralite - Qul::QuickUltralitePlatform) -endif() - +qul_add_target(%{ProjectName}) qul_target_qml_sources(%{ProjectName} %{MainQmlFile}) app_target_setup_os(%{ProjectName}) - -if(Qul_VERSION VERSION_GREATER_EQUAL "2.0") - app_target_default_entrypoint(%{ProjectName} %{RootItemName}) -else() - app_target_default_main(%{ProjectName} %{RootItemName}) -endif() +app_target_default_entrypoint(%{ProjectName} %{RootItemName}) From a5a50f01b1719bb3a8ce88610d4864c15f354f8d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 16 Feb 2022 12:50:27 +0100 Subject: [PATCH 06/76] Fix build Amends 45c018f560a. Change-Id: Iefb39e0855bf671a7a27f161bb99529c03fb8a66 Reviewed-by: Eike Ziller --- src/app/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index b77138468e2..e30d9fe6abd 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -26,6 +26,7 @@ add_qtc_executable(qtcreator extend_qtc_executable(qtcreator CONDITION APPLE + DEPENDS ${FWFoundation} SOURCES main_mac.mm ) From 2a1ce51ce308bfe73debd58b499f9ebc32b89d2f Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 17:51:35 +0100 Subject: [PATCH 07/76] Utils: Fix UI text punctuation and capitalization Also simplify the wording of a message. Task-number: QTCREATORBUG-27055 Change-Id: I29df31f8484d451d8d8d1869ca3a1b182072d2c1 Reviewed-by: Jarek Kobus --- src/libs/utils/launchersocket.cpp | 2 +- src/libs/utils/qtcprocess.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/utils/launchersocket.cpp b/src/libs/utils/launchersocket.cpp index e4bfed17f0a..c232579e20d 100644 --- a/src/libs/utils/launchersocket.cpp +++ b/src/libs/utils/launchersocket.cpp @@ -932,7 +932,7 @@ void LauncherSocket::handleSocketDisconnected() { QTC_ASSERT(isCalledFromLaunchersThread(), return); handleError(QCoreApplication::translate("Utils::LauncherSocket", - "Launcher socket closed unexpectedly")); + "Launcher socket closed unexpectedly.")); } void LauncherSocket::handleError(const QString &error) diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 9e56fe0f1be..90299e06bbd 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -986,12 +986,12 @@ static bool askToKill(const QString &command) #ifdef QT_GUI_LIB if (QThread::currentThread() != QCoreApplication::instance()->thread()) return true; - const QString title = QtcProcess::tr("Process not Responding"); + const QString title = QtcProcess::tr("Process Not Responding"); QString msg = command.isEmpty() ? QtcProcess::tr("The process is not responding.") : QtcProcess::tr("The process \"%1\" is not responding.").arg(command); msg += ' '; - msg += QtcProcess::tr("Would you like to terminate it?"); + msg += QtcProcess::tr("Terminate the process?"); // Restore the cursor that is set to wait while running. const bool hasOverrideCursor = QApplication::overrideCursor() != nullptr; if (hasOverrideCursor) From 2cd7d89ec58c0e308c5f434fbb65acf686cdf133 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 14 Jan 2022 17:14:02 +0100 Subject: [PATCH 08/76] Android: Remove a cast in AndroidDeployQtStep::init Don't do an additional dynamic_cast. Change-Id: Icf3beda4e78bc03232689439e8ba264287b603ab Reviewed-by: Assam Boudjelthia --- src/plugins/android/androiddeployqtstep.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/android/androiddeployqtstep.cpp b/src/plugins/android/androiddeployqtstep.cpp index 16177ca1afa..1d76083a6e0 100644 --- a/src/plugins/android/androiddeployqtstep.cpp +++ b/src/plugins/android/androiddeployqtstep.cpp @@ -164,14 +164,15 @@ bool AndroidDeployQtStep::init() if (selectedAbis.isEmpty()) selectedAbis.append(bs->extraData(buildKey, Constants::AndroidAbi).toString()); - // TODO: use AndroidDevice directly instead of AndroidDeviceInfo. if (!info.isValid()) { - const IDevice *dev = DeviceKitAspect::device(kit()).data(); + const auto dev = + static_cast(DeviceKitAspect::device(kit()).data()); if (!dev) { reportWarningOrError(tr("No valid deployment device is set."), Task::Error); return false; } + // TODO: use AndroidDevice directly instead of AndroidDeviceInfo. info = AndroidDevice::androidDeviceInfoFromIDevice(dev); m_deviceInfo = info; // Keep around for later steps @@ -181,18 +182,17 @@ bool AndroidDeployQtStep::init() return false; } - const AndroidDevice *androidDev = static_cast(dev); - if (androidDev && !androidDev->canSupportAbis(selectedAbis)) { + if (!dev->canSupportAbis(selectedAbis)) { const QString error = tr("The deployment device \"%1\" does not support the " "architectures used by the kit.\n" "The kit supports \"%2\", but the device uses \"%3\".") .arg(dev->displayName()).arg(selectedAbis.join(", ")) - .arg(androidDev->supportedAbis().join(", ")); + .arg(dev->supportedAbis().join(", ")); reportWarningOrError(error, Task::Error); return false; } - if (androidDev && !androidDev->canHandleDeployments()) { + if (!dev->canHandleDeployments()) { reportWarningOrError(tr("The deployment device \"%1\" is disconnected.") .arg(dev->displayName()), Task::Error); return false; From 4b7ab40ed0f5feecc418e3dc45b605008771a8f9 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Wed, 16 Feb 2022 12:39:46 +0100 Subject: [PATCH 09/76] QmlDesigner: Add private api to narrow down bug This is only a temporary patch to narrow down a bug in QtDS. Task-number: QDS-6239 Change-Id: Icf9cde008179174fd79fb92a92372fb2b541068b Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- src/plugins/studiowelcome/CMakeLists.txt | 2 +- src/plugins/studiowelcome/examplecheckout.cpp | 26 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/plugins/studiowelcome/CMakeLists.txt b/src/plugins/studiowelcome/CMakeLists.txt index 48c07d15b97..a8b92ab1f8b 100644 --- a/src/plugins/studiowelcome/CMakeLists.txt +++ b/src/plugins/studiowelcome/CMakeLists.txt @@ -1,6 +1,6 @@ add_qtc_plugin(StudioWelcome CONDITION TARGET Qt5::QuickWidgets AND TARGET QmlDesigner - DEPENDS Qt5::QuickWidgets + DEPENDS Qt5::QuickWidgets Qt5::QmlPrivate PLUGIN_DEPENDS Core ProjectExplorer QtSupport QmlDesigner DEFINES STUDIO_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/qml/" SOURCES diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp index 45d7dd440fb..b094fd2f08a 100644 --- a/src/plugins/studiowelcome/examplecheckout.cpp +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -31,6 +31,8 @@ #include #include +#include + #include #include #include @@ -247,6 +249,17 @@ void FileDownloader::probeUrl() }); QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() { + QQmlData *data = QQmlData::get(this, false); + if (!data) { + qDebug() << Q_FUNC_INFO << "FileDownloader is nullptr."; + return; + } + + if (QQmlData::wasDeleted(this)) { + qDebug() << Q_FUNC_INFO << "FileDownloader was deleted."; + return; + } + if (reply->error()) return; @@ -261,8 +274,17 @@ void FileDownloader::probeUrl() &QNetworkReply::errorOccurred, this, [this, reply](QNetworkReply::NetworkError code) { - // QNetworkReply::HostNotFoundError - // QNetworkReply::ContentNotFoundError + QQmlData *data = QQmlData::get(this, false); + if (!data) { + qDebug() << Q_FUNC_INFO << "FileDownloader is nullptr."; + return; + } + + if (QQmlData::wasDeleted(this)) { + qDebug() << Q_FUNC_INFO << "FileDownloader was deleted."; + return; + } + m_available = false; emit availableChanged(); }); From 59e90a439e2a8ad32b5556cd9feebf359561985b Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 17 Feb 2022 06:29:59 +0100 Subject: [PATCH 10/76] StudioWelcome: Fix qbs build Change-Id: I37c5f2df2480fd1357a55d36744330534385b68e Reviewed-by: David Schulz --- src/plugins/studiowelcome/studiowelcome.qbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/studiowelcome/studiowelcome.qbs b/src/plugins/studiowelcome/studiowelcome.qbs index afc9e627a52..cc655ea5a23 100644 --- a/src/plugins/studiowelcome/studiowelcome.qbs +++ b/src/plugins/studiowelcome/studiowelcome.qbs @@ -3,7 +3,7 @@ import qbs.FileInfo QtcPlugin { name: "StudioWelcome" - Depends { name: "Qt"; submodules: ["qml", "quick", "quickwidgets"] } + Depends { name: "Qt"; submodules: ["qml", "qml-private", "quick", "quickwidgets"] } Depends { name: "Utils" } Depends { name: "Core" } From 85976b3caf12d1e8e0241c2f6c945a45502be498 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 17 Feb 2022 06:41:27 +0100 Subject: [PATCH 11/76] Qbs: Include latest change in qbs build Amends 45c018f560ac6c75ea43. Change-Id: I161bae375e422a352ba702c1030498511bbe5d81 Reviewed-by: Christian Kandeler Reviewed-by: Eike Ziller --- src/app/app.qbs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/app/app.qbs b/src/app/app.qbs index 42172aa09f6..a0b30ae2ae4 100644 --- a/src/app/app.qbs +++ b/src/app/app.qbs @@ -43,6 +43,8 @@ QtcProduct { project.sharedSourcesDir + "/qtlockedfile", ] + cpp.frameworks: base.concat(qbs.targetOS.contains("macos") ? ["Foundation"] : []) + Depends { name: "app_version_header" } Depends { name: "Qt"; submodules: ["widgets", "network"] } Depends { name: "Utils" } @@ -97,4 +99,12 @@ QtcProduct { "../shared/qtlockedfile/qtlockedfile_win.cpp" ] } + + Group { + name: "main_macos" + condition: qbs.targetOS.contains("macos") + files: [ + "main_mac.mm" + ] + } } From 22b9628d54202a8492c38a79f755251e89d8b740 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 17 Feb 2022 08:56:00 +0100 Subject: [PATCH 12/76] Nanotrace: Fix build with older Xcode Change-Id: Ia0f29844ba95fc75199cbfd98932d5bf4c270335 Reviewed-by: Eike Ziller --- src/libs/nanotrace/nanotrace.cpp | 2 +- src/libs/nanotrace/nanotrace.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/nanotrace/nanotrace.cpp b/src/libs/nanotrace/nanotrace.cpp index 36c7fd74590..d6e6ca30a30 100644 --- a/src/libs/nanotrace/nanotrace.cpp +++ b/src/libs/nanotrace/nanotrace.cpp @@ -60,7 +60,7 @@ struct ConvertArgValueToString { std::string Arg::value() const { - return std::visit(ConvertArgValueToString(), m_value); + return Utils::visit(ConvertArgValueToString(), m_value); } diff --git a/src/libs/nanotrace/nanotrace.h b/src/libs/nanotrace/nanotrace.h index 0df2be76df1..ea26487e408 100644 --- a/src/libs/nanotrace/nanotrace.h +++ b/src/libs/nanotrace/nanotrace.h @@ -33,9 +33,9 @@ # define NANOTRACESHARED_EXPORT Q_DECL_IMPORT #endif +#include // revert when macos minimum target is >= 10.14 #include -#include #include @@ -80,7 +80,7 @@ using TimePoint = std::chrono::time_point< Clock >; class NANOTRACESHARED_EXPORT Arg { public: - using SupportedType = std::variant; + using SupportedType = Utils::variant; Arg(const std::string &name, const SupportedType &val); std::string name() const; From 120218e0fd6bdc68fc95a6ff0924e8a5a4b50d37 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 15 Feb 2022 16:47:07 +0100 Subject: [PATCH 13/76] Update qbs submodule ... to HEAD of 1.22 branch. Change-Id: Ib15854a88b6265f341c42f2b62d67f914fb9e747 Reviewed-by: Qt CI Bot Reviewed-by: Reviewed-by: Christian Stenger --- share/qtcreator/qml-type-descriptions/qbs-bundle.json | 1 + share/qtcreator/qml-type-descriptions/qbs.qmltypes | 2 ++ src/shared/qbs | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/share/qtcreator/qml-type-descriptions/qbs-bundle.json b/share/qtcreator/qml-type-descriptions/qbs-bundle.json index cf230cdefee..7f0c6886911 100644 --- a/share/qtcreator/qml-type-descriptions/qbs-bundle.json +++ b/share/qtcreator/qml-type-descriptions/qbs-bundle.json @@ -19,6 +19,7 @@ "qbs.FileInfo", "qbs.ModUtils", "qbs.PathTools", + "qbs.PkgConfig", "qbs.Probes", "qbs.Process", "qbs.PropertyList", diff --git a/share/qtcreator/qml-type-descriptions/qbs.qmltypes b/share/qtcreator/qml-type-descriptions/qbs.qmltypes index bc4244b63fc..941697b02d2 100644 --- a/share/qtcreator/qml-type-descriptions/qbs.qmltypes +++ b/share/qtcreator/qml-type-descriptions/qbs.qmltypes @@ -133,6 +133,7 @@ Module { Property { name: "multiplexedType"; type: "string"; isList: true } Property { name: "name"; type: "string" } Property { name: "profiles"; type: "string"; isList: true } + Property { name: "qbsModuleProviders"; type: "string"; isList: true } Property { name: "qbsSearchPaths"; type: "string"; isList: true } Property { name: "targetName"; type: "string" } Property { name: "type"; type: "string"; isList: true } @@ -155,6 +156,7 @@ Module { Property { name: "minimumQbsVersion"; type: "string" } Property { name: "name"; type: "string" } Property { name: "profile"; type: "string" } + Property { name: "qbsModuleProviders"; type: "string"; isList: true } Property { name: "qbsSearchPaths"; type: "string"; isList: true } Property { name: "references"; type: "string"; isList: true } Property { name: "sourceDirectory"; type: "string" } diff --git a/src/shared/qbs b/src/shared/qbs index 768b6894a8d..29b15e594f5 160000 --- a/src/shared/qbs +++ b/src/shared/qbs @@ -1 +1 @@ -Subproject commit 768b6894a8d189158fed83cbc79d92d5484cb2e4 +Subproject commit 29b15e594f50314959ce9b63c4a39cc86e831475 From ff71d1fb7b3c6e8d103339a1484588537764a98f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 17 Feb 2022 09:59:27 +0100 Subject: [PATCH 14/76] Update qlitehtml to latest master Change-Id: I3fbfcba59dbc43a617cad960556fe6484a088555 Reviewed-by: Christian Kandeler --- src/libs/qlitehtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/qlitehtml b/src/libs/qlitehtml index 1d73f76face..62a1650652f 160000 --- a/src/libs/qlitehtml +++ b/src/libs/qlitehtml @@ -1 +1 @@ -Subproject commit 1d73f76faceb4b70b4eedab110400db7fddf6eb9 +Subproject commit 62a1650652fe5aa45f3e79e4b1a26f3bf92c6d4b From 95287628557da81ac8188c053d8fd2a5a927dea4 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 10 Feb 2022 17:08:16 +0100 Subject: [PATCH 15/76] Disable -Wmissing-field-initializers when building with GCC This warning is enabled with -Wextra, but incomplete aggregate initialization is quite common in modern C++ due to direct member initialization, and we make use of that in Creator in several places. Change-Id: I585dd70e7c5c52e4549f1c5e3b8d16cc40b260ce Reviewed-by: Qt CI Bot Reviewed-by: Christian Stenger --- CMakeLists.txt | 3 +++ qbs/imports/QtcProduct.qbs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c6f603c7981..187fccd493c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,9 @@ if (Qt5_VERSION VERSION_LESS 6.0.0) if (MSVC AND MSVC_VERSION GREATER_EQUAL 1910) add_compile_options(/permissive- /Zc:__cplusplus) endif() + if (CMAKE_CXX_COMPILER_ID STREQUAL GNU) + add_compile_options(-Wno-missing-field-initializers) +endif() else() # Common intermediate directory for QML modules which are defined via qt_add_qml_module() set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml_modules") diff --git a/qbs/imports/QtcProduct.qbs b/qbs/imports/QtcProduct.qbs index 85b334daf0d..ee84b46aa3e 100644 --- a/qbs/imports/QtcProduct.qbs +++ b/qbs/imports/QtcProduct.qbs @@ -50,7 +50,7 @@ Product { flags.push("-Wno-deprecated-copy", "-Wno-constant-logical-operand"); } if (!qbs.toolchain.contains("clang")) { - flags.push("-Wno-noexcept-type"); + flags.push("-Wno-missing-field-initializers", "-Wno-noexcept-type"); if (Utilities.versionCompare(cpp.compilerVersion, "9") >= 0) flags.push("-Wno-deprecated-copy", "-Wno-init-list-lifetime"); } From 01a0f41ed57cfa55bc68f4bc753bca2beef7402a Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 17 Feb 2022 09:53:56 +0100 Subject: [PATCH 16/76] Utils: Fix MinGW build Change-Id: I019651bb7de30595790cfe3b79a12579ce24410f Reviewed-by: Christian Kandeler --- src/libs/utils/utils.qbs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index e6ad32fb028..318e7bcbef1 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -13,6 +13,8 @@ Project { var libs = []; if (qbs.targetOS.contains("windows")) { libs.push("user32", "iphlpapi", "ws2_32", "shell32", "ole32"); + if (qbs.toolchainType === "mingw") + libs.push("uuid"); } else if (qbs.targetOS.contains("unix")) { if (!qbs.targetOS.contains("macos")) libs.push("X11"); From c755de08238cc8c5878a1403f891d4023094ce00 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 14 Feb 2022 18:01:04 +0100 Subject: [PATCH 17/76] McuSupport: Move kit methods out of McuSupportOptions ... and into McuKitManager Task-number: QTCREATORBUG-26890 Change-Id: Ic5ed689458d3ef004ebb42a549c48a6326c2f45d Reviewed-by: Alessandro Portale --- src/plugins/mcusupport/mcupackage.h | 4 - src/plugins/mcusupport/mcusupportoptions.cpp | 81 ++++++++++--------- src/plugins/mcusupport/mcusupportoptions.h | 74 ++++++++++------- .../mcusupport/mcusupportoptionspage.cpp | 31 +++---- src/plugins/mcusupport/mcusupportplugin.cpp | 21 ++--- src/plugins/mcusupport/mcusupportsdk.cpp | 2 +- src/plugins/mcusupport/test/unittest.cpp | 2 +- 7 files changed, 116 insertions(+), 99 deletions(-) diff --git a/src/plugins/mcusupport/mcupackage.h b/src/plugins/mcusupport/mcupackage.h index b7d415fd3f3..5afa32e009f 100644 --- a/src/plugins/mcusupport/mcupackage.h +++ b/src/plugins/mcusupport/mcupackage.h @@ -86,10 +86,6 @@ public: const QString &environmentVariableName() const override; -signals: - void changed(); - void statusChanged(); - private: void updatePath(); void updateStatusUi(); diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index 93de54c47b8..f9972473613 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -307,13 +307,13 @@ void McuTarget::printPackageProblems() const package->updateStatus(); if (!package->validStatus()) printMessage(tr("Error creating kit for target %1, package %2: %3") - .arg(McuSupportOptions::kitName(this), + .arg(McuKitManager::kitName(this), package->label(), package->statusText()), true); if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion) printMessage(tr("Warning creating kit for target %1, package %2: %3") - .arg(McuSupportOptions::kitName(this), + .arg(McuKitManager::kitName(this), package->label(), package->statusText()), false); @@ -412,9 +412,9 @@ void McuSupportOptions::setQulDir(const FilePath &dir) if (qtForMCUsSdkPackage->validStatus()) Sdk::targetsAndPackages(dir, &sdkRepository); for (const auto &package : qAsConst(sdkRepository.packages)) - connect(package, &McuAbstractPackage::changed, this, &McuSupportOptions::changed); + connect(package, &McuAbstractPackage::changed, this, &McuSupportOptions::packagesChanged); - emit changed(); + emit packagesChanged(); } FilePath McuSupportOptions::qulDirFromSettings() @@ -647,7 +647,7 @@ static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePat if (!cMakeToolchainFile.exists()) { printMessage(McuTarget::tr( "Warning for target %1: missing CMake toolchain file expected at %2.") - .arg(McuSupportOptions::kitName(mcuTarget), + .arg(McuKitManager::kitName(mcuTarget), cMakeToolchainFile.toUserOutput()), false); } @@ -657,7 +657,7 @@ static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePat config.append(CMakeConfigItem("QUL_GENERATORS", generatorsPath.toString().toUtf8())); if (!generatorsPath.exists()) { printMessage(McuTarget::tr("Warning for target %1: missing QulGenerators expected at %2.") - .arg(McuSupportOptions::kitName(mcuTarget), generatorsPath.toUserOutput()), + .arg(McuKitManager::kitName(mcuTarget), generatorsPath.toUserOutput()), false); } @@ -687,7 +687,7 @@ static void setKitQtVersionOptions(Kit *k) // else: auto-select a Qt version } -QString McuSupportOptions::kitName(const McuTarget *mcuTarget) +QString McuKitManager::kitName(const McuTarget *mcuTarget) { const McuToolChainPackage *tcPkg = mcuTarget->toolChainPackage(); const QString compilerName = tcPkg && !tcPkg->isDesktopToolchain() @@ -708,7 +708,7 @@ QString McuSupportOptions::kitName(const McuTarget *mcuTarget) compilerName); } -QList McuSupportOptions::existingKits(const McuTarget *mcuTarget) +QList McuKitManager::existingKits(const McuTarget *mcuTarget) { using namespace Constants; return Utils::filtered(KitManager::kits(), [mcuTarget](Kit *kit) { @@ -724,23 +724,23 @@ QList McuSupportOptions::existingKits(const McuTarget *mcuTarget) }); } -QList McuSupportOptions::matchingKits(const McuTarget *mcuTarget, +QList McuKitManager::matchingKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage) { return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { - return kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); + return kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); }); } -QList McuSupportOptions::upgradeableKits(const McuTarget *mcuTarget, +QList McuKitManager::upgradeableKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage) { return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { - return !kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); + return !kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); }); } -QList McuSupportOptions::kitsWithMismatchedDependencies(const McuTarget *mcuTarget) +QList McuKitManager::kitsWithMismatchedDependencies(const McuTarget *mcuTarget) { return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) { const auto environment = Utils::NameValueDictionary( @@ -754,7 +754,7 @@ QList McuSupportOptions::kitsWithMismatchedDependencies(const McuTarget * }); } -QList McuSupportOptions::outdatedKits() +QList McuKitManager::outdatedKits() { return Utils::filtered(KitManager::kits(), [](Kit *kit) { return !kit->value(Constants::KIT_MCUTARGET_VENDOR_KEY).isNull() @@ -762,13 +762,13 @@ QList McuSupportOptions::outdatedKits() }); } -void McuSupportOptions::removeOutdatedKits() +void McuKitManager::removeOutdatedKits() { - for (auto kit : McuSupportOptions::outdatedKits()) + for (auto kit : outdatedKits()) KitManager::deregisterKit(kit); } -Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) +Kit *McuKitManager::newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) { const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) { KitGuard kitGuard(k); @@ -777,7 +777,7 @@ Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuAbstractPack setKitDevice(k, mcuTarget); setKitToolchains(k, mcuTarget->toolChainPackage()); setKitDebugger(k, mcuTarget->toolChainPackage()); - setKitEnvironment(k, mcuTarget, qtForMCUsSdk); + McuSupportOptions::setKitEnvironment(k, mcuTarget, qtForMCUsSdk); setKitDependencies(k, mcuTarget, qtForMCUsSdk); setKitCMakeOptions(k, mcuTarget, qtForMCUsSdk->path()); setKitQtVersionOptions(k); @@ -799,7 +799,7 @@ void printMessage(const QString &message, bool important) Core::MessageManager::writeSilently(displayMessage); } -QVersionNumber McuSupportOptions::kitQulVersion(const Kit *kit) +QVersionNumber McuKitManager::kitQulVersion(const Kit *kit) { return QVersionNumber::fromString( kit->value(McuSupport::Constants::KIT_MCUTARGET_SDKVERSION_KEY).toString()); @@ -814,9 +814,9 @@ static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) return FilePath(); } -bool McuSupportOptions::kitUpToDate(const Kit *kit, - const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage) +bool McuKitManager::kitIsUpToDate(const Kit *kit, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) { return kitQulVersion(kit) == mcuTarget->qulVersion() && kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput() @@ -828,7 +828,7 @@ void McuSupportOptions::deletePackagesAndTargets() sdkRepository.deletePackagesAndTargets(); } -McuSupportOptions::UpgradeOption McuSupportOptions::askForKitUpgrades() +McuKitManager::UpgradeOption McuKitManager::askForKitUpgrades() { QMessageBox upgradePopup(Core::ICore::dialogParent()); upgradePopup.setStandardButtons(QMessageBox::Cancel); @@ -841,15 +841,15 @@ McuSupportOptions::UpgradeOption McuSupportOptions::askForKitUpgrades() upgradePopup.exec(); if (upgradePopup.clickedButton() == keepButton) - return Keep; + return UpgradeOption::Keep; if (upgradePopup.clickedButton() == replaceButton) - return Replace; + return UpgradeOption::Replace; - return Ignore; + return UpgradeOption::Ignore; } -void McuSupportOptions::createAutomaticKits() +void McuKitManager::createAutomaticKits() { auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); @@ -929,15 +929,15 @@ void McuSupportOptions::checkUpgradeableKits() return; if (Utils::anyOf(sdkRepository.mcuTargets, [this](const McuTarget *target) { - return !upgradeableKits(target, this->qtForMCUsSdkPackage).empty() - && matchingKits(target, this->qtForMCUsSdkPackage).empty(); + return !McuKitManager::upgradeableKits(target, this->qtForMCUsSdkPackage).empty() + && McuKitManager::matchingKits(target, this->qtForMCUsSdkPackage).empty(); })) - upgradeKits(askForKitUpgrades()); + McuKitManager::upgradeKitsByCreatingNewPackage(McuKitManager::askForKitUpgrades()); } -void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption) +void McuKitManager::upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption) { - if (upgradeOption == Ignore) + if (upgradeOption == UpgradeOption::Ignore) return; auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); @@ -947,15 +947,16 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption) Sdk::targetsAndPackages(dir, &repo); for (const auto &target : qAsConst(repo.mcuTargets)) { - if (!matchingKits(target, qtForMCUsPackage).empty()) + if (!McuKitManager::matchingKits(target, qtForMCUsPackage).empty()) // already up-to-date continue; - const auto kits = upgradeableKits(target, qtForMCUsPackage); + const auto kits = McuKitManager::upgradeableKits(target, qtForMCUsPackage); if (!kits.empty()) { - if (upgradeOption == Replace) + if (upgradeOption == UpgradeOption::Replace) { for (auto existingKit : kits) KitManager::deregisterKit(existingKit); + } if (target->isValid()) newKit(target, qtForMCUsPackage); @@ -967,16 +968,16 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption) delete qtForMCUsPackage; } -void McuSupportOptions::upgradeKitInPlace(ProjectExplorer::Kit *kit, +void McuKitManager::upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) { setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path()); - setKitEnvironment(kit, mcuTarget, qtForMCUsSdk); + McuSupportOptions::setKitEnvironment(kit, mcuTarget, qtForMCUsSdk); setKitDependencies(kit, mcuTarget, qtForMCUsSdk); } -void McuSupportOptions::fixKitsDependencies() +void McuKitManager::fixKitsDependencies() { auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); @@ -986,7 +987,7 @@ void McuSupportOptions::fixKitsDependencies() for (const auto &target : qAsConst(repo.mcuTargets)) { if (target->isValid()) { for (auto *kit : kitsWithMismatchedDependencies(target)) { - updateKitEnvironment(kit, target); + McuSupportOptions::updateKitEnvironment(kit, target); } } } @@ -998,7 +999,7 @@ void McuSupportOptions::fixKitsDependencies() /** * @brief Fix/update existing kits if needed */ -void McuSupportOptions::fixExistingKits() +void McuKitManager::fixExistingKits() { for (Kit *kit : KitManager::kits()) { if (!kit->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY)) diff --git a/src/plugins/mcusupport/mcusupportoptions.h b/src/plugins/mcusupport/mcusupportoptions.h index 20e046384d7..61be8a8df6c 100644 --- a/src/plugins/mcusupport/mcusupportoptions.h +++ b/src/plugins/mcusupport/mcusupportoptions.h @@ -26,6 +26,9 @@ #pragma once #include +#include "mcusupport_global.h" + +#include #include #include #include @@ -106,8 +109,6 @@ class McuSupportOptions : public QObject Q_OBJECT public: - enum UpgradeOption { Ignore, Keep, Replace }; - explicit McuSupportOptions(QObject *parent = nullptr); ~McuSupportOptions() override; @@ -122,43 +123,60 @@ public: static void remapQul2xCmakeVars(ProjectExplorer::Kit *, const Utils::EnvironmentItems &); static Utils::FilePath qulDirFromSettings(); - static QString kitName(const McuTarget *mcuTarget); + static void registerQchFiles(); + static void registerExamples(); + static const QVersionNumber &minimalQulVersion(); + + void checkUpgradeableKits(); + void populatePackagesAndTargets(); +private: + void deletePackagesAndTargets(); + +signals: + void packagesChanged(); +}; + +class McuKitManager +{ + Q_DECLARE_TR_FUNCTIONS(McuSupport::Internal::McuKitManager) + +public: + enum class UpgradeOption { + Ignore, + Keep, + Replace + }; + + // Creating kits: + static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); + static void createAutomaticKits(); + + // Querying the kits: static QList existingKits(const McuTarget *mcuTarget); static QList matchingKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); static QList upgradeableKits( const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); static QList kitsWithMismatchedDependencies(const McuTarget *mcuTarget); + + // Upgrading kits: + static UpgradeOption askForKitUpgrades(); + static void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption); + static void upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); + + // Fixing kits: + static void fixKitsDependencies(); + static void fixExistingKits(); + + // Outdated kits: static QList outdatedKits(); static void removeOutdatedKits(); - static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdk); - static void createAutomaticKits(); - static UpgradeOption askForKitUpgrades(); - static void upgradeKits(UpgradeOption upgradeOption); - static void upgradeKitInPlace(ProjectExplorer::Kit *kit, - const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdk); - static void fixKitsDependencies(); - void checkUpgradeableKits(); - static void fixExistingKits(); - void populatePackagesAndTargets(); - static void registerQchFiles(); - static void registerExamples(); - - static const QVersionNumber &minimalQulVersion(); + // Querying kits: + static QString kitName(const McuTarget* mcuTarget); static QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit); - static bool kitUpToDate(const ProjectExplorer::Kit *kit, - const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage); - -private: - void deletePackagesAndTargets(); - -signals: - void changed(); + static bool kitIsUpToDate(const ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); }; } // namespace Internal diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp index 243caaff1ed..81fd58080e3 100644 --- a/src/plugins/mcusupport/mcusupportoptionspage.cpp +++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp @@ -160,16 +160,15 @@ McuSupportOptionsWidget::McuSupportOptionsWidget() m_kitCreationPushButton = new QPushButton(tr("Create Kit")); m_kitCreationPushButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); connect(m_kitCreationPushButton, &QPushButton::clicked, this, [this] { - McuSupportOptions::newKit(currentMcuTarget(), m_options.qtForMCUsSdkPackage); + McuKitManager::newKit(currentMcuTarget(), m_options.qtForMCUsSdkPackage); McuSupportOptions::registerQchFiles(); updateStatus(); }); m_kitUpdatePushButton = new QPushButton(tr("Update Kit")); m_kitUpdatePushButton->setSizePolicy(m_kitCreationPushButton->sizePolicy()); connect(m_kitUpdatePushButton, &QPushButton::clicked, this, [this] { - for (auto kit : McuSupportOptions::upgradeableKits(currentMcuTarget(), - m_options.qtForMCUsSdkPackage)) - m_options.upgradeKitInPlace(kit, currentMcuTarget(), m_options.qtForMCUsSdkPackage); + for (auto kit: McuKitManager::upgradeableKits(currentMcuTarget(), m_options.qtForMCUsSdkPackage)) + McuKitManager::upgradeKitInPlace(kit, currentMcuTarget(), m_options.qtForMCUsSdkPackage); updateStatus(); }); vLayout->addWidget(m_kitCreationPushButton); @@ -178,7 +177,10 @@ McuSupportOptionsWidget::McuSupportOptionsWidget() mainLayout->addStretch(); - connect(&m_options, &McuSupportOptions::changed, this, &McuSupportOptionsWidget::updateStatus); + connect(&m_options, + &McuSupportOptions::packagesChanged, + this, + &McuSupportOptionsWidget::updateStatus); showMcuTargetPackages(); } @@ -216,13 +218,11 @@ void McuSupportOptionsWidget::updateStatus() m_kitCreationPushButton->setVisible(mcuTargetValid); m_kitUpdatePushButton->setVisible(mcuTargetValid); if (mcuTargetValid) { - const bool hasMatchingKits - = !McuSupportOptions::matchingKits(mcuTarget, m_options.qtForMCUsSdkPackage) - .isEmpty(); - const bool hasUpgradeableKits - = !hasMatchingKits - && !McuSupportOptions::upgradeableKits(mcuTarget, m_options.qtForMCUsSdkPackage) - .isEmpty(); + const bool hasMatchingKits = !McuKitManager::matchingKits( + mcuTarget, m_options.qtForMCUsSdkPackage).isEmpty(); + const bool hasUpgradeableKits = !hasMatchingKits && + !McuKitManager::upgradeableKits( + mcuTarget, m_options.qtForMCUsSdkPackage).isEmpty(); m_kitCreationPushButton->setEnabled(!hasMatchingKits); m_kitUpdatePushButton->setEnabled(hasUpgradeableKits); @@ -305,7 +305,7 @@ void McuSupportOptionsWidget::apply() if (pathsChanged) { m_options.checkUpgradeableKits(); - m_options.fixKitsDependencies(); + McuKitManager::fixKitsDependencies(); } } @@ -314,8 +314,9 @@ void McuSupportOptionsWidget::populateMcuTargetsComboBox() m_options.populatePackagesAndTargets(); m_mcuTargetsComboBox->clear(); m_mcuTargetsComboBox->addItems( - Utils::transform(m_options.sdkRepository.mcuTargets, - [](McuTarget *t) { return McuSupportOptions::kitName(t); })); + Utils::transform(m_options.sdkRepository.mcuTargets, [](McuTarget *t) { + return McuKitManager::kitName(t); + })); updateStatus(); } diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp index 6e0d2d20b2f..75cc6b78921 100644 --- a/src/plugins/mcusupport/mcusupportplugin.cpp +++ b/src/plugins/mcusupport/mcusupportplugin.cpp @@ -93,9 +93,9 @@ void McuSupportPlugin::extensionsInitialized() ProjectExplorer::DeviceManager::instance()->addDevice(McuSupportDevice::create()); connect(KitManager::instance(), &KitManager::kitsLoaded, []() { - McuSupportOptions::removeOutdatedKits(); - McuSupportOptions::createAutomaticKits(); - McuSupportOptions::fixExistingKits(); + McuKitManager::removeOutdatedKits(); + McuKitManager::createAutomaticKits(); + McuKitManager::fixExistingKits(); McuSupportPlugin::askUserAboutMcuSupportKitsSetup(); }); } @@ -106,7 +106,7 @@ void McuSupportPlugin::askUserAboutMcuSupportKitsSetup() if (!ICore::infoBar()->canInfoBeAdded(setupMcuSupportKits) || McuSupportOptions::qulDirFromSettings().isEmpty() - || !McuSupportOptions::existingKits(nullptr).isEmpty()) + || !McuKitManager::existingKits(nullptr).isEmpty()) return; Utils::InfoBarEntry info(setupMcuSupportKits, @@ -130,18 +130,19 @@ void McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade() Utils::InfoBarEntry info(upgradeMcuSupportKits, tr("New version of Qt for MCUs detected. Upgrade existing Kits?"), Utils::InfoBarEntry::GlobalSuppression::Enabled); + static McuKitManager::UpgradeOption selectedOption = McuKitManager::UpgradeOption::Keep; - static McuSupportOptions::UpgradeOption selectedOption; - const QStringList options = {tr("Create new kits"), tr("Replace existing kits")}; - selectedOption = McuSupportOptions::UpgradeOption::Keep; + const QStringList options = { tr("Create new kits"), tr("Replace existing kits") }; info.setComboInfo(options, [options](const QString &selected) { - selectedOption = options.indexOf(selected) == 0 ? McuSupportOptions::UpgradeOption::Keep - : McuSupportOptions::UpgradeOption::Replace; + selectedOption = options.indexOf(selected) == 0 ? McuKitManager::UpgradeOption::Keep + : McuKitManager::UpgradeOption::Replace; }); info.addCustomButton(tr("Proceed"), [upgradeMcuSupportKits] { ICore::infoBar()->removeInfo(upgradeMcuSupportKits); - QTimer::singleShot(0, []() { McuSupportOptions::upgradeKits(selectedOption); }); + QTimer::singleShot(0, []() { + McuKitManager::upgradeKitsByCreatingNewPackage(selectedOption); + }); }); ICore::infoBar()->addInfo(info); diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index a3a041dfd76..9911fcbf50c 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -791,7 +791,7 @@ void targetsAndPackages(const Utils::FilePath &dir, McuSdkRepository *repo) std::sort(repo->mcuTargets.begin(), repo->mcuTargets.end(), [](const McuTarget *lhs, const McuTarget *rhs) { - return McuSupportOptions::kitName(lhs) < McuSupportOptions::kitName(rhs); + return McuKitManager::kitName(lhs) < McuKitManager::kitName(rhs); }); } diff --git a/src/plugins/mcusupport/test/unittest.cpp b/src/plugins/mcusupport/test/unittest.cpp index 57671caaf41..c5de1a208fb 100644 --- a/src/plugins/mcusupport/test/unittest.cpp +++ b/src/plugins/mcusupport/test/unittest.cpp @@ -65,7 +65,7 @@ void McuSupportTest::test_addNewKit() QSignalSpy kitAddedSpy(&kitManager, &KitManager::kitAdded); - auto *newKit{McuSupportOptions::newKit(&mcuTarget, &freeRtosPackage)}; + auto *newKit{McuKitManager::newKit(&mcuTarget, &freeRtosPackage)}; QVERIFY(newKit != nullptr); QCOMPARE(kitAddedSpy.count(), 1); From c8481710c9c9c8493d7ce0d61db8a5e1869e2540 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Mon, 14 Feb 2022 18:13:06 +0200 Subject: [PATCH 18/76] QmlDesigner: Enable searching in the text editor Also hide the bottom status bar when it is empty. Task-number: QDS-6187 Change-Id: I053771243c268ea20df8e127831b789b854021aa Reviewed-by: Thomas Hartmann --- .../components/texteditor/texteditorview.cpp | 18 +++----- .../texteditor/texteditorwidget.cpp | 45 +++++++++++-------- .../components/texteditor/texteditorwidget.h | 10 ++++- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp index e3a870f9801..7add0cd8e26 100644 --- a/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp +++ b/src/plugins/qmldesigner/components/texteditor/texteditorview.cpp @@ -81,7 +81,7 @@ TextEditorView::TextEditorView(QObject *parent) Core::Command *command = Core::ActionManager::registerAction(completionAction, TextEditor::Constants::COMPLETE_THIS, context); command->setDefaultKeySequence(QKeySequence(Core::useMacShortcuts ? tr("Meta+Space") : tr("Ctrl+Space"))); - connect(completionAction, &QAction::triggered, [this]() { + connect(completionAction, &QAction::triggered, this, [this] { if (m_widget->textEditor()) m_widget->textEditor()->editorWidget()->invokeAssist(TextEditor::Completion); }); @@ -99,16 +99,12 @@ void TextEditorView::modelAttached(Model *model) AbstractView::modelAttached(model); - auto textEditor = qobject_cast( + auto textEditor = qobject_cast( QmlDesignerPlugin::instance()->currentDesignDocument()->textEditor()->duplicate()); + // Set the context of the text editor, but we add another special context to override shortcuts. Core::Context context = textEditor->context(); context.prepend(TEXTEDITOR_CONTEXT_ID); - - /* - * Set the context of the text editor, but we add another special context to override shortcuts. - */ - m_textEditorContext->setContext(context); m_widget->setTextEditor(textEditor); @@ -272,10 +268,9 @@ void TextEditorView::reformatFile() auto document = qobject_cast(Core::EditorManager::currentDocument()); - /* Reformat document if we have a .ui.qml file */ - if (document - && document->filePath().toString().endsWith(".ui.qml") - && DesignerSettings::getValue(DesignerSettingsKey::REFORMAT_UI_QML_FILES).toBool()) { + // Reformat document if we have a .ui.qml file + if (document && document->filePath().toString().endsWith(".ui.qml") + && DesignerSettings::getValue(DesignerSettingsKey::REFORMAT_UI_QML_FILES).toBool()) { QmlJS::Document::Ptr currentDocument(document->semanticInfo().document); QmlJS::Snapshot snapshot = QmlJS::ModelManagerInterface::instance()->snapshot(); @@ -315,4 +310,3 @@ void TextEditorView::instancePropertyChanged(const QList #include - +#include #include #include @@ -52,13 +52,17 @@ TextEditorWidget::TextEditorWidget(TextEditorView *textEditorView) : QWidget() , m_textEditorView(textEditorView) , m_statusBar(new TextEditorStatusBar(this)) + , m_findToolBar(new Core::FindToolBarPlaceHolder(this)) + , m_layout(new QVBoxLayout(this)) { setAcceptDrops(true); - QBoxLayout *layout = new QVBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - layout->addWidget(m_statusBar); + m_statusBar->hide(); + + m_layout->setContentsMargins(0, 0, 0, 0); + m_layout->setSpacing(0); + m_layout->addWidget(m_statusBar); + m_layout->addWidget(m_findToolBar); m_updateSelectionTimer.setSingleShot(true); m_updateSelectionTimer.setInterval(200); @@ -72,24 +76,22 @@ void TextEditorWidget::setTextEditor(TextEditor::BaseTextEditor *textEditor) m_textEditor.reset(textEditor); if (textEditor) { - layout()->removeWidget(m_statusBar); - layout()->addWidget(textEditor->editorWidget()); - layout()->addWidget(m_statusBar); + m_layout->insertWidget(0, textEditor->editorWidget()); + setFocusProxy(textEditor->editorWidget()); QmlDesignerPlugin::instance()->emitCurrentTextEditorChanged(textEditor); - connect(textEditor->editorWidget(), &QPlainTextEdit::cursorPositionChanged, - this, [this]() { - /* Cursor position is changed by rewriter */ + connect(textEditor->editorWidget(), &QPlainTextEdit::cursorPositionChanged, this, [this] { + // Cursor position is changed by rewriter if (!m_blockCursorSelectionSynchronisation) m_updateSelectionTimer.start(); }); textEditor->editorWidget()->installEventFilter(this); + static QString styleSheet = Theme::replaceCssColors( - QString::fromUtf8(Utils::FileReader::fetchQrc( - ":/qmldesigner/scrollbar.css"))); + QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css"))); textEditor->editorWidget()->verticalScrollBar()->setStyleSheet(styleSheet); textEditor->editorWidget()->horizontalScrollBar()->setStyleSheet(styleSheet); } @@ -105,7 +107,6 @@ void TextEditorWidget::contextHelp(const Core::IContext::HelpCallback &callback) void TextEditorWidget::updateSelectionByCursorPosition() { - /* Because of the timer we have to be careful. */ if (!m_textEditorView->model()) return; @@ -162,11 +163,13 @@ void TextEditorWidget::gotoCursorPosition(int line, int column) void TextEditorWidget::setStatusText(const QString &text) { m_statusBar->setText(text); + m_statusBar->setVisible(!text.isEmpty()); } void TextEditorWidget::clearStatusBar() { m_statusBar->clearText(); + m_statusBar->hide(); } int TextEditorWidget::currentLine() const @@ -199,21 +202,25 @@ bool TextEditorWidget::eventFilter(QObject *, QEvent *event) auto keyEvent = static_cast(event); if (std::find(overrideKeys.begin(), overrideKeys.end(), keyEvent->key()) != overrideKeys.end()) { + if (keyEvent->key() == Qt::Key_Escape) + m_findToolBar->hide(); + keyEvent->accept(); return true; } static const Qt::KeyboardModifiers relevantModifiers = Qt::ShiftModifier - | Qt::ControlModifier - | Qt::AltModifier - | Qt::MetaModifier; + | Qt::ControlModifier + | Qt::AltModifier + | Qt::MetaModifier; - QKeySequence keySqeuence(keyEvent->key() | (keyEvent->modifiers() & relevantModifiers)); - for (const QKeySequence &overrideSequence : overrideSequences) + const QKeySequence keySqeuence(keyEvent->key() | (keyEvent->modifiers() & relevantModifiers)); + for (const QKeySequence &overrideSequence : overrideSequences) { if (keySqeuence.matches(overrideSequence)) { keyEvent->accept(); return true; } + } } return false; } diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h index 96a8361069f..efd51d8afc2 100644 --- a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h +++ b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.h @@ -26,11 +26,15 @@ #include -#include #include +#include +#include #include +namespace Core { +class FindToolBarPlaceHolder; +} namespace QmlDesigner { class TextEditorView; @@ -72,7 +76,9 @@ private: std::unique_ptr m_textEditor; QPointer m_textEditorView; QTimer m_updateSelectionTimer; - TextEditorStatusBar *m_statusBar; + TextEditorStatusBar *m_statusBar = nullptr; + Core::FindToolBarPlaceHolder *m_findToolBar = nullptr; + QVBoxLayout *m_layout = nullptr; bool m_blockCursorSelectionSynchronisation = false; bool m_blockRoundTrip = false; }; From 0d319ac3a1b558fab759ede8dc2178ccdb3502ea Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 11 Feb 2022 17:34:27 +0100 Subject: [PATCH 19/76] QmlDesigner: Fix loading of .metainfo for versioned folders This fixes a regression introduced by 7ea6492a17736e079ddf192b18d061076dfbf9c7. Since we actually check if import folders exist, we did not take versioned folders into account. e.g. 'MyPlugin.1' Extended and cleaned up the manual test case. Task-number: QDS-6078 Change-Id: I3235d8fe498745903c5ca897e25e3d43222c119f Reviewed-by: Miikka Heikkinen --- .../metainfo/subcomponentmanager.cpp | 46 +++++++--- .../imports/MyPlugin2.1/MyComponent.qml | 38 +++++++++ .../imports/MyPlugin2.1/MyComponent2.qml | 43 ++++++++++ .../designer/MyComponentSpecifics.qml | 84 +++++++++++++++++++ .../MyPlugin2.1/designer/MyPlugin.metainfo | 44 ++++++++++ .../plugins/imports/MyPlugin2.1/qmldir | 2 + .../qml/testprojects/plugins/plugins.qml | 15 ++-- .../qml/testprojects/plugins/plugins2.qml | 38 +++++++++ 8 files changed, 291 insertions(+), 19 deletions(-) create mode 100644 tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/MyComponent.qml create mode 100644 tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/MyComponent2.qml create mode 100644 tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/designer/MyComponentSpecifics.qml create mode 100644 tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/designer/MyPlugin.metainfo create mode 100644 tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/qmldir create mode 100644 tests/manual/qml/testprojects/plugins/plugins2.qml diff --git a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp index a001a8b0c29..9ff3289e459 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/subcomponentmanager.cpp @@ -69,10 +69,38 @@ SubComponentManager::SubComponentManager(Model *model, QObject *parent) this, [this](const QString &path) { parseDirectory(path); }); } +QString findFolderForImport(const QStringList &importPaths, const QString &url) +{ + if (url.isEmpty()) + return {}; + + QString folderUrl = url; + folderUrl.replace('.', '/'); + + for (const QString &path : importPaths) { + QFileInfo dirInfo = QFileInfo(path + QLatin1Char('/') + folderUrl); + + if (dirInfo.exists() && dirInfo.isDir()) + return dirInfo.canonicalFilePath(); + + const QDir parentDir = dirInfo.dir(); + if (parentDir.exists()) { + const QStringList parts = url.split('.'); + const QString lastFolder = parts.last(); + + const QStringList candidates = parentDir.entryList({lastFolder + ".*"}, QDir::Dirs); + if (!candidates.isEmpty()) + return parentDir.canonicalPath() + "/" + candidates.first(); + } + } + return {}; +} bool SubComponentManager::addImport(const Import &import, int index) { - if (debug) + if (debug) { qDebug() << Q_FUNC_INFO << index << import.file().toUtf8(); + qDebug() << Q_FUNC_INFO << index << import.url(); + } bool importExists = false; if (import.isFileImport()) { @@ -85,19 +113,11 @@ bool SubComponentManager::addImport(const Import &import, int index) } } else { QString url = import.url(); - - url.replace(QLatin1Char('.'), QLatin1Char('/')); - - foreach (const QString &path, importPaths()) { - QFileInfo dirInfo = QFileInfo(path + QLatin1Char('/') + url); - if (dirInfo.exists() && dirInfo.isDir()) { - const QString canonicalDirPath = dirInfo.canonicalFilePath(); - m_watcher.addPath(canonicalDirPath); - importExists = true; - //m_dirToQualifier.insertMulti(canonicalDirPath, import.qualifier()); ### todo: proper support for import as - } + const QString result = findFolderForImport(importPaths(), url); + if (!result.isEmpty()) { + m_watcher.addPath(result); + importExists = true; } - // TODO: QDeclarativeDomImport::Library } if (importExists) { diff --git a/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/MyComponent.qml b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/MyComponent.qml new file mode 100644 index 00000000000..e52e52d7d10 --- /dev/null +++ b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/MyComponent.qml @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +import QtQuick 2.0 + +Rectangle { + width: 60 + height: 60 + color: "green" + property alias text: textItem.text + + Text { + id: textItem + anchors.centerIn: parent + } +} diff --git a/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/MyComponent2.qml b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/MyComponent2.qml new file mode 100644 index 00000000000..5e2306a716f --- /dev/null +++ b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/MyComponent2.qml @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +import QtQuick 2.0 + +Item { + property alias text: textItem.text + property alias color: rect.color + property alias radius: rect.radius + + Rectangle { + id: rect + anchors.fill: parent + color: "green" + + Text { + id: textItem + anchors.centerIn: parent + } + } +} diff --git a/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/designer/MyComponentSpecifics.qml b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/designer/MyComponentSpecifics.qml new file mode 100644 index 00000000000..c6c888e369c --- /dev/null +++ b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/designer/MyComponentSpecifics.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +import QtQuick 2.0 +import HelperWidgets 2.0 +import QtQuick.Layouts 1.0 + +Column { + anchors.left: parent.left + anchors.right: parent.right + + Section { + anchors.left: parent.left + anchors.right: parent.right + caption: qsTr("Color") + + ColorEditor { + caption: qsTr("Color") + backendValue: backendValues.color + supportGradient: true + } + + + } + + Section { + anchors.left: parent.left + anchors.right: parent.right + caption: "Rectangle" + + SectionLayout { + rows: 2 + + Label { + text: qsTr("Text") + } + + SecondColumnLayout { + LineEdit { + backendValue: backendValues.text + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Radius") + } + SecondColumnLayout { + SpinBox { + backendValue: backendValues.radius + hasSlider: true + Layout.preferredWidth: 80 + minimumValue: 0 + maximumValue: Math.min(backendValues.height.value, backendValues.width.value) / 2 + } + ExpandingSpacer { + + } + } + } + } +} diff --git a/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/designer/MyPlugin.metainfo b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/designer/MyPlugin.metainfo new file mode 100644 index 00000000000..5eef250228c --- /dev/null +++ b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/designer/MyPlugin.metainfo @@ -0,0 +1,44 @@ +MetaInfo { + Type { + name: "MyPlugin2.MyComponent" + icon: ":/qtquickplugin/images/item-icon16.png" + + ItemLibraryEntry { + name: "My Component" + category: "My Test Plugin 2" + libraryIcon: ":/qtquickplugin/images/item-icon.png" + version: "1.0" + requiredImport: "MyPlugin2" + + Property { + name: "text" + type: "binding" + value: "qsTr(\"This is text\")" + } + } + } + + Type { + name: "MyPlugin2.MyComponent2" + icon: ":/qtquickplugin/images/item-icon16.png" + + ItemLibraryEntry { + name: "My Component 2" + category: "My Test Plugin 2" + libraryIcon: ":/qtquickplugin/images/item-icon.png" + version: "1.0" + requiredImport: "MyPlugin2" + + Property { + name: "text" + type: "binding" + value: "qsTr(\"This is text\")" + } + + Property { name: "width"; type: "int"; value: 200; } + Property { name: "height"; type: "int"; value: 200; } + Property { name: "color"; type: "QColor"; value: "red"; } + } + } + +} diff --git a/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/qmldir b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/qmldir new file mode 100644 index 00000000000..660f6d416b0 --- /dev/null +++ b/tests/manual/qml/testprojects/plugins/imports/MyPlugin2.1/qmldir @@ -0,0 +1,2 @@ +MyComponent 1.0 MyComponent.qml +MyComponent2 1.0 MyComponent2.qml diff --git a/tests/manual/qml/testprojects/plugins/plugins.qml b/tests/manual/qml/testprojects/plugins/plugins.qml index dc3d729077e..daf85ad3892 100644 --- a/tests/manual/qml/testprojects/plugins/plugins.qml +++ b/tests/manual/qml/testprojects/plugins/plugins.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -23,13 +23,10 @@ ** ****************************************************************************/ -import QtQuick 2.3 -import QtQuick.Controls 1.2 -import QtQuick.Window 2.2 +import QtQuick import MyPlugin 1.0 -ApplicationWindow { - title: qsTr("Hello World") +Rectangle { width: 640 height: 480 @@ -38,3 +35,9 @@ ApplicationWindow { } } + +/*##^## +Designer { + D{i:0;autoSize:true;height:480;width:640} +} +##^##*/ diff --git a/tests/manual/qml/testprojects/plugins/plugins2.qml b/tests/manual/qml/testprojects/plugins/plugins2.qml new file mode 100644 index 00000000000..9e586d56f85 --- /dev/null +++ b/tests/manual/qml/testprojects/plugins/plugins2.qml @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +import QtQuick 2.3 +import MyPlugin2 1.0 + +Rectangle { + + width: 640 + height: 480 + + MyComponent { + text: qsTr("Some Text") + + } +} From 1fa9034acaf6ace8f0e62186e145303642709459 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 16 Feb 2022 16:55:49 +0100 Subject: [PATCH 20/76] StudioWelcome: Avoid opening two projects on double click MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This issue was introdced because we do not go to the edit mode after opening a project. We stay in the WelcomeMode until the project is loaded. Since the recent project list did change a second click (aka double click) will open a second project. We now block the update of the model for 1000ms and also block opening another project for the same duration. Task-number: QDS-6286 Change-Id: I52ed6aa3686594b63fe4a6134c6db1287bca1dcb Reviewed-by: Qt CI Bot Reviewed-by: Henning Gründl --- src/plugins/studiowelcome/studiowelcomeplugin.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index c004b146691..0e4e1996fb6 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -224,9 +224,15 @@ public: Q_INVOKABLE void openProjectAt(int row) { + if (m_blockOpenRecent) + return; + + m_blockOpenRecent = true; const QString projectFile = data(index(row, 0), ProjectModel::FilePathRole).toString(); if (QFileInfo::exists(projectFile)) ProjectExplorer::ProjectExplorerPlugin::openProjectWelcomePage(projectFile); + + resetProjects(); } Q_INVOKABLE int get(int) { return -1; } @@ -311,6 +317,7 @@ private: bool m_communityVersion = true; bool m_enterpriseVersion = false; + bool m_blockOpenRecent = false; }; void ProjectModel::setupVersion() @@ -520,8 +527,11 @@ QHash ProjectModel::roleNames() const void ProjectModel::resetProjects() { - beginResetModel(); - endResetModel(); + QTimer::singleShot(2000, this, [this]() { + beginResetModel(); + endResetModel(); + m_blockOpenRecent = false; + }); } class WelcomeMode : public Core::IMode From d0852fb2a14a941d5f83d986fff891cd129d840f Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Wed, 16 Feb 2022 12:12:50 +0100 Subject: [PATCH 21/76] StudioWelcome: Remove unused code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I380a35cb735669feeeac5d0293ed43c4d2ef7059 Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Henning Gründl --- src/plugins/studiowelcome/examplecheckout.cpp | 66 ------------------- src/plugins/studiowelcome/examplecheckout.h | 29 +------- .../studiowelcome/studiowelcomeplugin.cpp | 25 ------- 3 files changed, 1 insertion(+), 119 deletions(-) diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp index b094fd2f08a..377d0f4cb7f 100644 --- a/src/plugins/studiowelcome/examplecheckout.cpp +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -47,11 +47,8 @@ using namespace Utils; -ExampleCheckout::ExampleCheckout(QObject *) {} - void ExampleCheckout::registerTypes() { - FileDownloader::registerQmlType(); static bool once = []() { FileDownloader::registerQmlType(); FileExtractor::registerQmlType(); @@ -61,69 +58,6 @@ void ExampleCheckout::registerTypes() QTC_ASSERT(once, ;); } -void ExampleCheckout::checkoutExample(const QUrl &url, const QString &tempFile, const QString &completeBaseFileName) -{ - registerTypes(); - - m_dialog.reset(new QDialog(Core::ICore::dialogParent())); - m_dialog->setModal(true); - m_dialog->setFixedSize(620, 300); - QHBoxLayout *layout = new QHBoxLayout(m_dialog.get()); - layout->setContentsMargins(2, 2, 2, 2); - - auto widget = new QQuickWidget(m_dialog.get()); - - layout->addWidget(widget); - widget->engine()->addImportPath("qrc:/studiofonts"); - - widget->engine()->addImportPath( - Core::ICore::resourcePath("/qmldesigner/propertyEditorQmlSources/imports").toString()); - - widget->setSource(QUrl("qrc:/qml/downloaddialog/main.qml")); - - m_dialog->setWindowFlag(Qt::Tool, true); - widget->setResizeMode(QQuickWidget::SizeRootObjectToView); - - rootObject = widget->rootObject(); - - QTC_ASSERT(rootObject, qWarning() << "QML error"; return ); - - rootObject->setProperty("url", url); - rootObject->setProperty("tempFile", tempFile); - rootObject->setProperty("completeBaseName", completeBaseFileName); - - m_dialog->show(); - - rootObject = widget->rootObject(); - - connect(rootObject, SIGNAL(canceled()), this, SLOT(handleCancel())); - connect(rootObject, SIGNAL(accepted()), this, SLOT(handleAccepted())); -} - -QString ExampleCheckout::extractionFolder() const -{ - return m_extrationFolder; -} - -ExampleCheckout::~ExampleCheckout() {} - -void ExampleCheckout::handleCancel() -{ - m_dialog->close(); - m_dialog.release()->deleteLater(); - deleteLater(); -} - -void ExampleCheckout::handleAccepted() -{ - QQmlProperty property(rootObject, "path"); - m_extrationFolder = property.read().toString(); - m_dialog->close(); - emit finishedSucessfully(); - m_dialog.release()->deleteLater(); - deleteLater(); -} - void FileDownloader::registerQmlType() { qmlRegisterType("ExampleCheckout", 1, 0, "FileDownloader"); diff --git a/src/plugins/studiowelcome/examplecheckout.h b/src/plugins/studiowelcome/examplecheckout.h index 4e256994377..af2be4893ec 100644 --- a/src/plugins/studiowelcome/examplecheckout.h +++ b/src/plugins/studiowelcome/examplecheckout.h @@ -33,36 +33,9 @@ #include -QT_BEGIN_NAMESPACE -class QDialog; -QT_END_NAMESPACE - -class ExampleCheckout : public QObject +struct ExampleCheckout { - Q_OBJECT -public: - explicit ExampleCheckout(QObject *parent = nullptr); - - Q_INVOKABLE void checkoutExample(const QUrl &url, const QString &tempFile, const QString &completeBaseFileName); - - QString extractionFolder() const; - - ~ExampleCheckout(); - static void registerTypes(); - -public slots: - void handleCancel(); - void handleAccepted(); - -signals: - void finishedSucessfully(); - void progressChanged(int); - -private: - std::unique_ptr m_dialog; - QObject *rootObject = nullptr; - QString m_extrationFolder; }; class FileExtractor : public QObject diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index 0e4e1996fb6..9b20e013162 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -271,31 +271,6 @@ public: const QString &tempFile, const QString &completeBaseName) { - if (!url.isEmpty()) { - ExampleCheckout *checkout = new ExampleCheckout; - checkout->checkoutExample(QUrl::fromUserInput(url), tempFile, completeBaseName); - connect(checkout, - &ExampleCheckout::finishedSucessfully, - this, - [checkout, formFile, example, explicitQmlproject]() { - const QString exampleFolder = checkout->extractionFolder() + "/" + example - + "/"; - - QString projectFile = exampleFolder + example + ".qmlproject"; - - if (!explicitQmlproject.isEmpty()) - projectFile = exampleFolder + explicitQmlproject; - - ProjectExplorer::ProjectExplorerPlugin::openProjectWelcomePage(projectFile); - - const QString qmlFile = QFileInfo(projectFile).dir().absolutePath() + "/" - + formFile; - - Core::EditorManager::openEditor(Utils::FilePath::fromString(qmlFile)); - }); - return; - } - const Utils::FilePath projectFile = Core::ICore::resourcePath("examples") / example / example + ".qmlproject"; ProjectExplorer::ProjectExplorerPlugin::openProjectWelcomePage(projectFile.toString()); From 1a90f06fe5fa400331556bb4bb8a75890cdd3e04 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 17:09:37 +0100 Subject: [PATCH 22/76] QML Designer: Fix UI text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix capitalization of strings and the wording of tooltips. Task-number: QTCREATORBUG-27055 Change-Id: Id8e324b44574b9cf0d1522ae204b452cea6193cd Reviewed-by: Thomas Hartmann Reviewed-by: Henning Gründl --- .../qmldesigner/itemLibraryQmlSources/Assets.qml | 16 ++++++++-------- .../QtMultimedia/MediaPlayerSection.qml | 8 ++++---- .../QtQuick/Controls/AbstractButtonSection.qml | 4 ++-- .../QtQuick/LoaderSpecifics.qml | 10 +++++----- .../imports/HelperWidgets/ComponentSection.qml | 4 ++-- .../assetexporterplugin/assetexporter.cpp | 4 ++-- .../components/edit3d/edit3dwidget.cpp | 2 +- .../components/navigator/navigatortreemodel.cpp | 2 +- .../transitioneditor/transitioneditorview.cpp | 2 +- src/plugins/qmldesigner/qmldesignerplugin.cpp | 4 ++-- .../qmlprojectmanager/qmlmultilanguageaspect.cpp | 3 +-- 11 files changed, 29 insertions(+), 30 deletions(-) diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml index 872afff1ac8..de2ded3c9d7 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml @@ -167,7 +167,7 @@ Item { Dialog { id: renameFolderDialog - title: qsTr("Rename folder") + title: qsTr("Rename Folder") anchors.centerIn: parent closePolicy: Popup.CloseOnEscape implicitWidth: 280 @@ -192,13 +192,13 @@ Item { } Text { - text: qsTr("Folder Name cannot be empty.") + text: qsTr("Folder name cannot be empty.") color: "#ff0000" visible: folderRename.text === "" && !renameFolderDialog.renameError } Text { - text: qsTr("Could not rename directory. Make sure no folder with the same name exists.") + text: qsTr("Could not rename folder. Make sure no folder with the same name exists.") wrapMode: Text.WordWrap width: renameFolderDialog.width color: "#ff0000" @@ -259,7 +259,7 @@ Item { Dialog { id: newFolderDialog - title: qsTr("Create new folder") + title: qsTr("Create New Folder") anchors.centerIn: parent closePolicy: Popup.CloseOnEscape modal: true @@ -269,7 +269,7 @@ Item { Row { Text { - text: qsTr("Folder Name: ") + text: qsTr("Folder name: ") anchors.verticalCenter: parent.verticalCenter color: StudioTheme.Values.themeTextColor } @@ -287,7 +287,7 @@ Item { } Text { - text: qsTr("Folder Name cannot be empty.") + text: qsTr("Folder name cannot be empty.") color: "#ff0000" anchors.right: parent.right visible: folderName.text === "" @@ -329,7 +329,7 @@ Item { Dialog { id: confirmDeleteFolderDialog - title: qsTr("Folder not empty") + title: qsTr("Folder Not Empty") anchors.centerIn: parent closePolicy: Popup.CloseOnEscape implicitWidth: 300 @@ -342,7 +342,7 @@ Item { Text { id: folderNotEmpty - text: qsTr("Folder '%1' is not empty. Are you sure you want to delete it?") + text: qsTr("Folder \"%1\" is not empty. Delete it anyway?") .arg(contextDir ? contextDir.dirName : "") color: StudioTheme.Values.themeTextColor wrapMode: Text.WordWrap diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSection.qml index 2e58189a4dd..e71d67f6295 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtMultimedia/MediaPlayerSection.qml @@ -59,8 +59,8 @@ Section { PropertyLabel { visible: root.showAudioOutput - text: qsTr("Audio Output") - tooltip: qsTr("Holds the target audio output.") + text: qsTr("Audio output") + tooltip: qsTr("Target audio output.") } SecondColumnLayout { @@ -80,8 +80,8 @@ Section { PropertyLabel { visible: root.showVideoOutput - text: qsTr("Video Output") - tooltip: qsTr("Holds the target video output.") + text: qsTr("Video output") + tooltip: qsTr("Target video output.") } SecondColumnLayout { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml index f5fd2282f01..54cf89cf255 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/Controls/AbstractButtonSection.qml @@ -41,7 +41,7 @@ import QtQuickDesignerTheme 1.0 import StudioTheme 1.0 as StudioTheme Section { - caption: qsTr("Button content") + caption: qsTr("Button Content") anchors.left: parent.left anchors.right: parent.right @@ -49,7 +49,7 @@ Section { SectionLayout { PropertyLabel { text: qsTr("Text") - tooltip: qsTr("The text displayed on the button.") + tooltip: qsTr("Text displayed on the button.") } SecondColumnLayout { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LoaderSpecifics.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LoaderSpecifics.qml index 2417c545876..b4447d2adab 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LoaderSpecifics.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/QtQuick/LoaderSpecifics.qml @@ -41,7 +41,7 @@ Column { SectionLayout { PropertyLabel { text: qsTr("Active") - tooltip: qsTr("This property is true if the Loader is currently active.") + tooltip: qsTr("Whether the loader is currently active.") } SecondColumnLayout { @@ -57,7 +57,7 @@ Column { PropertyLabel { text: qsTr("Source") - tooltip: qsTr("This property holds the URL of the QML component to instantiate.") + tooltip: qsTr("URL of the component to instantiate.") } SecondColumnLayout { @@ -70,8 +70,8 @@ Column { } PropertyLabel { - text: qsTr("Source Component") - tooltip: qsTr("This property holds the component to instantiate.") + text: qsTr("Source component") + tooltip: qsTr("Component to instantiate.") } SecondColumnLayout { @@ -88,7 +88,7 @@ Column { PropertyLabel { text: qsTr("Asynchronous") - tooltip: qsTr("This property holds whether the component will be instantiated asynchronously.") + tooltip: qsTr("Whether the component will be instantiated asynchronously.") } SecondColumnLayout { diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml index 7a2225bee7d..5d9a121a913 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ComponentSection.qml @@ -218,7 +218,7 @@ Section { AbstractButton { id: editAnnotationButton buttonIcon: StudioTheme.Constants.edit - tooltip: qsTr("Edit annotation") + tooltip: qsTr("Edit Annotation") onClicked: annotationEditor.showWidget() onHoveredChanged: annotationEditor.checkAux() } @@ -226,7 +226,7 @@ Section { AbstractButton { id: removeAnnotationButton buttonIcon: StudioTheme.Constants.closeCross - tooltip: qsTr("Remove annotation") + tooltip: qsTr("Remove Annotation") onClicked: annotationEditor.removeFullAnnotation() onHoveredChanged: annotationEditor.checkAux() } diff --git a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp index 5ac9a4ae8a8..d56c593a83c 100644 --- a/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp +++ b/src/plugins/qmldesigner/assetexporterplugin/assetexporter.cpp @@ -129,7 +129,7 @@ void AssetExporter::exportQml(const Utils::FilePaths &qmlFiles, const Utils::Fil .arg(exportAssets? tr("Yes") : tr("No"))); if (m_perComponentExport) - ExportNotification::addInfo(tr("Each component is exported separately")); + ExportNotification::addInfo(tr("Each component is exported separately.")); notifyProgress(0.0); m_exportFiles = qmlFiles; @@ -394,7 +394,7 @@ void AssetExporter::writeMetadata() const { if (m_cancelled) { notifyProgress(1.0); - ExportNotification::addInfo(tr("Export cancelled.")); + ExportNotification::addInfo(tr("Export canceled.")); m_currentState.change(ParsingState::ExportingDone); return; } diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp index d88cf612c15..945820d9134 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dwidget.cpp @@ -150,7 +150,7 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) : tr("Your file does not import Qt Quick 3D.

" "To create a 3D view, add the QtQuick3D module in the Library view. Or click" " here " - "here to add it immediately.

" + "to add it immediately.

" "To import 3D assets from another tool, click the \"Add New Assets...\" button in the Assets tab of the Library view."); m_onboardingLabel->setText(labelText.arg(Utils::creatorTheme()->color(Utils::Theme::TextColorLink).name())); m_onboardingLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp index 79e66976a97..654a18dfc9e 100644 --- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp +++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp @@ -768,7 +768,7 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in "NavigatorTreeModel", "Inserting materials under imported 3D component nodes is not supported. " "Materials used in imported 3D components have to be modified inside the component itself.\n\n" - "Would you like to go into component '%1'?") + "Would you like to go into component \"%1\"?") .arg(targetProperty.parentModelNode().id()), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); diff --git a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp index ccf84152b57..ec715624f34 100644 --- a/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp +++ b/src/plugins/qmldesigner/components/transitioneditor/transitioneditorview.cpp @@ -301,7 +301,7 @@ ModelNode TransitionEditorView::addNewTransition() if (!properties.isEmpty()) properties.chop(2); Core::AsynchronousMessageBox::warning( - tr("No properties to animate found."), + tr("No Property Changes to Animate"), tr("To add transitions, first change the properties that you want to animate in states (%1).") .arg(properties)); } diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 2114a56d3d7..979a0321f26 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -257,9 +257,9 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e designerActionManager().addDesignerAction(startNanotraceAction); auto shutDownNanotraceAction = new ModelNodeAction("ShutDown Nanotrace", - QObject::tr("ShutDown Nanotrace"), + QObject::tr("Shut Down Nanotrace"), shutdownNanotraceIcon(), - QObject::tr("ShutDown Nanotrace"), + QObject::tr("Shut Down Nanotrace"), ComponentCoreConstants::eventListCategory, QKeySequence(), 220, diff --git a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp index cfb2bfaf474..dc57689cad9 100644 --- a/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp +++ b/src/plugins/qmlprojectmanager/qmlmultilanguageaspect.cpp @@ -76,8 +76,7 @@ QmlMultiLanguageAspect::QmlMultiLanguageAspect(ProjectExplorer::Target *target) setVisible(isMultilanguagePresent()); setSettingsKey(Constants::USE_MULTILANGUAGE_KEY); setLabel(tr("Use MultiLanguage in Form Editor."), BoolAspect::LabelPlacement::AtCheckBox); - setToolTip(tr("By enabling this Form Editor can read translations\n" - "from MultiLanguage plugin.")); + setToolTip(tr("Reads translations from MultiLanguage plugin.")); setDefaultValue(!databaseFilePath().isEmpty()); QVariantMap getDefaultValues; From 4f3d3d445c8fcfcaf6638ac034aa6a541299caf6 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 18:02:48 +0100 Subject: [PATCH 23/76] Project Explorer: Fix UI text Task-number: QTCREATORBUG-27055 Change-Id: I9b0e4f02ea7d1ebb14a9581f21c76b8908589334 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/appoutputpane.cpp | 2 +- src/plugins/projectexplorer/buildconfiguration.cpp | 4 ++-- src/plugins/projectexplorer/compileoutputwindow.cpp | 2 +- src/plugins/projectexplorer/kit.cpp | 4 ++-- src/plugins/projectexplorer/runconfiguration.cpp | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index 076fb1c8953..9fc9562355e 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -174,7 +174,7 @@ AppOutputPane::AppOutputPane() : m_formatterWidget(new QWidget), m_handler(new ShowOutputTaskHandler(this, tr("Show &App Output"), - tr("Show the output that generated this issue in the application output window"), + tr("Show the output that generated this issue in the Application Output pane."), tr("A"))) { ExtensionSystem::PluginManager::addObject(m_handler); diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp index 7a68c276c3d..f5aec089ced 100644 --- a/src/plugins/projectexplorer/buildconfiguration.cpp +++ b/src/plugins/projectexplorer/buildconfiguration.cpp @@ -121,8 +121,8 @@ public: layout->setContentsMargins(0, 0, 0, 0); const auto pasteStdOutCB = new QCheckBox(tr("Parse standard output during build"), this); - pasteStdOutCB->setToolTip(tr("Check this to make output parsers look for diagnostics " - "on stdout rather than stderr")); + pasteStdOutCB->setToolTip(tr("Makes output parsers look for diagnostics " + "on stdout rather than stderr.")); pasteStdOutCB->setChecked(bc->parseStdOut()); layout->addWidget(pasteStdOutCB); diff --git a/src/plugins/projectexplorer/compileoutputwindow.cpp b/src/plugins/projectexplorer/compileoutputwindow.cpp index a51397bd256..abb6736a955 100644 --- a/src/plugins/projectexplorer/compileoutputwindow.cpp +++ b/src/plugins/projectexplorer/compileoutputwindow.cpp @@ -118,7 +118,7 @@ CompileOutputWindow::CompileOutputWindow(QAction *cancelBuildAction) : m_handler = new ShowOutputTaskHandler(this, tr("Show Compile &Output"), - tr("Show the output that generated this issue in the compile output window"), + tr("Show the output that generated this issue in the Compile Output pane."), tr("O")); ExtensionSystem::PluginManager::addObject(m_handler); setupContext(C_COMPILE_OUTPUT, m_outputWindow); diff --git a/src/plugins/projectexplorer/kit.cpp b/src/plugins/projectexplorer/kit.cpp index b509c5bc62f..114e6e25512 100644 --- a/src/plugins/projectexplorer/kit.cpp +++ b/src/plugins/projectexplorer/kit.cpp @@ -113,11 +113,11 @@ public: [kit] { return kit->fileSystemFriendlyName(); }); m_macroExpander.registerVariable("CurrentKit:Id", - tr("The id of the currently active kit."), + tr("The ID of the currently active kit."), [kit] { return kit->id().toString(); }, false); m_macroExpander.registerVariable("Kit:Id", - tr("The id of the kit."), + tr("The ID of the kit."), [kit] { return kit->id().toString(); }); } diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 76ac46ec224..430eadb8dae 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -188,13 +188,13 @@ RunConfiguration::RunConfiguration(Target *target, Utils::Id id) BuildConfiguration *bc = target->activeBuildConfiguration(); return bc ? bc->macroExpander() : target->macroExpander(); }); - m_expander.registerPrefix("RunConfig:Env", tr("Variables in the run environment"), + m_expander.registerPrefix("RunConfig:Env", tr("Variables in the run environment."), [this](const QString &var) { const auto envAspect = aspect(); return envAspect ? envAspect->environment().expandedValueForKey(var) : QString(); }); m_expander.registerVariable("RunConfig:WorkingDir", - tr("The run configuration's working directory"), + tr("The run configuration's working directory."), [this] { const auto wdAspect = aspect(); return wdAspect ? wdAspect->workingDirectory().toString() : QString(); From e4b39e0ce4b2c255881e61c3d2a70cdaa2204b78 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 18:00:07 +0100 Subject: [PATCH 24/76] CMake: Fix UI text Task-number: QTCREATORBUG-27055 Change-Id: I53a3ece8b6180afa4fbcbc474cc980aced5f55c8 Reviewed-by: Eike Ziller --- src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp | 2 +- src/plugins/cmakeprojectmanager/cmakekitinformation.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index abf3d4f552d..6513dadab92 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -303,7 +303,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc) m_resetButton->setEnabled(false); m_batchEditButton = new QPushButton(tr("Batch Edit...")); - m_batchEditButton->setToolTip(tr("Set or reset multiple values in the CMake Configuration.")); + m_batchEditButton->setToolTip(tr("Set or reset multiple values in the CMake configuration.")); m_showAdvancedCheckBox = new QCheckBox(tr("Advanced")); diff --git a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp index 5b677533ebb..cd315af53b8 100644 --- a/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp +++ b/src/plugins/cmakeprojectmanager/cmakekitinformation.cpp @@ -326,7 +326,7 @@ QSet CMakeKitAspect::availableFeatures(const Kit *k) const QString CMakeKitAspect::msgUnsupportedVersion(const QByteArray &versionString) { - return tr("CMake version %1 is unsupported. Please update to " + return tr("CMake version %1 is unsupported. Update to " "version 3.14 (with file-api) or later.") .arg(QString::fromUtf8(versionString)); } From eb8d84f6de49fbe9763887bbb3e201086ac7922f Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 18:15:29 +0100 Subject: [PATCH 25/76] Docker: Fix UI text caps and punctuation Task-number: QTCREATORBUG-27055 Change-Id: I6b5c2bbd36e34d4444b798e2e5040bff674ad02a Reviewed-by: hjk --- src/plugins/docker/dockerdevice.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index ccff135afa8..e3170577115 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -335,7 +335,7 @@ public: m_runAsOutsideUser = new QCheckBox(tr("Run as outside user")); m_runAsOutsideUser->setToolTip(tr("Uses user ID and group ID of the user running Qt Creator " - "in the Docker container.")); + "in the docker container.")); m_runAsOutsideUser->setChecked(data.useLocalUidGid); m_runAsOutsideUser->setEnabled(HostOsInfo::isLinuxHost()); @@ -363,7 +363,7 @@ public: m_pathsListEdit = new PathListEditor; m_pathsListEdit->setToolTip(tr("Maps paths in this list one-to-one to the " - "Docker container.")); + "docker container.")); m_pathsListEdit->setPathList(data.mounts); connect(m_pathsListEdit, &PathListEditor::changed, this, [dockerDevice, this]() { @@ -380,12 +380,12 @@ public: auto searchDirsComboBox = new QComboBox; searchDirsComboBox->addItem(tr("Search in PATH")); - searchDirsComboBox->addItem(tr("Search in selected directories")); + searchDirsComboBox->addItem(tr("Search in Selected Directories")); auto searchDirsLineEdit = new QLineEdit; searchDirsLineEdit->setText("/usr/bin;/opt"); searchDirsLineEdit->setToolTip( - tr("Select the paths in the Docker image that should be scanned for Kit entries")); + tr("Select the paths in the docker image that should be scanned for kit entries.")); auto searchPaths = [this, searchDirsComboBox, searchDirsLineEdit, dockerDevice] { FilePaths paths; @@ -493,7 +493,7 @@ Tasks DockerDevice::validate() const Tasks result; if (d->m_data.mounts.isEmpty()) { result << Task(Task::Error, - tr("The Docker device has not set up shared directories." + tr("The docker device has not set up shared directories." "This will not work for building."), {}, -1, {}); } @@ -531,7 +531,7 @@ DockerDevice::DockerDevice(const DockerDeviceData &data) Q_UNUSED(env); // TODO: That's the runnable's environment in general. Use it via -e below. updateContainerAccess(); if (d->m_container.isEmpty()) { - MessageManager::writeDisrupting(tr("Error starting remote shell. No container")); + MessageManager::writeDisrupting(tr("Error starting remote shell. No container.")); return; } @@ -909,7 +909,7 @@ void DockerDevicePrivate::startContainer() if (exitCode > 120) { DockerPlugin::setGlobalDaemonState(false); LOG("DOCKER DAEMON NOT RUNNING?"); - MessageManager::writeFlashing(tr("Docker Daemon appears to be not running. " + MessageManager::writeFlashing(tr("Docker daemon appears to be not running. " "Verify daemon is up and running and reset the " "docker daemon on the docker device settings page " "or restart Qt Creator.")); @@ -973,7 +973,7 @@ void DockerDevicePrivate::updateFileSystemAccess() if (!QFileInfo(m_mergedDir).isReadable()) { MessageManager::writeFlashing( - tr("Local read access to Docker container %1 unavailable through directory \"%2\".") + tr("Local read access to docker container %1 unavailable through directory \"%2\".") .arg(m_container, m_mergedDir) + '\n' + tr("Output: \"%1\"").arg(out) + '\n' + tr("Error: \"%1\"").arg(proc.stdErr())); From 99ceebe69503f737b7c6574a8427eceee2591c51 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 18:09:22 +0100 Subject: [PATCH 26/76] Debugger: Remove extra words from tooltips Task-number: QTCREATORBUG-27055 Change-Id: Ic7b447da2de3267ad897cdef0275a2faa4474099 Reviewed-by: hjk --- src/plugins/debugger/debuggeractions.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index bab0d00133d..736869cc591 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -120,7 +120,7 @@ DebuggerSettings::DebuggerSettings() forceLoggingToConsole.setSettingsKey(debugModeGroup, "ForceLoggingToConsole"); forceLoggingToConsole.setLabelText(tr("Force logging to console")); - forceLoggingToConsole.setToolTip(tr("This sets QT_LOGGING_TO_CONSOLE=1 in the environment " + forceLoggingToConsole.setToolTip(tr("Sets QT_LOGGING_TO_CONSOLE=1 in the environment " "of the debugged program, preventing storing debug output " "in system logs.")); @@ -165,7 +165,7 @@ DebuggerSettings::DebuggerSettings() CommonOptionsPage::msgSetBreakpointAtFunction(Constants::CRT_DEBUG_REPORT)); cdbBreakOnCrtDbgReport.setToolTip( CommonOptionsPage::msgSetBreakpointAtFunctionToolTip(Constants::CRT_DEBUG_REPORT, - tr("This is useful to catch runtime error messages for example caused by assert()."))); + tr("Catches runtime error messages caused by assert(), for example."))); useCdbConsole.setSettingsKey(cdbSettingsGroup, "CDB_Console"); useCdbConsole.setToolTip("

" + tr( @@ -421,7 +421,7 @@ DebuggerSettings::DebuggerSettings() useAnnotationsInMainEditor.setSettingsKey(debugModeGroup, "UseAnnotations"); useAnnotationsInMainEditor.setLabelText(tr("Use annotations in main editor when debugging")); - useAnnotationsInMainEditor.setToolTip(tr("

Checking this will show simple variable values " + useAnnotationsInMainEditor.setToolTip(tr("

Shows simple variable values " "as annotations in the main editor during debugging.")); useAnnotationsInMainEditor.setDefaultValue(true); @@ -440,7 +440,7 @@ DebuggerSettings::DebuggerSettings() useToolTipsInMainEditor.setSettingsKey(debugModeGroup, "UseToolTips"); useToolTipsInMainEditor.setLabelText(tr("Use tooltips in main editor when debugging")); - useToolTipsInMainEditor.setToolTip(tr("

Checking this will enable tooltips for variable " + useToolTipsInMainEditor.setToolTip(tr("

Enables tooltips for variable " "values during debugging. Since this can slow down debugging and " "does not provide reliable information as it does not use scope " "information, it is switched off by default.")); @@ -448,17 +448,17 @@ DebuggerSettings::DebuggerSettings() useToolTipsInLocalsView.setSettingsKey(debugModeGroup, "UseToolTipsInLocalsView"); useToolTipsInLocalsView.setLabelText(tr("Use Tooltips in Locals View when Debugging")); - useToolTipsInLocalsView.setToolTip(tr("

Checking this will enable tooltips in the locals " + useToolTipsInLocalsView.setToolTip(tr("

Enables tooltips in the locals " "view during debugging.")); useToolTipsInBreakpointsView.setSettingsKey(debugModeGroup, "UseToolTipsInBreakpointsView"); useToolTipsInBreakpointsView.setLabelText(tr("Use Tooltips in Breakpoints View when Debugging")); - useToolTipsInBreakpointsView.setToolTip(tr("

Checking this will enable tooltips in the breakpoints " + useToolTipsInBreakpointsView.setToolTip(tr("

Enables tooltips in the breakpoints " "view during debugging.")); useToolTipsInStackView.setSettingsKey(debugModeGroup, "UseToolTipsInStackView"); useToolTipsInStackView.setLabelText(tr("Use Tooltips in Stack View when Debugging")); - useToolTipsInStackView.setToolTip(tr("

Checking this will enable tooltips in the stack " + useToolTipsInStackView.setToolTip(tr("

Enables tooltips in the stack " "view during debugging.")); useToolTipsInStackView.setDefaultValue(true); From 0064dda2c0800ada4eec29632080bbb96c929353 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 18:19:42 +0100 Subject: [PATCH 27/76] Remote Linux: Do not use contractions in UI text Task-number: QTCREATORBUG-27055 Change-Id: I7fbc6374c910fa81900a10432892c10afb0ea6d4 Reviewed-by: Jarek Kobus --- .../remotelinux/remotelinuxcheckforfreediskspaceservice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp index bb2cdf86adc..bb1b67a746b 100644 --- a/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp +++ b/src/plugins/remotelinux/remotelinuxcheckforfreediskspaceservice.cpp @@ -68,7 +68,7 @@ void RemoteLinuxCheckForFreeDiskSpaceService::deployAndFinish() = deviceConfiguration()->mapToGlobalPath(Utils::FilePath::fromString(d->pathToCheck)); const qint64 freeSpace = path.bytesAvailable(); if (freeSpace < 0) { - emit errorMessage(tr("Can't get the info about the free disk space for \"%1\"") + emit errorMessage(tr("Cannot get info about free disk space for \"%1\"") .arg(path.toUserOutput())); return; } From 8851810658220231c798a27d67c78d74e6193869 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 17 Feb 2022 11:03:18 +0100 Subject: [PATCH 28/76] GitHub: Explicitly use MSVC 2019 machines windows-latest is "transitioning to 2022" currently, and that seems to mean that for some users this is already 2022 and for some still 2019. Explicitly state something. Change-Id: I1e7ba6fa60b9fe44c78505b322ff8278c2e41ee6 Reviewed-by: Alessandro Portale --- .github/workflows/build_cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_cmake.yml b/.github/workflows/build_cmake.yml index 5d4585d33ad..25e087fb25f 100644 --- a/.github/workflows/build_cmake.yml +++ b/.github/workflows/build_cmake.yml @@ -25,8 +25,8 @@ jobs: matrix: config: - { - name: "Windows Latest MSVC", artifact: "Windows-MSVC", - os: windows-latest, + name: "Windows MSVC 2019", artifact: "Windows-MSVC", + os: windows-2019, cc: "cl", cxx: "cl", environment_script: "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat", is_msvc: true From 5d660d7afe6c72a5902e4d86bfb244f0e3ad326e Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Thu, 17 Feb 2022 09:33:26 +0100 Subject: [PATCH 29/76] QmlDesigner: Add examples download path setting Add a PathChooser to StudioSettingsPage which enables setting the location to which the QtDesignStudio examples are extracted. Task-number: QDS-6174 Change-Id: I99232edf3c1200a84daaadf4a0d118317a5ea009 Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- src/plugins/studiowelcome/examplecheckout.cpp | 43 ++++++++++++++--- .../studiowelcome/studiowelcomeplugin.cpp | 48 +++++++++++++++++-- .../studiowelcome/studiowelcomeplugin.h | 7 +++ 3 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp index 377d0f4cb7f..7bfcc1902ac 100644 --- a/src/plugins/studiowelcome/examplecheckout.cpp +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -28,11 +28,19 @@ #include #include +#include #include #include #include +#include +#include + +#include + +#include + #include #include #include @@ -229,12 +237,9 @@ FileExtractor::FileExtractor(QObject *parent) : QObject(parent) { m_targetPath = Utils::FilePath::fromString( - QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); - - if (!m_targetPath.isEmpty()) - m_targetPath = m_targetPath.pathAppended("QtDesignStudio"); - else - m_targetPath = "/temp/"; + Core::ICore::settings() + ->value(StudioWelcome::Internal::EXAMPLES_DOWNLOAD_PATH) + .toString()); m_timer.setInterval(100); m_timer.setSingleShot(false); @@ -247,6 +252,32 @@ FileExtractor::FileExtractor(QObject *parent) emit birthTimeChanged(); }); + + const ExtensionSystem::PluginSpec *pluginSpec + = Utils::findOrDefault(ExtensionSystem::PluginManager::plugins(), + Utils::equal(&ExtensionSystem::PluginSpec::name, + QString("StudioWelcome"))); + + if (!pluginSpec) + return; + + ExtensionSystem::IPlugin *plugin = pluginSpec->plugin(); + + if (!plugin) + return; + + auto studioWelcomePlugin = qobject_cast(plugin); + + if (studioWelcomePlugin) { + QObject::connect(studioWelcomePlugin, + &StudioWelcome::Internal::StudioWelcomePlugin::examplesDownloadPathChanged, + this, + [this](const QString &path) { + m_targetPath = Utils::FilePath::fromString(path); + emit targetPathChanged(); + emit targetFolderExistsChanged(); + }); + } } FileExtractor::~FileExtractor() {} diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index 9b20e013162..e89bc5fa1d1 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -777,6 +778,18 @@ void setSettingIfDifferent(const QString &key, bool value, bool &dirty) } } +const Utils::FilePath defaultExamplesPath = Utils::FilePath::fromString( + QStandardPaths::writableLocation( + QStandardPaths::DocumentsLocation)) + .pathAppended("QtDesignStudio"); + +static QString examplesPathSetting() +{ + return Core::ICore::settings() + ->value(EXAMPLES_DOWNLOAD_PATH, defaultExamplesPath.toString()) + .toString(); +} + WelcomeMode::~WelcomeMode() { delete m_modeWidget; @@ -786,19 +799,18 @@ StudioSettingsPage::StudioSettingsPage() : m_buildCheckBox(new QCheckBox(tr("Build"))) , m_debugCheckBox(new QCheckBox(tr("Debug"))) , m_analyzeCheckBox(new QCheckBox(tr("Analyze"))) + , m_pathChooser(new Utils::PathChooser()) { const QString toolTip = tr( "Hide top-level menus with advanced functionality to simplify the UI. Build is " "generally not required in the context of Qt Design Studio.Debug and Analyze" "are only required for debugging and profiling."); - QVBoxLayout *boxLayout = new QVBoxLayout(this); + QVBoxLayout *boxLayout = new QVBoxLayout(); setLayout(boxLayout); auto groupBox = new QGroupBox(tr("Hide Menu")); groupBox->setToolTip(toolTip); boxLayout->addWidget(groupBox); - boxLayout->addSpacerItem( - new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding)); auto verticalLayout = new QVBoxLayout(); groupBox->setLayout(verticalLayout); @@ -816,6 +828,28 @@ StudioSettingsPage::StudioSettingsPage() m_buildCheckBox->setChecked(hideBuildMenuSetting()); m_debugCheckBox->setChecked(hideDebugMenuSetting()); m_analyzeCheckBox->setChecked(hideAnalyzeMenuSetting()); + + auto examplesGroupBox = new QGroupBox(tr("Examples")); + boxLayout->addWidget(examplesGroupBox); + + auto horizontalLayout = new QHBoxLayout(); + examplesGroupBox->setLayout(horizontalLayout); + + auto label = new QLabel(tr("Examples path:")); + m_pathChooser->setFilePath(Utils::FilePath::fromString(examplesPathSetting())); + auto resetButton = new QPushButton(tr("Reset Path")); + + connect(resetButton, &QPushButton::clicked, this, [this]() { + m_pathChooser->setFilePath(defaultExamplesPath); + }); + + horizontalLayout->addWidget(label); + horizontalLayout->addWidget(m_pathChooser); + horizontalLayout->addWidget(resetButton); + + + boxLayout->addSpacerItem( + new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding)); } void StudioSettingsPage::apply() @@ -840,6 +874,14 @@ void StudioSettingsPage::apply() Core::RestartDialog restartDialog(Core::ICore::dialogParent(), restartText); restartDialog.exec(); } + + QSettings *s = Core::ICore::settings(); + const QString value = m_pathChooser->filePath().toString(); + + if (s->value(EXAMPLES_DOWNLOAD_PATH, false).toString() != value) { + s->setValue(EXAMPLES_DOWNLOAD_PATH, value); + emit s_pluginInstance->examplesDownloadPathChanged(value); + } } StudioWelcomeSettingsPage::StudioWelcomeSettingsPage() diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.h b/src/plugins/studiowelcome/studiowelcomeplugin.h index 519f86dd863..11274b68a6b 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.h +++ b/src/plugins/studiowelcome/studiowelcomeplugin.h @@ -27,6 +27,7 @@ #include #include +#include #include @@ -35,6 +36,8 @@ QT_FORWARD_DECLARE_CLASS(QCheckBox) namespace StudioWelcome { namespace Internal { +const char EXAMPLES_DOWNLOAD_PATH[] = "StudioWelcome/ExamplesDownloadPath"; + class StudioSettingsPage : public Core::IOptionsPageWidget { public: @@ -46,6 +49,7 @@ private: QCheckBox *m_buildCheckBox; QCheckBox *m_debugCheckBox; QCheckBox *m_analyzeCheckBox; + Utils::PathChooser *m_pathChooser; }; class StudioWelcomeSettingsPage : public Core::IOptionsPage @@ -76,6 +80,9 @@ public: void pauseRemoveSplashTimer(); void resumeRemoveSplashTimer(); +signals: + void examplesDownloadPathChanged(const QString &path); + private: class WelcomeMode *m_welcomeMode = nullptr; QTimer m_removeSplashTimer; From f7cbc513aac3aaa55500fef783b2cedcef8dd29d Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Thu, 17 Feb 2022 10:14:20 +0100 Subject: [PATCH 30/76] QmlDesigner: Add missing context pointer connect * Add missing context pointer in connect statement * Fix console output "QFile::remove: Empty or null file name" Task-number: QDS-6170 Change-Id: I31f671dc1422c6b90aff81252f4bc4cf2c34e7d1 Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- src/plugins/studiowelcome/examplecheckout.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp index 7bfcc1902ac..5a4f9bee2e3 100644 --- a/src/plugins/studiowelcome/examplecheckout.cpp +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -77,7 +77,8 @@ FileDownloader::FileDownloader(QObject *parent) FileDownloader::~FileDownloader() { - m_tempFile.remove(); + if (m_tempFile.exists()) + m_tempFile.remove(); } void FileDownloader::start() @@ -111,7 +112,8 @@ void FileDownloader::start() QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() { if (reply->error()) { - m_tempFile.remove(); + if (m_tempFile.exists()) + m_tempFile.remove(); qDebug() << Q_FUNC_INFO << m_url << reply->errorString(); emit downloadFailed(); } else { @@ -411,7 +413,7 @@ void FileExtractor::extract() emit detailedTextChanged(); }); - QObject::connect(archive, &Utils::Archive::finished, [this](bool ret) { + QObject::connect(archive, &Utils::Archive::finished, this, [this](bool ret) { m_finished = ret; m_timer.stop(); From 9c4e4309f8d83b4f64c697a932fdf44461193436 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Thu, 17 Feb 2022 15:44:47 +0200 Subject: [PATCH 31/76] QmlDesigner: Close Assets Library context menu on press outside Fixes: QDS-6197 Change-Id: I0c694b5a64bc0a41e905523b16552d6b0493eac6 Reviewed-by: Samuel Ghinet Reviewed-by: Miikka Heikkinen --- share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml index de2ded3c9d7..8ed479868a7 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml @@ -98,6 +98,8 @@ Item { StudioControls.Menu { id: contextMenu + closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape + StudioControls.MenuItem { text: qsTr("Expand All") enabled: allExpandedState !== 1 From 81c9051feb61a4bdc27f2e8699d5de9ba83acbc0 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Thu, 17 Feb 2022 16:12:03 +0200 Subject: [PATCH 32/76] QmlDesigner: Fix rename asset folder dialog's error text width Fixes: QDS-6202 Change-Id: Iea6714561ce23e3a18889ab5d684fbeae85d62fe Reviewed-by: Miikka Heikkinen --- share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml index 8ed479868a7..f254a325508 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml @@ -202,7 +202,7 @@ Item { Text { text: qsTr("Could not rename folder. Make sure no folder with the same name exists.") wrapMode: Text.WordWrap - width: renameFolderDialog.width + width: renameFolderDialog.width - 12 color: "#ff0000" visible: renameFolderDialog.renameError } From b2d90241fee3e6bdaf8dfb8b587d68c92115da2b Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 18:07:05 +0100 Subject: [PATCH 33/76] Log Viewer: Fix UI text Also update the string in the documentation. Task-number: QTCREATORBUG-27055 Change-Id: Idce699a7796e7cb55d8218c105ec851c369cef7b Reviewed-by: Eike Ziller --- .../creator-only/creator-logging-viewer.qdoc | 2 +- src/plugins/coreplugin/loggingviewer.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/qtcreator/src/howto/creator-only/creator-logging-viewer.qdoc b/doc/qtcreator/src/howto/creator-only/creator-logging-viewer.qdoc index 963449be581..150354c3e37 100644 --- a/doc/qtcreator/src/howto/creator-only/creator-logging-viewer.qdoc +++ b/doc/qtcreator/src/howto/creator-only/creator-logging-viewer.qdoc @@ -83,7 +83,7 @@ By default, logging categories and messages coming directly from Qt are disabled. To display them, select \inlineimage icons/qtlogo-16.png - (\uicontrol {Toggle logging of Qt internal loggings.}) + (\uicontrol {Toggle Qt Internal Logging}). New messages automatically scroll the message display to the bottom. To stop automatic scrolling, toggle \inlineimage icons/arrowdown.png diff --git a/src/plugins/coreplugin/loggingviewer.cpp b/src/plugins/coreplugin/loggingviewer.cpp index 89046e39b2e..677bffd455c 100644 --- a/src/plugins/coreplugin/loggingviewer.cpp +++ b/src/plugins/coreplugin/loggingviewer.cpp @@ -425,7 +425,7 @@ LoggingViewManagerWidget::LoggingViewManagerWidget(QWidget *parent) buttonsLayout->addWidget(stop); auto qtInternal = new QToolButton; qtInternal->setIcon(Core::Icons::QTLOGO.icon()); - qtInternal->setToolTip(tr("Toggle logging of Qt internal loggings")); + qtInternal->setToolTip(tr("Toggle Qt Internal Logging")); qtInternal->setCheckable(true); qtInternal->setChecked(false); buttonsLayout->addWidget(qtInternal); @@ -616,7 +616,7 @@ void LoggingViewManagerWidget::saveLoggingsToFile() const if (enabled) m_manager->setEnabled(false); const Utils::FilePath fp = Utils::FileUtils::getSaveFilePath(ICore::dialogParent(), - tr("Save logs as")); + tr("Save Logs As")); if (fp.isEmpty()) return; const bool useTS = m_timestamps->isChecked(); @@ -628,7 +628,7 @@ void LoggingViewManagerWidget::saveLoggingsToFile() const if (res == -1) { QMessageBox::critical( ICore::dialogParent(), tr("Error"), - tr("Failed to write logs to '%1'.").arg(fp.toUserOutput())); + tr("Failed to write logs to \"%1\".").arg(fp.toUserOutput())); break; } } @@ -636,14 +636,14 @@ void LoggingViewManagerWidget::saveLoggingsToFile() const } else { QMessageBox::critical( ICore::dialogParent(), tr("Error"), - tr("Failed to open file '%1' for writing logs.").arg(fp.toUserOutput())); + tr("Failed to open file \"%1\" for writing logs.").arg(fp.toUserOutput())); } } void LoggingViewManagerWidget::saveEnabledCategoryPreset() const { Utils::FilePath fp = Utils::FileUtils::getSaveFilePath(ICore::dialogParent(), - tr("Save enabled categories as")); + tr("Save Enabled Categories As")); if (fp.isEmpty()) return; const QList enabled = m_categoryModel->enabledCategories(); @@ -663,13 +663,13 @@ void LoggingViewManagerWidget::saveEnabledCategoryPreset() const if (!fp.writeFileContents(doc.toJson(QJsonDocument::Compact))) QMessageBox::critical( ICore::dialogParent(), tr("Error"), - tr("Failed to write preset file '%1'.").arg(fp.toUserOutput())); + tr("Failed to write preset file \"%1\".").arg(fp.toUserOutput())); } void LoggingViewManagerWidget::loadAndUpdateFromPreset() { Utils::FilePath fp = Utils::FileUtils::getOpenFilePath(ICore::dialogParent(), - tr("Load enabled categories from")); + tr("Load Enabled Categories From")); if (fp.isEmpty()) return; // read file, update categories @@ -677,7 +677,7 @@ void LoggingViewManagerWidget::loadAndUpdateFromPreset() QJsonDocument doc = QJsonDocument::fromJson(fp.fileContents(), &error); if (error.error != QJsonParseError::NoError) { QMessageBox::critical(ICore::dialogParent(), tr("Error"), - tr("Failed to read preset file '%1': %2").arg(fp.toUserOutput()) + tr("Failed to read preset file \"%1\": %2").arg(fp.toUserOutput()) .arg(error.errorString())); return; } From 3805bec91ff9ebff063ada2db4c91fbbcfab5966 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 18:12:03 +0100 Subject: [PATCH 34/76] C++ Editor: Fix UI text capitalization Task-number: QTCREATORBUG-27055 Change-Id: I148cfb7b9628ab2460050c1127b6557b8830983b Reviewed-by: Christian Kandeler --- src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp b/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp index 4692a158ab8..a1de9d125dd 100644 --- a/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp +++ b/src/plugins/cppeditor/clangdiagnosticconfigsselectionwidget.cpp @@ -41,7 +41,7 @@ namespace CppEditor { ClangDiagnosticConfigsSelectionWidget::ClangDiagnosticConfigsSelectionWidget(QWidget *parent) : QWidget(parent) - , m_label(new QLabel(tr("Diagnostic Configuration:"))) + , m_label(new QLabel(tr("Diagnostic configuration:"))) , m_button(new QPushButton) { auto *layout = new QHBoxLayout(this); From e4ff13e52996200ca742b91fa8ced8a486f12f6d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 18 Feb 2022 06:35:35 +0100 Subject: [PATCH 35/76] StudioWelcome: Fix compile Amends 5d660d7afe6. Change-Id: I8d7239f2b57274c062cb2f9f535d274f5e149288 Reviewed-by: David Schulz --- src/plugins/studiowelcome/examplecheckout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp index 5a4f9bee2e3..a3c7d70e710 100644 --- a/src/plugins/studiowelcome/examplecheckout.cpp +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -24,6 +24,8 @@ ****************************************************************************/ #include "examplecheckout.h" +#include "studiowelcomeplugin.h" + #include #include @@ -39,8 +41,6 @@ #include -#include - #include #include #include From 1f3e6b4c7a1f45ce9562a0e536daed8440653248 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 17:56:12 +0100 Subject: [PATCH 36/76] Android: Fix punctuation and wording of messages Task-number: QTCREATORBUG-27055 Change-Id: I4180717163ec52a405c40e1a932713dda27c3f38 Reviewed-by: Alessandro Portale Reviewed-by: Leena Miettinen --- share/qtcreator/translations/qtcreator_ru.ts | 56 ++++++++++---------- src/plugins/android/androidservicewidget.cpp | 32 +++++------ src/plugins/android/androidsettingswidget.ui | 2 +- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts index 1305808ff41..0a7cda15516 100644 --- a/share/qtcreator/translations/qtcreator_ru.ts +++ b/share/qtcreator/translations/qtcreator_ru.ts @@ -1758,12 +1758,12 @@ Cancelling pending operations... Android::Internal::AndroidServiceWidget::AndroidServiceModel - The name of the class implementing the service - Имя класса, реализующего сервис + The name of the class implementing the service. + Имя класса, реализующего сервис. - Checked if the service is run in an external process - Отмечено, если сервис работает во внешнем процессе + Checked if the service is run in an external process. + Отмечено, если сервис работает во внешнем процессе. The name of the external process. @@ -1772,52 +1772,52 @@ Prefix with : if the process is private, use a lowercase name if the process is Если имя начинается с двоеточия, то процесс приватный, если написано в нижнем регистре, то процесс глобальный. - Checked if the service is in a separate dynamic library - Отмечено, если сервис в отдельной динамической библиотеке + Checked if the service is in a separate dynamic library. + Отмечено, если сервис в отдельной динамической библиотеке. - The name of the separate dynamic library - Имя отдельной динамической библиотеки + The name of the separate dynamic library. + Имя отдельной динамической библиотеки. - The arguments for telling the app to run the service instead of the main activity - Параметры запуска сервиса вместо основной функциональности приложения + The arguments for telling the app to run the service instead of the main activity. + Параметры запуска сервиса вместо основной функциональности приложения. - Service class name - Имя класса сервиса + Service class name. + Имя класса сервиса. - Run in external process - Работа во внешнем процессе + Run in external process. + Работа во внешнем процессе. - Process name - Имя процесса + Process name. + Имя процесса. - Run in external library - Работа во внешней библиотеке + Run in external library. + Работа во внешней библиотеке. - Library name - Имя библиотеки + Library name. + Имя библиотеки. - Service arguments - Параметры сервиса + Service arguments. + Параметры сервиса. - The class name must be set - Должно быть задано имя класса + The class name must be set. + Должно быть задано имя класса. - The process name must be set for a service run in an external process - Имя процесса должно быть задано для сервиса, работающего во внешнем процессе + The process name must be set for a service run in an external process. + Имя процесса должно быть задано для сервиса, работающего во внешнем процессе. - The library name must be set for a service run in an external library - Имя библиотеки должно быть задано для сервиса, работающего во внешней библиотеке + The library name must be set for a service run in an external library. + Имя библиотеки должно быть задано для сервиса, работающего во внешней библиотеке. The service arguments must be set for a service not run in an external library diff --git a/src/plugins/android/androidservicewidget.cpp b/src/plugins/android/androidservicewidget.cpp index f7e1f0c499f..02f5935c608 100644 --- a/src/plugins/android/androidservicewidget.cpp +++ b/src/plugins/android/androidservicewidget.cpp @@ -204,31 +204,31 @@ QVariant AndroidServiceWidget::AndroidServiceModel::headerData(int section, Qt:: { if (role == Qt::ToolTipRole && orientation == Qt::Horizontal) { if (section == 0) - return tr("The name of the class implementing the service"); + return tr("The name of the class implementing the service."); else if (section == 1) - return tr("Checked if the service is run in an external process"); + return tr("Checked if the service is run in an external process."); else if (section == 2) return tr("The name of the external process.\n" "Prefix with : if the process is private, use a lowercase name if the process is global."); else if (section == 3) - return tr("Checked if the service is in a separate dynamic library"); + return tr("Checked if the service is in a separate dynamic library."); else if (section == 4) - return tr("The name of the separate dynamic library"); + return tr("The name of the separate dynamic library."); else if (section == 5) - return tr("The arguments for telling the app to run the service instead of the main activity"); + return tr("The arguments for telling the app to run the service instead of the main activity."); } else if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { if (section == 0) - return tr("Service class name"); + return tr("Service class name."); else if (section == 1) - return tr("Run in external process"); + return tr("Run in external process."); else if (section == 2) - return tr("Process name"); + return tr("Process name."); else if (section == 3) - return tr("Run in external library"); + return tr("Run in external library."); else if (section == 4) - return tr("Library name"); + return tr("Library name."); else if (section == 5) - return tr("Service arguments"); + return tr("Service arguments."); } return {}; } @@ -247,22 +247,22 @@ QVariant AndroidServiceWidget::AndroidServiceModel::data(const QModelIndex &inde if (index.column() == 0) return m_services[index.row()].className(); else if (index.column() == 1) - return tr("Run in external process"); + return tr("Run in external process."); else if (index.column() == 2) return m_services[index.row()].externalProcessName(); else if (index.column() == 3) - return tr("Run in external library"); + return tr("Run in external library."); else if (index.column() == 4) return m_services[index.row()].externalLibraryName(); else if (index.column() == 5) return m_services[index.row()].serviceArguments(); } else if (role == Qt::ToolTipRole) { if (index.column() == 0 && m_services[index.row()].className().isEmpty()) - return tr("The class name must be set"); + return tr("The class name must be set."); else if (index.column() == 2 && m_services[index.row()].isRunInExternalProcess()) - return tr("The process name must be set for a service run in an external process"); + return tr("The process name must be set for a service run in an external process."); else if (index.column() == 4 && m_services[index.row()].isRunInExternalLibrary()) - return tr("The library name must be set for a service run in an external library"); + return tr("The library name must be set for a service run in an external library."); } else if (role == Qt::EditRole) { if (index.column() == 0) return m_services[index.row()].className(); diff --git a/src/plugins/android/androidsettingswidget.ui b/src/plugins/android/androidsettingswidget.ui index 1dd2d8779ac..fcfdc63a1d2 100644 --- a/src/plugins/android/androidsettingswidget.ui +++ b/src/plugins/android/androidsettingswidget.ui @@ -65,7 +65,7 @@ - Force a specific NDK installation to be used by all Android kits.<br/>Note that the forced NDK might not be compatible with all Qt registered versions. + Force a specific NDK installation to be used by all Android kits.<br/>Note that the forced NDK might not be compatible with all registered Qt versions. From d4871103511e46759738487b41b4bb1b6cfb1a22 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 15 Feb 2022 11:54:57 +0100 Subject: [PATCH 37/76] QML/JS: Fix terminology in messages - Replace Qt Quick Designer with Qt Design Studio - Replace "Qt Quick UI form" with "UI file (.ui.qml)" Also fix the docs: - Add missing messages - Hide QDS messages from Qt Creator Manual - Make punctuation consistent - Add some links to more information Task-number: QDS-2670 Task-number: QTCREATORBUG-27055 Change-Id: Id90f1ad82e7297f91225bc8d650a9578ba071330 Reviewed-by: Mats Honkamaa Reviewed-by: Reviewed-by: Thomas Hartmann --- .../src/editors/creator-code-syntax.qdoc | 72 ++++++++++++++----- .../src/qtquick/qtquick-ui-forms.qdoc | 8 ++- src/libs/qmljs/qmljsstaticanalysismessage.cpp | 34 ++++----- 3 files changed, 76 insertions(+), 38 deletions(-) diff --git a/doc/qtcreator/src/editors/creator-code-syntax.qdoc b/doc/qtcreator/src/editors/creator-code-syntax.qdoc index 65e41022e37..f54337dd903 100644 --- a/doc/qtcreator/src/editors/creator-code-syntax.qdoc +++ b/doc/qtcreator/src/editors/creator-code-syntax.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -291,7 +291,7 @@ \row \li M106 \li Warning - \li \c Name is already a var + \li \c Name already is a var \li \row @@ -416,6 +416,12 @@ \li A state cannot have the specified child item \li + \row + \li M129 + \li Error + \li Type cannot be instantiated recursively + \li + \row \li M201 \li Hint @@ -430,6 +436,7 @@ \li Use only one statement per line \li + \if defined(qtdesignstudio) \row \li M203 \li Warning @@ -463,60 +470,70 @@ \row \li M208 \li Error - \li This id might be ambiguous and is not supported in \QDS. + \li This id might be ambiguous and is not supported in \QDS \li \row \li M209 \li Error \li This type (type name) is not supported as a root element in - \QDS. + \QDS \li + \endif \row \li M220 \li Error \li This type (type name) is not supported as a root element of a - UI file (.ui.qml). - \li + UI file (.ui.qml) + \li For more information about supported QML types, see \l{UI Files}. \row \li M221 \li Error - \li This type (type name) is not supported in a UI file (.ui.qml). - \li + \li This type (type name) is not supported in a UI file (.ui.qml) + \li For more information about supported QML types, see \l{UI Files}. \row \li M222 \li Error - \li Functions are not supported in a UI file (.ui.qml). + \li Functions are not supported in a UI file (.ui.qml) \li For a list of supported JavaScript functions, see \l{Supported Methods}. \row \li M223 \li Error - \li Java Script blocks are not supported in a UI file (.ui.qml). - \li + \li JavaScript blocks are not supported in a UI file (.ui.qml) + \li For more information about supported features, see \l{UI Files}. \row \li M224 \li Error - \li Behavior type is not supported in a UI file (.ui.qml). - \li + \li Behavior type is not supported in a UI file (.ui.qml) + \li For more information about supported QML types, see \l{UI Files}. \row \li M225 \li Error - \li States are only supported in the root item in a UI file (.ui.qml). - \li + \li States are only supported in the root item in a UI file (.ui.qml) + \li For more information about supported features, see \l{UI Files}. \row \li M226 \li Error \li Referencing the parent of the root item is not supported in a - UI file (.ui.qml). - \li + UI file (.ui.qml) + \li For more information about supported features, see \l{UI Files}. + + \row + \li M227 + \li Error + \li Do not mix translation functions in a UI file (.ui.qml) + \li Even though several different translation functions, such as + \c qsTr and \c qsTrId are supported, you should pick one and + use it consistently within a UI file. For more information, + see \l{Qt QML Methods}. \row \li M300 @@ -674,11 +691,30 @@ and most likely invalid \li + \row + \li M325 + \li Warning + \li Logical value does not depend on actual values + \li + + \row + \li M326 + \li Error + \li Components are only allowed to have a single child element + \li For more information, see \l [QML] {Component}. + + \row + \li M327 + \li Warning + \li Components require a child element + \li For more information, see \l [QML] {Component}. + \row \li M400 \li Warning \li Duplicate import - \li + \li An import statement has been added twice. For more information, + see \l{Import Statements}. \endtable diff --git a/doc/qtcreator/src/qtquick/qtquick-ui-forms.qdoc b/doc/qtcreator/src/qtquick/qtquick-ui-forms.qdoc index fb76d5250cb..a21991f7ba8 100644 --- a/doc/qtcreator/src/qtquick/qtquick-ui-forms.qdoc +++ b/doc/qtcreator/src/qtquick/qtquick-ui-forms.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Creator documentation. @@ -52,6 +52,7 @@ be edited in \QDS only. \endif + The following features are not supported in .ui.qml files: \list @@ -61,6 +62,7 @@ \li States in other components than the root component \li Root components that are not derived from \l QQuickItem or \l [QML]{Item} + \li Referencing the parent of the root component \endlist The following components are not supported: @@ -69,11 +71,9 @@ \li Behavior \li Binding \li Canvas - \li Component \li Shader Effect \li Timer \li Transform - \li Transition \endlist \section1 Supported Methods @@ -165,6 +165,8 @@ \li \l{Qt::}{qsTrNoOp()} \endlist + \note Do not mix translation methods in a UI file. + For more information about using the methods, see \l{https://doc.qt.io/qt/qml-qtqml-qt.html}{Qt QML Methods}. diff --git a/src/libs/qmljs/qmljsstaticanalysismessage.cpp b/src/libs/qmljs/qmljsstaticanalysismessage.cpp index c65508bdfa5..0c026ecb75f 100644 --- a/src/libs/qmljs/qmljsstaticanalysismessage.cpp +++ b/src/libs/qmljs/qmljsstaticanalysismessage.cpp @@ -71,7 +71,7 @@ static inline QString msgInvalidConstructor(const char *what) StaticAnalysisMessages::StaticAnalysisMessages() { // When changing a message or severity, update the documentation, currently - // in creator-editors.qdoc, accordingly. + // in creator-code-syntax.qdoc, accordingly. newMsg(ErrInvalidEnumValue, Error, tr("Invalid value for enum.")); newMsg(ErrEnumValueMustBeStringOrNumber, Error, @@ -211,36 +211,36 @@ StaticAnalysisMessages::StaticAnalysisMessages() newMsg(ErrInvalidArrayValueLength, Error, tr("%1 elements expected in array value."), 1); newMsg(WarnImperativeCodeNotEditableInVisualDesigner, Warning, - tr("Imperative code is not supported in the Qt Quick Designer.")); + tr("Imperative code is not supported in Qt Design Studio.")); newMsg(WarnUnsupportedTypeInVisualDesigner, Warning, - tr("This type (%1) is not supported in the Qt Quick Designer."), 1); + tr("This type (%1) is not supported in Qt Design Studio."), 1); newMsg(WarnReferenceToParentItemNotSupportedByVisualDesigner, Warning, - tr("Reference to parent item cannot be resolved correctly by the Qt Quick Designer.")); + tr("Reference to parent item cannot be resolved correctly by Qt Design Studio.")); newMsg(WarnUndefinedValueForVisualDesigner, Warning, tr("This visual property binding cannot be evaluated in the local context " - "and might not show up in Qt Quick Designer as expected.")); + "and might not show up in Qt Design Studio as expected.")); newMsg(WarnStatesOnlyInRootItemForVisualDesigner, Warning, - tr("Qt Quick Designer only supports states in the root item.")); + tr("Qt Design Studio only supports states in the root item.")); newMsg(ErrInvalidIdeInVisualDesigner, Error, - tr("This id might be ambiguous and is not supported in the Qt Quick Designer.")); + tr("This id might be ambiguous and is not supported in Qt Design Studio.")); newMsg(ErrUnsupportedRootTypeInVisualDesigner, Error, - tr("This type (%1) is not supported as a root element by Qt Quick Designer."), 1); + tr("This type (%1) is not supported as a root element by Qt Design Studio."), 1); newMsg(ErrUnsupportedRootTypeInQmlUi, Error, - tr("This type (%1) is not supported as a root element of a Qt Quick UI form."), 1); + tr("This type (%1) is not supported as a root element of a UI file (.ui.qml)."), 1); newMsg(ErrUnsupportedTypeInQmlUi, Error, - tr("This type (%1) is not supported in a Qt Quick UI form."), 1); + tr("This type (%1) is not supported in a UI file (.ui.qml)."), 1); newMsg(ErrFunctionsNotSupportedInQmlUi, Error, - tr("Functions are not supported in a Qt Quick UI form.")); + tr("Functions are not supported in a UI file (.ui.qml).")); newMsg(ErrBlocksNotSupportedInQmlUi, Error, - tr("JavaScript blocks are not supported in a Qt Quick UI form.")); + tr("JavaScript blocks are not supported in a UI file (.ui.qml).")); newMsg(ErrBehavioursNotSupportedInQmlUi, Error, - tr("Behavior type is not supported in a Qt Quick UI form.")); + tr("Behavior type is not supported in a UI file (.ui.qml).")); newMsg(ErrStatesOnlyInRootItemInQmlUi, Error, - tr("States are only supported in the root item in a Qt Quick UI form.")); + tr("States are only supported in the root item in a UI file (.ui.qml).")); newMsg(ErrReferenceToParentItemNotSupportedInQmlUi, Error, - tr("Referencing the parent of the root item is not supported in a Qt Quick UI form.")); + tr("Referencing the parent of the root item is not supported in a UI file (.ui.qml).")); newMsg(ErrDoNotMixTranslationFunctionsInQmlUi, Error, - tr("Do not mix translation functions in a Qt Quick UI form.")); + tr("Do not mix translation functions in a UI file (.ui.qml).")); newMsg(StateCannotHaveChildItem, Error, tr("A State cannot have a child item (%1)."), 1); newMsg(WarnDuplicateImport, Warning, @@ -250,7 +250,7 @@ StaticAnalysisMessages::StaticAnalysisMessages() newMsg(ErrTypeIsInstantiatedRecursively, Error, tr("Type cannot be instantiated recursively (%1)."), 1); newMsg(WarnLogicalValueDoesNotDependOnValues, Warning, - tr("Logical value does not depend on actual values")); + tr("Logical value does not depend on actual values.")); newMsg(ErrToManyComponentChildren, Error, tr("Components are only allowed to have a single child element.")); newMsg(WarnComponentRequiresChildren, Warning, From 088d692bb25915c9bc253e6df81c151f92ec0417 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 17 Feb 2022 15:56:36 +0100 Subject: [PATCH 38/76] Editor: fix crash after triggering select all with no search results Change-Id: I32d5172e8b5df6db93053f358c5a72cb8d38f6ea Reviewed-by: Eike Ziller --- src/plugins/texteditor/texteditor.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index fd814163a72..a36caf3befc 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -857,7 +857,10 @@ void TextEditorWidgetFind::selectAll(const QString &txt, FindFlags findFlags) m_selectWatcher = new QFutureWatcher(); connect(m_selectWatcher, &QFutureWatcher::finished, this, [this]() { - const FileSearchResultList &results = m_selectWatcher->result(); + const QFuture future = m_selectWatcher->future(); + if (future.resultCount() <= 0) + return; + const FileSearchResultList &results = future.result(); const QTextCursor c(m_editor->document()); auto cursorForResult = [c](const FileSearchResult &r) { return Utils::Text::selectAt(c, r.lineNumber, r.matchStart + 1, r.matchLength); From 088b926ff43da5f7c7598ee6e8f46fe4e84eb3b6 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Thu, 17 Feb 2022 11:40:44 +0100 Subject: [PATCH 39/76] QmlDesigner: Update supported macOS version Task-number: QDS-6290 Change-Id: I41a0cca5cc0f5113fe3a06e3cb93a7e49b20a341 Reviewed-by: Leena Miettinen --- doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc index bbd1d0ddd86..9935bcfbc4e 100644 --- a/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc +++ b/doc/qtdesignstudio/src/qtdesignstudio-platforms.qdoc @@ -38,7 +38,7 @@ \QDS is available in binary packages for the following operating systems: \list - \li \macOS 10.15 + \li \macOS 11.0 \li Linux: \list \li CentOS 8.1 From a08e0f7a9dab2271aee781fc194e58fb10283462 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 17 Feb 2022 15:54:37 +0100 Subject: [PATCH 40/76] ClangCodeModel: Differentiate between clangd debug output log levels Depending on the kind of highlighting issue we want to debug, we may or may not be interested in the actual tokens. Change-Id: I412126d3e97949a31f1dd5f339dc09072f28be64 Reviewed-by: Reviewed-by: David Schulz --- src/plugins/clangcodemodel/clangdclient.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index ab7a1ae5a06..ef10edd5eb1 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -2854,9 +2854,10 @@ void ClangdClient::Private::handleSemanticTokens(TextDocument *doc, int version, bool force) { SubtaskTimer t(highlightingTimer); - qCDebug(clangdLog) << "handling LSP tokens" << doc->filePath() << tokens.size(); + qCInfo(clangdLogHighlight) << "handling LSP tokens" << doc->filePath() + << version << tokens.size(); if (version != q->documentVersion(doc->filePath())) { - qCDebug(clangdLogHighlight) << "LSP tokens outdated; aborting highlighting procedure" + qCInfo(clangdLogHighlight) << "LSP tokens outdated; aborting highlighting procedure" << version << q->documentVersion(doc->filePath()); return; } @@ -2864,7 +2865,7 @@ void ClangdClient::Private::handleSemanticTokens(TextDocument *doc, const auto previous = previousTokens.find(doc); if (previous != previousTokens.end()) { if (!force && previous->first == tokens && previous->second == version) { - qCDebug(clangdLogHighlight) << "tokens and version same as last time; nothing to do"; + qCInfo(clangdLogHighlight) << "tokens and version same as last time; nothing to do"; return; } previous->first = tokens; @@ -2881,7 +2882,7 @@ void ClangdClient::Private::handleSemanticTokens(TextDocument *doc, if (!q->documentOpen(doc)) return; if (version != q->documentVersion(doc->filePath())) { - qCDebug(clangdLogHighlight) << "AST not up to date; aborting highlighting procedure" + qCInfo(clangdLogHighlight) << "AST not up to date; aborting highlighting procedure" << version << q->documentVersion(doc->filePath()); return; } From 2834e90930cb1ba48a0a19cb32aa071f724f74c1 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Wed, 16 Feb 2022 16:48:28 +0100 Subject: [PATCH 41/76] McuSupport: split mcusupportoptions Several independent classes were mashed together in mcusupportoptions.cpp This patch moves McuToolChainPackage together with McuPackage, McuTarget to its own header+source pair, and McuKitManager to its own header+source pair. Task-number: QTCREATORBUG-26890 Change-Id: I0b51da4e1cae5a976201dffd290a665eaa318b33 Reviewed-by: Alessandro Portale --- src/plugins/mcusupport/CMakeLists.txt | 2 + src/plugins/mcusupport/mcukitmanager.cpp | 596 +++++++++++++++ src/plugins/mcusupport/mcukitmanager.h | 86 +++ src/plugins/mcusupport/mcupackage.cpp | 4 +- src/plugins/mcusupport/mcupackage.h | 7 +- src/plugins/mcusupport/mcusupport.qbs | 4 + src/plugins/mcusupport/mcusupportoptions.cpp | 676 +----------------- src/plugins/mcusupport/mcusupportoptions.h | 90 +-- .../mcusupport/mcusupportoptionspage.cpp | 2 + src/plugins/mcusupport/mcusupportplugin.cpp | 12 + src/plugins/mcusupport/mcusupportplugin.h | 2 + src/plugins/mcusupport/mcusupportsdk.cpp | 3 + src/plugins/mcusupport/mcutarget.cpp | 290 ++++++++ src/plugins/mcusupport/mcutarget.h | 89 +++ src/plugins/mcusupport/test/unittest.cpp | 1 + src/plugins/mcusupport/test/unittest.h | 1 + 16 files changed, 1120 insertions(+), 745 deletions(-) create mode 100644 src/plugins/mcusupport/mcukitmanager.cpp create mode 100644 src/plugins/mcusupport/mcukitmanager.h create mode 100644 src/plugins/mcusupport/mcutarget.cpp create mode 100644 src/plugins/mcusupport/mcutarget.h diff --git a/src/plugins/mcusupport/CMakeLists.txt b/src/plugins/mcusupport/CMakeLists.txt index c82bf2b1f45..6d7602c2f0e 100644 --- a/src/plugins/mcusupport/CMakeLists.txt +++ b/src/plugins/mcusupport/CMakeLists.txt @@ -8,8 +8,10 @@ add_qtc_plugin(McuSupport mcusupportconstants.h mcusupportdevice.cpp mcusupportdevice.h mcusupportoptions.cpp mcusupportoptions.h mcuabstractpackage.h + mcukitmanager.cpp mcukitmanager.h mcusupportoptionspage.cpp mcusupportoptionspage.h mcupackage.cpp mcupackage.h + mcutarget.cpp mcutarget.h mcusupportplugin.cpp mcusupportplugin.h mcusupportsdk.cpp mcusupportsdk.h mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h diff --git a/src/plugins/mcusupport/mcukitmanager.cpp b/src/plugins/mcusupport/mcukitmanager.cpp new file mode 100644 index 00000000000..e142072242d --- /dev/null +++ b/src/plugins/mcusupport/mcukitmanager.cpp @@ -0,0 +1,596 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +#include "mcukitmanager.h" +#include "mcusupportoptions.h" + +#include "mcusupportconstants.h" +#include "mcukitinformation.h" +#include "mcupackage.h" +#include "mcutarget.h" +#include "mcusupportplugin.h" +#include "mcusupportsdk.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using CMakeProjectManager::CMakeConfigItem; +using CMakeProjectManager::CMakeConfigurationKitAspect; +using namespace ProjectExplorer; +using namespace Utils; + +namespace McuSupport { +namespace Internal { +namespace McuKitManager { + +static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change + +static FilePath qulDocsDir() +{ + const FilePath qulDir = McuSupportOptions::qulDirFromSettings(); + if (qulDir.isEmpty() || !qulDir.exists()) + return {}; + const FilePath docsDir = qulDir.pathAppended("docs"); + return docsDir.exists() ? docsDir : FilePath(); +} + +static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage) +{ + switch (tcPackage->type()) { + case McuToolChainPackage::Type::Unsupported: + return; + + case McuToolChainPackage::Type::GHS: + case McuToolChainPackage::Type::GHSArm: + return; // No Green Hills toolchain, because support for it is missing. + + case McuToolChainPackage::Type::IAR: + case McuToolChainPackage::Type::KEIL: + case McuToolChainPackage::Type::MSVC: + case McuToolChainPackage::Type::GCC: + case McuToolChainPackage::Type::ArmGcc: + ToolChainKitAspect::setToolChain(k, + tcPackage->toolChain( + ProjectExplorer::Constants::C_LANGUAGE_ID)); + ToolChainKitAspect::setToolChain(k, + tcPackage->toolChain( + ProjectExplorer::Constants::CXX_LANGUAGE_ID)); + return; + + default: + Q_UNREACHABLE(); + } +} + + +static void setKitProperties(const QString &kitName, + Kit *k, + const McuTarget *mcuTarget, + const FilePath &sdkPath) +{ + using namespace Constants; + + k->setUnexpandedDisplayName(kitName); + k->setValue(KIT_MCUTARGET_VENDOR_KEY, mcuTarget->platform().vendor); + k->setValue(KIT_MCUTARGET_MODEL_KEY, mcuTarget->platform().name); + k->setValue(KIT_MCUTARGET_COLORDEPTH_KEY, mcuTarget->colorDepth()); + k->setValue(KIT_MCUTARGET_SDKVERSION_KEY, mcuTarget->qulVersion().toString()); + k->setValue(KIT_MCUTARGET_KITVERSION_KEY, KIT_VERSION); + k->setValue(KIT_MCUTARGET_OS_KEY, static_cast(mcuTarget->os())); + k->setValue(KIT_MCUTARGET_TOOCHAIN_KEY, mcuTarget->toolChainPackage()->toolChainName()); + k->setAutoDetected(false); + k->makeSticky(); + if (mcuTarget->toolChainPackage()->isDesktopToolchain()) + k->setDeviceTypeForIcon(DEVICE_TYPE); + k->setValue(QtSupport::SuppliesQtQuickImportPath::id(), true); + k->setValue(QtSupport::KitQmlImportPath::id(), sdkPath.pathAppended("include/qul").toVariant()); + k->setValue(QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), true); + QSet irrelevant = { + SysRootKitAspect::id(), + QtSupport::SuppliesQtQuickImportPath::id(), + QtSupport::KitQmlImportPath::id(), + QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), + }; + if (!McuSupportOptions::kitsNeedQtVersion()) + irrelevant.insert(QtSupport::QtKitAspect::id()); + k->setIrrelevantAspects(irrelevant); +} + + +static void setKitDebugger(Kit *k, const McuToolChainPackage *tcPackage) +{ + if (tcPackage->isDesktopToolchain()) { + // Qt Creator seems to be smart enough to deduce the right Kit debugger from the ToolChain + return; + } + + switch (tcPackage->type()) { + case McuToolChainPackage::Type::Unsupported: + case McuToolChainPackage::Type::GHS: + case McuToolChainPackage::Type::GHSArm: + case McuToolChainPackage::Type::IAR: + return; // No Green Hills and IAR debugger, because support for it is missing. + + case McuToolChainPackage::Type::KEIL: + case McuToolChainPackage::Type::MSVC: + case McuToolChainPackage::Type::GCC: + case McuToolChainPackage::Type::ArmGcc: { + const QVariant debuggerId = tcPackage->debuggerId(); + if (debuggerId.isValid()) { + Debugger::DebuggerKitAspect::setDebugger(k, debuggerId); + } + return; + } + + default: + Q_UNREACHABLE(); + } +} + +static void setKitDevice(Kit *k, const McuTarget *mcuTarget) +{ + // "Device Type" Desktop is the default. We use that for the Qt for MCUs Desktop Kit + if (mcuTarget->toolChainPackage()->isDesktopToolchain()) + return; + + DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DEVICE_TYPE); +} + +static bool expectsCmakeVars(const McuTarget *mcuTarget) +{ + return mcuTarget->qulVersion() >= QVersionNumber{2, 0}; +} + +static void setKitDependencies(Kit *k, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) +{ + NameValueItems dependencies; + + auto processPackage = [&dependencies](const McuAbstractPackage *package) { + if (!package->environmentVariableName().isEmpty()) + dependencies.append({package->environmentVariableName(), + QDir::toNativeSeparators(package->detectionPath())}); + }; + for (auto package : mcuTarget->packages()) + processPackage(package); + processPackage(qtForMCUsSdkPackage); + + McuDependenciesKitAspect::setDependencies(k, dependencies); + + auto irrelevant = k->irrelevantAspects(); + irrelevant.insert(McuDependenciesKitAspect::id()); + k->setIrrelevantAspects(irrelevant); +} + +static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePath &qulDir) +{ + using namespace CMakeProjectManager; + + CMakeConfig config = CMakeConfigurationKitAspect::configuration(k); + // CMake ToolChain file for ghs handles CMAKE_*_COMPILER autonomously + if (mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHS + && mcuTarget->toolChainPackage()->type() != McuToolChainPackage::Type::GHSArm) { + config.append(CMakeConfigItem("CMAKE_CXX_COMPILER", "%{Compiler:Executable:Cxx}")); + config.append(CMakeConfigItem("CMAKE_C_COMPILER", "%{Compiler:Executable:C}")); + } + + if (!mcuTarget->toolChainPackage()->isDesktopToolchain()) { + const FilePath cMakeToolchainFile = qulDir.pathAppended( + "lib/cmake/Qul/toolchain/" + mcuTarget->toolChainPackage()->cmakeToolChainFileName()); + + config.append( + CMakeConfigItem("CMAKE_TOOLCHAIN_FILE", cMakeToolchainFile.toString().toUtf8())); + if (!cMakeToolchainFile.exists()) { + printMessage(McuTarget::tr( + "Warning for target %1: missing CMake toolchain file expected at %2.") + .arg(kitName(mcuTarget), + cMakeToolchainFile.toUserOutput()), + false); + } + } + + const FilePath generatorsPath = qulDir.pathAppended("/lib/cmake/Qul/QulGenerators.cmake"); + config.append(CMakeConfigItem("QUL_GENERATORS", generatorsPath.toString().toUtf8())); + if (!generatorsPath.exists()) { + printMessage(McuTarget::tr("Warning for target %1: missing QulGenerators expected at %2.") + .arg(kitName(mcuTarget), generatorsPath.toUserOutput()), + false); + } + + config.append(CMakeConfigItem("QUL_PLATFORM", mcuTarget->platform().name.toUtf8())); + + if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth) + config.append(CMakeConfigItem("QUL_COLOR_DEPTH", + QString::number(mcuTarget->colorDepth()).toLatin1())); + if (McuSupportOptions::kitsNeedQtVersion()) + config.append(CMakeConfigItem("CMAKE_PREFIX_PATH", "%{Qt:QT_INSTALL_PREFIX}")); + CMakeConfigurationKitAspect::setConfiguration(k, config); + + if (HostOsInfo::isWindowsHost()) { + auto type = mcuTarget->toolChainPackage()->type(); + if (type == McuToolChainPackage::Type::GHS || type == McuToolChainPackage::Type::GHSArm) { + // See https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565802&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565802 + // and https://bugreports.qt.io/browse/UL-4247?focusedCommentId=565803&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-565803 + CMakeGeneratorKitAspect::setGenerator(k, "NMake Makefiles JOM"); + } + } +} + +static void setKitQtVersionOptions(Kit *k) +{ + if (!McuSupportOptions::kitsNeedQtVersion()) + QtSupport::QtKitAspect::setQtVersion(k, nullptr); + // else: auto-select a Qt version +} + +QString kitName(const McuTarget *mcuTarget) +{ + const McuToolChainPackage *tcPkg = mcuTarget->toolChainPackage(); + const QString compilerName = tcPkg && !tcPkg->isDesktopToolchain() + ? QString::fromLatin1(" (%1)").arg( + tcPkg->toolChainName().toUpper()) + : ""; + const QString colorDepth = mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth + ? QString::fromLatin1(" %1bpp").arg(mcuTarget->colorDepth()) + : ""; + const QString targetName = mcuTarget->platform().displayName.isEmpty() + ? mcuTarget->platform().name + : mcuTarget->platform().displayName; + return QString::fromLatin1("Qt for MCUs %1.%2 - %3%4%5") + .arg(QString::number(mcuTarget->qulVersion().majorVersion()), + QString::number(mcuTarget->qulVersion().minorVersion()), + targetName, + colorDepth, + compilerName); +} + +QList existingKits(const McuTarget *mcuTarget) +{ + using namespace Constants; + return Utils::filtered(KitManager::kits(), [mcuTarget](Kit *kit) { + return kit->value(KIT_MCUTARGET_KITVERSION_KEY) == KIT_VERSION + && (!mcuTarget + || (kit->value(KIT_MCUTARGET_VENDOR_KEY) == mcuTarget->platform().vendor + && kit->value(KIT_MCUTARGET_MODEL_KEY) == mcuTarget->platform().name + && kit->value(KIT_MCUTARGET_COLORDEPTH_KEY) == mcuTarget->colorDepth() + && kit->value(KIT_MCUTARGET_OS_KEY).toInt() + == static_cast(mcuTarget->os()) + && kit->value(KIT_MCUTARGET_TOOCHAIN_KEY) + == mcuTarget->toolChainPackage()->toolChainName())); + }); +} + +QList matchingKits(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) +{ + return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { + return kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); + }); +} + +QList upgradeableKits(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) +{ + return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { + return !kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); + }); +} + +QList kitsWithMismatchedDependencies(const McuTarget *mcuTarget) +{ + return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) { + const auto environment = Utils::NameValueDictionary( + Utils::NameValueItem::toStringList(EnvironmentKitAspect::environmentChanges(kit))); + return Utils::anyOf(mcuTarget->packages(), + [&environment](const McuAbstractPackage *package) { + return !package->environmentVariableName().isEmpty() + && environment.value(package->environmentVariableName()) + != package->path().toUserOutput(); + }); + }); +} + +QList outdatedKits() +{ + return Utils::filtered(KitManager::kits(), [](Kit *kit) { + return !kit->value(Constants::KIT_MCUTARGET_VENDOR_KEY).isNull() + && kit->value(Constants::KIT_MCUTARGET_KITVERSION_KEY) != KIT_VERSION; + }); +} + +void removeOutdatedKits() +{ + for (auto kit : outdatedKits()) + KitManager::deregisterKit(kit); +} + +Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) +{ + const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) { + KitGuard kitGuard(k); + + setKitProperties(kitName(mcuTarget), k, mcuTarget, qtForMCUsSdk->path()); + setKitDevice(k, mcuTarget); + setKitToolchains(k, mcuTarget->toolChainPackage()); + setKitDebugger(k, mcuTarget->toolChainPackage()); + McuSupportOptions::setKitEnvironment(k, mcuTarget, qtForMCUsSdk); + setKitDependencies(k, mcuTarget, qtForMCUsSdk); + setKitCMakeOptions(k, mcuTarget, qtForMCUsSdk->path()); + setKitQtVersionOptions(k); + + k->setup(); + k->fix(); + }; + + return KitManager::registerKit(init); +} + +QVersionNumber kitQulVersion(const Kit *kit) +{ + return QVersionNumber::fromString( + kit->value(McuSupport::Constants::KIT_MCUTARGET_SDKVERSION_KEY).toString()); +} + +static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) +{ + for (const NameValueItem &nameValueItem : EnvironmentKitAspect::environmentChanges(kit)) { + if (nameValueItem.name == variableName) + return FilePath::fromUserInput(nameValueItem.value); + } + return FilePath(); +} + +bool kitIsUpToDate(const Kit *kit, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage) +{ + return kitQulVersion(kit) == mcuTarget->qulVersion() + && kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput() + == qtForMCUsSdkPackage->path().toUserOutput(); +} + +void createAutomaticKits() +{ + auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); + + const auto createKits = [qtForMCUsPackage]() { + if (qtForMCUsPackage->automaticKitCreationEnabled()) { + qtForMCUsPackage->updateStatus(); + if (!qtForMCUsPackage->validStatus()) { + switch (qtForMCUsPackage->status()) { + case McuAbstractPackage::Status::ValidPathInvalidPackage: { + const QString displayPath + = FilePath::fromString(qtForMCUsPackage->detectionPath()).toUserOutput(); + printMessage(McuPackage::tr("Path %1 exists, but does not contain %2.") + .arg(qtForMCUsPackage->path().toUserOutput(), displayPath), + true); + break; + } + case McuAbstractPackage::Status::InvalidPath: { + printMessage(McuPackage::tr("Path %1 does not exist. Add the path in Tools > Options > " + "Devices > MCU.") + .arg(qtForMCUsPackage->path().toUserOutput()), + true); + break; + } + case McuAbstractPackage::Status::EmptyPath: { + printMessage(McuPackage::tr("Missing %1. Add the path in Tools > Options > Devices > MCU.") + .arg(qtForMCUsPackage->detectionPath()), + true); + return; + } + default: + break; + } + return; + } + + if (CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty()) { + printMessage(McuPackage::tr("No CMake tool was detected. Add a CMake tool in Tools > Options > " + "Kits > CMake."), + true); + return; + } + + FilePath dir = qtForMCUsPackage->path(); + McuSdkRepository repo; + Sdk::targetsAndPackages(dir, &repo); + + bool needsUpgrade = false; + for (const auto &target : qAsConst(repo.mcuTargets)) { + // if kit already exists, skip + if (!matchingKits(target, qtForMCUsPackage).empty()) + continue; + if (!upgradeableKits(target, qtForMCUsPackage).empty()) { + // if kit exists but wrong version/path + needsUpgrade = true; + } else { + // if no kits for this target, create + if (target->isValid()) + newKit(target, qtForMCUsPackage); + target->printPackageProblems(); + } + } + + repo.deletePackagesAndTargets(); + + if (needsUpgrade) + McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade(); + } + }; + + createKits(); + delete qtForMCUsPackage; +} + +void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption) +{ + if (upgradeOption == UpgradeOption::Ignore) + return; + + auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); + + auto dir = qtForMCUsPackage->path(); + McuSdkRepository repo; + Sdk::targetsAndPackages(dir, &repo); + + for (const auto &target : qAsConst(repo.mcuTargets)) { + if (!matchingKits(target, qtForMCUsPackage).empty()) + // already up-to-date + continue; + + const auto kits = upgradeableKits(target, qtForMCUsPackage); + if (!kits.empty()) { + if (upgradeOption == UpgradeOption::Replace) { + for (auto existingKit : kits) + KitManager::deregisterKit(existingKit); + } + + if (target->isValid()) + newKit(target, qtForMCUsPackage); + target->printPackageProblems(); + } + } + + repo.deletePackagesAndTargets(); + delete qtForMCUsPackage; +} + +void upgradeKitInPlace(ProjectExplorer::Kit *kit, + const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdk) +{ + setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path()); + McuSupportOptions::setKitEnvironment(kit, mcuTarget, qtForMCUsSdk); + setKitDependencies(kit, mcuTarget, qtForMCUsSdk); +} + +void fixKitsDependencies() +{ + auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); + + FilePath dir = qtForMCUsPackage->path(); + McuSdkRepository repo; + Sdk::targetsAndPackages(dir, &repo); + for (const auto &target : qAsConst(repo.mcuTargets)) { + if (target->isValid()) { + for (auto *kit : kitsWithMismatchedDependencies(target)) { + McuSupportOptions::updateKitEnvironment(kit, target); + } + } + } + + repo.deletePackagesAndTargets(); + delete qtForMCUsPackage; +} + +/** + * @brief Fix/update existing kits if needed + */ +void fixExistingKits() +{ + for (Kit *kit : KitManager::kits()) { + if (!kit->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY)) + continue; + + if (kit->isAutoDetected()) { + kit->setAutoDetected(false); + } + + // Check if the MCU kits are flagged as supplying a QtQuick import path, in order + // to tell the QMLJS code-model that it won't need to add a fall-back import + // path. + const auto bringsQtQuickImportPath = QtSupport::SuppliesQtQuickImportPath::id(); + auto irrelevantAspects = kit->irrelevantAspects(); + if (!irrelevantAspects.contains(bringsQtQuickImportPath)) { + irrelevantAspects.insert(bringsQtQuickImportPath); + kit->setIrrelevantAspects(irrelevantAspects); + } + if (!kit->hasValue(bringsQtQuickImportPath)) { + kit->setValue(bringsQtQuickImportPath, true); + } + + // Check if the MCU kit supplies its import path. + const auto kitQmlImportPath = QtSupport::KitQmlImportPath::id(); + if (!irrelevantAspects.contains(kitQmlImportPath)) { + irrelevantAspects.insert(kitQmlImportPath); + kit->setIrrelevantAspects(irrelevantAspects); + } + if (!kit->hasValue(kitQmlImportPath)) { + auto config = CMakeProjectManager::CMakeConfigurationKitAspect::configuration(kit); + for (const auto &cfgItem : qAsConst(config)) { + if (cfgItem.key == "QUL_GENERATORS") { + auto idx = cfgItem.value.indexOf("/lib/cmake/Qul"); + auto qulDir = cfgItem.value.left(idx); + kit->setValue(kitQmlImportPath, QVariant(qulDir + "/include/qul")); + break; + } + } + } + + // Check if the MCU kit has the flag for merged header/qml-import paths set. + const auto mergedPaths = QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(); + if (!irrelevantAspects.contains(mergedPaths)) { + irrelevantAspects.insert(mergedPaths); + kit->setIrrelevantAspects(irrelevantAspects); + } + if (!kit->value(mergedPaths, false).toBool()) { + kit->setValue(mergedPaths, true); + } + } + + // Fix kit dependencies for known targets + auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); + qtForMCUsPackage->updateStatus(); + if (qtForMCUsPackage->validStatus()) { + FilePath dir = qtForMCUsPackage->path(); + McuSdkRepository repo; + Sdk::targetsAndPackages(dir, &repo); + for (const auto &target : qAsConst(repo.mcuTargets)) + for (auto kit : existingKits(target)) { + if (McuDependenciesKitAspect::dependencies(kit).isEmpty()) { + setKitDependencies(kit, target, qtForMCUsPackage); + } + } + + repo.deletePackagesAndTargets(); + } + delete qtForMCUsPackage; +} + +} // namespace McuKitManager +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/mcukitmanager.h b/src/plugins/mcusupport/mcukitmanager.h new file mode 100644 index 00000000000..1814fb26432 --- /dev/null +++ b/src/plugins/mcusupport/mcukitmanager.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +#pragma once + +#include +#include "mcusupport_global.h" + +#include +#include +#include +#include + +namespace ProjectExplorer { +class Kit; +} // namespace ProjectExplorer + +namespace McuSupport { +namespace Internal { + +class McuAbstractPackage; +class McuToolChainPackage; +class McuTarget; + +namespace McuKitManager +{ + enum class UpgradeOption { + Ignore, + Keep, + Replace + }; + + // Creating kits: + ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); + void createAutomaticKits(); + + // Querying the kits: + QList existingKits(const McuTarget *mcuTarget); + QList matchingKits(const McuTarget *mcuTarget, + const McuAbstractPackage *qtForMCUsSdkPackage); + QList upgradeableKits( + const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); + QList kitsWithMismatchedDependencies(const McuTarget *mcuTarget); + + // Upgrading kits: + void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption); + void upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); + + // Fixing kits: + void fixKitsDependencies(); + void fixExistingKits(); + + // Outdated kits: + QList outdatedKits(); + void removeOutdatedKits(); + + // Querying kits: + QString kitName(const McuTarget* mcuTarget); + QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit); + bool kitIsUpToDate(const ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); + +} // namespace McuKitManager +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/mcupackage.cpp b/src/plugins/mcusupport/mcupackage.cpp index b27752e79e2..ed963652edb 100644 --- a/src/plugins/mcusupport/mcupackage.cpp +++ b/src/plugins/mcusupport/mcupackage.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,6 +25,7 @@ #include "mcupackage.h" #include "mcusupportconstants.h" +#include "mcusupportversiondetection.h" #include "mcusupportsdk.h" #include @@ -314,4 +315,5 @@ bool McuToolChainPackage::isDesktopToolchain() const return m_type == Type::MSVC || m_type == Type::GCC; } + } // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/mcupackage.h b/src/plugins/mcusupport/mcupackage.h index 5afa32e009f..f2d6aa5276d 100644 --- a/src/plugins/mcusupport/mcupackage.h +++ b/src/plugins/mcusupport/mcupackage.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -26,10 +26,8 @@ #pragma once #include "mcuabstractpackage.h" -#include "mcusupportversiondetection.h" #include -#include #include @@ -42,11 +40,14 @@ class ToolChain; namespace Utils { class PathChooser; class InfoLabel; +class Id; } // namespace Utils namespace McuSupport { namespace Internal { +class McuPackageVersionDetector; + class McuPackage : public McuAbstractPackage { Q_OBJECT diff --git a/src/plugins/mcusupport/mcusupport.qbs b/src/plugins/mcusupport/mcusupport.qbs index 1710166a975..b7b8e146102 100644 --- a/src/plugins/mcusupport/mcusupport.qbs +++ b/src/plugins/mcusupport/mcusupport.qbs @@ -18,6 +18,8 @@ QtcPlugin { "mcuabstractpackage.h", "mcupackage.cpp", "mcupackage.h", + "mcutarget.cpp", + "mcutarget.h", "mcusupport.qrc", "mcusupport_global.h", "mcusupportconstants.h", @@ -25,6 +27,8 @@ QtcPlugin { "mcusupportdevice.h", "mcusupportoptions.cpp", "mcusupportoptions.h", + "mcukitmanager.cpp", + "mcukitmanager.h", "mcusupportoptionspage.cpp", "mcusupportoptionspage.h", "mcusupportplugin.cpp", diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index f9972473613..8d8721323b9 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -25,47 +25,26 @@ #include "mcusupportoptions.h" -#include "mcukitinformation.h" #include "mcupackage.h" +#include "mcutarget.h" +#include "mcukitmanager.h" +#include "mcukitinformation.h" #include "mcusupportcmakemapper.h" #include "mcusupportconstants.h" -#include "mcusupportplugin.h" #include "mcusupportsdk.h" +#include "mcusupportplugin.h" -#include #include #include #include #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include #include #include -#include -#include -#include using CMakeProjectManager::CMakeConfigItem; using CMakeProjectManager::CMakeConfigurationKitAspect; @@ -75,261 +54,6 @@ using namespace Utils; namespace McuSupport { namespace Internal { -static const int KIT_VERSION = 9; // Bumps up whenever details in Kit creation change - -static bool kitNeedsQtVersion() -{ - // Only on Windows, Qt is linked into the distributed qul Desktop libs. Also, the host tools - // are missing the Qt runtime libraries on non-Windows. - return !HostOsInfo::isWindowsHost(); -} - -static ToolChain *msvcToolChain(Id language) -{ - ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { - const Abi abi = t->targetAbi(); - // TODO: Should Abi::WindowsMsvc2022Flavor be added too? - return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor - || abi.osFlavor() == Abi::WindowsMsvc2019Flavor) - && abi.architecture() == Abi::X86Architecture && abi.wordWidth() == 64 - && t->language() == language; - }); - return toolChain; -} - -static ToolChain *gccToolChain(Id language) -{ - ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { - const Abi abi = t->targetAbi(); - return abi.os() != Abi::WindowsOS && abi.architecture() == Abi::X86Architecture - && abi.wordWidth() == 64 && t->language() == language; - }); - return toolChain; -} - -static ToolChain *armGccToolChain(const FilePath &path, Id language) -{ - ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t) { - return t->compilerCommand() == path && t->language() == language; - }); - if (!toolChain) { - ToolChainFactory *gccFactory - = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), - [](ToolChainFactory *f) { - return f->supportedToolChainType() - == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; - }); - if (gccFactory) { - const QList detected = gccFactory->detectForImport({path, language}); - if (!detected.isEmpty()) { - toolChain = detected.first(); - toolChain->setDetection(ToolChain::ManualDetection); - toolChain->setDisplayName("Arm GCC"); - ToolChainManager::registerToolChain(toolChain); - } - } - } - - return toolChain; -} - -static ToolChain *iarToolChain(const FilePath &path, Id language) -{ - ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { - return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID - && t->language() == language; - }); - if (!toolChain) { - ToolChainFactory *iarFactory - = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), - [](ToolChainFactory *f) { - return f->supportedToolChainType() - == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID; - }); - if (iarFactory) { - Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {})); - if (detected.isEmpty()) - detected = iarFactory->detectForImport({path, language}); - for (auto tc : detected) { - if (tc->language() == language) { - toolChain = tc; - toolChain->setDetection(ToolChain::ManualDetection); - toolChain->setDisplayName("IAREW"); - ToolChainManager::registerToolChain(toolChain); - } - } - } - } - - return toolChain; -} - -ToolChain *McuToolChainPackage::toolChain(Id language) const -{ - switch (m_type) { - case Type::MSVC: - return msvcToolChain(language); - case Type::GCC: - return gccToolChain(language); - case Type::IAR: { - const FilePath compiler = path().pathAppended("/bin/iccarm").withExecutableSuffix(); - return iarToolChain(compiler, language); - } - case Type::ArmGcc: - case Type::KEIL: - case Type::GHS: - case Type::GHSArm: - case Type::Unsupported: { - const QLatin1String compilerName( - language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++"); - const QString comp = QLatin1String(m_type == Type::ArmGcc ? "/bin/arm-none-eabi-%1" - : "/bar/foo-keil-%1") - .arg(compilerName); - const FilePath compiler = path().pathAppended(comp).withExecutableSuffix(); - - return armGccToolChain(compiler, language); - } - default: - Q_UNREACHABLE(); - } -} - -QString McuToolChainPackage::toolChainName() const -{ - switch (m_type) { - case Type::ArmGcc: - return QLatin1String("armgcc"); - case Type::IAR: - return QLatin1String("iar"); - case Type::KEIL: - return QLatin1String("keil"); - case Type::GHS: - return QLatin1String("ghs"); - case Type::GHSArm: - return QLatin1String("ghs-arm"); - default: - return QLatin1String("unsupported"); - } -} - -QString McuToolChainPackage::cmakeToolChainFileName() const -{ - return toolChainName() + QLatin1String(".cmake"); -} - -QVariant McuToolChainPackage::debuggerId() const -{ - using namespace Debugger; - - QString sub, displayName; - DebuggerEngineType engineType; - - switch (m_type) { - case Type::ArmGcc: { - sub = QString::fromLatin1("bin/arm-none-eabi-gdb-py"); - displayName = McuPackage::tr("Arm GDB at %1"); - engineType = Debugger::GdbEngineType; - break; - } - case Type::IAR: { - sub = QString::fromLatin1("../common/bin/CSpyBat"); - displayName = QLatin1String("CSpy"); - engineType = Debugger::NoEngineType; // support for IAR missing - break; - } - case Type::KEIL: { - sub = QString::fromLatin1("UV4/UV4"); - displayName = QLatin1String("KEIL uVision Debugger"); - engineType = Debugger::UvscEngineType; - break; - } - default: - return QVariant(); - } - - const FilePath command = path().pathAppended(sub).withExecutableSuffix(); - if (const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command)) { - return debugger->id(); - } - - DebuggerItem newDebugger; - newDebugger.setCommand(command); - newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput())); - newDebugger.setEngineType(engineType); - return DebuggerItemManager::registerDebugger(newDebugger); -} - -McuTarget::McuTarget(const QVersionNumber &qulVersion, - const Platform &platform, - OS os, - const QVector &packages, - const McuToolChainPackage *toolChainPackage, - int colorDepth) - : m_qulVersion(qulVersion) - , m_platform(platform) - , m_os(os) - , m_packages(packages) - , m_toolChainPackage(toolChainPackage) - , m_colorDepth(colorDepth) -{} - -const QVector &McuTarget::packages() const -{ - return m_packages; -} - -const McuToolChainPackage *McuTarget::toolChainPackage() const -{ - return m_toolChainPackage; -} - -McuTarget::OS McuTarget::os() const -{ - return m_os; -} - -const McuTarget::Platform &McuTarget::platform() const -{ - return m_platform; -} - -bool McuTarget::isValid() const -{ - return Utils::allOf(packages(), [](McuAbstractPackage *package) { - package->updateStatus(); - return package->validStatus(); - }); -} - -void McuTarget::printPackageProblems() const -{ - for (auto package : packages()) { - package->updateStatus(); - if (!package->validStatus()) - printMessage(tr("Error creating kit for target %1, package %2: %3") - .arg(McuKitManager::kitName(this), - package->label(), - package->statusText()), - true); - if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion) - printMessage(tr("Warning creating kit for target %1, package %2: %3") - .arg(McuKitManager::kitName(this), - package->label(), - package->statusText()), - false); - } -} - -const QVersionNumber &McuTarget::qulVersion() const -{ - return m_qulVersion; -} - -int McuTarget::colorDepth() const -{ - return m_colorDepth; -} - void McuSdkRepository::deletePackagesAndTargets() { qDeleteAll(packages); @@ -423,39 +147,6 @@ FilePath McuSupportOptions::qulDirFromSettings() QSettings::UserScope, {}); } -static void setKitProperties(const QString &kitName, - Kit *k, - const McuTarget *mcuTarget, - const FilePath &sdkPath) -{ - using namespace Constants; - - k->setUnexpandedDisplayName(kitName); - k->setValue(KIT_MCUTARGET_VENDOR_KEY, mcuTarget->platform().vendor); - k->setValue(KIT_MCUTARGET_MODEL_KEY, mcuTarget->platform().name); - k->setValue(KIT_MCUTARGET_COLORDEPTH_KEY, mcuTarget->colorDepth()); - k->setValue(KIT_MCUTARGET_SDKVERSION_KEY, mcuTarget->qulVersion().toString()); - k->setValue(KIT_MCUTARGET_KITVERSION_KEY, KIT_VERSION); - k->setValue(KIT_MCUTARGET_OS_KEY, static_cast(mcuTarget->os())); - k->setValue(KIT_MCUTARGET_TOOCHAIN_KEY, mcuTarget->toolChainPackage()->toolChainName()); - k->setAutoDetected(false); - k->makeSticky(); - if (mcuTarget->toolChainPackage()->isDesktopToolchain()) - k->setDeviceTypeForIcon(DEVICE_TYPE); - k->setValue(QtSupport::SuppliesQtQuickImportPath::id(), true); - k->setValue(QtSupport::KitQmlImportPath::id(), sdkPath.pathAppended("include/qul").toVariant()); - k->setValue(QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), true); - QSet irrelevant = { - SysRootKitAspect::id(), - QtSupport::SuppliesQtQuickImportPath::id(), - QtSupport::KitQmlImportPath::id(), - QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(), - }; - if (!kitNeedsQtVersion()) - irrelevant.insert(QtSupport::QtKitAspect::id()); - k->setIrrelevantAspects(irrelevant); -} - void McuSupportOptions::remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems) { const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems); @@ -567,7 +258,7 @@ void McuSupportOptions::setKitEnvironment(Kit *k, processPackage(package); processPackage(qtForMCUsSdkPackage); - if (kitNeedsQtVersion()) + if (McuSupportOptions::kitsNeedQtVersion()) changes.append({QLatin1String("LD_LIBRARY_PATH"), "%{Qt:QT_INSTALL_LIBS}"}); // Hack, this problem should be solved in lower layer @@ -666,7 +357,7 @@ static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePat if (mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth) config.append(CMakeConfigItem("QUL_COLOR_DEPTH", QString::number(mcuTarget->colorDepth()).toLatin1())); - if (kitNeedsQtVersion()) + if (McuSupportOptions::kitsNeedQtVersion()) config.append(CMakeConfigItem("CMAKE_PREFIX_PATH", "%{Qt:QT_INSTALL_PREFIX}")); CMakeConfigurationKitAspect::setConfiguration(k, config); @@ -682,129 +373,11 @@ static void setKitCMakeOptions(Kit *k, const McuTarget *mcuTarget, const FilePat static void setKitQtVersionOptions(Kit *k) { - if (!kitNeedsQtVersion()) + if (!McuSupportOptions::kitsNeedQtVersion()) QtSupport::QtKitAspect::setQtVersion(k, nullptr); // else: auto-select a Qt version } -QString McuKitManager::kitName(const McuTarget *mcuTarget) -{ - const McuToolChainPackage *tcPkg = mcuTarget->toolChainPackage(); - const QString compilerName = tcPkg && !tcPkg->isDesktopToolchain() - ? QString::fromLatin1(" (%1)").arg( - tcPkg->toolChainName().toUpper()) - : ""; - const QString colorDepth = mcuTarget->colorDepth() != McuTarget::UnspecifiedColorDepth - ? QString::fromLatin1(" %1bpp").arg(mcuTarget->colorDepth()) - : ""; - const QString targetName = mcuTarget->platform().displayName.isEmpty() - ? mcuTarget->platform().name - : mcuTarget->platform().displayName; - return QString::fromLatin1("Qt for MCUs %1.%2 - %3%4%5") - .arg(QString::number(mcuTarget->qulVersion().majorVersion()), - QString::number(mcuTarget->qulVersion().minorVersion()), - targetName, - colorDepth, - compilerName); -} - -QList McuKitManager::existingKits(const McuTarget *mcuTarget) -{ - using namespace Constants; - return Utils::filtered(KitManager::kits(), [mcuTarget](Kit *kit) { - return kit->value(KIT_MCUTARGET_KITVERSION_KEY) == KIT_VERSION - && (!mcuTarget - || (kit->value(KIT_MCUTARGET_VENDOR_KEY) == mcuTarget->platform().vendor - && kit->value(KIT_MCUTARGET_MODEL_KEY) == mcuTarget->platform().name - && kit->value(KIT_MCUTARGET_COLORDEPTH_KEY) == mcuTarget->colorDepth() - && kit->value(KIT_MCUTARGET_OS_KEY).toInt() - == static_cast(mcuTarget->os()) - && kit->value(KIT_MCUTARGET_TOOCHAIN_KEY) - == mcuTarget->toolChainPackage()->toolChainName())); - }); -} - -QList McuKitManager::matchingKits(const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage) -{ - return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { - return kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); - }); -} - -QList McuKitManager::upgradeableKits(const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage) -{ - return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) { - return !kitIsUpToDate(kit, mcuTarget, qtForMCUsSdkPackage); - }); -} - -QList McuKitManager::kitsWithMismatchedDependencies(const McuTarget *mcuTarget) -{ - return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) { - const auto environment = Utils::NameValueDictionary( - Utils::NameValueItem::toStringList(EnvironmentKitAspect::environmentChanges(kit))); - return Utils::anyOf(mcuTarget->packages(), - [&environment](const McuAbstractPackage *package) { - return !package->environmentVariableName().isEmpty() - && environment.value(package->environmentVariableName()) - != package->path().toUserOutput(); - }); - }); -} - -QList McuKitManager::outdatedKits() -{ - return Utils::filtered(KitManager::kits(), [](Kit *kit) { - return !kit->value(Constants::KIT_MCUTARGET_VENDOR_KEY).isNull() - && kit->value(Constants::KIT_MCUTARGET_KITVERSION_KEY) != KIT_VERSION; - }); -} - -void McuKitManager::removeOutdatedKits() -{ - for (auto kit : outdatedKits()) - KitManager::deregisterKit(kit); -} - -Kit *McuKitManager::newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk) -{ - const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) { - KitGuard kitGuard(k); - - setKitProperties(kitName(mcuTarget), k, mcuTarget, qtForMCUsSdk->path()); - setKitDevice(k, mcuTarget); - setKitToolchains(k, mcuTarget->toolChainPackage()); - setKitDebugger(k, mcuTarget->toolChainPackage()); - McuSupportOptions::setKitEnvironment(k, mcuTarget, qtForMCUsSdk); - setKitDependencies(k, mcuTarget, qtForMCUsSdk); - setKitCMakeOptions(k, mcuTarget, qtForMCUsSdk->path()); - setKitQtVersionOptions(k); - - k->setup(); - k->fix(); - }; - - return KitManager::registerKit(init); -} - -void printMessage(const QString &message, bool important) -{ - const QString displayMessage = QCoreApplication::translate("QtForMCUs", "Qt for MCUs: %1") - .arg(message); - if (important) - Core::MessageManager::writeFlashing(displayMessage); - else - Core::MessageManager::writeSilently(displayMessage); -} - -QVersionNumber McuKitManager::kitQulVersion(const Kit *kit) -{ - return QVersionNumber::fromString( - kit->value(McuSupport::Constants::KIT_MCUTARGET_SDKVERSION_KEY).toString()); -} - static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) { for (const NameValueItem &nameValueItem : EnvironmentKitAspect::environmentChanges(kit)) { @@ -814,21 +387,7 @@ static FilePath kitDependencyPath(const Kit *kit, const QString &variableName) return FilePath(); } -bool McuKitManager::kitIsUpToDate(const Kit *kit, - const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage) -{ - return kitQulVersion(kit) == mcuTarget->qulVersion() - && kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput() - == qtForMCUsSdkPackage->path().toUserOutput(); -} - -void McuSupportOptions::deletePackagesAndTargets() -{ - sdkRepository.deletePackagesAndTargets(); -} - -McuKitManager::UpgradeOption McuKitManager::askForKitUpgrades() +McuKitManager::UpgradeOption McuSupportOptions::askForKitUpgrades() { QMessageBox upgradePopup(Core::ICore::dialogParent()); upgradePopup.setStandardButtons(QMessageBox::Cancel); @@ -841,88 +400,21 @@ McuKitManager::UpgradeOption McuKitManager::askForKitUpgrades() upgradePopup.exec(); if (upgradePopup.clickedButton() == keepButton) - return UpgradeOption::Keep; + return McuKitManager::UpgradeOption::Keep; if (upgradePopup.clickedButton() == replaceButton) - return UpgradeOption::Replace; + return McuKitManager::UpgradeOption::Replace; - return UpgradeOption::Ignore; + return McuKitManager::UpgradeOption::Ignore; } -void McuKitManager::createAutomaticKits() + +void McuSupportOptions::deletePackagesAndTargets() { - auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); - - const auto createKits = [qtForMCUsPackage]() { - if (qtForMCUsPackage->automaticKitCreationEnabled()) { - qtForMCUsPackage->updateStatus(); - if (!qtForMCUsPackage->validStatus()) { - switch (qtForMCUsPackage->status()) { - case McuAbstractPackage::Status::ValidPathInvalidPackage: { - const QString displayPath - = FilePath::fromString(qtForMCUsPackage->detectionPath()).toUserOutput(); - printMessage(tr("Path %1 exists, but does not contain %2.") - .arg(qtForMCUsPackage->path().toUserOutput(), displayPath), - true); - break; - } - case McuAbstractPackage::Status::InvalidPath: { - printMessage(tr("Path %1 does not exist. Add the path in Tools > Options > " - "Devices > MCU.") - .arg(qtForMCUsPackage->path().toUserOutput()), - true); - break; - } - case McuAbstractPackage::Status::EmptyPath: { - printMessage(tr("Missing %1. Add the path in Tools > Options > Devices > MCU.") - .arg(qtForMCUsPackage->detectionPath()), - true); - return; - } - default: - break; - } - return; - } - - if (CMakeProjectManager::CMakeToolManager::cmakeTools().isEmpty()) { - printMessage(tr("No CMake tool was detected. Add a CMake tool in Tools > Options > " - "Kits > CMake."), - true); - return; - } - - FilePath dir = qtForMCUsPackage->path(); - McuSdkRepository repo; - Sdk::targetsAndPackages(dir, &repo); - - bool needsUpgrade = false; - for (const auto &target : qAsConst(repo.mcuTargets)) { - // if kit already exists, skip - if (!matchingKits(target, qtForMCUsPackage).empty()) - continue; - if (!upgradeableKits(target, qtForMCUsPackage).empty()) { - // if kit exists but wrong version/path - needsUpgrade = true; - } else { - // if no kits for this target, create - if (target->isValid()) - newKit(target, qtForMCUsPackage); - target->printPackageProblems(); - } - } - - repo.deletePackagesAndTargets(); - - if (needsUpgrade) - McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade(); - } - }; - - createKits(); - delete qtForMCUsPackage; + sdkRepository.deletePackagesAndTargets(); } + void McuSupportOptions::checkUpgradeableKits() { if (!qtForMCUsSdkPackage->validStatus() || sdkRepository.mcuTargets.length() == 0) @@ -932,142 +424,14 @@ void McuSupportOptions::checkUpgradeableKits() return !McuKitManager::upgradeableKits(target, this->qtForMCUsSdkPackage).empty() && McuKitManager::matchingKits(target, this->qtForMCUsSdkPackage).empty(); })) - McuKitManager::upgradeKitsByCreatingNewPackage(McuKitManager::askForKitUpgrades()); + McuKitManager::upgradeKitsByCreatingNewPackage(askForKitUpgrades()); } -void McuKitManager::upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption) +bool McuSupportOptions::kitsNeedQtVersion() { - if (upgradeOption == UpgradeOption::Ignore) - return; - - auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); - - auto dir = qtForMCUsPackage->path(); - McuSdkRepository repo; - Sdk::targetsAndPackages(dir, &repo); - - for (const auto &target : qAsConst(repo.mcuTargets)) { - if (!McuKitManager::matchingKits(target, qtForMCUsPackage).empty()) - // already up-to-date - continue; - - const auto kits = McuKitManager::upgradeableKits(target, qtForMCUsPackage); - if (!kits.empty()) { - if (upgradeOption == UpgradeOption::Replace) { - for (auto existingKit : kits) - KitManager::deregisterKit(existingKit); - } - - if (target->isValid()) - newKit(target, qtForMCUsPackage); - target->printPackageProblems(); - } - } - - repo.deletePackagesAndTargets(); - delete qtForMCUsPackage; -} - -void McuKitManager::upgradeKitInPlace(ProjectExplorer::Kit *kit, - const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdk) -{ - setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path()); - McuSupportOptions::setKitEnvironment(kit, mcuTarget, qtForMCUsSdk); - setKitDependencies(kit, mcuTarget, qtForMCUsSdk); -} - -void McuKitManager::fixKitsDependencies() -{ - auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); - - FilePath dir = qtForMCUsPackage->path(); - McuSdkRepository repo; - Sdk::targetsAndPackages(dir, &repo); - for (const auto &target : qAsConst(repo.mcuTargets)) { - if (target->isValid()) { - for (auto *kit : kitsWithMismatchedDependencies(target)) { - McuSupportOptions::updateKitEnvironment(kit, target); - } - } - } - - repo.deletePackagesAndTargets(); - delete qtForMCUsPackage; -} - -/** - * @brief Fix/update existing kits if needed - */ -void McuKitManager::fixExistingKits() -{ - for (Kit *kit : KitManager::kits()) { - if (!kit->hasValue(Constants::KIT_MCUTARGET_KITVERSION_KEY)) - continue; - - if (kit->isAutoDetected()) { - kit->setAutoDetected(false); - } - - // Check if the MCU kits are flagged as supplying a QtQuick import path, in order - // to tell the QMLJS code-model that it won't need to add a fall-back import - // path. - const auto bringsQtQuickImportPath = QtSupport::SuppliesQtQuickImportPath::id(); - auto irrelevantAspects = kit->irrelevantAspects(); - if (!irrelevantAspects.contains(bringsQtQuickImportPath)) { - irrelevantAspects.insert(bringsQtQuickImportPath); - kit->setIrrelevantAspects(irrelevantAspects); - } - if (!kit->hasValue(bringsQtQuickImportPath)) { - kit->setValue(bringsQtQuickImportPath, true); - } - - // Check if the MCU kit supplies its import path. - const auto kitQmlImportPath = QtSupport::KitQmlImportPath::id(); - if (!irrelevantAspects.contains(kitQmlImportPath)) { - irrelevantAspects.insert(kitQmlImportPath); - kit->setIrrelevantAspects(irrelevantAspects); - } - if (!kit->hasValue(kitQmlImportPath)) { - auto config = CMakeProjectManager::CMakeConfigurationKitAspect::configuration(kit); - for (const auto &cfgItem : qAsConst(config)) { - if (cfgItem.key == "QUL_GENERATORS") { - auto idx = cfgItem.value.indexOf("/lib/cmake/Qul"); - auto qulDir = cfgItem.value.left(idx); - kit->setValue(kitQmlImportPath, QVariant(qulDir + "/include/qul")); - break; - } - } - } - - // Check if the MCU kit has the flag for merged header/qml-import paths set. - const auto mergedPaths = QtSupport::KitHasMergedHeaderPathsWithQmlImportPaths::id(); - if (!irrelevantAspects.contains(mergedPaths)) { - irrelevantAspects.insert(mergedPaths); - kit->setIrrelevantAspects(irrelevantAspects); - } - if (!kit->value(mergedPaths, false).toBool()) { - kit->setValue(mergedPaths, true); - } - } - - // Fix kit dependencies for known targets - auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); - qtForMCUsPackage->updateStatus(); - if (qtForMCUsPackage->validStatus()) { - FilePath dir = qtForMCUsPackage->path(); - McuSdkRepository repo; - Sdk::targetsAndPackages(dir, &repo); - for (const auto &target : qAsConst(repo.mcuTargets)) - for (auto kit : existingKits(target)) { - if (McuDependenciesKitAspect::dependencies(kit).isEmpty()) { - setKitDependencies(kit, target, qtForMCUsPackage); - } - } - - repo.deletePackagesAndTargets(); - } - delete qtForMCUsPackage; + // Only on Windows, Qt is linked into the distributed qul Desktop libs. Also, the host tools + // are missing the Qt runtime libraries on non-Windows. + return !HostOsInfo::isWindowsHost(); } } // namespace Internal diff --git a/src/plugins/mcusupport/mcusupportoptions.h b/src/plugins/mcusupport/mcusupportoptions.h index 61be8a8df6c..02e672486c2 100644 --- a/src/plugins/mcusupport/mcusupportoptions.h +++ b/src/plugins/mcusupport/mcusupportoptions.h @@ -27,8 +27,8 @@ #include #include "mcusupport_global.h" +#include "mcukitmanager.h" -#include #include #include #include @@ -51,49 +51,7 @@ namespace Internal { class McuAbstractPackage; class McuToolChainPackage; - -void printMessage(const QString &message, bool important); - -class McuTarget : public QObject -{ - Q_OBJECT - -public: - enum class OS { Desktop, BareMetal, FreeRTOS }; - - struct Platform - { - QString name; - QString displayName; - QString vendor; - }; - - enum { UnspecifiedColorDepth = -1 }; - - McuTarget(const QVersionNumber &qulVersion, - const Platform &platform, - OS os, - const QVector &packages, - const McuToolChainPackage *toolChainPackage, - int colorDepth = UnspecifiedColorDepth); - - const QVersionNumber &qulVersion() const; - const QVector &packages() const; - const McuToolChainPackage *toolChainPackage() const; - const Platform &platform() const; - OS os() const; - int colorDepth() const; - bool isValid() const; - void printPackageProblems() const; - -private: - const QVersionNumber m_qulVersion; - const Platform m_platform; - const OS m_os; - const QVector m_packages; - const McuToolChainPackage *m_toolChainPackage; - const int m_colorDepth; -}; // class McuTarget +class McuTarget; class McuSdkRepository { @@ -122,6 +80,7 @@ public: static void updateKitEnvironment(ProjectExplorer::Kit *, const McuTarget *); static void remapQul2xCmakeVars(ProjectExplorer::Kit *, const Utils::EnvironmentItems &); static Utils::FilePath qulDirFromSettings(); + static McuKitManager::UpgradeOption askForKitUpgrades(); static void registerQchFiles(); static void registerExamples(); @@ -130,6 +89,8 @@ public: void checkUpgradeableKits(); void populatePackagesAndTargets(); + + static bool kitsNeedQtVersion(); private: void deletePackagesAndTargets(); @@ -137,47 +98,6 @@ signals: void packagesChanged(); }; -class McuKitManager -{ - Q_DECLARE_TR_FUNCTIONS(McuSupport::Internal::McuKitManager) - -public: - enum class UpgradeOption { - Ignore, - Keep, - Replace - }; - - // Creating kits: - static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); - static void createAutomaticKits(); - - // Querying the kits: - static QList existingKits(const McuTarget *mcuTarget); - static QList matchingKits(const McuTarget *mcuTarget, - const McuAbstractPackage *qtForMCUsSdkPackage); - static QList upgradeableKits( - const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); - static QList kitsWithMismatchedDependencies(const McuTarget *mcuTarget); - - // Upgrading kits: - static UpgradeOption askForKitUpgrades(); - static void upgradeKitsByCreatingNewPackage(UpgradeOption upgradeOption); - static void upgradeKitInPlace(ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk); - - // Fixing kits: - static void fixKitsDependencies(); - static void fixExistingKits(); - - // Outdated kits: - static QList outdatedKits(); - static void removeOutdatedKits(); - - // Querying kits: - static QString kitName(const McuTarget* mcuTarget); - static QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit); - static bool kitIsUpToDate(const ProjectExplorer::Kit *kit, const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage); -}; } // namespace Internal } // namespace McuSupport diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp index 81fd58080e3..7eb8c160b0b 100644 --- a/src/plugins/mcusupport/mcusupportoptionspage.cpp +++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp @@ -25,9 +25,11 @@ #include "mcusupportoptionspage.h" #include "mcupackage.h" +#include "mcutarget.h" #include "mcusupportconstants.h" #include "mcusupportoptions.h" #include "mcusupportsdk.h" +#include "mcukitmanager.h" #include #include diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp index 75cc6b78921..f0778b04b24 100644 --- a/src/plugins/mcusupport/mcusupportplugin.cpp +++ b/src/plugins/mcusupport/mcusupportplugin.cpp @@ -28,6 +28,7 @@ #include "mcusupportconstants.h" #include "mcusupportdevice.h" #include "mcusupportoptions.h" +#include "mcukitmanager.h" #include "mcusupportoptionspage.h" #include "mcusupportrunconfiguration.h" @@ -38,6 +39,7 @@ #include #include #include +#include #include #include @@ -53,6 +55,16 @@ using namespace ProjectExplorer; namespace McuSupport { namespace Internal { +void printMessage(const QString &message, bool important) +{ + const QString displayMessage = QCoreApplication::translate("QtForMCUs", "Qt for MCUs: %1") + .arg(message); + if (important) + Core::MessageManager::writeFlashing(displayMessage); + else + Core::MessageManager::writeSilently(displayMessage); +} + class McuSupportPluginPrivate { public: diff --git a/src/plugins/mcusupport/mcusupportplugin.h b/src/plugins/mcusupport/mcusupportplugin.h index 2286ed0aad2..21767a02f07 100644 --- a/src/plugins/mcusupport/mcusupportplugin.h +++ b/src/plugins/mcusupport/mcusupportplugin.h @@ -31,6 +31,8 @@ namespace McuSupport::Internal { +void printMessage(const QString &message, bool important); + class McuSupportPlugin final : public ExtensionSystem::IPlugin { Q_OBJECT diff --git a/src/plugins/mcusupport/mcusupportsdk.cpp b/src/plugins/mcusupport/mcusupportsdk.cpp index 9911fcbf50c..5550a6848cc 100644 --- a/src/plugins/mcusupport/mcusupportsdk.cpp +++ b/src/plugins/mcusupport/mcusupportsdk.cpp @@ -25,10 +25,13 @@ #include "mcusupportsdk.h" #include "mcupackage.h" +#include "mcutarget.h" #include "mcusupportconstants.h" #include "mcusupportoptions.h" +#include "mcukitmanager.h" #include "mcusupportversiondetection.h" #include "mcutargetdescription.h" +#include "mcusupportplugin.h" #include #include diff --git a/src/plugins/mcusupport/mcutarget.cpp b/src/plugins/mcusupport/mcutarget.cpp new file mode 100644 index 00000000000..291b861e221 --- /dev/null +++ b/src/plugins/mcusupport/mcutarget.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +#include "mcutarget.h" +#include "mcupackage.h" +#include "mcukitmanager.h" + +#include "mcusupportplugin.h" + +#include +#include +#include +#include +#include +#include + +using namespace ProjectExplorer; +using namespace Utils; + +namespace McuSupport::Internal { + +static ToolChain *msvcToolChain(Id language) +{ + ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { + const Abi abi = t->targetAbi(); + // TODO: Should Abi::WindowsMsvc2022Flavor be added too? + return (abi.osFlavor() == Abi::WindowsMsvc2017Flavor + || abi.osFlavor() == Abi::WindowsMsvc2019Flavor) + && abi.architecture() == Abi::X86Architecture && abi.wordWidth() == 64 + && t->language() == language; + }); + return toolChain; +} + +static ToolChain *gccToolChain(Id language) +{ + ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { + const Abi abi = t->targetAbi(); + return abi.os() != Abi::WindowsOS && abi.architecture() == Abi::X86Architecture + && abi.wordWidth() == 64 && t->language() == language; + }); + return toolChain; +} + +static ToolChain *armGccToolChain(const FilePath &path, Id language) +{ + ToolChain *toolChain = ToolChainManager::toolChain([&path, language](const ToolChain *t) { + return t->compilerCommand() == path && t->language() == language; + }); + if (!toolChain) { + ToolChainFactory *gccFactory + = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), + [](ToolChainFactory *f) { + return f->supportedToolChainType() + == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID; + }); + if (gccFactory) { + const QList detected = gccFactory->detectForImport({path, language}); + if (!detected.isEmpty()) { + toolChain = detected.first(); + toolChain->setDetection(ToolChain::ManualDetection); + toolChain->setDisplayName("Arm GCC"); + ToolChainManager::registerToolChain(toolChain); + } + } + } + + return toolChain; +} + +static ToolChain *iarToolChain(const FilePath &path, Id language) +{ + ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) { + return t->typeId() == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID + && t->language() == language; + }); + if (!toolChain) { + ToolChainFactory *iarFactory + = Utils::findOrDefault(ToolChainFactory::allToolChainFactories(), + [](ToolChainFactory *f) { + return f->supportedToolChainType() + == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID; + }); + if (iarFactory) { + Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {})); + if (detected.isEmpty()) + detected = iarFactory->detectForImport({path, language}); + for (auto tc : detected) { + if (tc->language() == language) { + toolChain = tc; + toolChain->setDetection(ToolChain::ManualDetection); + toolChain->setDisplayName("IAREW"); + ToolChainManager::registerToolChain(toolChain); + } + } + } + } + + return toolChain; +} + +ToolChain *McuToolChainPackage::toolChain(Id language) const +{ + switch (m_type) { + case Type::MSVC: + return msvcToolChain(language); + case Type::GCC: + return gccToolChain(language); + case Type::IAR: { + const FilePath compiler = path().pathAppended("/bin/iccarm").withExecutableSuffix(); + return iarToolChain(compiler, language); + } + case Type::ArmGcc: + case Type::KEIL: + case Type::GHS: + case Type::GHSArm: + case Type::Unsupported: { + const QLatin1String compilerName( + language == ProjectExplorer::Constants::C_LANGUAGE_ID ? "gcc" : "g++"); + const QString comp = QLatin1String(m_type == Type::ArmGcc ? "/bin/arm-none-eabi-%1" + : "/bar/foo-keil-%1") + .arg(compilerName); + const FilePath compiler = path().pathAppended(comp).withExecutableSuffix(); + + return armGccToolChain(compiler, language); + } + default: + Q_UNREACHABLE(); + } +} + +QString McuToolChainPackage::toolChainName() const +{ + switch (m_type) { + case Type::ArmGcc: + return QLatin1String("armgcc"); + case Type::IAR: + return QLatin1String("iar"); + case Type::KEIL: + return QLatin1String("keil"); + case Type::GHS: + return QLatin1String("ghs"); + case Type::GHSArm: + return QLatin1String("ghs-arm"); + default: + return QLatin1String("unsupported"); + } +} + +QString McuToolChainPackage::cmakeToolChainFileName() const +{ + return toolChainName() + QLatin1String(".cmake"); +} + +QVariant McuToolChainPackage::debuggerId() const +{ + using namespace Debugger; + + QString sub, displayName; + DebuggerEngineType engineType; + + switch (m_type) { + case Type::ArmGcc: { + sub = QString::fromLatin1("bin/arm-none-eabi-gdb-py"); + displayName = McuPackage::tr("Arm GDB at %1"); + engineType = Debugger::GdbEngineType; + break; + } + case Type::IAR: { + sub = QString::fromLatin1("../common/bin/CSpyBat"); + displayName = QLatin1String("CSpy"); + engineType = Debugger::NoEngineType; // support for IAR missing + break; + } + case Type::KEIL: { + sub = QString::fromLatin1("UV4/UV4"); + displayName = QLatin1String("KEIL uVision Debugger"); + engineType = Debugger::UvscEngineType; + break; + } + default: + return QVariant(); + } + + const FilePath command = path().pathAppended(sub).withExecutableSuffix(); + if (const DebuggerItem *debugger = DebuggerItemManager::findByCommand(command)) { + return debugger->id(); + } + + DebuggerItem newDebugger; + newDebugger.setCommand(command); + newDebugger.setUnexpandedDisplayName(displayName.arg(command.toUserOutput())); + newDebugger.setEngineType(engineType); + return DebuggerItemManager::registerDebugger(newDebugger); +} + +McuTarget::McuTarget(const QVersionNumber &qulVersion, + const Platform &platform, + OS os, + const QVector &packages, + const McuToolChainPackage *toolChainPackage, + int colorDepth) + : m_qulVersion(qulVersion) + , m_platform(platform) + , m_os(os) + , m_packages(packages) + , m_toolChainPackage(toolChainPackage) + , m_colorDepth(colorDepth) +{} + +const QVector &McuTarget::packages() const +{ + return m_packages; +} + +const McuToolChainPackage *McuTarget::toolChainPackage() const +{ + return m_toolChainPackage; +} + +McuTarget::OS McuTarget::os() const +{ + return m_os; +} + +const McuTarget::Platform &McuTarget::platform() const +{ + return m_platform; +} + +bool McuTarget::isValid() const +{ + return Utils::allOf(packages(), [](McuAbstractPackage *package) { + package->updateStatus(); + return package->validStatus(); + }); +} + +void McuTarget::printPackageProblems() const +{ + for (auto package : packages()) { + package->updateStatus(); + if (!package->validStatus()) + printMessage(tr("Error creating kit for target %1, package %2: %3") + .arg(McuKitManager::kitName(this), + package->label(), + package->statusText()), + true); + if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion) + printMessage(tr("Warning creating kit for target %1, package %2: %3") + .arg(McuKitManager::kitName(this), + package->label(), + package->statusText()), + false); + } +} + +const QVersionNumber &McuTarget::qulVersion() const +{ + return m_qulVersion; +} + +int McuTarget::colorDepth() const +{ + return m_colorDepth; +} + +} // namespace McuSupport::Internal diff --git a/src/plugins/mcusupport/mcutarget.h b/src/plugins/mcusupport/mcutarget.h new file mode 100644 index 00000000000..7426f81e152 --- /dev/null +++ b/src/plugins/mcusupport/mcutarget.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +#pragma once + +#include +#include + +namespace ProjectExplorer { +class ToolChain; +} + +namespace Utils { +class PathChooser; +class InfoLabel; +} // namespace Utils + +namespace McuSupport { +namespace Internal { + +class McuAbstractPackage; +class McuToolChainPackage; + +class McuTarget : public QObject +{ + Q_OBJECT + +public: + enum class OS { Desktop, BareMetal, FreeRTOS }; + + struct Platform + { + QString name; + QString displayName; + QString vendor; + }; + + enum { UnspecifiedColorDepth = -1 }; + + McuTarget(const QVersionNumber &qulVersion, + const Platform &platform, + OS os, + const QVector &packages, + const McuToolChainPackage *toolChainPackage, + int colorDepth = UnspecifiedColorDepth); + + const QVersionNumber &qulVersion() const; + const QVector &packages() const; + const McuToolChainPackage *toolChainPackage() const; + const Platform &platform() const; + OS os() const; + int colorDepth() const; + bool isValid() const; + void printPackageProblems() const; + +private: + const QVersionNumber m_qulVersion; + const Platform m_platform; + const OS m_os; + const QVector m_packages; + const McuToolChainPackage *m_toolChainPackage; + const int m_colorDepth; +}; // class McuTarget + + +} // namespace Internal +} // namespace McuSupport diff --git a/src/plugins/mcusupport/test/unittest.cpp b/src/plugins/mcusupport/test/unittest.cpp index c5de1a208fb..3651369cb92 100644 --- a/src/plugins/mcusupport/test/unittest.cpp +++ b/src/plugins/mcusupport/test/unittest.cpp @@ -25,6 +25,7 @@ #include "unittest.h" #include "mcutargetdescription.h" +#include "mcukitmanager.h" #include "nxp_1064_json.h" #include "utils/filepath.h" #include diff --git a/src/plugins/mcusupport/test/unittest.h b/src/plugins/mcusupport/test/unittest.h index 0f2235afa19..dcdb5370b2d 100644 --- a/src/plugins/mcusupport/test/unittest.h +++ b/src/plugins/mcusupport/test/unittest.h @@ -26,6 +26,7 @@ #pragma once #include "mcupackage.h" +#include "mcutarget.h" #include "mcusupportoptions.h" #include "mcusupportplugin.h" #include "mcusupportsdk.h" From 59fb0e9c9ca18f21402bcafe530321cddc005b67 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 18 Feb 2022 10:31:33 +0100 Subject: [PATCH 42/76] Core: Properly handle file path arguments with -client option These paths come from the user, so the separators must be translated. Fixes: QTCREATORBUG-27075 Change-Id: Ia20c2662d30626b8b7ed3dd19afb64a43c8a716f Reviewed-by: Eike Ziller Reviewed-by: Qt CI Bot Reviewed-by: --- src/plugins/coreplugin/coreplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index 6b3195d16d7..483c8c3c2b9 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -283,7 +283,7 @@ QObject *CorePlugin::remoteCommand(const QStringList & /* options */, }); return nullptr; } - const FilePaths filePaths = Utils::transform(args, FilePath::fromString); + const FilePaths filePaths = Utils::transform(args, FilePath::fromUserInput); IDocument *res = MainWindow::openFiles( filePaths, ICore::OpenFilesFlags(ICore::SwitchMode | ICore::CanContainLineAndColumnNumbers | ICore::SwitchSplitIfAlreadyVisible), From 8538f919caf00919b1eeaa06002e00bd1bb83403 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Thu, 17 Feb 2022 17:49:15 +0100 Subject: [PATCH 43/76] QmlDesigner: Adjust wizard template Instead of using the constants we can use the size of the main screen directly. This has the advantage that if the size of the main screen changes without adjusting the constants it still works. Change-Id: I602cf4089249e90efb6a35b803d67df6ca2b1bab Reviewed-by: Thomas Hartmann --- .../qmldesigner/studio_templates/projects/common/App.qml.tpl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/App.qml.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/App.qml.tpl index 1a6597e2271..32b90720938 100644 --- a/share/qtcreator/qmldesigner/studio_templates/projects/common/App.qml.tpl +++ b/share/qtcreator/qmldesigner/studio_templates/projects/common/App.qml.tpl @@ -35,13 +35,14 @@ import QtQuick.VirtualKeyboard %{QtQuickVersion} @endif Window { - width: Constants.width - height: Constants.height + width: mainScreen.width + height: mainScreen.height visible: true title: "%{ProjectName}" %{UIClassName} { + id: mainScreen } @if %{UseVirtualKeyboard} From 61d5bbbdadc54d2ad02d4a98f04285d6ffc0f282 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Fri, 18 Feb 2022 10:11:01 +0100 Subject: [PATCH 44/76] QmlDesigner: Fix example download missing setting When starting with a clean config the location for download/extraction of an example is empty. The first call to the settings needed a default location. Change-Id: I2d63f805dc46c564f13346648f3e3bf29a0970d8 Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- src/plugins/studiowelcome/examplecheckout.cpp | 4 +-- .../studiowelcome/studiowelcomeplugin.cpp | 33 +++++++++++-------- .../studiowelcome/studiowelcomeplugin.h | 5 +-- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp index a3c7d70e710..9cbc57cd827 100644 --- a/src/plugins/studiowelcome/examplecheckout.cpp +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -239,9 +239,7 @@ FileExtractor::FileExtractor(QObject *parent) : QObject(parent) { m_targetPath = Utils::FilePath::fromString( - Core::ICore::settings() - ->value(StudioWelcome::Internal::EXAMPLES_DOWNLOAD_PATH) - .toString()); + StudioWelcome::Internal::StudioWelcomePlugin::examplesPathSetting()); m_timer.setInterval(100); m_timer.setSingleShot(false); diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index e89bc5fa1d1..dfb554c2974 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -98,6 +98,8 @@ const char STATISTICS_COLLECTION_MODE[] = "StatisticsCollectionMode"; const char NO_TELEMETRY[] = "NoTelemetry"; const char CRASH_REPORTER_SETTING[] = "CrashReportingEnabled"; +const char EXAMPLES_DOWNLOAD_PATH[] = "StudioWelcome/ExamplesDownloadPath"; + QPointer s_view = nullptr; static StudioWelcomePlugin *s_pluginInstance = nullptr; @@ -676,6 +678,20 @@ void StudioWelcomePlugin::resumeRemoveSplashTimer() m_removeSplashTimer.start(m_removeSplashRemainingTime); } +Utils::FilePath StudioWelcomePlugin::defaultExamplesPath() +{ + return Utils::FilePath::fromString( + QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)) + .pathAppended("QtDesignStudio"); +} + +QString StudioWelcomePlugin::examplesPathSetting() +{ + return Core::ICore::settings() + ->value(EXAMPLES_DOWNLOAD_PATH, defaultExamplesPath().toString()) + .toString(); +} + WelcomeMode::WelcomeMode() { setDisplayName(tr("Studio")); @@ -778,18 +794,6 @@ void setSettingIfDifferent(const QString &key, bool value, bool &dirty) } } -const Utils::FilePath defaultExamplesPath = Utils::FilePath::fromString( - QStandardPaths::writableLocation( - QStandardPaths::DocumentsLocation)) - .pathAppended("QtDesignStudio"); - -static QString examplesPathSetting() -{ - return Core::ICore::settings() - ->value(EXAMPLES_DOWNLOAD_PATH, defaultExamplesPath.toString()) - .toString(); -} - WelcomeMode::~WelcomeMode() { delete m_modeWidget; @@ -836,11 +840,12 @@ StudioSettingsPage::StudioSettingsPage() examplesGroupBox->setLayout(horizontalLayout); auto label = new QLabel(tr("Examples path:")); - m_pathChooser->setFilePath(Utils::FilePath::fromString(examplesPathSetting())); + m_pathChooser->setFilePath( + Utils::FilePath::fromString(StudioWelcomePlugin::examplesPathSetting())); auto resetButton = new QPushButton(tr("Reset Path")); connect(resetButton, &QPushButton::clicked, this, [this]() { - m_pathChooser->setFilePath(defaultExamplesPath); + m_pathChooser->setFilePath(StudioWelcomePlugin::defaultExamplesPath()); }); horizontalLayout->addWidget(label); diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.h b/src/plugins/studiowelcome/studiowelcomeplugin.h index 11274b68a6b..cd6b8ea87f2 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.h +++ b/src/plugins/studiowelcome/studiowelcomeplugin.h @@ -36,8 +36,6 @@ QT_FORWARD_DECLARE_CLASS(QCheckBox) namespace StudioWelcome { namespace Internal { -const char EXAMPLES_DOWNLOAD_PATH[] = "StudioWelcome/ExamplesDownloadPath"; - class StudioSettingsPage : public Core::IOptionsPageWidget { public: @@ -80,6 +78,9 @@ public: void pauseRemoveSplashTimer(); void resumeRemoveSplashTimer(); + static Utils::FilePath defaultExamplesPath(); + static QString examplesPathSetting(); + signals: void examplesDownloadPathChanged(const QString &path); From 844a5e624a255760acecc09ba5ce57ed20c8fa64 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 18 Feb 2022 08:59:27 +0100 Subject: [PATCH 45/76] Editor: make sure to cleanup select all future watcher Change-Id: I39e1bc7926905684601eb72cdd7a4357c708c432 Reviewed-by: Eike Ziller --- src/plugins/texteditor/texteditor.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index a36caf3befc..81c833e72ed 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -835,6 +835,8 @@ public: setMultiTextCursorProvider([editor]() { return editor->multiTextCursor(); }); } + ~TextEditorWidgetFind() override { cancelCurrentSelectAll(); } + bool supportsSelectAll() const override { return true; } void selectAll(const QString &txt, FindFlags findFlags) override; @@ -858,6 +860,8 @@ void TextEditorWidgetFind::selectAll(const QString &txt, FindFlags findFlags) connect(m_selectWatcher, &QFutureWatcher::finished, this, [this]() { const QFuture future = m_selectWatcher->future(); + m_selectWatcher->deleteLater(); + m_selectWatcher = nullptr; if (future.resultCount() <= 0) return; const FileSearchResultList &results = future.result(); From 24c9340d3d5739ea65399ba9b65963245b8ae50c Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Wed, 16 Feb 2022 17:46:00 +0100 Subject: [PATCH 46/76] QML/JS: Fix punctuation of message Task-number: QTCREATORBUG-27055 Change-Id: Ibaa37fc49e9ae3671cc7904b63682d245c0bdd8d Reviewed-by: Thomas Hartmann --- src/libs/qmljs/qmljsbind.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/qmljs/qmljsbind.cpp b/src/libs/qmljs/qmljsbind.cpp index 512776ff550..96b0ee2908f 100644 --- a/src/libs/qmljs/qmljsbind.cpp +++ b/src/libs/qmljs/qmljsbind.cpp @@ -185,7 +185,7 @@ ObjectValue *Bind::bindObject(UiQualifiedId *qualifiedTypeNameId, UiObjectInitia void Bind::throwRecursionDepthError() { - _diagnosticMessages->append(DiagnosticMessage(Severity::Error, SourceLocation(), tr("Hit maximal recursion depth in AST visit"))); + _diagnosticMessages->append(DiagnosticMessage(Severity::Error, SourceLocation(), tr("Hit maximal recursion depth in AST visit."))); } void Bind::accept(Node *node) From abf1ec7cdc366c49dc604ec064ac63aef6daefbf Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 18 Feb 2022 08:42:28 +0100 Subject: [PATCH 47/76] Open only designer related project files in Design Studio DocumentManager::setFileDialogFilter allows overriding the open Project/File filter. In QDS we only allow the relevant suffixes. Task-number: QDS-5825 Change-Id: I6cdc0f15628a215edc41cdaeb485bd17e08ef4ec Reviewed-by: Miikka Heikkinen Reviewed-by: Eike Ziller --- src/plugins/coreplugin/documentmanager.cpp | 16 ++++++++++++++++ src/plugins/coreplugin/documentmanager.h | 4 ++++ .../coreplugin/editormanager/editormanager.cpp | 2 +- .../studiowelcome/studiowelcomeplugin.cpp | 10 +++++++++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/documentmanager.cpp b/src/plugins/coreplugin/documentmanager.cpp index 15fb2edfdc1..43ddad0ceef 100644 --- a/src/plugins/coreplugin/documentmanager.cpp +++ b/src/plugins/coreplugin/documentmanager.cpp @@ -199,6 +199,7 @@ public: IDocument *m_blockedIDocument = nullptr; QAction *m_saveAllAction; + QString fileDialogFilterOverride; }; static DocumentManager *m_instance; @@ -770,6 +771,16 @@ bool DocumentManager::saveDocument(IDocument *document, return ret; } +QString DocumentManager::fileDialogFilter(QString *selectedFilter) +{ + if (!d->fileDialogFilterOverride.isEmpty()) { + if (selectedFilter) + *selectedFilter = d->fileDialogFilterOverride.split(";;").first(); + return d->fileDialogFilterOverride; + } + return allDocumentFactoryFiltersString(selectedFilter); +} + QString DocumentManager::allDocumentFactoryFiltersString(QString *allFilesFilter = nullptr) { QSet uniqueFilters; @@ -1531,6 +1542,11 @@ void DocumentManager::notifyFilesChangedInternally(const FilePaths &filePaths) emit m_instance->filesChangedInternally(filePaths); } +void DocumentManager::setFileDialogFilter(const QString &filter) +{ + d->fileDialogFilterOverride = filter; +} + void DocumentManager::registerSaveAllAction() { d->registerSaveAllAction(); diff --git a/src/plugins/coreplugin/documentmanager.h b/src/plugins/coreplugin/documentmanager.h index 01fa660272c..46667cf8ded 100644 --- a/src/plugins/coreplugin/documentmanager.h +++ b/src/plugins/coreplugin/documentmanager.h @@ -142,6 +142,10 @@ public: lead to any editors to reload or any other editor manager actions. */ static void notifyFilesChangedInternally(const Utils::FilePaths &filePaths); + static void setFileDialogFilter(const QString &filter); + + static QString fileDialogFilter(QString *selectedFilter = nullptr); + signals: /* Used to notify e.g. the code model to update the given files. Does *not* lead to any editors to reload or any other editor manager actions. */ diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index e328bd50435..150d5d957b2 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -3231,7 +3231,7 @@ void EditorManager::addCloseEditorListener(const std::function FilePaths EditorManager::getOpenFilePaths() { QString selectedFilter; - const QString &fileFilters = DocumentManager::allDocumentFactoryFiltersString(&selectedFilter); + const QString &fileFilters = DocumentManager::fileDialogFilter(&selectedFilter); return DocumentManager::getOpenFileNames(fileFilters, {}, &selectedFilter); } diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index dfb554c2974..d808a435e95 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -52,11 +53,12 @@ #include #include +#include #include #include +#include #include #include -#include #include #include @@ -605,6 +607,12 @@ void StudioWelcomePlugin::extensionsInitialized() Core::ICore::resourcePath("qmldesigner/studio_templates")); Core::ICore::setNewDialogFactory([](QWidget *parent) { return new QdsNewDialog(parent); }); + + const QString filters = QString("Project (*.qmlproject);;UI file (*.ui.qml);;QML file " + "(*.qml);;JavaScript file (*.js);;%1") + .arg(Utils::allFilesFilterString()); + + Core::DocumentManager::setFileDialogFilter(filters); } if (showSplashScreen()) { From 1d0603245384b3f809253f4944f749f5ef3718c8 Mon Sep 17 00:00:00 2001 From: Tapani Mattila Date: Wed, 16 Feb 2022 16:07:59 +0200 Subject: [PATCH 48/76] CMake Generator: Fix modules with nested imports Task-number: QDS-6220 Change-Id: Icdb37b5b856af369a8d6a0e00a02ae469116864a Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/generatecmakelists.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/generatecmakelists.cpp b/src/plugins/qmldesigner/generatecmakelists.cpp index 1dc5cd1bc81..d4758619ccd 100644 --- a/src/plugins/qmldesigner/generatecmakelists.cpp +++ b/src/plugins/qmldesigner/generatecmakelists.cpp @@ -381,7 +381,7 @@ void generateModuleCmake(const FilePath &dir, const QString &uri) QString moduleUri = uri.isEmpty() ? dir.fileName() : uri; - QString moduleName = QString(moduleUri).remove('.'); + QString moduleName = QString(moduleUri).replace('.', '_'); moduleNames.append(moduleName); QString fileContent; From 3d56b8b54a369d50a9544c0f594fa75d7d18bac6 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Thu, 17 Feb 2022 21:39:54 +0100 Subject: [PATCH 49/76] QmlDesigner: Fix creation date issue on macOS On macOS the creation date was not according to the date/time when the example was unzipped it was rather the date/time when the example folder was zipped. By removing the already existing folder and create it again to hold the content of the zip archive this issue should b circumvented. Task-number: QDS-6288 Change-Id: Icf18c4fcddcacf69feeca536f6d0e81f4c126afe Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- src/plugins/studiowelcome/examplecheckout.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/plugins/studiowelcome/examplecheckout.cpp b/src/plugins/studiowelcome/examplecheckout.cpp index 9cbc57cd827..06d37a39317 100644 --- a/src/plugins/studiowelcome/examplecheckout.cpp +++ b/src/plugins/studiowelcome/examplecheckout.cpp @@ -368,12 +368,21 @@ QString FileExtractor::sourceFile() const void FileExtractor::extract() { + const QString targetFolder = m_targetPath.toString() + "/" + m_archiveName; + + // If the target directory already exists, remove it and its content + QDir targetDir(targetFolder); + if (targetDir.exists()) + targetDir.removeRecursively(); + + // Create a new directory to generate a proper creation date + targetDir.mkdir(targetFolder); + Utils::Archive *archive = Utils::Archive::unarchive(m_sourceFile, m_targetPath); archive->setParent(this); QTC_ASSERT(archive, return ); m_timer.start(); - const QString targetFolder = m_targetPath.toString() + "/" + m_archiveName; qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable(); qint64 compressedSize = QFileInfo(m_sourceFile.toString()).size(); From 8ad7ab2d2a7fefcd3a9ef3ff2f0ef7e5fe792417 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 17 Feb 2022 11:46:00 +0100 Subject: [PATCH 50/76] ClangCodeModel: Use project-specific clangd client, if possible If we open a file that does not belong to a currently open project, there is a good chance that the current project's parse context is a better fit for the file than the fallback client's. Fixes: QTCREATORBUG-26697 Change-Id: I6c17e275b047602c51364f3203b3f0a3e74a49fc Reviewed-by: Qt CI Bot Reviewed-by: David Schulz --- .../clangmodelmanagersupport.cpp | 48 ++++++++++++------- .../clangcodemodel/clangmodelmanagersupport.h | 2 +- .../clangcodemodel/test/clangdtests.cpp | 2 +- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 7ceb40011f8..85c2d1318bc 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -58,6 +58,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,13 @@ static CppEditor::CppModelManager *cppModelManager() return CppEditor::CppModelManager::instance(); } +static ProjectExplorer::Project *fallbackProject() +{ + if (ProjectExplorer::Project * const p = ProjectExplorer::ProjectTree::currentProject()) + return p; + return ProjectExplorer::SessionManager::startupProject(); +} + static const QList allCppEditors() { QList cppEditors; @@ -148,10 +156,7 @@ ClangModelManagerSupport::ClangModelManagerSupport() connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject, this, &ClangModelManagerSupport::onAboutToRemoveProject); connect(sessionManager, &ProjectExplorer::SessionManager::projectRemoved, - this, [this] { - if (ClangdClient * const fallbackClient = clientForProject(nullptr)) - claimNonProjectSources(fallbackClient); - }); + this, [this] { claimNonProjectSources(clientForProject(fallbackProject())); }); CppEditor::ClangdSettings::setDefaultClangdPath(Core::ICore::clangdExecutable(CLANG_BINDIR)); connect(&CppEditor::ClangdSettings::instance(), &CppEditor::ClangdSettings::changed, @@ -369,12 +374,15 @@ void ClangModelManagerSupport::updateLanguageClient( // Acquaint the client with all open C++ documents for this project. bool hasDocuments = false; for (TextEditor::BaseTextEditor * const editor : allCppEditors()) { - const Utils::FilePath filePath = editor->textDocument()->filePath(); - if (!project->isKnownFile(filePath)) - continue; - LanguageClientManager::openDocumentWithClient(editor->textDocument(), client); - ClangEditorDocumentProcessor::clearTextMarks(filePath); - hasDocuments = true; + TextEditor::TextDocument * const doc = editor->textDocument(); + const Client * const currentClient = LanguageClientManager::clientForDocument(doc); + if (!currentClient || !currentClient->project() + || currentClient->state() != Client::Initialized + || project->isKnownFile(doc->filePath())) { + LanguageClientManager::openDocumentWithClient(editor->textDocument(), client); + ClangEditorDocumentProcessor::clearTextMarks(doc->filePath()); + hasDocuments = true; + } } if (client->state() == Client::Initialized) @@ -443,7 +451,7 @@ ClangdClient *ClangModelManagerSupport::clientForProject( ClangdClient *ClangModelManagerSupport::clientForFile(const Utils::FilePath &file) const { - return clientForProject(ProjectExplorer::SessionManager::projectForFile(file)); + return qobject_cast(LanguageClientManager::clientForFilePath(file)); } ClangdClient *ClangModelManagerSupport::createClient(ProjectExplorer::Project *project, @@ -454,15 +462,19 @@ ClangdClient *ClangModelManagerSupport::createClient(ProjectExplorer::Project *p return client; } -void ClangModelManagerSupport::claimNonProjectSources(ClangdClient *fallbackClient) +void ClangModelManagerSupport::claimNonProjectSources(ClangdClient *client) { + if (!client) + return; for (TextEditor::BaseTextEditor * const editor : allCppEditors()) { - if (ProjectExplorer::SessionManager::projectForFile(editor->textDocument()->filePath())) + if (Client * const currentClient = LanguageClientManager::clientForDocument( + editor->textDocument()); + currentClient && currentClient->state() == Client::Initialized + && (currentClient == client || currentClient->project())) { continue; - if (!fallbackClient->documentOpen(editor->textDocument())) { - ClangEditorDocumentProcessor::clearTextMarks(editor->textDocument()->filePath()); - fallbackClient->openDocument(editor->textDocument()); } + ClangEditorDocumentProcessor::clearTextMarks(editor->textDocument()->filePath()); + client->openDocument(editor->textDocument()); } } @@ -562,8 +574,10 @@ void ClangModelManagerSupport::onEditorOpened(Core::IEditor *editor) // TODO: Ensure that not fully loaded documents are updated? - ProjectExplorer::Project * const project + ProjectExplorer::Project * project = ProjectExplorer::SessionManager::projectForFile(document->filePath()); + if (!project) + project = fallbackProject(); if (ClangdClient * const client = clientForProject(project)) LanguageClientManager::openDocumentWithClient(textDocument, client); } diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index 8307ece252f..b957ae69b90 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -134,7 +134,7 @@ private: void updateLanguageClient(ProjectExplorer::Project *project, const CppEditor::ProjectInfo::ConstPtr &projectInfo); ClangdClient *createClient(ProjectExplorer::Project *project, const Utils::FilePath &jsonDbDir); - void claimNonProjectSources(ClangdClient *fallbackClient); + void claimNonProjectSources(ClangdClient *client); void watchForExternalChanges(); void watchForInternalChanges(); diff --git a/src/plugins/clangcodemodel/test/clangdtests.cpp b/src/plugins/clangcodemodel/test/clangdtests.cpp index 44f71140cee..d03fcc2c896 100644 --- a/src/plugins/clangcodemodel/test/clangdtests.cpp +++ b/src/plugins/clangcodemodel/test/clangdtests.cpp @@ -2036,7 +2036,7 @@ void ClangdTestExternalChanges::test() QVERIFY(waitForSignalOrTimeout(ClangModelManagerSupport::instance(), &ClangModelManagerSupport::createdClient, timeOutInMs())); ClangdClient * const newClient = ClangModelManagerSupport::instance() - ->clientForFile(filePath("main.cpp")); + ->clientForProject(project()); QVERIFY(newClient); QVERIFY(newClient != oldClient); newClient->enableTesting(); From f87c25acb51f4d55c6327e08e665b7bbb404e188 Mon Sep 17 00:00:00 2001 From: Mats Honkamaa Date: Thu, 10 Feb 2022 15:56:34 +0200 Subject: [PATCH 51/76] Doc: Update particle system documentation Update particle system documentation and add downloadable fire particle example. Task-number: QDS-6190 Change-Id: Id2922f536a8400029b290328c1bdc6c1bd408fd6 Reviewed-by: Miikka Heikkinen Reviewed-by: Leena Miettinen Reviewed-by: Mahmoud Badri --- .../examples/doc/rainSnowParticles.qdoc | 8 ++--- .../studio-3d-particles-fire-emitter1.png | Bin 8730 -> 7086 bytes ...-3d-particles-fire-properties-rotation.png | Bin 0 -> 17009 bytes .../qtdesignstudio-3d-particles.qdoc | 31 +++++++++--------- 4 files changed, 17 insertions(+), 22 deletions(-) create mode 100644 doc/qtdesignstudio/images/studio-3d-particles-fire-properties-rotation.png diff --git a/doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc b/doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc index 49c42a84603..689f89d903f 100644 --- a/doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc +++ b/doc/qtdesignstudio/examples/doc/rainSnowParticles.qdoc @@ -74,12 +74,8 @@ In \uicontrol Navigator, select \e particleSystem and in \uicontrol Properties, set \uicontrol Translation > \uicontrol Y to 193. \li Set the \e rain-drop-white-square.png as texture for the particles. - From \uicontrol Library > \uicontrol Components, drag a \uicontrol Texture - to \e spriteParticle. - \li In \uicontrol Navigator, select \uicontrol texture1 and in \uicontrol - Properties, set \uicontrol Source to \e rain-drop-white-square.png. - \li In \uicontrol Navigator, select \uicontrol spriteParticle and in the - \uicontrol Properties, set \uicontrol Sprite to texture. + From \uicontrol Library > \uicontrol Assets, drag + \e {rain-drop-white-square.png} to \e spriteParticle. \li Adjust the apperance and behavior of the sprite further. In \uicontrol Properties, set: \list diff --git a/doc/qtdesignstudio/images/studio-3d-particles-fire-emitter1.png b/doc/qtdesignstudio/images/studio-3d-particles-fire-emitter1.png index ee56c599c7ae6f7810579bc800a208dac85374ba..6972f27021d8b4589197988c2f50a3e94434d5ed 100644 GIT binary patch literal 7086 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 literal 8730 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 diff --git a/doc/qtdesignstudio/images/studio-3d-particles-fire-properties-rotation.png b/doc/qtdesignstudio/images/studio-3d-particles-fire-properties-rotation.png new file mode 100644 index 0000000000000000000000000000000000000000..36709e7520a7ea1f35dd76ec18ac440c72d477d7 GIT binary patch literal 17009 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 XSb1jI7QLGc3=9mOu6{1-oD!M<^Mus3 literal 0 HcmV?d00001 diff --git a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-particles.qdoc b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-particles.qdoc index 42d3843f0d8..9d8c944b6e2 100644 --- a/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-particles.qdoc +++ b/doc/qtdesignstudio/src/qtquick3d-editor/qtdesignstudio-3d-particles.qdoc @@ -92,22 +92,9 @@ \li Drag-and-drop an instance of the \uicontrol {Particle System} component from \uicontrol Library to a scene component instance in \l Navigator. - \li Drag-and-drop an instance of the \uicontrol Texture component - from \uicontrol Library > \uicontrol Components > - \uicontrol {Qt Quick 3D} to the sprite particle instance - in \uicontrol Navigator. \li Drag-and-drop the sprite image from \uicontrol Library > - \uicontrol Assets to the texture instance in \uicontrol Navigator. - \li Select the sprite particle instance in \uicontrol Navigator to - display its properties in \l Properties. - \li In \uicontrol Sprite, select the texture instance. - \li Select the emitter instance in \uicontrol Navigator to - display its properties in \uicontrol Properties. - \li In \uicontrol Particle, select the particle instance to emit. - \li Select the vector 3D instance in \uicontrol Navigator to - display its properties in \uicontrol Properties. - \li In \uicontrol Direction, set the emitted particle velocity - towards the target vector. + \uicontrol Assets to the sprite particle instance + in \uicontrol Navigator. \endlist Add instances of other components according to your use case. The following @@ -122,6 +109,9 @@ their property values, such as particle source images and their color, life span, and fading effects, to simulate fire. + You can download the completed project from + \l {https://git.qt.io/public-demos/qtdesign-studio/-/tree/master/tutorial%20projects/FireParticles}{here}. + We will need the following \l{Assets}{assets}: \list @@ -199,12 +189,16 @@ \uicontrol {Particle end scale} to \e 5.00 for the flame particles and to \e 6.00 for the smoke particles. - We can now modify the appearance of the particles by setting their color in + We can now modify the appearance of the particles by selecting the + \e spriteParticle in \uicontrol Navigator and then setting their color in \uicontrol Properties > \uicontrol Particle. We select transparent yellow, orange, and transparent gray in \uicontrol Color and set values for \uicontrol {Color variation} to use slightly different colors for the individual particles. + We can also try changing the \uicontrol{Blend Mode} for the particle to get + a more realistic fire effect. + \image studio-3d-particles-fire-properties-particle.png "Particle properties" We set \uicontrol {Fade in effect} and \uicontrol {Fade out effect} values @@ -220,6 +214,11 @@ \image studio-3d-particles-fire-properties-sprite-particle.png "Sprite Particle properties" + In \uicontrol{Particle Rotation}, we also need to set \uicontrol Rotation + and \uicontrol{Velocity Variation} for all emitters to 0. + + \image studio-3d-particles-fire-properties-rotation.png "Emitter rotation properties" + Finally, we will specify the direction in which the particles move by modifying the property values of the \uicontrol {Vector Direction} component instances in \uicontrol Properties > \uicontrol {Particle Vector Direction}. From 5866f78049fbd61ff6caeddb61303ca5354d58da Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 17 Feb 2022 16:12:02 +0100 Subject: [PATCH 52/76] ClangCodeModel: Fix libclang tests We must make sure clangd doesn't get in the way. Change-Id: Ica053cce6928920b39602c7c467b5d16f8232fe6 Reviewed-by: Reviewed-by: Christian Stenger --- .../clangcodemodel/test/clangcodecompletion_test.cpp | 9 +++++++++ .../clangcodemodel/test/clangcodecompletion_test.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp index cdcb78742e4..4fa51c94b7c 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.cpp @@ -35,10 +35,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -514,6 +516,13 @@ namespace ClangCodeModel { namespace Internal { namespace Tests { +void ClangCodeCompletionTest::initTestCase() +{ + CppEditor::ClangdSettings::setUseClangd(false); + for (LanguageClient::Client * const c : LanguageClient::LanguageClientManager::clients()) + LanguageClient::LanguageClientManager::shutdownClient(c); +} + void ClangCodeCompletionTest::testCompleteDoxygenKeywords() { ProjectLessCompletionTest t("doxygenKeywordsCompletion.cpp"); diff --git a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h b/src/plugins/clangcodemodel/test/clangcodecompletion_test.h index cf8bac668e5..ad2dd83ada2 100644 --- a/src/plugins/clangcodemodel/test/clangcodecompletion_test.h +++ b/src/plugins/clangcodemodel/test/clangcodecompletion_test.h @@ -38,6 +38,8 @@ class ClangCodeCompletionTest : public QObject Q_OBJECT private slots: + void initTestCase(); + void testCompleteDoxygenKeywords(); void testCompletePreprocessorKeywords(); void testCompleteIncludeDirective(); From 4f69996190573daf4fb499b1c22b10705b9e8bb4 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 18 Feb 2022 13:19:07 +0100 Subject: [PATCH 53/76] ClangCodeModel: iterate over documents instead of editors Makes sure to handle each document just once since we can have multiple editors for the same document. Change-Id: I0d26a9931086d9b6be0c9c93b01f4485716d75e3 Reviewed-by: Christian Kandeler --- .../clangmodelmanagersupport.cpp | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 85c2d1318bc..94902075e91 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -93,21 +94,13 @@ static ProjectExplorer::Project *fallbackProject() return ProjectExplorer::SessionManager::startupProject(); } -static const QList allCppEditors() +static const QList allCppDocuments() { - QList cppEditors; - for (const Core::DocumentModel::Entry * const entry : Core::DocumentModel::entries()) { - const auto textDocument = qobject_cast(entry->document); - if (!textDocument) - continue; - if (const auto cppEditor = qobject_cast(Utils::findOrDefault( - Core::DocumentModel::editorsForDocument(textDocument), [](Core::IEditor *editor) { - return CppEditor::CppModelManager::isCppEditor(editor); - }))) { - cppEditors << cppEditor; - } - } - return cppEditors; + const auto isCppDocument = Utils::equal(&Core::IDocument::id, + Utils::Id(CppEditor::Constants::CPPEDITOR_ID)); + const QList documents + = Utils::filtered(Core::DocumentModel::openedDocuments(), isCppDocument); + return Utils::qobject_container_cast(documents); } ClangModelManagerSupport::ClangModelManagerSupport() @@ -373,13 +366,12 @@ void ClangModelManagerSupport::updateLanguageClient( // Acquaint the client with all open C++ documents for this project. bool hasDocuments = false; - for (TextEditor::BaseTextEditor * const editor : allCppEditors()) { - TextEditor::TextDocument * const doc = editor->textDocument(); + for (TextEditor::TextDocument * const doc : allCppDocuments()) { const Client * const currentClient = LanguageClientManager::clientForDocument(doc); if (!currentClient || !currentClient->project() || currentClient->state() != Client::Initialized || project->isKnownFile(doc->filePath())) { - LanguageClientManager::openDocumentWithClient(editor->textDocument(), client); + LanguageClientManager::openDocumentWithClient(doc, client); ClangEditorDocumentProcessor::clearTextMarks(doc->filePath()); hasDocuments = true; } @@ -466,15 +458,14 @@ void ClangModelManagerSupport::claimNonProjectSources(ClangdClient *client) { if (!client) return; - for (TextEditor::BaseTextEditor * const editor : allCppEditors()) { - if (Client * const currentClient = LanguageClientManager::clientForDocument( - editor->textDocument()); + for (TextEditor::TextDocument * const doc : allCppDocuments()) { + if (Client * const currentClient = LanguageClientManager::clientForDocument(doc); currentClient && currentClient->state() == Client::Initialized && (currentClient == client || currentClient->project())) { continue; } - ClangEditorDocumentProcessor::clearTextMarks(editor->textDocument()->filePath()); - client->openDocument(editor->textDocument()); + ClangEditorDocumentProcessor::clearTextMarks(doc->filePath()); + client->openDocument(doc); } } From 022510f1e66f2026099b8fa1865e822d89a586bb Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 15 Feb 2022 15:34:41 +0100 Subject: [PATCH 54/76] ClangCodeModel: Mention project name in clangd indexing message This will help avoid confusion in case of multi-project sessions. We also shorten the message a bit so it won't be cut off in the progress bar before the project name. Change-Id: I0e5885f89a976b14f758f9be77e7669f199cd887 Reviewed-by: Reviewed-by: David Schulz --- src/plugins/clangcodemodel/clangdclient.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index ef10edd5eb1..effe6a1f760 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -1307,7 +1307,10 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir) setClientCapabilities(caps); setLocatorsEnabled(false); setAutoRequestCodeActions(false); // clangd sends code actions inside diagnostics - setProgressTitleForToken(indexingToken(), tr("Parsing C/C++ Files (clangd)")); + if (project) { + setProgressTitleForToken(indexingToken(), + tr("Indexing %1 with clangd").arg(project->displayName())); + } setCurrentProject(project); setDocumentChangeUpdateThreshold(d->settings.documentUpdateThreshold); From a29154225e922222384f691fee48196d18f2195c Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 18 Feb 2022 12:54:59 +0100 Subject: [PATCH 55/76] StudioWelcome: Reduce minimum size to 640, 480 Change-Id: Ie6694cd62837c91f573bdcc348457876771ac479 Reviewed-by: Reviewed-by: Knud Dollereder --- src/plugins/studiowelcome/studiowelcomeplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index d808a435e95..9c7b82d1698 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -719,7 +719,7 @@ WelcomeMode::WelcomeMode() ExampleCheckout::registerTypes(); m_modeWidget = new QQuickWidget; - m_modeWidget->setMinimumSize(1024, 768); + m_modeWidget->setMinimumSize(640, 480); m_modeWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); QmlDesigner::Theme::setupTheme(m_modeWidget->engine()); m_modeWidget->engine()->addImportPath("qrc:/studiofonts"); From 4cbe956722af219be73b6720ad8c804b4cfebd82 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 18 Feb 2022 13:44:12 +0100 Subject: [PATCH 56/76] QmlDesigner: Cache result of eventListEnabled Calling EventList::hasEventListModel() takes time, since it includes file access. Since eventListEnabled() is called on each selection change, we cache the result. If the root node is the same, also the document is the same and there is no reason to check again. This way we check only once per document. Change-Id: Id664811b1319a306c70283d2b37de258a129892f Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Knud Dollereder --- .../components/eventlist/eventlistactions.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmldesigner/components/eventlist/eventlistactions.cpp b/src/plugins/qmldesigner/components/eventlist/eventlistactions.cpp index 823ce30da3b..a23b8f83a20 100644 --- a/src/plugins/qmldesigner/components/eventlist/eventlistactions.cpp +++ b/src/plugins/qmldesigner/components/eventlist/eventlistactions.cpp @@ -33,9 +33,18 @@ namespace QmlDesigner { -inline bool eventListEnabled(const SelectionContext &) +inline bool eventListEnabled(const SelectionContext &context) { - return EventList::hasEventListModel(); + static ModelNode lastRootNode; + static bool lastValue = false; + + if (lastRootNode == context.rootNode()) + return lastValue; + + lastRootNode = context.rootNode(); + lastValue = EventList::hasEventListModel(); + + return lastValue; } QIcon eventListIconFromIconFont(Theme::Icon iconType) From a0d19e088e65038815c2c43533d2244c7139d92d Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 18 Feb 2022 14:52:01 +0100 Subject: [PATCH 57/76] Wizards: Remove the .ui.qml wizard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qt Creator does not offer editing .ui.qml documents, so it should not produce them. For creating and editing .ui.qml, please use Qt Design Studio. Fixes: QTCREATORBUG-27085 Change-Id: I8bce9379a4bff8762a694067c25a0b266c41c417 Reviewed-by: Kimmo Leppälä Reviewed-by: hjk --- .../wizards/classes/qtquickui/file.qml.tpl | 4 - .../classes/qtquickui/fileForm.ui.qml.tpl | 6 -- .../wizards/classes/qtquickui/wizard.json | 91 ------------------- 3 files changed, 101 deletions(-) delete mode 100644 share/qtcreator/templates/wizards/classes/qtquickui/file.qml.tpl delete mode 100644 share/qtcreator/templates/wizards/classes/qtquickui/fileForm.ui.qml.tpl delete mode 100644 share/qtcreator/templates/wizards/classes/qtquickui/wizard.json diff --git a/share/qtcreator/templates/wizards/classes/qtquickui/file.qml.tpl b/share/qtcreator/templates/wizards/classes/qtquickui/file.qml.tpl deleted file mode 100644 index d5287a5f9ee..00000000000 --- a/share/qtcreator/templates/wizards/classes/qtquickui/file.qml.tpl +++ /dev/null @@ -1,4 +0,0 @@ -import QtQuick 2.4 - -%{FormClass} { -} diff --git a/share/qtcreator/templates/wizards/classes/qtquickui/fileForm.ui.qml.tpl b/share/qtcreator/templates/wizards/classes/qtquickui/fileForm.ui.qml.tpl deleted file mode 100644 index 96a8ae4f577..00000000000 --- a/share/qtcreator/templates/wizards/classes/qtquickui/fileForm.ui.qml.tpl +++ /dev/null @@ -1,6 +0,0 @@ -import QtQuick 2.4 - -Item { - width: 400 - height: 400 -} diff --git a/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json b/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json deleted file mode 100644 index e8bd200d759..00000000000 --- a/share/qtcreator/templates/wizards/classes/qtquickui/wizard.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "version": 1, - "supportedProjectTypes": [ ], - "id": "R.QtQuickUi", - "category": "R.Qt", - "trDescription": "Creates a Qt Quick Designer UI form along with a matching QML file for implementation purposes. You can add the form and file to an existing Qt Quick Project.", - "trDisplayName": "QtQuick UI File", - "trDisplayCategory": "Qt", - "iconText": "ui.qml", - "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.UiFiles" ], - "enabled": "%{JS: value('Plugins').indexOf('QmlJSEditor') >= 0}", - - "options" : [ - { "key": "QmlFile", "value": "%{Class}.%{JS: Util.preferredSuffix('text/x-qml')}" }, - { "key": "UiFile", "value": "%{FormClass}.%{JS: Util.preferredSuffix('application/x-qt.ui+qml')}" } - ], - - "pages" : - [ - { - "trDisplayName": "Define Class", - "trShortTitle": "Details", - "typeId": "Fields", - "data" : - [ - { - "name": "Class", - "trDisplayName": "Component name:", - "mandatory": true, - "type": "LineEdit", - "data": { - "validator": "(?:[A-Z_][a-zA-Z_0-9]*|)", - "fixup": "%{JS: '%{INPUT}'.charAt(0).toUpperCase() + '%{INPUT}'.slice(1) }" - } - }, - - { - "name": "Sp1", - "type": "Spacer", - "data": { "factor": 2 } - }, - { - "name": "FormClass", - "trDisplayName": "Component form name:", - "mandatory": true, - "type": "LineEdit", - "data": { - "validator": "(?:[A-Z_][a-zA-Z_0-9]*|)", - "fixup": "%{JS: '%{INPUT}'.charAt(0).toUpperCase() + '%{INPUT}'.slice(1) }", - "trText": "%{Class}Form" - } - }, - { - "name": "TargetPath", - "type": "PathChooser", - "trDisplayName": "Path:", - "mandatory": true, - "data": - { - "kind": "directory", - "basePath": "%{InitialPath}", - "path": "%{InitialPath}" - } - } - ] - }, - { - "trDisplayName": "Project Management", - "trShortTitle": "Summary", - "typeId": "Summary" - } - ], - "generators" : - [ - { - "typeId": "File", - "data": [ - { - "source": "file.qml.tpl", - "target": "%{TargetPath}/%{QmlFile}", - "openInEditor": true - }, - { - "source": "fileForm.ui.qml.tpl", - "target": "%{TargetPath}/%{UiFile}", - "openInEditor": true - } - ] - } - ] -} From c82937a78cb7bc23352d2c698dd7a4d5b6e53b21 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 18 Feb 2022 20:22:19 +0100 Subject: [PATCH 58/76] Convert old projects to project that supports the cmake generation workflow Task-number: QDS-5992 Change-Id: I9dd4204d7422052c80c86665ded558d959bb020b Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/CMakeLists.txt | 2 + src/plugins/qmldesigner/boilerplate.qrc | 1 + .../qmldesigner/cmakegeneratordialog.cpp | 4 +- .../qmldesigner/cmakeprojectconverter.cpp | 391 ++++++++++++++++++ .../qmldesigner/cmakeprojectconverter.h | 96 +++++ .../cmakeprojectconverterdialog.cpp | 227 ++++++++++ .../qmldesigner/cmakeprojectconverterdialog.h | 69 ++++ .../qmldesigner/generatecmakelists.cpp | 261 +++++++----- src/plugins/qmldesigner/generatecmakelists.h | 77 ++-- .../qmldesigner/generatecmakelistsconstants.h | 12 +- src/plugins/qmldesigner/qmldesignerplugin.cpp | 2 + src/plugins/qmldesigner/qmldesignerplugin.qbs | 2 + .../qmldesigner/qmlprojectappmainqml.tpl | 14 + .../qmldesigner/qmlprojectmaincmakelists.tpl | 3 +- 14 files changed, 1021 insertions(+), 140 deletions(-) create mode 100644 src/plugins/qmldesigner/cmakeprojectconverter.cpp create mode 100644 src/plugins/qmldesigner/cmakeprojectconverter.h create mode 100644 src/plugins/qmldesigner/cmakeprojectconverterdialog.cpp create mode 100644 src/plugins/qmldesigner/cmakeprojectconverterdialog.h create mode 100644 src/plugins/qmldesigner/qmlprojectappmainqml.tpl diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index b501a98bdd1..742b6f055c0 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -30,6 +30,8 @@ add_qtc_plugin(QmlDesigner checkablefiletreeitem.cpp checkablefiletreeitem.h cmakegeneratordialog.cpp cmakegeneratordialog.h cmakegeneratordialogtreemodel.cpp cmakegeneratordialogtreemodel.h + cmakeprojectconverter.cpp cmakeprojectconverter.h + cmakeprojectconverterdialog.cpp cmakeprojectconverterdialog.h generateresource.cpp generateresource.h generatecmakelists.cpp generatecmakelists.h generatecmakelistsconstants.h diff --git a/src/plugins/qmldesigner/boilerplate.qrc b/src/plugins/qmldesigner/boilerplate.qrc index 790f605c08e..a89643d6fff 100644 --- a/src/plugins/qmldesigner/boilerplate.qrc +++ b/src/plugins/qmldesigner/boilerplate.qrc @@ -7,5 +7,6 @@ qmlprojectmaincmakelists.tpl qmlprojectmodulecmakelists.tpl qmlprojectmainqml.tpl + qmlprojectappmainqml.tpl diff --git a/src/plugins/qmldesigner/cmakegeneratordialog.cpp b/src/plugins/qmldesigner/cmakegeneratordialog.cpp index eb7a35f170c..e8cf8e872f4 100644 --- a/src/plugins/qmldesigner/cmakegeneratordialog.cpp +++ b/src/plugins/qmldesigner/cmakegeneratordialog.cpp @@ -151,5 +151,5 @@ void CmakeGeneratorDialog::refreshNotificationText() } } -} -} +} //GenerateCmake +} //QmlDesigner diff --git a/src/plugins/qmldesigner/cmakeprojectconverter.cpp b/src/plugins/qmldesigner/cmakeprojectconverter.cpp new file mode 100644 index 00000000000..52448835771 --- /dev/null +++ b/src/plugins/qmldesigner/cmakeprojectconverter.cpp @@ -0,0 +1,391 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ +#include "cmakeprojectconverter.h" +#include "cmakeprojectconverterdialog.h" +#include "generatecmakelists.h" +#include "generatecmakelistsconstants.h" + +#include +#include + +#include +#include + +#include +#include +#include + +using namespace Utils; +using namespace QmlDesigner::GenerateCmake::Constants; + +namespace QmlDesigner { +namespace GenerateCmake { + +const QString MENU_ITEM_CONVERT = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter", + "Export as Latest Project Format"); +const QString ERROR_TITLE = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter", + "Creating Project"); +const QString SUCCESS_TITLE = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter", + "Creating Project"); +const QString ERROR_TEXT = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter", + "Creating project failed.\n%1"); +const QString SUCCESS_TEXT = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter", + "Creating project succeeded."); + +void CmakeProjectConverter::generateMenuEntry() +{ + Core::ActionContainer *menu = + Core::ActionManager::actionContainer(Core::Constants::M_FILE); + auto action = new QAction(MENU_ITEM_CONVERT); + QObject::connect(action, &QAction::triggered, CmakeProjectConverter::onConvertProject); + Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.ConvertToCmakeProject"); + menu->addAction(cmd, Core::Constants::G_FILE_EXPORT); + + action->setEnabled(ProjectExplorer::SessionManager::startupProject() != nullptr); + QObject::connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::startupProjectChanged, [action]() { + action->setEnabled(ProjectExplorer::SessionManager::startupProject() != nullptr); + }); +} + +void CmakeProjectConverter::onConvertProject() +{ + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + const QmlProjectManager::QmlProject *qmlProject = + qobject_cast(project); + if (qmlProject) { + CmakeProjectConverterDialog dialog(qmlProject); + if (dialog.exec()) { + FilePath newProjectPath = dialog.newPath(); + CmakeProjectConverter converter; + converter.convertProject(qmlProject, newProjectPath); + } + } +} + +bool CmakeProjectConverter::convertProject(const QmlProjectManager::QmlProject *project, + const FilePath &targetDir) +{ + m_converterObjects.clear(); + m_projectDir = project->projectDirectory(); + m_newProjectDir = targetDir; + m_project = project; + + m_rootDirFiles = QStringList(FILENAME_FILTER_QMLPROJECT); + const QString confFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF); + if (!confFile.isEmpty()) + m_rootDirFiles.append(confFile); + + bool retVal = prepareAndExecute(); + + if (retVal) + QMessageBox::information(nullptr, SUCCESS_TITLE, SUCCESS_TEXT); + else + QMessageBox::critical(nullptr, ERROR_TITLE, ERROR_TEXT.arg(m_errorText)); + + return retVal; +} + +bool CmakeProjectConverter::prepareAndExecute() +{ + GenerateCmake::CmakeFileGenerator cmakeGenerator; + + if (!performSanityCheck()) + return false; + if (!prepareBaseDirectoryStructure()) + return false; + if (!prepareCopy()) + return false; + if (!createPreparedProject()) + return false; + if (!cmakeGenerator.prepare(m_newProjectDir, false)) + return false; + if (!cmakeGenerator.execute()) + return false; + if (!modifyNewFiles()) + return false; + + return true; +} + +bool CmakeProjectConverter::isFileBlacklisted(const Utils::FilePath &file) const +{ + if (!file.fileName().compare(FILENAME_CMAKELISTS)) + return true; + if (!file.suffix().compare(FILENAME_SUFFIX_QMLPROJECT)) + return true; + if (!file.suffix().compare(FILENAME_SUFFIX_USER)) + return true; + if (m_rootDirFiles.contains(file.fileName())) + return true; + + return false; +} + +bool CmakeProjectConverter::isDirBlacklisted(const Utils::FilePath &dir) const +{ + if (!dir.isDir()) + return true; + + return false; +} + +const QString ERROR_CANNOT_WRITE_DIR = QCoreApplication::translate("QmlDesigner::CmakeProjectConverter", + "Unable to write to directory\n%1."); + +bool CmakeProjectConverter::performSanityCheck() +{ + if (!m_newProjectDir.parentDir().isWritableDir()) { + m_errorText = ERROR_CANNOT_WRITE_DIR.arg(m_newProjectDir.parentDir().toString()); + return false; + } + + return true; +} + +bool CmakeProjectConverter::prepareBaseDirectoryStructure() +{ + addDirectory(m_newProjectDir); + addDirectory(contentDir()); + addDirectory(sourceDir()); + addDirectory(importDir()); + addDirectory(assetDir()); + addDirectory(assetImportDir()); + addFile(contentDir().pathAppended(FILENAME_APPMAINQML)); + + return true; +} + +bool CmakeProjectConverter::prepareCopy() +{ + FilePaths rootFiles = m_projectDir.dirEntries({m_rootDirFiles, QDir::Files}); + for (const FilePath &file : rootFiles) { + addFile(file, m_newProjectDir.pathAppended(file.fileName())); + } + + prepareCopyDirFiles(m_projectDir, contentDir()); + + FilePaths subDirs = m_projectDir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot); + for (FilePath &subDir : subDirs) { + if (subDir.fileName() == DIRNAME_IMPORT) { + prepareCopyDirTree(subDir, importDir()); + } + else if (subDir.fileName() == DIRNAME_CPP) { + prepareCopyDirTree(subDir, sourceDir()); + } + else if (subDir.fileName() == DIRNAME_ASSET) { + prepareCopyDirTree(subDir, assetDir()); + } + else if (subDir.fileName() == DIRNAME_ASSETIMPORT) { + prepareCopyDirTree(subDir, assetImportDir()); + } + else { + prepareCopyDirTree(subDir, contentDir().pathAppended(subDir.fileName())); + } + } + + return true; +} + +bool CmakeProjectConverter::prepareCopyDirFiles(const FilePath &dir, const FilePath &targetDir) +{ + FilePaths dirFiles = dir.dirEntries(QDir::Files); + for (FilePath file : dirFiles) { + if (!isFileBlacklisted(file)) + addFile(file, targetDir.pathAppended(file.fileName())); + } + + return true; +} + +bool CmakeProjectConverter::prepareCopyDirTree(const FilePath &dir, const FilePath &targetDir) +{ + prepareCopyDirFiles(dir, targetDir); + FilePaths subDirs = dir.dirEntries(QDir::Dirs|QDir::NoDotAndDotDot); + for (FilePath &subDir : subDirs) { + if (isDirBlacklisted(subDir)) + continue; + addDirectory(targetDir.pathAppended(subDir.fileName())); + prepareCopyDirFiles(subDir, targetDir.pathAppended(subDir.fileName())); + prepareCopyDirTree(subDir, targetDir.pathAppended(subDir.fileName())); + } + + return true; +} + +bool CmakeProjectConverter::addDirectory(const Utils::FilePath &target) +{ + return addObject(ProjectConverterObjectType::Directory, FilePath(), target); +} + +bool CmakeProjectConverter::addFile(const Utils::FilePath &target) +{ + return addFile(FilePath(), target); +} + +bool CmakeProjectConverter::addFile(const Utils::FilePath &original, const Utils::FilePath &target) +{ + addDirectory(target.parentDir()); + return addObject(ProjectConverterObjectType::File, original, target); +} + +bool CmakeProjectConverter::addObject(ProjectConverterObjectType type, + const Utils::FilePath &original, const Utils::FilePath &target) +{ + if (target.isChildOf(m_projectDir)) + return false; + + if (!target.isChildOf(m_newProjectDir) && + ((type == ProjectConverterObjectType::Directory) && (target != m_newProjectDir))) { + return false; + } + + for (ProjectConverterObject &o : m_converterObjects) { + if (o.target == target) + return false; + } + + ProjectConverterObject object; + object.type = type; + object.target = target; + object.original = original; + + m_converterObjects.append(object); + + return true; +} + +bool CmakeProjectConverter::createPreparedProject() +{ + for (ProjectConverterObject &pco : m_converterObjects) { + if (pco.type == ProjectConverterObjectType::Directory) { + pco.target.createDir(); + } + else if (pco.type == ProjectConverterObjectType::File) { + if (pco.original.isEmpty()) { + QFile newFile(pco.target.toString()); + newFile.open(QIODevice::WriteOnly); + newFile.close(); + } + else { + pco.original.copyFile(pco.target); + } + } + } + + return true; +} + +const FilePath CmakeProjectConverter::contentDir() +{ + return m_newProjectDir.pathAppended(DIRNAME_CONTENT); +} + +const FilePath CmakeProjectConverter::sourceDir() +{ + return m_newProjectDir.pathAppended(DIRNAME_CPP); +} + +const FilePath CmakeProjectConverter::importDir() +{ + return m_newProjectDir.pathAppended(DIRNAME_IMPORT); +} + +const FilePath CmakeProjectConverter::assetDir() +{ + return contentDir().pathAppended(DIRNAME_ASSET); +} + +const FilePath CmakeProjectConverter::assetImportDir() +{ + return m_newProjectDir.pathAppended(DIRNAME_ASSETIMPORT); +} + +const FilePath CmakeProjectConverter::projectMainFile() const +{ + auto *target = m_project->activeTarget(); + if (target && target->buildSystem()) { + auto buildSystem = qobject_cast(target->buildSystem()); + if (buildSystem) { + return buildSystem->mainFilePath(); + } + } + return {}; +} + +const QString CmakeProjectConverter::projectMainClass() const +{ + return projectMainFile().baseName(); +} + +bool CmakeProjectConverter::modifyNewFiles() +{ + return modifyAppMainQml() && modifyProjectFile(); +} + +const char APPMAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectappmainqml.tpl"; + +bool CmakeProjectConverter::modifyAppMainQml() +{ + QString appMainQmlPath = contentDir().pathAppended(FILENAME_APPMAINQML).toString(); + QFile appMainQml(appMainQmlPath); + appMainQml.open(QIODevice::ReadWrite); + if (!appMainQml.isOpen()) + return false; + + QString templateContent = GenerateCmake::readTemplate(APPMAIN_QMLFILE_TEMPLATE_PATH); + QString appMainQmlContent = templateContent.arg(projectMainClass()); + + appMainQml.reset(); + appMainQml.write(appMainQmlContent.toUtf8()); + appMainQml.close(); + + return true; +} + +bool CmakeProjectConverter::modifyProjectFile() +{ + QString projectFileName = m_project->projectFilePath().fileName(); + FilePath projectFilePath = m_newProjectDir.pathAppended(projectFileName); + QFile projectFile(projectFilePath.toString()); + projectFile.open(QIODevice::ReadWrite); + if (!projectFile.isOpen()) + return false; + + QString projectFileContent = QString::fromUtf8(projectFile.readAll()); + const QRegularExpression mainFilePattern("^\\s*mainFile:\\s*\".*\"", QRegularExpression::MultilineOption); + const QString mainFileString(" mainFile: \"content/App.qml\""); + + projectFileContent.replace(mainFilePattern, mainFileString); + + projectFile.reset(); + projectFile.write(projectFileContent.toUtf8()); + projectFile.close(); + + return true; +} + +} //GenerateCmake +} //QmlDesigner diff --git a/src/plugins/qmldesigner/cmakeprojectconverter.h b/src/plugins/qmldesigner/cmakeprojectconverter.h new file mode 100644 index 00000000000..4b21d65ac8b --- /dev/null +++ b/src/plugins/qmldesigner/cmakeprojectconverter.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +#ifndef CMAKEPROJECTCONVERTER_H +#define CMAKEPROJECTCONVERTER_H + +#include +#include + +namespace QmlDesigner { + +namespace GenerateCmake { + +enum ProjectConverterObjectType { + File, + Directory +}; + +struct ProjectConverterObject { + ProjectConverterObjectType type; + Utils::FilePath target; + Utils::FilePath original; +}; + +class CmakeProjectConverter { + +public: + bool convertProject(const QmlProjectManager::QmlProject *project, + const Utils::FilePath &targetDir); + static void generateMenuEntry(); + static void onConvertProject(); + +private: + bool prepareAndExecute(); + bool isFileBlacklisted(const Utils::FilePath &file) const; + bool isDirBlacklisted(const Utils::FilePath &dir) const; + bool performSanityCheck(); + bool prepareBaseDirectoryStructure(); + bool prepareCopyDirFiles(const Utils::FilePath &dir, const Utils::FilePath &targetDir); + bool prepareCopyDirTree(const Utils::FilePath &dir, const Utils::FilePath &targetDir); + bool prepareCopy(); + bool addDirectory(const Utils::FilePath &target); + bool addFile(const Utils::FilePath &target); + bool addFile(const Utils::FilePath &original, const Utils::FilePath &target); + bool addObject(ProjectConverterObjectType type, + const Utils::FilePath &original, const Utils::FilePath &target); + bool createPreparedProject(); + + const Utils::FilePath contentDir(); + const Utils::FilePath sourceDir(); + const Utils::FilePath importDir(); + const Utils::FilePath assetDir(); + const Utils::FilePath assetImportDir(); + + const QString environmentVariable(const QString &key) const; + const Utils::FilePath projectMainFile() const; + const QString projectMainClass() const; + bool modifyNewFiles(); + bool modifyAppMainQml(); + bool modifyProjectFile(); + +private: + QList m_converterObjects; + QStringList m_rootDirFiles; + Utils::FilePath m_projectDir; + Utils::FilePath m_newProjectDir; + const QmlProjectManager::QmlProject *m_project; + QString m_errorText; +}; + +} //GenerateCmake +} //QmlDesigner + +#endif // CMAKEPROJECTCONVERTER_H diff --git a/src/plugins/qmldesigner/cmakeprojectconverterdialog.cpp b/src/plugins/qmldesigner/cmakeprojectconverterdialog.cpp new file mode 100644 index 00000000000..1c15043779c --- /dev/null +++ b/src/plugins/qmldesigner/cmakeprojectconverterdialog.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +#include "cmakeprojectconverterdialog.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Utils; + +namespace QmlDesigner { +namespace GenerateCmake { + +const QRegularExpression projectNameRegexp("^(?!(import))(?!(QtQml))(?!(QtQuick))(?:[A-Z][a-zA-Z0-9-_]*)$"); + +static bool projectNameValidationFunction(FancyLineEdit *editor, QString *) +{ + return editor->text().count(projectNameRegexp); +} + +static bool dirValidationFunction(FancyLineEdit *editor, QString *) +{ + return FilePath::fromString(editor->text()).isWritableDir(); +} + +const QString EXPLANATION_TEXT = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "This process creates a copy of the existing project. The new project's folder structure is adjusted for CMake build process and necessary related new files are generated.\n\nThe new project can be opened in Qt Creator using the main CMakeLists.txt file."); + +const QString PROJECT_NAME_LABEL = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "Name:"); + +const QString PARENT_DIR_LABEL = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "Create in:"); + +CmakeProjectConverterDialog::CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject) + : QDialog() +{ + const FilePath defaultDir = Core::DocumentManager::projectsDirectory(); + const QString defaultName = uniqueProjectName(defaultDir, oldProject->displayName()); + + QLabel *mainLabel = new QLabel(EXPLANATION_TEXT, this); + mainLabel->setWordWrap(true); + + mainLabel->setMargin(20); + mainLabel->setMinimumWidth(600); + + m_errorLabel = new InfoLabel(); + m_errorLabel->setType(InfoLabel::InfoType::None); + + m_nameEditor = new FancyLineEdit(); + m_nameEditor->setValidationFunction(projectNameValidationFunction); + m_nameEditor->setText(defaultName); + + m_dirSelector = new PathChooser(); + m_dirSelector->setExpectedKind(PathChooser::Directory); + m_dirSelector->setValidationFunction(dirValidationFunction); + m_dirSelector->setPath(defaultDir.toString()); + + QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); + m_okButton = buttons->button(QDialogButtonBox::Ok); + m_okButton->setDefault(true); + + connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); + connect(m_nameEditor, &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged); + connect(m_dirSelector->lineEdit(), &FancyLineEdit::textChanged, this, &CmakeProjectConverterDialog::pathValidChanged); + + QGroupBox *form = new QGroupBox(); + QFormLayout *formLayout = new QFormLayout(form); + formLayout->addRow(PROJECT_NAME_LABEL, m_nameEditor); + formLayout->addRow(PARENT_DIR_LABEL, m_dirSelector); + + QVBoxLayout *dialogLayout = new QVBoxLayout(this); + dialogLayout->addWidget(mainLabel); + dialogLayout->addWidget(form); + dialogLayout->addWidget(m_errorLabel); + dialogLayout->addWidget(buttons); + + pathValidChanged(); +} + +void CmakeProjectConverterDialog::pathValidChanged() +{ + bool valid = isValid(); + + if (valid) { + m_newProjectDir = FilePath::fromString(m_dirSelector->path()).pathAppended(m_nameEditor->text()); + } + else { + m_newProjectDir = FilePath(); + } + + const QString error = errorText(); + m_errorLabel->setType(error.isEmpty() ? InfoLabel::None : InfoLabel::Warning); + m_errorLabel->setText(error); + m_okButton->setEnabled(valid); +} + +const FilePath CmakeProjectConverterDialog::newPath() const +{ + return m_newProjectDir; +} + +const QStringList blackListedStarts = {"import","QtQml","QtQuick"}; + +const QString CmakeProjectConverterDialog::startsWithBlacklisted(const QString &text) const +{ + for (const QString &badWord : blackListedStarts) { + if (text.startsWith(badWord)) + return badWord; + } + + return {}; +} + +const QString ERROR_TEXT_NAME_EMPTY = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "Name is empty."); +const QString ERROR_TEXT_NAME_BAD_START = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "Name must not start with \"%1\"."); +const QString ERROR_TEXT_NAME_LOWERCASE_START = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "Name must begin with a capital letter"); +const QString ERROR_TEXT_NAME_BAD_CHARACTERS = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "Name must contain only letters, numbers or characters - _."); + +const QString ERROR_DIR_NOT_DIR = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "Target is not a directory."); +const QString ERROR_DIR_NOT_WRITABLE = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "Cannot write to target directory."); +const QString ERROR_DIR_EXISTS = QCoreApplication::translate( + "QmlDesigner::CmakeProjectConverterDialog", + "Project directory already exists."); + +const QString CmakeProjectConverterDialog::errorText() const +{ + QString text; + + if (!m_nameEditor->isValid()) { + QString name = m_nameEditor->text(); + + if (name.isEmpty()) + return ERROR_TEXT_NAME_EMPTY; + + const QString badStart = startsWithBlacklisted(text); + if (!badStart.isEmpty()) + return ERROR_TEXT_NAME_BAD_START.arg(badStart); + + if (name[0].isLower()) + return ERROR_TEXT_NAME_LOWERCASE_START; + + return ERROR_TEXT_NAME_BAD_CHARACTERS; + + } + + if (!m_dirSelector->isValid()) { + FilePath path = m_dirSelector->filePath(); + if (!path.isDir()) + return ERROR_DIR_NOT_DIR; + if (!path.isWritableDir()) + return ERROR_DIR_NOT_WRITABLE; + } + + if (FilePath::fromString(m_dirSelector->path()).pathAppended(m_nameEditor->text()).exists()) + return ERROR_DIR_EXISTS; + + + return text; +} + +const QString CmakeProjectConverterDialog::uniqueProjectName(const FilePath &dir, const QString &oldName) const +{ + for (unsigned i = 0; ; ++i) { + QString name = oldName; + if (i) + name += QString::number(i); + if (!dir.pathAppended(name).exists()) + return name; + } + return oldName; +} + +bool CmakeProjectConverterDialog::isValid() +{ + FilePath newPath = FilePath::fromString(m_dirSelector->path()).pathAppended(m_nameEditor->text()); + return m_dirSelector->isValid() && m_nameEditor->isValid() && !newPath.exists(); +} + +} //GenerateCmake +} //QmlDesigner diff --git a/src/plugins/qmldesigner/cmakeprojectconverterdialog.h b/src/plugins/qmldesigner/cmakeprojectconverterdialog.h new file mode 100644 index 00000000000..a3143de7cd8 --- /dev/null +++ b/src/plugins/qmldesigner/cmakeprojectconverterdialog.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Design Tooling +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + + +#ifndef CMAKEPROJECTCONVERTERDIALOG_H +#define CMAKEPROJECTCONVERTERDIALOG_H + +#include +#include +#include +#include +#include + +#include + +namespace QmlDesigner { +namespace GenerateCmake { + +class CmakeProjectConverterDialog : public QDialog +{ + Q_OBJECT + +public: + CmakeProjectConverterDialog(const QmlProjectManager::QmlProject *oldProject); + const Utils::FilePath newPath() const; + +public slots: + void pathValidChanged(); + +private: + const QString startsWithBlacklisted(const QString &text) const; + const QString errorText() const; + const QString uniqueProjectName(const Utils::FilePath &dir, const QString &oldName) const; + bool isValid(); + +private: + Utils::FilePath m_newProjectDir; + Utils::FancyLineEdit *m_nameEditor; + Utils::PathChooser *m_dirSelector; + Utils::InfoLabel *m_errorLabel; + QPushButton *m_okButton; +}; + +} //GenerateCmake +} //Qmldesigner + +#endif // CMAKEPROJECTCONVERTERDIALOG_H diff --git a/src/plugins/qmldesigner/generatecmakelists.cpp b/src/plugins/qmldesigner/generatecmakelists.cpp index d4758619ccd..a585f2d2d40 100644 --- a/src/plugins/qmldesigner/generatecmakelists.cpp +++ b/src/plugins/qmldesigner/generatecmakelists.cpp @@ -66,24 +66,26 @@ enum ProjectDirectoryError { NoError = 0, MissingContentDir = 1<<1, MissingImportDir = 1<<2, - MissingAssetImportDir = 1<<3, - MissingCppDir = 1<<4, - MissingMainCMake = 1<<5, - MissingMainQml = 1<<6, - MissingAppMainQml = 1<<7, - MissingQmlModules = 1<<8, - MissingMainCpp = 1<<9, - MissingMainCppHeader = 1<<10, - MissingEnvHeader = 1<<11 + MissingAssetDir = 1<<3, + MissingAssetImportDir = 1<<4, + MissingCppDir = 1<<5, + MissingMainCMake = 1<<6, + MissingMainQml = 1<<7, + MissingAppMainQml = 1<<8, + MissingQmlModules = 1<<9, + MissingMainCpp = 1<<10, + MissingMainCppHeader = 1<<11, + MissingEnvHeader = 1<<12 }; -QVector queuedFiles; +const QString MENU_ITEM_GENERATE = QCoreApplication::translate("QmlDesigner::GenerateCmake", + "Generate CMake Build Files"); void generateMenuEntry() { Core::ActionContainer *menu = Core::ActionManager::actionContainer(Core::Constants::M_FILE); - auto action = new QAction(QCoreApplication::translate("QmlDesigner::GenerateCmake", "Export to Qt Creator (CMake)")); + auto action = new QAction(MENU_ITEM_GENERATE); QObject::connect(action, &QAction::triggered, GenerateCmake::onGenerateCmakeLists); Core::Command *cmd = Core::ActionManager::registerAction(action, "QmlProject.CreateCMakeLists"); menu->addAction(cmd, Core::Constants::G_FILE_EXPORT); @@ -106,11 +108,19 @@ void onGenerateCmakeLists() return; } - queuedFiles.clear(); - GenerateCmakeLists::generateCmakes(rootDir); - GenerateEntryPoints::generateEntryPointFiles(rootDir); - if (showConfirmationDialog(rootDir)) - writeQueuedFiles(); + CmakeFileGenerator cmakeGen; + cmakeGen.prepare(rootDir); + + FilePaths allFiles; + for (const GeneratableFile &file: cmakeGen.fileQueue().queuedFiles()) + allFiles.append(file.filePath); + + CmakeGeneratorDialog dialog(rootDir, allFiles); + if (dialog.exec()) { + FilePaths confirmedFiles = dialog.getFilePaths(); + cmakeGen.filterFileQueue(confirmedFiles); + cmakeGen.execute(); + } } bool isErrorFatal(int error) @@ -135,7 +145,7 @@ int isProjectCorrectlyFormed(const FilePath &rootDir) if (!rootDir.pathAppended(DIRNAME_IMPORT).exists()) errors |= MissingImportDir; - if (!rootDir.pathAppended(DIRNAME_ASSET).exists()) + if (!rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists()) errors |= MissingAssetImportDir; if (!rootDir.pathAppended(DIRNAME_CPP).exists()) @@ -157,13 +167,6 @@ int isProjectCorrectlyFormed(const FilePath &rootDir) return errors; } -void removeUnconfirmedQueuedFiles(const Utils::FilePaths confirmedFiles) -{ - QtConcurrent::blockingFilter(queuedFiles, [confirmedFiles](const GeneratableFile &qf) { - return confirmedFiles.contains(qf.filePath); - }); -} - const QString WARNING_MISSING_STRUCTURE_FATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", "The project is not properly structured for automatically generating CMake files.\n\nAborting process.\n\nThe following files or directories are missing:\n\n%1"); //const QString WARNING_MISSING_STRUCTURE_NONFATAL = QCoreApplication::translate("QmlDesigner::GenerateCmake", @@ -198,44 +201,32 @@ void showProjectDirErrorDialog(int error) } } -bool showConfirmationDialog(const Utils::FilePath &rootDir) -{ - Utils::FilePaths files; - for (GeneratableFile &file: queuedFiles) - files.append(file.filePath); - - CmakeGeneratorDialog dialog(rootDir, files); - if (dialog.exec()) { - Utils::FilePaths confirmedFiles = dialog.getFilePaths(); - removeUnconfirmedQueuedFiles(confirmedFiles); - - return true; - } - - return false; -} - -bool queueFile(const FilePath &filePath, const QString &fileContent) +bool FileQueue::queueFile(const FilePath &filePath, const QString &fileContent) { GeneratableFile file; file.filePath = filePath; file.content = fileContent; file.fileExists = filePath.exists(); - queuedFiles.append(file); + m_queuedFiles.append(file); return true; } -bool writeQueuedFiles() +const QVector FileQueue::queuedFiles() const { - for (GeneratableFile &file: queuedFiles) + return m_queuedFiles; +} + +bool FileQueue::writeQueuedFiles() +{ + for (GeneratableFile &file: m_queuedFiles) if (!writeFile(file)) return false; return true; } -bool writeFile(const GeneratableFile &file) +bool FileQueue::writeFile(const GeneratableFile &file) { QFile fileHandle(file.filePath.toString()); fileHandle.open(QIODevice::WriteOnly); @@ -246,6 +237,13 @@ bool writeFile(const GeneratableFile &file) return true; } +void FileQueue::filterFiles(const Utils::FilePaths keepFiles) +{ + QtConcurrent::blockingFilter(m_queuedFiles, [keepFiles](const GeneratableFile &qf) { + return keepFiles.contains(qf.filePath); + }); +} + QString readTemplate(const QString &templatePath) { QFile templatefile(templatePath); @@ -257,54 +255,90 @@ QString readTemplate(const QString &templatePath) return content; } +const QString projectEnvironmentVariable(const QString &key) +{ + QString value = {}; + + auto *target = ProjectExplorer::SessionManager::startupProject()->activeTarget(); + if (target && target->buildSystem()) { + auto buildSystem = qobject_cast(target->buildSystem()); + if (buildSystem) { + auto envItems = buildSystem->environment(); + auto confEnv = std::find_if(envItems.begin(), envItems.end(), + [key](NameValueItem &item){return item.name == key;}); + if (confEnv != envItems.end()) + value = confEnv->value; + } + } + return value; } -namespace GenerateCmakeLists { - -QStringList moduleNames; - const QDir::Filters FILES_ONLY = QDir::Files; const QDir::Filters DIRS_ONLY = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot; const char MAIN_CMAKEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmaincmakelists.tpl"; const char QMLMODULES_FILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodules.tpl"; -bool generateCmakes(const FilePath &rootDir) +bool CmakeFileGenerator::prepare(const FilePath &rootDir, bool checkFileBelongs) { - moduleNames.clear(); + m_checkFileIsInProject = checkFileBelongs; FilePath contentDir = rootDir.pathAppended(DIRNAME_CONTENT); FilePath importDir = rootDir.pathAppended(DIRNAME_IMPORT); - FilePath assetDir = rootDir.pathAppended(DIRNAME_ASSET); + FilePath assetImportDir = rootDir.pathAppended(DIRNAME_ASSETIMPORT); generateModuleCmake(contentDir); generateImportCmake(importDir); - generateImportCmake(assetDir); + generateImportCmake(assetImportDir); generateMainCmake(rootDir); + generateEntryPointFiles(rootDir); return true; } +const FileQueue CmakeFileGenerator::fileQueue() const +{ + return m_fileQueue; +} + +void CmakeFileGenerator::filterFileQueue(const Utils::FilePaths &keepFiles) +{ + m_fileQueue.filterFiles(keepFiles); +} + +bool CmakeFileGenerator::execute() +{ + return m_fileQueue.writeQueuedFiles(); +} + const char DO_NOT_EDIT_FILE_COMMENT[] = "### This file is automatically generated by Qt Design Studio.\n### Do not change\n\n"; const char ADD_SUBDIR[] = "add_subdirectory(%1)\n"; -void generateMainCmake(const FilePath &rootDir) +void CmakeFileGenerator::generateMainCmake(const FilePath &rootDir) { //TODO startupProject() may be a terrible way to try to get "current project". It's not necessarily the same thing at all. QString projectName = ProjectExplorer::SessionManager::startupProject()->displayName(); QString appName = projectName + "App"; - QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH).arg(appName); + QString fileSection = ""; + const QString qtcontrolsConfFile = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF); + if (!qtcontrolsConfFile.isEmpty()) + fileSection = QString(" FILES\n %1").arg(qtcontrolsConfFile); + + QString cmakeFileContent = GenerateCmake::readTemplate(MAIN_CMAKEFILE_TEMPLATE_PATH) + .arg(appName) + .arg(fileSection); + queueCmakeFile(rootDir, cmakeFileContent); QString subdirIncludes; subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_CONTENT)); subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_IMPORT)); - if (rootDir.pathAppended(DIRNAME_ASSET).exists()) - subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_ASSET)); + if (rootDir.pathAppended(DIRNAME_ASSETIMPORT).exists()) + subdirIncludes.append(QString(ADD_SUBDIR).arg(DIRNAME_ASSETIMPORT)); QString modulesAsPlugins; - for (const QString &moduleName : moduleNames) + for (const QString &moduleName : m_moduleNames) modulesAsPlugins.append(" " + moduleName + "plugin\n"); QString moduleFileContent = GenerateCmake::readTemplate(QMLMODULES_FILE_TEMPLATE_PATH) @@ -312,10 +346,10 @@ void generateMainCmake(const FilePath &rootDir) .arg(subdirIncludes) .arg(modulesAsPlugins); - GenerateCmake::queueFile(rootDir.pathAppended(FILENAME_MODULES), moduleFileContent); + m_fileQueue.queueFile(rootDir.pathAppended(FILENAME_MODULES), moduleFileContent); } -void generateImportCmake(const FilePath &dir, const QString &modulePrefix) +void CmakeFileGenerator::generateImportCmake(const FilePath &dir, const QString &modulePrefix) { if (!dir.exists()) return; @@ -347,7 +381,7 @@ const char MODULEFILE_PROPERTY_SINGLETON[] = "QT_QML_SINGLETON_TYPE"; const char MODULEFILE_PROPERTY_SET[] = "set_source_files_properties(%1\n PROPERTIES\n %2 %3\n)\n\n"; const char MODULEFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmodulecmakelists.tpl"; -void generateModuleCmake(const FilePath &dir, const QString &uri) +void CmakeFileGenerator::generateModuleCmake(const FilePath &dir, const QString &uri) { QString fileTemplate = GenerateCmake::readTemplate(MODULEFILE_TEMPLATE_PATH); @@ -381,15 +415,16 @@ void generateModuleCmake(const FilePath &dir, const QString &uri) QString moduleUri = uri.isEmpty() ? dir.fileName() : uri; + QString moduleName = QString(moduleUri).replace('.', '_'); - moduleNames.append(moduleName); + m_moduleNames.append(moduleName); QString fileContent; fileContent.append(fileTemplate.arg(singletonContent, moduleName, moduleUri, moduleContent)); queueCmakeFile(dir, fileContent); } -QStringList getSingletonsFromQmldirFile(const FilePath &filePath) +QStringList CmakeFileGenerator::getSingletonsFromQmldirFile(const FilePath &filePath) { QStringList singletons; QFile f(filePath.toString()); @@ -412,36 +447,42 @@ QStringList getSingletonsFromQmldirFile(const FilePath &filePath) return singletons; } -FilePaths getDirectoryQmls(const FilePath &dir) +QStringList CmakeFileGenerator::getDirectoryQmls(const FilePath &dir) { - const QStringList qmlFilesOnly("*.qml"); - ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + QStringList moduleFiles; + + const QStringList qmlFilesOnly(FILENAME_FILTER_QML); FilePaths allFiles = dir.dirEntries({qmlFilesOnly, FILES_ONLY}); - FilePaths moduleFiles; for (FilePath &file : allFiles) { - if (!isFileBlacklisted(file.fileName()) && - project->isKnownFile(file)) { - moduleFiles.append(file); + if (includeFile(file)) { + moduleFiles.append(file.fileName()); } } return moduleFiles; } -QStringList getDirectoryTreeQmls(const FilePath &dir) +QStringList CmakeFileGenerator::getDirectoryResources(const FilePath &dir) { - const QStringList qmlFilesOnly("*.qml"); - ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); - QStringList qmlFileList; + QStringList moduleFiles; - FilePaths thisDirFiles = dir.dirEntries({qmlFilesOnly, FILES_ONLY}); - for (FilePath &file : thisDirFiles) { - if (!isFileBlacklisted(file.fileName()) && - project->isKnownFile(file)) { - qmlFileList.append(file.fileName()); + FilePaths allFiles = dir.dirEntries(FILES_ONLY); + for (FilePath &file : allFiles) { + if (!file.fileName().endsWith(".qml", Qt::CaseInsensitive) && + includeFile(file)) { + moduleFiles.append(file.fileName()); } } + return moduleFiles; +} + +QStringList CmakeFileGenerator::getDirectoryTreeQmls(const FilePath &dir) +{ + QStringList qmlFileList; + + qmlFileList.append(getDirectoryQmls(dir)); + FilePaths subDirsList = dir.dirEntries(DIRS_ONLY); for (FilePath &subDir : subDirsList) { if (isDirBlacklisted(subDir)) @@ -455,19 +496,11 @@ QStringList getDirectoryTreeQmls(const FilePath &dir) return qmlFileList; } -QStringList getDirectoryTreeResources(const FilePath &dir) +QStringList CmakeFileGenerator::getDirectoryTreeResources(const FilePath &dir) { - ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); QStringList resourceFileList; - FilePaths thisDirFiles = dir.dirEntries(FILES_ONLY); - for (FilePath &file : thisDirFiles) { - if (!isFileBlacklisted(file.fileName()) && - !file.fileName().endsWith(".qml", Qt::CaseInsensitive) && - project->isKnownFile(file)) { - resourceFileList.append(file.fileName()); - } - } + resourceFileList.append(getDirectoryResources(dir)); FilePaths subDirsList = dir.dirEntries(DIRS_ONLY); for (FilePath &subDir : subDirsList) { @@ -483,28 +516,41 @@ QStringList getDirectoryTreeResources(const FilePath &dir) return resourceFileList; } -void queueCmakeFile(const FilePath &dir, const QString &content) +void CmakeFileGenerator::queueCmakeFile(const FilePath &dir, const QString &content) { FilePath filePath = dir.pathAppended(FILENAME_CMAKELISTS); - GenerateCmake::queueFile(filePath, content); + m_fileQueue.queueFile(filePath, content); } -bool isFileBlacklisted(const QString &fileName) +bool CmakeFileGenerator::isFileBlacklisted(const QString &fileName) { return (!fileName.compare(FILENAME_QMLDIR) || !fileName.compare(FILENAME_CMAKELISTS)); } -bool isDirBlacklisted(const FilePath &dir) +bool CmakeFileGenerator::isDirBlacklisted(const FilePath &dir) { return (!dir.fileName().compare(DIRNAME_DESIGNER)); } +bool CmakeFileGenerator::includeFile(const FilePath &filePath) +{ + if (m_checkFileIsInProject) { + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); + if (!project->isKnownFile(filePath)) + return false; + } + + return !isFileBlacklisted(filePath.fileName()); } -namespace GenerateEntryPoints { -bool generateEntryPointFiles(const FilePath &dir) + +bool CmakeFileGenerator::generateEntryPointFiles(const FilePath &dir) { + const QString qtcontrolsConf = GenerateCmake::projectEnvironmentVariable(ENV_VARIABLE_CONTROLCONF); + if (!qtcontrolsConf.isEmpty()) + m_resourceFileLocations.append(qtcontrolsConf); + bool cppOk = generateMainCpp(dir); bool qmlOk = generateMainQml(dir); @@ -517,23 +563,23 @@ const char MAIN_CPPFILE_HEADER_PLUGIN_LINE[] = "Q_IMPORT_QML_PLUGIN(%1)\n"; const char ENV_HEADER_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectenvheader.tpl"; const char ENV_HEADER_VARIABLE_LINE[] = " qputenv(\"%1\", \"%2\");\n"; -bool generateMainCpp(const FilePath &dir) +bool CmakeFileGenerator::generateMainCpp(const FilePath &dir) { FilePath srcDir = dir.pathAppended(DIRNAME_CPP); QString cppContent = GenerateCmake::readTemplate(MAIN_CPPFILE_TEMPLATE_PATH); FilePath cppFilePath = srcDir.pathAppended(FILENAME_MAINCPP); - bool cppOk = GenerateCmake::queueFile(cppFilePath, cppContent); + bool cppOk = m_fileQueue.queueFile(cppFilePath, cppContent); QString modulesAsPlugins; - for (const QString &moduleName : GenerateCmakeLists::moduleNames) + for (const QString &moduleName : m_moduleNames) modulesAsPlugins.append( QString(MAIN_CPPFILE_HEADER_PLUGIN_LINE).arg(moduleName + "Plugin")); QString headerContent = GenerateCmake::readTemplate(MAIN_CPPFILE_HEADER_TEMPLATE_PATH) .arg(modulesAsPlugins); FilePath headerFilePath = srcDir.pathAppended(FILENAME_MAINCPP_HEADER); - bool pluginHeaderOk = GenerateCmake::queueFile(headerFilePath, headerContent); + bool pluginHeaderOk = m_fileQueue.queueFile(headerFilePath, headerContent); bool envHeaderOk = true; QString environment; @@ -551,7 +597,7 @@ bool generateMainCpp(const FilePath &dir) QString envHeaderContent = GenerateCmake::readTemplate(ENV_HEADER_TEMPLATE_PATH) .arg(environment); FilePath envHeaderPath = srcDir.pathAppended(FILENAME_ENV_HEADER); - envHeaderOk = GenerateCmake::queueFile(envHeaderPath, envHeaderContent); + envHeaderOk = m_fileQueue.queueFile(envHeaderPath, envHeaderContent); } } @@ -560,24 +606,21 @@ bool generateMainCpp(const FilePath &dir) const char MAIN_QMLFILE_TEMPLATE_PATH[] = ":/boilerplatetemplates/qmlprojectmainqml.tpl"; -bool generateMainQml(const FilePath &dir) +bool CmakeFileGenerator::generateMainQml(const FilePath &dir) { QString content = GenerateCmake::readTemplate(MAIN_QMLFILE_TEMPLATE_PATH); FilePath filePath = dir.pathAppended(FILENAME_MAINQML); - return GenerateCmake::queueFile(filePath, content); + return m_fileQueue.queueFile(filePath, content); } -const QStringList resourceFileLocations = {"qtquickcontrols2.conf"}; - -bool isFileResource(const QString &relativeFilePath) +bool CmakeFileGenerator::isFileResource(const QString &relativeFilePath) { - if (resourceFileLocations.contains(relativeFilePath)) + if (m_resourceFileLocations.contains(relativeFilePath)) return true; return false; } -} //GenerateEntryPoints - +} //GenerateCmake } //QmlDesigner diff --git a/src/plugins/qmldesigner/generatecmakelists.h b/src/plugins/qmldesigner/generatecmakelists.h index eafe72defcb..7045ce17c8a 100644 --- a/src/plugins/qmldesigner/generatecmakelists.h +++ b/src/plugins/qmldesigner/generatecmakelists.h @@ -43,31 +43,56 @@ void generateMenuEntry(); void onGenerateCmakeLists(); bool isErrorFatal(int error); int isProjectCorrectlyFormed(const Utils::FilePath &rootDir); -void removeUnconfirmedQueuedFiles(const Utils::FilePaths confirmedFiles); void showProjectDirErrorDialog(int error); -bool showConfirmationDialog(const Utils::FilePath &rootDir); -bool queueFile(const Utils::FilePath &filePath, const QString &fileContent); -bool writeFile(const GeneratableFile &file); -bool writeQueuedFiles(); QString readTemplate(const QString &templatePath); -} -namespace GenerateCmakeLists { -bool generateCmakes(const Utils::FilePath &rootDir); -void generateMainCmake(const Utils::FilePath &rootDir); -void generateImportCmake(const Utils::FilePath &dir, const QString &modulePrefix = QString()); -void generateModuleCmake(const Utils::FilePath &dir, const QString &moduleUri = QString()); -Utils::FilePaths getDirectoryQmls(const Utils::FilePath &dir); -QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath); -QStringList getDirectoryTreeQmls(const Utils::FilePath &dir); -QStringList getDirectoryTreeResources(const Utils::FilePath &dir); -void queueCmakeFile(const Utils::FilePath &filePath, const QString &content); -bool isFileBlacklisted(const QString &fileName); -bool isDirBlacklisted(const Utils::FilePath &dir); -} -namespace GenerateEntryPoints { -bool generateEntryPointFiles(const Utils::FilePath &dir); -bool generateMainCpp(const Utils::FilePath &dir); -bool generateMainQml(const Utils::FilePath &dir); -bool isFileResource(const QString &relativeFilePath); -} -} +const QString projectEnvironmentVariable(const QString &key); + +class FileQueue { +public: + bool queueFile(const Utils::FilePath &filePath, const QString &fileContent); + const QVector queuedFiles() const; + bool writeQueuedFiles(); + void filterFiles(const Utils::FilePaths keepFiles); + +private: + bool writeFile(const GeneratableFile &file); + +private: + QVector m_queuedFiles; +}; + +class CmakeFileGenerator { +public: + bool prepare(const Utils::FilePath &rootDir, bool check = true); + const FileQueue fileQueue() const; + void filterFileQueue(const Utils::FilePaths &keepFiles); + bool execute(); + +private: + void generateMainCmake(const Utils::FilePath &rootDir); + void generateImportCmake(const Utils::FilePath &dir, const QString &modulePrefix = QString()); + void generateModuleCmake(const Utils::FilePath &dir, const QString &moduleUri = QString()); + bool generateEntryPointFiles(const Utils::FilePath &dir); + bool generateMainCpp(const Utils::FilePath &dir); + bool generateMainQml(const Utils::FilePath &dir); + QStringList getDirectoryQmls(const Utils::FilePath &dir); + QStringList getDirectoryResources(const Utils::FilePath &dir); + QStringList getSingletonsFromQmldirFile(const Utils::FilePath &filePath); + QStringList getDirectoryTreeQmls(const Utils::FilePath &dir); + QStringList getDirectoryTreeResources(const Utils::FilePath &dir); + void queueCmakeFile(const Utils::FilePath &filePath, const QString &content); + bool isFileResource(const QString &relativeFilePath); + bool isFileBlacklisted(const QString &fileName); + bool isDirBlacklisted(const Utils::FilePath &dir); + bool includeFile(const Utils::FilePath &filePath); + +private: + FileQueue m_fileQueue; + QStringList m_resourceFileLocations; + QStringList m_moduleNames; + bool m_checkFileIsInProject; +}; + +} //GenerateCmake + +} //QmlDesigner diff --git a/src/plugins/qmldesigner/generatecmakelistsconstants.h b/src/plugins/qmldesigner/generatecmakelistsconstants.h index 0374ac2ad65..e4358dc5999 100644 --- a/src/plugins/qmldesigner/generatecmakelistsconstants.h +++ b/src/plugins/qmldesigner/generatecmakelistsconstants.h @@ -34,7 +34,8 @@ namespace Constants { const char DIRNAME_CONTENT[] = "content"; const char DIRNAME_IMPORT[] = "imports"; -const char DIRNAME_ASSET[] = "asset_imports"; +const char DIRNAME_ASSET[] = "assets"; +const char DIRNAME_ASSETIMPORT[] = "asset_imports"; const char DIRNAME_CPP[] = "src"; const char DIRNAME_DESIGNER[] = "designer"; @@ -47,6 +48,15 @@ const char FILENAME_MODULES[] = "qmlmodules"; const char FILENAME_QMLDIR[] = "qmldir"; const char FILENAME_ENV_HEADER[] = "app_environment.h"; +const char FILENAME_SUFFIX_QMLPROJECT[] = "qmlproject"; +const char FILENAME_SUFFIX_QML[] = "qml"; +const char FILENAME_SUFFIX_USER[] = "user"; + +const char FILENAME_FILTER_QMLPROJECT[] = "*.qmlproject"; +const char FILENAME_FILTER_QML[] = "*.qml"; + +const char ENV_VARIABLE_CONTROLCONF[] = "QT_QUICK_CONTROLS_CONF"; + } //Constants } //GenerateCmake } //QmlDesigner diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index 979a0321f26..3748a2164e0 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -24,6 +24,7 @@ ****************************************************************************/ #include "qmldesignerplugin.h" +#include "cmakeprojectconverter.h" #include "designmodecontext.h" #include "designmodewidget.h" #include "exception.h" @@ -230,6 +231,7 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e GenerateResource::generateMenuEntry(); GenerateCmake::generateMenuEntry(); + GenerateCmake::CmakeProjectConverter::generateMenuEntry(); const QString fontPath = Core::ICore::resourcePath( diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index a3f5649680c..4ab3c754c9f 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -1035,6 +1035,8 @@ Project { "cmakegeneratordialogtreemodel.h", "cmakegeneratordialog.cpp", "cmakegeneratordialog.h", + "cmakeprojectconverter.cpp", + "cmakeprojectconverter.h", "designersettings.cpp", "designersettings.h", "designmodecontext.cpp", diff --git a/src/plugins/qmldesigner/qmlprojectappmainqml.tpl b/src/plugins/qmldesigner/qmlprojectappmainqml.tpl new file mode 100644 index 00000000000..35f8218dc65 --- /dev/null +++ b/src/plugins/qmldesigner/qmlprojectappmainqml.tpl @@ -0,0 +1,14 @@ +import QtQuick +import QtQuick.Window + +Window { + visible: true + title: "%1" + width: mainScreen.width + height: mainScreen.height + + %1 { + id: mainScreen + } + +} diff --git a/src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl b/src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl index 14a91d20eaf..423ed1a921a 100644 --- a/src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl +++ b/src/plugins/qmldesigner/qmlprojectmaincmakelists.tpl @@ -10,8 +10,7 @@ qt_add_executable(%1 src/main.cpp) qt_add_resources(%1 "configuration" PREFIX "/" - FILES - qtquickcontrols2.conf +%2 ) target_link_libraries(%1 PRIVATE From 00c7161e3359d5eb59d1463df9ad3448d74f5414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20L=C3=B6hning?= Date: Mon, 13 Dec 2021 21:59:38 +0100 Subject: [PATCH 59/76] Squish: Run tst_save_before_build on CMake and qmake Change-Id: I91501633e0fe7c863c43af4224474c09f57dbf8c Reviewed-by: Reviewed-by: Christian Stenger --- tests/system/README | 2 +- .../tst_save_before_build/test.py | 82 ++++++++++++------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/tests/system/README b/tests/system/README index 61847485fbf..2d71245cb34 100644 --- a/tests/system/README +++ b/tests/system/README @@ -59,7 +59,7 @@ This folder must contain the following: * a speedcrunch 0.11 repository (or source copy) inside 'creator-test-data' named 'speedcrunch' Fifth - you'll have to make sure that some needed tools are available (no matter on which OS you're on). - * cmake + * cmake 3.14 or newer * wget or curl, capable of HTTPS Normally it should be okay to just install them as usual and add their executables' path(s) to the PATH variable. diff --git a/tests/system/suite_general/tst_save_before_build/test.py b/tests/system/suite_general/tst_save_before_build/test.py index 728f849975a..3befbbd8eac 100644 --- a/tests/system/suite_general/tst_save_before_build/test.py +++ b/tests/system/suite_general/tst_save_before_build/test.py @@ -25,43 +25,63 @@ source("../../shared/qtcreator.py") -def ensureSaveBeforeBuildChecked(shouldBeChecked): + +def __openBuildAndRunSettings__(): invokeMenuItem("Tools", "Options...") mouseClick(waitForObjectItem(":Options_QListView", "Build & Run")) clickOnTab(":Options.qt_tabwidget_tabbar_QTabBar", "General") - if test.compare(waitForObject(":Build and Run.Save all files before build_QCheckBox").checked, - shouldBeChecked, "'Save all files before build' should be %s" % str(shouldBeChecked)): - clickButton(waitForObject(":Options.Cancel_QPushButton")) - else: - ensureChecked(":Build and Run.Save all files before build_QCheckBox", shouldBeChecked) - clickButton(waitForObject(":Options.OK_QPushButton")) + + +def verifySaveBeforeBuildChecked(shouldBeChecked): + __openBuildAndRunSettings__() + test.compare(waitForObject(":Build and Run.Save all files before build_QCheckBox").checked, + shouldBeChecked, + "'Save all files before build' should be %s" % str(shouldBeChecked)) + clickButton(waitForObject(":Options.Cancel_QPushButton")) + + +def ensureSaveBeforeBuildChecked(shouldBeChecked): + __openBuildAndRunSettings__() + ensureChecked(":Build and Run.Save all files before build_QCheckBox", shouldBeChecked) + clickButton(waitForObject(":Options.OK_QPushButton")) + def main(): startQC() if not startedWithoutPluginError(): return - ensureSaveBeforeBuildChecked(False) - # create qt quick application - createNewQtQuickApplication(tempDir(), "SampleApp") - for expectDialog in [True, False]: - files = ["SampleApp.SampleApp\\.pro", - "SampleApp.Sources.main\\.cpp", - "SampleApp.Resources.qml\.qrc./.main\\.qml"] - for i, file in enumerate(files): - if not openDocument(file): - test.fatal("Could not open file '%s'" % simpleFileName(file)) - continue - test.log("Changing file '%s'" % simpleFileName(file)) - typeLines(getEditorForFileSuffix(file, True), "") - # try to compile - clickButton(waitForObject(":*Qt Creator.Build Project_Core::Internal::FancyToolButton")) - try: - ensureChecked(":Save Changes.Always save files before build_QCheckBox", - i == len(files) - 1, 5000) # At the last iteration, check the box - clickButton(waitForObject(":Save Changes.Save All_QPushButton")) - test.verify(expectDialog, "The 'Save Changes' dialog was shown.") - except: - test.verify(not expectDialog, "The 'Save Changes' dialog was not shown.") - waitForCompile() - ensureSaveBeforeBuildChecked(True) + verifySaveBeforeBuildChecked(False) + for buildSystem in ["CMake", "qmake"]: + projectName = "SampleApp-" + buildSystem + ensureSaveBeforeBuildChecked(False) + # create qt quick application + createNewQtQuickApplication(tempDir(), projectName, buildSystem=buildSystem) + for expectDialog in [True, False]: + verifySaveBeforeBuildChecked(not expectDialog) + if buildSystem == "CMake": + files = ["%s.CMakeLists\\.txt" % projectName, + "%s.%s.Source Files.main\\.cpp" % (projectName, projectName), + "%s.%s.qml\.qrc./.main\\.qml" % (projectName, projectName)] + elif buildSystem == "qmake": + files = ["%s.%s\\.pro" % (projectName, projectName), + "%s.Sources.main\\.cpp" % projectName, + "%s.Resources.qml\.qrc./.main\\.qml" % projectName] + for i, file in enumerate(files): + if not openDocument(file): + test.fatal("Could not open file '%s'" % simpleFileName(file)) + continue + test.log("Changing file '%s'" % simpleFileName(file)) + typeLines(getEditorForFileSuffix(file, True), "") + # try to compile + clickButton(waitForObject(":*Qt Creator.Build Project_Core::Internal::FancyToolButton")) + try: + ensureChecked(":Save Changes.Always save files before build_QCheckBox", + i == len(files) - 1, 5000) # At the last iteration, check the box + clickButton(waitForObject(":Save Changes.Save All_QPushButton")) + test.verify(expectDialog, "The 'Save Changes' dialog was shown.") + except: + test.verify(not expectDialog, "The 'Save Changes' dialog was not shown.") + waitForCompile() + verifySaveBeforeBuildChecked(True) + invokeMenuItem("File", "Close All Projects and Editors") invokeMenuItem("File", "Exit") From 4318bfb9b6d90693e621f37fd3bc7724bcdf3ed2 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 18 Feb 2022 22:31:10 +0100 Subject: [PATCH 60/76] QmlDesigner: Fix qbs build Amends c82937a78cb7bc2. Change-Id: I7438fbc84351e9de61dc27dfb5ecb4226974d6ce Reviewed-by: Reviewed-by: Alessandro Portale --- src/plugins/qmldesigner/qmldesignerplugin.qbs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index 4ab3c754c9f..09690f9d2f4 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -1037,6 +1037,8 @@ Project { "cmakegeneratordialog.h", "cmakeprojectconverter.cpp", "cmakeprojectconverter.h", + "cmakeprojectconverterdialog.cpp", + "cmakeprojectconverterdialog.h", "designersettings.cpp", "designersettings.h", "designmodecontext.cpp", From 8b994bd79b7cafd855eb3fa4ae656cf52b0fc00d Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 21 Feb 2022 11:28:16 +0100 Subject: [PATCH 61/76] McuSupport: Fix test expectation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I4cd0fa4d326e7681f187980c11d37668ae46c798 Reviewed-by: Alessandro Portale Reviewed-by: Piotr Mućko --- src/plugins/mcusupport/test/unittest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/mcusupport/test/unittest.cpp b/src/plugins/mcusupport/test/unittest.cpp index 3651369cb92..349fdacfc06 100644 --- a/src/plugins/mcusupport/test/unittest.cpp +++ b/src/plugins/mcusupport/test/unittest.cpp @@ -92,7 +92,7 @@ void McuSupportTest::test_addFreeRtosCmakeVarToKit() QCOMPARE(cmakeConfig.size(), 1); CMakeConfigItem expectedCmakeVar{freeRtosCmakeVar.toLocal8Bit(), - defaultfreeRtosPath.toLocal8Bit()}; + FilePath::fromString(defaultfreeRtosPath).toUserOutput().toLocal8Bit()}; QVERIFY(cmakeConfig.contains(expectedCmakeVar)); } From 38f5415d9aba11ee206f33d9cb0362241ce03d41 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 21 Feb 2022 11:12:06 +0100 Subject: [PATCH 62/76] McuSupport: Do not use compiler specific syntax Change-Id: Ib466c989318b5d303f89def56fcd3f1369407843 Reviewed-by: Alessandro Portale --- src/plugins/mcusupport/test/unittest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/mcusupport/test/unittest.cpp b/src/plugins/mcusupport/test/unittest.cpp index 349fdacfc06..30a6fa8a532 100644 --- a/src/plugins/mcusupport/test/unittest.cpp +++ b/src/plugins/mcusupport/test/unittest.cpp @@ -56,7 +56,7 @@ void McuSupportTest::test_parseBasicInfoFromJson() { const auto description = Sdk::parseDescriptionJson(nxp_1064_json); - QVERIFY(not description.freeRTOS.envVar.isEmpty()); + QVERIFY(!description.freeRTOS.envVar.isEmpty()); QVERIFY(description.freeRTOS.boardSdkSubDir.isEmpty()); } @@ -86,7 +86,7 @@ void McuSupportTest::test_addFreeRtosCmakeVarToKit() QVERIFY(kit.hasValue(EnvironmentKitAspect::id())); QVERIFY(kit.isValid()); - QVERIFY(not kit.allKeys().empty()); + QVERIFY(!kit.allKeys().empty()); const auto &cmakeConfig{CMakeConfigurationKitAspect::configuration(&kit)}; QCOMPARE(cmakeConfig.size(), 1); From 610480620847628b3640336ddbd33d236d61d80e Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 21 Feb 2022 11:31:31 +0100 Subject: [PATCH 63/76] QmlDesigner: Add new workspaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QDS-6234 Change-Id: I839459c18fd0937615d97c7b74584e97300b430b Reviewed-by: Henning Gründl --- share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk | 1 + share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk | 1 + share/qtcreator/qmldesigner/workspacePresets/Basic.wrk | 1 + share/qtcreator/qmldesigner/workspacePresets/Code.wrk | 1 + .../workspacePresets/{3D_Preset.wrk => Essentials-3D.wrk} | 0 share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk | 1 + share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk | 1 + src/libs/advanceddockingsystem/dockmanager.h | 2 +- 8 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk create mode 100644 share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk create mode 100644 share/qtcreator/qmldesigner/workspacePresets/Basic.wrk create mode 100644 share/qtcreator/qmldesigner/workspacePresets/Code.wrk rename share/qtcreator/qmldesigner/workspacePresets/{3D_Preset.wrk => Essentials-3D.wrk} (100%) create mode 100644 share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk create mode 100644 share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk diff --git a/share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk b/share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk new file mode 100644 index 00000000000..e5c5d40bc03 --- /dev/null +++ b/share/qtcreator/qmldesigner/workspacePresets/Animation-2D.wrk @@ -0,0 +1 @@ +346 0 365712 00 0914 00 0712 0712 0 0310 914 406712 255 diff --git a/share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk b/share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk new file mode 100644 index 00000000000..b74da2a048a --- /dev/null +++ b/share/qtcreator/qmldesigner/workspacePresets/Animation-3D.wrk @@ -0,0 +1 @@ +541 0 426353 3530 0919 0919 0707 260968 0 0312 919 408 diff --git a/share/qtcreator/qmldesigner/workspacePresets/Basic.wrk b/share/qtcreator/qmldesigner/workspacePresets/Basic.wrk new file mode 100644 index 00000000000..82556f540a6 --- /dev/null +++ b/share/qtcreator/qmldesigner/workspacePresets/Basic.wrk @@ -0,0 +1 @@ +481 0 486968 0968 0919 00 919968 0968 0 0312 919 408 diff --git a/share/qtcreator/qmldesigner/workspacePresets/Code.wrk b/share/qtcreator/qmldesigner/workspacePresets/Code.wrk new file mode 100644 index 00000000000..c2510cb7dc2 --- /dev/null +++ b/share/qtcreator/qmldesigner/workspacePresets/Code.wrk @@ -0,0 +1 @@ +541 0 426707 0488 218601 4481050 0707 260541 0 426274 1050 315 diff --git a/share/qtcreator/qmldesigner/workspacePresets/3D_Preset.wrk b/share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk similarity index 100% rename from share/qtcreator/qmldesigner/workspacePresets/3D_Preset.wrk rename to share/qtcreator/qmldesigner/workspacePresets/Essentials-3D.wrk diff --git a/share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk b/share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk new file mode 100644 index 00000000000..aec1d2e2943 --- /dev/null +++ b/share/qtcreator/qmldesigner/workspacePresets/UX-Design.wrk @@ -0,0 +1 @@ +487 0 480707 0707 0914 0914 0707 260707 0 260310 914 406 diff --git a/share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk b/share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk new file mode 100644 index 00000000000..7a2639e9550 --- /dev/null +++ b/share/qtcreator/qmldesigner/workspacePresets/Views-All.wrk @@ -0,0 +1 @@ +343 353 270353 353353 353448 465457 456707 260343 353 270310 914 406 diff --git a/src/libs/advanceddockingsystem/dockmanager.h b/src/libs/advanceddockingsystem/dockmanager.h index 174239e22a7..acf29a5616e 100644 --- a/src/libs/advanceddockingsystem/dockmanager.h +++ b/src/libs/advanceddockingsystem/dockmanager.h @@ -60,7 +60,7 @@ QT_END_NAMESPACE namespace ADS { namespace Constants { -const char DEFAULT_WORKSPACE[] = "Essentials"; // This needs to align with a name of the shipped presets +const char DEFAULT_WORKSPACE[] = "Basic"; // This needs to align with a name of the shipped presets const char STARTUP_WORKSPACE_SETTINGS_KEY[] = "QML/Designer/StartupWorkspace"; const char AUTO_RESTORE_WORKSPACE_SETTINGS_KEY[] = "QML/Designer/AutoRestoreLastWorkspace"; } // namespace Constants From 3eac52dc7dfe7cfd6f0c50879dfee97019961bdd Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 21 Feb 2022 11:27:53 +0100 Subject: [PATCH 64/76] Mercurial: Fix saving of settings Fixes: QTCREATORBUG-27091 Change-Id: I59297993f19c60a9eaf67910638818ffd17b4ff8 Reviewed-by: Eike Ziller Reviewed-by: Reviewed-by: Qt CI Bot --- src/plugins/coreplugin/dialogs/ioptionspage.h | 5 ++++- src/plugins/mercurial/mercurialsettings.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/plugins/coreplugin/dialogs/ioptionspage.h b/src/plugins/coreplugin/dialogs/ioptionspage.h index cd0e59b016e..6c989ccad45 100644 --- a/src/plugins/coreplugin/dialogs/ioptionspage.h +++ b/src/plugins/coreplugin/dialogs/ioptionspage.h @@ -83,13 +83,16 @@ protected: void setSettings(Utils::AspectContainer *settings); void setLayouter(const std::function &layouter); + // Used in FontSettingsPage. FIXME? + QPointer m_widget; // Used in conjunction with m_widgetCreator + +private: Utils::Id m_id; Utils::Id m_category; QString m_displayName; QString m_displayCategory; Utils::Icon m_categoryIcon; WidgetCreator m_widgetCreator; - QPointer m_widget; // Used in conjunction with m_widgetCreator mutable bool m_keywordsInitialized = false; mutable QStringList m_keywords; diff --git a/src/plugins/mercurial/mercurialsettings.cpp b/src/plugins/mercurial/mercurialsettings.cpp index 94734464828..018f6594e16 100644 --- a/src/plugins/mercurial/mercurialsettings.cpp +++ b/src/plugins/mercurial/mercurialsettings.cpp @@ -73,7 +73,7 @@ MercurialSettingsPage::MercurialSettingsPage(MercurialSettings *settings) setId(VcsBase::Constants::VCS_ID_MERCURIAL); setDisplayName(MercurialSettings::tr("Mercurial")); setCategory(VcsBase::Constants::VCS_SETTINGS_CATEGORY); - setSettings(m_settings); + setSettings(settings); setLayouter([settings](QWidget *widget) { MercurialSettings &s = *settings; From 3be545123acb20a9130651d272d88206898f423f Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 21 Feb 2022 14:21:24 +0100 Subject: [PATCH 65/76] QmlDesigner: Add QMLSCENE_CORE_PROFILE for Qt 5 Task-number: QDS-5522 Change-Id: Iff3591e05a172716f3f37963e0430875e3ad9e04 Reviewed-by: Thomas Hartmann --- .../studio_templates/projects/common/app.qmlproject.tpl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl b/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl index f24482bcac8..60aa8715873 100644 --- a/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl +++ b/share/qtcreator/qmldesigner/studio_templates/projects/common/app.qmlproject.tpl @@ -62,6 +62,10 @@ Project { Environment { QT_QUICK_CONTROLS_CONF: "qtquickcontrols2.conf" QT_AUTO_SCREEN_SCALE_FACTOR: "1" +@if %{IsQt6Project} +@else + QMLSCENE_CORE_PROFILE: "true" // Required for macOS, but can create issues on embedded Linux +@endif @if %{UseVirtualKeyboard} QT_IM_MODULE: "qtvirtualkeyboard" QT_VIRTUALKEYBOARD_DESKTOP_DISABLE: 1 From c3bd3d6a628c1571059ed981e1666c9cc7e37643 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Mon, 21 Feb 2022 15:41:16 +0100 Subject: [PATCH 66/76] qds: make code reusable Change-Id: Ic11917f8a442a1ed15482a1ea492a7cef9f2a7ff Reviewed-by: Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- src/libs/utils/CMakeLists.txt | 1 + src/libs/utils/dynamiclicensecheck.h | 68 +++++++++++++++++++ .../studiowelcome/studiowelcomeplugin.cpp | 36 ++-------- 3 files changed, 73 insertions(+), 32 deletions(-) create mode 100644 src/libs/utils/dynamiclicensecheck.h diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index 780f3e2017a..49e2ab648d2 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -34,6 +34,7 @@ add_qtc_library(Utils differ.cpp differ.h displayname.cpp displayname.h dropsupport.cpp dropsupport.h + dynamiclicensecheck.h elfreader.cpp elfreader.h elidinglabel.cpp elidinglabel.h environment.cpp environment.h diff --git a/src/libs/utils/dynamiclicensecheck.h b/src/libs/utils/dynamiclicensecheck.h new file mode 100644 index 00000000000..634c6b28d11 --- /dev/null +++ b/src/libs/utils/dynamiclicensecheck.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file 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 file. 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. +** +****************************************************************************/ + +#pragma once + +#include +#include +#include + +#include +#include + +#include + +namespace Utils { + +enum FoundLicense { + community, + professional, + enterprise +}; + +FoundLicense checkLicense() { + const ExtensionSystem::PluginSpec *pluginSpec = Utils::findOrDefault( + ExtensionSystem::PluginManager::plugins(), + Utils::equal(&ExtensionSystem::PluginSpec::name, QString("LicenseChecker"))); + + if (!pluginSpec) + return community; + + ExtensionSystem::IPlugin *plugin = pluginSpec->plugin(); + + if (!plugin) + return community; + + bool retVal = false; + bool success = QMetaObject::invokeMethod(plugin, + "qdsEnterpriseLicense", + Qt::DirectConnection, + Q_RETURN_ARG(bool, retVal)); + if (success && retVal) + return enterprise; + + return professional; +} +} // namespace Utils diff --git a/src/plugins/studiowelcome/studiowelcomeplugin.cpp b/src/plugins/studiowelcome/studiowelcomeplugin.cpp index 9c7b82d1698..72f6afcdb57 100644 --- a/src/plugins/studiowelcome/studiowelcomeplugin.cpp +++ b/src/plugins/studiowelcome/studiowelcomeplugin.cpp @@ -39,9 +39,6 @@ #include #include -#include -#include - #include #include #include @@ -59,6 +56,7 @@ #include #include #include +#include #include #include @@ -302,35 +300,9 @@ private: void ProjectModel::setupVersion() { - const ExtensionSystem::PluginSpec *pluginSpec = Utils::findOrDefault( - ExtensionSystem::PluginManager::plugins(), - Utils::equal(&ExtensionSystem::PluginSpec::name, QString("LicenseChecker"))); - - if (!pluginSpec) - return; - - ExtensionSystem::IPlugin *plugin = pluginSpec->plugin(); - - if (!plugin) - return; - - m_communityVersion = false; - - bool retVal = false; - bool success = QMetaObject::invokeMethod(plugin, - "qdsEnterpriseLicense", - Qt::DirectConnection, - Q_RETURN_ARG(bool, retVal)); - - if (!success) { - qWarning("Check for Qt Design Studio Enterprise License failed."); - return; - } - if (!retVal) { - qWarning("No Qt Design Studio Enterprise License. Disabling asset importer."); - return; - } - m_enterpriseVersion = true; + Utils::FoundLicense license = Utils::checkLicense(); + m_communityVersion = license == Utils::FoundLicense::community; + m_enterpriseVersion = license == Utils::FoundLicense::enterprise; } ProjectModel::ProjectModel(QObject *parent) From 0c13c1c0842e1b657f628ad4b00fc9b76a81f965 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 21 Feb 2022 16:39:54 +0100 Subject: [PATCH 67/76] Doc: Describe formatting in CMake Build Settings Italic text indicates that a value was inherited from the kit configuration or initial configuration. Red text indicates mismatches. Change-Id: Ief30eef1d2667d0b4e570ea439ffb6af681db2b7 Reviewed-by: Cristian Adam --- .../src/cmake/creator-projects-cmake-building.qdoc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc b/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc index 2932e1c9d81..45e55f42987 100644 --- a/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc +++ b/doc/qtcreator/src/cmake/creator-projects-cmake-building.qdoc @@ -39,6 +39,17 @@ \image qtcreator-cmake-build-settings-initial.png "CMake build settings" + \uicontrol {Initial Configuration} lists the variables that are used to + configure the CMake project for the first time. The default values that + are inherited from the kit's CMake configuration are displayed in italic. + The initial configuration list of variables is saved in the project's source + directory as the \e CMakeLists.txt.user file. + + \uicontrol {Current Configuration} lists the CMake variables in the + \c cmake-file-api JSON export in the \c {.cmake/api/v1/reply} directory. + The variables that are inherited from the initial configuration are + displayed in italic. Mismatched values are displayed in red. + You can view and edit the actual values of the variables that are passed to CMake. Variable names are listed in the \uicontrol Key column and their current values in the \uicontrol Value column. For more information about From e59b7612b171c6f0378f990b7235353b67b2ee7d Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 18 Feb 2022 13:53:50 +0100 Subject: [PATCH 68/76] LanguageClient: do not disconnect client from everything before deletion Otherwise cleanup code connected to QObject::destoyed might not be executed. Change-Id: I12bf2b614cf0d216b2f2c0762cc153b4bb845e1f Reviewed-by: Christian Kandeler --- src/plugins/languageclient/languageclientmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp index 8ac21b6ef4e..992138f06a1 100644 --- a/src/plugins/languageclient/languageclientmanager.cpp +++ b/src/plugins/languageclient/languageclientmanager.cpp @@ -232,7 +232,7 @@ void LanguageClientManager::deleteClient(Client *client) QTC_ASSERT(managerInstance, return); QTC_ASSERT(client, return); qCDebug(Log) << "delete client: " << client->name() << client; - client->disconnect(); + client->disconnect(managerInstance); managerInstance->m_clients.removeAll(client); for (QVector &clients : managerInstance->m_clientsForSetting) clients.removeAll(client); From eccbc0fbcc5d23c4a4d0d7961f28dfbcb497affa Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 21 Feb 2022 11:10:54 +0100 Subject: [PATCH 69/76] Qbs: Factor out gtest dependency check ..to make it re-usable. Change-Id: I7653ee7b3ced5fb9d2b7262aecdab12438628928 Reviewed-by: Christian Kandeler --- .../qtc_gtest_gmock/qtc_gtest_gmock.qbs | 65 +++++++++++++++++++ tests/unit/unittest/unittest.qbs | 46 +------------ 2 files changed, 67 insertions(+), 44 deletions(-) create mode 100644 qbs/modules/qtc_gtest_gmock/qtc_gtest_gmock.qbs diff --git a/qbs/modules/qtc_gtest_gmock/qtc_gtest_gmock.qbs b/qbs/modules/qtc_gtest_gmock/qtc_gtest_gmock.qbs new file mode 100644 index 00000000000..5229db14403 --- /dev/null +++ b/qbs/modules/qtc_gtest_gmock/qtc_gtest_gmock.qbs @@ -0,0 +1,65 @@ +import qbs +import qbs.File +import qbs.FileInfo + +Module { + property bool preferExternalLibs: true + + Depends { name: "pkgconfig"; condition: preferExternalLibs; required: false } + Depends { name: "gtest"; condition: preferExternalLibs; required: false } + Depends { name: "gmock"; condition: preferExternalLibs; required: false } + Depends { name: "cpp" } + + Probe { + id: gtestProbe + + property string repoDir + property string gtestDir + property string gmockDir + property bool hasRepo + + configure: { + repoDir = FileInfo.cleanPath(path + "/../../../tests/unit/unittest/3rdparty/googletest"); + gtestDir = FileInfo.joinPaths(repoDir, "googletest"); + gmockDir = FileInfo.joinPaths(repoDir, "googlemock"); + hasRepo = File.exists(gtestDir); + found = hasRepo; + } + } + + property bool hasRepo: gtestProbe.hasRepo + property bool externalLibsPresent: preferExternalLibs && gtest.present && gmock.present + property bool useRepo: !externalLibsPresent && hasRepo + property string gtestDir: gtestProbe.gtestDir + property string gmockDir: gtestProbe.gmockDir + + Group { + name: "Files from repository" + condition: qtc_gtest_gmock.useRepo + cpp.includePaths: [ + qtc_gtest_gmock.gtestDir, + qtc_gtest_gmock.gmockDir, + FileInfo.joinPaths(qtc_gtest_gmock.gtestDir, "include"), + FileInfo.joinPaths(qtc_gtest_gmock.gmockDir, "include"), + ] + files: [ + FileInfo.joinPaths(qtc_gtest_gmock.gtestDir, "src", "gtest-all.cc"), + FileInfo.joinPaths(qtc_gtest_gmock.gmockDir, "src", "gmock-all.cc"), + ] + } + + Properties { + condition: qtc_gtest_gmock.useRepo + cpp.includePaths: [ + FileInfo.joinPaths(qtc_gtest_gmock.gtestDir, "include"), + FileInfo.joinPaths(qtc_gtest_gmock.gmockDir, "include"), + ] + } + + validate: { + if (!qtc_gtest_gmock.externalLibsPresent && !gtestProbe.found) { + console.warn("No GTest found."); + throw new Error(); + } + } +} diff --git a/tests/unit/unittest/unittest.qbs b/tests/unit/unittest/unittest.qbs index 83c6260c5a9..5401aa09e1b 100644 --- a/tests/unit/unittest/unittest.qbs +++ b/tests/unit/unittest/unittest.qbs @@ -4,52 +4,10 @@ import qbs.FileInfo Project { name: "Unit test & helper products" - Product { - name: "qtc_gtest_gmock" - - Export { - property bool useExternalLibs: preferExternalLibs && externalLibsPresent - property bool useRepo: !useExternalLibs && hasRepo - property bool preferExternalLibs: true - property bool externalLibsPresent: preferExternalLibs && gtest.present && gmock.present - property string repoDir: FileInfo.joinPaths(path, "3rdparty", "googletest") - property string gtestDir: FileInfo.joinPaths(repoDir, "googletest") - property string gmockDir: FileInfo.joinPaths(repoDir, "googlemock") - property bool hasRepo: File.exists(gtestDir) - - Depends { name: "pkgconfig"; condition: preferExternalLibs; required: false } - Depends { name: "gtest"; condition: preferExternalLibs; required: false } - Depends { name: "gmock"; condition: preferExternalLibs; required: false } - - Depends { name: "cpp" } - Group { - name: "Files from repository" - condition: qtc_gtest_gmock.useRepo - cpp.includePaths: [ - qtc_gtest_gmock.gtestDir, - qtc_gtest_gmock.gmockDir, - FileInfo.joinPaths(qtc_gtest_gmock.gtestDir, "include"), - FileInfo.joinPaths(qtc_gtest_gmock.gmockDir, "include"), - ] - files: [ - FileInfo.joinPaths(qtc_gtest_gmock.gtestDir, "src", "gtest-all.cc"), - FileInfo.joinPaths(qtc_gtest_gmock.gmockDir, "src", "gmock-all.cc"), - ] - } - - Properties { - condition: useRepo - cpp.includePaths: [ - FileInfo.joinPaths(gtestDir, "include"), - FileInfo.joinPaths(gmockDir, "include"), - ] - } - } - } - QtcProduct { name: "Unit test" condition: qtc_gtest_gmock.hasRepo || qtc_gtest_gmock.externalLibsPresent + type: ["application", "autotest"] consoleApplication: true destinationDirectory: FileInfo.joinPaths(project.buildDirectory, @@ -72,7 +30,7 @@ Project { Depends { name: "pkgconfig"; required: false } Depends { name: "benchmark"; required: false } - Depends { name: "qtc_gtest_gmock" } + Depends { name: "qtc_gtest_gmock"; required: false } sqlite_sources.buildSharedLib: false From e4da77965377d7ec9e4e22d72e5401565b310b98 Mon Sep 17 00:00:00 2001 From: Christiaan Janssen Date: Mon, 21 Feb 2022 13:41:57 +0100 Subject: [PATCH 70/76] McuSupport: move auto-kit-creation option to McuSupportOptions It was part of McuPackage, and only used by the SDK instance. Task-number: QTCREATORBUG-27093 Change-Id: I9d9eaac621e9997129c227fae3ac88b502ba4340 Reviewed-by: Reviewed-by: Alessandro Portale --- src/plugins/mcusupport/mcuabstractpackage.h | 4 --- src/plugins/mcusupport/mcukitmanager.cpp | 2 +- src/plugins/mcusupport/mcupackage.cpp | 28 ------------------ src/plugins/mcusupport/mcupackage.h | 6 ---- src/plugins/mcusupport/mcusupportoptions.cpp | 29 +++++++++++++++++++ src/plugins/mcusupport/mcusupportoptions.h | 6 ++++ .../mcusupport/mcusupportoptionspage.cpp | 7 ++--- src/plugins/mcusupport/test/packagemock.h | 6 ---- 8 files changed, 39 insertions(+), 49 deletions(-) diff --git a/src/plugins/mcusupport/mcuabstractpackage.h b/src/plugins/mcusupport/mcuabstractpackage.h index 27b8b75c97d..9406b474fb9 100644 --- a/src/plugins/mcusupport/mcuabstractpackage.h +++ b/src/plugins/mcusupport/mcuabstractpackage.h @@ -58,14 +58,10 @@ public: virtual const QString &environmentVariableName() const = 0; virtual void setAddToPath(bool) = 0; virtual bool addToPath() const = 0; - virtual void writeGeneralSettings() const = 0; virtual bool writeToSettings() const = 0; virtual void setRelativePathModifier(const QString &) = 0; virtual void setVersions(const QStringList &) = 0; - virtual bool automaticKitCreationEnabled() const = 0; - virtual void setAutomaticKitCreationEnabled(const bool enabled) = 0; - virtual QWidget *widget() = 0; signals: diff --git a/src/plugins/mcusupport/mcukitmanager.cpp b/src/plugins/mcusupport/mcukitmanager.cpp index e142072242d..5fffe2b8da3 100644 --- a/src/plugins/mcusupport/mcukitmanager.cpp +++ b/src/plugins/mcusupport/mcukitmanager.cpp @@ -387,7 +387,7 @@ void createAutomaticKits() auto qtForMCUsPackage = Sdk::createQtForMCUsPackage(); const auto createKits = [qtForMCUsPackage]() { - if (qtForMCUsPackage->automaticKitCreationEnabled()) { + if (McuSupportOptions::automaticKitCreationFromSettings()) { qtForMCUsPackage->updateStatus(); if (!qtForMCUsPackage->validStatus()) { switch (qtForMCUsPackage->status()) { diff --git a/src/plugins/mcusupport/mcupackage.cpp b/src/plugins/mcusupport/mcupackage.cpp index ed963652edb..f108ca67f83 100644 --- a/src/plugins/mcusupport/mcupackage.cpp +++ b/src/plugins/mcusupport/mcupackage.cpp @@ -41,15 +41,6 @@ using namespace Utils; namespace McuSupport::Internal { -static bool automaticKitCreationFromSettings(QSettings::Scope scope = QSettings::UserScope) -{ - QSettings *settings = Core::ICore::settings(scope); - const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' - + QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION); - bool automaticKitCreation = settings->value(key, true).toBool(); - return automaticKitCreation; -} - McuPackage::McuPackage(const QString &label, const FilePath &defaultPath, const QString &detectionPath, @@ -66,7 +57,6 @@ McuPackage::McuPackage(const QString &label, , m_downloadUrl(downloadUrl) { m_path = Sdk::packagePathFromSettings(settingsKey, QSettings::UserScope, m_defaultPath); - m_automaticKitCreation = automaticKitCreationFromSettings(QSettings::UserScope); } FilePath McuPackage::basePath() const @@ -162,14 +152,6 @@ bool McuPackage::addToPath() const return m_addToPath; } -void McuPackage::writeGeneralSettings() const -{ - const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' - + QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION); - QSettings *settings = Core::ICore::settings(); - settings->setValue(key, m_automaticKitCreation); -} - bool McuPackage::writeToSettings() const { const FilePath savedPath = Sdk::packagePathFromSettings(m_settingsKey, @@ -192,16 +174,6 @@ void McuPackage::setVersions(const QStringList &versions) m_versions = versions; } -bool McuPackage::automaticKitCreationEnabled() const -{ - return m_automaticKitCreation; -} - -void McuPackage::setAutomaticKitCreationEnabled(const bool enabled) -{ - m_automaticKitCreation = enabled; -} - void McuPackage::updatePath() { m_path = m_fileChooser->rawFilePath(); diff --git a/src/plugins/mcusupport/mcupackage.h b/src/plugins/mcusupport/mcupackage.h index f2d6aa5276d..dcc9917c1ce 100644 --- a/src/plugins/mcusupport/mcupackage.h +++ b/src/plugins/mcusupport/mcupackage.h @@ -74,15 +74,10 @@ public: bool validStatus() const override; void setAddToPath(bool addToPath) override; bool addToPath() const override; - void writeGeneralSettings() const override; bool writeToSettings() const override; void setRelativePathModifier(const QString &path) override; void setVersions(const QStringList &versions) override; - //TODO(piotr.mucko): Why every package knows about automatic kit creation. This should be outside of this class. - bool automaticKitCreationEnabled() const override; - void setAutomaticKitCreationEnabled(const bool enabled) override; - QWidget *widget() override; const QString &environmentVariableName() const override; @@ -108,7 +103,6 @@ private: const QString m_environmentVariableName; const QString m_downloadUrl; bool m_addToPath = false; - bool m_automaticKitCreation = true; Status m_status = Status::InvalidPath; }; diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index 8d8721323b9..a5915c7affc 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -70,6 +70,7 @@ McuSupportOptions::McuSupportOptions(QObject *parent) &McuAbstractPackage::changed, this, &McuSupportOptions::populatePackagesAndTargets); + m_automaticKitCreation = automaticKitCreationFromSettings(); } McuSupportOptions::~McuSupportOptions() @@ -434,5 +435,33 @@ bool McuSupportOptions::kitsNeedQtVersion() return !HostOsInfo::isWindowsHost(); } + +bool McuSupportOptions::automaticKitCreationEnabled() const +{ + return m_automaticKitCreation; +} + +void McuSupportOptions::setAutomaticKitCreationEnabled(const bool enabled) +{ + m_automaticKitCreation = enabled; +} + +void McuSupportOptions::writeGeneralSettings() const +{ + const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + + QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION); + QSettings *settings = Core::ICore::settings(QSettings::UserScope); + settings->setValue(key, m_automaticKitCreation); +} + +bool McuSupportOptions::automaticKitCreationFromSettings() +{ + QSettings *settings = Core::ICore::settings(QSettings::UserScope); + const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + + QLatin1String(Constants::SETTINGS_KEY_AUTOMATIC_KIT_CREATION); + const bool automaticKitCreation = settings->value(key, true).toBool(); + return automaticKitCreation; +} + } // namespace Internal } // namespace McuSupport diff --git a/src/plugins/mcusupport/mcusupportoptions.h b/src/plugins/mcusupport/mcusupportoptions.h index 02e672486c2..04dbb24b6ae 100644 --- a/src/plugins/mcusupport/mcusupportoptions.h +++ b/src/plugins/mcusupport/mcusupportoptions.h @@ -91,9 +91,15 @@ public: void populatePackagesAndTargets(); static bool kitsNeedQtVersion(); + + bool automaticKitCreationEnabled() const; + void setAutomaticKitCreationEnabled(const bool enabled); + void writeGeneralSettings() const; + static bool automaticKitCreationFromSettings(); private: void deletePackagesAndTargets(); + bool m_automaticKitCreation = true; signals: void packagesChanged(); }; diff --git a/src/plugins/mcusupport/mcusupportoptionspage.cpp b/src/plugins/mcusupport/mcusupportoptionspage.cpp index 7eb8c160b0b..36a8d318a0a 100644 --- a/src/plugins/mcusupport/mcusupportoptionspage.cpp +++ b/src/plugins/mcusupport/mcusupportoptionspage.cpp @@ -146,7 +146,7 @@ McuSupportOptionsWidget::McuSupportOptionsWidget() m_kitAutomaticCreationCheckBox = new QCheckBox( tr("Automatically create kits for all available targets on start")); connect(m_kitAutomaticCreationCheckBox, &QCheckBox::stateChanged, this, [this](int state) { - m_options.qtForMCUsSdkPackage->setAutomaticKitCreationEnabled( + m_options.setAutomaticKitCreationEnabled( state == Qt::CheckState::Checked); }); mainLayout->addWidget(m_kitAutomaticCreationCheckBox); @@ -245,8 +245,7 @@ void McuSupportOptionsWidget::updateStatus() } // Automatic Kit creation - m_kitAutomaticCreationCheckBox->setChecked( - m_options.qtForMCUsSdkPackage->automaticKitCreationEnabled()); + m_kitAutomaticCreationCheckBox->setChecked(m_options.automaticKitCreationEnabled()); // Status label in the bottom { @@ -300,7 +299,7 @@ void McuSupportOptionsWidget::apply() { bool pathsChanged = false; - m_options.qtForMCUsSdkPackage->writeGeneralSettings(); + m_options.writeGeneralSettings(); pathsChanged |= m_options.qtForMCUsSdkPackage->writeToSettings(); for (auto package : qAsConst(m_options.sdkRepository.packages)) pathsChanged |= package->writeToSettings(); diff --git a/src/plugins/mcusupport/test/packagemock.h b/src/plugins/mcusupport/test/packagemock.h index b7e2f54351c..7f8e98d40f5 100644 --- a/src/plugins/mcusupport/test/packagemock.h +++ b/src/plugins/mcusupport/test/packagemock.h @@ -45,19 +45,13 @@ public: MOCK_METHOD(Status, status, (), (const)); MOCK_METHOD(bool, validStatus, (), (const)); - MOCK_METHOD(void, setDownloadUrl, (const QString &) ); - MOCK_METHOD(void, setEnvironmentVariableName, (const QString &) ); MOCK_METHOD(const QString &, environmentVariableName, (), (const)); MOCK_METHOD(void, setAddToPath, (bool) ); MOCK_METHOD(bool, addToPath, (), (const)); - MOCK_METHOD(void, writeGeneralSettings, (), (const)); MOCK_METHOD(bool, writeToSettings, (), (const)); MOCK_METHOD(void, setRelativePathModifier, (const QString &) ); MOCK_METHOD(void, setVersions, (const QStringList &) ); - MOCK_METHOD(bool, automaticKitCreationEnabled, (), (const)); - MOCK_METHOD(void, setAutomaticKitCreationEnabled, (const bool enabled)); - MOCK_METHOD(QWidget *, widget, ()); }; // class PackageMock } // namespace McuSupport::Internal From 298765c2628d4f8b90ba7e5ca4eb3119643a777b Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 21 Feb 2022 11:07:59 +0100 Subject: [PATCH 71/76] ProjectExplorer: get clang cl version via windows api If it fails fall back to executing clang-cl --version. Change-Id: Ia344f6eceb1ad2117dc2f7dc7f91b79daa2235ce Reviewed-by: Reviewed-by: Christian Stenger --- src/plugins/projectexplorer/msvctoolchain.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 8f734f78a80..13a945a2807 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -1546,6 +1546,12 @@ static const MsvcToolChain *findMsvcToolChain(const QString &displayedVarsBat) static QVersionNumber clangClVersion(const FilePath &clangClPath) { + QString error; + QString dllversion = winGetDLLVersion(Utils::WinDLLFileVersion, clangClPath.toString(), &error); + + if (!dllversion.isEmpty()) + return QVersionNumber::fromString(dllversion); + QtcProcess clangClProcess; clangClProcess.setCommand({clangClPath, {"--version"}}); clangClProcess.runBlocking(); From 3f078ee89d32857f99b1805274d74cd3dd8572ba Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 15 Feb 2022 16:12:13 +0100 Subject: [PATCH 72/76] QmlDesigner: Add preview of pure 3D component in form editor If the root node is a 3D node we show a preview similar to the state preview in the form editor. The size of the preview is hard coded as (640, 480). Change-Id: If7f96522b093c17422fa38102bffe11ede016063 Reviewed-by: Qt CI Bot Reviewed-by: Miikka Heikkinen --- .../instances/qt5nodeinstanceserver.cpp | 5 +++ .../instances/qt5rendernodeinstanceserver.cpp | 8 ++++ .../instances/quick3dnodeinstance.cpp | 39 +++++++++++++++++-- .../instances/quick3dnodeinstance.h | 6 +++ .../instances/servernodeinstance.cpp | 5 +++ .../qml2puppet/instances/servernodeinstance.h | 2 + .../components/formeditor/formeditoritem.cpp | 35 +++++++++++++++++ .../components/formeditor/formeditoritem.h | 17 ++++++++ .../components/formeditor/formeditorscene.cpp | 4 +- .../components/formeditor/formeditorscene.h | 3 +- .../components/formeditor/formeditorview.cpp | 26 ++++++++++++- .../components/formeditor/formeditorview.h | 1 + 12 files changed, 144 insertions(+), 7 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp index c97de4636aa..908e06ea50a 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5nodeinstanceserver.cpp @@ -398,6 +398,8 @@ QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item) QQuickItemPrivate *pItem = QQuickItemPrivate::get(item); + const bool rootIs3dNode = rootNodeInstance().isSubclassOf("QQuick3DNode"); + const bool renderEffects = qEnvironmentVariableIsSet("QMLPUPPET_RENDER_EFFECTS"); if (renderEffects) { @@ -426,6 +428,9 @@ QImage Qt5NodeInstanceServer::grabItem(QQuickItem *item) QRectF renderBoundingRect; if (instance.isValid()) renderBoundingRect = instance.boundingRect(); + + else if (rootIs3dNode) + renderBoundingRect = item->boundingRect(); else renderBoundingRect = ServerNodeInstance::effectAdjustedBoundingRect(item); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp index 6fe0807d01a..ae333343726 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5rendernodeinstanceserver.cpp @@ -133,6 +133,14 @@ void Qt5RenderNodeInstanceServer::collectItemChangesAndSendChangeCommands() nodeInstanceClient()->synchronizeWithClientProcess(); } + if (rootNodeInstance().isSubclassOf("QQuick3DNode") && rootNodeInstance().contentItem() + && DesignerSupport::isDirty(rootNodeInstance().contentItem(), + DesignerSupport::ContentUpdateMask) + && nodeInstanceClient()->bytesToWrite() < 10000) { + Internal::QuickItemNodeInstance::updateDirtyNode(rootNodeInstance().contentItem()); + nodeInstanceClient()->pixmapChanged(createPixmapChangedCommand({rootNodeInstance()})); + } + inFunction = false; } } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp index ec0beb521df..0c70ccca8f0 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.cpp @@ -55,6 +55,8 @@ namespace QmlDesigner { namespace Internal { +const QRectF preview3dBoundingRect(0, 0, 640, 480); + Quick3DNodeInstance::Quick3DNodeInstance(QObject *node) : ObjectNodeInstance(node) { @@ -97,7 +99,7 @@ void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNo #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // In case this is the scene root, we need to create a dummy View3D for the scene // in preview puppets - if (instanceId() == 0 && nodeInstanceServer()->isPreviewServer()) { + if (instanceId() == 0 && (!nodeInstanceServer()->isInformationServer())) { auto helper = new QmlDesigner::Internal::GeneralHelper(); engine()->rootContext()->setContextProperty("_generalHelper", helper); @@ -111,8 +113,8 @@ void Quick3DNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNo nodeInstanceServer()->setRootItem(m_dummyRootView); } -#endif -#endif +#endif // QT_VERSION +#endif // QUICK3D_MODULE ObjectNodeInstance::initialize(objectNodeInstance, flags); } @@ -122,7 +124,7 @@ QImage Quick3DNodeInstance::renderImage() const if (!isRootNodeInstance() || !m_dummyRootView) return {}; - QSize size(640, 480); + QSize size = preview3dBoundingRect.size().toSize(); nodeInstanceServer()->quickWindow()->resize(size); m_dummyRootView->setSize(size); @@ -190,13 +192,37 @@ bool Quick3DNodeInstance::isRenderable() const return m_dummyRootView; } +bool Quick3DNodeInstance::hasContent() const +{ + return true; +} + QRectF Quick3DNodeInstance::boundingRect() const { + //The information server has no m_dummyRootView therefore we use the hardcoded value + if (nodeInstanceServer()->isInformationServer()) + return preview3dBoundingRect; + if (m_dummyRootView) return m_dummyRootView->boundingRect(); return ObjectNodeInstance::boundingRect(); } +QRectF Quick3DNodeInstance::contentItemBoundingBox() const +{ + return boundingRect(); +} + +QPointF Quick3DNodeInstance::position() const +{ + return QPointF(0, 0); +} + +QSizeF Quick3DNodeInstance::size() const +{ + return boundingRect().size(); +} + QList Quick3DNodeInstance::stateInstances() const { QList instanceList; @@ -212,6 +238,11 @@ QList Quick3DNodeInstance::stateInstances() const return instanceList; } +QQuickItem *Quick3DNodeInstance::contentItem() const +{ + return m_dummyRootView; +} + Qt5NodeInstanceServer *Quick3DNodeInstance::qt5NodeInstanceServer() const { return qobject_cast(nodeInstanceServer()); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h index 322762af26a..b3b4f789724 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3dnodeinstance.h @@ -51,10 +51,16 @@ public: QImage renderPreviewImage(const QSize &previewImageSize) const override; bool isRenderable() const override; + bool hasContent() const override; QRectF boundingRect() const override; + QRectF contentItemBoundingBox() const override; + QPointF position() const override; + QSizeF size() const override; QList stateInstances() const override; + QQuickItem *contentItem() const override; + protected: explicit Quick3DNodeInstance(QObject *node); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp index 9803f6d79e6..f6c7f94bcaa 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.cpp @@ -162,6 +162,11 @@ bool ServerNodeInstance::isComponentWrap() const return m_nodeInstance->isComponentWrap(); } +QQuickItem *ServerNodeInstance::contentItem() const +{ + return m_nodeInstance->contentItem(); +} + void ServerNodeInstance::updateDirtyNodeRecursive() { m_nodeInstance->updateAllDirtyNodesRecursive(); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h index 0e5ca3547db..bc79cb4f689 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/servernodeinstance.h @@ -188,6 +188,8 @@ public: bool isComponentWrap() const; + QQuickItem *contentItem() const; + private: // functions ServerNodeInstance(const QSharedPointer &abstractInstance); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp index 4f000e12953..95d92e68fe9 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.cpp @@ -2226,4 +2226,39 @@ void FormEditorFlowWildcardItem::paint(QPainter *painter, const QStyleOptionGrap FormEditorFlowDecisionItem::paint(painter, option, widget); } +void FormEditor3dPreview::updateGeometry() +{ + prepareGeometryChange(); + + m_selectionBoundingRect = qmlItemNode().instanceBoundingRect().adjusted(0, 0, 1., 1.); + m_boundingRect = qmlItemNode().instanceBoundingRect(); + m_paintedBoundingRect = m_boundingRect; + setTransform(QTransform()); + +} + +QPointF FormEditor3dPreview::instancePosition() const +{ + return QPointF(0, 0); +} + +void FormEditor3dPreview::paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + if (!painter->isActive()) + return; + + painter->save(); + + bool showPlaceHolder = qmlItemNode().instanceIsRenderPixmapNull(); + + if (showPlaceHolder) + paintPlaceHolderForInvisbleItem(painter); + else + painter->drawPixmap(m_boundingRect.topLeft(), qmlItemNode().instanceRenderPixmap()); + + painter->restore(); +} + } //QmlDesigner diff --git a/src/plugins/qmldesigner/components/formeditor/formeditoritem.h b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h index 2213f42a664..a9e70145e2e 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditoritem.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditoritem.h @@ -171,6 +171,23 @@ private: QPointF m_oldPos; }; +class FormEditor3dPreview : public FormEditorItem +{ + friend FormEditorScene; + +public: + void updateGeometry() override; + QPointF instancePosition() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; + +protected: + FormEditor3dPreview(const QmlItemNode &qmlItemNode, FormEditorScene *scene) + : FormEditorItem(qmlItemNode, scene) + { + setHighlightBoundingRect(true); + } +}; + class FormEditorFlowActionItem : public FormEditorItem { friend FormEditorScene; diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp index bbc1f283e1f..dea52631d85 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp @@ -173,7 +173,9 @@ FormEditorItem *FormEditorScene::addFormEditorItem(const QmlItemNode &qmlItemNod { FormEditorItem *formEditorItem = nullptr; - if (type == Flow) + if (type == Preview3d) + formEditorItem = new FormEditor3dPreview(qmlItemNode, this); + else if (type == Flow) formEditorItem = new FormEditorFlowItem(qmlItemNode, this); else if (type == FlowAction) formEditorItem = new FormEditorFlowActionItem(qmlItemNode, this); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.h b/src/plugins/qmldesigner/components/formeditor/formeditorscene.h index 070d5877762..2d15af77a23 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorscene.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.h @@ -58,7 +58,8 @@ public: FlowAction, FlowTransition, FlowDecision, - FlowWildcard + FlowWildcard, + Preview3d }; FormEditorScene(FormEditorWidget *widget, FormEditorView *editorView); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index c2d63d2183a..e07c17cb04e 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -655,6 +656,14 @@ static void updateTransitions(FormEditorScene *scene, const QmlItemNode &qmlItem void FormEditorView::instancesCompleted(const QVector &completedNodeList) { + if (Qml3DNode::isValidQml3DNode(rootModelNode())) { + if (completedNodeList.contains(rootModelNode())) { + FormEditorItem *item = scene()->itemForQmlItemNode(rootModelNode()); + if (item) + scene()->synchronizeTransformation(item); + } + } + const bool isFlow = rootModelNode().isValid() && QmlItemNode(rootModelNode()).isFlowView(); QList itemNodeList; for (const ModelNode &node : completedNodeList) { @@ -724,6 +733,10 @@ void FormEditorView::instancesRenderImageChanged(const QVector &nodeL if (QmlItemNode::isValidQmlItemNode(node)) if (FormEditorItem *item = scene()->itemForQmlItemNode(QmlItemNode(node))) item->update(); + if (Qml3DNode::isValidQml3DNode(node)) { + if (FormEditorItem *item = scene()->itemForQmlItemNode(node)) + item->update(); + } } } @@ -795,6 +808,9 @@ void FormEditorView::setupFormEditorWidget() if (QmlItemNode::isValidQmlItemNode(rootModelNode())) setupFormEditorItemTree(rootModelNode()); + if (Qml3DNode::isValidQml3DNode(rootModelNode())) + setupFormEditor3DView(); + m_formEditorWidget->initialize(); if (!rewriterView()->errors().isEmpty()) @@ -903,7 +919,8 @@ void FormEditorView::checkRootModelNode() QTC_ASSERT(rootModelNode().isValid(), return); - if (!rootModelNode().metaInfo().isGraphicalItem()) + if (!rootModelNode().metaInfo().isGraphicalItem() + && !Qml3DNode::isValidQml3DNode(rootModelNode())) m_formEditorWidget->showErrorMessageBox( {DocumentMessage(tr("%1 is not supported as the root element by Form Editor.") .arg(rootModelNode().simplifiedTypeName()))}); @@ -911,6 +928,13 @@ void FormEditorView::checkRootModelNode() m_formEditorWidget->hideErrorMessageBox(); } +void FormEditorView::setupFormEditor3DView() +{ + m_scene->addFormEditorItem(rootModelNode(), FormEditorScene::Preview3d); + FormEditorItem *item = m_scene->itemForQmlItemNode(rootModelNode()); + item->updateGeometry(); +} + void FormEditorView::reset() { QTimer::singleShot(200, this, &FormEditorView::delayedReset); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h index 1db4ae1b4d1..c15f73498b5 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h @@ -151,6 +151,7 @@ private: void resetNodeInstanceView(); void addOrRemoveFormEditorItem(const ModelNode &node); void checkRootModelNode(); + void setupFormEditor3DView(); QPointer m_formEditorWidget; QPointer m_scene; From f7020a83c66a5e831002216b650b9b847d2070d6 Mon Sep 17 00:00:00 2001 From: Mahmoud Badri Date: Mon, 21 Feb 2022 13:35:30 +0200 Subject: [PATCH 73/76] QmlDesigner: Fix project path inside imported subcomponent When user goes inside a Qml that is part of an imported component, project path is not accessible. This commit fixes it. Fixes: QDS-6201 Change-Id: I4efff48399e487b586b10383f19c2d6877714dc9 Reviewed-by: Miikka Heikkinen Reviewed-by: Qt CI Bot Reviewed-by: Thomas Hartmann --- .../componentcore/modelnodeoperations.cpp | 13 ++----------- .../components/integration/designdocument.cpp | 2 +- src/plugins/qmldesigner/documentmanager.cpp | 15 +++++++++++---- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index 5327098cf3a..79242905905 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -989,15 +989,6 @@ void addTabBarToStackedContainer(const SelectionContext &selectionContext) } -Utils::FilePath projectFilePath() -{ - if (auto *doc = QmlDesignerPlugin::instance()->documentManager().currentDesignDocument()) { - if (auto *proj = ProjectExplorer::SessionManager::projectForFile(doc->fileName())) - return proj->projectDirectory(); - } - return Utils::FilePath(); -} - static AddFilesResult addFilesToProject(const QStringList &fileNames, const QString &defaultDirectory) { QString directory = AddImagesDialog::getDirectory(fileNames, defaultDirectory); @@ -1050,10 +1041,10 @@ static QString getAssetDefaultDirectory(const QString &assetDir, const QString & { QString adjustedDefaultDirectory = defaultDirectory; - Utils::FilePath contentPath = projectFilePath(); + Utils::FilePath contentPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath(); if (contentPath.pathAppended("content").exists()) - contentPath = contentPath.pathAppended("content"); + contentPath = contentPath.pathAppended("content"); Utils::FilePath assetPath = contentPath.pathAppended(assetDir); diff --git a/src/plugins/qmldesigner/components/integration/designdocument.cpp b/src/plugins/qmldesigner/components/integration/designdocument.cpp index f32a66b832f..e9e76c29cba 100644 --- a/src/plugins/qmldesigner/components/integration/designdocument.cpp +++ b/src/plugins/qmldesigner/components/integration/designdocument.cpp @@ -344,7 +344,7 @@ Utils::FilePath DesignDocument::projectFolder() const bool DesignDocument::hasProject() const { - return ProjectExplorer::SessionManager::projectForFile(fileName()); + return !DocumentManager::currentProjectDirPath().isEmpty(); } void DesignDocument::changeToInFileComponentModel(ComponentTextModifier *textModifer) diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index d75d570fc92..453dd96232a 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -358,11 +358,18 @@ Utils::FilePath DocumentManager::currentProjectDirPath() return {}; Utils::FilePath qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName(); - ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName); - if (!project) - return {}; - return project->projectDirectory(); + ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName); + if (project) + return project->projectDirectory(); + + const QList projects = ProjectExplorer::SessionManager::projects(); + for (auto p : projects) { + if (qmlFileName.startsWith(p->projectDirectory().toString())) + return p->projectDirectory(); + } + + return {}; } QStringList DocumentManager::isoIconsQmakeVariableValue(const QString &proPath) From ad9365d8fd5ddfff278ab0f6faea129d17e49b64 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 18 Feb 2022 12:38:31 +0100 Subject: [PATCH 74/76] LanguageClient: Do not assert on opening the same document twice Just silently ignore a second open. This is now consistent with LanguageClientManager::openDocumentWithClient that also supports calling it multiple times with the same document client combination. Change-Id: I6e8eaf312805cd4e82070209b414d63433158360 Reviewed-by: Christian Stenger --- src/plugins/languageclient/client.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index e4923f3bc84..3d23d0cfb48 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -358,7 +358,7 @@ void Client::setClientCapabilities(const LanguageServerProtocol::ClientCapabilit void Client::openDocument(TextEditor::TextDocument *document) { using namespace TextEditor; - if (!isSupportedDocument(document)) + if (m_openedDocument.contains(document) || !isSupportedDocument(document)) return; if (m_state != Initialized) { @@ -366,8 +366,6 @@ void Client::openDocument(TextEditor::TextDocument *document) return; } - QTC_ASSERT(!m_openedDocument.contains(document), return); - const FilePath &filePath = document->filePath(); const QString method(DidOpenTextDocumentNotification::methodName); if (Utils::optional registered = m_dynamicCapabilities.isRegistered(method)) { From 05e102fbac7ff1cc2714c415bca623d3676a306a Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 22 Feb 2022 07:42:54 +0100 Subject: [PATCH 75/76] LanguageClient: forcefully delete client after timeout If the client does not react within 20 seconds on the shutdown or exit message delete the client. Task-number: QTCREATORBUG-27064 Change-Id: I9680242e471989ea820c4e28d28c500c27a20bb7 Reviewed-by: Reviewed-by: Christian Kandeler --- src/plugins/languageclient/client.cpp | 8 ++++++++ src/plugins/languageclient/client.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 3d23d0cfb48..2b7594539cc 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -112,6 +112,11 @@ Client::Client(BaseClientInterface *clientInterface) m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap()); m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap()); + + m_shutdownTimer.setInterval(20 /*seconds*/ * 1000); + connect(&m_shutdownTimer, &QTimer::timeout, this, [this] { + LanguageClientManager::deleteClient(this); + }); } QString Client::name() const @@ -325,6 +330,7 @@ void Client::shutdown() }); sendContent(shutdown); m_state = ShutdownRequested; + m_shutdownTimer.start(); } Client::State Client::state() const @@ -1551,6 +1557,7 @@ void Client::initializeCallback(const InitializeRequest::Response &initResponse) void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse) { + m_shutdownTimer.stop(); QTC_ASSERT(m_state == ShutdownRequested, return); QTC_ASSERT(m_clientInterface, return); optional errorValue = shutdownResponse.error(); @@ -1563,6 +1570,7 @@ void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse) sendMessage(ExitNotification().toBaseMessage()); qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " shutdown"; m_state = Shutdown; + m_shutdownTimer.start(); } bool Client::sendWorkspceFolderChanges() const diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index c999dd84ef6..d95d5693609 100644 --- a/src/plugins/languageclient/client.h +++ b/src/plugins/languageclient/client.h @@ -305,6 +305,7 @@ private: LogTarget m_logTarget = LogTarget::Ui; bool m_locatorsEnabled = true; bool m_autoRequestCodeActions = true; + QTimer m_shutdownTimer; }; } // namespace LanguageClient From 08668e71da740b2bc8feb0138730fc95127fbc76 Mon Sep 17 00:00:00 2001 From: Henning Gruendl Date: Tue, 22 Feb 2022 11:43:06 +0100 Subject: [PATCH 76/76] QmlDesigner: Disable fill type outside base state Disable fill type ComboBox in ColorEditor when not in base state. Add tool tip to make user aware. Task-number: QDS-6184 Change-Id: Iee5644fff16fe93f2090e1cb117e96bb436fe1dd Reviewed-by: Thomas Hartmann Reviewed-by: Reviewed-by: Leena Miettinen --- .../imports/HelperWidgets/ColorEditor.qml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml index 30dbeccea9e..f2df9c0d042 100644 --- a/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml +++ b/share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/ColorEditor.qml @@ -386,6 +386,7 @@ SecondColumnLayout { property ListModel items: ListModel {} + enabled: isBaseState implicitWidth: StudioTheme.Values.colorEditorPopupCmoboBoxWidth width: implicitWidth actionIndicatorVisible: false @@ -442,6 +443,13 @@ SecondColumnLayout { } colorEditor.updateThumbnail() } + + ToolTipArea { + enabled: !isBaseState + anchors.fill: parent + tooltip: qsTr("Fill type can only be changed in base state.") + z: 10 + } } ExpandingSpacer {}