diff --git a/doc/qtcreator/images/creator-qbs-build-clean.png b/doc/qtcreator/images/creator-qbs-build-clean.png index 1ced6632727..5a4d859a827 100644 Binary files a/doc/qtcreator/images/creator-qbs-build-clean.png and b/doc/qtcreator/images/creator-qbs-build-clean.png differ diff --git a/doc/qtcreator/images/qtcreator-build-steps-custom.png b/doc/qtcreator/images/qtcreator-build-steps-custom.png index edea702bcac..45dcbdffeb9 100644 Binary files a/doc/qtcreator/images/qtcreator-build-steps-custom.png and b/doc/qtcreator/images/qtcreator-build-steps-custom.png differ diff --git a/doc/qtcreator/images/qtcreator-clean-steps.png b/doc/qtcreator/images/qtcreator-clean-steps.png index 6d2ad4f0cc8..28086d10d46 100644 Binary files a/doc/qtcreator/images/qtcreator-clean-steps.png and b/doc/qtcreator/images/qtcreator-clean-steps.png differ diff --git a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build.qdoc b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build.qdoc index 142671563a4..c898b337ee2 100644 --- a/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build.qdoc +++ b/doc/qtcreator/src/projects/creator-only/creator-projects-settings-build.qdoc @@ -47,10 +47,16 @@ build that is delivered with separate debug information. It is best suited for analyzing applications. + \section1 Managing Build Configurations + You specify build settings in the \uicontrol Projects mode. To add a new build configuration, click \uicontrol Add and select the type of configuration you would like to add. You can add as many build - configurations as you need. + configurations as you need. You can also select \uicontrol Clone to + add a build configuration that is based on the currently selected one. + + Select \uicontrol Rename to give the currently selected build configuration + a new name. To delete the build configuration currently selected, click \uicontrol Remove. diff --git a/src/plugins/android/androidbuildapkstep.cpp b/src/plugins/android/androidbuildapkstep.cpp index 04df90943c9..3112d22ae59 100644 --- a/src/plugins/android/androidbuildapkstep.cpp +++ b/src/plugins/android/androidbuildapkstep.cpp @@ -155,7 +155,8 @@ bool AndroidBuildApkStep::init() return false; const QVersionNumber sdkToolsVersion = AndroidConfigurations::currentConfig().sdkToolsVersion(); - if (sdkToolsVersion >= gradleScriptRevokedSdkVersion) { + if (sdkToolsVersion >= gradleScriptRevokedSdkVersion + || AndroidConfigurations::currentConfig().isCmdlineSdkToolsInstalled()) { if (!version->sourcePath().pathAppended("src/3rdparty/gradle").exists()) { emit addOutput(tr("The installed SDK tools version (%1) does not include Gradle " "scripts. The minimum Qt version required for Gradle build to work " diff --git a/src/plugins/android/androidconfigurations.cpp b/src/plugins/android/androidconfigurations.cpp index c753e43bf79..ea899697d56 100644 --- a/src/plugins/android/androidconfigurations.cpp +++ b/src/plugins/android/androidconfigurations.cpp @@ -428,6 +428,15 @@ QString AndroidConfig::apiLevelNameFor(const SdkPlatform *platform) QString("android-%1").arg(platform->apiLevel()) : ""; } +bool AndroidConfig::isCmdlineSdkToolsInstalled() const +{ + QString toolPath("cmdline-tools/latest/bin/sdkmanager"); + if (HostOsInfo::isWindowsHost()) + toolPath += ANDROID_BAT_SUFFIX; + + return m_sdkLocation.pathAppended(toolPath).exists(); +} + FilePath AndroidConfig::adbToolPath() const { return m_sdkLocation / "platform-tools/adb" QTC_HOST_EXE_SUFFIX; @@ -449,25 +458,43 @@ FilePath AndroidConfig::androidToolPath() const FilePath AndroidConfig::emulatorToolPath() const { QString relativePath = "emulator/emulator"; - if (sdkToolsVersion() < QVersionNumber(25, 3, 0)) + if (sdkToolsVersion() < QVersionNumber(25, 3, 0) && !isCmdlineSdkToolsInstalled()) relativePath = "tools/emulator"; return m_sdkLocation / (relativePath + QTC_HOST_EXE_SUFFIX); } FilePath AndroidConfig::sdkManagerToolPath() const { - QString toolPath = "tools/bin/sdkmanager"; - if (HostOsInfo::isWindowsHost()) - toolPath += ANDROID_BAT_SUFFIX; - return m_sdkLocation / toolPath; + QStringList sdkmanagerPaths = {"cmdline-tools/latest/bin/sdkmanager", + "tools/bin/sdkmanager"}; + + for (QString &toolPath : sdkmanagerPaths) { + if (HostOsInfo::isWindowsHost()) + toolPath += ANDROID_BAT_SUFFIX; + + const FilePath sdkmanagerPath = m_sdkLocation / toolPath; + if (sdkmanagerPath.exists()) + return sdkmanagerPath; + } + + return FilePath(); } FilePath AndroidConfig::avdManagerToolPath() const { - QString toolPath = "tools/bin/avdmanager"; - if (HostOsInfo::isWindowsHost()) - toolPath += ANDROID_BAT_SUFFIX; - return m_sdkLocation / toolPath; + QStringList sdkmanagerPaths = {"cmdline-tools/latest/bin/avdmanager", + "tools/bin/avdmanager"}; + + for (QString &toolPath : sdkmanagerPaths) { + if (HostOsInfo::isWindowsHost()) + toolPath += ANDROID_BAT_SUFFIX; + + const FilePath sdkmanagerPath = m_sdkLocation / toolPath; + if (sdkmanagerPath.exists()) + return sdkmanagerPath; + } + + return FilePath(); } FilePath AndroidConfig::aaptToolPath() const @@ -812,7 +839,7 @@ QStringList AndroidConfig::getAbis(const FilePath &adbToolPath, const QString &d bool AndroidConfig::useNativeUiTools() const { const QVersionNumber version = sdkToolsVersion(); - return !version.isNull() && version <= QVersionNumber(25, 3 ,0); + return !version.isNull() && version <= QVersionNumber(25, 3, 0) && !isCmdlineSdkToolsInstalled(); } bool AndroidConfig::isValidNdk(const QString &ndkLocation) const @@ -849,7 +876,11 @@ QVersionNumber AndroidConfig::sdkToolsVersion() const { QVersionNumber version; if (m_sdkLocation.exists()) { - const FilePath sdkToolsPropertiesPath = m_sdkLocation / "tools/source.properties"; + FilePath sdkToolsPropertiesPath; + if (isCmdlineSdkToolsInstalled()) + sdkToolsPropertiesPath = m_sdkLocation / "cmdline-tools/latest/source.properties"; + else + sdkToolsPropertiesPath = m_sdkLocation / "tools/source.properties"; QSettings settings(sdkToolsPropertiesPath.toString(), QSettings::IniFormat); auto versionStr = settings.value(sdkToolsVersionKey).toString(); version = QVersionNumber::fromString(versionStr); @@ -867,7 +898,6 @@ QVersionNumber AndroidConfig::buildToolsVersion() const return maxVersion; } - QStringList AndroidConfig::sdkManagerToolArgs() const { return m_sdkManagerToolArgs; diff --git a/src/plugins/android/androidconfigurations.h b/src/plugins/android/androidconfigurations.h index 4268afa73be..93a037cd0a5 100644 --- a/src/plugins/android/androidconfigurations.h +++ b/src/plugins/android/androidconfigurations.h @@ -185,6 +185,7 @@ public: bool isConnected(const QString &serialNumber) const; bool useNativeUiTools() const; + bool isCmdlineSdkToolsInstalled() const; bool sdkFullyConfigured() const { return m_sdkFullyConfigured; } void setSdkFullyConfigured(bool allEssentialsInstalled) { m_sdkFullyConfigured = allEssentialsInstalled; } diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp index e3ea6860890..3b58d81ad20 100644 --- a/src/plugins/android/androidsdkmanager.cpp +++ b/src/plugins/android/androidsdkmanager.cpp @@ -1,4 +1,4 @@ -/**************************************************************************** +/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ @@ -277,6 +277,7 @@ public: EmulatorToolsMarker = 0x400, NdkMarker = 0x800, ExtrasMarker = 0x1000, + CmdlineSdkToolsMarker = 0x2000, SectionMarkers = InstalledPackagesMarker | AvailablePackagesMarkers | AvailableUpdatesMarker }; @@ -313,6 +314,7 @@ const std::map markerTags { {SdkManagerOutputParser::MarkerTag::SystemImageMarker, "system-images"}, {SdkManagerOutputParser::MarkerTag::BuildToolsMarker, "build-tools"}, {SdkManagerOutputParser::MarkerTag::SdkToolsMarker, "tools"}, + {SdkManagerOutputParser::MarkerTag::CmdlineSdkToolsMarker, "cmdline-tools"}, {SdkManagerOutputParser::MarkerTag::PlatformToolsMarker, "platform-tools"}, {SdkManagerOutputParser::MarkerTag::EmulatorToolsMarker, "emulator"}, {SdkManagerOutputParser::MarkerTag::NdkMarker, "ndk"}, @@ -597,6 +599,10 @@ void SdkManagerOutputParser::parsePackageData(MarkerTag packageMarker, const QSt createPackage(&SdkManagerOutputParser::parseSdkToolsPackage); break; + case MarkerTag::CmdlineSdkToolsMarker: + createPackage(&SdkManagerOutputParser::parseSdkToolsPackage); + break; + case MarkerTag::PlatformToolsMarker: createPackage(&SdkManagerOutputParser::parsePlatformToolsPackage); break; @@ -882,7 +888,7 @@ void AndroidSdkManagerPrivate::reloadSdkPackages() return; } - if (m_config.sdkToolsVersion() < sdkManagerIntroVersion) { + if (m_config.sdkToolsVersion() < sdkManagerIntroVersion && !m_config.isCmdlineSdkToolsInstalled()) { // Old Sdk tools. m_packageListingSuccessful = true; AndroidToolManager toolManager(m_config); diff --git a/src/plugins/android/androidsettingswidget.cpp b/src/plugins/android/androidsettingswidget.cpp index 7f27b2544fb..bfdfb3360bb 100644 --- a/src/plugins/android/androidsettingswidget.cpp +++ b/src/plugins/android/androidsettingswidget.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,10 @@ #include +namespace { +static Q_LOGGING_CATEGORY(androidsettingswidget, "qtc.android.androidsettingswidget", QtWarningMsg); +} + namespace Android { namespace Internal { @@ -739,6 +744,10 @@ void AndroidSettingsWidget::onSdkPathChanged() { auto sdkPath = Utils::FilePath::fromUserInput(m_ui->SDKLocationPathChooser->rawPath()); m_androidConfig.setSdkLocation(sdkPath); + Utils::FilePath currentOpenSslPath = m_androidConfig.openSslLocation(); + if (currentOpenSslPath.isEmpty() || !currentOpenSslPath.exists()) + currentOpenSslPath = sdkPath.pathAppended("android_openssl"); + m_ui->openSslPathChooser->setFileName(currentOpenSslPath); // Package reload will trigger validateSdk. m_sdkManager->reloadPackages(); } @@ -820,8 +829,12 @@ void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent) const QString openSslRepo("https://github.com/KDAB/android_openssl.git"); Utils::QtcProcess *gitCloner = new Utils::QtcProcess(this); - gitCloner->setCommand(Utils::CommandLine("git", {"clone", "--depth=1", openSslRepo, openSslPath.fileName()})); - gitCloner->setWorkingDirectory(openSslPath.parentDir().toString()); + Utils::CommandLine gitCloneCommand("git", + {"clone", "--depth=1", openSslRepo, openSslPath.toString()}); + gitCloner->setCommand(gitCloneCommand); + + qCDebug(androidsettingswidget) << "Cloning OpenSSL repo: " << + gitCloneCommand.toUserOutput(); QDir openSslDir(openSslPath.toString()); if (openSslDir.exists()) { diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp index e8283c4b4c6..61d0f93cf56 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp @@ -944,6 +944,9 @@ bool ModelNode::hasNodeListProperty(const PropertyName &name) const static bool recursiveAncestor(const ModelNode &possibleAncestor, const ModelNode &node) { + if (!node.isValid()) + return false; + if (node.hasParentProperty()) { if (node.parentProperty().parentModelNode() == possibleAncestor) return true; diff --git a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp index ab9acc25e8c..9fa5ef8e42d 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlvisualnode.cpp @@ -327,17 +327,23 @@ NodeListProperty QmlVisualNode::findSceneNodeProperty(AbstractView *view, qint32 bool QmlVisualNode::isFlowTransition(const ModelNode &node) { - return node.metaInfo().isValid() && node.metaInfo().isSubclassOf("FlowView.FlowTransition"); + return node.isValid() + && node.metaInfo().isValid() + && node.metaInfo().isSubclassOf("FlowView.FlowTransition"); } bool QmlVisualNode::isFlowDecision(const ModelNode &node) { - return node.metaInfo().isValid() && node.metaInfo().isSubclassOf("FlowView.FlowDecision"); + return node.isValid() + && node.metaInfo().isValid() + && node.metaInfo().isSubclassOf("FlowView.FlowDecision"); } bool QmlVisualNode::isFlowWildcard(const ModelNode &node) { - return node.metaInfo().isValid() && node.metaInfo().isSubclassOf("FlowView.FlowWildcard"); + return node.isValid() + && node.metaInfo().isValid() + && node.metaInfo().isSubclassOf("FlowView.FlowWildcard"); } bool QmlVisualNode::isFlowTransition() const diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp index 00dc64af5fd..127039a55ab 100644 --- a/src/plugins/qtsupport/qtoptionspage.cpp +++ b/src/plugins/qtsupport/qtoptionspage.cpp @@ -796,6 +796,12 @@ static QString settingsFile(const QString &baseDir) + Core::Constants::IDE_CASED_ID + ".ini"; } +static QString qtVersionsFile(const QString &baseDir) +{ + return baseDir + (baseDir.isEmpty() ? "" : "/") + Core::Constants::IDE_SETTINGSVARIANT_STR + '/' + + Core::Constants::IDE_ID + '/' + "qtversion.xml"; +} + static Utils::optional currentlyLinkedQtDir(bool *hasInstallSettings) { const QString installSettingsFilePath = settingsFile(Core::ICore::resourcePath()); @@ -883,7 +889,18 @@ void QtOptionsPageWidget::apply() const QStringList kSubdirsToCheck = {"", "Qt Creator.app/Contents/Resources", "Contents/Resources", - "Tools/QtCreator/share/qtcreator"}; + "Tools/QtCreator/share/qtcreator", + "share/qtcreator"}; + +static QStringList settingsFilesToCheck() +{ + return Utils::transform(kSubdirsToCheck, [](const QString &dir) { return settingsFile(dir); }); +} + +static QStringList qtversionFilesToCheck() +{ + return Utils::transform(kSubdirsToCheck, [](const QString &dir) { return qtVersionsFile(dir); }); +} static Utils::optional settingsDirForQtDir(const QString &qtDir) { @@ -891,7 +908,7 @@ static Utils::optional settingsDirForQtDir(const QString &qtDir) return QString(qtDir + '/' + dir); }); const QString validDir = Utils::findOrDefault(dirsToCheck, [](const QString &dir) { - return QFile::exists(settingsFile(dir)); + return QFile::exists(settingsFile(dir)) || QFile::exists(qtVersionsFile(dir)); }); if (!validDir.isEmpty()) return validDir; @@ -903,15 +920,11 @@ static bool validateQtInstallDir(FancyLineEdit *input, QString *errorString) const QString qtDir = input->text(); if (!settingsDirForQtDir(qtDir)) { if (errorString) { - const QStringList filesToCheck = Utils::transform(kSubdirsToCheck, - [](const QString &dir) { - return settingsFile(dir); - }); + const QStringList filesToCheck = settingsFilesToCheck() + qtversionFilesToCheck(); *errorString = "" + QtOptionsPageWidget::tr( "Qt installation information was not found in \"%1\". " "Choose a directory that contains one of the files %2") - .arg(qtDir, "
" + filesToCheck.join('\n') + "
") - + ""; + .arg(qtDir, "
" + filesToCheck.join('\n') + "
"); } return false; }