From a76474f5c54e74734b5fbe19fe28f36929205922 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 10 Mar 2017 15:17:40 +0100 Subject: [PATCH 01/56] ProjectExplorer: Evaluate -mfloat-abi for macros The option -mfloat-abi sets macros (in this case __ARM_PCS_VFP), so it should be evaluated while determining the macros for the code model and the clang static analyzer. Task-number: QTCREATORBUG-17797 Change-Id: I22a72d31956521b7e2ad7c1126036b25cfe0898d Reviewed-by: Christian Kandeler Reviewed-by: Tobias Hunger Reviewed-by: Eike Ziller --- src/plugins/projectexplorer/gcctoolchain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index c65e0ce2a40..12337069e40 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -377,6 +377,7 @@ QByteArray GccToolChain::predefinedMacros(const QStringList &cxxflags) const || a == QLatin1String("-m64") || a == QLatin1String("-m96bit-long-double") || a == QLatin1String("-mabm") || a == QLatin1String("-maes") || a.startsWith(QLatin1String("-march=")) || a == QLatin1String("-mavx") + || a.startsWith(QLatin1String("-mfloat-abi")) || a.startsWith(QLatin1String("-masm=")) || a == QLatin1String("-mcx16") || a == QLatin1String("-mfma") || a == QLatin1String("-mfma4") || a == QLatin1String("-mlwp") || a == QLatin1String("-mpclmul") From 8e631c9b26abbb481f92a94af93ebe199700db81 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 8 Mar 2017 17:43:27 +0100 Subject: [PATCH 02/56] make fixnavi actually work with examples we reference examples by title, not by file name (as it's unknowable). Change-Id: I24e2a543138b77e8c6ea60e2aca49ba057c13273 Reviewed-by: Leena Miettinen --- doc/fixnavi.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/fixnavi.pl b/doc/fixnavi.pl index 1ddbd4fe1ba..eb0f16be57b 100755 --- a/doc/fixnavi.pl +++ b/doc/fixnavi.pl @@ -133,7 +133,8 @@ my %next = (); my $last = $doctitle; my $lastpage = $title2page{$last}; for my $title (@toc) { - my $page = $title2page{$title}; + my $type = $title2type{$title}; + my $page = ($type eq "page") ? $title2page{$title} : "{$title}\n"; defined($page) or die "TOC refers to unknown page/example '$title'.\n"; $next{$last} = $page; $prev{$title} = $lastpage; From fed805d56816c3265a94204212f37804b22db614 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 9 Mar 2017 16:17:38 +0100 Subject: [PATCH 03/56] QmlDebugger: Limit recursive property lookups The QML engine will send the number of children in an object as the "value" property together with the ref. We can use that to determine if an object has children without actually fetching it. Also, always save the type of a ref, even if we don't know the value yet. This avoids redundant lookups. Task-number: QTBUG-42435 Change-Id: Ia423b661187dc054fb5782349d1256711ee11265 Reviewed-by: hjk --- src/plugins/debugger/qml/qmlengine.cpp | 126 ++++++++++++++----------- 1 file changed, 73 insertions(+), 53 deletions(-) diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 06471158854..18805d8adb8 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -112,10 +112,16 @@ enum StepAction struct QmlV8ObjectData { int handle = -1; + int expectedProperties = -1; QString name; QString type; QVariant value; QVariantList properties; + + bool hasChildren() const + { + return expectedProperties > 0 || !properties.isEmpty(); + } }; typedef std::function QmlCallback; @@ -1391,7 +1397,7 @@ void QmlEnginePrivate::handleEvaluateExpression(const QVariantMap &response, if (success) { item->type = body.type; item->value = body.value.toString(); - item->wantsChildren = body.properties.count(); + item->setHasChildren(body.hasChildren()); } else { //Do not set type since it is unknown item->setError(body.value.toString()); @@ -1658,55 +1664,69 @@ QmlV8ObjectData QmlEnginePrivate::extractData(const QVariant &data) const objectData.name = dataMap.value(NAME).toString(); + QString type = dataMap.value(TYPE).toString(); + objectData.handle = dataMap.value(HANDLE).toInt(); + + if (type == "undefined") { + objectData.type = "undefined"; + objectData.value = "undefined"; + + } else if (type == "null") { // Deprecated. typeof(null) == "object" in JavaScript + objectData.type = "object"; + objectData.value = "null"; + + } else if (type == "boolean") { + objectData.type = "boolean"; + objectData.value = dataMap.value(VALUE); + + } else if (type == "number") { + objectData.type = "number"; + objectData.value = dataMap.value(VALUE); + + } else if (type == "string") { + QLatin1Char quote('"'); + objectData.type = "string"; + objectData.value = QString(quote + dataMap.value(VALUE).toString() + quote); + + } else if (type == "object") { + objectData.type = "object"; + // ignore "className": it doesn't make any sense. + + if (dataMap.contains("value")) { + QVariant value = dataMap.value("value"); + if (value.isNull()) + objectData.value = "null"; // Yes, null is an object. + else if (value.isValid()) + objectData.expectedProperties = value.toInt(); + } + + if (dataMap.contains("properties")) + objectData.properties = dataMap.value("properties").toList(); + } else if (type == "function") { + objectData.type = "function"; + objectData.value = dataMap.value(NAME); + objectData.properties = dataMap.value("properties").toList(); + QVariant value = dataMap.value("value"); + if (value.isValid()) + objectData.expectedProperties = value.toInt(); + + } else if (type == "script") { + objectData.type = "script"; + objectData.value = dataMap.value(NAME); + } + if (dataMap.contains(REF)) { objectData.handle = dataMap.value(REF).toInt(); if (refVals.contains(objectData.handle)) { QmlV8ObjectData data = refVals.value(objectData.handle); - objectData.type = data.type; - objectData.value = data.value; - objectData.properties = data.properties; - } - } else { - objectData.handle = dataMap.value(HANDLE).toInt(); - QString type = dataMap.value(TYPE).toString(); - - if (type == "undefined") { - objectData.type = "undefined"; - objectData.value = "undefined"; - - } else if (type == "null") { // Deprecated. typeof(null) == "object" in JavaScript - objectData.type = "object"; - objectData.value = "null"; - - } else if (type == "boolean") { - objectData.type = "boolean"; - objectData.value = dataMap.value(VALUE); - - } else if (type == "number") { - objectData.type = "number"; - objectData.value = dataMap.value(VALUE); - - } else if (type == "string") { - QLatin1Char quote('"'); - objectData.type = "string"; - objectData.value = QString(quote + dataMap.value(VALUE).toString() + quote); - - } else if (type == "object") { - objectData.type = "object"; - // ignore "className": it doesn't make any sense. - - if (dataMap.contains("properties")) - objectData.properties = dataMap.value("properties").toList(); - else if (dataMap.value("value").isNull()) - objectData.value = "null"; // Yes, null is an object. - } else if (type == "function") { - objectData.type = "function"; - objectData.value = dataMap.value(NAME); - objectData.properties = dataMap.value("properties").toList(); - - } else if (type == "script") { - objectData.type = "script"; - objectData.value = dataMap.value(NAME); + if (objectData.type.isEmpty()) + objectData.type = data.type; + if (!objectData.value.isValid()) + objectData.value = data.value; + if (objectData.properties.isEmpty()) + objectData.properties = data.properties; + if (objectData.expectedProperties < 0) + objectData.expectedProperties = data.expectedProperties; } } @@ -2216,7 +2236,7 @@ void QmlEnginePrivate::handleFrame(const QVariantMap &response) item->id = objectData.handle; item->type = objectData.type; item->value = objectData.value.toString(); - item->setHasChildren(objectData.properties.count()); + item->setHasChildren(objectData.hasChildren()); // In case of global object, we do not get children // Set children nevertheless and query later. if (item->value == "global") { @@ -2298,11 +2318,11 @@ void QmlEnginePrivate::handleScope(const QVariantMap &response) item->name = item->exp; item->iname = "local." + item->exp; item->id = localData.handle; + item->type = localData.type; + item->value = localData.value.toString(); + item->setHasChildren(localData.hasChildren()); - if (localData.value.isValid()) { - item->type = localData.type; - item->value = localData.value.toString(); - item->setHasChildren(localData.properties.count()); + if (localData.value.isValid() || item->wantsChildren || localData.expectedProperties == 0) { engine->watchHandler()->insertItem(item.release()); } else { itemsToLookup.insert(int(item->id), {item->iname, item->name, item->exp}); @@ -2443,7 +2463,7 @@ void QmlEnginePrivate::insertSubItems(WatchItem *parent, const QVariantList &pro item->value = propertyData.value.toString(); if (item->type.isEmpty() || expandedINames.contains(item->iname)) itemsToLookup.insert(propertyData.handle, {item->iname, item->name, item->exp}); - item->setHasChildren(propertyData.properties.count() > 0); + item->setHasChildren(propertyData.hasChildren()); parent->appendChild(item.release()); } @@ -2499,7 +2519,7 @@ void QmlEnginePrivate::handleLookup(const QVariantMap &response) item->type = bodyObjectData.type; item->value = bodyObjectData.value.toString(); - item->setHasChildren(bodyObjectData.properties.count()); + item->setHasChildren(bodyObjectData.hasChildren()); insertSubItems(item, bodyObjectData.properties); engine->watchHandler()->insertItem(item); From f087f3626913dcd63b9c89e27976a94e7d45240f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 9 Mar 2017 19:12:58 +0100 Subject: [PATCH 04/56] Qml Debugger: Raise sanity level to 1 This signals that we understand packages without extra "handles", that we can deal with only one level of nesting on replies to lookups and expression evaluations, and that we can understand script and function names transmitted as plain strings rather than refs. Change-Id: Iffdd50179b8f9374e2fc8ad3a03cf44fbc627bf1 Task-number: QTBUG-42435 Reviewed-by: hjk --- src/plugins/debugger/qml/qmlengine.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 18805d8adb8..9272cb4860c 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -2535,7 +2535,9 @@ void QmlEnginePrivate::stateChanged(State state) if (state == QmlDebugClient::Enabled) { /// Start session. flushSendBuffer(); - runDirectCommand(CONNECT); + QJsonObject parameters; + parameters.insert("sanity", 1); + runDirectCommand(CONNECT, QJsonDocument(parameters).toJson()); runCommand({VERSION}, CB(handleVersion)); } } From c05222c8e7125288870a0557f03b7d7e31bbfca1 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 13 Mar 2017 14:22:16 +0100 Subject: [PATCH 05/56] CMake: Trim down on headers Change-Id: I9a168dfd6eecbe5a4ba9c5c69d5c99e962708024 Reviewed-by: Tim Jenssen --- .../cmakeprojectmanager/builddirmanager.cpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index a68dd482201..1cce3d8a370 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -24,43 +24,26 @@ ****************************************************************************/ #include "builddirmanager.h" + #include "cmakebuildconfiguration.h" #include "cmakekitinformation.h" -#include "cmakeparser.h" -#include "cmakeprojectconstants.h" -#include "cmakeprojectmanager.h" #include "cmakeprojectnodes.h" #include "cmaketool.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 using namespace ProjectExplorer; From 98505427d319e34bec8658e853fb5000bbf1adaa Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 13 Mar 2017 14:32:12 +0100 Subject: [PATCH 06/56] CMake: forward dirty signal in server-mode This fixes auto-running cmake on changes to the project files. Change-Id: I652b48b243b5decb6927b1619c47527af83d7f03 Reviewed-by: Tim Jenssen --- src/plugins/cmakeprojectmanager/servermodereader.cpp | 9 +++++++++ src/plugins/cmakeprojectmanager/servermodereader.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index ed6daf8e5ec..9f247b483ad 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -95,6 +95,8 @@ void ServerModeReader::setParameters(const BuildDirReader::Parameters &p) this, &ServerModeReader::handleError); connect(m_cmakeServer.get(), &ServerMode::cmakeProgress, this, &ServerModeReader::handleProgress); + connect(m_cmakeServer.get(), &ServerMode::cmakeSignal, + this, &ServerModeReader::handleSignal); connect(m_cmakeServer.get(), &ServerMode::cmakeMessage, this, [this](const QString &m) { Core::MessageManager::write(m); }); connect(m_cmakeServer.get(), &ServerMode::message, @@ -387,6 +389,13 @@ void ServerModeReader::handleProgress(int min, int cur, int max, const QString & m_future->setProgressValue(progress); } +void ServerModeReader::handleSignal(const QString &signal, const QVariantMap &data) +{ + Q_UNUSED(data); + if (signal == "dirty") + emit dirty(); +} + void ServerModeReader::extractCodeModelData(const QVariantMap &data) { const QVariantList configs = data.value("configurations").toList(); diff --git a/src/plugins/cmakeprojectmanager/servermodereader.h b/src/plugins/cmakeprojectmanager/servermodereader.h index 36d75fc2ded..d58103c326e 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.h +++ b/src/plugins/cmakeprojectmanager/servermodereader.h @@ -62,6 +62,7 @@ private: void handleReply(const QVariantMap &data, const QString &inReplyTo); void handleError(const QString &message); void handleProgress(int min, int cur, int max, const QString &inReplyTo); + void handleSignal(const QString &signal, const QVariantMap &data); struct Target; struct Project; From 25087b015356eb17f1c1addab4375e588392fb9f Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Fri, 10 Mar 2017 16:47:39 +0100 Subject: [PATCH 07/56] ModelEditor: Fix various warnings Change-Id: Ibcd95304c2c59dd047481e89ac3162c74b53307b Reviewed-by: Jochen Becher Reviewed-by: Tobias Hunger --- .../qmt/diagram_scene/items/classitem.cpp | 131 ++++++------------ 1 file changed, 42 insertions(+), 89 deletions(-) diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp index 87354577fba..8f6c935417f 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp @@ -565,11 +565,6 @@ void ClassItem::updateMembers(const Style *style) auto dclass = dynamic_cast(object()); QMT_CHECK(dclass); - // TODO move bool haveIconFonts into class Style? - bool haveIconFonts = false; // style->normalFont().family() == QStringLiteral("Modelling"); - // TODO any reason to show visibility as group instead of per member? - bool useGroupVisibility = false; - foreach (const MClassMember &member, dclass->members()) { switch (member.memberType()) { case MClassMember::MemberUndefined: @@ -587,50 +582,14 @@ void ClassItem::updateMembers(const Style *style) break; } - if (!text->isEmpty()) + if (text && !text->isEmpty()) *text += QStringLiteral("
"); bool addNewline = false; bool addSpace = false; - if (member.visibility() != *currentVisibility) { - if (useGroupVisibility) { - if (member.visibility() != MClassMember::VisibilityUndefined) { - QString vis; - switch (member.visibility()) { - case MClassMember::VisibilityUndefined: - break; - case MClassMember::VisibilityPublic: - vis = QStringLiteral("public:"); - break; - case MClassMember::VisibilityProtected: - vis = QStringLiteral("protected:"); - break; - case MClassMember::VisibilityPrivate: - vis = QStringLiteral("private:"); - break; - case MClassMember::VisibilitySignals: - vis = QStringLiteral("signals:"); - break; - case MClassMember::VisibilityPrivateSlots: - vis = QStringLiteral("private slots:"); - break; - case MClassMember::VisibilityProtectedSlots: - vis = QStringLiteral("protected slots:"); - break; - case MClassMember::VisibilityPublicSlots: - vis = QStringLiteral("public slots:"); - break; - } - *text += vis; - addNewline = true; - addSpace = true; - } - } + if (currentVisibility) *currentVisibility = member.visibility(); - } if (member.group() != currentGroup) { - if (addSpace) - *text += QStringLiteral(" "); *text += QString(QStringLiteral("[%1]")).arg(member.group()); addNewline = true; *currentGroup = member.group(); @@ -638,61 +597,55 @@ void ClassItem::updateMembers(const Style *style) if (addNewline) *text += QStringLiteral("
"); - addSpace = false; bool haveSignal = false; bool haveSlot = false; - if (!useGroupVisibility) { - if (member.visibility() != MClassMember::VisibilityUndefined) { - QString vis; - switch (member.visibility()) { - case MClassMember::VisibilityUndefined: - break; - case MClassMember::VisibilityPublic: - vis = haveIconFonts ? QString(QChar(0xe990)) : QStringLiteral("+"); - addSpace = true; - break; - case MClassMember::VisibilityProtected: - vis = haveIconFonts ? QString(QChar(0xe98e)) : QStringLiteral("#"); - addSpace = true; - break; - case MClassMember::VisibilityPrivate: - vis = haveIconFonts ? QString(QChar(0xe98f)) : QStringLiteral("-"); - addSpace = true; - break; - case MClassMember::VisibilitySignals: - vis = haveIconFonts ? QString(QChar(0xe994)) : QStringLiteral(">"); - haveSignal = true; - addSpace = true; - break; - case MClassMember::VisibilityPrivateSlots: - vis = haveIconFonts ? QString(QChar(0xe98f)) + QChar(0xe9cb) - : QStringLiteral("-$"); - haveSlot = true; - addSpace = true; - break; - case MClassMember::VisibilityProtectedSlots: - vis = haveIconFonts ? QString(QChar(0xe98e)) + QChar(0xe9cb) - : QStringLiteral("#$"); - haveSlot = true; - addSpace = true; - break; - case MClassMember::VisibilityPublicSlots: - vis = haveIconFonts ? QString(QChar(0xe990)) + QChar(0xe9cb) - : QStringLiteral("+$"); - haveSlot = true; - addSpace = true; - break; - } - *text += vis; + if (member.visibility() != MClassMember::VisibilityUndefined) { + QString vis; + switch (member.visibility()) { + case MClassMember::VisibilityUndefined: + break; + case MClassMember::VisibilityPublic: + vis = QStringLiteral("+"); + addSpace = true; + break; + case MClassMember::VisibilityProtected: + vis = QStringLiteral("#"); + addSpace = true; + break; + case MClassMember::VisibilityPrivate: + vis = QStringLiteral("-"); + addSpace = true; + break; + case MClassMember::VisibilitySignals: + vis = QStringLiteral(">"); + haveSignal = true; + addSpace = true; + break; + case MClassMember::VisibilityPrivateSlots: + vis = QStringLiteral("-$"); + haveSlot = true; + addSpace = true; + break; + case MClassMember::VisibilityProtectedSlots: + vis = QStringLiteral("#$"); + haveSlot = true; + addSpace = true; + break; + case MClassMember::VisibilityPublicSlots: + vis = QStringLiteral("+$"); + haveSlot = true; + addSpace = true; + break; } + *text += vis; } if (member.properties() & MClassMember::PropertyQsignal && !haveSignal) { - *text += haveIconFonts ? QString(QChar(0xe994)) : QStringLiteral(">"); + *text += QStringLiteral(">"); addSpace = true; } if (member.properties() & MClassMember::PropertyQslot && !haveSlot) { - *text += haveIconFonts ? QString(QChar(0xe9cb)) : QStringLiteral("$"); + *text += QStringLiteral("$"); addSpace = true; } if (addSpace) From bd9824a45c10a77f5c0bc63d55fa0e0f8158506a Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Mon, 13 Mar 2017 18:09:51 +0100 Subject: [PATCH 08/56] Debugger: Comment out quasi dead code Change-Id: I8d7773d911646b05d6343241ae09882b40e861b2 Reviewed-by: hjk --- src/plugins/debugger/breakhandler.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 7a08a568c05..8c104e0dd8f 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -1969,15 +1969,15 @@ bool BreakHandler::contextMenuEvent(const ItemViewEvent &ev) // FIXME BP: m_engine->threadsHandler()->currentThreadId(); - int threadId = 0; - addAction(menu, - threadId == -1 ? tr("Associate Breakpoint with All Threads") - : tr("Associate Breakpoint with Thread %1").arg(threadId), - !selectedItems.isEmpty(), - [this, selectedItems, threadId] { - for (Breakpoint bp : selectedItems) - bp.setThreadSpec(threadId); - }); + // int threadId = 0; + // addAction(menu, + // threadId == -1 ? tr("Associate Breakpoint with All Threads") + // : tr("Associate Breakpoint with Thread %1").arg(threadId), + // !selectedItems.isEmpty(), + // [this, selectedItems, threadId] { + // for (Breakpoint bp : selectedItems) + // bp.setThreadSpec(threadId); + // }); addAction(menu, selectedItems.size() > 1 From e0c6fd334f1a1c5d09203701f3e516678eaf0e1e Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 13 Mar 2017 17:06:45 +0200 Subject: [PATCH 09/56] Gerrit: Remove superfluous title assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's already done in setupUi(). Change-Id: I5f768436f5e374ef252d0ca4086180027e69f75b Reviewed-by: AndrĂ© Hartmann --- src/plugins/git/gerrit/gerritdialog.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/git/gerrit/gerritdialog.cpp b/src/plugins/git/gerrit/gerritdialog.cpp index 87ff53730bb..8ed04952b72 100644 --- a/src/plugins/git/gerrit/gerritdialog.cpp +++ b/src/plugins/git/gerrit/gerritdialog.cpp @@ -69,7 +69,6 @@ GerritDialog::GerritDialog(const QSharedPointer &p, setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); m_ui->setupUi(this); - setWindowTitle(tr("Gerrit")); m_queryModel->setStringList(m_parameters->savedQueries); QCompleter *completer = new QCompleter(this); completer->setModel(m_queryModel); From 4033471aa91ac0cde52786c45c9e95b119197dfc Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 9 Mar 2017 23:02:32 +0100 Subject: [PATCH 10/56] QRegExp include cleanup This patch adds the missing include statements for QRegExp. Change-Id: Ibb03b929940adb84ae190b5090cb6b88653cc14c Reviewed-by: Orgad Shaneh --- src/libs/qmljs/qmljscheck.cpp | 1 + src/libs/qmljs/qmljsdocument.cpp | 1 + src/libs/qmljs/qmljsfindexportedcpptypes.cpp | 1 + src/libs/qmljs/qmljsscopechain.cpp | 2 ++ src/libs/utils/buildablehelperlibrary.cpp | 1 + src/libs/utils/fileutils.cpp | 1 + src/libs/utils/qtcprocess.cpp | 1 + src/libs/utils/templateengine.cpp | 1 + src/plugins/android/androidmanager.cpp | 1 + src/plugins/android/androidrunner.cpp | 1 + src/plugins/android/androidtoolchain.cpp | 1 + src/plugins/android/javaparser.h | 2 ++ src/plugins/autotest/gtest/gtestoutputreader.cpp | 1 + src/plugins/bazaar/bazaarclient.cpp | 1 + .../beautifier/artisticstyle/artisticstylesettings.cpp | 1 + src/plugins/beautifier/beautifierplugin.cpp | 1 + src/plugins/clearcase/clearcasesync.cpp | 1 + src/plugins/cmakeprojectmanager/builddirmanager.cpp | 1 + src/plugins/cmakeprojectmanager/cmakeautocompleter.cpp | 1 + src/plugins/cmakeprojectmanager/cmakebuildstep.h | 2 ++ src/plugins/cmakeprojectmanager/cmakeparser.h | 1 + src/plugins/coreplugin/actionmanager/command.cpp | 1 + src/plugins/coreplugin/find/basetextfind.cpp | 3 ++- src/plugins/coreplugin/locator/basefilefilter.cpp | 1 + src/plugins/coreplugin/locator/opendocumentsfilter.cpp | 1 + src/plugins/coreplugin/toolsettings.cpp | 1 + src/plugins/cppeditor/cppfunctiondecldeflink.cpp | 1 + src/plugins/cpptools/builtinindexingsupport.cpp | 1 + src/plugins/cpptools/cppcurrentdocumentfilter.cpp | 1 + src/plugins/cpptools/cpplocatorfilter.cpp | 1 + src/plugins/diffeditor/differ.cpp | 1 + src/plugins/diffeditor/diffutils.cpp | 1 + src/plugins/genericprojectmanager/genericproject.cpp | 1 + src/plugins/git/githighlighters.h | 2 ++ src/plugins/help/searchwidget.cpp | 1 + src/plugins/nim/project/nimproject.cpp | 1 + src/plugins/projectexplorer/abi.cpp | 1 + src/plugins/projectexplorer/settingsaccessor.cpp | 1 + src/plugins/pythoneditor/pythoneditorplugin.cpp | 1 + .../customwidgetwizard/plugingenerator.cpp | 1 + src/plugins/qmakeprojectmanager/makefileparse.cpp | 1 + .../qmldesigner/components/stateseditor/stateseditorview.cpp | 1 + src/plugins/qmldesigner/designercore/model/abstractview.cpp | 2 ++ src/plugins/qmldesigner/designercore/model/modelnode.cpp | 1 + src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp | 2 ++ src/plugins/qmljstools/qmljsfunctionfilter.cpp | 1 + src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp | 1 + src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp | 1 + src/plugins/qmlprofiler/qmlprofilertraceview.cpp | 1 + src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp | 1 + src/plugins/qmlprojectmanager/fileformat/filefilteritems.h | 1 + src/plugins/qmlprojectmanager/qmlproject.cpp | 1 + src/plugins/qnx/qnxversionnumber.cpp | 1 + src/plugins/qnx/slog2inforunner.cpp | 2 ++ src/plugins/qtsupport/qscxmlcgenerator.cpp | 5 +++-- src/plugins/qtsupport/qtkitinformation.cpp | 2 ++ src/plugins/qtsupport/qtparser.h | 2 ++ src/plugins/subversion/subversioneditor.cpp | 1 + src/plugins/todo/todoitemsprovider.cpp | 1 + src/plugins/vcsbase/vcsoutputwindow.cpp | 1 + src/shared/proparser/ioutils.cpp | 1 + src/shared/proparser/prowriter.cpp | 1 + 62 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index 483b563a043..8b77c8a4a4c 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -33,6 +33,7 @@ #include #include +#include using namespace QmlJS; using namespace QmlJS::AST; diff --git a/src/libs/qmljs/qmljsdocument.cpp b/src/libs/qmljs/qmljsdocument.cpp index 071da4fff92..474a64b1e7d 100644 --- a/src/libs/qmljs/qmljsdocument.cpp +++ b/src/libs/qmljs/qmljsdocument.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include diff --git a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp index e1c4d55de70..7c45339d905 100644 --- a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp +++ b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp @@ -34,6 +34,7 @@ #include #include +#include //using namespace QmlJS; diff --git a/src/libs/qmljs/qmljsscopechain.cpp b/src/libs/qmljs/qmljsscopechain.cpp index a2d3b253efb..cda0b0c6564 100644 --- a/src/libs/qmljs/qmljsscopechain.cpp +++ b/src/libs/qmljs/qmljsscopechain.cpp @@ -29,6 +29,8 @@ #include "qmljsmodelmanagerinterface.h" #include "parser/qmljsengine_p.h" +#include + using namespace QmlJS; /*! diff --git a/src/libs/utils/buildablehelperlibrary.cpp b/src/libs/utils/buildablehelperlibrary.cpp index c46b4b85020..13d3f14f4b7 100644 --- a/src/libs/utils/buildablehelperlibrary.cpp +++ b/src/libs/utils/buildablehelperlibrary.cpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace Utils { diff --git a/src/libs/utils/fileutils.cpp b/src/libs/utils/fileutils.cpp index bf4dc5f6703..606d6e324ed 100644 --- a/src/libs/utils/fileutils.cpp +++ b/src/libs/utils/fileutils.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include diff --git a/src/libs/utils/qtcprocess.cpp b/src/libs/utils/qtcprocess.cpp index 1f302a02d39..1d51a088192 100644 --- a/src/libs/utils/qtcprocess.cpp +++ b/src/libs/utils/qtcprocess.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #ifdef Q_OS_WIN diff --git a/src/libs/utils/templateengine.cpp b/src/libs/utils/templateengine.cpp index b76d42d6314..e78af8bc36a 100644 --- a/src/libs/utils/templateengine.cpp +++ b/src/libs/utils/templateengine.cpp @@ -28,6 +28,7 @@ #include "qtcassert.h" #include +#include #include namespace Utils { diff --git a/src/plugins/android/androidmanager.cpp b/src/plugins/android/androidmanager.cpp index a91a7404aad..dfb96fca021 100644 --- a/src/plugins/android/androidmanager.cpp +++ b/src/plugins/android/androidmanager.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp index 0be297369ef..aa9920908e3 100644 --- a/src/plugins/android/androidrunner.cpp +++ b/src/plugins/android/androidrunner.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index 6794d85d3e1..235dfcd3aab 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include namespace { diff --git a/src/plugins/android/javaparser.h b/src/plugins/android/javaparser.h index 642db44e236..f47075b4e28 100644 --- a/src/plugins/android/javaparser.h +++ b/src/plugins/android/javaparser.h @@ -28,6 +28,8 @@ #include #include +#include + namespace Android { namespace Internal { diff --git a/src/plugins/autotest/gtest/gtestoutputreader.cpp b/src/plugins/autotest/gtest/gtestoutputreader.cpp index 8b581bc4b98..0239e06a321 100644 --- a/src/plugins/autotest/gtest/gtestoutputreader.cpp +++ b/src/plugins/autotest/gtest/gtestoutputreader.cpp @@ -28,6 +28,7 @@ #include #include +#include namespace Autotest { namespace Internal { diff --git a/src/plugins/bazaar/bazaarclient.cpp b/src/plugins/bazaar/bazaarclient.cpp index 991f9947419..4d1ba0d6524 100644 --- a/src/plugins/bazaar/bazaarclient.cpp +++ b/src/plugins/bazaar/bazaarclient.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include diff --git a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp index b0014036791..26129e0f200 100644 --- a/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp +++ b/src/plugins/beautifier/artisticstyle/artisticstylesettings.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include namespace Beautifier { diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp index e58d746964c..b54e3d95420 100644 --- a/src/plugins/beautifier/beautifierplugin.cpp +++ b/src/plugins/beautifier/beautifierplugin.cpp @@ -63,6 +63,7 @@ #include #include #include +#include #include #include diff --git a/src/plugins/clearcase/clearcasesync.cpp b/src/plugins/clearcase/clearcasesync.cpp index cbbacba8109..8f8262ee7c5 100644 --- a/src/plugins/clearcase/clearcasesync.cpp +++ b/src/plugins/clearcase/clearcasesync.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index 3bc0ab684eb..869c84f9e30 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include diff --git a/src/plugins/cmakeprojectmanager/cmakeautocompleter.cpp b/src/plugins/cmakeprojectmanager/cmakeautocompleter.cpp index 2605830d0b5..8c2a0ba0a1d 100644 --- a/src/plugins/cmakeprojectmanager/cmakeautocompleter.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeautocompleter.cpp @@ -25,6 +25,7 @@ #include "cmakeautocompleter.h" +#include #include #include #include diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.h b/src/plugins/cmakeprojectmanager/cmakebuildstep.h index 1fb677e24cb..e7cec2c3b6d 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.h @@ -27,6 +27,8 @@ #include +#include + QT_BEGIN_NAMESPACE class QLineEdit; class QListWidget; diff --git a/src/plugins/cmakeprojectmanager/cmakeparser.h b/src/plugins/cmakeprojectmanager/cmakeparser.h index 877051f276e..d9073165520 100644 --- a/src/plugins/cmakeprojectmanager/cmakeparser.h +++ b/src/plugins/cmakeprojectmanager/cmakeparser.h @@ -28,6 +28,7 @@ #include #include +#include #include namespace CMakeProjectManager { diff --git a/src/plugins/coreplugin/actionmanager/command.cpp b/src/plugins/coreplugin/actionmanager/command.cpp index cdbbe200e3a..186ac4649f1 100644 --- a/src/plugins/coreplugin/actionmanager/command.cpp +++ b/src/plugins/coreplugin/actionmanager/command.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include diff --git a/src/plugins/coreplugin/find/basetextfind.cpp b/src/plugins/coreplugin/find/basetextfind.cpp index a6603e17939..fd40cab904e 100644 --- a/src/plugins/coreplugin/find/basetextfind.cpp +++ b/src/plugins/coreplugin/find/basetextfind.cpp @@ -30,8 +30,9 @@ #include -#include #include +#include +#include #include namespace Core { diff --git a/src/plugins/coreplugin/locator/basefilefilter.cpp b/src/plugins/coreplugin/locator/basefilefilter.cpp index 99dec707bd0..7562a76d766 100644 --- a/src/plugins/coreplugin/locator/basefilefilter.cpp +++ b/src/plugins/coreplugin/locator/basefilefilter.cpp @@ -30,6 +30,7 @@ #include #include +#include #include #include diff --git a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp index f4ed4b8b29b..73c3c2dc40a 100644 --- a/src/plugins/coreplugin/locator/opendocumentsfilter.cpp +++ b/src/plugins/coreplugin/locator/opendocumentsfilter.cpp @@ -32,6 +32,7 @@ #include #include #include +#include using namespace Core; using namespace Core; diff --git a/src/plugins/coreplugin/toolsettings.cpp b/src/plugins/coreplugin/toolsettings.cpp index 764cbfab6f3..a892edbadc3 100644 --- a/src/plugins/coreplugin/toolsettings.cpp +++ b/src/plugins/coreplugin/toolsettings.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp index ce41df99403..dcc842d0bc1 100644 --- a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp +++ b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp @@ -46,6 +46,7 @@ #include #include +#include #include using namespace CPlusPlus; diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp index de9a0c81ca4..b927a10be31 100644 --- a/src/plugins/cpptools/builtinindexingsupport.cpp +++ b/src/plugins/cpptools/builtinindexingsupport.cpp @@ -46,6 +46,7 @@ #include #include #include +#include using namespace CppTools; using namespace CppTools::Internal; diff --git a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp index 588915348cb..964720e7a93 100644 --- a/src/plugins/cpptools/cppcurrentdocumentfilter.cpp +++ b/src/plugins/cpptools/cppcurrentdocumentfilter.cpp @@ -31,6 +31,7 @@ #include #include +#include #include using namespace CppTools::Internal; diff --git a/src/plugins/cpptools/cpplocatorfilter.cpp b/src/plugins/cpptools/cpplocatorfilter.cpp index 6c735582711..e18a1a4c57a 100644 --- a/src/plugins/cpptools/cpplocatorfilter.cpp +++ b/src/plugins/cpptools/cpplocatorfilter.cpp @@ -28,6 +28,7 @@ #include +#include #include #include diff --git a/src/plugins/diffeditor/differ.cpp b/src/plugins/diffeditor/differ.cpp index 97c69f7c5aa..0ff690e2d13 100644 --- a/src/plugins/diffeditor/differ.cpp +++ b/src/plugins/diffeditor/differ.cpp @@ -34,6 +34,7 @@ publication by Neil Fraser: http://neil.fraser.name/writing/diff/ #include "differ.h" #include +#include #include #include #include diff --git a/src/plugins/diffeditor/diffutils.cpp b/src/plugins/diffeditor/diffutils.cpp index d3a186e5c63..1a6a2b729dd 100644 --- a/src/plugins/diffeditor/diffutils.cpp +++ b/src/plugins/diffeditor/diffutils.cpp @@ -25,6 +25,7 @@ #include "diffutils.h" #include "differ.h" +#include #include #include #include "texteditor/fontsettings.h" diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index b2f26bb5c7d..03b3ffc29fa 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -52,6 +52,7 @@ #include #include +#include using namespace Core; using namespace ProjectExplorer; diff --git a/src/plugins/git/githighlighters.h b/src/plugins/git/githighlighters.h index 166c6a7be8b..16325423bf4 100644 --- a/src/plugins/git/githighlighters.h +++ b/src/plugins/git/githighlighters.h @@ -27,6 +27,8 @@ #include +#include + namespace Git { namespace Internal { diff --git a/src/plugins/help/searchwidget.cpp b/src/plugins/help/searchwidget.cpp index 1288673a6ec..27e21a9ff88 100644 --- a/src/plugins/help/searchwidget.cpp +++ b/src/plugins/help/searchwidget.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp index eb0829e7a68..7388626ae53 100644 --- a/src/plugins/nim/project/nimproject.cpp +++ b/src/plugins/nim/project/nimproject.cpp @@ -39,6 +39,7 @@ #include #include +#include #include using namespace ProjectExplorer; diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp index 993bd2fd7b5..8b18128990f 100644 --- a/src/plugins/projectexplorer/abi.cpp +++ b/src/plugins/projectexplorer/abi.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/src/plugins/projectexplorer/settingsaccessor.cpp b/src/plugins/projectexplorer/settingsaccessor.cpp index cb0381ba580..bec38af0095 100644 --- a/src/plugins/projectexplorer/settingsaccessor.cpp +++ b/src/plugins/projectexplorer/settingsaccessor.cpp @@ -43,6 +43,7 @@ #include #include +#include using namespace Utils; diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index 2aab5cf231e..11bf21d95a1 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -60,6 +60,7 @@ #include #include #include +#include using namespace Core; using namespace ProjectExplorer; diff --git a/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.cpp b/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.cpp index 1355dffde7a..f43b4ca73e5 100644 --- a/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.cpp +++ b/src/plugins/qmakeprojectmanager/customwidgetwizard/plugingenerator.cpp @@ -33,6 +33,7 @@ #include #include +#include #include static QString headerGuard(const QString &header) diff --git a/src/plugins/qmakeprojectmanager/makefileparse.cpp b/src/plugins/qmakeprojectmanager/makefileparse.cpp index e0c2e4100c4..aea591e5abd 100644 --- a/src/plugins/qmakeprojectmanager/makefileparse.cpp +++ b/src/plugins/qmakeprojectmanager/makefileparse.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp index 0b6a118e3e2..a4ca2ee78f9 100644 --- a/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp +++ b/src/plugins/qmldesigner/components/stateseditor/stateseditorview.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include diff --git a/src/plugins/qmldesigner/designercore/model/abstractview.cpp b/src/plugins/qmldesigner/designercore/model/abstractview.cpp index 4d9c17c2b83..d07c0191ff0 100644 --- a/src/plugins/qmldesigner/designercore/model/abstractview.cpp +++ b/src/plugins/qmldesigner/designercore/model/abstractview.cpp @@ -34,6 +34,8 @@ #include #include +#include + namespace QmlDesigner { diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp index 5b4da5cbd82..c98277105c2 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp @@ -43,6 +43,7 @@ #include #include +#include #include #include diff --git a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp index 72bfe1a78a5..ea9ea7d63de 100644 --- a/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/qmlobjectnode.cpp @@ -39,6 +39,8 @@ #include #endif +#include + namespace QmlDesigner { void QmlObjectNode::setVariantProperty(const PropertyName &name, const QVariant &value) diff --git a/src/plugins/qmljstools/qmljsfunctionfilter.cpp b/src/plugins/qmljstools/qmljsfunctionfilter.cpp index 88af53a0e50..d7c5979fd77 100644 --- a/src/plugins/qmljstools/qmljsfunctionfilter.cpp +++ b/src/plugins/qmljstools/qmljsfunctionfilter.cpp @@ -29,6 +29,7 @@ #include #include +#include #include using namespace QmlJSTools::Internal; diff --git a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp index 0390d493cd0..9674204ea75 100644 --- a/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerdatamodel.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp index 4c933040e64..7706941c8d4 100644 --- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp +++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp index e50c4d82947..19c8b04005a 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include #include diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp index abdfe4141a0..21863b48d3a 100644 --- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp +++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.cpp @@ -32,6 +32,7 @@ #include #include #include +#include namespace QmlProjectManager { diff --git a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h index aebf3093ba7..3b44d8b06cb 100644 --- a/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h +++ b/src/plugins/qmlprojectmanager/fileformat/filefilteritems.h @@ -28,6 +28,7 @@ #include "qmlprojectitem.h" #include +#include #include #include diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index b8ab17a24df..24b4cae84b7 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -44,6 +44,7 @@ #include #include +#include using namespace Core; using namespace ProjectExplorer; diff --git a/src/plugins/qnx/qnxversionnumber.cpp b/src/plugins/qnx/qnxversionnumber.cpp index 5d4c4ad4135..0dd3e7374bb 100644 --- a/src/plugins/qnx/qnxversionnumber.cpp +++ b/src/plugins/qnx/qnxversionnumber.cpp @@ -26,6 +26,7 @@ #include "qnxversionnumber.h" #include +#include namespace Qnx { namespace Internal { diff --git a/src/plugins/qnx/slog2inforunner.cpp b/src/plugins/qnx/slog2inforunner.cpp index 43ad13beeeb..f88df44f93a 100644 --- a/src/plugins/qnx/slog2inforunner.cpp +++ b/src/plugins/qnx/slog2inforunner.cpp @@ -30,6 +30,8 @@ #include #include +#include + using namespace ProjectExplorer; namespace Qnx { diff --git a/src/plugins/qtsupport/qscxmlcgenerator.cpp b/src/plugins/qtsupport/qscxmlcgenerator.cpp index 423bfc763b1..29b0ffaa63c 100644 --- a/src/plugins/qtsupport/qscxmlcgenerator.cpp +++ b/src/plugins/qtsupport/qscxmlcgenerator.cpp @@ -30,9 +30,10 @@ #include #include -#include -#include #include +#include +#include +#include using namespace ProjectExplorer; diff --git a/src/plugins/qtsupport/qtkitinformation.cpp b/src/plugins/qtsupport/qtkitinformation.cpp index 6589e1496d7..436b9ca22db 100644 --- a/src/plugins/qtsupport/qtkitinformation.cpp +++ b/src/plugins/qtsupport/qtkitinformation.cpp @@ -25,6 +25,8 @@ #include "qtkitinformation.h" +#include + #include "qtkitconfigwidget.h" #include "qtsupportconstants.h" #include "qtversionmanager.h" diff --git a/src/plugins/qtsupport/qtparser.h b/src/plugins/qtsupport/qtparser.h index 91b74a4aaa1..e4263b7b7e6 100644 --- a/src/plugins/qtsupport/qtparser.h +++ b/src/plugins/qtsupport/qtparser.h @@ -25,6 +25,8 @@ #pragma once +#include + #include "qtsupport_global.h" #include diff --git a/src/plugins/subversion/subversioneditor.cpp b/src/plugins/subversion/subversioneditor.cpp index 09074723243..cb48da5daaf 100644 --- a/src/plugins/subversion/subversioneditor.cpp +++ b/src/plugins/subversion/subversioneditor.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include diff --git a/src/plugins/todo/todoitemsprovider.cpp b/src/plugins/todo/todoitemsprovider.cpp index 3bedefac057..ca68e425dd4 100644 --- a/src/plugins/todo/todoitemsprovider.cpp +++ b/src/plugins/todo/todoitemsprovider.cpp @@ -39,6 +39,7 @@ #include #include +#include #include using namespace ProjectExplorer; diff --git a/src/plugins/vcsbase/vcsoutputwindow.cpp b/src/plugins/vcsbase/vcsoutputwindow.cpp index 7a1f99cab60..8787e0ecec2 100644 --- a/src/plugins/vcsbase/vcsoutputwindow.cpp +++ b/src/plugins/vcsbase/vcsoutputwindow.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include diff --git a/src/shared/proparser/ioutils.cpp b/src/shared/proparser/ioutils.cpp index 4239d6ba5c9..97e4c0b8ed4 100644 --- a/src/shared/proparser/ioutils.cpp +++ b/src/shared/proparser/ioutils.cpp @@ -27,6 +27,7 @@ #include #include +#include #ifdef Q_OS_WIN # include diff --git a/src/shared/proparser/prowriter.cpp b/src/shared/proparser/prowriter.cpp index d49c3aa8645..046143c8efb 100644 --- a/src/shared/proparser/prowriter.cpp +++ b/src/shared/proparser/prowriter.cpp @@ -28,6 +28,7 @@ #include "proitems.h" #include +#include #include using namespace QmakeProjectManager::Internal; From 8a071a57bdb133961589daffab16e4538cbbaf8e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 13 Mar 2017 11:11:16 +0100 Subject: [PATCH 11/56] AutoTest: Make some strings translatable Change-Id: I9cbb3051d5b3d63116c086cbdcdb97992202298e Reviewed-by: David Schulz --- src/plugins/autotest/testrunner.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index 16ad6efbfac..2e579e7dfa9 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -166,11 +166,11 @@ static void performTestRun(QFutureInterface &futureInterface, } } else { futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal, - QString("Failed to start test for project \"%1\".").arg(testConfiguration->displayName())))); + TestRunner::tr("Failed to start test for project \"%1\".").arg(testConfiguration->displayName())))); } if (testProcess.exitStatus() == QProcess::CrashExit) { futureInterface.reportResult(TestResultPtr(new FaultyTestResult(Result::MessageFatal, - QString("Test for project \"%1\" crashed.").arg(testConfiguration->displayName())))); + TestRunner::tr("Test for project \"%1\" crashed.").arg(testConfiguration->displayName())))); } if (canceledByTimeout) { From 6f3892bf51eac3a11decb9901d6a82e393a85c58 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 13 Mar 2017 16:31:20 +0200 Subject: [PATCH 12/56] QmlDesigner: Fix tests compilation Change-Id: I08f1abdfb19a04f83e01afd5917ee97e7d61f9cd Reviewed-by: Christian Stenger Reviewed-by: Tim Jenssen --- src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp | 2 ++ .../qmldesigner/designercore/instances/puppetcreator.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp index 212541f0775..ee7de9629d0 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp @@ -398,7 +398,9 @@ QPixmap NodeInstance::blurredRenderPixmap() const void NodeInstance::setRenderPixmap(const QImage &image) { d->renderPixmap = QPixmap::fromImage(image); +#ifndef QMLDESIGNER_TEST d->renderPixmap.setDevicePixelRatio(QmlDesignerPlugin::formEditorDevicePixelRatio()); +#endif d->blurredRenderPixmap = QPixmap(); } diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp index 38fd35a5b02..67a2764215d 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp +++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp @@ -414,7 +414,9 @@ QProcessEnvironment PuppetCreator::processEnvironment() const environment.set(QLatin1String("QT_LABS_CONTROLS_STYLE"), controlsStyle); } +#ifndef QMLDESIGNER_TEST environment.set(QLatin1String("FORMEDITOR_DEVICE_PIXEL_RATIO"), QString::number(QmlDesignerPlugin::formEditorDevicePixelRatio())); +#endif const QString styleConfigFileName = getStyleConfigFileName(); From 37c0176883b270c368f8a8901f95531dc790c0eb Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 10 Mar 2017 13:28:25 +0100 Subject: [PATCH 13/56] QmlDesigner: Fix nodeAtTextCursorPosition() The old implementation assumes that the order of nodes returned by directSubModelNodes() is the order in the QML\ text document. This is not always true if we mix different node properties. If we cannot rely on the sorting the algorithm becomes slow. This fixes selection of delegate items in styles. e.g. Button { text: Text { } some children } The selection of the Text element did not work in all cases before. Change-Id: Icf89bdcab4cb9d2a9fe395d1fbf4e961c09e10e1 Reviewed-by: Tim Jenssen --- .../designercore/model/rewriterview.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp index 08a7d3629fe..2dfe00546fb 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -559,12 +560,24 @@ static bool isInNodeDefinition(int nodeTextOffset, int nodeTextLength, int curso ModelNode RewriterView::nodeAtTextCursorPositionRekursive(const ModelNode &root, int cursorPosition) const { ModelNode node = root; + + int lastOffset = -1; + + bool sorted = true; + + if (!root.nodeProperties().isEmpty()) + sorted = false; + foreach (const ModelNode ¤tNode, node.directSubModelNodes()) { const int offset = nodeOffset(currentNode); - if (offset < cursorPosition) + + if (offset < cursorPosition && offset > lastOffset) { node = nodeAtTextCursorPositionRekursive(currentNode, cursorPosition); - else - break; + lastOffset = offset; + } else { + if (sorted) + break; + } } const int nodeTextLength = nodeLength(node); From a1165291774411a5f2dd864540d638f810267ad5 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Fri, 10 Mar 2017 13:30:46 +0100 Subject: [PATCH 14/56] QmlDesigner: Fix performance regression when selecting The method nodeContainsCursor() is rather slow for huge documents and we do not really have to call it. Checking if the selected node does contain the cursor is enough and can be done in constant time. Since we do this whenever the selection changes this fixes notable slowdown in huge documents. Change-Id: Ie525f0fbcacd6abb72f843f59a793c4f82190a0c Reviewed-by: Tim Jenssen --- .../components/texteditor/texteditorwidget.cpp | 5 +---- .../qmldesigner/designercore/include/rewriterview.h | 1 + .../qmldesigner/designercore/model/rewriterview.cpp | 9 +++++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp index 646b43e47eb..0d89af30e78 100644 --- a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp +++ b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp @@ -121,10 +121,7 @@ void TextEditorWidget::jumpTextCursorToSelectedModelNode() const int nodeOffset = rewriterView->nodeOffset(selectedNode); if (nodeOffset > 0) { - const ModelNode currentSelectedNode = rewriterView-> - nodeAtTextCursorPosition(m_textEditor->editorWidget()->textCursor().position()); - - if (currentSelectedNode != selectedNode) { + if (!rewriterView->nodeContainsCursor(selectedNode, m_textEditor->editorWidget()->textCursor().position())) { int line, column; m_textEditor->editorWidget()->convertPosition(nodeOffset, &line, &column); m_textEditor->editorWidget()->gotoLine(line, column); diff --git a/src/plugins/qmldesigner/designercore/include/rewriterview.h b/src/plugins/qmldesigner/designercore/include/rewriterview.h index 5d5bc8bb282..9d6e29d8fbd 100644 --- a/src/plugins/qmldesigner/designercore/include/rewriterview.h +++ b/src/plugins/qmldesigner/designercore/include/rewriterview.h @@ -130,6 +130,7 @@ public: int firstDefinitionInsideLength(const ModelNode &node) const; bool modificationGroupActive(); ModelNode nodeAtTextCursorPosition(int cursorPosition) const; + bool nodeContainsCursor(const ModelNode &node, int cursorPosition) const; bool renameId(const QString& oldId, const QString& newId); diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp index 2dfe00546fb..7b793716794 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp @@ -593,6 +593,15 @@ ModelNode RewriterView::nodeAtTextCursorPosition(int cursorPosition) const return nodeAtTextCursorPositionRekursive(rootModelNode(), cursorPosition); } +bool RewriterView::nodeContainsCursor(const ModelNode &node, int cursorPosition) const +{ + const int nodeTextLength = nodeLength(node); + const int nodeTextOffset = nodeOffset(node); + + if (isInNodeDefinition(nodeTextOffset, nodeTextLength, cursorPosition)) + return true; +} + bool RewriterView::renameId(const QString& oldId, const QString& newId) { if (textModifier()) { From 30b4955ed7aa1ac3b78e9eb9385c033311b3a620 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 10 Mar 2017 09:05:52 +0100 Subject: [PATCH 15/56] ProjectExplorer: Add a SimpleRunControl implementation Essentially a RunControl with and ApplicationLauncher member like it is used directly or in disguise in the LocalApplicationRunControl, Nim and Python. Extenting that to RemoteLinux/Qnx is possible, but left to the next patch. Change-Id: I91b3199d3d6a418fe4e5be7a5d61689c581a5121 Reviewed-by: Tobias Hunger --- src/plugins/nim/nim.pro | 2 - src/plugins/nim/nim.qbs | 1 - src/plugins/nim/project/nimruncontrol.cpp | 92 -------------- src/plugins/nim/project/nimruncontrol.h | 56 --------- .../nim/project/nimruncontrolfactory.cpp | 3 +- .../localapplicationruncontrol.cpp | 85 +------------ .../projectexplorer/runconfiguration.cpp | 93 +++++++++++++- .../projectexplorer/runconfiguration.h | 22 +++- .../pythoneditor/pythoneditorplugin.cpp | 119 +++--------------- 9 files changed, 130 insertions(+), 343 deletions(-) delete mode 100644 src/plugins/nim/project/nimruncontrol.cpp delete mode 100644 src/plugins/nim/project/nimruncontrol.h diff --git a/src/plugins/nim/nim.pro b/src/plugins/nim/nim.pro index 85e3881e92c..1a27ab50cf0 100644 --- a/src/plugins/nim/nim.pro +++ b/src/plugins/nim/nim.pro @@ -29,7 +29,6 @@ HEADERS += \ project/nimcompilerbuildstepfactory.h \ project/nimcompilercleanstepfactory.h \ project/nimbuildconfigurationwidget.h \ - project/nimruncontrol.h \ project/nimruncontrolfactory.h \ editor/nimeditorfactory.h \ settings/nimcodestylesettingspage.h \ @@ -59,7 +58,6 @@ SOURCES += \ project/nimcompilerbuildstepfactory.cpp \ project/nimcompilercleanstepfactory.cpp \ project/nimbuildconfigurationwidget.cpp \ - project/nimruncontrol.cpp \ project/nimruncontrolfactory.cpp \ editor/nimeditorfactory.cpp \ settings/nimcodestylesettingspage.cpp \ diff --git a/src/plugins/nim/nim.qbs b/src/plugins/nim/nim.qbs index 94ec0a0de4e..d8fb94f0d9a 100644 --- a/src/plugins/nim/nim.qbs +++ b/src/plugins/nim/nim.qbs @@ -49,7 +49,6 @@ QtcPlugin { "nimrunconfiguration.h", "nimrunconfiguration.cpp", "nimrunconfigurationfactory.h", "nimrunconfigurationfactory.cpp", "nimrunconfigurationwidget.h", "nimrunconfigurationwidget.cpp", - "nimruncontrol.h", "nimruncontrol.cpp", "nimruncontrolfactory.h", "nimruncontrolfactory.cpp", "nimtoolchain.h", "nimtoolchain.cpp", "nimtoolchainfactory.h", "nimtoolchainfactory.cpp", diff --git a/src/plugins/nim/project/nimruncontrol.cpp b/src/plugins/nim/project/nimruncontrol.cpp deleted file mode 100644 index 3e5ea4eee56..00000000000 --- a/src/plugins/nim/project/nimruncontrol.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) Filippo Cucchetto -** Contact: http://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 "nimruncontrol.h" -#include "nimrunconfiguration.h" - -#include -#include -#include - -#include - -using namespace ProjectExplorer; -using namespace Utils; - -namespace Nim { - -NimRunControl::NimRunControl(NimRunConfiguration *rc, Core::Id mode) - : RunControl(rc, mode) - , m_runnable(rc->runnable().as()) -{ - connect(&m_applicationLauncher, &ApplicationLauncher::appendMessage, - this, &NimRunControl::slotAppendMessage); - connect(&m_applicationLauncher, &ApplicationLauncher::processStarted, - this, &NimRunControl::processStarted); - connect(&m_applicationLauncher, &ApplicationLauncher::processExited, - this, &NimRunControl::processExited); -} - -void NimRunControl::start() -{ - reportApplicationStart(); - m_applicationLauncher.start(m_runnable); - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - bringApplicationToForeground(); -} - -ProjectExplorer::RunControl::StopResult NimRunControl::stop() -{ - m_applicationLauncher.stop(); - return StoppedSynchronously; -} - -void NimRunControl::processStarted() -{ - // Console processes only know their pid after being started - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); -} - -void NimRunControl::processExited(int exitCode, QProcess::ExitStatus status) -{ - setApplicationProcessHandle(ProcessHandle()); - QString msg; - if (status == QProcess::CrashExit) { - msg = tr("%1 crashed") - .arg(QDir::toNativeSeparators(m_runnable.executable)); - } else { - msg = tr("%1 exited with code %2") - .arg(QDir::toNativeSeparators(m_runnable.executable)).arg(exitCode); - } - appendMessage(msg + QLatin1Char('\n'), NormalMessageFormat); - reportApplicationStop(); -} - -void NimRunControl::slotAppendMessage(const QString &err, OutputFormat format) -{ - appendMessage(err, format); -} - -} diff --git a/src/plugins/nim/project/nimruncontrol.h b/src/plugins/nim/project/nimruncontrol.h deleted file mode 100644 index 0eba08e8cea..00000000000 --- a/src/plugins/nim/project/nimruncontrol.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) Filippo Cucchetto -** Contact: http://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 - -namespace Nim { - -class NimRunConfiguration; - -class NimRunControl : public ProjectExplorer::RunControl -{ - Q_DECLARE_TR_FUNCTIONS(Nim::NimRunControl) - -public: - NimRunControl(NimRunConfiguration *runConfiguration, Core::Id mode); - - void start() override; - StopResult stop() override; - -private: - void processStarted(); - void processExited(int exitCode, QProcess::ExitStatus status); - void slotAppendMessage(const QString &err, Utils::OutputFormat isError); - - ProjectExplorer::ApplicationLauncher m_applicationLauncher; - ProjectExplorer::StandardRunnable m_runnable; -}; - -} diff --git a/src/plugins/nim/project/nimruncontrolfactory.cpp b/src/plugins/nim/project/nimruncontrolfactory.cpp index 3f02586ed7d..170e79f82db 100644 --- a/src/plugins/nim/project/nimruncontrolfactory.cpp +++ b/src/plugins/nim/project/nimruncontrolfactory.cpp @@ -25,7 +25,6 @@ #include "nimruncontrolfactory.h" #include "nimrunconfiguration.h" -#include "nimruncontrol.h" namespace Nim { @@ -39,7 +38,7 @@ ProjectExplorer::RunControl *NimRunControlFactory::create(ProjectExplorer::RunCo { Q_UNUSED(errorMessage) QTC_ASSERT(canRun(runConfiguration, mode), return 0); - return new NimRunControl(static_cast(runConfiguration), mode); + return new ProjectExplorer::SimpleRunControl(runConfiguration, mode); } } diff --git a/src/plugins/projectexplorer/localapplicationruncontrol.cpp b/src/plugins/projectexplorer/localapplicationruncontrol.cpp index 9cd27dc166e..bb13231ae9d 100644 --- a/src/plugins/projectexplorer/localapplicationruncontrol.cpp +++ b/src/plugins/projectexplorer/localapplicationruncontrol.cpp @@ -25,7 +25,6 @@ #include "localapplicationruncontrol.h" #include "runnables.h" -#include "environmentaspect.h" #include #include @@ -34,91 +33,11 @@ #include #include -#include - using namespace Utils; namespace ProjectExplorer { namespace Internal { -class LocalApplicationRunControl : public RunControl -{ - Q_OBJECT - -public: - LocalApplicationRunControl(RunConfiguration *runConfiguration, Core::Id mode); - - void start() override; - StopResult stop() override; - -private: - void processStarted(); - void processExited(int exitCode, QProcess::ExitStatus status); - - ApplicationLauncher m_applicationLauncher; -}; - -LocalApplicationRunControl::LocalApplicationRunControl(RunConfiguration *rc, Core::Id mode) - : RunControl(rc, mode) -{ - setRunnable(rc->runnable()); - setIcon(Utils::Icons::RUN_SMALL_TOOLBAR); - connect(&m_applicationLauncher, &ApplicationLauncher::appendMessage, - this, static_cast(&RunControl::appendMessage)); - connect(&m_applicationLauncher, &ApplicationLauncher::processStarted, - this, &LocalApplicationRunControl::processStarted); - connect(&m_applicationLauncher, &ApplicationLauncher::processExited, - this, &LocalApplicationRunControl::processExited); -} - -void LocalApplicationRunControl::start() -{ - QTC_ASSERT(runnable().is(), return); - auto r = runnable().as(); - reportApplicationStart(); - if (r.executable.isEmpty()) { - appendMessage(tr("No executable specified.") + QLatin1Char('\n'), Utils::ErrorMessageFormat); - reportApplicationStop(); - } else if (!QFileInfo::exists(r.executable)) { - appendMessage(tr("Executable %1 does not exist.") - .arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n'), - Utils::ErrorMessageFormat); - reportApplicationStop(); - } else { - QString msg = tr("Starting %1...").arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n'); - appendMessage(msg, Utils::NormalMessageFormat); - m_applicationLauncher.start(r); - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - } -} - -LocalApplicationRunControl::StopResult LocalApplicationRunControl::stop() -{ - m_applicationLauncher.stop(); - return StoppedSynchronously; -} - -void LocalApplicationRunControl::processStarted() -{ - // Console processes only know their pid after being started - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - bringApplicationToForeground(); -} - -void LocalApplicationRunControl::processExited(int exitCode, QProcess::ExitStatus status) -{ - QString msg; - QString exe = runnable().as().executable; - if (status == QProcess::CrashExit) - msg = tr("%1 crashed.").arg(QDir::toNativeSeparators(exe)); - else - msg = tr("%1 exited with code %2").arg(QDir::toNativeSeparators(exe)).arg(exitCode); - appendMessage(msg + QLatin1Char('\n'), Utils::NormalMessageFormat); - reportApplicationStop(); -} - -// LocalApplicationRunControlFactory - static bool isLocal(RunConfiguration *runConfiguration) { Target *target = runConfiguration ? runConfiguration->target() : nullptr; @@ -142,10 +61,8 @@ bool LocalApplicationRunControlFactory::canRun(RunConfiguration *runConfiguratio RunControl *LocalApplicationRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage) { Q_UNUSED(errorMessage) - return new LocalApplicationRunControl(runConfiguration, mode); + return new SimpleRunControl(runConfiguration, mode); } } // namespace Internal } // namespace ProjectExplorer - -#include "localapplicationruncontrol.moc" diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 9ad838d3ca4..5f3e99c0c5d 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -32,18 +32,22 @@ #include "buildconfiguration.h" #include "environmentaspect.h" #include "kitinformation.h" +#include "runnables.h" + #include #include -#include #include +#include #include +#include #include #include -#include +#include #include +#include #ifdef Q_OS_OSX #include @@ -785,4 +789,89 @@ bool Runnable::canReUseOutputPane(const Runnable &other) const return d ? d->canReUseOutputPane(other.d) : (other.d.get() == 0); } + +// SimpleRunControlPrivate + +namespace Internal { + +class SimpleRunControlPrivate +{ +public: + ApplicationLauncher m_launcher; +}; + +} // Internal + +SimpleRunControl::SimpleRunControl(RunConfiguration *runConfiguration, Core::Id mode) + : RunControl(runConfiguration, mode), d(new Internal::SimpleRunControlPrivate) +{ + setRunnable(runConfiguration->runnable()); + setIcon(Utils::Icons::RUN_SMALL_TOOLBAR); +} + +SimpleRunControl::~SimpleRunControl() +{ + delete d; +} + +ApplicationLauncher &SimpleRunControl::applicationLauncher() +{ + return d->m_launcher; +} + +void SimpleRunControl::start() +{ + reportApplicationStart(); + d->m_launcher.disconnect(this); + + connect(&d->m_launcher, &ApplicationLauncher::appendMessage, + this, static_cast(&RunControl::appendMessage)); + connect(&d->m_launcher, &ApplicationLauncher::processStarted, + this, &SimpleRunControl::onProcessStarted); + connect(&d->m_launcher, &ApplicationLauncher::processExited, + this, &SimpleRunControl::onProcessFinished); + + QTC_ASSERT(runnable().is(), return); + auto r = runnable().as(); + if (r.executable.isEmpty()) { + appendMessage(RunControl::tr("No executable specified.") + QLatin1Char('\n'), Utils::ErrorMessageFormat); + reportApplicationStop(); + } else if (!QFileInfo::exists(r.executable)) { + appendMessage(RunControl::tr("Executable %1 does not exist.") + .arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n'), + Utils::ErrorMessageFormat); + reportApplicationStop(); + } else { + QString msg = RunControl::tr("Starting %1...").arg(QDir::toNativeSeparators(r.executable)) + QLatin1Char('\n'); + appendMessage(msg, Utils::NormalMessageFormat); + d->m_launcher.start(r); + setApplicationProcessHandle(d->m_launcher.applicationPID()); + } +} + +RunControl::StopResult SimpleRunControl::stop() +{ + d->m_launcher.stop(); + return StoppedSynchronously; +} + +void SimpleRunControl::onProcessStarted() +{ + // Console processes only know their pid after being started + setApplicationProcessHandle(d->m_launcher.applicationPID()); + bringApplicationToForeground(); +} + +void SimpleRunControl::onProcessFinished(int exitCode, QProcess::ExitStatus status) +{ + QString msg; + QString exe = runnable().as().executable; + if (status == QProcess::CrashExit) + msg = tr("%1 crashed.").arg(QDir::toNativeSeparators(exe)); + else + msg = tr("%1 exited with code %2").arg(QDir::toNativeSeparators(exe)).arg(exitCode); + appendMessage(msg + QLatin1Char('\n'), Utils::NormalMessageFormat); + reportApplicationStop(); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 753b3bf494f..e6ad09513e8 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -51,7 +51,10 @@ class RunConfigWidget; class RunControl; class Target; -namespace Internal { class RunControlPrivate; } +namespace Internal { +class RunControlPrivate; +class SimpleRunControlPrivate; +} // Internal /** * An interface for a hunk of global or per-project @@ -414,4 +417,21 @@ private: Internal::RunControlPrivate *d; }; +class PROJECTEXPLORER_EXPORT SimpleRunControl : public RunControl +{ +public: + SimpleRunControl(RunConfiguration *runConfiguration, Core::Id mode); + ~SimpleRunControl(); + + ApplicationLauncher &applicationLauncher(); + void start() override; + StopResult stop() override; + + virtual void onProcessStarted(); + virtual void onProcessFinished(int exitCode, QProcess::ExitStatus status); + +private: + Internal::SimpleRunControlPrivate *d; +}; + } // namespace ProjectExplorer diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index da63b5232ac..f926c13ecd1 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -197,6 +197,7 @@ public: bool fromMap(const QVariantMap &map) override; bool isEnabled() const override { return m_enabled; } QString disabledReason() const override; + Runnable runnable() const override; bool supportsDebugger() const { return true; } QString mainScript() const { return m_mainScript; } @@ -215,28 +216,6 @@ private: bool m_enabled; }; -class PythonRunControl : public RunControl -{ - Q_OBJECT -public: - PythonRunControl(PythonRunConfiguration *runConfiguration, Core::Id mode); - - void start() override; - StopResult stop() override; - -private: - void processStarted(); - void processExited(int exitCode, QProcess::ExitStatus status); - void slotAppendMessage(const QString &err, Utils::OutputFormat isError); - - ApplicationLauncher m_applicationLauncher; - QString m_interpreter; - QString m_mainScript; - QString m_commandLineArguments; - Utils::Environment m_environment; - ApplicationLauncher::Mode m_runMode; -}; - //////////////////////////////////////////////////////////////// PythonRunConfiguration::PythonRunConfiguration(Target *parent, Core::Id id) : @@ -307,6 +286,17 @@ QString PythonRunConfiguration::disabledReason() const return QString(); } +Runnable PythonRunConfiguration::runnable() const +{ + StandardRunnable r; + QtcProcess::addArg(&r.commandLineArguments, m_mainScript); + QtcProcess::addArgs(&r.commandLineArguments, extraAspect()->arguments()); + r.executable = m_interpreter; + r.runMode = extraAspect()->runMode(); + r.environment = extraAspect()->environment(); + return r; +} + QString PythonRunConfiguration::arguments() const { auto aspect = extraAspect(); @@ -732,95 +722,18 @@ public: bool PythonRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id mode) const { - return mode == ProjectExplorer::Constants::NORMAL_RUN_MODE - && dynamic_cast(runConfiguration); + auto rc = dynamic_cast(runConfiguration); + return mode == ProjectExplorer::Constants::NORMAL_RUN_MODE && rc && !rc->interpreter().isEmpty(); } RunControl *PythonRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage) { Q_UNUSED(errorMessage) QTC_ASSERT(canRun(runConfiguration, mode), return 0); - return new PythonRunControl(static_cast(runConfiguration), mode); + return new SimpleRunControl(runConfiguration, mode); } -// PythonRunControl - -PythonRunControl::PythonRunControl(PythonRunConfiguration *rc, Core::Id mode) - : RunControl(rc, mode) -{ - setIcon(Utils::Icons::RUN_SMALL_TOOLBAR); - - m_interpreter = rc->interpreter(); - m_mainScript = rc->mainScript(); - m_runMode = rc->extraAspect()->runMode(); - m_commandLineArguments = rc->extraAspect()->arguments(); - m_environment = rc->extraAspect()->environment(); - - connect(&m_applicationLauncher, &ApplicationLauncher::appendMessage, - this, &PythonRunControl::slotAppendMessage); - connect(&m_applicationLauncher, &ApplicationLauncher::processStarted, - this, &PythonRunControl::processStarted); - connect(&m_applicationLauncher, &ApplicationLauncher::processExited, - this, &PythonRunControl::processExited); -} - -void PythonRunControl::start() -{ - reportApplicationStart(); - if (m_interpreter.isEmpty()) { - appendMessage(tr("No Python interpreter specified.") + '\n', Utils::ErrorMessageFormat); - reportApplicationStop(); - } else if (!QFileInfo::exists(m_interpreter)) { - appendMessage(tr("Python interpreter %1 does not exist.").arg(QDir::toNativeSeparators(m_interpreter)) + '\n', - Utils::ErrorMessageFormat); - reportApplicationStop(); - } else { - QString msg = tr("Starting %1...").arg(QDir::toNativeSeparators(m_interpreter)) + '\n'; - appendMessage(msg, Utils::NormalMessageFormat); - - StandardRunnable r; - QtcProcess::addArg(&r.commandLineArguments, m_mainScript); - QtcProcess::addArgs(&r.commandLineArguments, m_commandLineArguments); - r.executable = m_interpreter; - r.runMode = m_runMode; - r.environment = m_environment; - m_applicationLauncher.start(r); - - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - } -} - -PythonRunControl::StopResult PythonRunControl::stop() -{ - m_applicationLauncher.stop(); - return StoppedSynchronously; -} - -void PythonRunControl::slotAppendMessage(const QString &err, Utils::OutputFormat format) -{ - appendMessage(err, format); -} - -void PythonRunControl::processStarted() -{ - // Console processes only know their pid after being started - setApplicationProcessHandle(m_applicationLauncher.applicationPID()); - bringApplicationToForeground(); -} - -void PythonRunControl::processExited(int exitCode, QProcess::ExitStatus status) -{ - QString msg; - if (status == QProcess::CrashExit) { - msg = tr("%1 crashed") - .arg(QDir::toNativeSeparators(m_interpreter)); - } else { - msg = tr("%1 exited with code %2") - .arg(QDir::toNativeSeparators(m_interpreter)).arg(exitCode); - } - appendMessage(msg + '\n', Utils::NormalMessageFormat); - reportApplicationStop(); -} +// PythonRunConfigurationWidget void PythonRunConfigurationWidget::setInterpreter(const QString &interpreter) { From 116c92ba8dcfa84b32ae86c91a75ff1d3419ef39 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 14 Mar 2017 11:50:00 +0100 Subject: [PATCH 16/56] QmlDesigner: Fix warning Change-Id: I77f2963957ec0679485e5582b79edd13a57beee9 Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/designercore/model/rewriterview.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp index 7b793716794..4c58b573f48 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp @@ -600,6 +600,8 @@ bool RewriterView::nodeContainsCursor(const ModelNode &node, int cursorPosition) if (isInNodeDefinition(nodeTextOffset, nodeTextLength, cursorPosition)) return true; + + return false; } bool RewriterView::renameId(const QString& oldId, const QString& newId) From 7428aa9cec41823cd77f58a5dc8c0b4d7b530811 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 14 Mar 2017 12:44:42 +0100 Subject: [PATCH 17/56] QmlDesigner: fix linking the tests Change-Id: I8cf37aa48c05c0c67dc0c31373e8365584fb106c Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp index ee7de9629d0..6589ceb8756 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstance.cpp @@ -26,7 +26,9 @@ #include "nodeinstance.h" #include +#ifndef QMLDESIGNER_TEST #include +#endif #include #include From 4d8352a6c177ecfc609d6bc7fefbfcd00204b0f6 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 10 Mar 2017 17:30:40 +0100 Subject: [PATCH 18/56] ProjectExplorer: Add a FolderNode::addNestedNode() function Also, rename buildTree() to addNestedNodes(), it's really adding things, not recompletely (re-)building the subtree. Use it whenever possible to avoid intermediate lists of items to insert. Change-Id: I5fde41e5b164a8a292410bd381a85f5efadf3471 Reviewed-by: Tobias Hunger --- .../autotoolsproject.cpp | 14 ++++----- .../cmakeprojectmanager/servermodereader.cpp | 2 +- .../cmakeprojectmanager/tealeafreader.cpp | 2 +- .../genericprojectmanager/genericproject.cpp | 29 +++++++++---------- src/plugins/nim/project/nimproject.cpp | 2 +- src/plugins/projectexplorer/projectnodes.cpp | 22 ++++++++------ src/plugins/projectexplorer/projectnodes.h | 3 +- .../pythoneditor/pythoneditorplugin.cpp | 11 +++---- .../qmakenodetreebuilder.cpp | 6 ++-- src/plugins/qmlprojectmanager/qmlproject.cpp | 10 +++---- 10 files changed, 46 insertions(+), 55 deletions(-) diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp index a01fe2c518d..296142ec5a4 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp @@ -215,16 +215,12 @@ void AutotoolsProject::makefileParsingFinished() m_watchedFiles.append(configureAcFilePath); } - QList fileNodes = Utils::transform(files, [dir](const QString &f) { - const Utils::FileName path = Utils::FileName::fromString(dir.absoluteFilePath(f)); - return new FileNode(path, - (f == QLatin1String("Makefile.am") || - f == QLatin1String("configure.ac")) ? FileType::Project : FileType::Resource, - false); - }); - auto newRoot = new AutotoolsProjectNode(projectDirectory()); - newRoot->buildTree(fileNodes); + for (const QString &f : files) { + const Utils::FileName path = Utils::FileName::fromString(dir.absoluteFilePath(f)); + FileType ft = (f == "Makefile.am" || f == "configure.ac") ? FileType::Project : FileType::Resource; + newRoot->addNestedNode(new FileNode(path, ft, false)); + } setRootProjectNode(newRoot); updateCppCodeModel(); diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index 9f247b483ad..bcc809e295f 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -226,7 +226,7 @@ static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, i auto folder = new VirtualFolderNode(basePath, priority); folder->setDisplayName(displayName); base->addNode(folder); - folder->buildTree(files); + folder->addNestedNodes(files); for (FolderNode *fn : folder->folderNodes()) fn->compress(); } diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index 170a7fa2529..e7f7a20b09f 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -311,7 +311,7 @@ void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList fileNodes = m_files + Utils::transform(missingHeaders, [](const FileNode *fn) { return new FileNode(*fn); }); - root->buildTree(fileNodes, m_parameters.sourceDirectory); + root->addNestedNodes(fileNodes, m_parameters.sourceDirectory); m_files.clear(); // Some of the FileNodes in files() were deleted! } diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index 08b4fdf5adb..c8b14a125d5 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -259,28 +259,25 @@ void GenericProject::refresh(RefreshOptions options) parseProject(options); if (options & Files) { - QList fileNodes = Utils::transform(files(), [](const QString &f) { + auto newRoot = new GenericProjectNode(this); + + for (const QString &f : files()) { FileType fileType = FileType::Source; // ### FIXME if (f.endsWith(".qrc")) fileType = FileType::Resource; - return new FileNode(Utils::FileName::fromString(f), fileType, false); - }); + newRoot->addNestedNode(new FileNode(Utils::FileName::fromString(f), fileType, false)); + } - auto projectFilesNode = new FileNode(Utils::FileName::fromString(m_filesFileName), + newRoot->addNestedNode(new FileNode(Utils::FileName::fromString(m_filesFileName), FileType::Project, - /* generated = */ false); + /* generated = */ false)); + newRoot->addNestedNode(new FileNode(Utils::FileName::fromString(m_includesFileName), + FileType::Project, + /* generated = */ false)); + newRoot->addNestedNode(new FileNode(Utils::FileName::fromString(m_configFileName), + FileType::Project, + /* generated = */ false)); - auto projectIncludesNode = new FileNode(Utils::FileName::fromString(m_includesFileName), - FileType::Project, - /* generated = */ false); - - auto projectConfigNode = new FileNode(Utils::FileName::fromString(m_configFileName), - FileType::Project, - /* generated = */ false); - fileNodes << projectFilesNode << projectIncludesNode << projectConfigNode; - - auto newRoot = new GenericProjectNode(this); - newRoot->buildTree(fileNodes); setRootProjectNode(newRoot); } diff --git a/src/plugins/nim/project/nimproject.cpp b/src/plugins/nim/project/nimproject.cpp index 2b6b297adb7..a73daf10955 100644 --- a/src/plugins/nim/project/nimproject.cpp +++ b/src/plugins/nim/project/nimproject.cpp @@ -156,7 +156,7 @@ void NimProject::updateProject() auto newRoot = new NimProjectNode(*this, projectDirectory()); newRoot->setDisplayName(displayName()); - newRoot->buildTree(fileNodes); + newRoot->addNestedNodes(fileNodes); setRootProjectNode(newRoot); emit fileListChanged(); diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 87a759efea1..604d73cb16a 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -468,16 +468,20 @@ QList FolderNode::folderNodes() const return result; } -void FolderNode::buildTree(QList &files, const Utils::FileName &overrideBaseDir) +void FolderNode::addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir) { - foreach (ProjectExplorer::FileNode *fn, files) { - // Get relative path to rootNode - QString parentDir = fn->filePath().toFileInfo().absolutePath(); - ProjectExplorer::FolderNode *folder - = recursiveFindOrCreateFolderNode(this, Utils::FileName::fromString(parentDir), - overrideBaseDir); - folder->addNode(fn); - } + // Get relative path to rootNode + QString parentDir = fileNode->filePath().toFileInfo().absolutePath(); + FolderNode *folder = recursiveFindOrCreateFolderNode(this, Utils::FileName::fromString(parentDir), + overrideBaseDir); + folder->addNode(fileNode); + +} + +void FolderNode::addNestedNodes(QList &files, const Utils::FileName &overrideBaseDir) +{ + for (FileNode *fn : files) + addNestedNode(fn, overrideBaseDir); } // "Compress" a tree of foldernodes such that foldernodes with exactly one foldernode as a child diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index 3785d2265d8..e740c3c5e7a 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -201,7 +201,8 @@ public: FileNode *fileNode(const Utils::FileName &file) const; QList recursiveFileNodes() const; QList folderNodes() const; - void buildTree(QList &files, const Utils::FileName &overrideBaseDir = Utils::FileName()); + void addNestedNodes(QList &files, const Utils::FileName &overrideBaseDir = Utils::FileName()); + void addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir = Utils::FileName()); void compress(); bool isAncesterOf(Node *n); diff --git a/src/plugins/pythoneditor/pythoneditorplugin.cpp b/src/plugins/pythoneditor/pythoneditorplugin.cpp index f926c13ecd1..2a7e4784564 100644 --- a/src/plugins/pythoneditor/pythoneditorplugin.cpp +++ b/src/plugins/pythoneditor/pythoneditorplugin.cpp @@ -556,14 +556,11 @@ void PythonProject::refresh() parseProject(); QDir baseDir(projectDirectory().toString()); - - QList fileNodes - = Utils::transform(m_files, [baseDir](const QString &f) -> FileNode * { - const QString displayName = baseDir.relativeFilePath(f); - return new PythonFileNode(FileName::fromString(f), displayName); - }); auto newRoot = new PythonProjectNode(this); - newRoot->buildTree(fileNodes); + for (const QString &f : m_files) { + const QString displayName = baseDir.relativeFilePath(f); + newRoot->addNestedNode(new PythonFileNode(FileName::fromString(f), displayName)); + } setRootProjectNode(newRoot); emit parsingFinished(); diff --git a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp index bed5cfc44b4..2bc3b23682f 100644 --- a/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp +++ b/src/plugins/qmakeprojectmanager/qmakenodetreebuilder.cpp @@ -172,10 +172,8 @@ static void createTree(const QmakePriFile *pri, QmakePriFileNode *node) vfolder->addNode(resourceNode); } } else { - QList fileNodes = Utils::transform(newFilePaths, [type](const FileName &fn) { - return new FileNode(fn, type, false); - }); - vfolder->buildTree(fileNodes); + for (const FileName &fn : newFilePaths) + vfolder->addNestedNode(new FileNode(fn, type, false)); for (FolderNode *fn : vfolder->folderNodes()) fn->compress(); } diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 45d791b4ff5..22a69da34b0 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -384,17 +384,15 @@ Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *erro void QmlProject::generateProjectTree() { - QStringList allFiles = files(); + auto newRoot = new Internal::QmlProjectNode(this); - QList fileNodes = Utils::transform(allFiles, [this](const QString &f) { + for (const QString &f : files()) { FileType fileType = FileType::Source; // ### FIXME if (f == projectFilePath().toString()) fileType = FileType::Project; - return new FileNode(Utils::FileName::fromString(f), fileType, false); - }); + newRoot->addNestedNode(new FileNode(Utils::FileName::fromString(f), fileType, false)); + } - auto newRoot = new Internal::QmlProjectNode(this); - newRoot->buildTree(fileNodes); setRootProjectNode(newRoot); } From a6a271881f77b3de36ac897776e2a4ac00228552 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 10 Mar 2017 18:08:03 +0100 Subject: [PATCH 19/56] ProjectExplorer: Inline FolderNode::recursiveFileNodes() ... into its only remaining user. Change-Id: I5efa716ce34ba6a237dfcbcfebb257c863fdd21d Reviewed-by: Tobias Hunger --- .../cmakeprojectmanager/cmakeproject.cpp | 20 +++++++------------ src/plugins/projectexplorer/projectnodes.cpp | 8 -------- src/plugins/projectexplorer/projectnodes.h | 1 - 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 1ecc0c6e5ee..9339591c939 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -309,21 +309,15 @@ QString CMakeProject::displayName() const QStringList CMakeProject::files(FilesMode fileMode) const { - const QList nodes = filtered(rootProjectNode()->recursiveFileNodes(), - [fileMode](const FileNode *fn) { + QStringList result; + rootProjectNode()->forEachNode([&](const FileNode *fn) { const bool isGenerated = fn->isGenerated(); - switch (fileMode) - { - case Project::SourceFiles: - return !isGenerated; - case Project::GeneratedFiles: - return isGenerated; - case Project::AllFiles: - default: - return true; - } + if (fileMode == Project::SourceFiles && !isGenerated) + result.append(fn->filePath().toString()); + if (fileMode == Project::GeneratedFiles && isGenerated) + result.append(fn->filePath().toString()); }); - return transform(nodes, [fileMode](const FileNode* fn) { return fn->filePath().toString(); }); + return result; } Project::RestoreResult CMakeProject::fromMap(const QVariantMap &map, QString *errorMessage) diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 604d73cb16a..8067795304f 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -450,14 +450,6 @@ FileNode *FolderNode::fileNode(const Utils::FileName &file) const })); } -QList FolderNode::recursiveFileNodes() const -{ - QList result = fileNodes(); - foreach (ProjectExplorer::FolderNode *folder, folderNodes()) - result.append(folder->recursiveFileNodes()); - return result; -} - QList FolderNode::folderNodes() const { QList result; diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index e740c3c5e7a..aa5b9e397f2 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -199,7 +199,6 @@ public: const QList nodes() const { return m_nodes; } QList fileNodes() const; FileNode *fileNode(const Utils::FileName &file) const; - QList recursiveFileNodes() const; QList folderNodes() const; void addNestedNodes(QList &files, const Utils::FileName &overrideBaseDir = Utils::FileName()); void addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir = Utils::FileName()); From c1d013437fb1cf10d73bb77f0b6dc658f286bd4f Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 13 Mar 2017 00:18:50 +0200 Subject: [PATCH 20/56] Gerrit: Persist server details MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid repeating connection tests for the same server between runs. Change-Id: Iecea52af986a708f317878c171d4fcea088cbbde Reviewed-by: AndrĂ© Hartmann Reviewed-by: Tobias Hunger --- src/plugins/git/gerrit/gerritserver.cpp | 73 ++++++++++++++++++++++--- src/plugins/git/gerrit/gerritserver.h | 9 +++ 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/src/plugins/git/gerrit/gerritserver.cpp b/src/plugins/git/gerrit/gerritserver.cpp index ea80e8d6e2b..babe4fd0f47 100644 --- a/src/plugins/git/gerrit/gerritserver.cpp +++ b/src/plugins/git/gerrit/gerritserver.cpp @@ -29,12 +29,14 @@ #include "../gitplugin.h" #include "../gitclient.h" +#include #include #include #include #include #include +#include using namespace Utils; using namespace Git::Internal; @@ -44,6 +46,11 @@ namespace Internal { static const char defaultHostC[] = "codereview.qt-project.org"; static const char accountUrlC[] = "/accounts/self"; +static const char isGerritKey[] = "IsGerrit"; +static const char rootPathKey[] = "RootPath"; +static const char userNameKey[] = "UserName"; +static const char fullNameKey[] = "FullName"; +static const char isAuthenticatedKey[] = "IsAuthenticated"; bool GerritUser::isSameAs(const GerritUser &other) const { @@ -136,12 +143,60 @@ bool GerritServer::fillFromRemote(const QString &remote, const GerritParameters curlBinary = parameters.curl; if (curlBinary.isEmpty() || !QFile::exists(curlBinary)) return false; - rootPath = r.path; - // Strip the last part of the path, which is always the repo name - // The rest of the path needs to be inspected to find the root path - // (can be http://example.net/review) - ascendPath(); - return resolveRoot(); + switch (loadSettings()) { + case Invalid: + rootPath = r.path; + // Strip the last part of the path, which is always the repo name + // The rest of the path needs to be inspected to find the root path + // (can be http://example.net/review) + ascendPath(); + return resolveRoot(); + case NotGerrit: + return false; + case Valid: + return true; + } + return true; +} + +GerritServer::StoredHostValidity GerritServer::loadSettings() +{ + StoredHostValidity validity = Invalid; + QSettings *settings = Core::ICore::settings(); + settings->beginGroup("Gerrit/" + host); + if (!settings->value(isGerritKey, true).toBool()) { + validity = NotGerrit; + } else if (settings->contains(isAuthenticatedKey)) { + rootPath = settings->value(rootPathKey).toString(); + user.userName = settings->value(userNameKey).toString(); + user.fullName = settings->value(fullNameKey).toString(); + authenticated = settings->value(isAuthenticatedKey).toBool(); + validity = Valid; + } + settings->endGroup(); + return validity; +} + +void GerritServer::saveSettings(StoredHostValidity validity) const +{ + QSettings *settings = Core::ICore::settings(); + settings->beginGroup("Gerrit/" + host); + switch (validity) { + case NotGerrit: + settings->setValue(isGerritKey, false); + break; + case Valid: + settings->setValue(rootPathKey, rootPath); + settings->setValue(userNameKey, user.userName); + settings->setValue(fullNameKey, user.fullName); + settings->setValue(isAuthenticatedKey, authenticated); + break; + case Invalid: + settings->clear(); + break; + } + + settings->endGroup(); } QStringList GerritServer::curlArguments() @@ -182,6 +237,7 @@ bool GerritServer::setupAuthentication() if (!dialog.exec()) return false; authenticated = dialog.isAuthenticated(); + saveSettings(Valid); return true; } @@ -199,12 +255,15 @@ bool GerritServer::resolveRoot() for (;;) { switch (testConnection()) { case 200: + saveSettings(Valid); return true; case 401: return setupAuthentication(); case 404: - if (!ascendPath()) + if (!ascendPath()) { + saveSettings(NotGerrit); return false; + } break; default: // unknown error - fail return false; diff --git a/src/plugins/git/gerrit/gerritserver.h b/src/plugins/git/gerrit/gerritserver.h index b24c0248514..dad3a790851 100644 --- a/src/plugins/git/gerrit/gerritserver.h +++ b/src/plugins/git/gerrit/gerritserver.h @@ -61,6 +61,13 @@ public: RestUrl }; + enum StoredHostValidity + { + Invalid, + NotGerrit, + Valid + }; + GerritServer(); GerritServer(const QString &host, unsigned short port, const QString &userName, HostType type); bool operator==(const GerritServer &other) const; @@ -68,6 +75,8 @@ public: QString hostArgument() const; QString url(UrlType urlType = DefaultUrl) const; bool fillFromRemote(const QString &remote, const GerritParameters ¶meters); + StoredHostValidity loadSettings(); + void saveSettings(StoredHostValidity validity) const; int testConnection(); static QStringList curlArguments(); From db16f265c9fe9f3877c7ba65337024deddbcbbd9 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 13 Mar 2017 17:17:40 +0200 Subject: [PATCH 21/56] Gerrit: Add a button for server revalidation Change-Id: I0ef823aa562093e5e3d63bc2766ab1a95ae259d5 Reviewed-by: Tobias Hunger Reviewed-by: Leena Miettinen --- src/plugins/git/gerrit/gerritdialog.cpp | 9 +++++++-- src/plugins/git/gerrit/gerritdialog.h | 2 +- src/plugins/git/gerrit/gerritdialog.ui | 7 +++++++ src/plugins/git/gerrit/gerritserver.cpp | 7 +++++-- src/plugins/git/gerrit/gerritserver.h | 2 +- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/plugins/git/gerrit/gerritdialog.cpp b/src/plugins/git/gerrit/gerritdialog.cpp index 8ed04952b72..af471345dc6 100644 --- a/src/plugins/git/gerrit/gerritdialog.cpp +++ b/src/plugins/git/gerrit/gerritdialog.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -110,6 +111,10 @@ GerritDialog::GerritDialog(const QSharedPointer &p, connect(m_ui->treeView, &QAbstractItemView::activated, this, &GerritDialog::slotActivated); + m_ui->resetRemoteButton->setIcon(Utils::Icons::RESET_TOOLBAR.icon()); + connect(m_ui->resetRemoteButton, &QToolButton::clicked, + this, [this] { updateRemotes(true); }); + m_displayButton = addActionButton(tr("&Show"), [this]() { slotFetchDisplay(); }); m_cherryPickButton = addActionButton(tr("Cherry &Pick"), [this]() { slotFetchCherryPick(); }); m_checkoutButton = addActionButton(tr("C&heckout"), [this]() { slotFetchCheckout(); }); @@ -225,7 +230,7 @@ void GerritDialog::remoteChanged() slotRefresh(); } -void GerritDialog::updateRemotes() +void GerritDialog::updateRemotes(bool forceReload) { m_ui->remoteComboBox->clear(); if (m_repository.isEmpty() || !QFileInfo(m_repository).isDir()) @@ -239,7 +244,7 @@ void GerritDialog::updateRemotes() while (mapIt.hasNext()) { mapIt.next(); GerritServer server; - if (!server.fillFromRemote(mapIt.value(), *m_parameters)) + if (!server.fillFromRemote(mapIt.value(), *m_parameters, forceReload)) continue; addRemote(server, mapIt.key()); } diff --git a/src/plugins/git/gerrit/gerritdialog.h b/src/plugins/git/gerrit/gerritdialog.h index 21c4500be3c..6c1f087764e 100644 --- a/src/plugins/git/gerrit/gerritdialog.h +++ b/src/plugins/git/gerrit/gerritdialog.h @@ -76,7 +76,7 @@ private: void slotFetchCheckout(); void slotRefresh(); void remoteChanged(); - void updateRemotes(); + void updateRemotes(bool forceReload = false); void addRemote(const GerritServer &server, const QString &name); void manageProgressIndicator(); diff --git a/src/plugins/git/gerrit/gerritdialog.ui b/src/plugins/git/gerrit/gerritdialog.ui index cf8ce050d7c..c7be2cd2cda 100644 --- a/src/plugins/git/gerrit/gerritdialog.ui +++ b/src/plugins/git/gerrit/gerritdialog.ui @@ -65,6 +65,13 @@ + + + + Refresh Remote Servers + + + diff --git a/src/plugins/git/gerrit/gerritserver.cpp b/src/plugins/git/gerrit/gerritserver.cpp index babe4fd0f47..668e7f0e3dc 100644 --- a/src/plugins/git/gerrit/gerritserver.cpp +++ b/src/plugins/git/gerrit/gerritserver.cpp @@ -118,7 +118,9 @@ QString GerritServer::url(UrlType urlType) const return res; } -bool GerritServer::fillFromRemote(const QString &remote, const GerritParameters ¶meters) +bool GerritServer::fillFromRemote(const QString &remote, + const GerritParameters ¶meters, + bool forceReload) { const GitRemote r(remote); if (!r.isValid) @@ -143,7 +145,8 @@ bool GerritServer::fillFromRemote(const QString &remote, const GerritParameters curlBinary = parameters.curl; if (curlBinary.isEmpty() || !QFile::exists(curlBinary)) return false; - switch (loadSettings()) { + const StoredHostValidity validity = forceReload ? Invalid : loadSettings(); + switch (validity) { case Invalid: rootPath = r.path; // Strip the last part of the path, which is always the repo name diff --git a/src/plugins/git/gerrit/gerritserver.h b/src/plugins/git/gerrit/gerritserver.h index dad3a790851..f9f58236131 100644 --- a/src/plugins/git/gerrit/gerritserver.h +++ b/src/plugins/git/gerrit/gerritserver.h @@ -74,7 +74,7 @@ public: static QString defaultHost(); QString hostArgument() const; QString url(UrlType urlType = DefaultUrl) const; - bool fillFromRemote(const QString &remote, const GerritParameters ¶meters); + bool fillFromRemote(const QString &remote, const GerritParameters ¶meters, bool forceReload); StoredHostValidity loadSettings(); void saveSettings(StoredHostValidity validity) const; int testConnection(); From 8795ec0beb93261b3ad8ffbb177d9f5805b1cd3f Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 13 Mar 2017 17:29:34 +0200 Subject: [PATCH 22/56] Gerrit: Replace single line slots with lambdas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I63c3e963a2aa04043c4da3da6313757b001f568d Reviewed-by: AndrĂ© Hartmann Reviewed-by: Tobias Hunger --- src/plugins/git/gerrit/gerritmodel.cpp | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/plugins/git/gerrit/gerritmodel.cpp b/src/plugins/git/gerrit/gerritmodel.cpp index 20cc112b6a6..18f0bcd9857 100644 --- a/src/plugins/git/gerrit/gerritmodel.cpp +++ b/src/plugins/git/gerrit/gerritmodel.cpp @@ -238,8 +238,6 @@ signals: private: void processError(QProcess::ProcessError); void processFinished(int exitCode, QProcess::ExitStatus); - void readyReadStandardError(); - void readyReadStandardOutput(); void timeout(); void errorTermination(const QString &msg); @@ -277,10 +275,12 @@ QueryContext::QueryContext(const QString &query, + "&o=CURRENT_REVISION&o=DETAILED_LABELS&o=DETAILED_ACCOUNTS"; m_arguments = GerritServer::curlArguments() << url; } - connect(&m_process, &QProcess::readyReadStandardError, - this, &QueryContext::readyReadStandardError); - connect(&m_process, &QProcess::readyReadStandardOutput, - this, &QueryContext::readyReadStandardOutput); + connect(&m_process, &QProcess::readyReadStandardError, this, [this] { + VcsOutputWindow::appendError(QString::fromLocal8Bit(m_process.readAllStandardError())); + }); + connect(&m_process, &QProcess::readyReadStandardOutput, this, [this] { + m_output.append(m_process.readAllStandardOutput()); + }); connect(&m_process, static_cast(&QProcess::finished), this, &QueryContext::processFinished); connect(&m_process, &QProcess::errorOccurred, this, &QueryContext::processError); @@ -357,16 +357,6 @@ void QueryContext::processFinished(int exitCode, QProcess::ExitStatus es) emit finished(); } -void QueryContext::readyReadStandardError() -{ - VcsOutputWindow::appendError(QString::fromLocal8Bit(m_process.readAllStandardError())); -} - -void QueryContext::readyReadStandardOutput() -{ - m_output.append(m_process.readAllStandardOutput()); -} - void QueryContext::timeout() { if (m_process.state() != QProcess::Running) From 75273506c1b537426c11fbaa2efff3fd1ccae188 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 12 Mar 2017 23:50:24 +0200 Subject: [PATCH 23/56] Gerrit: Resolve also user name from gerrit response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If gerrit provides it (version >= 2.10). Change-Id: I7087be338e954fa13eb4a9fcc4f848d6272a46d6 Reviewed-by: AndrĂ© Hartmann Reviewed-by: Tobias Hunger --- src/plugins/git/gerrit/gerritserver.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/git/gerrit/gerritserver.cpp b/src/plugins/git/gerrit/gerritserver.cpp index 668e7f0e3dc..6b3a40e8536 100644 --- a/src/plugins/git/gerrit/gerritserver.cpp +++ b/src/plugins/git/gerrit/gerritserver.cpp @@ -223,8 +223,13 @@ int GerritServer::testConnection() QString output = resp.stdOut(); output.remove(0, output.indexOf('\n')); // Strip first line QJsonDocument doc = QJsonDocument::fromJson(output.toUtf8()); - if (!doc.isNull()) - user.fullName = doc.object().value("name").toString(); + if (!doc.isNull()) { + const QJsonObject obj = doc.object(); + user.fullName = obj.value("name").toString(); + const QString userName = obj.value("username").toString(); + if (!userName.isEmpty()) + user.userName = userName; + } return 200; } const QRegularExpression errorRegexp("returned error: (\\d+)"); From 11e8ce65db825e1f9f03c25270f25b89b9c8a78c Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 13 Mar 2017 17:50:28 +0200 Subject: [PATCH 24/56] Gerrit: Force remote refreshing on 401 error Can happen if the password was changed. Change-Id: If0f0fa047c376c193ceda50e5465d016e16b61a3 Reviewed-by: Tobias Hunger --- src/plugins/git/gerrit/gerritdialog.cpp | 5 +++++ src/plugins/git/gerrit/gerritmodel.cpp | 8 +++++++- src/plugins/git/gerrit/gerritmodel.h | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/plugins/git/gerrit/gerritdialog.cpp b/src/plugins/git/gerrit/gerritdialog.cpp index af471345dc6..66c8c38d22d 100644 --- a/src/plugins/git/gerrit/gerritdialog.cpp +++ b/src/plugins/git/gerrit/gerritdialog.cpp @@ -124,6 +124,11 @@ GerritDialog::GerritDialog(const QSharedPointer &p, m_refreshButton, &QWidget::setDisabled); connect(m_model, &GerritModel::refreshStateChanged, this, &GerritDialog::slotRefreshStateChanged); + connect(m_model, &GerritModel::errorText, + this, [this](const QString &text) { + if (text.contains("returned error: 401")) + updateRemotes(true); + }, Qt::QueuedConnection); setCurrentPath(repository); slotCurrentChanged(); diff --git a/src/plugins/git/gerrit/gerritmodel.cpp b/src/plugins/git/gerrit/gerritmodel.cpp index 18f0bcd9857..1cc7a63f90c 100644 --- a/src/plugins/git/gerrit/gerritmodel.cpp +++ b/src/plugins/git/gerrit/gerritmodel.cpp @@ -233,6 +233,7 @@ public: signals: void resultRetrieved(const QByteArray &); + void errorText(const QString &text); void finished(); private: @@ -247,6 +248,7 @@ private: QTimer m_timer; QString m_binary; QByteArray m_output; + QString m_error; QFutureInterface m_progress; QFutureWatcher m_watcher; QStringList m_arguments; @@ -276,7 +278,9 @@ QueryContext::QueryContext(const QString &query, m_arguments = GerritServer::curlArguments() << url; } connect(&m_process, &QProcess::readyReadStandardError, this, [this] { - VcsOutputWindow::appendError(QString::fromLocal8Bit(m_process.readAllStandardError())); + const QString text = QString::fromLocal8Bit(m_process.readAllStandardError()); + VcsOutputWindow::appendError(text); + m_error.append(text); }); connect(&m_process, &QProcess::readyReadStandardOutput, this, [this] { m_output.append(m_process.readAllStandardOutput()); @@ -345,6 +349,7 @@ void QueryContext::processFinished(int exitCode, QProcess::ExitStatus es) { if (m_timer.isActive()) m_timer.stop(); + emit errorText(m_error); if (es != QProcess::NormalExit) { errorTermination(tr("%1 crashed.").arg(m_binary)); return; @@ -510,6 +515,7 @@ void GerritModel::refresh(const QSharedPointer &server, const QStr m_query = new QueryContext(realQuery, m_parameters, *m_server, this); connect(m_query, &QueryContext::resultRetrieved, this, &GerritModel::resultRetrieved); + connect(m_query, &QueryContext::errorText, this, &GerritModel::errorText); connect(m_query, &QueryContext::finished, this, &GerritModel::queryFinished); emit refreshStateChanged(true); m_query->start(); diff --git a/src/plugins/git/gerrit/gerritmodel.h b/src/plugins/git/gerrit/gerritmodel.h index 863a2c97c16..d9efd0edd25 100644 --- a/src/plugins/git/gerrit/gerritmodel.h +++ b/src/plugins/git/gerrit/gerritmodel.h @@ -127,6 +127,7 @@ public: signals: void refreshStateChanged(bool isRefreshing); // For disabling the "Refresh" button. void stateChanged(); + void errorText(const QString &text); private: void resultRetrieved(const QByteArray &); From e41befd4f7bf9214ca1a8295699d4a7332488a9d Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 14 Mar 2017 07:36:01 +0100 Subject: [PATCH 25/56] Debugger: Check also for Qt5Core(d).dll on Windows Change-Id: Ic078a165d35c316cb12d08ca84913b4b07143aa4 Reviewed-by: Christian Stenger Reviewed-by: hjk --- share/qtcreator/debugger/gdbbridge.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index ebf15ab8288..2506ec10e32 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -976,11 +976,18 @@ class Dumper(DumperBase): for objfile in gdb.objfiles(): name = objfile.filename - if name.find('/libQt5Core') >= 0: + if self.isWindowsTarget(): + isQtCoreObjFile = name.find('Qt5Cored.dll') >= 0 or name.find('Qt5Core.dll') >= 0 + else: + isQtCoreObjFile = name.find('/libQt5Core') >= 0 + if isQtCoreObjFile: fd, tmppath = tempfile.mkstemp() os.close(fd) cmd = 'maint print msymbols %s "%s"' % (tmppath, name) - symbols = gdb.execute(cmd, to_string = True) + try: + symbols = gdb.execute(cmd, to_string = True) + except: + pass ns = '' with open(tmppath) as f: for line in f: From 629dd8bbed28a53affb0634971bc89379f5bbd94 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Tue, 14 Mar 2017 13:51:27 +0100 Subject: [PATCH 26/56] Squish: Update expexted log in tst_git_clone Change-Id: Ie0f87cf23d9c86c6e5ada37be00cf8e7c2c8ecb5 Reviewed-by: Christian Stenger --- tests/system/suite_tools/tst_git_clone/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/suite_tools/tst_git_clone/test.py b/tests/system/suite_tools/tst_git_clone/test.py index 20a74e6546d..10126c857b2 100644 --- a/tests/system/suite_tools/tst_git_clone/test.py +++ b/tests/system/suite_tools/tst_git_clone/test.py @@ -65,7 +65,7 @@ def verifyVersionControlView(targetDir, canceled): vcsLog = str(waitForObject("{type='Core::OutputWindow' unnamed='1' visible='1' " "window=':Qt Creator_Core::Internal::MainWindow'}").plainText) test.log("Clone log is: %s" % vcsLog) - test.verify("Executing in " + targetDir + ":" in vcsLog, + test.verify("Running in " + targetDir + ":" in vcsLog, "Searching for target directory in clone log") test.verify(" ".join(["clone", "--progress", cloneUrl, cloneDir]) in vcsLog, "Searching for git parameters in clone log") From 2e54c89738b23f5be6eebdea4d39a0a5663877b6 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 14 Mar 2017 11:59:54 +0100 Subject: [PATCH 27/56] GccToolChain: Remove autodetection for gcc-4.0 and 4.2 on macOS Change-Id: I64f9533a153d6a2577747f31a422f91ff555351e Reviewed-by: Eike Ziller --- src/plugins/projectexplorer/gcctoolchain.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 30f77f739e0..9af71fa40af 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -907,17 +907,6 @@ ToolChain *GccToolChainFactory::create(Core::Id language) QList GccToolChainFactory::autoDetect(const QList &alreadyKnown) { QList tcs; - if (HostOsInfo::isMacHost()) { - // Old mac compilers needed to support macx-gccXY mkspecs: - tcs.append(autoDetectToolchains("g++-4.0", Abi::hostAbi(), Constants::CXX_LANGUAGE_ID, - Constants::GCC_TOOLCHAIN_TYPEID, alreadyKnown)); - tcs.append(autoDetectToolchains("g++-4.2", Abi::hostAbi(), Constants::CXX_LANGUAGE_ID, - Constants::GCC_TOOLCHAIN_TYPEID, alreadyKnown)); - tcs.append(autoDetectToolchains("gcc-4.0", Abi::hostAbi(), Constants::C_LANGUAGE_ID, - Constants::GCC_TOOLCHAIN_TYPEID, alreadyKnown)); - tcs.append(autoDetectToolchains("gcc-4.2", Abi::hostAbi(), Constants::C_LANGUAGE_ID, - Constants::GCC_TOOLCHAIN_TYPEID, alreadyKnown)); - } tcs.append(autoDetectToolchains("g++", Abi::hostAbi(), Constants::CXX_LANGUAGE_ID, Constants::GCC_TOOLCHAIN_TYPEID, alreadyKnown)); tcs.append(autoDetectToolchains("gcc", Abi::hostAbi(), Constants::C_LANGUAGE_ID, From 2d703c7dd41510e14c85d3fa4b8a44658e004154 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Tue, 14 Mar 2017 13:25:40 +0100 Subject: [PATCH 28/56] qmljs/parser: Remove check for impossible value Change-Id: Ide23dd761016a37ef4720c7637818e20925df7d7 Reviewed-by: Tim Jenssen --- src/libs/qmljs/parser/qmljskeywords_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/qmljs/parser/qmljskeywords_p.h b/src/libs/qmljs/parser/qmljskeywords_p.h index df0030d6dde..94c2d8aca23 100644 --- a/src/libs/qmljs/parser/qmljskeywords_p.h +++ b/src/libs/qmljs/parser/qmljskeywords_p.h @@ -63,7 +63,7 @@ static inline int classify2(const QChar *s, bool qmlMode) { } else if (qmlMode && s[0].unicode() == 'o') { if (s[1].unicode() == 'n') { - return qmlMode ? Lexer::T_ON : Lexer::T_IDENTIFIER; + return Lexer::T_ON; } } return Lexer::T_IDENTIFIER; @@ -675,7 +675,7 @@ static inline int classify8(const QChar *s, bool qmlMode) { if (s[5].unicode() == 'r') { if (s[6].unicode() == 't') { if (s[7].unicode() == 'y') { - return qmlMode ? Lexer::T_PROPERTY : Lexer::T_IDENTIFIER; + return Lexer::T_PROPERTY; } } } From 9804d56009e4259174cb14a9aabb8d3ac92dc036 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 13 Mar 2017 16:19:45 +0200 Subject: [PATCH 29/56] Nim: Add an explicit include for QRegExp Other includes will be merged from 4.2. Nim doesn't exist there. Change-Id: I0d701a07adefe04e730898a219be021ec4e70860 Reviewed-by: Samuel Gaist Reviewed-by: Eike Ziller --- src/plugins/nim/project/nimtoolchain.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/nim/project/nimtoolchain.cpp b/src/plugins/nim/project/nimtoolchain.cpp index 1c34ec24058..6c8fd0f32b8 100644 --- a/src/plugins/nim/project/nimtoolchain.cpp +++ b/src/plugins/nim/project/nimtoolchain.cpp @@ -32,6 +32,7 @@ #include #include +#include using namespace ProjectExplorer; using namespace Utils; From 6815633dffea4903ea164300d83eae280fa9ff3c Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 14 Mar 2017 14:06:21 +0100 Subject: [PATCH 30/56] Qbs: Fix build after update to ProjectNodes Change-Id: Ibb736901596a7295f50059f5dd448a2b5da32e85 Reviewed-by: hjk --- src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp index 2bad75e16e1..49fafa9d057 100644 --- a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp @@ -63,7 +63,7 @@ void setupArtifacts(ProjectExplorer::FolderNode *root, const QListbuildTree(fileNodes); + root->addNestedNodes(fileNodes); root->compress(); } @@ -197,7 +197,7 @@ QbsRootProjectNode *QbsNodeTreeBuilder::buildTree(QbsProject *project) if (filePath.isChildOf(base)) projectBuildSystemFiles.append(new ProjectExplorer::FileNode(filePath, ProjectExplorer::FileType::Project, false)); } - buildSystemFiles->buildTree(projectBuildSystemFiles); + buildSystemFiles->addNestedNodes(projectBuildSystemFiles); buildSystemFiles->compress(); root->addNode(buildSystemFiles); From 5b9eaf747daba9e783d467619b2b73da77af426a Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 14 Mar 2017 16:56:28 +0200 Subject: [PATCH 31/56] QbsPM: Add nodes incrementally Change-Id: Id53a0107df64b26d8ec57eda734635bda9e045f6 Reviewed-by: Tobias Hunger --- src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp index 49fafa9d057..80308251074 100644 --- a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp @@ -55,15 +55,13 @@ ProjectExplorer::FileType fileType(const qbs::ArtifactData &artifact) void setupArtifacts(ProjectExplorer::FolderNode *root, const QList &artifacts) { - QList fileNodes - = Utils::transform(artifacts, [](const qbs::ArtifactData &ad) { + for (const qbs::ArtifactData &ad : artifacts) { const Utils::FileName path = Utils::FileName::fromString(ad.filePath()); const ProjectExplorer::FileType type = fileType(ad); const bool isGenerated = ad.isGenerated(); - return new ProjectExplorer::FileNode(path, type, isGenerated); - }); + root->addNestedNode(new ProjectExplorer::FileNode(path, type, isGenerated)); + }; - root->addNestedNodes(fileNodes); root->compress(); } @@ -190,14 +188,12 @@ QbsRootProjectNode *QbsNodeTreeBuilder::buildTree(QbsProject *project) ProjectExplorer::NodeType::Folder, QCoreApplication::translate("QbsRootProjectNode", "Qbs files")); - QList projectBuildSystemFiles; Utils::FileName base = project->projectDirectory(); for (const QString &f : unreferencedBuildSystemFiles(project->qbsProject())) { const Utils::FileName filePath = Utils::FileName::fromString(f); if (filePath.isChildOf(base)) - projectBuildSystemFiles.append(new ProjectExplorer::FileNode(filePath, ProjectExplorer::FileType::Project, false)); + root->addNestedNode(new ProjectExplorer::FileNode(filePath, ProjectExplorer::FileType::Project, false)); } - buildSystemFiles->addNestedNodes(projectBuildSystemFiles); buildSystemFiles->compress(); root->addNode(buildSystemFiles); From 713616204703a2a8972ac6d9f367bf2f6a765d2f Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Fri, 3 Mar 2017 16:18:08 +0100 Subject: [PATCH 32/56] add extra arguments for qmake unlike user arguments, extra arguments are not user editable Change-Id: I0413c2da699c6d2fce1db10a8bc3dd938c8477b0 Reviewed-by: Tobias Hunger --- src/plugins/qmakeprojectmanager/qmakestep.cpp | 19 +++++++++++++++++++ src/plugins/qmakeprojectmanager/qmakestep.h | 8 +++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/plugins/qmakeprojectmanager/qmakestep.cpp b/src/plugins/qmakeprojectmanager/qmakestep.cpp index d8f83e6a0e0..5250042ca27 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.cpp +++ b/src/plugins/qmakeprojectmanager/qmakestep.cpp @@ -86,6 +86,7 @@ QMakeStep::QMakeStep(BuildStepList *bsl, Core::Id id) : QMakeStep::QMakeStep(BuildStepList *bsl, QMakeStep *bs) : AbstractProcessStep(bsl, bs), m_userArgs(bs->m_userArgs), + m_extraArgs(bs->m_extraArgs), m_forced(bs->m_forced), m_linkQmlDebuggingLibrary(bs->m_linkQmlDebuggingLibrary), m_useQtQuickCompiler(bs->m_useQtQuickCompiler), @@ -154,6 +155,8 @@ QString QMakeStep::allArguments(const BaseQtVersion *v, bool shorted) const QString args = QtcProcess::joinArgs(arguments); // User arguments QtcProcess::addArgs(&args, m_userArgs); + foreach (QString arg, m_extraArgs) + QtcProcess::addArgs(&args, arg); return args; } @@ -405,6 +408,21 @@ void QMakeStep::setUserArguments(const QString &arguments) qmakeBuildConfiguration()->emitProFileEvaluateNeeded(); } +QStringList QMakeStep::extraArguments() const +{ + return m_extraArgs; +} + +void QMakeStep::setExtraArguments(const QStringList &args) +{ + if (m_extraArgs != args) { + m_extraArgs = args; + emit extraArgumentsChanged(); + qmakeBuildConfiguration()->emitQMakeBuildConfigurationChanged(); + qmakeBuildConfiguration()->emitProFileEvaluateNeeded(); + } +} + bool QMakeStep::linkQmlDebuggingLibrary() const { return m_linkQmlDebuggingLibrary; @@ -517,6 +535,7 @@ QString QMakeStep::userArguments() FileName QMakeStep::mkspec() const { QString additionalArguments = m_userArgs; + QtcProcess::addArgs(&additionalArguments, m_extraArgs); for (QtcProcess::ArgIterator ait(&additionalArguments); ait.next(); ) { if (ait.value() == QLatin1String("-spec")) { if (ait.next()) diff --git a/src/plugins/qmakeprojectmanager/qmakestep.h b/src/plugins/qmakeprojectmanager/qmakestep.h index 237e48bb0f5..a69db1113eb 100644 --- a/src/plugins/qmakeprojectmanager/qmakestep.h +++ b/src/plugins/qmakeprojectmanager/qmakestep.h @@ -135,8 +135,11 @@ public: QStringList parserArguments(); // arguments set by the user QString userArguments(); - Utils::FileName mkspec() const; void setUserArguments(const QString &arguments); + // QMake extra arguments. Not user editable. + QStringList extraArguments() const; + void setExtraArguments(const QStringList &args); + Utils::FileName mkspec() const; bool linkQmlDebuggingLibrary() const; void setLinkQmlDebuggingLibrary(bool enable); bool useQtQuickCompiler() const; @@ -152,6 +155,7 @@ public: signals: void userArgumentsChanged(); + void extraArgumentsChanged(); void linkQmlDebuggingLibraryChanged(); void useQtQuickCompilerChanged(); void separateDebugInfoChanged(); @@ -174,6 +178,8 @@ private: QString m_makeExecutable; QString m_makeArguments; QString m_userArgs; + // Extra arguments for qmake. + QStringList m_extraArgs; QFutureInterface m_inputFuture; QFutureWatcher m_inputWatcher; From 6f0a31166d495bcbe4ce2fb5b6ff114724aa1874 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 14 Mar 2017 12:27:57 +0100 Subject: [PATCH 33/56] ToolChains: Write compatibility information for QtC 4.2 This avoids turning all toolchains into C++ when going from Qt Creator 4.3 to Qt Creator 4.2 and back. Change-Id: I607606f76d958c634ab27cb6db3bf35a1236b2b6 Reviewed-by: Eike Ziller --- src/plugins/projectexplorer/toolchain.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index bc69b898561..cb636437046 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -225,6 +225,15 @@ QVariantMap ToolChain::toMap() const result.insert(QLatin1String(ID_KEY), idToSave); result.insert(QLatin1String(DISPLAY_NAME_KEY), displayName()); result.insert(QLatin1String(AUTODETECT_KEY), isAutoDetected()); + // + int oldLanguageId = -1; + if (language() == ProjectExplorer::Constants::C_LANGUAGE_ID) + oldLanguageId = 1; + else if (language() == ProjectExplorer::Constants::CXX_LANGUAGE_ID) + oldLanguageId = 2; + if (oldLanguageId >= 0) + result.insert(LANGUAGE_KEY_V1, oldLanguageId); + // result.insert(QLatin1String(LANGUAGE_KEY_V2), language().toSetting()); return result; } From 7c95aedfd369f1fabc3a1195c51229ea4874c5b9 Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Fri, 3 Mar 2017 16:20:53 +0100 Subject: [PATCH 34/56] iOS: Add API's to get provisioning data Change-Id: I927b2dbaa9e6c175d90b1407418570bbd2a3d96e Reviewed-by: Eike Ziller --- src/plugins/ios/iosconfigurations.cpp | 217 +++++++++++++++++++++++++- src/plugins/ios/iosconfigurations.h | 70 ++++++++- 2 files changed, 281 insertions(+), 6 deletions(-) diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp index 19f6f39d63b..4a6e004da1d 100644 --- a/src/plugins/ios/iosconfigurations.cpp +++ b/src/plugins/ios/iosconfigurations.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -49,12 +50,15 @@ #include #include +#include #include #include +#include #include #include +#include +#include #include -#include #include using namespace ProjectExplorer; @@ -74,6 +78,21 @@ namespace Internal { const QLatin1String SettingsGroup("IosConfigurations"); const QLatin1String ignoreAllDevicesKey("IgnoreAllDevices"); +const char provisioningTeamsTag[] = "IDEProvisioningTeams"; +const char freeTeamTag[] = "isFreeProvisioningTeam"; +const char emailTag[] = "eMail"; +const char teamNameTag[] = "teamName"; +const char teamIdTag[] = "teamID"; + +const char udidTag[] = "UUID"; +const char profileNameTag[] = "Name"; +const char appIdTag[] = "AppIDName"; +const char expirationDateTag[] = "ExpirationDate"; +const char profileTeamIdTag[] = "TeamIdentifier"; + +static const QString xcodePlistPath = QDir::homePath() + "/Library/Preferences/com.apple.dt.Xcode.plist"; +static const QString provisioningProfileDirPath = QDir::homePath() + "/Library/MobileDevice/Provisioning Profiles"; + static Core::Id deviceId(const Platform &platform) { if (platform.name.startsWith(QLatin1String("iphoneos-"))) @@ -246,6 +265,20 @@ static QVersionNumber findXcodeVersion() return QVersionNumber(); } +static QByteArray decodeProvisioningProfile(const QString &path) +{ + QTC_ASSERT(!path.isEmpty(), return QByteArray()); + + Utils::SynchronousProcess p; + p.setTimeoutS(3); + // path is assumed to be valid file path to .mobileprovision + const QStringList args = {"smime", "-inform", "der", "-verify", "-in", path}; + Utils::SynchronousProcessResponse res = p.runBlocking("openssl", args); + if (res.result != Utils::SynchronousProcessResponse::Finished) + qCDebug(iosCommonLog) << "Reading signed provisioning file failed" << path; + return res.stdOut().toLatin1(); +} + void IosConfigurations::updateAutomaticKitList() { const QList platforms = handledPlatforms(); @@ -320,9 +353,9 @@ void IosConfigurations::updateAutomaticKitList() KitManager::deregisterKit(kit); } -static IosConfigurations *m_instance = 0; +static IosConfigurations *m_instance = nullptr; -QObject *IosConfigurations::instance() +IosConfigurations *IosConfigurations::instance() { return m_instance; } @@ -409,6 +442,137 @@ void IosConfigurations::setDeveloperPath(const FileName &devPath) } } +void IosConfigurations::initializeProvisioningData() +{ + // Initialize provisioning data only on demand. i.e. when first call to a provisioing data API + // is made. + static bool initialized = false; + if (initialized) + return; + initialized = true; + + m_instance->loadProvisioningData(false); + + // Watch the provisioing profiles folder and xcode plist for changes and + // update the content accordingly. + m_provisioningDataWatcher = new QFileSystemWatcher(this); + m_provisioningDataWatcher->addPath(xcodePlistPath); + m_provisioningDataWatcher->addPath(provisioningProfileDirPath); + connect(m_provisioningDataWatcher, &QFileSystemWatcher::directoryChanged, + std::bind(&IosConfigurations::loadProvisioningData, this, true)); + connect(m_provisioningDataWatcher, &QFileSystemWatcher::fileChanged, + std::bind(&IosConfigurations::loadProvisioningData, this, true)); +} + +void IosConfigurations::loadProvisioningData(bool notify) +{ + m_developerTeams.clear(); + m_provisioningProfiles.clear(); + + // Populate Team id's + const QSettings xcodeSettings(xcodePlistPath, QSettings::NativeFormat); + const QVariantMap teamMap = xcodeSettings.value(provisioningTeamsTag).toMap(); + QList teams; + QMapIterator accountiterator(teamMap); + while (accountiterator.hasNext()) { + accountiterator.next(); + QVariantMap teamInfo = accountiterator.value().toMap(); + int provisioningTeamIsFree = teamInfo.value(freeTeamTag).toBool() ? 1 : 0; + teamInfo[freeTeamTag] = provisioningTeamIsFree; + teamInfo[emailTag] = accountiterator.key(); + teams.append(teamInfo); + } + + // Sort team id's to move the free provisioning teams at last of the list. + Utils::sort(teams, [](const QVariantMap &teamInfo1, const QVariantMap &teamInfo2) { + return teamInfo1.value(freeTeamTag).toInt() < teamInfo2.value(freeTeamTag).toInt(); + }); + + foreach (auto teamInfo, teams) { + auto team = std::shared_ptr::make_shared(); + team->m_name = teamInfo.value(teamNameTag).toString(); + team->m_email = teamInfo.value(emailTag).toString(); + team->m_identifier = teamInfo.value(teamIdTag).toString(); + team->m_freeTeam = teamInfo.value(freeTeamTag).toInt() == 1; + m_developerTeams.append(team); + } + + const QDir provisioningProflesDir(provisioningProfileDirPath); + foreach (QFileInfo fileInfo, provisioningProflesDir.entryInfoList({"*.mobileprovision"}, QDir::NoDotAndDotDot | QDir::Files)) { + QDomDocument provisioningDoc; + auto profile = ProvisioningProfilePtr::make_shared();; + QString teamID; + if (provisioningDoc.setContent(decodeProvisioningProfile(fileInfo.absoluteFilePath()))) { + QDomNodeList nodes = provisioningDoc.elementsByTagName("key"); + for (int i = 0;im_identifier = e.nextSiblingElement().text(); + + if (e.text().compare(profileNameTag) == 0) + profile->m_name = e.nextSiblingElement().text(); + + if (e.text().compare(appIdTag) == 0) + profile->m_appID = e.nextSiblingElement().text(); + + if (e.text().compare(expirationDateTag) == 0) + profile->m_expirationDate = QDateTime::fromString(e.nextSiblingElement().text(), + Qt::ISODate).toUTC(); + + if (e.text().compare(profileTeamIdTag) == 0) { + teamID = e.nextSibling().firstChildElement().text(); + auto team = developmentTeam(teamID); + if (team) { + profile->m_team = team; + team->m_profiles.append(profile); + } + } + } + } else { + qCDebug(iosCommonLog) << "Error reading provisoing profile" << fileInfo.absoluteFilePath(); + } + + if (profile->m_team) + m_provisioningProfiles.append(profile); + else + qCDebug(iosCommonLog) << "Skipping profile. No corresponding team found" << profile; + } + + if (notify) + emit provisioningDataChanged(); +} + +const DevelopmentTeams &IosConfigurations::developmentTeams() +{ + QTC_CHECK(m_instance); + m_instance->initializeProvisioningData(); + return m_instance->m_developerTeams; +} + +DevelopmentTeamPtr IosConfigurations::developmentTeam(const QString &teamID) +{ + QTC_CHECK(m_instance); + m_instance->initializeProvisioningData(); + return findOrDefault(m_instance->m_developerTeams, + Utils::equal(&DevelopmentTeam::identifier, teamID)); +} + +const ProvisioningProfiles &IosConfigurations::provisioningProfiles() +{ + QTC_CHECK(m_instance); + m_instance->initializeProvisioningData(); + return m_instance->m_provisioningProfiles; +} + +ProvisioningProfilePtr IosConfigurations::provisioningProfile(const QString &profileID) +{ + QTC_CHECK(m_instance); + m_instance->initializeProvisioningData(); + return Utils::findOrDefault(m_instance->m_provisioningProfiles, + Utils::equal(&ProvisioningProfile::identifier, profileID)); +} + static ClangToolChain *createToolChain(const Platform &platform, Core::Id l) { if (!l.isValid()) @@ -455,5 +619,52 @@ QList IosToolChainFactory::autoDetect(const QList &exi return Utils::transform(toolChains, [](ClangToolChain *tc) -> ToolChain * { return tc; }); } +QString DevelopmentTeam::identifier() const +{ + return m_identifier; +} + +QString DevelopmentTeam::displayName() const +{ + return QString("%1 - %2").arg(m_email).arg(m_name); +} + +QString DevelopmentTeam::details() const +{ + return tr("%1 - Free Provisioning Team : %2") + .arg(m_identifier).arg(m_freeTeam ? tr("Yes") : tr("No")); +} + +QDebug &operator<<(QDebug &stream, DevelopmentTeamPtr team) +{ + QTC_ASSERT(team, return stream); + stream << team->displayName() << team->identifier() << team->isFreeProfile(); + foreach (auto profile, team->m_profiles) + stream << "Profile:" << profile; + return stream; +} + +QString ProvisioningProfile::identifier() const +{ + return m_identifier; +} + +QString ProvisioningProfile::displayName() const +{ + return m_name; +} + +QString ProvisioningProfile::details() const +{ + return tr("Team: %1\nApp ID: %2\nExpiration date: %3").arg(m_team->identifier()).arg(m_appID) + .arg(m_expirationDate.toLocalTime().toString(Qt::SystemLocaleShortDate)); +} + +QDebug &operator<<(QDebug &stream, std::shared_ptr profile) +{ + QTC_ASSERT(profile, return stream); + return stream << profile->displayName() << profile->identifier() << profile->details(); +} + } // namespace Internal } // namespace Ios diff --git a/src/plugins/ios/iosconfigurations.h b/src/plugins/ios/iosconfigurations.h index 7ddbb7e4620..a4e1163b01f 100644 --- a/src/plugins/ios/iosconfigurations.h +++ b/src/plugins/ios/iosconfigurations.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -36,11 +37,62 @@ QT_BEGIN_NAMESPACE class QSettings; +class QFileSystemWatcher; QT_END_NAMESPACE namespace Ios { namespace Internal { +class DevelopmentTeam; + +class ProvisioningProfile +{ + Q_DECLARE_TR_FUNCTIONS(ProvisioningProfile) +public: + ProvisioningProfile() {} + std::shared_ptr developmentTeam() { return m_team; } + QString identifier() const; + QString displayName() const; + QString details() const; + const QDateTime &expirationDate() const { return m_expirationDate; } + +private: + std::shared_ptr m_team; + QString m_identifier; + QString m_name; + QString m_appID; + QDateTime m_expirationDate; + friend class IosConfigurations; + friend QDebug &operator<<(QDebug &stream, std::shared_ptr profile); +}; + +using ProvisioningProfilePtr = std::shared_ptr; +using ProvisioningProfiles = QList; + +class DevelopmentTeam +{ + Q_DECLARE_TR_FUNCTIONS(DevelopmentTeam) +public: + DevelopmentTeam() {} + QString identifier() const; + QString displayName() const; + QString details() const; + bool isFreeProfile() const { return m_freeTeam; } + bool hasProvisioningProfile() const { return !m_profiles.isEmpty(); } + +private: + QString m_identifier; + QString m_name; + QString m_email; + bool m_freeTeam = false; + ProvisioningProfiles m_profiles; + friend class IosConfigurations; + friend QDebug &operator<<(QDebug &stream, std::shared_ptr team); +}; + +using DevelopmentTeamPtr = std::shared_ptr; +using DevelopmentTeams = QList; + class IosToolChainFactory : public ProjectExplorer::ToolChainFactory { Q_OBJECT @@ -50,13 +102,12 @@ public: QList autoDetect(const QList &existingToolChains) override; }; - class IosConfigurations : public QObject { Q_OBJECT public: - static QObject *instance(); + static IosConfigurations *instance(); static void initialize(); static bool ignoreAllDevices(); static void setIgnoreAllDevices(bool ignoreDevices); @@ -64,6 +115,13 @@ public: static QVersionNumber xcodeVersion(); static Utils::FileName lldbPath(); static void updateAutomaticKitList(); + static const DevelopmentTeams &developmentTeams(); + static DevelopmentTeamPtr developmentTeam(const QString &teamID); + static const ProvisioningProfiles &provisioningProfiles(); + static ProvisioningProfilePtr provisioningProfile(const QString &profileID); + +signals: + void provisioningDataChanged(); private: IosConfigurations(QObject *parent); @@ -71,11 +129,17 @@ private: void save(); void updateSimulators(); static void setDeveloperPath(const Utils::FileName &devPath); + void initializeProvisioningData(); + void loadProvisioningData(bool notify = true); Utils::FileName m_developerPath; QVersionNumber m_xcodeVersion; bool m_ignoreAllDevices; + QFileSystemWatcher *m_provisioningDataWatcher; + ProvisioningProfiles m_provisioningProfiles; + DevelopmentTeams m_developerTeams; }; - +QDebug &operator<<(QDebug &stream, std::shared_ptr profile); +QDebug &operator<<(QDebug &stream, std::shared_ptr team); } // namespace Internal } // namespace Ios From f80808f5e911d85912de997de3f03e3304e35159 Mon Sep 17 00:00:00 2001 From: Vikas Pachdha Date: Fri, 3 Mar 2017 16:21:55 +0100 Subject: [PATCH 35/56] iOS: Let user specify developer team and provisioning profile Task-number: QTCREATORBUG-16936 Change-Id: Ie4a91125f34fbf35cda4e1593919899af5f4cdbb Reviewed-by: Eike Ziller --- src/plugins/ios/ios.pro | 11 +- src/plugins/ios/iosbuildconfiguration.cpp | 193 ++++++++++++++ src/plugins/ios/iosbuildconfiguration.h | 75 ++++++ src/plugins/ios/iosbuildsettingswidget.cpp | 290 +++++++++++++++++++++ src/plugins/ios/iosbuildsettingswidget.h | 80 ++++++ src/plugins/ios/iosbuildsettingswidget.ui | 137 ++++++++++ src/plugins/ios/iosplugin.cpp | 2 + 7 files changed, 785 insertions(+), 3 deletions(-) create mode 100644 src/plugins/ios/iosbuildconfiguration.cpp create mode 100644 src/plugins/ios/iosbuildconfiguration.h create mode 100644 src/plugins/ios/iosbuildsettingswidget.cpp create mode 100644 src/plugins/ios/iosbuildsettingswidget.h create mode 100644 src/plugins/ios/iosbuildsettingswidget.ui diff --git a/src/plugins/ios/ios.pro b/src/plugins/ios/ios.pro index f54bde30e81..3e5f5bd9597 100644 --- a/src/plugins/ios/ios.pro +++ b/src/plugins/ios/ios.pro @@ -34,7 +34,9 @@ HEADERS += \ iosdeploystepfactory.h \ iosdeploystepwidget.h \ iosanalyzesupport.h \ - simulatorcontrol.h + simulatorcontrol.h \ + iosbuildconfiguration.h \ + iosbuildsettingswidget.h SOURCES += \ @@ -63,13 +65,16 @@ SOURCES += \ iosdeploystepfactory.cpp \ iosdeploystepwidget.cpp \ iosanalyzesupport.cpp \ - simulatorcontrol.cpp + simulatorcontrol.cpp \ + iosbuildconfiguration.cpp \ + iosbuildsettingswidget.cpp FORMS += \ iossettingswidget.ui \ iosbuildstep.ui \ iosdeploystepwidget.ui \ - iospresetbuildstep.ui + iospresetbuildstep.ui \ + iosbuildsettingswidget.ui DEFINES += IOS_LIBRARY diff --git a/src/plugins/ios/iosbuildconfiguration.cpp b/src/plugins/ios/iosbuildconfiguration.cpp new file mode 100644 index 00000000000..74d14d08db4 --- /dev/null +++ b/src/plugins/ios/iosbuildconfiguration.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "iosbuildconfiguration.h" + +#include "iosconfigurations.h" +#include "iosconstants.h" +#include "iosbuildsettingswidget.h" +#include "iosmanager.h" + +#include "projectexplorer/kitinformation.h" +#include "projectexplorer/namedwidget.h" +#include "projectexplorer/target.h" +#include "qmakeprojectmanager/qmakebuildinfo.h" +#include "utils/algorithm.h" + +#include + +using namespace QmakeProjectManager; + +namespace Ios { +namespace Internal { + +const char qmakeIosTeamSettings[] = "QMAKE_MAC_XCODE_SETTINGS+=qteam qteam.name=DEVELOPMENT_TEAM qteam.value="; +const char qmakeProvisioningProfileSettings[] = "QMAKE_MAC_XCODE_SETTINGS+=qprofile qprofile.name=PROVISIONING_PROFILE_SPECIFIER qprofile.value="; +const char signingIdentifierKey[] = "Ios.SigningIdentifier"; +const char autoManagedSigningKey[] = "Ios.AutoManagedSigning"; + +IosBuildConfiguration::IosBuildConfiguration(ProjectExplorer::Target *target) : + QmakeBuildConfiguration(target) +{ +} + +IosBuildConfiguration::IosBuildConfiguration(ProjectExplorer::Target *target, IosBuildConfiguration *source) : + QmakeBuildConfiguration(target, source) +{ +} + +QList IosBuildConfiguration::createSubConfigWidgets() +{ + auto subConfigWidgets = QmakeBuildConfiguration::createSubConfigWidgets(); + + Core::Id devType = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(target()->kit()); + // Ownership of this widget is with BuildSettingsWidget + auto buildSettingsWidget = new IosBuildSettingsWidget(devType, m_signingIdentifier, + m_autoManagedSigning); + subConfigWidgets.prepend(buildSettingsWidget); + connect(buildSettingsWidget, &IosBuildSettingsWidget::signingSettingsChanged, + this, &IosBuildConfiguration::onSigningSettingsChanged); + return subConfigWidgets; +} + +QVariantMap IosBuildConfiguration::toMap() const +{ + QVariantMap map(QmakeBuildConfiguration::toMap()); + map.insert(signingIdentifierKey, m_signingIdentifier); + map.insert(autoManagedSigningKey, m_autoManagedSigning); + return map; +} + +bool IosBuildConfiguration::fromMap(const QVariantMap &map) +{ + if (!QmakeBuildConfiguration::fromMap(map)) + return false; + m_autoManagedSigning = map.value(autoManagedSigningKey).toBool(); + m_signingIdentifier = map.value(signingIdentifierKey).toString(); + updateQmakeCommand(); + return true; +} + +void IosBuildConfiguration::onSigningSettingsChanged(bool autoManagedSigning, QString identifier) +{ + if (m_signingIdentifier.compare(identifier) != 0 + || m_autoManagedSigning != autoManagedSigning) { + m_autoManagedSigning = autoManagedSigning; + m_signingIdentifier = identifier; + updateQmakeCommand(); + } +} + +void IosBuildConfiguration::updateQmakeCommand() +{ + QMakeStep *qmakeStepInstance = qmakeStep(); + const QString forceOverrideArg("-after"); + if (qmakeStepInstance) { + QStringList extraArgs = qmakeStepInstance->extraArguments(); + // remove old extra arguments. + Utils::erase(extraArgs, [forceOverrideArg](const QString& arg) { + return arg.startsWith(qmakeIosTeamSettings) + || arg.startsWith(qmakeProvisioningProfileSettings) + || arg == forceOverrideArg; + }); + + // Set force ovveride qmake switch + if (!m_signingIdentifier.isEmpty() ) + extraArgs << forceOverrideArg; + + Core::Id devType = ProjectExplorer::DeviceTypeKitInformation::deviceTypeId(target()->kit()); + if (devType == Constants::IOS_DEVICE_TYPE && !m_signingIdentifier.isEmpty()) { + if (m_autoManagedSigning) { + extraArgs << qmakeIosTeamSettings + m_signingIdentifier; + } else { + // Get the team id from provisioning profile + ProvisioningProfilePtr profile = + IosConfigurations::provisioningProfile(m_signingIdentifier); + QString teamId; + if (profile) + teamId = profile->developmentTeam()->identifier(); + else + qCDebug(iosLog) << "No provisioing profile found for id:"<< m_signingIdentifier; + + if (!teamId.isEmpty()) { + extraArgs << qmakeProvisioningProfileSettings + m_signingIdentifier; + extraArgs << qmakeIosTeamSettings + teamId; + } else { + qCDebug(iosLog) << "Development team unavailable for profile:" << profile; + } + } + } + + qmakeStepInstance->setExtraArguments(extraArgs); + } +} + +IosBuildConfigurationFactory::IosBuildConfigurationFactory(QObject *parent) + : QmakeBuildConfigurationFactory(parent) +{ +} + + +int IosBuildConfigurationFactory::priority(const ProjectExplorer::Kit *k, const QString &projectPath) const +{ + return (QmakeBuildConfigurationFactory::priority(k, projectPath) >= 0 + && IosManager::supportsIos(k)) ? 1 : -1; +} + +int IosBuildConfigurationFactory::priority(const ProjectExplorer::Target *parent) const +{ + return (QmakeBuildConfigurationFactory::priority(parent) >= 0 + && IosManager::supportsIos(parent)) ? 1 : -1; +} + +ProjectExplorer::BuildConfiguration *IosBuildConfigurationFactory::create(ProjectExplorer::Target *parent, + const ProjectExplorer::BuildInfo *info) const +{ + auto qmakeInfo = static_cast(info); + auto bc = new IosBuildConfiguration(parent); + configureBuildConfiguration(parent, bc, qmakeInfo); + return bc; +} + +ProjectExplorer::BuildConfiguration *IosBuildConfigurationFactory::clone(ProjectExplorer::Target *parent, + ProjectExplorer::BuildConfiguration *source) +{ + if (!canClone(parent, source)) + return nullptr; + auto *oldbc = static_cast(source); + return new IosBuildConfiguration(parent, oldbc); +} + +ProjectExplorer::BuildConfiguration *IosBuildConfigurationFactory::restore(ProjectExplorer::Target *parent, const QVariantMap &map) +{ + if (canRestore(parent, map)) { + std::unique_ptr bc(new IosBuildConfiguration(parent)); + if (bc->fromMap(map)) + return bc.release(); + } + return nullptr; +} + +} // namespace Internal +} // namespace Ios diff --git a/src/plugins/ios/iosbuildconfiguration.h b/src/plugins/ios/iosbuildconfiguration.h new file mode 100644 index 00000000000..2bb94fc529b --- /dev/null +++ b/src/plugins/ios/iosbuildconfiguration.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "qmakeprojectmanager/qmakebuildconfiguration.h" + +namespace ProjectExplorer { +class Target; +class Kit; +class NamedWidget; +} + +namespace Ios { +namespace Internal { + +class IosBuildConfiguration : public QmakeProjectManager::QmakeBuildConfiguration +{ + friend class IosBuildConfigurationFactory; + Q_OBJECT +public: + explicit IosBuildConfiguration(ProjectExplorer::Target *target); + IosBuildConfiguration(ProjectExplorer::Target *target, IosBuildConfiguration *source); + + QList createSubConfigWidgets() override; + QVariantMap toMap() const override; +protected: + bool fromMap(const QVariantMap &map) override; + +private: + void onSigningSettingsChanged(bool autoManagedSigning, QString identifier); + void updateQmakeCommand(); + +private: + QString m_signingIdentifier; + bool m_autoManagedSigning = true; +}; + + +class IosBuildConfigurationFactory : public QmakeProjectManager::QmakeBuildConfigurationFactory +{ +public: + explicit IosBuildConfigurationFactory(QObject *parent = 0); + + int priority(const ProjectExplorer::Kit *k, const QString &projectPath) const override; + int priority(const ProjectExplorer::Target *parent) const override; + + ProjectExplorer::BuildConfiguration *create(ProjectExplorer::Target *parent, const ProjectExplorer::BuildInfo *info) const override; + ProjectExplorer::BuildConfiguration *clone(ProjectExplorer::Target *parent, ProjectExplorer::BuildConfiguration *source) override; + ProjectExplorer::BuildConfiguration *restore(ProjectExplorer::Target *parent, const QVariantMap &map) override; +}; + +} // namespace Internal +} // namespace Ios diff --git a/src/plugins/ios/iosbuildsettingswidget.cpp b/src/plugins/ios/iosbuildsettingswidget.cpp new file mode 100644 index 00000000000..f5c61fea793 --- /dev/null +++ b/src/plugins/ios/iosbuildsettingswidget.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "iosbuildsettingswidget.h" +#include "ui_iosbuildsettingswidget.h" +#include "iosconfigurations.h" +#include "iosconstants.h" + +#include "utils/utilsicons.h" +#include "utils/algorithm.h" +#include "qmakeprojectmanager/qmakeproject.h" +#include "qmakeprojectmanager/qmakenodes.h" +#include "utils/detailswidget.h" + +#include +#include + +using namespace QmakeProjectManager; + +namespace Ios { +namespace Internal { + +namespace { +Q_LOGGING_CATEGORY(iosSettingsLog, "qtc.ios.common") +} + +static const int IdentifierRole = Qt::UserRole+1; + +IosBuildSettingsWidget::IosBuildSettingsWidget(const Core::Id &deviceType, + const QString &signingIdentifier, + bool isSigningAutoManaged, QWidget *parent) : + ProjectExplorer::NamedWidget(parent), + ui(new Ui::IosBuildSettingsWidget), + m_detailsWidget(new Utils::DetailsWidget(this)), + m_deviceType(deviceType) +{ + auto rootLayout = new QVBoxLayout(this); + rootLayout->setMargin(0); + rootLayout->addWidget(m_detailsWidget); + + auto container = new QWidget(m_detailsWidget); + ui->setupUi(container); + ui->m_autoSignCheckbox->setChecked(isSigningAutoManaged); + connect(ui->m_qmakeDefaults, &QPushButton::clicked, this, &IosBuildSettingsWidget::onReset); + + ui->m_infoIconLabel->hide(); + ui->m_infoIconLabel->setPixmap(Utils::Icons::INFO.pixmap()); + ui->m_infoLabel->hide(); + + ui->m_warningIconLabel->hide(); + ui->m_warningIconLabel->setPixmap(Utils::Icons::WARNING.pixmap()); + ui->m_warningLabel->hide(); + + m_detailsWidget->setState(Utils::DetailsWidget::NoSummary); + m_detailsWidget->setWidget(container); + + setDisplayName(tr("iOS Settings")); + + const bool isDevice = m_deviceType == Constants::IOS_DEVICE_TYPE; + if (isDevice) { + connect(IosConfigurations::instance(), &IosConfigurations::provisioningDataChanged, + this, &IosBuildSettingsWidget::populateDevelopmentTeams); + connect(ui->m_signEntityCombo, static_cast(&QComboBox::currentIndexChanged), + this, &IosBuildSettingsWidget::onSigningEntityComboIndexChanged); + connect(ui->m_autoSignCheckbox, &QCheckBox::toggled, + this, &IosBuildSettingsWidget::configureSigningUi); + configureSigningUi(ui->m_autoSignCheckbox->isChecked()); + setDefaultSigningIdentfier(signingIdentifier); + } + + ui->m_autoSignCheckbox->setEnabled(isDevice); + ui->m_signEntityCombo->setEnabled(isDevice); + ui->m_qmakeDefaults->setEnabled(isDevice); + ui->m_signEntityLabel->setEnabled(isDevice); + adjustSize(); +} + +IosBuildSettingsWidget::~IosBuildSettingsWidget() +{ + delete ui; +} + +void IosBuildSettingsWidget::setDefaultSigningIdentfier(const QString &identifier) const +{ + if (identifier.isEmpty()) { + ui->m_signEntityCombo->setCurrentIndex(0); + return; + } + + int defaultIndex = -1; + for (int index = 0; index < ui->m_signEntityCombo->count(); ++index) { + QString teamID = ui->m_signEntityCombo->itemData(index, IdentifierRole).toString(); + if (teamID == identifier) { + defaultIndex = index; + break; + } + } + if (defaultIndex > -1) { + ui->m_signEntityCombo->setCurrentIndex(defaultIndex); + } else { + // Reset to default + ui->m_signEntityCombo->setCurrentIndex(0); + qCDebug(iosSettingsLog) << "Can not find default" + << (ui->m_autoSignCheckbox->isChecked() ? "team": "provisioning profile") + << ". Identifier: " << identifier; + } +} + +bool IosBuildSettingsWidget::isSigningAutomaticallyManaged() const +{ + return ui->m_autoSignCheckbox->isChecked() && ui->m_signEntityCombo->currentIndex() > 0; +} + +void IosBuildSettingsWidget::onSigningEntityComboIndexChanged() +{ + QString identifier = selectedIdentifier(); + (ui->m_autoSignCheckbox->isChecked() ? m_lastTeamSelection : m_lastProfileSelection) = identifier; + + updateInfoText(); + updateWarningText(); + emit signingSettingsChanged(ui->m_autoSignCheckbox->isChecked(), identifier); +} + +void IosBuildSettingsWidget::onReset() +{ + m_lastTeamSelection.clear(); + m_lastProfileSelection.clear(); + ui->m_autoSignCheckbox->setChecked(true); + setDefaultSigningIdentfier(""); +} + +void IosBuildSettingsWidget::configureSigningUi(bool autoManageSigning) +{ + ui->m_signEntityLabel->setText(autoManageSigning ? tr("Development team:") + : tr("Provisioning profile:")); + if (autoManageSigning) + populateDevelopmentTeams(); + else + populateProvisioningProfiles(); + + updateInfoText(); + emit signingSettingsChanged(autoManageSigning, selectedIdentifier()); +} + +void IosBuildSettingsWidget::populateDevelopmentTeams() +{ + // Populate Team id's + ui->m_signEntityCombo->blockSignals(true); + ui->m_signEntityCombo->clear(); + ui->m_signEntityCombo->addItem(tr("Default")); + foreach (auto team, IosConfigurations::developmentTeams()) { + ui->m_signEntityCombo->addItem(team->displayName()); + const int index = ui->m_signEntityCombo->count() - 1; + ui->m_signEntityCombo->setItemData(index, team->identifier(), IdentifierRole); + ui->m_signEntityCombo->setItemData(index, team->details(), Qt::ToolTipRole); + } + ui->m_signEntityCombo->blockSignals(false); + // Maintain previous selection. + setDefaultSigningIdentfier(m_lastTeamSelection); + updateWarningText(); +} + +void IosBuildSettingsWidget::populateProvisioningProfiles() +{ + // Populate Team id's + ui->m_signEntityCombo->blockSignals(true); + ui->m_signEntityCombo->clear(); + ProvisioningProfiles profiles = IosConfigurations::provisioningProfiles(); + if (profiles.count() > 0) { + foreach (auto profile, profiles) { + ui->m_signEntityCombo->addItem(profile->displayName()); + const int index = ui->m_signEntityCombo->count() - 1; + ui->m_signEntityCombo->setItemData(index, profile->identifier(), IdentifierRole); + ui->m_signEntityCombo->setItemData(index, profile->details(), Qt::ToolTipRole); + } + } else { + ui->m_signEntityCombo->addItem(tr("None")); + } + ui->m_signEntityCombo->blockSignals(false); + // Maintain previous selection. + setDefaultSigningIdentfier(m_lastProfileSelection); + updateWarningText(); +} + +QString IosBuildSettingsWidget::selectedIdentifier() const +{ + return ui->m_signEntityCombo->currentData(IdentifierRole).toString(); +} + +void IosBuildSettingsWidget::updateInfoText() +{ + if (m_deviceType != Constants::IOS_DEVICE_TYPE) + return; + + QString infoMessage; + auto addMessage = [&infoMessage](const QString &msg) { + if (!infoMessage.isEmpty()) + infoMessage += "\n"; + infoMessage += msg; + }; + + QString identifier = selectedIdentifier(); + bool configuringTeams = ui->m_autoSignCheckbox->isChecked(); + + if (identifier.isEmpty()) { + // No signing entity selection. + if (configuringTeams) + addMessage(tr("Development team is not selected.")); + else + addMessage(tr("Provisioning profile is not selected.")); + + addMessage(tr("Using default development team and provisioning profile.")); + } else { + if (!configuringTeams) { + ProvisioningProfilePtr profile = IosConfigurations::provisioningProfile(identifier); + QTC_ASSERT(profile, return); + auto team = profile->developmentTeam(); + if (team) { + // Display corresponding team information. + addMessage(tr("Development team: %1 (%2)").arg(team->displayName()) + .arg(team->identifier())); + addMessage(tr("Settings defined here override the QMake environment.")); + } else { + qCDebug(iosSettingsLog) << "Development team not found for profile" << profile; + } + } else { + addMessage(tr("Settings defined here override the QMake environment.")); + } + } + + ui->m_infoIconLabel->setVisible(!infoMessage.isEmpty()); + ui->m_infoLabel->setVisible(!infoMessage.isEmpty()); + ui->m_infoLabel->setText(infoMessage); +} + +void IosBuildSettingsWidget::updateWarningText() +{ + if (m_deviceType != Constants::IOS_DEVICE_TYPE) + return; + + QString warningText; + bool configuringTeams = ui->m_autoSignCheckbox->isChecked(); + if (ui->m_signEntityCombo->count() < 2) { + warningText = tr("%1 not configured. Use Xcode and Apple developer account to configure the " + "provisioning profiles and teams.") + .arg(configuringTeams ? tr("Development teams") : tr("Provisioning profiles")); + } else { + QString identifier = selectedIdentifier(); + if (configuringTeams) { + auto team = IosConfigurations::developmentTeam(identifier); + if (team && !team->hasProvisioningProfile()) + warningText = tr("No provisioning profile found for the selected team."); + } else { + auto profile = IosConfigurations::provisioningProfile(identifier); + if (profile && QDateTime::currentDateTimeUtc() > profile->expirationDate()) { + warningText = tr("Provisioning profile expired. Expiration date: %1") + .arg(profile->expirationDate().toLocalTime().toString(Qt::SystemLocaleLongDate)); + } + } + } + + ui->m_warningLabel->setVisible(!warningText.isEmpty()); + ui->m_warningIconLabel->setVisible(!warningText.isEmpty()); + ui->m_warningLabel->setText(warningText); +} + +} // namespace Internal +} // namespace Ios diff --git a/src/plugins/ios/iosbuildsettingswidget.h b/src/plugins/ios/iosbuildsettingswidget.h new file mode 100644 index 00000000000..6460599c616 --- /dev/null +++ b/src/plugins/ios/iosbuildsettingswidget.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "coreplugin/id.h" +#include "projectexplorer/namedwidget.h" + +#include + +namespace Utils { +class DetailsWidget; +} + + +namespace Ios { +namespace Internal { +namespace Ui { + class IosBuildSettingsWidget; +} + +class IosBuildSettingsWidget : public ProjectExplorer::NamedWidget +{ + Q_OBJECT + +public: + explicit IosBuildSettingsWidget(const Core::Id &deviceType, const QString &signingIdentifier, + bool isSigningAutoManaged, QWidget *parent = 0); + ~IosBuildSettingsWidget(); + +public: + bool isSigningAutomaticallyManaged() const; + +private slots: + void onSigningEntityComboIndexChanged(); + void onReset(); + +signals: + void signingSettingsChanged(bool isAutoManaged, QString identifier); + +private: + void setDefaultSigningIdentfier(const QString &identifier) const; + void configureSigningUi(bool autoManageSigning); + void populateDevelopmentTeams(); + void populateProvisioningProfiles(); + QString selectedIdentifier() const; + void updateInfoText(); + void updateWarningText(); + +private: + Ui::IosBuildSettingsWidget *ui; + Utils::DetailsWidget *m_detailsWidget; + QString m_lastProfileSelection; + QString m_lastTeamSelection; + const Core::Id m_deviceType; +}; + +} // namespace Internal +} // namespace Ios diff --git a/src/plugins/ios/iosbuildsettingswidget.ui b/src/plugins/ios/iosbuildsettingswidget.ui new file mode 100644 index 00000000000..3ad4928a893 --- /dev/null +++ b/src/plugins/ios/iosbuildsettingswidget.ui @@ -0,0 +1,137 @@ + + + Ios::Internal::IosBuildSettingsWidget + + + + 0 + 0 + 467 + 141 + + + + Form + + + + + + + + + 0 + 0 + + + + Reset + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Automatically manage signing + + + true + + + + + + + Development team: + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + + + + false + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + + + + true + + + + + + + + + + diff --git a/src/plugins/ios/iosplugin.cpp b/src/plugins/ios/iosplugin.cpp index 761326ba05c..28e590167e0 100644 --- a/src/plugins/ios/iosplugin.cpp +++ b/src/plugins/ios/iosplugin.cpp @@ -25,6 +25,7 @@ #include "iosplugin.h" +#include "iosbuildconfiguration.h" #include "iosbuildstep.h" #include "iosconfigurations.h" #include "iosconstants.h" @@ -64,6 +65,7 @@ bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage) Internal::IosConfigurations::initialize(); + addAutoReleasedObject(new Internal::IosBuildConfigurationFactory); addAutoReleasedObject(new Internal::IosToolChainFactory); addAutoReleasedObject(new Internal::IosRunControlFactory); addAutoReleasedObject(new Internal::IosRunConfigurationFactory); From 5d1e12faad81aa5d7dc555829afa798b1c570d9c Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 14 Mar 2017 20:25:06 +0200 Subject: [PATCH 36/56] iOS: Fix compilation Change-Id: Ieb5357a25240a64c4461325cc7165b68df3e71b9 Reviewed-by: Jake Petroules --- src/plugins/ios/iosconfigurations.cpp | 4 ++-- src/plugins/ios/iosconfigurations.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp index 4a6e004da1d..566fcc9fef4 100644 --- a/src/plugins/ios/iosconfigurations.cpp +++ b/src/plugins/ios/iosconfigurations.cpp @@ -489,7 +489,7 @@ void IosConfigurations::loadProvisioningData(bool notify) }); foreach (auto teamInfo, teams) { - auto team = std::shared_ptr::make_shared(); + auto team = std::make_shared(); team->m_name = teamInfo.value(teamNameTag).toString(); team->m_email = teamInfo.value(emailTag).toString(); team->m_identifier = teamInfo.value(teamIdTag).toString(); @@ -500,7 +500,7 @@ void IosConfigurations::loadProvisioningData(bool notify) const QDir provisioningProflesDir(provisioningProfileDirPath); foreach (QFileInfo fileInfo, provisioningProflesDir.entryInfoList({"*.mobileprovision"}, QDir::NoDotAndDotDot | QDir::Files)) { QDomDocument provisioningDoc; - auto profile = ProvisioningProfilePtr::make_shared();; + auto profile = std::make_shared(); QString teamID; if (provisioningDoc.setContent(decodeProvisioningProfile(fileInfo.absoluteFilePath()))) { QDomNodeList nodes = provisioningDoc.elementsByTagName("key"); diff --git a/src/plugins/ios/iosconfigurations.h b/src/plugins/ios/iosconfigurations.h index a4e1163b01f..f5f5f9798d5 100644 --- a/src/plugins/ios/iosconfigurations.h +++ b/src/plugins/ios/iosconfigurations.h @@ -35,6 +35,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE class QSettings; class QFileSystemWatcher; From df73d572951ce5d46471bef4090f90f25cf01978 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 14 Mar 2017 11:18:09 +0100 Subject: [PATCH 37/56] QmlProject: Simplify interface a bit Remove unneeded code and don't repeately fetch a singleton value. Change-Id: I718a44c28be7ef8718f813f987f45b32cbcd7ad5 Reviewed-by: Tim Jenssen --- src/plugins/qmlprojectmanager/qmlproject.cpp | 34 ++++++-------------- src/plugins/qmlprojectmanager/qmlproject.h | 3 -- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp index 587059f80fc..bb88cc898eb 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.cpp +++ b/src/plugins/qmlprojectmanager/qmlproject.cpp @@ -145,8 +145,8 @@ void QmlProject::parseProject(RefreshOptions options) } if (m_projectItem) { m_projectItem.data()->setSourceDirectory(projectDir().path()); - if (modelManager()) - modelManager()->updateSourceFiles(m_projectItem.data()->files(), true); + if (auto modelManager = QmlJS::ModelManagerInterface::instance()) + modelManager->updateSourceFiles(m_projectItem.data()->files(), true); QString mainFilePath = m_projectItem.data()->mainFile(); if (!mainFilePath.isEmpty()) { @@ -180,37 +180,21 @@ void QmlProject::refresh(RefreshOptions options) if (options & Files) generateProjectTree(); - if (!modelManager()) + auto modelManager = QmlJS::ModelManagerInterface::instance(); + if (!modelManager) return; QmlJS::ModelManagerInterface::ProjectInfo projectInfo = - modelManager()->defaultProjectInfoForProject(this); + modelManager->defaultProjectInfoForProject(this); foreach (const QString &searchPath, customImportPaths()) projectInfo.importPaths.maybeInsert(Utils::FileName::fromString(searchPath), QmlJS::Dialect::Qml); - modelManager()->updateProjectInfo(projectInfo, this); + modelManager->updateProjectInfo(projectInfo, this); emit parsingFinished(); } -QStringList QmlProject::convertToAbsoluteFiles(const QStringList &paths) const -{ - const QDir projectDir(projectDirectory().toString()); - QStringList absolutePaths; - foreach (const QString &file, paths) { - QFileInfo fileInfo(projectDir, file); - absolutePaths.append(fileInfo.absoluteFilePath()); - } - absolutePaths.removeDuplicates(); - return absolutePaths; -} - -QmlJS::ModelManagerInterface *QmlProject::modelManager() const -{ - return QmlJS::ModelManagerInterface::instance(); -} - QStringList QmlProject::files() const { QStringList files; @@ -265,8 +249,10 @@ QmlProject::QmlImport QmlProject::defaultImport() const void QmlProject::refreshFiles(const QSet &/*added*/, const QSet &removed) { refresh(Files); - if (!removed.isEmpty() && modelManager()) - modelManager()->removeFiles(removed.toList()); + if (!removed.isEmpty()) { + if (auto modelManager = QmlJS::ModelManagerInterface::instance()) + modelManager->removeFiles(removed.toList()); + } } QString QmlProject::displayName() const diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h index 8bf4f35bc50..c8900b6ebe1 100644 --- a/src/plugins/qmlprojectmanager/qmlproject.h +++ b/src/plugins/qmlprojectmanager/qmlproject.h @@ -33,7 +33,6 @@ #include namespace ProjectExplorer { class RunConfiguration; } -namespace QmlJS { class ModelManagerInterface; } namespace QmlProjectManager { @@ -91,8 +90,6 @@ private: // plain format void parseProject(RefreshOptions options); - QStringList convertToAbsoluteFiles(const QStringList &paths) const; - QmlJS::ModelManagerInterface *modelManager() const; QmlImport m_defaultImport; ProjectExplorer::Target *m_activeTarget = 0; From 5e43e6c6ae66fdca25f89356c35e4433a51710d9 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 14 Mar 2017 13:03:06 +0100 Subject: [PATCH 38/56] QmlDesigner: Disable QML compiler for tests Change-Id: Ia0c9a0241b5c2dd11a3a0c0f667adcdef9706191 Reviewed-by: Tim Jenssen --- tests/auto/qml/qmldesigner/coretests/coretests.pro | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/auto/qml/qmldesigner/coretests/coretests.pro b/tests/auto/qml/qmldesigner/coretests/coretests.pro index bdf97a1ce0a..fbc7f4f0e2e 100644 --- a/tests/auto/qml/qmldesigner/coretests/coretests.pro +++ b/tests/auto/qml/qmldesigner/coretests/coretests.pro @@ -14,6 +14,8 @@ QTC_PLUGIN_DEPENDS += \ qmljseditor \ qmakeprojectmanager +CONFIG -= qtquickcompiler + include(../../../qttest.pri) QT += qml network core-private From 73f83089599497f584407907af20cca825e939d4 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 14 Mar 2017 15:58:36 +0100 Subject: [PATCH 39/56] QmlDesigner: Only change selection if required This avoids sending selection changed notifications. Change-Id: I2303941f388495e98171ef40dce2ee12739f7dcd Reviewed-by: Tim Jenssen --- .../qmldesigner/components/texteditor/texteditorwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp index 0d89af30e78..e645ad2ef6a 100644 --- a/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp +++ b/src/plugins/qmldesigner/components/texteditor/texteditorwidget.cpp @@ -104,7 +104,7 @@ void TextEditorWidget::updateSelectionByCursorPosition() if (rewriterView) { ModelNode modelNode = rewriterView->nodeAtTextCursorPosition(cursorPosition); - if (modelNode.isValid()) + if (modelNode.isValid() && !m_textEditorView->isSelectedModelNode(modelNode)) m_textEditorView->setSelectedModelNode(modelNode); } } From b3238d57361bde667ea890b60a04c075eec2e952 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 14 Mar 2017 15:59:17 +0100 Subject: [PATCH 40/56] QmlDesigner: Fix nodeAtTextCursorPositionRekursive() If the length is -1 then the document is invalid and we should return an invalid model node. Change-Id: Id2a329a16617f862a518a3c1f00f9078697d72d8 Reviewed-by: Tim Jenssen --- src/plugins/qmldesigner/designercore/model/rewriterview.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp index 4c58b573f48..1eff8b446fa 100644 --- a/src/plugins/qmldesigner/designercore/model/rewriterview.cpp +++ b/src/plugins/qmldesigner/designercore/model/rewriterview.cpp @@ -582,6 +582,10 @@ ModelNode RewriterView::nodeAtTextCursorPositionRekursive(const ModelNode &root, const int nodeTextLength = nodeLength(node); const int nodeTextOffset = nodeOffset(node); + + if (nodeTextLength < 0) + return ModelNode(); + if (isInNodeDefinition(nodeTextOffset, nodeTextLength, cursorPosition)) return node; From b8417e0f0c57b2646c190bdb177b8e9a61e1ee41 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 13 Mar 2017 18:13:47 +0100 Subject: [PATCH 41/56] CMake: Fix projects with complex CMakeLists.txt layouts This fixes soft assserts in e.g. Musescore. Change-Id: I860c8c184161e53918fb901d66b89cffb0c09e23 Reviewed-by: Tim Jenssen --- .../cmakebuildconfiguration.cpp | 2 +- .../cmakeprojectmanager/servermodereader.cpp | 84 ++++--------------- src/plugins/projectexplorer/projectnodes.cpp | 15 ++-- src/plugins/projectexplorer/projectnodes.h | 7 +- 4 files changed, 29 insertions(+), 79 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index f33ecf164a8..78f11b0b27d 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -218,7 +218,7 @@ QList CMakeBuildConfiguration::buildTargets() const CMakeListsNode * CMakeBuildConfiguration::generateProjectTree(const QList &allFiles) const { - auto root = new CMakeListsNode(target()->project()->projectFilePath()); + auto root = new CMakeListsNode(target()->project()->projectDirectory()); if (!m_buildDirManager || m_buildDirManager->isParsing()) return nullptr; diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index bcc809e295f..19ec690ba06 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -531,87 +531,31 @@ void ServerModeReader::addCMakeLists(CMakeListsNode *root, const QList nodeHash; - for (FileNode *cm : cmakeLists) { - const QString relPath = baseDir.relativeFilePath(cm->filePath().parentDir().toString()); - QTC_CHECK(!nodeHash.contains(relPath)); - nodeHash[(relPath == ".") ? QString() : relPath ] = cm; - } - QStringList tmp = nodeHash.keys(); - Utils::sort(tmp, [](const QString &a, const QString &b) { return a.count() < b.count(); }); - const QStringList keys = tmp; - - QHash knownNodes; - knownNodes[QString()] = root; - - for (const QString &k : keys) { - FileNode *fn = nodeHash[k]; - CMakeListsNode *parentNode = nullptr; - QString prefix = k; - forever { - if (knownNodes.contains(prefix)) { - parentNode = knownNodes.value(prefix); - break; - } - const int pos = prefix.lastIndexOf('/'); - prefix = (pos < 0) ? QString() : prefix.left(prefix.lastIndexOf('/')); - } - - // Find or create CMakeListsNode: - CMakeListsNode *cmln = nullptr; - if (parentNode->filePath() == fn->filePath()) - cmln = parentNode; // Top level! + root->addNestedNodes(cmakeLists, Utils::FileName(), + [&cmakeLists](const Utils::FileName &fp) -> ProjectExplorer::FolderNode * { + if (Utils::contains(cmakeLists, [&fp](const FileNode *fn) { return fn->filePath().parentDir() == fp; })) + return new CMakeListsNode(fp); else - cmln = static_cast(parentNode->projectNode(fn->filePath())); - if (!cmln) { - cmln = new CMakeListsNode(fn->filePath()); - parentNode->addNode(cmln); - } - - // Find or create CMakeLists.txt filenode below CMakeListsNode: - FileNode *cmFn = cmln->fileNode(fn->filePath()); - if (!cmFn) { - cmFn = fn; - cmln->addNode(cmFn); - } - // Update displayName of CMakeListsNode: - const QString dn = prefix.isEmpty() ? k : k.mid(prefix.count() + 1); - if (!dn.isEmpty()) - cmln->setDisplayName(dn); // Set partial path as display name - - knownNodes.insert(k, cmln); - } + return new FolderNode(fp); + }); } static CMakeListsNode *findCMakeNode(CMakeListsNode *root, const Utils::FileName &dir) { const Utils::FileName stepDir = dir; - const Utils::FileName topDir = root->filePath().parentDir(); + const Utils::FileName topDir = root->filePath(); QStringList relative = stepDir.relativeChildPath(topDir).toString().split('/', QString::SkipEmptyParts); - CMakeListsNode *result = root; - - QString relativePathElement; + FolderNode *result = root; while (!relative.isEmpty()) { - const QString nextDirPath = result->filePath().parentDir().toString(); - Utils::FileName nextFullPath; - // Some directory may not contain CMakeLists.txt file, skip it: - do { - relativePathElement += '/' + relative.takeFirst(); - nextFullPath = Utils::FileName::fromString(nextDirPath + relativePathElement + "/CMakeLists.txt"); - } while (!nextFullPath.exists() && !relative.isEmpty()); - result = static_cast(result->projectNode(nextFullPath)); - // Intermediate directory can contain CMakeLists.txt file - // that is not a part of the root node, skip it: - if (!result && !relative.isEmpty()) { - result = root; - } else { - relativePathElement.clear(); - } - QTC_ASSERT(result, return nullptr); + Utils::FileName nextFullPath = result->filePath(); + nextFullPath.appendPath(relative.takeFirst()); + result = findOrDefault(result->folderNodes(), Utils::equal(&FolderNode::filePath, nextFullPath)); + if (!result) + return nullptr; } - return result; + return dynamic_cast(result); } static CMakeProjectNode *findOrCreateProjectNode(CMakeListsNode *root, const Utils::FileName &dir, diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 8067795304f..099ff9b76ad 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -60,7 +60,8 @@ static FolderNode *folderNode(const FolderNode *folder, const Utils::FileName &d static FolderNode *recursiveFindOrCreateFolderNode(FolderNode *folder, const Utils::FileName &directory, - const Utils::FileName &overrideBaseDir) + const Utils::FileName &overrideBaseDir, + const FolderNode::FolderNodeFactory &factory) { Utils::FileName path = overrideBaseDir.isEmpty() ? folder->filePath() : overrideBaseDir; @@ -90,7 +91,7 @@ static FolderNode *recursiveFindOrCreateFolderNode(FolderNode *folder, FolderNode *next = folderNode(parent, path); if (!next) { // No FolderNode yet, so create it - auto tmp = new ProjectExplorer::FolderNode(path); + auto tmp = factory(path); tmp->setDisplayName(part); parent->addNode(tmp); next = tmp; @@ -460,20 +461,22 @@ QList FolderNode::folderNodes() const return result; } -void FolderNode::addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir) +void FolderNode::addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir, + const FolderNodeFactory &factory) { // Get relative path to rootNode QString parentDir = fileNode->filePath().toFileInfo().absolutePath(); FolderNode *folder = recursiveFindOrCreateFolderNode(this, Utils::FileName::fromString(parentDir), - overrideBaseDir); + overrideBaseDir, factory); folder->addNode(fileNode); } -void FolderNode::addNestedNodes(QList &files, const Utils::FileName &overrideBaseDir) +void FolderNode::addNestedNodes(const QList &files, const Utils::FileName &overrideBaseDir, + const FolderNodeFactory &factory) { for (FileNode *fn : files) - addNestedNode(fn, overrideBaseDir); + addNestedNode(fn, overrideBaseDir, factory); } // "Compress" a tree of foldernodes such that foldernodes with exactly one foldernode as a child diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index aa5b9e397f2..9ac9d678cce 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -200,8 +200,11 @@ public: QList fileNodes() const; FileNode *fileNode(const Utils::FileName &file) const; QList folderNodes() const; - void addNestedNodes(QList &files, const Utils::FileName &overrideBaseDir = Utils::FileName()); - void addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir = Utils::FileName()); + using FolderNodeFactory = std::function; + void addNestedNodes(const QList &files, const Utils::FileName &overrideBaseDir = Utils::FileName(), + const FolderNodeFactory &factory = [](const Utils::FileName &fn) { return new FolderNode(fn); }); + void addNestedNode(FileNode *fileNode, const Utils::FileName &overrideBaseDir = Utils::FileName(), + const FolderNodeFactory &factory = [](const Utils::FileName &fn) { return new FolderNode(fn); }); void compress(); bool isAncesterOf(Node *n); From 6e91fe5046dd87613062257b095104d5a33a8e1e Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 14 Mar 2017 15:35:02 +0100 Subject: [PATCH 42/56] CMake: Use a CMakeProjectNode as top level cmake node Change-Id: I6e68b971cf490b9b064a2866bd99865a7f4a7bd9 Reviewed-by: Tim Jenssen --- .../cmakeprojectmanager/builddirmanager.cpp | 2 +- .../cmakeprojectmanager/builddirmanager.h | 2 +- src/plugins/cmakeprojectmanager/builddirreader.h | 4 ++-- .../cmakebuildconfiguration.cpp | 4 ++-- .../cmakebuildconfiguration.h | 4 ++-- .../cmakeprojectmanager/servermodereader.cpp | 16 ++++++++-------- .../cmakeprojectmanager/servermodereader.h | 10 ++++++---- .../cmakeprojectmanager/tealeafreader.cpp | 2 +- src/plugins/cmakeprojectmanager/tealeafreader.h | 2 +- src/plugins/projectexplorer/project.cpp | 2 +- 10 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index 1cce3d8a370..f3e039cd375 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -257,7 +257,7 @@ bool BuildDirManager::persistCMakeState() return true; } -void BuildDirManager::generateProjectTree(CMakeListsNode *root, const QList &allFiles) +void BuildDirManager::generateProjectTree(CMakeProjectNode *root, const QList &allFiles) { QTC_ASSERT(m_reader, return); diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.h b/src/plugins/cmakeprojectmanager/builddirmanager.h index 85b95884648..4446c3f03f2 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.h +++ b/src/plugins/cmakeprojectmanager/builddirmanager.h @@ -69,7 +69,7 @@ public: bool updateCMakeStateBeforeBuild(); bool persistCMakeState(); - void generateProjectTree(CMakeListsNode *root, + void generateProjectTree(CMakeProjectNode *root, const QList &allFiles); void updateCodeModel(CppTools::RawProjectParts &rpps); diff --git a/src/plugins/cmakeprojectmanager/builddirreader.h b/src/plugins/cmakeprojectmanager/builddirreader.h index b13de736f20..42630c5e13a 100644 --- a/src/plugins/cmakeprojectmanager/builddirreader.h +++ b/src/plugins/cmakeprojectmanager/builddirreader.h @@ -42,7 +42,7 @@ namespace CMakeProjectManager { namespace Internal { class CMakeBuildConfiguration; -class CMakeListsNode; +class CMakeProjectNode; class BuildDirReader : public QObject { @@ -95,7 +95,7 @@ public: virtual CMakeConfig takeParsedConfiguration() = 0; virtual QList buildTargets() const = 0; - virtual void generateProjectTree(CMakeListsNode *root, + virtual void generateProjectTree(CMakeProjectNode *root, const QList &allFiles) = 0; virtual void updateCodeModel(CppTools::RawProjectParts &rpps) = 0; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index 78f11b0b27d..6db04c5287a 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -215,13 +215,13 @@ QList CMakeBuildConfiguration::buildTargets() const return m_buildDirManager->buildTargets(); } -CMakeListsNode * +CMakeProjectNode * CMakeBuildConfiguration::generateProjectTree(const QList &allFiles) const { - auto root = new CMakeListsNode(target()->project()->projectDirectory()); if (!m_buildDirManager || m_buildDirManager->isParsing()) return nullptr; + auto root = new CMakeProjectNode(target()->project()->projectDirectory()); m_buildDirManager->generateProjectTree(root, allFiles); return root; } diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h index 3ebc2e80bb0..c97cd0f33ae 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h @@ -47,7 +47,7 @@ namespace Internal { class BuildDirManager; class CMakeBuildConfigurationFactory; class CMakeBuildSettingsWidget; -class CMakeListsNode; +class CMakeProjectNode; class CMakeBuildConfiguration : public ProjectExplorer::BuildConfiguration { @@ -86,7 +86,7 @@ public: void clearCache(); QList buildTargets() const; - CMakeListsNode *generateProjectTree(const QList &allFiles) const; + CMakeProjectManager::Internal::CMakeProjectNode *generateProjectTree(const QList &allFiles) const; void updateCodeModel(CppTools::RawProjectParts &rpps); static Utils::FileName diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index 19ec690ba06..93f719b272d 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -231,7 +231,7 @@ static void addCMakeVFolder(FolderNode *base, const Utils::FileName &basePath, i fn->compress(); } -static void addCMakeInputs(CMakeListsNode *root, +static void addCMakeInputs(FolderNode *root, const Utils::FileName &sourceDir, const Utils::FileName &buildDir, QList &sourceInputs, @@ -252,7 +252,7 @@ static void addCMakeInputs(CMakeListsNode *root, rootInputs); } -void ServerModeReader::generateProjectTree(CMakeListsNode *root, +void ServerModeReader::generateProjectTree(CMakeProjectNode *root, const QList &allFiles) { // Split up cmake inputs into useful chunks: @@ -527,7 +527,7 @@ void ServerModeReader::extractCacheData(const QVariantMap &data) m_cmakeCache = config; } -void ServerModeReader::addCMakeLists(CMakeListsNode *root, const QList &cmakeLists) +void ServerModeReader::addCMakeLists(CMakeProjectNode *root, const QList &cmakeLists) { const QDir baseDir = QDir(m_parameters.sourceDirectory.toString()); @@ -540,7 +540,7 @@ void ServerModeReader::addCMakeLists(CMakeListsNode *root, const QListfilePath(); @@ -558,7 +558,7 @@ static CMakeListsNode *findCMakeNode(CMakeListsNode *root, const Utils::FileName return dynamic_cast(result); } -static CMakeProjectNode *findOrCreateProjectNode(CMakeListsNode *root, const Utils::FileName &dir, +static CMakeProjectNode *findOrCreateProjectNode(FolderNode *root, const Utils::FileName &dir, const QString &displayName) { CMakeListsNode *cmln = findCMakeNode(root, dir); @@ -576,7 +576,7 @@ static CMakeProjectNode *findOrCreateProjectNode(CMakeListsNode *root, const Uti return pn; } -void ServerModeReader::addProjects(CMakeListsNode *root, +void ServerModeReader::addProjects(CMakeProjectNode *root, const QList &projects, const QList &allFiles) { @@ -595,7 +595,7 @@ void ServerModeReader::addProjects(CMakeListsNode *root, } } -static CMakeTargetNode *findOrCreateTargetNode(CMakeListsNode *root, const Utils::FileName &dir, +static CMakeTargetNode *findOrCreateTargetNode(FolderNode *root, const Utils::FileName &dir, const QString &displayName) { CMakeListsNode *cmln = findCMakeNode(root, dir); @@ -613,7 +613,7 @@ static CMakeTargetNode *findOrCreateTargetNode(CMakeListsNode *root, const Utils return tn; } -void ServerModeReader::addTargets(CMakeListsNode *root, +void ServerModeReader::addTargets(CMakeProjectNode *root, const QList &targets, const QHash> &headers) { diff --git a/src/plugins/cmakeprojectmanager/servermodereader.h b/src/plugins/cmakeprojectmanager/servermodereader.h index d58103c326e..8b973ce0ecd 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.h +++ b/src/plugins/cmakeprojectmanager/servermodereader.h @@ -33,6 +33,8 @@ namespace CMakeProjectManager { namespace Internal { +class CMakeListsNode; + class ServerModeReader : public BuildDirReader { Q_OBJECT @@ -54,7 +56,7 @@ public: QList buildTargets() const final; CMakeConfig takeParsedConfiguration() final; - void generateProjectTree(CMakeListsNode *root, + void generateProjectTree(CMakeProjectNode *root, const QList &allFiles) final; void updateCodeModel(CppTools::RawProjectParts &rpps) final; @@ -111,10 +113,10 @@ private: void extractCMakeInputsData(const QVariantMap &data); void extractCacheData(const QVariantMap &data); - void addCMakeLists(CMakeListsNode *root, const QList &cmakeLists); - void addProjects(CMakeListsNode *root, const QList &projects, + void addCMakeLists(CMakeProjectNode *root, const QList &cmakeLists); + void addProjects(CMakeProjectNode *root, const QList &projects, const QList &allFiles); - void addTargets(CMakeListsNode *root, const QList &targets, + void addTargets(CMakeProjectNode *root, const QList &targets, const QHash> &headers); void addFileGroups(ProjectExplorer::ProjectNode *targetRoot, const Utils::FileName &sourceDirectory, diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index e7f7a20b09f..da7d07c00fb 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -264,7 +264,7 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration() return result; } -void TeaLeafReader::generateProjectTree(CMakeListsNode *root, const QList &allFiles) +void TeaLeafReader::generateProjectTree(CMakeProjectNode *root, const QList &allFiles) { root->setDisplayName(m_projectName); diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.h b/src/plugins/cmakeprojectmanager/tealeafreader.h index 3aa258580a5..9853a1b0a2b 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.h +++ b/src/plugins/cmakeprojectmanager/tealeafreader.h @@ -56,7 +56,7 @@ public: QList buildTargets() const final; CMakeConfig takeParsedConfiguration() final; - void generateProjectTree(CMakeListsNode *root, + void generateProjectTree(CMakeProjectNode *root, const QList &allFiles) final; void updateCodeModel(CppTools::RawProjectParts &rpps) final; diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 43870201dbd..6c97502dd6b 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -419,7 +419,7 @@ void Project::setDocument(Core::IDocument *doc) d->m_document = doc; if (!d->m_rootProjectNode) { - auto newRoot = new ProjectNode(projectDirectory()); + auto newRoot = new ProjectNode(projectFilePath()); newRoot->setDisplayName(displayName()); newRoot->addNode(new FileNode(projectFilePath(), FileType::Project, false)); setRootProjectNode(newRoot); From 1621aaa26eff78f17ef3cbd61fed5a6ca859046b Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 14 Mar 2017 16:21:33 +0100 Subject: [PATCH 43/56] CMake: Fix some more SOFT-ASSERTS in CMake server-mode Fix two more SOFT-ASSERTs in CMake server-mode that could be triggered by complex projects. Move and simplify search functionality into FolderNode and use that instead of hand-crafting a custom tree search in CMake. Change-Id: If4bde5c4a7ff84c7d5dba4f595e99b39f54ac8aa Reviewed-by: Tim Jenssen --- .../cmakeprojectmanager/servermodereader.cpp | 31 ++++++------------- src/plugins/projectexplorer/projectnodes.cpp | 31 +++++++++++++++++++ src/plugins/projectexplorer/projectnodes.h | 3 ++ 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index 93f719b272d..6bb09612f1d 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -540,28 +540,16 @@ void ServerModeReader::addCMakeLists(CMakeProjectNode *root, const QListfilePath(); - - QStringList relative = stepDir.relativeChildPath(topDir).toString().split('/', QString::SkipEmptyParts); - - FolderNode *result = root; - while (!relative.isEmpty()) { - Utils::FileName nextFullPath = result->filePath(); - nextFullPath.appendPath(relative.takeFirst()); - result = findOrDefault(result->folderNodes(), Utils::equal(&FolderNode::filePath, nextFullPath)); - if (!result) - return nullptr; - } - return dynamic_cast(result); + Node *n = root->findNode([&dir](Node *n) { return n->asProjectNode() && n->filePath() == dir; }); + return n ? n->asProjectNode() : nullptr; } -static CMakeProjectNode *findOrCreateProjectNode(FolderNode *root, const Utils::FileName &dir, - const QString &displayName) +static ProjectNode *findOrCreateProjectNode(ProjectNode *root, const Utils::FileName &dir, + const QString &displayName) { - CMakeListsNode *cmln = findCMakeNode(root, dir); + ProjectNode *cmln = findCMakeNode(root, dir); QTC_ASSERT(cmln, return nullptr); Utils::FileName projectName = dir; @@ -588,17 +576,16 @@ void ServerModeReader::addProjects(CMakeProjectNode *root, } for (const Project *p : projects) { - CMakeProjectNode *pNode = findOrCreateProjectNode(root, p->sourceDirectory, p->name); + ProjectNode *pNode = findOrCreateProjectNode(root, p->sourceDirectory, p->name); QTC_ASSERT(pNode, continue); - QTC_ASSERT(root, continue); addTargets(root, p->targets, includeFiles); } } -static CMakeTargetNode *findOrCreateTargetNode(FolderNode *root, const Utils::FileName &dir, +static CMakeTargetNode *findOrCreateTargetNode(ProjectNode *root, const Utils::FileName &dir, const QString &displayName) { - CMakeListsNode *cmln = findCMakeNode(root, dir); + ProjectNode *cmln = findCMakeNode(root, dir); QTC_ASSERT(cmln, return nullptr); Utils::FileName targetName = dir; diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 099ff9b76ad..d0fbf0b2767 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -401,6 +401,37 @@ QIcon FolderNode::icon() const return m_icon; } +Node *FolderNode::findNode(const std::function &filter) +{ + if (filter(this)) + return this; + + for (Node *n : m_nodes) { + if (n->asFileNode() && filter(n)) { + return n; + } else if (FolderNode *folder = n->asFolderNode()) { + Node *result = folder->findNode(filter); + if (result) + return result; + } + } + return nullptr; +} + +QList FolderNode::findNodes(const std::function &filter) +{ + QList result; + if (filter(this)) + result.append(this); + for (Node *n : m_nodes) { + if (n->asFileNode() && filter(n)) + result.append(n); + else if (FolderNode *folder = n->asFolderNode()) + result.append(folder->findNode(filter)); + } + return result; +} + void FolderNode::forEachNode(const std::function &fileTask, const std::function &folderTask, const std::function &folderFilterTask) const diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index 9ac9d678cce..03858db5e73 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -192,6 +192,9 @@ public: QString displayName() const override; QIcon icon() const; + Node *findNode(const std::function &filter); + QList findNodes(const std::function &filter); + void forEachNode(const std::function &fileTask, const std::function &folderTask = {}, const std::function &folderFilterTask = {}) const; From 423cca3521d83541917615716f2fa20e5abc340e Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 14 Mar 2017 23:04:23 +0200 Subject: [PATCH 44/56] Qmake: Fix "Build File" for initial opened file If a session contains an open file, when Qt Creator loads this session on startup, Build File is invisible, and doesn't work. Change-Id: Icbc918a4b74f6293d100c04bae0a070d99ce7196 Reviewed-by: Tobias Hunger --- src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp index a771f344d54..9641c289e48 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp @@ -357,6 +357,7 @@ void QmakeProjectManagerPlugin::updateContextActions() m_subProjectRebuildSeparator->setVisible(subProjectActionsVisible && isProjectNode); m_rebuildSubProjectContextMenu->setVisible(subProjectActionsVisible && isProjectNode); m_cleanSubProjectContextMenu->setVisible(subProjectActionsVisible && isProjectNode); + m_buildFileAction->setVisible(buildFilePossible); m_buildSubProjectAction->setEnabled(enabled); m_rebuildSubProjectAction->setEnabled(enabled); From 181766c41daefebec524d2e79dc07b9280e51c41 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 14 Mar 2017 22:53:51 +0200 Subject: [PATCH 45/56] Qmake: Fix "Build File" for sub-projects in pri For example, locatorwidget.cpp which is in locator.pri under coreplugin.pro. Change-Id: I93e6d06ad19b14280c6c3c9e701c64dca3a51856 Reviewed-by: Tobias Hunger --- src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp index 4a54beadd52..766e9513450 100644 --- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp @@ -216,9 +216,11 @@ void QmakeManager::handleSubDirContextMenu(QmakeManager::Action action, bool isF if (!contextNode || !buildableFile) isFileBuild = false; - if (QmakeProFileNode *profile = dynamic_cast(contextNode)) { - if (profile != contextProject->rootProjectNode() || isFileBuild) - bc->setSubNodeBuild(profile); + if (QmakePriFileNode *prifile = dynamic_cast(contextNode)) { + if (QmakeProFileNode *profile = prifile->proFileNode()) { + if (profile != contextProject->rootProjectNode() || isFileBuild) + bc->setSubNodeBuild(profile->proFileNode()); + } } if (isFileBuild) From 831864c56c0aaee4e03cd38aba59590ae2d5b3ea Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 14 Mar 2017 15:38:02 +0100 Subject: [PATCH 46/56] ProjectExplorer: Report VCS topics in all cases Report VCS topics when the top level project node is a file or a directory. Task-number: QTCREATORBUG-17498 Change-Id: Ie20109b228afc79bfc2ac21505a8798d9fd5efd6 Reviewed-by: Orgad Shaneh --- src/plugins/projectexplorer/projectnodes.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index d0fbf0b2767..413d722bd2b 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -703,7 +703,8 @@ ProjectNode::ProjectNode(const Utils::FileName &projectFilePath) : QString ProjectNode::vcsTopic() const { - const QString dir = filePath().toFileInfo().absolutePath(); + const QFileInfo fi = filePath().toFileInfo(); + const QString dir = fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath(); if (Core::IVersionControl *const vc = Core::VcsManager::findVersionControlForDirectory(dir)) From 802eff34850a4d0e648d87069ad5d4790c08ee86 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Mon, 27 Feb 2017 14:46:45 +0100 Subject: [PATCH 47/56] CppTools: Add target information to ProjectPart This is important to be able to map sources to actual things that are going to be built. Change-Id: I1aef940767d60192642ed79a1703cff8dfdad9e1 Reviewed-by: Tim Jenssen Reviewed-by: Christian Stenger --- src/plugins/cmakeprojectmanager/servermodereader.cpp | 1 + src/plugins/cmakeprojectmanager/tealeafreader.cpp | 1 + src/plugins/cppeditor/cppcodemodelinspectordialog.cpp | 4 ++++ src/plugins/cpptools/cppprojectinfogenerator.cpp | 1 + src/plugins/cpptools/cpprawprojectpart.cpp | 5 +++++ src/plugins/cpptools/cpprawprojectpart.h | 2 ++ src/plugins/cpptools/projectpart.h | 1 + src/plugins/qbsprojectmanager/qbsproject.cpp | 1 + src/plugins/qmakeprojectmanager/qmakeproject.cpp | 1 + 9 files changed, 17 insertions(+) diff --git a/src/plugins/cmakeprojectmanager/servermodereader.cpp b/src/plugins/cmakeprojectmanager/servermodereader.cpp index 6bb09612f1d..b62060b1032 100644 --- a/src/plugins/cmakeprojectmanager/servermodereader.cpp +++ b/src/plugins/cmakeprojectmanager/servermodereader.cpp @@ -306,6 +306,7 @@ void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps) CppTools::RawProjectPart rpp; rpp.setProjectFileLocation(fg->target->sourceDirectory.toString() + "/CMakeLists.txt"); + rpp.setBuildSystemTarget(fg->target->name); rpp.setDisplayName(fg->target->name + QString::number(counter)); rpp.setDefines(defineArg.toUtf8()); rpp.setIncludePaths(includes); diff --git a/src/plugins/cmakeprojectmanager/tealeafreader.cpp b/src/plugins/cmakeprojectmanager/tealeafreader.cpp index da7d07c00fb..b41176d1ed1 100644 --- a/src/plugins/cmakeprojectmanager/tealeafreader.cpp +++ b/src/plugins/cmakeprojectmanager/tealeafreader.cpp @@ -358,6 +358,7 @@ void TeaLeafReader::updateCodeModel(CppTools::RawProjectParts &rpps) includePaths += m_parameters.buildDirectory.toString(); CppTools::RawProjectPart rpp; rpp.setProjectFileLocation(QString()); // No project file information available! + rpp.setBuildSystemTarget(cbt.title); rpp.setIncludePaths(includePaths); CppTools::RawProjectPartFlags cProjectFlags; diff --git a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp index 7f3f624d183..04a1326f206 100644 --- a/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp +++ b/src/plugins/cppeditor/cppcodemodelinspectordialog.cpp @@ -1779,12 +1779,16 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr & } const QString callGroupId = part->callGroupId.isEmpty() ? QString::fromLatin1("") : part->callGroupId; + const QString buildSystemTarget + = part->buildSystemTarget.isEmpty() ? QString::fromLatin1("") + : part->buildSystemTarget; KeyValueModel::Table table = KeyValueModel::Table() << qMakePair(QString::fromLatin1("Project Part Name"), part->displayName) << qMakePair(QString::fromLatin1("Project Part File"), part->projectFileLocation()) << qMakePair(QString::fromLatin1("Project Name"), projectName) << qMakePair(QString::fromLatin1("Project File"), projectFilePath) + << qMakePair(QString::fromLatin1("Buildsystem Target"), buildSystemTarget) << qMakePair(QString::fromLatin1("Callgroup Id"), callGroupId) << qMakePair(QString::fromLatin1("Selected For Building"), CMI::Utils::toString(part->selectedForBuilding)) diff --git a/src/plugins/cpptools/cppprojectinfogenerator.cpp b/src/plugins/cpptools/cppprojectinfogenerator.cpp index 525cdbf284a..422dad8cfdf 100644 --- a/src/plugins/cpptools/cppprojectinfogenerator.cpp +++ b/src/plugins/cpptools/cppprojectinfogenerator.cpp @@ -185,6 +185,7 @@ static ProjectPart::Ptr projectPartFromRawProjectPart(const RawProjectPart &rawP part->projectFileLine = rawProjectPart.projectFileLine; part->projectFileColumn = rawProjectPart.projectFileColumn; part->callGroupId = rawProjectPart.callGroupId; + part->buildSystemTarget = rawProjectPart.buildSystemTarget; part->qtVersion = rawProjectPart.qtVersion; part->projectDefines = rawProjectPart.projectDefines; part->headerPaths = rawProjectPart.headerPaths; diff --git a/src/plugins/cpptools/cpprawprojectpart.cpp b/src/plugins/cpptools/cpprawprojectpart.cpp index 6cd5a213157..3668f8caec0 100644 --- a/src/plugins/cpptools/cpprawprojectpart.cpp +++ b/src/plugins/cpptools/cpprawprojectpart.cpp @@ -66,6 +66,11 @@ void RawProjectPart::setConfigFileName(const QString &configFileName) this->projectConfigFile = configFileName; } +void RawProjectPart::setBuildSystemTarget(const QString &target) +{ + buildSystemTarget = target; +} + void RawProjectPart::setCallGroupId(const QString &id) { callGroupId = id; diff --git a/src/plugins/cpptools/cpprawprojectpart.h b/src/plugins/cpptools/cpprawprojectpart.h index c3708f3a3cf..18f0591ec26 100644 --- a/src/plugins/cpptools/cpprawprojectpart.h +++ b/src/plugins/cpptools/cpprawprojectpart.h @@ -63,6 +63,7 @@ public: void setProjectFileLocation(const QString &projectFile, int line = -1, int column = -1); void setConfigFileName(const QString &configFileName); void setCallGroupId(const QString &id); + void setBuildSystemTarget(const QString &target); void setQtVersion(ProjectPart::QtVersion qtVersion); @@ -84,6 +85,7 @@ public: int projectFileColumn = -1; QString projectConfigFile; // currently only used by the Generic Project Manager QString callGroupId; + QString buildSystemTarget; QStringList precompiledHeaders; ProjectPartHeaderPaths headerPaths; QByteArray projectDefines; diff --git a/src/plugins/cpptools/projectpart.h b/src/plugins/cpptools/projectpart.h index 98fc5367adc..fa13aed3444 100644 --- a/src/plugins/cpptools/projectpart.h +++ b/src/plugins/cpptools/projectpart.h @@ -110,6 +110,7 @@ public: int projectFileColumn = -1; QString projectConfigFile; // currently only used by the Generic Project Manager QString callGroupId; + QString buildSystemTarget; ProjectFiles files; diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 182537bfaaf..ec047b86390 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -996,6 +996,7 @@ void QbsProject::updateCppCodeModel() rpp.setDisplayName(grp.name()); rpp.setProjectFileLocation(grp.location().filePath(), grp.location().line(), grp.location().column()); + rpp.setBuildSystemTarget(uniqueProductName(prd)); QHash filePathToSourceArtifact; bool hasCFiles = false; diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index a5e9cee2b9c..ffdcee6f2ad 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -345,6 +345,7 @@ void QmakeProject::updateCppCodeModel() CppTools::RawProjectPart rpp; rpp.setDisplayName(pro->displayName()); rpp.setProjectFileLocation(pro->filePath().toString()); + rpp.setBuildSystemTarget(pro->targetInformation().target); // TODO: Handle QMAKE_CFLAGS rpp.setFlagsForCxx({cxxToolChain, pro->variableValue(Variable::CppFlags)}); rpp.setDefines(pro->cxxDefines()); From 68a4a3db943884c152694bfcc3c6e8f5f069c2ed Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 15 Mar 2017 09:19:12 +0100 Subject: [PATCH 48/56] Debugger: Use gdb provided hooks to track loaded shared objects Change-Id: I4f3cce56910e0e737febaf0ff442956b78b19c30 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/gdbbridge.py | 111 +++++++++++++++----------- 1 file changed, 63 insertions(+), 48 deletions(-) diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 2506ec10e32..fc21ecb212c 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -970,58 +970,60 @@ class Dumper(DumperBase): except: return 0 + def handleNewObjectFile(self, objfile): + name = objfile.filename + if self.isWindowsTarget(): + isQtCoreObjFile = name.find('Qt5Cored.dll') >= 0 or name.find('Qt5Core.dll') >= 0 + else: + isQtCoreObjFile = name.find('/libQt5Core') >= 0 + if isQtCoreObjFile: + self.handleQtCoreLoaded(objfile) + + def handleQtCoreLoaded(self, objfile): + fd, tmppath = tempfile.mkstemp() + os.close(fd) + cmd = 'maint print msymbols %s "%s"' % (tmppath, objfile.filename) + try: + symbols = gdb.execute(cmd, to_string = True) + except: + pass + ns = '' + with open(tmppath) as f: + for line in f: + if line.find('msgHandlerGrabbed ') >= 0: + # [11] b 0x7ffff683c000 _ZN4MynsL17msgHandlerGrabbedE + # section .tbss Myns::msgHandlerGrabbed qlogging.cpp + ns = re.split('_ZN?(\d*)(\w*)L17msgHandlerGrabbedE? ', line)[2] + if len(ns): + ns += '::' + break + os.remove(tmppath) + + lenns = len(ns) + strns = ('%d%s' % (lenns - 2, ns[:lenns - 2])) if lenns else '' + + if lenns: + sym = '_ZN%s7QObject11customEventEPNS_6QEventE' % strns + else: + sym = '_ZN7QObject11customEventEP6QEvent' + self.qtCustomEventFunc = self.findSymbol(sym) + + sym += '@plt' + self.qtCustomEventPltFunc = self.findSymbol(sym) + + sym = '_ZNK%s7QObject8propertyEPKc' % strns + self.qtPropertyFunc = self.findSymbol(sym) + + # This might be wrong, but we can't do better: We found + # a libQt5Core and could not extract a namespace. + # The best guess is that there isn't any. + self.qtNamespaceToReport = ns + self.qtNamespace = lambda: ns + def qtNamespaceX(self): if not self.currentQtNamespaceGuess is None: return self.currentQtNamespaceGuess - for objfile in gdb.objfiles(): - name = objfile.filename - if self.isWindowsTarget(): - isQtCoreObjFile = name.find('Qt5Cored.dll') >= 0 or name.find('Qt5Core.dll') >= 0 - else: - isQtCoreObjFile = name.find('/libQt5Core') >= 0 - if isQtCoreObjFile: - fd, tmppath = tempfile.mkstemp() - os.close(fd) - cmd = 'maint print msymbols %s "%s"' % (tmppath, name) - try: - symbols = gdb.execute(cmd, to_string = True) - except: - pass - ns = '' - with open(tmppath) as f: - for line in f: - if line.find('msgHandlerGrabbed ') >= 0: - # [11] b 0x7ffff683c000 _ZN4MynsL17msgHandlerGrabbedE - # section .tbss Myns::msgHandlerGrabbed qlogging.cpp - ns = re.split('_ZN?(\d*)(\w*)L17msgHandlerGrabbedE? ', line)[2] - if len(ns): - ns += '::' - break - os.remove(tmppath) - - lenns = len(ns) - strns = ('%d%s' % (lenns - 2, ns[:lenns - 2])) if lenns else '' - - if lenns: - sym = '_ZN%s7QObject11customEventEPNS_6QEventE' % strns - else: - sym = '_ZN7QObject11customEventEP6QEvent' - self.qtCustomEventFunc = self.findSymbol(sym) - - sym += '@plt' - self.qtCustomEventPltFunc = self.findSymbol(sym) - - sym = '_ZNK%s7QObject8propertyEPKc' % strns - self.qtPropertyFunc = self.findSymbol(sym) - - # This might be wrong, but we can't do better: We found - # a libQt5Core and could not extract a namespace. - # The best guess is that there isn't any. - self.qtNamespaceToReport = ns - self.qtNamespace = lambda: ns - return ns - self.currentQtNamespaceGuess = '' return '' @@ -1413,4 +1415,17 @@ class InterpreterMessageBreakpoint(gdb.Breakpoint): print('Interpreter event received.') return theDumper.handleInterpreterMessage() + +####################################################################### +# +# Shared objects +# +####################################################################### + +def new_objfile_handler(event): + return theDumper.handleNewObjectFile(event.new_objfile) + +gdb.events.new_objfile.connect(new_objfile_handler) + + #InterpreterMessageBreakpoint() From 61501042bcf6c3e0e22ee3b8294b1752846b8c84 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 15 Mar 2017 10:05:05 +0100 Subject: [PATCH 49/56] Debugger: Simplify Qt namespace guessing code We get proper notification when QtCore is loaded now, and we either got it, or not. Change-Id: I9485126d9b15b8d859ba440f3ba1623f03527ef8 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/dumper.py | 7 ------- share/qtcreator/debugger/gdbbridge.py | 25 ++++++++----------------- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 9111b230b37..40230fee147 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -286,8 +286,6 @@ class DumperBase: 'personaltypes', ] - self.currentQtNamespaceGuess = None - # These values are never used, but the variables need to have # some value base for the swapping logic in Children.__enter__() # and Children.__exit__(). @@ -324,11 +322,6 @@ class DumperBase: #warn('EXPANDED INAMES: %s' % self.expandedINames) #warn('WATCHERS: %s' % self.watchers) - # The guess does not need to be updated during a fetchVariables() - # as the result is fixed during that time (ignoring "active" - # dumpers causing loading of shared objects etc). - self.currentQtNamespaceGuess = None - def resetCaches(self): # This is a cache mapping from 'type name' to 'display alternatives'. self.qqFormats = { 'QVariant (QVariantMap)' : mapForms() } diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index fc21ecb212c..33c19a20658 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -959,10 +959,8 @@ class Dumper(DumperBase): self.importPlainDumper(printer) def qtNamespace(self): - self.preping('qtNamespace') - res = self.qtNamespaceX() - self.ping('qtNamespace') - return res + # This function is replaced by handleQtCoreLoaded() + return '' def findSymbol(self, symbolName): try: @@ -1003,6 +1001,12 @@ class Dumper(DumperBase): strns = ('%d%s' % (lenns - 2, ns[:lenns - 2])) if lenns else '' if lenns: + # This might be wrong, but we can't do better: We found + # a libQt5Core and could not extract a namespace. + # The best guess is that there isn't any. + self.qtNamespaceToReport = ns + self.qtNamespace = lambda: ns + sym = '_ZN%s7QObject11customEventEPNS_6QEventE' % strns else: sym = '_ZN7QObject11customEventEP6QEvent' @@ -1014,19 +1018,6 @@ class Dumper(DumperBase): sym = '_ZNK%s7QObject8propertyEPKc' % strns self.qtPropertyFunc = self.findSymbol(sym) - # This might be wrong, but we can't do better: We found - # a libQt5Core and could not extract a namespace. - # The best guess is that there isn't any. - self.qtNamespaceToReport = ns - self.qtNamespace = lambda: ns - - def qtNamespaceX(self): - if not self.currentQtNamespaceGuess is None: - return self.currentQtNamespaceGuess - - self.currentQtNamespaceGuess = '' - return '' - def assignValue(self, args): typeName = self.hexdecode(args['type']) expr = self.hexdecode(args['expr']) From 8457949dbc48cde6eb229743757b1c943973635c Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 14 Mar 2017 16:41:00 +0200 Subject: [PATCH 50/56] Debugger: Fix MSVC warning Implicit cast from size_t to int. Change-Id: I8e53a6511afa4a3435f571217d736725771fef9c Reviewed-by: hjk --- src/plugins/debugger/watchhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index f60cbf59233..f14d82e8caa 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -2008,7 +2008,7 @@ bool WatchHandler::insertItem(WatchItem *item) bool found = false; const std::vector siblings(parent->begin(), parent->end()); - for (int row = 0, n = siblings.size(); row < n; ++row) { + for (int row = 0, n = int(siblings.size()); row < n; ++row) { if (static_cast(siblings[row])->iname == item->iname) { m_model->destroyItem(parent->childAt(row)); parent->insertChild(row, item); From 7236f2124a2d9c97fee8ddca1dc8e3db2996c48a Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 14 Mar 2017 18:00:15 +0100 Subject: [PATCH 51/56] Qml Debugger: Set detailed options rather than "sanity" The v4 debug service doesn't understand "sanity" after all, but wants to know the features we support. So state that we don't need redundant references and that we understand names when sent as strings. Change-Id: Ie973dd8002935a113a367d098337983d61663265 Reviewed-by: hjk --- src/plugins/debugger/qml/qmlengine.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 9272cb4860c..33759888faf 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -2536,7 +2536,8 @@ void QmlEnginePrivate::stateChanged(State state) /// Start session. flushSendBuffer(); QJsonObject parameters; - parameters.insert("sanity", 1); + parameters.insert("redundantRefs", false); + parameters.insert("namesAsObjects", false); runDirectCommand(CONNECT, QJsonDocument(parameters).toJson()); runCommand({VERSION}, CB(handleVersion)); } From 53a32f7fc64fa3e81d7d7eeed11dfb9a36919657 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 15 Mar 2017 16:49:07 +0100 Subject: [PATCH 52/56] ScxmlEditor: Don't generate invalid state names '(' and ')' should be avoided when copy/pasting states. Change-Id: Ic54528ed51b2f4596651bb1d23f282e70210f3a7 Reviewed-by: Marco Benelli --- src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp b/src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp index 15dea2d2e1f..ed4ce3e507a 100644 --- a/src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp +++ b/src/plugins/scxmleditor/plugin_interface/scxmldocument.cpp @@ -625,7 +625,7 @@ QString ScxmlDocument::getUniqueCopyId(const ScxmlTag *tag) // Check duplicate foreach (const ScxmlTag *t, m_tags) { if (t->attribute("id") == name && t != tag) { - name = QString::fromLatin1("%1_Copy(%2)").arg(key).arg(counter); + name = QString::fromLatin1("%1_Copy%2").arg(key).arg(counter); bFound = true; counter++; } From 408e384e9bb9a9bf721ba2468c20c93dafd22b1c Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 15 Mar 2017 17:03:55 +0100 Subject: [PATCH 53/56] ProjectWizardPage: Simplify tree walking Change-Id: I74eb980a762b6a880ec40a359afb6b36a6bab419 Reviewed-by: Tobias Hunger --- .../projectexplorer/projectwizardpage.cpp | 58 ++++++------------- 1 file changed, 19 insertions(+), 39 deletions(-) diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp index 2a455525f75..6a5c2bd261a 100644 --- a/src/plugins/projectexplorer/projectwizardpage.cpp +++ b/src/plugins/projectexplorer/projectwizardpage.cpp @@ -254,19 +254,6 @@ static inline AddNewTree *buildAddProjectTree(ProjectNode *root, const QString & return new AddNewTree(root, children, root->displayName()); } -static inline AddNewTree *buildAddProjectTree(SessionNode *root, const QString &projectPath, Node *contextNode, BestNodeSelector *selector) -{ - QList children; - for (Node *node : root->nodes()) { - if (ProjectNode *pn = node->asProjectNode()) { - if (AddNewTree *child = buildAddProjectTree(pn, projectPath, contextNode, selector)) - children.append(child); - } - } - children.prepend(createNoneNode(selector)); - return new AddNewTree(root, children, root->displayName()); -} - static inline AddNewTree *buildAddFilesTree(FolderNode *root, const QStringList &files, Node *contextNode, BestNodeSelector *selector) { @@ -289,31 +276,6 @@ static inline AddNewTree *buildAddFilesTree(FolderNode *root, const QStringList return new AddNewTree(root, children, root->displayName()); } -static inline AddNewTree *buildAddFilesTree(SessionNode *root, const QStringList &files, - Node *contextNode, BestNodeSelector *selector) -{ - QList children; - for (Node *node : root->nodes()) { - if (ProjectNode *pn = node->asProjectNode()) { - if (AddNewTree *child = buildAddFilesTree(pn, files, contextNode, selector)) - children.append(child); - } - } - children.prepend(createNoneNode(selector)); - return new AddNewTree(root, children, root->displayName()); -} - -static inline AddNewTree *getChoices(const QStringList &generatedFiles, - IWizardFactory::WizardKind wizardKind, - Node *contextNode, - BestNodeSelector *selector) -{ - if (wizardKind == IWizardFactory::ProjectWizard) - return buildAddProjectTree(SessionManager::sessionNode(), generatedFiles.first(), contextNode, selector); - else - return buildAddFilesTree(SessionManager::sessionNode(), generatedFiles, contextNode, selector); -} - // -------------------------------------------------------------------- // ProjectWizardPage: // -------------------------------------------------------------------- @@ -491,7 +453,25 @@ void ProjectWizardPage::initializeProjectTree(Node *context, const QStringList & ProjectAction action) { BestNodeSelector selector(m_commonDirectory, paths); - AddNewTree *tree = getChoices(paths, kind, context, &selector); + + AddNewTree *tree; + SessionNode *root = SessionManager::sessionNode(); + QList children; + + for (Node *node : root->nodes()) { + if (ProjectNode *pn = node->asProjectNode()) { + if (kind == IWizardFactory::ProjectWizard) { + if (AddNewTree *child = buildAddProjectTree(pn, paths.first(), context, &selector)) + children.append(child); + } else { + if (AddNewTree *child = buildAddFilesTree(pn, paths, context, &selector)) + children.append(child); + } + } + } + + children.prepend(createNoneNode(&selector)); + tree = new AddNewTree(root, children, root->displayName()); setAdditionalInfo(selector.deployingProjects()); From 5c3fce7f974e7efa7e44288275afc38e99c725e3 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Wed, 15 Mar 2017 13:16:27 +0100 Subject: [PATCH 54/56] QmlJS: Fix version detection in updateProjectInfo Change-Id: Ib8b53e8fdf5e69caf843a34390e820e9221a8be5 Reviewed-by: Marco Benelli --- src/libs/qmljs/qmljsmodelmanagerinterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp index 577fbf4b2b1..d88b1c261e7 100644 --- a/src/libs/qmljs/qmljsmodelmanagerinterface.cpp +++ b/src/libs/qmljs/qmljsmodelmanagerinterface.cpp @@ -579,7 +579,7 @@ void ModelManagerInterface::updateProjectInfo(const ProjectInfo &pinfo, ProjectE &majorVersion, &minorVersion, &patchVersion) != 3) majorVersion = minorVersion = patchVersion = -1; - if (majorVersion > 4 || (majorVersion == 4 && (minorVersion > 8 || (majorVersion == 8 + if (majorVersion > 4 || (majorVersion == 4 && (minorVersion > 8 || (minorVersion == 8 && patchVersion >= 5)))) { m_pluginDumper->loadBuiltinTypes(pinfo); } From 3d6b1089711227acc432c404729f8cb5a431d2cc Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 16 Mar 2017 07:41:25 +0100 Subject: [PATCH 55/56] AutoTest: Fix handling of subtyping TestCase again We need a more present snapshot when inspecting the AST of QML files we need to process. Due to handling all problematic accesses inside the QmlJS model by guarding it with mutexes it is no problem even when parsing multi threaded. The former fix collided with another patch and therefore went in without fixing the issue. Task-number: QTCREATORBUG-17787 Change-Id: I460bae4b09cdc9a0cd38bc3383fd593c3abdfaad Reviewed-by: Marco Benelli --- src/plugins/autotest/quick/quicktestparser.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp index f6b7cf78176..c3440ce15d2 100644 --- a/src/plugins/autotest/quick/quicktestparser.cpp +++ b/src/plugins/autotest/quick/quicktestparser.cpp @@ -165,7 +165,6 @@ static QList scanDirectoryForQuickTestQmlFiles(const QStri } static bool checkQmlDocumentForQuickTestCode(QFutureInterface futureInterface, - const QmlJS::Snapshot &snapshot, const QmlJS::Document::Ptr &qmlJSDoc, const Core::Id &id, const QString &proFile = QString()) @@ -174,6 +173,7 @@ static bool checkQmlDocumentForQuickTestCode(QFutureInterfaceast(); QTC_ASSERT(ast, return false); + QmlJS::Snapshot snapshot = QmlJS::ModelManagerInterface::instance()->snapshot(); TestQmlVisitor qmlVisitor(qmlJSDoc, snapshot); QmlJS::AST::Node::accept(ast, &qmlVisitor); if (!qmlVisitor.isValid()) @@ -212,7 +212,6 @@ static bool checkQmlDocumentForQuickTestCode(QFutureInterface futureInterface, - const QmlJS::Snapshot &snapshot, CPlusPlus::Document::Ptr document, const Core::Id &id) { @@ -233,7 +232,7 @@ static bool handleQtQuickTest(QFutureInterface futureInterfa const QList qmlDocs = scanDirectoryForQuickTestQmlFiles(srcDir); bool result = false; for (const QmlJS::Document::Ptr &qmlJSDoc : qmlDocs) - result |= checkQmlDocumentForQuickTestCode(futureInterface, snapshot, qmlJSDoc, id, proFile); + result |= checkQmlDocumentForQuickTestCode(futureInterface, qmlJSDoc, id, proFile); return result; } @@ -280,14 +279,14 @@ bool QuickTestParser::processDocument(QFutureInterface futur if (proFile.isEmpty()) return false; QmlJS::Document::Ptr qmlJSDoc = m_qmlSnapshot.document(fileName); - return checkQmlDocumentForQuickTestCode(futureInterface, m_qmlSnapshot, qmlJSDoc, id(), proFile); + return checkQmlDocumentForQuickTestCode(futureInterface, qmlJSDoc, id(), proFile); } if (!m_cppSnapshot.contains(fileName) || !selectedForBuilding(fileName)) return false; CPlusPlus::Document::Ptr document = m_cppSnapshot.find(fileName).value(); if (!includesQtQuickTest(document, m_cppSnapshot)) return false; - return handleQtQuickTest(futureInterface, m_qmlSnapshot, document, id()); + return handleQtQuickTest(futureInterface, document, id()); } } // namespace Internal From 96010fb8d366bb52725f862bc0e91a61010d801a Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 15 Mar 2017 15:43:58 +0100 Subject: [PATCH 56/56] ClangStaticAnalyzer: Remove -fPIC workaround The option -fPIC predefines the macros __pic__ and __PIC__ and it was added just to have these macros and thus avoid a parse error somewhere in qglobal.h. Nowadays we get these macros from the project/toolchain, so remove this workaround. Change-Id: Ib6106cf217f7d8a08da6f7dde435bcadd04b6ba8 Reviewed-by: Christian Kandeler --- .../clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 1a31123fc6a..35607a95480 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -189,9 +189,6 @@ public: optionsBuilder.addPrecompiledHeaderOptions(pchUsage); optionsBuilder.addMsvcCompatibilityVersion(); - if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) - optionsBuilder.add(QLatin1String("-fPIC")); // TODO: Remove? - return optionsBuilder.options(); }