From dc66a01b108ab722042e0d64df3f3249d07abeea Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Wed, 2 Apr 2014 13:16:48 +0200 Subject: [PATCH 01/13] Squish: Configure old Qt Quick projects with Qt 4 Change-Id: I3a891ba8a3ca5d437c114a95fb1620a200261301 Reviewed-by: Christian Stenger --- tests/system/suite_QMLS/tst_QMLS03/test.py | 2 +- tests/system/suite_editors/tst_qml_editor/test.py | 2 +- tests/system/suite_general/tst_session_handling/test.py | 2 +- tests/system/suite_qtquick/tst_qml_outline/test.py | 6 +----- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/system/suite_QMLS/tst_QMLS03/test.py b/tests/system/suite_QMLS/tst_QMLS03/test.py index d8b435b24e1..a46a13999cf 100644 --- a/tests/system/suite_QMLS/tst_QMLS03/test.py +++ b/tests/system/suite_QMLS/tst_QMLS03/test.py @@ -79,7 +79,7 @@ def main(): if not startedWithoutPluginError(): return # open example project - openQmakeProject(examplePath) + openQmakeProject(examplePath, Targets.DESKTOP_480_GCC) # open qml file openDocument("propertyanimation.QML.qml.color-animation\\.qml") # get editor diff --git a/tests/system/suite_editors/tst_qml_editor/test.py b/tests/system/suite_editors/tst_qml_editor/test.py index fe188db5129..cd6fca51585 100644 --- a/tests/system/suite_editors/tst_qml_editor/test.py +++ b/tests/system/suite_editors/tst_qml_editor/test.py @@ -43,7 +43,7 @@ def main(): addHelpDocumentation([os.path.join(sdkPath, "Documentation", "qt.qch")]) templateDir = prepareTemplate(sourceExample) installLazySignalHandler("{type='Core::FutureProgress' unnamed='1'}", "finished()", "__handleFutureProgress__") - openQmakeProject(os.path.join(templateDir,proFile)) + openQmakeProject(os.path.join(templateDir,proFile), Targets.DESKTOP_480_GCC) openDocument("focus.QML.qml.focus\\.qml") testRenameId() testFindUsages() diff --git a/tests/system/suite_general/tst_session_handling/test.py b/tests/system/suite_general/tst_session_handling/test.py index 9d81da376d0..1bfec7e6951 100644 --- a/tests/system/suite_general/tst_session_handling/test.py +++ b/tests/system/suite_general/tst_session_handling/test.py @@ -42,7 +42,7 @@ def main(): test.verify(waitFor("sessionName in str(mainWindow.windowTitle)", 2000), "Verifying window title contains created session name.") for project in projects: - openQmakeProject(project) + openQmakeProject(project, Targets.DESKTOP_480_GCC) progressBarWait(20000) checkNavigator(68, "Verifying whether all projects have been opened.") openDocument("propertyanimation.QML.qml.color-animation\\.qml") diff --git a/tests/system/suite_qtquick/tst_qml_outline/test.py b/tests/system/suite_qtquick/tst_qml_outline/test.py index 46420f3310d..879e05e3089 100644 --- a/tests/system/suite_qtquick/tst_qml_outline/test.py +++ b/tests/system/suite_qtquick/tst_qml_outline/test.py @@ -42,11 +42,7 @@ def main(): startApplication("qtcreator" + SettingsPath) if not startedWithoutPluginError(): return - targets = openQmakeProject(os.path.join(templateDir, proFile)) - # make sure we use the 474 kit for having QtQuick 1.0 support - switchViewTo(ViewConstants.PROJECTS) - switchToBuildOrRunSettingsFor(len(targets), 0, ProjectSettings.BUILD) - switchViewTo(ViewConstants.EDIT) + openQmakeProject(os.path.join(templateDir, proFile), Targets.DESKTOP_480_GCC) qmlFiles = ["focus.QML.qml.focus\\.qml", "focus.QML.qml.Core.ListMenu\\.qml"] checkOutlineFor(qmlFiles) testModify() From 57f11f40d60d508a09cbc9ee474e2347cc9485fb Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 2 Apr 2014 13:42:53 +0200 Subject: [PATCH 02/13] Welcome: Store examples search text in settings in QtCreator.ini under "WelcomePage/ExamplesSearchString". The installer pre-set that setting, and in that way pre- select a set of examples. Change-Id: I8ac5a38ad0bd3f33875ef1997ccbf0352410dcc3 Reviewed-by: Thomas Hartmann --- share/qtcreator/welcomescreen/examples.qml | 7 ++++++- src/plugins/qtsupport/exampleslistmodel.cpp | 11 +++++++++++ src/plugins/qtsupport/exampleslistmodel.h | 2 ++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/share/qtcreator/welcomescreen/examples.qml b/share/qtcreator/welcomescreen/examples.qml index 53d77a0d3bf..5dc5d53bde6 100644 --- a/share/qtcreator/welcomescreen/examples.qml +++ b/share/qtcreator/welcomescreen/examples.qml @@ -56,8 +56,13 @@ Rectangle { anchors.right: parent.right anchors.leftMargin: 18 + text: examplesModel.readSearchStringsFromSettings() + placeholderText: qsTr("Search in Examples...") - onTextChanged: examplesModel.parseSearchString(text) + onTextChanged: { + examplesModel.parseSearchString(text); + examplesModel.writeSearchStringToSettings(text); + } } ComboBox { diff --git a/src/plugins/qtsupport/exampleslistmodel.cpp b/src/plugins/qtsupport/exampleslistmodel.cpp index 22f4bf66d1f..ebab7763180 100644 --- a/src/plugins/qtsupport/exampleslistmodel.cpp +++ b/src/plugins/qtsupport/exampleslistmodel.cpp @@ -54,6 +54,7 @@ static bool debugExamples() } static const char kSelectedExampleSetKey[] = "WelcomePage/SelectedExampleSet"; +static const char kExamplesSearchStringKey[] = "WelcomePage/ExamplesSearchString"; void ExampleSetModel::writeCurrentIdToSettings(int currentIndex) const { @@ -841,6 +842,16 @@ void ExamplesListModelFilter::filterForExampleSet(int index) m_sourceModel->selectExampleSet(index); } +void ExamplesListModelFilter::writeSearchStringToSettings(const QString &string) +{ + Core::ICore::settings()->setValue(QLatin1String(kExamplesSearchStringKey), string); +} + +QString ExamplesListModelFilter::readSearchStringsFromSettings() +{ + return Core::ICore::settings()->value(QLatin1String(kExamplesSearchStringKey)).toString(); +} + void ExamplesListModelFilter::setShowTutorialsOnly(bool showTutorialsOnly) { m_showTutorialsOnly = showTutorialsOnly; diff --git a/src/plugins/qtsupport/exampleslistmodel.h b/src/plugins/qtsupport/exampleslistmodel.h index 6a2607de741..ae30ec9290f 100644 --- a/src/plugins/qtsupport/exampleslistmodel.h +++ b/src/plugins/qtsupport/exampleslistmodel.h @@ -185,6 +185,8 @@ public: QAbstractItemModel* exampleSetModel(); Q_INVOKABLE void filterForExampleSet(int index); + Q_INVOKABLE void writeSearchStringToSettings(const QString &string); + Q_INVOKABLE QString readSearchStringsFromSettings(); public slots: void setFilterTags(const QStringList &arg) From ee4f2557ca2ffdee36ac975b621b67e730ce03bd Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 2 Apr 2014 13:20:52 +0200 Subject: [PATCH 03/13] More changelog Change-Id: I7088ac84ae840c9e1dc83ff667938447406cc607 Reviewed-by: Leena Miettinen --- dist/changes-3.1.0 | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/dist/changes-3.1.0 b/dist/changes-3.1.0 index e60625d25e5..dec584e72ba 100644 --- a/dist/changes-3.1.0 +++ b/dist/changes-3.1.0 @@ -26,6 +26,7 @@ Editing Managing and Building Projects * Re-added option to import existing builds even after project configuration (QTCREATORBUG-7836) * Fixed that compiler output in issues list was not using monospace font (QTCREATORBUG-11345) + * Fixed crash when removing run configuration that was about to be run (QTCREATORBUG-11594) QMake Projects * Added context menu item "Add Existing Directory" that adds all @@ -46,20 +47,24 @@ Debugging * Removed support for GDB without Python * Added context menu item for saving backtrace as tasks-file * GDB, LLDB - * Added pretty printer for std::unordered_set + * Added pretty printers for std::unordered_set and boost::container::list * Fixed various pretty printers * CDB * Added pretty printer for std::complex and C++11 std::array * LLDB + * Added support for debugging applications that run in terminal (QTCREATORBUG-9650) + * Added support for "Create Full Backtrace" (QTCREATORBUG-11642) * Fixed that debugging was not possible with MallocScribble environment variable set (QTCREATORBUG-11371) * Fixed "Jump to Line", "Run to Line" and "Jump to Address" + * Fixed updating breakpoint locations while debugging (QTCREATORBUG-11564) QML Profiler * Improved performance (QTCREATORBUG-10950) * Improved layout of details views * Added JavaScript calls in Events view and Timeline view * Fixed opening files from JavaScript profiling output (QTCREATORBUG-11094) + * Fixed hovering over narrow items in Timeline view (QTCREATORBUG-11692) C++ Support * Added code model inspector @@ -72,6 +77,7 @@ C++ Support * Fixed syntax highlighting of multiline strings and comments (QTCREATORBUG-662) * Fixed that symbol dropdown was jumping to the wrong editor (QTCREATORBUG-11157) * Fixed highlighting when #undef is used (QTCREATORBUG-10454) + * Fixed issue with follow symbol and overloaded functions (QTCREATORBUG-10295) * Improved the Insert Virtual Functions refactoring action: * Check only pure virtual functions by default * Display all overrides of a function @@ -131,6 +137,7 @@ QNX * Added support for attaching debugger to running applications * Fixed several issues with certificate password dialog in BlackBerry options (QTCREATORBUG-10948) + * Fixed mkspec setting in the qmake build step (QTCREATORBUG-11674) Android * Made it possible to cancel waiting for an AVD to boot up @@ -146,9 +153,14 @@ Android * Fixed that Qt Creator restart was required after configuring Android SDK (QTCREATORBUG-10936) iOS + * Enabled iOS support by default + * Added support for QML debugging * Added check for already running application on device * Added automatic detection that developer mode becomes activated on connected device +WinRT + * Added experimental support + Credits for these changes go to: Alessandro Portale From ee6ecef5fb42609f819e0bf57470e461212c0031 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 26 Mar 2014 10:41:59 +0100 Subject: [PATCH 04/13] Use mapping file for app deployment on Windows Phone Change-Id: I4c61e1b19c89277829148d31f8ff2b971375d93e Reviewed-by: Andrew Knight Reviewed-by: Joerg Bornemann --- .../winrt/winrtpackagedeploymentstep.cpp | 136 ++++++++++++++++++ .../winrt/winrtpackagedeploymentstep.h | 11 ++ 2 files changed, 147 insertions(+) diff --git a/src/plugins/winrt/winrtpackagedeploymentstep.cpp b/src/plugins/winrt/winrtpackagedeploymentstep.cpp index ff746e2c3d7..71a53155d39 100644 --- a/src/plugins/winrt/winrtpackagedeploymentstep.cpp +++ b/src/plugins/winrt/winrtpackagedeploymentstep.cpp @@ -35,8 +35,14 @@ #include #include #include +#include +#include +#include +#include #include +#include + using namespace ProjectExplorer; using Utils::QtcProcess; @@ -45,6 +51,7 @@ namespace Internal { WinRtPackageDeploymentStep::WinRtPackageDeploymentStep(BuildStepList *bsl) : AbstractProcessStep(bsl, Constants::WINRT_BUILD_STEP_DEPLOY) + , m_createMappingFile(false) { setDisplayName(tr("Run windeployqt")); m_args = defaultWinDeployQtArguments(); @@ -56,11 +63,46 @@ bool WinRtPackageDeploymentStep::init() const QString targetPath = target()->applicationTargets().targetForProject(proFile).toString() + QLatin1String(".exe"); + QString targetDir = targetPath.left(targetPath.lastIndexOf(QLatin1Char('/')) + 1); // ### Actually, targetForProject is supposed to return the file path including the file // extension. Whenever this will eventually work, we have to remove the .exe suffix here. + const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit()); + if (!qt) + return false; + + m_isWinPhone = (qt->type() == QLatin1String(Constants::WINRT_WINPHONEQT)); + QString args = QtcProcess::quoteArg(QDir::toNativeSeparators(targetPath)); args += QLatin1Char(' ') + m_args; + if (m_isWinPhone) { + m_manifestFileName = QLatin1String("WMAppManifest"); + m_createMappingFile = true; + } else { + m_manifestFileName = QLatin1String("AppxManifest"); + } + + if (m_createMappingFile) { + args += QLatin1String(" -list mapping"); + m_mappingFileContent = QLatin1String("[Files]\n\"") + QDir::toNativeSeparators(targetDir) + + m_manifestFileName + QLatin1String(".xml\" \"") + m_manifestFileName + QLatin1String(".xml\"\n"); + + QDir assetDirectory(targetDir + QLatin1String("assets")); + if (assetDirectory.exists()) { + QStringList iconsToDeploy; + const QString fullManifestPath = targetDir + m_manifestFileName + QLatin1String(".xml"); + if (!parseIconsAndExecutableFromManifest(fullManifestPath, &iconsToDeploy, + &m_executablePathInManifest)) { + raiseError(tr("Cannot parse manifest file %1.").arg(fullManifestPath)); + return false; + } + foreach (QString icon, iconsToDeploy) { + m_mappingFileContent += QLatin1Char('"') + + QDir::toNativeSeparators(targetDir + icon) + QLatin1String("\" \"") + + QDir::toNativeSeparators(icon) + QLatin1String("\"\n"); + } + } + } ProcessParameters *params = processParameters(); params->setCommand(QLatin1String("windeployqt.exe")); @@ -70,6 +112,67 @@ bool WinRtPackageDeploymentStep::init() return AbstractProcessStep::init(); } +bool WinRtPackageDeploymentStep::processSucceeded(int exitCode, QProcess::ExitStatus status) +{ + if (m_createMappingFile) { + Utils::FileName proFile = Utils::FileName::fromString(project()->projectFilePath()); + QString targetPath + = target()->applicationTargets().targetForProject(proFile).toString(); + QString targetDir = targetPath.left(targetPath.lastIndexOf(QLatin1Char('/')) + 1); + QString targetInstallationPath; + // The list holds the local file paths and the "remote" file paths + QList > installableFilesList; + foreach (DeployableFile file, target()->deploymentData().allFiles()) { + QString remoteFilePath = file.remoteFilePath(); + QString localFilePath = file.localFilePath().toString(); + if (localFilePath == targetPath) { + if (!targetPath.endsWith(QLatin1String(".exe"))) { + remoteFilePath += QLatin1String(".exe"); + localFilePath += QLatin1String(".exe"); + } + targetInstallationPath = remoteFilePath; + } + installableFilesList.append(QPair(localFilePath, remoteFilePath)); + } + + // if there are no INSTALLS set we just deploy the files from windeployqt, the manifest + // and the icons referenced in there and the actual build target + if (targetInstallationPath.isEmpty()) { + targetPath += QLatin1String(".exe"); + m_mappingFileContent + += QLatin1Char('"') + QDir::toNativeSeparators(targetPath) + QLatin1String("\" \"") + + QDir::toNativeSeparators(m_executablePathInManifest) + QLatin1String("\"\n"); + } else { + targetInstallationPath = targetInstallationPath.left(targetInstallationPath.lastIndexOf(QLatin1Char('/')) + 1); + for (int i = 0; i < installableFilesList.length(); ++i) { + QPair pair = installableFilesList.at(i); + // For the mapping file we need the remote paths relative to the application's executable + const QString relativeRemotePath = QDir(targetInstallationPath).relativeFilePath(pair.second); + m_mappingFileContent += QLatin1Char('"') + QDir::toNativeSeparators(pair.first) + + QLatin1String("\" \"") + QDir::toNativeSeparators(relativeRemotePath) + + QLatin1String("\"\n"); + } + } + + const QString mappingFilePath = targetDir + m_manifestFileName + QLatin1String(".map"); + QFile mappingFile(mappingFilePath); + if (!mappingFile.open(QFile::WriteOnly | QFile::Text)) { + raiseError(tr("Cannot open mapping file %1 for writing.").arg(mappingFilePath)); + return false; + } + mappingFile.write(m_mappingFileContent.toUtf8()); + } + + return AbstractProcessStep::processSucceeded(exitCode, status); +} + +void WinRtPackageDeploymentStep::stdOutput(const QString &line) +{ + if (m_createMappingFile) + m_mappingFileContent += line; + AbstractProcessStep::stdOutput(line); +} + BuildStepConfigWidget *WinRtPackageDeploymentStep::createConfigWidget() { return new WinRtPackageDeploymentStepWidget(this); @@ -93,6 +196,13 @@ QString WinRtPackageDeploymentStep::defaultWinDeployQtArguments() const return args; } +void WinRtPackageDeploymentStep::raiseError(const QString &errorMessage) +{ + emit addOutput(errorMessage, BuildStep::ErrorMessageOutput); + emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error, errorMessage, Utils::FileName(), -1, + ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT)); +} + bool WinRtPackageDeploymentStep::fromMap(const QVariantMap &map) { if (!AbstractProcessStep::fromMap(map)) @@ -110,5 +220,31 @@ QVariantMap WinRtPackageDeploymentStep::toMap() const return map; } +bool WinRtPackageDeploymentStep::parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *icons, QString *executable) +{ + if (!icons->isEmpty()) + icons->clear(); + QFile manifestFile(manifestFileName); + if (!manifestFile.open(QFile::ReadOnly)) + return false; + const QString contents = QString::fromUtf8(manifestFile.readAll()); + + QRegularExpression iconPattern(QStringLiteral("[\\\\/a-zA-Z0-9_\\-\\!]*\\.(png|jpg|jpeg)")); + QRegularExpressionMatchIterator iterator = iconPattern.globalMatch(contents); + while (iterator.hasNext()) { + QRegularExpressionMatch match = iterator.next(); + const QString icon = match.captured(0); + icons->append(icon); + } + + QRegularExpression executablePattern(QStringLiteral("ImagePath=\"([a-zA-Z0-9_-]*\\.exe)\"")); + QRegularExpressionMatch match = executablePattern.match(contents); + if (!match.hasMatch()) + return false; + *executable = match.captured(1); + + return true; +} + } // namespace Internal } // namespace WinRt diff --git a/src/plugins/winrt/winrtpackagedeploymentstep.h b/src/plugins/winrt/winrtpackagedeploymentstep.h index 592395827b1..0c567b93d4f 100644 --- a/src/plugins/winrt/winrtpackagedeploymentstep.h +++ b/src/plugins/winrt/winrtpackagedeploymentstep.h @@ -41,17 +41,28 @@ class WinRtPackageDeploymentStep : public ProjectExplorer::AbstractProcessStep public: explicit WinRtPackageDeploymentStep(ProjectExplorer::BuildStepList *bsl); bool init(); + bool processSucceeded(int exitCode, QProcess::ExitStatus status); + void stdOutput(const QString &line); ProjectExplorer::BuildStepConfigWidget *createConfigWidget(); void setWinDeployQtArguments(const QString &args); QString winDeployQtArguments() const; QString defaultWinDeployQtArguments() const; + void raiseError(const QString &errorMessage); + bool fromMap(const QVariantMap &map); QVariantMap toMap() const; private: + bool parseIconsAndExecutableFromManifest(QString manifestFileName, QStringList *items, QString *executable); + QString m_args; + QString m_executablePathInManifest; + QString m_mappingFileContent; + QString m_manifestFileName; + bool m_isWinPhone; + bool m_createMappingFile; }; } // namespace Internal From 1ca022e3785793ad23f5efc0461b4e6b5c6da122 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 1 Apr 2014 18:42:56 +0200 Subject: [PATCH 05/13] FakeVim: Check handler pointer before using it Shouldn't happen in that case. But better safe than sorry. Change-Id: I8461fec32c23e7efe6c949724cf522b58b703acc Reviewed-by: Lukas Holecek Reviewed-by: Eike Ziller --- src/plugins/fakevim/fakevimplugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/fakevim/fakevimplugin.cpp b/src/plugins/fakevim/fakevimplugin.cpp index 756121aeef2..1ec80f51079 100644 --- a/src/plugins/fakevim/fakevimplugin.cpp +++ b/src/plugins/fakevim/fakevimplugin.cpp @@ -2123,6 +2123,7 @@ void FakeVimPluginPrivate::showExtraInformation(const QString &text) IEditor *iedit = EditorManager::openEditorWithContents(Id(), &title, text.toUtf8()); EditorManager::activateEditor(iedit); FakeVimHandler *handler = m_editorToHandler.value(iedit, 0); + QTC_ASSERT(handler, return); handler->handleCommand(_("0")); } From 41327df2a93e8baca94e9e8a858d0aeb15105d50 Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Wed, 2 Apr 2014 03:16:09 +0200 Subject: [PATCH 06/13] ios: override spec for ios On ios qmake is called recursively and the second call with a different spec (macx-xcode instead of macx-ios-clang) which contains the correct build settings (includes, compiler flags) as ios builds with xcode. macx-ios-clang just creates supporting makefiles, and to avoid being slow does not evaluate everything, and contains misleading information (that is never used), whereas macx-xcode correctly evaluates the the variables and generates the xcodeproject that is actually used to build the application. It is important to override only for the creator evaluator, and not the qmake buildstep used to build the app (as we use the makefiles). Task-number: QTCREATORBUG-11908 Change-Id: I06d569de16f934fca5e104a8da727a3557a4c2e3 Reviewed-by: Daniel Teske Reviewed-by: Eike Ziller Reviewed-by: Oswald Buddenhagen --- src/plugins/qmakeprojectmanager/qmakeproject.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index bc0bee6b8d3..21fa44ede63 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -989,6 +989,20 @@ QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFileNo m_qmakeGlobals->setCommandLineArguments(m_rootProjectNode->buildDir(), qmakeArgs); QtSupport::ProFileCacheManager::instance()->incRefCount(); + + // On ios, qmake is called recursively, and the second call with a different + // spec. + // macx-ios-clang just creates supporting makefiles, and to avoid being + // slow does not evaluate everything, and contains misleading information + // (that is never used). + // macx-xcode correctly evaluates the variables and generates the xcodeproject + // that is actually used to build the application. + // + // It is important to override the spec file only for the creator evaluator, + // and not the qmake buildstep used to build the app (as we use the makefiles). + const char IOSQT[] = "Qt4ProjectManager.QtVersion.Ios"; // from Ios::Constants + if (qtVersion->type() == QLatin1String(IOSQT)) + m_qmakeGlobals->xqmakespec = QLatin1String("macx-xcode"); } ++m_qmakeGlobalsRefCnt; From 73577b33f3c62d3558d3e6e4fb275e6c2022bc1c Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Wed, 2 Apr 2014 12:35:59 +0200 Subject: [PATCH 07/13] profileevaluator: do not add sysroot if the result does not exist Required for Qt paths in includes on ios. Task-number: QTCREATORBUG-11908 Change-Id: Ic56c81812d13e3d6f6acb31d59c1ff7c7048aeff Reviewed-by: Eike Ziller --- src/shared/proparser/profileevaluator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp index bb781a50a5a..024dbb52fc6 100644 --- a/src/shared/proparser/profileevaluator.cpp +++ b/src/shared/proparser/profileevaluator.cpp @@ -100,7 +100,8 @@ QString ProFileEvaluator::sysrootify(const QString &path, const QString &baseDir #endif const bool isHostSystemPath = option->sysroot.isEmpty() || path.startsWith(option->sysroot, cs) - || path.startsWith(baseDir, cs) || path.startsWith(d->m_outputDir, cs); + || path.startsWith(baseDir, cs) || path.startsWith(d->m_outputDir, cs) + || !QFileInfo(option->sysroot + path).exists(); return isHostSystemPath ? path : option->sysroot + path; } From 4e176cb15cc09868392076082d4d3f6f11790463 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 2 Apr 2014 15:08:50 +0200 Subject: [PATCH 08/13] Debugger: Abort gdb session if no python support is found The message will be untranslated due to the string freeze, but better than nothing. Task-number: QTCREATORBUG-11505 Change-Id: I6f5e65615e4c20f42ce6800b8107f923c2ae2c4f Reviewed-by: Eike Ziller --- src/plugins/debugger/gdb/gdbengine.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 89b52fde81d..e514199616e 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1763,6 +1763,13 @@ void GdbEngine::handlePythonSetup(const GdbResponse &response) showMessage(_("ENGINE SUCCESSFULLY STARTED")); notifyEngineSetupOk(); } else { + QByteArray msg = response.data["msg"].data(); + if (msg.contains("Python scripting is not supported in this copy of GDB.")) { + QString out1 = _("The selected build of GDB does not support Python scripting."); + QString out2 = _("It cannot be used in Qt Creator."); + showStatusMessage(out1 + QLatin1Char(' ') + out2); + showMessageBox(QMessageBox::Critical, tr("Execution Error"), out1 + _("
") + out2); + } notifyEngineSetupFailed(); } } From bde0571b749a50ed7e50ad958b6b145a83e36948 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Wed, 2 Apr 2014 14:16:03 +0200 Subject: [PATCH 09/13] Fix missing white space in German translation Change-Id: I0b4db6f76befed238427f7fbf51fd73446dbb773 Reviewed-by: Friedemann Kleint --- share/qtcreator/translations/qtcreator_de.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts index f51cfaa01db..ca4b9657837 100644 --- a/share/qtcreator/translations/qtcreator_de.ts +++ b/share/qtcreator/translations/qtcreator_de.ts @@ -7213,7 +7213,7 @@ Add, modify, and remove document filters, which determine the documentation set Error while building/deploying project %1 (kit: %2) - Fehler beim Erstellen/Deployment des Projekts %1(Kit: %2) + Fehler beim Erstellen/Deployment des Projekts %1 (Kit: %2) When executing step '%1' From a0239e3e719910fba96beab7e28adf0468844566 Mon Sep 17 00:00:00 2001 From: Daniel Teske Date: Tue, 1 Apr 2014 13:35:47 +0200 Subject: [PATCH 10/13] MsvcToolchain: Fix environment detection for some setups Instead of redirecting the set output to a temporary file output it on stdout with some begin/end markers. This way we don't need to write any filenames into the batch file. Task-number: QTCREATORBUG-11539 Change-Id: I7cfef0f0361d5a2e93fd46298be40f511158b694 Reviewed-by: Tobias Hunger --- .../projectexplorer/abstractmsvctoolchain.cpp | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp index f71c1892cc9..3964f8f8e07 100644 --- a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp @@ -243,17 +243,11 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env, const QString &batchArgs, QMap &envPairs) { + const QByteArray marker = "####################\r\n"; // Create a temporary file name for the output. Use a temporary file here // as I don't know another way to do this in Qt... // Note, can't just use a QTemporaryFile all the way through as it remains open // internally so it can't be streamed to later. - QString tempOutFile; - QTemporaryFile* pVarsTempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/XXXXXX.txt")); - pVarsTempFile->setAutoRemove(false); - pVarsTempFile->open(); - pVarsTempFile->close(); - tempOutFile = pVarsTempFile->fileName(); - delete pVarsTempFile; // Create a batch file to create and save the env settings Utils::TempFileSaver saver(QDir::tempPath() + QLatin1String("/XXXXXX.bat")); @@ -265,10 +259,9 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env, call += batchArgs.toLocal8Bit(); } saver.write(call + "\r\n"); - - const QByteArray redirect = "set > " + Utils::QtcProcess::quoteArg( - QDir::toNativeSeparators(tempOutFile)).toLocal8Bit() + "\r\n"; - saver.write(redirect); + saver.write("@echo " + marker); + saver.write("set\r\n"); + saver.write("@echo " + marker); if (!saver.finalize()) { qWarning("%s: %s", Q_FUNC_INFO, qPrintable(saver.errorString())); return false; @@ -304,19 +297,31 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env, return false; } // The SDK/MSVC scripts do not return exit codes != 0. Check on stdout. - const QByteArray stdOut = run.readAllStandardOutput(); + QByteArray stdOut = run.readAllStandardOutput(); if (!stdOut.isEmpty() && (stdOut.contains("Unknown") || stdOut.contains("Error"))) qWarning("%s: '%s' reports:\n%s", Q_FUNC_INFO, call.constData(), stdOut.constData()); // // Now parse the file to get the environment settings - QFile varsFile(tempOutFile); - if (!varsFile.open(QIODevice::ReadOnly)) + int start = stdOut.indexOf(marker); + if (start == -1) { + qWarning("Could not find start marker in stdout output."); return false; + } + stdOut = stdOut.mid(start + marker.size()); + + int end = stdOut.indexOf(marker); + if (end == -1) { + qWarning("Could not find end marker in stdout output."); + return false; + } + + stdOut = stdOut.left(end); + + QStringList lines = QString::fromLocal8Bit(stdOut).split(QLatin1String("\r\n")); QRegExp regexp(QLatin1String("(\\w*)=(.*)")); - while (!varsFile.atEnd()) { - const QString line = QString::fromLocal8Bit(varsFile.readLine()).trimmed(); + foreach (const QString &line, lines) { if (regexp.exactMatch(line)) { const QString varName = regexp.cap(1); const QString varValue = regexp.cap(2); @@ -326,10 +331,6 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env, } } - // Tidy up and remove the file - varsFile.close(); - varsFile.remove(); - return true; } From be1a94ef1f06780c52221a1c0ed1cf978cf6e1f4 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 28 Mar 2014 16:06:07 +0100 Subject: [PATCH 11/13] QmlProfiler: Keep an extra time window in ZoomControl This window is dynamically sized so that no integer overflows can occur when using it in the timeline view instead of the whole trace time. Task-number: QTCREATORBUG-11879 Change-Id: Id86faaf614b5f833e47ce26bb859b63eb09e7547 Reviewed-by: Kai Koehne --- .../qmlprofiler/qmlprofilermodelmanager.cpp | 14 ++- .../qmlprofiler/qmlprofilermodelmanager.h | 4 + .../qmlprofiler/qmlprofilertraceview.cpp | 87 ++++++++++++++++++- .../qmlprofiler/qmlprofilertraceview.h | 29 ++++++- 4 files changed, 126 insertions(+), 8 deletions(-) diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index 17b894647ed..4ec8c71ed0a 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -112,18 +112,24 @@ qint64 QmlProfilerTraceTime::duration() const void QmlProfilerTraceTime::clear() { - m_startTime = -1; - m_endTime = -1; + setStartTime(-1); + setEndTime(-1); } void QmlProfilerTraceTime::setStartTime(qint64 time) { - m_startTime = time; + if (time != m_startTime) { + m_startTime = time; + emit startTimeChanged(time); + } } void QmlProfilerTraceTime::setEndTime(qint64 time) { - m_endTime = time; + if (time != m_endTime) { + m_endTime = time; + emit endTimeChanged(time); + } } diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h index c9e2047cead..1be9abd973f 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h @@ -84,6 +84,10 @@ public: qint64 endTime() const; qint64 duration() const; +signals: + void startTimeChanged(qint64); + void endTimeChanged(qint64); + public slots: void clear(); void setStartTime(qint64 time); diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp index c8f6562704d..6d7fa6a5944 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -61,15 +61,88 @@ namespace QmlProfiler { namespace Internal { ///////////////////////////////////////////////////////// +ZoomControl::ZoomControl(const QmlProfilerTraceTime *traceTime, QObject *parent) : + QObject(parent), m_startTime(traceTime->startTime()), m_endTime(traceTime->endTime()), + m_windowStart(traceTime->startTime()), m_windowEnd(traceTime->endTime()), + m_traceTime(traceTime), m_windowLocked(false) +{ + connect(traceTime, SIGNAL(startTimeChanged(qint64)), this, SLOT(rebuildWindow())); + connect(traceTime, SIGNAL(endTimeChanged(qint64)), this, SLOT(rebuildWindow())); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(moveWindow())); +} + void ZoomControl::setRange(qint64 startTime, qint64 endTime) { if (m_startTime != startTime || m_endTime != endTime) { + m_timer.stop(); m_startTime = startTime; m_endTime = endTime; + rebuildWindow(); emit rangeChanged(); } } +void ZoomControl::rebuildWindow() +{ + qint64 minDuration = 1; // qMax needs equal data types, so literal 1 won't do + qint64 shownDuration = qMax(duration(), minDuration); + + qint64 oldWindowStart = m_windowStart; + qint64 oldWindowEnd = m_windowEnd; + if (m_traceTime->duration() / shownDuration < MAX_ZOOM_FACTOR) { + m_windowStart = m_traceTime->startTime(); + m_windowEnd = m_traceTime->endTime(); + } else if (windowLength() / shownDuration > MAX_ZOOM_FACTOR || + windowLength() / shownDuration * 2 < MAX_ZOOM_FACTOR) { + qint64 keep = shownDuration * MAX_ZOOM_FACTOR / 2 - shownDuration; + m_windowStart = m_startTime - keep; + if (m_windowStart < m_traceTime->startTime()) { + keep += m_traceTime->startTime() - m_windowStart; + m_windowStart = m_traceTime->startTime(); + } + + m_windowEnd = m_endTime + keep; + if (m_windowEnd > m_traceTime->endTime()) { + m_windowStart = qMax(m_traceTime->startTime(), + m_windowStart - m_windowEnd - m_traceTime->endTime()); + m_windowEnd = m_traceTime->endTime(); + } + } else { + m_timer.start(500); + } + if (oldWindowStart != m_windowStart || oldWindowEnd != m_windowEnd) + emit windowChanged(); +} + +void ZoomControl::moveWindow() +{ + if (m_windowLocked) + return; + m_timer.stop(); + + qint64 offset = (m_endTime - m_windowEnd + m_startTime - m_windowStart) / 2; + if (offset == 0 || (offset < 0 && m_windowStart == m_traceTime->startTime()) || + (offset > 0 && m_windowEnd == m_traceTime->endTime())) { + return; + } else if (offset > duration()) { + offset = (offset + duration()) / 2; + } else if (offset < -duration()) { + offset = (offset - duration()) / 2; + } + m_windowStart += offset; + if (m_windowStart < m_traceTime->startTime()) { + m_windowEnd += m_traceTime->startTime() - m_windowStart; + m_windowStart = m_traceTime->startTime(); + } + m_windowEnd += offset; + if (m_windowEnd > m_traceTime->endTime()) { + m_windowStart -= m_windowEnd - m_traceTime->endTime(); + m_windowEnd = m_traceTime->endTime(); + } + emit windowChanged(); + m_timer.start(100); +} + ///////////////////////////////////////////////////////// class QmlProfilerTraceView::QmlProfilerTraceViewPrivate { @@ -108,7 +181,7 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, Analyzer::IAnalyzerT { setObjectName(QLatin1String("QML Profiler")); - d->m_zoomControl = new ZoomControl(this); + d->m_zoomControl = new ZoomControl(modelManager->traceTime(), this); connect(d->m_zoomControl, SIGNAL(rangeChanged()), this, SLOT(updateRange())); QVBoxLayout *groupLayout = new QVBoxLayout; @@ -396,6 +469,18 @@ void QmlProfilerTraceView::resizeEvent(QResizeEvent *event) emit resized(); } +void QmlProfilerTraceView::mousePressEvent(QMouseEvent *event) +{ + d->m_zoomControl->setWindowLocked(true); + QWidget::mousePressEvent(event); +} + +void QmlProfilerTraceView::mouseReleaseEvent(QMouseEvent *event) +{ + d->m_zoomControl->setWindowLocked(false); + QWidget::mouseReleaseEvent(event); +} + //////////////////////////////////////////////////////////////// // Context menu void QmlProfilerTraceView::contextMenuEvent(QContextMenuEvent *ev) diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.h b/src/plugins/qmlprofiler/qmlprofilertraceview.h index d6c0210c547..2203e643474 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceview.h +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.h @@ -30,8 +30,10 @@ #ifndef QMLPROFILERTRACEVIEW_H #define QMLPROFILERTRACEVIEW_H +#include "qmlprofilermodelmanager.h" #include #include +#include namespace Analyzer { class IAnalyzerTool; } @@ -47,19 +49,38 @@ class QmlProfilerViewManager; class ZoomControl : public QObject { Q_OBJECT public: - ZoomControl(QObject *parent=0):QObject(parent),m_startTime(0),m_endTime(0) {} + static const qint64 MAX_ZOOM_FACTOR = 1 << 12; + + ZoomControl(const QmlProfilerTraceTime *traceTime, QObject *parent = 0); ~ZoomControl(){} Q_INVOKABLE void setRange(qint64 startTime, qint64 endTime); - Q_INVOKABLE qint64 startTime() { return m_startTime; } - Q_INVOKABLE qint64 endTime() { return m_endTime; } + Q_INVOKABLE qint64 startTime() const { return m_startTime; } + Q_INVOKABLE qint64 endTime() const { return m_endTime; } + Q_INVOKABLE qint64 duration() const { return m_endTime - m_startTime; } + + Q_INVOKABLE qint64 windowStart() const { return m_windowStart; } + Q_INVOKABLE qint64 windowEnd() const { return m_windowEnd; } + Q_INVOKABLE qint64 windowLength() const { return m_windowEnd - m_windowStart; } + void setWindowLocked(bool lock) { m_windowLocked = lock; } signals: void rangeChanged(); + void windowChanged(); + +private slots: + void rebuildWindow(); + void moveWindow(); private: qint64 m_startTime; qint64 m_endTime; + qint64 m_windowStart; + qint64 m_windowEnd; + + const QmlProfilerTraceTime *m_traceTime; + QTimer m_timer; + bool m_windowLocked; }; class QmlProfilerTraceView : public QWidget @@ -97,6 +118,8 @@ private slots: protected: virtual void resizeEvent(QResizeEvent *event); virtual void contextMenuEvent(QContextMenuEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); private slots: void setZoomSliderEnabled(bool enabled); From cdfc09f16f9da0b2a13d493593eab795a95d487c Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 28 Mar 2014 16:11:16 +0100 Subject: [PATCH 12/13] QmlProfiler: Prevent integer overflows on contentWidth and contentX Using the extra window the ZoomControl keeps makes it impossible to increase contentWidth to a point where it overflows. The drawback is that the position on the scrollbar doesn't reflect the real position of the visible part of the trace anymore if you zoom in to such a depth. Task-number: QTCREATORBUG-11879 Change-Id: I6649f3c139f76c242a91d60364a28a4a00c9acee Reviewed-by: Kai Koehne --- src/plugins/qmlprofiler/qml/MainView.qml | 41 ++++++++++--------- .../qmlprofiler/qml/SelectionRange.qml | 2 +- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/plugins/qmlprofiler/qml/MainView.qml b/src/plugins/qmlprofiler/qml/MainView.qml index c97814e2ed2..3455e262a56 100644 --- a/src/plugins/qmlprofiler/qml/MainView.qml +++ b/src/plugins/qmlprofiler/qml/MainView.qml @@ -70,7 +70,12 @@ Rectangle { mainviewTimePerPixel = Math.abs(endTime - startTime) / root.width; backgroundMarks.updateMarks(startTime, endTime); - view.updateFlickRange(startTime, endTime); + view.startTime = startTime; + view.endTime = endTime; + view.updateWindow(); + } + onWindowChanged: { + view.updateWindow(); } } @@ -250,7 +255,7 @@ Rectangle { onWidthChanged: { var duration = Math.abs(zoomControl.endTime() - zoomControl.startTime()); if (duration > 0) - contentWidth = qmlProfilerModelProxy.traceDuration() * width / duration; + contentWidth = zoomControl.windowLength() * width / duration; } // ***** child items @@ -293,33 +298,29 @@ Rectangle { return; var newStartTime = Math.round(flick.contentX * (endTime - startTime) / flick.width) + - qmlProfilerModelProxy.traceStartTime(); + zoomControl.windowStart(); if (Math.abs(newStartTime - startTime) > 1) { var newEndTime = Math.round((flick.contentX + flick.width) * (endTime - startTime) / - flick.width) + - qmlProfilerModelProxy.traceStartTime(); + flick.width) + zoomControl.windowStart(); zoomControl.setRange(newStartTime, newEndTime); } } - function updateFlickRange(start, end) { - var duration = end - start; - if (recursionGuard || duration <= 0 || (start === startTime && end === endTime)) + function updateWindow() { + var duration = zoomControl.duration(); + if (recursionGuard || duration <= 0) return; recursionGuard = true; - startTime = start; - endTime = end; - if (!flick.flickingHorizontally) { + if (!flick.movingHorizontally) { // This triggers an unwanted automatic change in contentX. We ignore that by // checking recursionGuard in this function and in updateZoomControl. - flick.contentWidth = qmlProfilerModelProxy.traceDuration() * flick.width / - duration; + flick.contentWidth = zoomControl.windowLength() * flick.width / duration; - var newStartX = (startTime - qmlProfilerModelProxy.traceStartTime()) * - flick.width / duration; + var newStartX = (startTime - zoomControl.windowStart()) * flick.width / + duration; if (isFinite(newStartX) && Math.abs(newStartX - flick.contentX) >= 1) flick.contentX = newStartX; @@ -418,7 +419,9 @@ Rectangle { function updateZoomLevel() { zoomSlider.externalUpdate = true; - zoomSlider.value = Math.pow((view.endTime - view.startTime) / qmlProfilerModelProxy.traceDuration(), 1 / zoomSlider.exponent) * zoomSlider.maximumValue; + zoomSlider.value = Math.pow((view.endTime - view.startTime) / + zoomControl.windowLength(), + 1 / zoomSlider.exponent) * zoomSlider.maximumValue; } @@ -434,7 +437,7 @@ Rectangle { property int minWindowLength: 1e5 // 0.1 ms onValueChanged: { - if (externalUpdate || qmlProfilerModelProxy.traceEndTime() <= qmlProfilerModelProxy.traceStartTime()) { + if (externalUpdate || zoomControl.windowEnd() <= zoomControl.windowStart()) { // Zoom range is independently updated. We shouldn't mess // with it here as otherwise we might introduce rounding // or arithmetic errors. @@ -443,7 +446,7 @@ Rectangle { } var windowLength = Math.max( - Math.pow(value / maximumValue, exponent) * qmlProfilerModelProxy.traceDuration(), + Math.pow(value / maximumValue, exponent) * zoomControl.windowLength(), minWindowLength); var fixedPoint = (view.startTime + view.endTime) / 2; @@ -454,7 +457,7 @@ Rectangle { fixedPoint = newFixedPoint; } - var startTime = Math.max(qmlProfilerModelProxy.traceStartTime(), fixedPoint - windowLength / 2) + var startTime = Math.max(zoomControl.windowStart(), fixedPoint - windowLength / 2) zoomControl.setRange(startTime, startTime + windowLength); } } diff --git a/src/plugins/qmlprofiler/qml/SelectionRange.qml b/src/plugins/qmlprofiler/qml/SelectionRange.qml index b54d0d3eeee..7931bdea3a5 100644 --- a/src/plugins/qmlprofiler/qml/SelectionRange.qml +++ b/src/plugins/qmlprofiler/qml/SelectionRange.qml @@ -38,7 +38,7 @@ RangeMover { property string endTimeString: detailedPrintTime(startTime+duration) property string durationString: detailedPrintTime(duration) - property double startTime: getLeft() * viewTimePerPixel + qmlProfilerModelProxy.traceStartTime() + property double startTime: getLeft() * viewTimePerPixel + zoomControl.windowStart() property double duration: Math.max(getWidth() * viewTimePerPixel, 500) property double viewTimePerPixel: 1 property double creationReference : 0 From 248180da15cc969a9525d3c1231c349edda66171 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 2 Apr 2014 15:39:39 +0200 Subject: [PATCH 13/13] Welcome: developer.qtc.io --> qtcloudservices.com Change-Id: I748cb2d6e3b810728e4138f2b0983931233105a5 Reviewed-by: Thomas Hartmann --- share/qtcreator/welcomescreen/widgets/SideBar.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/qtcreator/welcomescreen/widgets/SideBar.qml b/share/qtcreator/welcomescreen/widgets/SideBar.qml index a3abe54fe72..5cb9b5e2a19 100644 --- a/share/qtcreator/welcomescreen/widgets/SideBar.qml +++ b/share/qtcreator/welcomescreen/widgets/SideBar.qml @@ -140,7 +140,7 @@ ColumnLayout { IconAndLink { iconSource: "images/icons/qt_cloud.png" title: qsTr("Qt Cloud Services") - openUrl: "https://developer.qtc.io?utm_source=qtcreator31" + openUrl: "https://developer.qtcloudservices.com?utm_source=qtcreator31" } IconAndLink { iconSource: "images/icons/onlineCommunity.png"