From c308ec7b736b1e105803845c2b15599bd1c0a7c6 Mon Sep 17 00:00:00 2001 From: Vladislav Tronko Date: Wed, 15 Mar 2017 18:56:40 +0200 Subject: [PATCH 01/36] Fix system options not being retained after restart Auto-suspend unmodified files checkbox was always checked after restart, and min files to keep opened was set to 30. Change-Id: I7f52fee41155188ee8389e922fdc265f8c0a6459 Task-number: QTCREATORBUG-17844 Reviewed-by: Eike Ziller --- src/plugins/coreplugin/editormanager/editormanager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 1f103bdcd53..e4d005e3fec 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -1036,6 +1036,12 @@ void EditorManagerPrivate::readSettings() d->m_autoSaveEnabled = qs->value(autoSaveEnabledKey).toBool(); d->m_autoSaveInterval = qs->value(autoSaveIntervalKey).toInt(); } + + if (qs->contains(autoSuspendEnabledKey)) { + d->m_autoSuspendEnabled = qs->value(autoSuspendEnabledKey).toBool(); + d->m_autoSuspendMinDocumentCount = qs->value(autoSuspendMinDocumentCountKey).toInt(); + } + updateAutoSave(); } From 262141a0dc74f30f435d929f96bcf6e1162d1743 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Mon, 20 Mar 2017 14:21:55 +0100 Subject: [PATCH 02/36] Squish: Make workaround permanent in tst_simple_debug The fix is in 4.3 Task-number: QTCREATORBUG-17492 Change-Id: If155bd9b16a119e7b91161788708c21653222f8d Reviewed-by: Christian Stenger --- tests/system/shared/debugger.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/system/shared/debugger.py b/tests/system/shared/debugger.py index 13f22f4a22b..74ea190a303 100644 --- a/tests/system/shared/debugger.py +++ b/tests/system/shared/debugger.py @@ -128,8 +128,7 @@ def doSimpleDebugging(kitCount, currentKit, currentConfigName, pressContinueCoun expectedLabelTexts = ['Stopped\.', 'Stopped at breakpoint \d+ \(\d+\) in thread \d+\.'] if len(expectedBPOrder) == 0: expectedLabelTexts.append("Running\.") - if JIRA.isBugStillOpen(17492): - expectedLabelTexts.append("QML Debugger: Error: Unknown socket error 0") + expectedLabelTexts.append("QML Debugger: Error: Unknown socket error 0") switchViewTo(ViewConstants.PROJECTS) switchToBuildOrRunSettingsFor(kitCount, currentKit, ProjectSettings.RUN) ensureChecked(waitForObject("{container=':Qt Creator.scrollArea_QScrollArea' text='Enable QML' " From 42333ec1d23d481a4aa59314cd7ae38a158b0c41 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 20 Mar 2017 16:40:50 +0100 Subject: [PATCH 03/36] Welcome: Fix visibility of session tool tip It was not shown at all for collapsed items. Change-Id: Ia1e3590cc5ed6ad01eefad2465e7f7586c50603f Reviewed-by: Orgad Shaneh --- .../projectexplorer/projectwelcomepage.cpp | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp index ebd52104bac..3e67f07da73 100644 --- a/src/plugins/projectexplorer/projectwelcomepage.cpp +++ b/src/plugins/projectexplorer/projectwelcomepage.cpp @@ -55,6 +55,8 @@ using namespace Core; using namespace Utils; +const int LINK_HEIGHT = 35; + namespace ProjectExplorer { namespace Internal { @@ -154,13 +156,18 @@ class BaseDelegate : public QAbstractItemDelegate { protected: virtual QString entryType() = 0; + virtual QRect toolTipArea(const QRect &itemRect, const QModelIndex &) const + { + return itemRect; + } bool helpEvent(QHelpEvent *ev, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &idx) final { - const int y = ev->pos().y(); - if (y > option.rect.bottom() - 20) + if (!toolTipArea(option.rect, idx).contains(ev->pos())) { + QToolTip::hideText(); return false; + } QString shortcut; if (idx.row() < m_shortcuts.size()) @@ -188,6 +195,13 @@ class SessionDelegate : public BaseDelegate { protected: QString entryType() override { return tr("session", "Appears in \"Open session \""); } + QRect toolTipArea(const QRect &itemRect, const QModelIndex &idx) const override + { + // in expanded state bottom contains 'Clone', 'Rename', etc links, where the tool tip + // would be confusing + const bool expanded = m_expandedSessions.contains(idx.data(Qt::DisplayRole).toString()); + return expanded ? itemRect.adjusted(0, 0, 0, -LINK_HEIGHT) : itemRect; + } public: SessionDelegate() { @@ -312,7 +326,7 @@ public: QString sessionName = idx.data(Qt::DisplayRole).toString(); if (m_expandedSessions.contains(sessionName)) { QStringList projects = SessionManager::projectsForSessionName(sessionName); - h += projects.size() * 40 + 35; + h += projects.size() * 40 + LINK_HEIGHT; } return QSize(380, h); } From 16d2a10a1b0f5bf4685246fa90e345d8f82eb189 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 20 Mar 2017 20:20:56 +0200 Subject: [PATCH 04/36] Gerrit: Fix wrong references in REST parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fetch url/ref * Patch set number Change-Id: I1aec8850add21dc269326c637b246ba62266b889 Reviewed-by: AndrĂ© Hartmann --- src/plugins/git/gerrit/gerritmodel.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/plugins/git/gerrit/gerritmodel.cpp b/src/plugins/git/gerrit/gerritmodel.cpp index 1cc7a63f90c..aed258fb74a 100644 --- a/src/plugins/git/gerrit/gerritmodel.cpp +++ b/src/plugins/git/gerrit/gerritmodel.cpp @@ -737,10 +737,15 @@ static GerritChangePtr parseSshOutput(const QJsonObject &object) } */ +static int restNumberValue(const QJsonObject &object) +{ + return object.value("_number").toInt(); +} + static GerritChangePtr parseRestOutput(const QJsonObject &object, const GerritServer &server) { GerritChangePtr change(new GerritChange); - change->number = object.value("_number").toInt(); + change->number = restNumberValue(object); change->url = QString("%1/%2").arg(server.url()).arg(change->number); change->title = object.value("subject").toString(); change->owner = parseGerritUser(object.value("owner").toObject()); @@ -751,10 +756,11 @@ static GerritChangePtr parseRestOutput(const QJsonObject &object, const GerritSe Qt::DateFormat::ISODate).toLocalTime(); // Read current patch set. const QJsonObject patchSet = object.value("revisions").toObject().begin().value().toObject(); - change->currentPatchSet.patchSetNumber = qMax(1, patchSet.value("number").toString().toInt()); - change->currentPatchSet.ref = patchSet.value("ref").toString(); + change->currentPatchSet.patchSetNumber = qMax(1, restNumberValue(patchSet)); + const QJsonObject fetchInfo = patchSet.value("fetch").toObject().value("http").toObject(); + change->currentPatchSet.ref = fetchInfo.value("ref").toString(); // Replace * in ssh://*:29418/qt-creator/qt-creator with the hostname - change->currentPatchSet.url = patchSet.value("url").toString().replace('*', server.host); + change->currentPatchSet.url = fetchInfo.value("url").toString().replace('*', server.host); const QJsonObject labels = object.value("labels").toObject(); for (auto it = labels.constBegin(), end = labels.constEnd(); it != end; ++it) { const QJsonArray all = it.value().toObject().value("all").toArray(); From ae63f89f35246927c1805e67f53e507fe982d2ee Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Fri, 17 Mar 2017 09:15:49 +0100 Subject: [PATCH 05/36] AutoTest: Reduce auto test wizard to useful parts This patch reduces the former wizard to the test project part. The wizard appeared more or less useless as there was no easy way to add test cases later on and you normally do not need to have the full skeleton of the project including a test sub project - except when starting a TDD project. Change-Id: I404d843b29f058876ea9696b7881f2e5e11b6af2 Reviewed-by: Tobias Hunger --- .../templates/wizards/autotest/files/auto.pro | 3 - .../templates/wizards/autotest/files/auto.qbs | 26 ----- .../templates/wizards/autotest/files/main.cpp | 31 ------ .../templates/wizards/autotest/files/src.pro | 18 ---- .../templates/wizards/autotest/files/src.qbs | 27 ------ .../wizards/autotest/files/tests.pro | 3 - .../wizards/autotest/files/tests.qbs | 8 -- .../templates/wizards/autotest/files/tmp.pro | 12 --- .../templates/wizards/autotest/files/tmp.qbs | 8 -- .../templates/wizards/autotest/files/tst.pro | 2 +- .../templates/wizards/autotest/files/tst.qbs | 24 ++++- .../templates/wizards/autotest/wizard.json | 97 +++---------------- 12 files changed, 33 insertions(+), 226 deletions(-) delete mode 100644 share/qtcreator/templates/wizards/autotest/files/auto.pro delete mode 100644 share/qtcreator/templates/wizards/autotest/files/auto.qbs delete mode 100644 share/qtcreator/templates/wizards/autotest/files/main.cpp delete mode 100644 share/qtcreator/templates/wizards/autotest/files/src.pro delete mode 100644 share/qtcreator/templates/wizards/autotest/files/src.qbs delete mode 100644 share/qtcreator/templates/wizards/autotest/files/tests.pro delete mode 100644 share/qtcreator/templates/wizards/autotest/files/tests.qbs delete mode 100644 share/qtcreator/templates/wizards/autotest/files/tmp.pro delete mode 100644 share/qtcreator/templates/wizards/autotest/files/tmp.qbs diff --git a/share/qtcreator/templates/wizards/autotest/files/auto.pro b/share/qtcreator/templates/wizards/autotest/files/auto.pro deleted file mode 100644 index 510a3710068..00000000000 --- a/share/qtcreator/templates/wizards/autotest/files/auto.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS += %{JS: '%{TestCaseName}'.toLowerCase()} diff --git a/share/qtcreator/templates/wizards/autotest/files/auto.qbs b/share/qtcreator/templates/wizards/autotest/files/auto.qbs deleted file mode 100644 index 319bfbd1d46..00000000000 --- a/share/qtcreator/templates/wizards/autotest/files/auto.qbs +++ /dev/null @@ -1,26 +0,0 @@ -import qbs -@if "%{TestFrameWork}" == "GTest" -import qbs.Environment -@endif - -Project { - name: "auto tests" - -@if "%{TestFrameWork}" == "GTest" - property string googletestDir: { - if (typeof Environment.getEnv("GOOGLETEST_DIR") === 'undefined') { - console.warn("Using googletest src dir specified at Qt Creator wizard") - console.log("set GOOGLETEST_DIR as environment variable or Qbs property to get rid of this message") - return "%{GTestRepository}" - } else { - return Environment.getEnv("GOOGLETEST_DIR") - } - } -@endif -@if "%{BuildAutoTests}" == "debug" - condition: qbs.buildVariant === "debug" -@endif - references: [ - "%{JS: '%{TestCaseName}'.toLowerCase()}/%{JS: '%{TestCaseName}'.toLowerCase()}.qbs" - ] -} diff --git a/share/qtcreator/templates/wizards/autotest/files/main.cpp b/share/qtcreator/templates/wizards/autotest/files/main.cpp deleted file mode 100644 index 8a4a5671fc3..00000000000 --- a/share/qtcreator/templates/wizards/autotest/files/main.cpp +++ /dev/null @@ -1,31 +0,0 @@ -%{Cpp:LicenseTemplate}\ -@if "%{TestFrameWork}" == "QtTest" -@if "%{RequireGUI}" == "true" -%{JS: QtSupport.qtIncludes([ 'QtGui/QApplication' ], - [ 'QtWidgets/QApplication' ]) }\ -@else -%{JS: QtSupport.qtIncludes([ 'QtCore/QCoreApplication' ], - [ 'QtCore/QCoreApplication' ]) }\ -@endif -// add necessary includes here - -int main(int argc, char *argv[]) -{ -@if "%{RequireGUI}" == "true" - QApplication a(argc, argv); -@else - QCoreApplication a(argc, argv); -@endif - - return a.exec(); -} -@else -#include - -int main(int , char **) -{ - std::cout << "Hello World!\\n"; - - return 0; -} -@endif diff --git a/share/qtcreator/templates/wizards/autotest/files/src.pro b/share/qtcreator/templates/wizards/autotest/files/src.pro deleted file mode 100644 index 8d664760666..00000000000 --- a/share/qtcreator/templates/wizards/autotest/files/src.pro +++ /dev/null @@ -1,18 +0,0 @@ -@if "%{TestFrameWork}" == "QtTest" -@if "%{RequireGUI}" == "true" -QT += core gui -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -@else -QT -= gui -@endif -@else -CONFIG -= qt -@endif -CONFIG += console c++11 -CONFIG -= app_bundle - -TEMPLATE = app - -TARGET = %{ProjectName} - -SOURCES += %{MainCppName} diff --git a/share/qtcreator/templates/wizards/autotest/files/src.qbs b/share/qtcreator/templates/wizards/autotest/files/src.qbs deleted file mode 100644 index 36e44e774b3..00000000000 --- a/share/qtcreator/templates/wizards/autotest/files/src.qbs +++ /dev/null @@ -1,27 +0,0 @@ -import qbs - -CppApplication { - type: "application" - consoleApplication: true - name: "%{ProjectName}" -@if "%{TestFrameWork}" == "QtTest" -@if "%{RequireGUI}" == "true" - - Depends { name: "Qt.core" } - Depends { name: "Qt.gui" } - Depends { - name: "Qt.widgets" - condition: Qt.core.versionMajor > 4 - } -@else - - Depends { name: "Qt.core" } -@endif -@endif - - cpp.cxxLanguageVersion: "c++11" - - files: [ - "%{MainCppName}" - ] -} diff --git a/share/qtcreator/templates/wizards/autotest/files/tests.pro b/share/qtcreator/templates/wizards/autotest/files/tests.pro deleted file mode 100644 index f9277000081..00000000000 --- a/share/qtcreator/templates/wizards/autotest/files/tests.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = subdirs - -SUBDIRS += auto diff --git a/share/qtcreator/templates/wizards/autotest/files/tests.qbs b/share/qtcreator/templates/wizards/autotest/files/tests.qbs deleted file mode 100644 index 6a83cf65ef1..00000000000 --- a/share/qtcreator/templates/wizards/autotest/files/tests.qbs +++ /dev/null @@ -1,8 +0,0 @@ -import qbs - -Project { - name: "%{ProjectName} tests" - references: [ - "auto/auto.qbs" - ] -} diff --git a/share/qtcreator/templates/wizards/autotest/files/tmp.pro b/share/qtcreator/templates/wizards/autotest/files/tmp.pro deleted file mode 100644 index 4832797c026..00000000000 --- a/share/qtcreator/templates/wizards/autotest/files/tmp.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = subdirs - -@if "%{BuildAutoTests}" == "always" -SUBDIRS += src \ - tests -@else -SUBDIRS += src - -CONFIG(debug, debug|release) { - SUBDIRS += tests -} -@endif diff --git a/share/qtcreator/templates/wizards/autotest/files/tmp.qbs b/share/qtcreator/templates/wizards/autotest/files/tmp.qbs deleted file mode 100644 index dfc99c15df3..00000000000 --- a/share/qtcreator/templates/wizards/autotest/files/tmp.qbs +++ /dev/null @@ -1,8 +0,0 @@ -import qbs - -Project { - references: [ - "src/src.qbs", - "tests/tests.qbs" - ] -} diff --git a/share/qtcreator/templates/wizards/autotest/files/tst.pro b/share/qtcreator/templates/wizards/autotest/files/tst.pro index 5f0f7455f47..695f0f7ffd2 100644 --- a/share/qtcreator/templates/wizards/autotest/files/tst.pro +++ b/share/qtcreator/templates/wizards/autotest/files/tst.pro @@ -14,7 +14,7 @@ TEMPLATE = app SOURCES += %{TestCaseFileWithCppSuffix} @else -include(../gtest_dependency.pri) +include(gtest_dependency.pri) TEMPLATE = app @if "%{GTestCXX11}" == "true" diff --git a/share/qtcreator/templates/wizards/autotest/files/tst.qbs b/share/qtcreator/templates/wizards/autotest/files/tst.qbs index 1000451bc63..58a647df861 100644 --- a/share/qtcreator/templates/wizards/autotest/files/tst.qbs +++ b/share/qtcreator/templates/wizards/autotest/files/tst.qbs @@ -1,6 +1,7 @@ import qbs @if "%{TestFrameWork}" == "GTest" -import "../googlecommon.js" as googleCommon +import qbs.Environment +import "googlecommon.js" as googleCommon @endif CppApplication { @@ -16,6 +17,19 @@ CppApplication { ] @else consoleApplication: true + +@if "%{TestFrameWork}" == "GTest" + property string googletestDir: { + if (typeof Environment.getEnv("GOOGLETEST_DIR") === 'undefined') { + console.warn("Using googletest src dir specified at Qt Creator wizard") + console.log("set GOOGLETEST_DIR as environment variable or Qbs property to get rid of this message") + return "%{GTestRepository}" + } else { + return Environment.getEnv("GOOGLETEST_DIR") + } + } +@endif + @if "%{GTestCXX11}" == "true" cpp.cxxLanguageVersion: "c++11" cpp.defines: [ "GTEST_LANG_CXX11" ] @@ -23,13 +37,13 @@ CppApplication { cpp.dynamicLibraries: [ "pthread" ] - cpp.includePaths: [].concat(googleCommon.getGTestIncludes(project.googletestDir)) - .concat(googleCommon.getGMockIncludes(project.googletestDir)) + cpp.includePaths: [].concat(googleCommon.getGTestIncludes(googletestDir)) + .concat(googleCommon.getGMockIncludes(googletestDir)) files: [ "%{MainCppName}", "%{TestCaseFileWithHeaderSuffix}", - ].concat(googleCommon.getGTestAll(project.googletestDir)) - .concat(googleCommon.getGMockAll(project.googletestDir)) + ].concat(googleCommon.getGTestAll(googletestDir)) + .concat(googleCommon.getGMockAll(googletestDir)) @endif } diff --git a/share/qtcreator/templates/wizards/autotest/wizard.json b/share/qtcreator/templates/wizards/autotest/wizard.json index 1f0d9cf5b5b..f1490a1dc9a 100644 --- a/share/qtcreator/templates/wizards/autotest/wizard.json +++ b/share/qtcreator/templates/wizards/autotest/wizard.json @@ -3,7 +3,7 @@ "supportedProjectTypes": [ "Qt4ProjectManager.Qt4Project" ], "id": "R.AutoTest", "category": "H.Project", - "trDescription": "Creates a new project including an auto test skeleton.", + "trDescription": "Creates a new unit test project. Unit tests allow you to verify that the code is fit for use and that there are no regressions.", "trDisplayName": "Auto Test Project", "trDisplayCategory": "Other Project", "icon": "autotest_24.png", @@ -46,7 +46,7 @@ "typeId": "Project", "data": { - "trDescription": "This wizard creates a simple project with an additional auto test skeleton." + "trDescription": "This wizard creates a simple unit test project." } }, { @@ -133,26 +133,6 @@ "uncheckedValue": "false" } }, - { - "name": "BuildAutoTests", - "trDisplayName": "Build auto tests", - "type": "ComboBox", - "data": - { - "index": 0, - "items": - [ - { - "trKey": "always", - "value": "always" - }, - { - "trKey": "debug only", - "value": "debug" - } - ] - } - }, { "name": "GTestRepository", "trDisplayName": "Googletest repository:", @@ -206,98 +186,47 @@ "typeId": "File", "data": [ - { - "source": "files/tmp.pro", - "target": "%{ProFileName}", - "condition": "%{JS: '%{BuildSystem}' == 'qmake'}", - "openAsProject": true - }, - { - "source": "files/tmp.qbs", - "target": "%{QbsFileName}", - "condition": "%{JS: '%{BuildSystem}' == 'qbs'}", - "openAsProject": true - }, - { - "source": "files/src.pro", - "target": "src/src.pro", - "condition": "%{JS: '%{BuildSystem}' == 'qmake'}", - "openInEditor": false - }, - { - "source": "files/src.qbs", - "target": "src/src.qbs", - "condition": "%{JS: '%{BuildSystem}' == 'qbs'}", - "openInEditor": false - }, - { - "source": "files/main.cpp", - "target": "src/%{MainCppName}", - "openInEditor": true - }, - { - "source": "files/tests.pro", - "target": "tests/tests.pro", - "condition": "%{JS: '%{BuildSystem}' == 'qmake'}", - "openInEditor": false - }, - { - "source": "files/tests.qbs", - "target": "tests/tests.qbs", - "condition": "%{JS: '%{BuildSystem}' == 'qbs'}", - "openInEditor": false - }, - { - "source": "files/auto.pro", - "target": "tests/auto/auto.pro", - "condition": "%{JS: '%{BuildSystem}' == 'qmake'}", - "openInEditor": false - }, - { - "source": "files/auto.qbs", - "target": "tests/auto/auto.qbs", - "condition": "%{JS: '%{BuildSystem}' == 'qbs'}", - "openInEditor": false - }, { "source": "files/gtest_dependency.pri", - "target": "tests/auto/gtest_dependency.pri", + "target": "gtest_dependency.pri", "condition": "%{JS: '%{TestFrameWork}' == 'GTest' && '%{BuildSystem}' == 'qmake'}", "openInEditor": false }, { "source": "files/googlecommon.js", - "target": "tests/auto/googlecommon.js", + "target": "googlecommon.js", "condition": "%{JS: '%{TestFrameWork}' == 'GTest' && '%{BuildSystem}' == 'qbs'}", "openInEditor": false }, { "source": "files/tst.pro", - "target": "%{JS: 'tests/auto/' + '%{TestCaseName}/%{TestCaseName}'.toLowerCase() + '.pro' }", + "target": "%{ProjectFilePath}", "condition": "%{JS: '%{BuildSystem}' == 'qmake'}", - "openInEditor": false + "openInEditor": false, + "openAsProject": true }, { "source": "files/tst.qbs", - "target": "%{JS: 'tests/auto/' + '%{TestCaseName}/%{TestCaseName}'.toLowerCase() + '.qbs' }", + "target": "%{ProjectFilePath}", "condition": "%{JS: '%{BuildSystem}' == 'qbs'}", - "openInEditor": false + "openInEditor": false, + "openAsProject": true }, { "source": "files/tst_src.h", - "target": "%{JS: 'tests/auto/' + '%{TestCaseName}/'.toLowerCase() + '%{TestCaseFileWithHeaderSuffix}' }", + "target": "%{TestCaseFileWithHeaderSuffix}", "condition": "%{JS: '%{TestFrameWork}' == 'GTest'}", "openInEditor": true }, { "source": "files/tst_src.cpp", - "target": "%{JS: 'tests/auto/' + '%{TestCaseName}/'.toLowerCase() + '%{TestCaseFileWithCppSuffix}' }", + "target": "%{TestCaseFileWithCppSuffix}", "condition": "%{JS: '%{TestFrameWork}' == 'QtTest'}", "openInEditor": true }, { "source": "files/tst_main.cpp", - "target": "%{JS: 'tests/auto/' + '%{TestCaseName}'.toLowerCase() + '/%{MainCppName}' }", + "target": "%{MainCppName}", "condition": "%{JS: '%{TestFrameWork}' == 'GTest'}", "openInEditor": true }, From 33e8f2e09933815aa8dc731dd49090828e57b2c2 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 14 Mar 2017 07:36:33 +0100 Subject: [PATCH 06/36] Debugger: Fix QObject detection on Windows Change-Id: I054161dfde0c03167a6d57861b069c403330e746 Reviewed-by: hjk Reviewed-by: Christian Stenger --- share/qtcreator/debugger/cdbbridge.py | 22 --------------- share/qtcreator/debugger/dumper.py | 39 ++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index 55a531e63a5..0849b532c20 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -318,28 +318,6 @@ class Dumper(DumperBase): % (self.qtCoreModuleName(), namespace)) return namespace - def couldBeQObjectVTable(self, vtablePtr): - try: - customEventFunc = self.extractPointer(vtablePtr + 8 * self.ptrSize()) - except: - self.bump('nostruct-3') - return False - - if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc): - return True - try: - delta = int.from_bytes(self.readRawMemory(customEventFunc + 1, 4), byteorder='little') - if (customEventFunc + 5 + delta) in (self.qtCustomEventFunc, self.qtCustomEventPltFunc): - return True - except: - pass - - try: - return 'QObject::customEvent' in cdbext.getNameByAddress(customEventFunc) - except: - return False - - def qtVersion(self): qtVersion = self.findValueByExpression('((void**)&%s)[2]' % self.qtHookDataSymbolName()) if qtVersion is None and self.qtCoreModuleName() is not None: diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 8392aceb96f..6a09b0f6ff3 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -1494,12 +1494,49 @@ class DumperBase: return self.couldBeQObjectVTable(vtablePtr) def couldBeQObjectVTable(self, vtablePtr): + def getJumpAddress_x86(dumper, address): + relativeJumpCode = 0xe9 + jumpCode = 0xff + data = dumper.readRawMemory(address, 6) + primaryOpcode = data[0] + if primaryOpcode == relativeJumpCode: + # relative jump on 32 and 64 bit with a 32bit offset + offset = int.from_bytes(data[1:5], byteorder='little') + return address + 5 + offset + if primaryOpcode == jumpCode: + if data[1] != 0x25: # check for known extended opcode + return 0 + # 0xff25 is a relative jump on 64bit and an absolute jump on 32 bit + if self.ptrSize() == 8: + offset = int.from_bytes(data[2:6], byteorder='little') + return address + 6 + offset + else: + return int.from_bytes(data[2:6], byteorder='little') + return 0 + + # Do not try to extract a function pointer if there are no values to compare with + if self.qtCustomEventFunc == 0 and self.qtCustomEventPltFunc == 0: + return False + try: - customEventFunc = self.extractPointer(vtablePtr + 9 * self.ptrSize()) + customEventOffset = 8 if self.isMsvcTarget() else 9 + customEventFunc = self.extractPointer(vtablePtr + customEventOffset * self.ptrSize()) except: self.bump('nostruct-3') return False + if self.isWindowsTarget(): + if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc): + return True + # The vtable may point to a function that is just calling the customEvent function + customEventFunc = getJumpAddress_x86(self, customEventFunc) + if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc): + return True + customEventFunc = self.extractPointer(customEventFunc) + if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc): + return True + # If the object is defined in another module there may be another level of indirection + customEventFunc = getJumpAddress_x86(self, customEventFunc) return customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc) # def extractQObjectProperty(objectPtr): From f32b1d00f41aefeb4318158648cd1c84c06f580f Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 14 Mar 2017 12:22:29 +0100 Subject: [PATCH 07/36] Debugger: Adjust offset for QFile dumper Change-Id: I20704cdcdda1273cdc0df91bf963c979a1f51190 Reviewed-by: Christian Stenger --- share/qtcreator/debugger/qttypes.py | 12 ++++++++++-- tests/auto/debugger/tst_offsets.cpp | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 0877634a3c5..69443b6cdc4 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -487,12 +487,20 @@ def qdump__QFile(d, value): # 9fc0965 and a373ffcd change the layout of the private structure qtVersion = d.qtVersion() is32bit = d.ptrSize() == 4 - if qtVersion >= 0x050600: + if qtVersion >= 0x050700: if d.isWindowsTarget(): if d.isMsvcTarget(): offset = 184 if is32bit else 248 else: - offset = 164 if is32bit else 248 + offset = 172 if is32bit else 248 + else: + offset = 168 if is32bit else 248 + elif qtVersion >= 0x050600: + if d.isWindowsTarget(): + if d.isMsvcTarget(): + offset = 184 if is32bit else 248 + else: + offset = 180 if is32bit else 248 else: offset = 168 if is32bit else 248 elif qtVersion >= 0x050500: diff --git a/tests/auto/debugger/tst_offsets.cpp b/tests/auto/debugger/tst_offsets.cpp index ee39d08a768..11009cd8027 100644 --- a/tests/auto/debugger/tst_offsets.cpp +++ b/tests/auto/debugger/tst_offsets.cpp @@ -146,12 +146,22 @@ void tst_offsets::offsets_data() const int qtVersion = QT_VERSION; - if (qtVersion >= 0x50600) + if (qtVersion >= 0x50700) #ifdef Q_OS_WIN # ifdef Q_CC_MSVC OFFSET_TEST(QFilePrivate, fileName) << 184 << 248; # else // MinGW - OFFSET_TEST(QFilePrivate, fileName) << 164 << 248; + OFFSET_TEST(QFilePrivate, fileName) << 172 << 248; +# endif +#else + OFFSET_TEST(QFilePrivate, fileName) << 168 << 248; +#endif + else if (qtVersion >= 0x50600) +#ifdef Q_OS_WIN +# ifdef Q_CC_MSVC + OFFSET_TEST(QFilePrivate, fileName) << 184 << 248; +# else // MinGW + OFFSET_TEST(QFilePrivate, fileName) << 180 << 248; # endif #else OFFSET_TEST(QFilePrivate, fileName) << 168 << 248; From 47d24fe33cc18f9c8435ccae99ac77e158c8c705 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 21 Mar 2017 10:16:37 +0100 Subject: [PATCH 08/36] QmlDesigner: Add Q_INVOKABLE for QML Change-Id: I9541357498c0d0dcf24841a22f9bf5e3b08dc745 Reviewed-by: Thomas Hartmann --- .../qmldesigner/components/itemlibrary/itemlibrarywidget.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h index 7d24c842d1c..946dfc9b7d0 100644 --- a/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h +++ b/src/plugins/qmldesigner/components/itemlibrary/itemlibrarywidget.h @@ -82,10 +82,10 @@ public: void setResourcePath(const QString &resourcePath); - void startDragAndDrop(QVariant itemLibId); - void setModel(Model *model); + Q_INVOKABLE void startDragAndDrop(QVariant itemLibId); + protected: void removeImport(const QString &name); void addImport(const QString &name, const QString &version); From 4275fe1bbf113ee3d68d11c0c672ddd1cc3bc5df Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Tue, 21 Mar 2017 09:31:10 +0100 Subject: [PATCH 09/36] Welcome: Use specific role enums instead of UserRole arithmetic Change-Id: I7cbcbf8f4dcf22d2b780af295f577f82fff4c275 Reviewed-by: hjk --- src/plugins/projectexplorer/projectwelcomepage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp index 3e67f07da73..8f9029028e6 100644 --- a/src/plugins/projectexplorer/projectwelcomepage.cpp +++ b/src/plugins/projectexplorer/projectwelcomepage.cpp @@ -422,7 +422,7 @@ public: painter->drawPixmap(x + 11, y + 3, pixmap("project", Theme::Welcome_ForegroundSecondaryColor)); QString projectName = idx.data(Qt::DisplayRole).toString(); - QString projectPath = idx.data(Qt::UserRole + 1).toString(); + QString projectPath = idx.data(ProjectModel::FilePathRole).toString(); painter->setPen(themeColor(Theme::Welcome_ForegroundSecondaryColor)); painter->setFont(sizedFont(10, option.widget)); @@ -443,7 +443,7 @@ public: QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &idx) const final { QString projectName = idx.data(Qt::DisplayRole).toString(); - QString projectPath = idx.data(Qt::UserRole + 1).toString(); + QString projectPath = idx.data(ProjectModel::FilePathRole).toString(); QFontMetrics fm(sizedFont(13, option.widget)); int width = std::max(fm.width(projectName), fm.width(projectPath)) + 36; return QSize(width, 48); @@ -453,7 +453,7 @@ public: const QStyleOptionViewItem &, const QModelIndex &idx) final { if (ev->type() == QEvent::MouseButtonRelease) { - QString projectFile = idx.data(Qt::UserRole + 1).toString(); + QString projectFile = idx.data(ProjectModel::FilePathRole).toString(); ProjectExplorerPlugin::openProjectWelcomePage(projectFile); return true; } From 897ce16452da3c72b82ef0b8792432befdccc531 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Mon, 20 Mar 2017 17:16:54 +0100 Subject: [PATCH 10/36] Doc: Describe changes in the Search Change-Id: I2c4450719203383bae9951c75863fe90504a2d13 Reviewed-by: Orgad Shaneh --- doc/images/qtcreator-search-allprojects.png | Bin 6551 -> 14387 bytes doc/images/qtcreator-search-filesystem.png | Bin 8223 -> 20861 bytes doc/images/qtcreator-searchresults.png | Bin 8141 -> 28648 bytes doc/src/editors/creator-editors.qdoc | 42 +++++++++++--------- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/doc/images/qtcreator-search-allprojects.png b/doc/images/qtcreator-search-allprojects.png index f78038af4bbbf2915218528a8ad73a458a2b3a80..c48cd50b47299ffe91c701d4e306dd72e309d2fb 100644 GIT binary patch literal 14387 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 literal 6551 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ìPF{t(%`c7thLi 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 WtPY4em4i+mWbkzLb6Mw<&;$UTo13oy literal 8223 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 diff --git a/doc/images/qtcreator-searchresults.png b/doc/images/qtcreator-searchresults.png index 02835cbb4b4dfa1402b77b9d103aaccf7c223cd7..8a663c0e17917c9243dac92ca81423c078ef21a2 100644 GIT binary patch literal 28648 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 literal 8141 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 wCWZuohD2NS Date: Mon, 20 Mar 2017 18:27:41 +0100 Subject: [PATCH 11/36] Macros: Add missing break Change-Id: Icec6312195cd069f8a50fc3a378c7f4449082134 Reviewed-by: Nicolas Arnaud-Cormos Reviewed-by: Eike Ziller --- src/plugins/macros/findmacrohandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/macros/findmacrohandler.cpp b/src/plugins/macros/findmacrohandler.cpp index ee2709a9bec..ee5cc6ade5e 100644 --- a/src/plugins/macros/findmacrohandler.cpp +++ b/src/plugins/macros/findmacrohandler.cpp @@ -91,6 +91,7 @@ bool FindMacroHandler::executeEvent(const MacroEvent ¯oEvent) currentFind->replace(macroEvent.value(BEFORE).toString(), macroEvent.value(AFTER).toString(), (Core::FindFlags)macroEvent.value(FLAGS).toInt()); + break; case REPLACESTEP: currentFind->replaceStep(macroEvent.value(BEFORE).toString(), macroEvent.value(AFTER).toString(), From b86011c3751fd47eb7c00e76968b3e59f4ed55e6 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 20 Mar 2017 15:42:08 +0100 Subject: [PATCH 12/36] AutoTest: Avoid dead-lock of file system watcher Calling addPath() on the watcher could dead-lock on some operating systems as we were in an asynchronous process. Avoid calling addPath() from inside an asynchronous process and perform this call from synchronous context. Change-Id: I94cd401e12ccbb3526b8cc4232a9cff7ed552bbb Reviewed-by: David Schulz --- .../autotest/quick/quicktestparser.cpp | 39 +++++++++---------- src/plugins/autotest/quick/quicktestparser.h | 11 +++++- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp index c3440ce15d2..cb7e5a04646 100644 --- a/src/plugins/autotest/quick/quicktestparser.cpp +++ b/src/plugins/autotest/quick/quicktestparser.cpp @@ -37,13 +37,9 @@ #include #include -#include - namespace Autotest { namespace Internal { -static QFileSystemWatcher s_directoryWatcher; - TestTreeItem *QuickTestParseResult::createTestTreeItem() const { if (itemType == TestTreeItem::Root || itemType == TestTreeItem::TestDataTag) @@ -126,7 +122,7 @@ static QString quickTestName(const CPlusPlus::Document::Ptr &doc) return QString(); } -static QList scanDirectoryForQuickTestQmlFiles(const QString &srcDir) +QList QuickTestParser::scanDirectoryForQuickTestQmlFiles(const QString &srcDir) const { QStringList dirs(srcDir); QmlJS::ModelManagerInterface *qmlJsMM = QmlJSTools::Internal::ModelManager::instance(); @@ -142,9 +138,9 @@ static QList scanDirectoryForQuickTestQmlFiles(const QStri while (it.hasNext()) { it.next(); QFileInfo fi(it.fileInfo().canonicalFilePath()); - dirs << fi.filePath(); + dirs.append(fi.filePath()); } - s_directoryWatcher.addPaths(dirs); + emit updateWatchPaths(dirs); QList foundDocs; @@ -211,9 +207,9 @@ static bool checkQmlDocumentForQuickTestCode(QFutureInterface futureInterface, - CPlusPlus::Document::Ptr document, - const Core::Id &id) +bool QuickTestParser::handleQtQuickTest(QFutureInterface futureInterface, + CPlusPlus::Document::Ptr document, + const Core::Id &id) const { const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); if (quickTestName(document).isEmpty()) @@ -229,32 +225,35 @@ static bool handleQtQuickTest(QFutureInterface futureInterfa if (srcDir.isEmpty()) return false; + if (futureInterface.isCanceled()) + return false; const QList qmlDocs = scanDirectoryForQuickTestQmlFiles(srcDir); bool result = false; - for (const QmlJS::Document::Ptr &qmlJSDoc : qmlDocs) + for (const QmlJS::Document::Ptr &qmlJSDoc : qmlDocs) { + if (futureInterface.isCanceled()) + break; result |= checkQmlDocumentForQuickTestCode(futureInterface, qmlJSDoc, id, proFile); + } return result; } QuickTestParser::QuickTestParser() : CppParser() { - QObject::connect(ProjectExplorer::SessionManager::instance(), - &ProjectExplorer::SessionManager::startupProjectChanged, [] { - const QStringList &dirs = s_directoryWatcher.directories(); + connect(ProjectExplorer::SessionManager::instance(), + &ProjectExplorer::SessionManager::startupProjectChanged, [this] { + const QStringList &dirs = m_directoryWatcher.directories(); if (!dirs.isEmpty()) - s_directoryWatcher.removePaths(dirs); + m_directoryWatcher.removePaths(dirs); }); - QObject::connect(&s_directoryWatcher, &QFileSystemWatcher::directoryChanged, + connect(&m_directoryWatcher, &QFileSystemWatcher::directoryChanged, [this] { TestTreeModel::instance()->parser()->emitUpdateTestTree(this); }); + connect(this, &QuickTestParser::updateWatchPaths, + &m_directoryWatcher, &QFileSystemWatcher::addPaths, Qt::QueuedConnection); } QuickTestParser::~QuickTestParser() { - QObject::disconnect(&s_directoryWatcher, 0, 0, 0); - const QStringList &dirs = s_directoryWatcher.directories(); - if (!dirs.isEmpty()) - s_directoryWatcher.removePaths(dirs); } void QuickTestParser::init(const QStringList &filesToParse) diff --git a/src/plugins/autotest/quick/quicktestparser.h b/src/plugins/autotest/quick/quicktestparser.h index 9258599e717..26ba514f2fb 100644 --- a/src/plugins/autotest/quick/quicktestparser.h +++ b/src/plugins/autotest/quick/quicktestparser.h @@ -29,6 +29,8 @@ #include +#include + namespace Autotest { namespace Internal { @@ -39,8 +41,9 @@ public: TestTreeItem *createTestTreeItem() const override; }; -class QuickTestParser : public CppParser +class QuickTestParser : public QObject, public CppParser { + Q_OBJECT public: QuickTestParser(); virtual ~QuickTestParser(); @@ -48,9 +51,15 @@ public: void release() override; bool processDocument(QFutureInterface futureInterface, const QString &fileName) override; +signals: + void updateWatchPaths(const QStringList &directories) const; private: + bool handleQtQuickTest(QFutureInterface futureInterface, + CPlusPlus::Document::Ptr document, const Core::Id &id) const; + QList scanDirectoryForQuickTestQmlFiles(const QString &srcDir) const; QmlJS::Snapshot m_qmlSnapshot; QHash m_proFilesForQmlFiles; + QFileSystemWatcher m_directoryWatcher; }; } // namespace Internal From da03ab72af33978271c53d1ff1545a6b70a0523e Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 21 Mar 2017 10:11:37 +0100 Subject: [PATCH 13/36] Tests: Exclude connections check for cdb Change-Id: I1f3a1ed0bb130a7d4dc413c15c4fd32cb496a7ab Reviewed-by: David Schulz --- tests/auto/debugger/tst_dumpers.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index eb3fa0dd5f4..5fd4e09ab0b 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -2724,7 +2724,8 @@ void tst_Dumpers::dumper_data() + Check("ob", "\"An Object\"", "@QWidget") + Check("ob1", "\"Another Object\"", "@QObject") + Check("ob2", "\"A Subobject\"", "@QObject") - + Check("ob.[extra].[connections].0.0.receiver", "\"Another Object\"", "@QObject"); + + Check("ob.[extra].[connections].0.0.receiver", "\"Another Object\"", + "@QObject") % NoCdbEngine; QString senderData = From 13643362541a17ec55c7bd63c91f539a3b4ee4b5 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 19 Mar 2017 19:31:56 +0200 Subject: [PATCH 14/36] Utils: Remove old style connection Change-Id: I725a1611cd5547e51d3acb3802938c91cbf32cf4 Reviewed-by: hjk --- src/libs/utils/basetreeview.cpp | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/src/libs/utils/basetreeview.cpp b/src/libs/utils/basetreeview.cpp index a3bc33f0c1a..abe01ada6e1 100644 --- a/src/libs/utils/basetreeview.cpp +++ b/src/libs/utils/basetreeview.cpp @@ -26,6 +26,7 @@ #include "basetreeview.h" #include "progressindicator.h" +#include "treemodel.h" #include @@ -271,35 +272,14 @@ BaseTreeView::~BaseTreeView() void BaseTreeView::setModel(QAbstractItemModel *m) { - struct ExtraConnection { - const char *signature; - const char *qsignal; - QObject *receiver; - const char *qslot; - }; -#define DESC(sign, receiver, slot) { #sign, SIGNAL(sign), receiver, SLOT(slot) } - const ExtraConnection c[] = { - DESC(requestExpansion(QModelIndex), this, expand(QModelIndex)) - }; -#undef DESC - - QAbstractItemModel *oldModel = model(); - if (oldModel) { - for (unsigned i = 0; i < sizeof(c) / sizeof(c[0]); ++i) { - int index = model()->metaObject()->indexOfSignal(c[i].signature); - if (index != -1) - disconnect(model(), c[i].qsignal, c[i].receiver, c[i].qslot); - } - } + if (BaseTreeModel *oldModel = qobject_cast(model())) + disconnect(oldModel, &BaseTreeModel::requestExpansion, this, &BaseTreeView::expand); TreeView::setModel(m); if (m) { - for (unsigned i = 0; i < sizeof(c) / sizeof(c[0]); ++i) { - int index = m->metaObject()->indexOfSignal(c[i].signature); - if (index != -1) - connect(model(), c[i].qsignal, c[i].receiver, c[i].qslot); - } + if (BaseTreeModel *newModel = qobject_cast(m)) + connect(newModel, &BaseTreeModel::requestExpansion, this, &BaseTreeView::expand); d->restoreState(); QVariant delegateBlob = m->data(QModelIndex(), ItemDelegateRole); From 9a9f1f9cfe246dae7eb5d46e5d13585bc4dfe44c Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Tue, 21 Mar 2017 12:40:22 +0100 Subject: [PATCH 15/36] QmlProfiler: Add comments about deliberate fallthroughs Change-Id: Ia9a7d62f8f3dbc753f2746f3f53f5557d9607d45 Reviewed-by: Ulf Hermann --- src/plugins/qmlprofiler/inputeventsmodel.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/qmlprofiler/inputeventsmodel.cpp b/src/plugins/qmlprofiler/inputeventsmodel.cpp index 0d1f91d2b80..0c7e9b50fc8 100644 --- a/src/plugins/qmlprofiler/inputeventsmodel.cpp +++ b/src/plugins/qmlprofiler/inputeventsmodel.cpp @@ -84,6 +84,7 @@ QVariantMap InputEventsModel::details(int index) const switch (event.type) { case InputKeyPress: type = tr("Key Press"); + // fallthrough case InputKeyRelease: if (type.isEmpty()) type = tr("Key Release"); @@ -97,9 +98,11 @@ QVariantMap InputEventsModel::details(int index) const break; case InputMouseDoubleClick: type = tr("Double Click"); + // fallthrough case InputMousePress: if (type.isEmpty()) type = tr("Mouse Press"); + // fallthrough case InputMouseRelease: if (type.isEmpty()) type = tr("Mouse Release"); From 8b1b5e9a80dc6429480ade3711cba3dcf3c765a8 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 21 Mar 2017 13:09:42 +0100 Subject: [PATCH 16/36] fix warning "there is */ outside of a comment" Change-Id: I86d7ce281a7395f9be4d74f353d7d57c7bb5dedc Reviewed-by: Eike Ziller --- src/plugins/silversearcher/findinfilessilversearcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/silversearcher/findinfilessilversearcher.cpp b/src/plugins/silversearcher/findinfilessilversearcher.cpp index 3d40de93490..613066de365 100644 --- a/src/plugins/silversearcher/findinfilessilversearcher.cpp +++ b/src/plugins/silversearcher/findinfilessilversearcher.cpp @@ -192,7 +192,7 @@ IEditor *FindInFilesSilverSearcher::openEditor(const SearchResultItem & /*item*/ return 0; } -void FindInFilesSilverSearcher::readSettings(QSettings */*settings*/) +void FindInFilesSilverSearcher::readSettings(QSettings * /*settings*/) { } From 312784a930078992c290b330a7e41ea219a6e3b1 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Tue, 21 Mar 2017 13:16:47 +0100 Subject: [PATCH 17/36] QmlProfiler: Avoid overflows in loadEvent Change-Id: I23271d6dc8ede3f76ef712547519b04dc86d94a6 Reviewed-by: Ulf Hermann --- src/plugins/qmlprofiler/pixmapcachemodel.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/plugins/qmlprofiler/pixmapcachemodel.cpp b/src/plugins/qmlprofiler/pixmapcachemodel.cpp index 6ea4d5db2b6..5af3a124021 100644 --- a/src/plugins/qmlprofiler/pixmapcachemodel.cpp +++ b/src/plugins/qmlprofiler/pixmapcachemodel.cpp @@ -208,9 +208,10 @@ void PixmapCacheModel::loadEvent(const QmlEvent &event, const QmlEventType &type PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; if (state.cacheState == ToBeCached) { - m_lastCacheSizeEvent = updateCacheCount(m_lastCacheSizeEvent, pixmapStartTime, - state.size.width() * state.size.height(), newEvent, - event.typeIndex()); + m_lastCacheSizeEvent = updateCacheCount( + m_lastCacheSizeEvent, pixmapStartTime, + (qint64) state.size.width() * (qint64) state.size.height(), + newEvent, event.typeIndex()); state.cacheState = Cached; } break; @@ -230,7 +231,7 @@ void PixmapCacheModel::loadEvent(const QmlEvent &event, const QmlEventType &type } else if (!uncache && i->cacheState == Uncached) { newEvent.sizeIndex = i - pixmap.sizes.begin(); if (i->size.isValid()) { - pixSize = i->size.width() * i->size.height(); + pixSize = (qint64) i->size.width() * i->size.height(); i->cacheState = Cached; } else { i->cacheState = ToBeCached; @@ -247,7 +248,7 @@ void PixmapCacheModel::loadEvent(const QmlEvent &event, const QmlEventType &type if (uncache && (i->cacheState == Cached || i->cacheState == ToBeCached)) { newEvent.sizeIndex = i - pixmap.sizes.begin(); if (i->size.isValid()) - pixSize = -i->size.width() * i->size.height(); + pixSize = (qint64) -i->size.width() * i->size.height(); i->cacheState = Uncached; break; } else if (!uncache && i->cacheState == Uncacheable) { From ebae6426f8246f21ac6354147d67efcde782c624 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 17 Mar 2017 12:26:00 +0100 Subject: [PATCH 18/36] ProjectManager: Remove SessionNode Instead, get root project nodes directly from the project. Change-Id: I5cf95a7dce1fa29c1adc26013ad03cc017f38a6d Reviewed-by: Tobias Hunger --- src/plugins/modeleditor/pxnodecontroller.cpp | 2 - src/plugins/modeleditor/pxnodeutilities.cpp | 3 - src/plugins/projectexplorer/project.cpp | 53 +++++++- src/plugins/projectexplorer/project.h | 2 +- src/plugins/projectexplorer/projectmodels.cpp | 82 +++++------- src/plugins/projectexplorer/projectmodels.h | 1 - src/plugins/projectexplorer/projectnodes.cpp | 45 +------ src/plugins/projectexplorer/projectnodes.h | 23 +--- src/plugins/projectexplorer/projecttree.cpp | 20 +-- src/plugins/projectexplorer/projecttree.h | 6 +- .../projectexplorer/projecttreewidget.cpp | 34 ++--- .../projectexplorer/projectwizardpage.cpp | 33 ++--- .../projectexplorer/projectwizardpage.h | 2 +- src/plugins/projectexplorer/session.cpp | 121 +++++------------- src/plugins/projectexplorer/session.h | 8 +- 15 files changed, 165 insertions(+), 270 deletions(-) diff --git a/src/plugins/modeleditor/pxnodecontroller.cpp b/src/plugins/modeleditor/pxnodecontroller.cpp index dfd03932038..e272c67f6ff 100644 --- a/src/plugins/modeleditor/pxnodecontroller.cpp +++ b/src/plugins/modeleditor/pxnodecontroller.cpp @@ -198,8 +198,6 @@ void PxNodeController::addExplorerNode(const ProjectExplorer::Node *node, menu->popup(QCursor::pos()); break; } - case ProjectExplorer::NodeType::Session: - break; } } diff --git a/src/plugins/modeleditor/pxnodeutilities.cpp b/src/plugins/modeleditor/pxnodeutilities.cpp index 6df0e93a97f..31fede39fbd 100644 --- a/src/plugins/modeleditor/pxnodeutilities.cpp +++ b/src/plugins/modeleditor/pxnodeutilities.cpp @@ -80,9 +80,6 @@ QString PxNodeUtilities::calcRelativePath(const ProjectExplorer::Node *node, case ProjectExplorer::NodeType::Project: nodePath = node->filePath().toString(); break; - case ProjectExplorer::NodeType::Session: - QTC_ASSERT(false, return QString()); - break; } return qmt::NameController::calcRelativePath(nodePath, anchorFolder); diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index 7d283d39011..fee9f07f354 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -39,6 +39,9 @@ #include #include #include +#include +#include + #include #include #include @@ -80,18 +83,52 @@ const char PLUGIN_SETTINGS_KEY[] = "ProjectExplorer.Project.PluginSettings"; } // namespace namespace ProjectExplorer { + +class ContainerNode : public ProjectNode +{ +public: + ContainerNode(Project *project) + : ProjectNode(Utils::FileName()), + m_project(project) + {} + + QString displayName() const final + { + QString name = m_project->displayName(); + + const QFileInfo fi = m_project->projectFilePath().toFileInfo(); + const QString dir = fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath(); + if (Core::IVersionControl *vc = Core::VcsManager::findVersionControlForDirectory(dir)) { + QString vcsTopic = vc->vcsTopic(dir); + if (!vcsTopic.isEmpty()) + name += " [" + vcsTopic + ']'; + } + + return name; + } + + QList supportedActions(Node *) const final + { + return {}; + } + +private: + Project *m_project; +}; + // ------------------------------------------------------------------------- // Project // ------------------------------------------------------------------------- - class ProjectPrivate { public: + ProjectPrivate(Project *owner) : m_containerNode(owner) {} ~ProjectPrivate(); Core::Id m_id; Core::IDocument *m_document = nullptr; ProjectNode *m_rootProjectNode = nullptr; + ContainerNode m_containerNode; QList m_targets; Target *m_activeTarget = nullptr; EditorConfiguration m_editorConfiguration; @@ -117,7 +154,7 @@ ProjectPrivate::~ProjectPrivate() delete m_accessor; } -Project::Project() : d(new ProjectPrivate) +Project::Project() : d(new ProjectPrivate(this)) { d->m_macroExpander.setDisplayName(tr("Project")); d->m_macroExpander.registerVariable("Project:Name", tr("Project Name"), @@ -427,8 +464,11 @@ void Project::setRootProjectNode(ProjectNode *root) ProjectTree::applyTreeManager(root); d->m_rootProjectNode = root; - emit projectTreeChanged(this, QPrivateSignal()); - // Do not delete oldNode! The ProjectTree owns that! + if (root) + d->m_rootProjectNode->setParentFolderNode(&d->m_containerNode); + ProjectTree::emitSubtreeChanged(d->m_rootProjectNode); + + delete d->m_rootProjectNode; } Target *Project::restoreTarget(const QVariantMap &data) @@ -532,6 +572,11 @@ ProjectNode *Project::rootProjectNode() const return d->m_rootProjectNode; } +ProjectNode *Project::containerNode() const +{ + return &d->m_containerNode; +} + Project::RestoreResult Project::fromMap(const QVariantMap &map, QString *errorMessage) { Q_UNUSED(errorMessage); diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h index 3ca35707fcf..8de6d9ec21b 100644 --- a/src/plugins/projectexplorer/project.h +++ b/src/plugins/projectexplorer/project.h @@ -81,6 +81,7 @@ public: static Utils::FileName projectDirectory(const Utils::FileName &top); virtual ProjectNode *rootProjectNode() const; + ProjectNode *containerNode() const; bool hasActiveBuildSettings() const; @@ -142,7 +143,6 @@ public: Utils::MacroExpander *macroExpander() const; signals: - void projectTreeChanged(Project *project, QPrivateSignal); void displayNameChanged(); void fileListChanged(); diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp index 1a362da0c52..53be442b194 100644 --- a/src/plugins/projectexplorer/projectmodels.cpp +++ b/src/plugins/projectexplorer/projectmodels.cpp @@ -71,7 +71,7 @@ static bool sortWrapperNodes(const WrapperNode *w1, const WrapperNode *w2) } FlatModel::FlatModel(QObject *parent) - : TreeModel(new WrapperNode(SessionManager::sessionNode()), parent) + : TreeModel(new WrapperNode(nullptr), parent) { ProjectTree *tree = ProjectTree::instance(); connect(tree, &ProjectTree::subtreeChanged, this, &FlatModel::update); @@ -93,17 +93,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const FolderNode *folderNode = node->asFolderNode(); switch (role) { case Qt::DisplayRole: { - QString name = node->displayName(); - if (node->nodeType() == NodeType::Project - && node->parentFolderNode() - && node->parentFolderNode()->nodeType() == NodeType::Session) { - const QString vcsTopic = static_cast(node)->vcsTopic(); - - if (!vcsTopic.isEmpty()) - name += QLatin1String(" [") + vcsTopic + QLatin1Char(']'); - } - - result = name; + result = node->displayName(); break; } case Qt::EditRole: { @@ -124,7 +114,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const case Qt::FontRole: { QFont font; if (Project *project = SessionManager::startupProject()) { - if (node == SessionManager::nodeForProject(project)) + if (node == project->containerNode()) font.setBold(true); } result = font; @@ -187,23 +177,44 @@ void FlatModel::update() void FlatModel::rebuildModel() { + QList projects = SessionManager::projects(); + + Utils::sort(projects, [](Project *p1, Project *p2) { + const int displayNameResult = caseFriendlyCompare(p1->displayName(), p2->displayName()); + if (displayNameResult != 0) + return displayNameResult < 0; + return p1 < p2; // sort by pointer value + }); + QSet seen; rootItem()->removeChildren(); - for (Node *node : SessionManager::sessionNode()->nodes()) { - if (ProjectNode *projectNode = node->asProjectNode()) { - if (!seen.contains(projectNode)) - addProjectNode(rootItem(), projectNode, &seen); + for (Project *project : projects) { + WrapperNode *container = new WrapperNode(project->containerNode()); + + ProjectNode *projectNode = project->rootProjectNode(); + if (projectNode) { + addFolderNode(container, projectNode, &seen); + } else { + FileNode *projectFileNode = new FileNode(project->projectFilePath(), FileType::Project, false); + seen.insert(projectFileNode); + container->appendChild(new WrapperNode(projectFileNode)); } + + container->sortChildren(&sortWrapperNodes); + rootItem()->appendChild(container); } - rootItem()->sortChildren(&sortWrapperNodes); forAllItems([this](WrapperNode *node) { - const QString path = node->m_node->filePath().toString(); - const QString displayName = node->m_node->displayName(); - ExpandData ed(path, displayName); - if (m_toExpand.contains(ed)) + if (node->m_node) { + const QString path = node->m_node->filePath().toString(); + const QString displayName = node->m_node->displayName(); + ExpandData ed(path, displayName); + if (m_toExpand.contains(ed)) + emit requestExpansion(node->index()); + } else { emit requestExpansion(node->index()); + } }); } @@ -227,7 +238,7 @@ ExpandData FlatModel::expandDataForNode(const Node *node) const void FlatModel::handleProjectAdded(Project *project) { - Node *node = SessionManager::nodeForProject(project); + Node *node = project->rootProjectNode(); m_toExpand.insert(expandDataForNode(node)); if (WrapperNode *wrapper = wrapperForNode(node)) { wrapper->forFirstLevelChildren([this](WrapperNode *child) { @@ -251,21 +262,6 @@ void FlatModel::saveExpandData() SessionManager::setValue(QLatin1String("ProjectTree.ExpandData"), data); } -void FlatModel::addProjectNode(WrapperNode *parent, ProjectNode *projectNode, QSet *seen) -{ - seen->insert(projectNode); - auto node = new WrapperNode(projectNode); - parent->appendChild(node); - addFolderNode(node, projectNode, seen); - for (Node *subNode : projectNode->nodes()) { - if (ProjectNode *subProjectNode = subNode->asProjectNode()) { - if (!seen->contains(subProjectNode)) - addProjectNode(node, subProjectNode, seen); - } - } - node->sortChildren(&sortWrapperNodes); -} - void FlatModel::addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet *seen) { const QList subFolderNodes = folderNode->folderNodes(); @@ -374,16 +370,6 @@ const QLoggingCategory &FlatModel::logger() return logger; } -bool isSorted(const QList &nodes) -{ - int size = nodes.size(); - for (int i = 0; i < size -1; ++i) { - if (!sortNodes(nodes.at(i), nodes.at(i+1))) - return false; - } - return true; -} - namespace Internal { int caseFriendlyCompare(const QString &a, const QString &b) diff --git a/src/plugins/projectexplorer/projectmodels.h b/src/plugins/projectexplorer/projectmodels.h index 25a808ce35c..8d177c8b0c7 100644 --- a/src/plugins/projectexplorer/projectmodels.h +++ b/src/plugins/projectexplorer/projectmodels.h @@ -94,7 +94,6 @@ private: void update(); void rebuildModel(); - void addProjectNode(WrapperNode *parent, ProjectNode *projectNode, QSet *seen); void addFolderNode(WrapperNode *parent, FolderNode *folderNode, QSet *seen); ExpandData expandDataForNode(const Node *node) const; diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp index 8557b99003f..0d3b102522d 100644 --- a/src/plugins/projectexplorer/projectnodes.cpp +++ b/src/plugins/projectexplorer/projectnodes.cpp @@ -214,9 +214,12 @@ bool Node::isEnabled() const QList Node::supportedActions(Node *node) const { - QList list = parentFolderNode()->supportedActions(node); - list.append(InheritedFromParent); - return list; + if (FolderNode *folder = parentFolderNode()) { + QList list = folder->supportedActions(node); + list.append(InheritedFromParent); + return list; + } + return {}; } void Node::setEnabled(bool enabled) @@ -702,18 +705,6 @@ ProjectNode::ProjectNode(const Utils::FileName &projectFilePath) : setDisplayName(projectFilePath.fileName()); } -QString ProjectNode::vcsTopic() const -{ - const QFileInfo fi = filePath().toFileInfo(); - const QString dir = fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath(); - - if (Core::IVersionControl *const vc = - Core::VcsManager::findVersionControlForDirectory(dir)) - return vc->vcsTopic(dir); - - return QString(); -} - bool ProjectNode::canAddSubProject(const QString &proFilePath) const { Q_UNUSED(proFilePath) @@ -797,28 +788,4 @@ bool FolderNode::isEmpty() const return m_nodes.isEmpty(); } -/*! - \class ProjectExplorer::SessionNode -*/ - -SessionNode::SessionNode() : - FolderNode(Utils::FileName::fromString("session"), NodeType::Session) -{ } - -QList SessionNode::supportedActions(Node *node) const -{ - Q_UNUSED(node) - return QList(); -} - -bool SessionNode::showInSimpleTree() const -{ - return true; -} - -QString SessionNode::addFileFilter() const -{ - return QString::fromLatin1("*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.hpp; *.hxx;"); -} - } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h index fb17b4806e8..757529da8b5 100644 --- a/src/plugins/projectexplorer/projectnodes.h +++ b/src/plugins/projectexplorer/projectnodes.h @@ -40,14 +40,12 @@ namespace Utils { class MimeType; } namespace ProjectExplorer { class RunConfiguration; -class SessionManager; enum class NodeType : quint16 { File = 1, Folder, VirtualFolder, - Project, - Session + Project }; // File types common for qt projects @@ -275,8 +273,6 @@ private: class PROJECTEXPLORER_EXPORT ProjectNode : public FolderNode { public: - QString vcsTopic() const; - virtual bool canAddSubProject(const QString &proFilePath) const; virtual bool addSubProject(const QString &proFile); virtual bool removeSubProject(const QString &proFilePath); @@ -298,24 +294,7 @@ public: const ProjectNode *asProjectNode() const final { return this; } protected: - // this is just the in-memory representation, a subclass - // will add the persistent stuff explicit ProjectNode(const Utils::FileName &projectFilePath); - - friend class SessionManager; -}; - -// Documentation inside. -class PROJECTEXPLORER_EXPORT SessionNode : public FolderNode -{ -public: - SessionNode(); - -private: - QList supportedActions(Node *node) const final; - QString addFileFilter() const final; - - bool showInSimpleTree() const final; }; } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp index 86d8ef1d269..6d32406015a 100644 --- a/src/plugins/projectexplorer/projecttree.cpp +++ b/src/plugins/projectexplorer/projecttree.cpp @@ -261,9 +261,6 @@ void ProjectTree::updateContext() void ProjectTree::emitSubtreeChanged(FolderNode *node) { - if (!SessionManager::sessionNode()->isAncesterOf(node)) - return; - emit s_instance->subtreeChanged(node); } @@ -318,16 +315,15 @@ bool ProjectTree::hasFocus(ProjectTreeWidget *widget) void ProjectTree::showContextMenu(ProjectTreeWidget *focus, const QPoint &globalPos, Node *node) { QMenu *contextMenu = nullptr; + Project *project = SessionManager::projectForNode(node); + emit s_instance->aboutToShowContextMenu(project, node); - if (!node) - node = SessionManager::sessionNode(); - if (node->nodeType() != NodeType::Session) { - Project *project = SessionManager::projectForNode(node); - - emit s_instance->aboutToShowContextMenu(project, node); + if (!node) { + contextMenu = Core::ActionManager::actionContainer(Constants::M_SESSIONCONTEXT)->menu(); + } else { switch (node->nodeType()) { case NodeType::Project: - if (node->parentFolderNode() == SessionManager::sessionNode()) + if (node->parentFolderNode()) contextMenu = Core::ActionManager::actionContainer(Constants::M_PROJECTCONTEXT)->menu(); else contextMenu = Core::ActionManager::actionContainer(Constants::M_SUBPROJECTCONTEXT)->menu(); @@ -342,10 +338,6 @@ void ProjectTree::showContextMenu(ProjectTreeWidget *focus, const QPoint &global default: qWarning("ProjectExplorerPlugin::showContextMenu - Missing handler for node type"); } - } else { // session item - emit s_instance->aboutToShowContextMenu(nullptr, node); - - contextMenu = Core::ActionManager::actionContainer(Constants::M_SESSIONCONTEXT)->menu(); } if (contextMenu && contextMenu->actions().count() > 0) { diff --git a/src/plugins/projectexplorer/projecttree.h b/src/plugins/projectexplorer/projecttree.h index 74f0c53a2cb..eb84adf58b7 100644 --- a/src/plugins/projectexplorer/projecttree.h +++ b/src/plugins/projectexplorer/projecttree.h @@ -70,6 +70,9 @@ public: void collapseAll(); + // for nodes to emit signals, do not call unless you are a node + static void emitSubtreeChanged(FolderNode *node); + signals: void currentProjectChanged(ProjectExplorer::Project *project); void currentNodeChanged(); @@ -80,9 +83,6 @@ signals: void aboutToShowContextMenu(ProjectExplorer::Project *project, ProjectExplorer::Node *node); -public: // for nodes to emit signals, do not call unless you are a node - static void emitSubtreeChanged(FolderNode *node); - private: void sessionChanged(); void focusChanged(); diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp index 67bbf074051..372dbdb7576 100644 --- a/src/plugins/projectexplorer/projecttreewidget.cpp +++ b/src/plugins/projectexplorer/projecttreewidget.cpp @@ -275,23 +275,27 @@ Node *ProjectTreeWidget::nodeForFile(const Utils::FileName &fileName) Node *bestNode = nullptr; int bestNodeExpandCount = INT_MAX; - SessionManager::sessionNode()->forEachGenericNode([&](Node *node) { - if (node->filePath() == fileName) { - if (!bestNode) { - bestNode = node; - bestNodeExpandCount = ProjectTreeWidget::expandedCount(node); - } else if (node->nodeType() < bestNode->nodeType()) { - bestNode = node; - bestNodeExpandCount = ProjectTreeWidget::expandedCount(node); - } else if (node->nodeType() == bestNode->nodeType()) { - int nodeExpandCount = ProjectTreeWidget::expandedCount(node); - if (nodeExpandCount < bestNodeExpandCount) { - bestNode = node; - bestNodeExpandCount = ProjectTreeWidget::expandedCount(node); + for (Project *project : SessionManager::projects()) { + if (ProjectNode *projectNode = project->rootProjectNode()) { + projectNode->forEachGenericNode([&](Node *node) { + if (node->filePath() == fileName) { + if (!bestNode) { + bestNode = node; + bestNodeExpandCount = ProjectTreeWidget::expandedCount(node); + } else if (node->nodeType() < bestNode->nodeType()) { + bestNode = node; + bestNodeExpandCount = ProjectTreeWidget::expandedCount(node); + } else if (node->nodeType() == bestNode->nodeType()) { + int nodeExpandCount = ProjectTreeWidget::expandedCount(node); + if (nodeExpandCount < bestNodeExpandCount) { + bestNode = node; + bestNodeExpandCount = ProjectTreeWidget::expandedCount(node); + } + } } - } + }); } - }); + } return bestNode; } diff --git a/src/plugins/projectexplorer/projectwizardpage.cpp b/src/plugins/projectexplorer/projectwizardpage.cpp index 6a5c2bd261a..88756a3599c 100644 --- a/src/plugins/projectexplorer/projectwizardpage.cpp +++ b/src/plugins/projectexplorer/projectwizardpage.cpp @@ -26,6 +26,7 @@ #include "projectwizardpage.h" #include "ui_projectwizardpage.h" +#include "project.h" #include "projectexplorer.h" #include "session.h" @@ -300,18 +301,14 @@ ProjectWizardPage::~ProjectWizardPage() { disconnect(m_ui->projectComboBox, static_cast(&QComboBox::currentIndexChanged), this, &ProjectWizardPage::projectChanged); - delete m_model; delete m_ui; } void ProjectWizardPage::setModel(Utils::TreeModel<> *model) { - delete m_model; - m_model = model; - // TODO see OverViewCombo and OverView for click event filter m_ui->projectComboBox->setModel(model); - bool enabled = m_model->rowCount(QModelIndex()) > 1; + bool enabled = m_model.rowCount(QModelIndex()) > 1; m_ui->projectComboBox->setEnabled(enabled); expandTree(QModelIndex()); @@ -324,9 +321,9 @@ bool ProjectWizardPage::expandTree(const QModelIndex &root) expand = true; // Check children - int count = m_model->rowCount(root); + int count = m_model.rowCount(root); for (int i = 0; i < count; ++i) { - if (expandTree(m_model->index(i, 0, root))) + if (expandTree(m_model.index(i, 0, root))) expand = true; } @@ -346,7 +343,7 @@ bool ProjectWizardPage::expandTree(const QModelIndex &root) void ProjectWizardPage::setBestNode(AddNewTree *tree) { - QModelIndex index = tree ? m_model->indexForItem(tree) : QModelIndex(); + QModelIndex index = tree ? m_model.indexForItem(tree) : QModelIndex(); m_ui->projectComboBox->setCurrentIndex(index); while (index.isValid()) { @@ -454,28 +451,22 @@ void ProjectWizardPage::initializeProjectTree(Node *context, const QStringList & { BestNodeSelector selector(m_commonDirectory, paths); - AddNewTree *tree; - SessionNode *root = SessionManager::sessionNode(); - QList children; - - for (Node *node : root->nodes()) { - if (ProjectNode *pn = node->asProjectNode()) { + TreeItem *root = m_model.rootItem(); + root->removeChildren(); + for (Project *project : SessionManager::projects()) { + if (ProjectNode *pn = project->rootProjectNode()) { if (kind == IWizardFactory::ProjectWizard) { if (AddNewTree *child = buildAddProjectTree(pn, paths.first(), context, &selector)) - children.append(child); + root->appendChild(child); } else { if (AddNewTree *child = buildAddFilesTree(pn, paths, context, &selector)) - children.append(child); + root->appendChild(child); } } } - - children.prepend(createNoneNode(&selector)); - tree = new AddNewTree(root, children, root->displayName()); + root->prependChild(createNoneNode(&selector)); setAdditionalInfo(selector.deployingProjects()); - - setModel(new TreeModel<>(tree)); setBestNode(selector.bestChoice()); setAddingSubProject(action == AddSubProject); } diff --git a/src/plugins/projectexplorer/projectwizardpage.h b/src/plugins/projectexplorer/projectwizardpage.h index ce4f77d6251..1516a87cfe8 100644 --- a/src/plugins/projectexplorer/projectwizardpage.h +++ b/src/plugins/projectexplorer/projectwizardpage.h @@ -95,7 +95,7 @@ private: Ui::WizardPage *m_ui; QStringList m_projectToolTips; - Utils::TreeModel<> *m_model = nullptr; + Utils::TreeModel<> m_model; QList m_activeVersionControls; QString m_commonDirectory; diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp index 2e87aef4ff7..9286155bfbc 100644 --- a/src/plugins/projectexplorer/session.cpp +++ b/src/plugins/projectexplorer/session.cpp @@ -92,13 +92,7 @@ public: static QString sessionTitle(const QString &filePath); bool hasProjects() const { return !m_projects.isEmpty(); } - bool hasProject(Project *p) const - { - return Utils::contains(m_projects, - [p](const QPair &pair) { return pair.first == p; }); - } - SessionNode m_sessionNode; QString m_sessionName = QLatin1String("default"); bool m_virginSession = true; bool m_loadingSession = false; @@ -110,7 +104,7 @@ public: mutable QHash m_projectFileCache; Project *m_startupProject = nullptr; - QList> m_projects; + QList m_projects; QStringList m_failedProjects; QMap m_depMap; QMap m_values; @@ -188,36 +182,6 @@ void SessionManager::clearProjectFileCache() d->m_projectFileCache.clear(); } -void SessionManager::updateProjectTree(Project *pro) -{ - if (!pro) - return; - - QPair *currentPair = nullptr; - for (QPair &pair : d->m_projects) { - if (pair.first == pro) { - currentPair = &pair; - break; - } - } - - if (!currentPair) - return; // Project was already de-registered and is shutting down - - ProjectNode *const oldNode = currentPair->second; - ProjectNode *newNode = pro->rootProjectNode(); - - if (!newNode) { - // Set up generic project structure if the project does not provide any! - newNode = new ProjectNode(pro->projectDirectory()); - newNode->setDisplayName(pro->displayName()); - newNode->addNode(new FileNode(pro->projectFilePath(), FileType::Project, false)); - } - - d->m_sessionNode.replaceSubtree(oldNode, newNode); - currentPair->second = newNode; -} - bool SessionManagerPrivate::recursiveDependencyCheck(const QString &newDep, const QString &checkDep) const { if (newDep == checkDep) @@ -393,8 +357,8 @@ void SessionManager::setActiveDeployConfiguration(Target *target, DeployConfigur void SessionManager::setStartupProject(Project *startupProject) { - QTC_ASSERT((!startupProject) - || (startupProject && hasProject(startupProject)), return); + QTC_ASSERT(!startupProject + || (startupProject && d->m_projects.contains(startupProject)), return); if (d->m_startupProject == startupProject) return; @@ -413,13 +377,11 @@ void SessionManager::addProject(Project *pro) QTC_ASSERT(pro, return); d->m_virginSession = false; - QTC_ASSERT(!hasProject(pro), return); + QTC_ASSERT(!d->m_projects.contains(pro), return); - d->m_projects.append(qMakePair(pro, nullptr)); - m_instance->updateProjectTree(pro); + d->m_projects.append(pro); connect(pro, &Project::fileListChanged, m_instance, &SessionManager::clearProjectFileCache); - connect(pro, &Project::projectTreeChanged, m_instance, &SessionManager::updateProjectTree); emit m_instance->projectAdded(pro); configureEditors(pro); @@ -522,8 +484,7 @@ void SessionManager::closeAllProjects() const QList SessionManager::projects() { - return Utils::transform(d->m_projects, - [](const QPair &pair) { return pair.first; }); + return d->m_projects; } bool SessionManager::hasProjects() @@ -533,7 +494,7 @@ bool SessionManager::hasProjects() bool SessionManager::hasProject(Project *p) { - return d->hasProject(p); + return d->m_projects.contains(p); } QStringList SessionManagerPrivate::dependencies(const QString &proName) const @@ -604,8 +565,8 @@ QStringList SessionManagerPrivate::dependenciesOrder() const QStringList ordered; // copy the map to a temporary list - for (const QPair &pro : m_projects) { - const QString proName = pro.first->projectFilePath().toString(); + for (const Project *pro : m_projects) { + const QString proName = pro->projectFilePath().toString(); unordered << QPair(proName, m_depMap.value(proName)); } @@ -658,13 +619,17 @@ QList SessionManager::projectOrder(const Project *project) Node *SessionManager::nodeForFile(const Utils::FileName &fileName) { Node *node = nullptr; - sessionNode()->forEachGenericNode([&](Node *n) { - if (n->filePath() == fileName) { - // prefer file nodes - if (!node || (node->nodeType() != NodeType::File && n->nodeType() == NodeType::File)) - node = n; + for (Project *project : d->m_projects) { + if (ProjectNode *projectNode = project->rootProjectNode()) { + projectNode->forEachGenericNode([&](Node *n) { + if (n->filePath() == fileName) { + // prefer file nodes + if (!node || (node->nodeType() != NodeType::File && n->nodeType() == NodeType::File)) + node = n; + } + }); } - }); + } return node; } @@ -673,25 +638,16 @@ Project *SessionManager::projectForNode(Node *node) if (!node) return nullptr; - FolderNode *rootProjectNode = node->asFolderNode(); - if (!rootProjectNode) - rootProjectNode = node->parentFolderNode(); + FolderNode *folder = node->asFolderNode(); + if (!folder) + folder = node->parentFolderNode(); - while (rootProjectNode && rootProjectNode->parentFolderNode() != &d->m_sessionNode) - rootProjectNode = rootProjectNode->parentFolderNode(); + while (folder && folder->parentFolderNode()) + folder = folder->parentFolderNode(); - for (const QPair &pair : d->m_projects) { - if (pair.second == rootProjectNode) - return pair.first; - } - return nullptr; -} - -Node *SessionManager::nodeForProject(Project *project) -{ - for (const QPair &pair : d->m_projects) { - if (pair.first == project) - return pair.second; + for (Project *pro : d->m_projects) { + if (pro->containerNode() == folder) + return pro; } return nullptr; } @@ -771,17 +727,9 @@ void SessionManager::removeProjects(QList remove) // Delete projects foreach (Project *pro, remove) { pro->saveSettings(); - pro->setRootProjectNode(nullptr); // Deregister project with sessionnode! // Remove the project node: - Node *projectNode = nodeForProject(pro); - d->m_sessionNode.removeNode(projectNode); - - d->m_projects - = Utils::filtered(d->m_projects, [pro](const QPair &pair) - { - return pair.first != pro; - }); + d->m_projects.removeOne(pro); if (pro == d->m_startupProject) setStartupProject(nullptr); @@ -965,9 +913,9 @@ void SessionManagerPrivate::restoreStartupProject(const PersistentSettingsReader { const QString startupProject = reader.restoreValue(QLatin1String("StartupProject")).toString(); if (!startupProject.isEmpty()) { - for (const QPair &pro : m_projects) { - if (pro.first->projectFilePath().toString() == startupProject) { - m_instance->setStartupProject(pro.first); + for (Project *pro : m_projects) { + if (pro->projectFilePath().toString() == startupProject) { + m_instance->setStartupProject(pro); break; } } @@ -976,7 +924,7 @@ void SessionManagerPrivate::restoreStartupProject(const PersistentSettingsReader if (!startupProject.isEmpty()) qWarning() << "Could not find startup project" << startupProject; if (hasProjects()) - m_instance->setStartupProject(m_projects.first().first); + m_instance->setStartupProject(m_projects.first()); } } @@ -1140,11 +1088,6 @@ QString SessionManager::lastSession() return ICore::settings()->value(QLatin1String("ProjectExplorer/StartupSession")).toString(); } -SessionNode *SessionManager::sessionNode() -{ - return &d->m_sessionNode; -} - void SessionManager::reportProjectLoadingProgress() { d->sessionLoadingProgress(); diff --git a/src/plugins/projectexplorer/session.h b/src/plugins/projectexplorer/session.h index c654efc615e..8d6987363a4 100644 --- a/src/plugins/projectexplorer/session.h +++ b/src/plugins/projectexplorer/session.h @@ -44,7 +44,6 @@ class Target; class BuildConfiguration; class DeployConfiguration; class Node; -class SessionNode; enum class SetActive { Cascade, NoCascade }; @@ -113,10 +112,7 @@ public: // NBS rewrite projectOrder (dependency management) static QList projectOrder(const Project *project = 0); - static SessionNode *sessionNode(); - static Project *projectForNode(Node *node); - static Node *nodeForProject(Project *project); static Node *nodeForFile(const Utils::FileName &fileName); static Project *projectForFile(const Utils::FileName &fileName); @@ -126,8 +122,7 @@ public: static bool loadingSession(); signals: - void projectAdded(ProjectExplorer::Project *project); - void aboutToRemoveProject(ProjectExplorer::Project *project); + void projectAdded(ProjectExplorer::Project *project); void aboutToRemoveProject(ProjectExplorer::Project *project); void projectDisplayNameChanged(ProjectExplorer::Project *project); void projectRemoved(ProjectExplorer::Project *project); @@ -145,7 +140,6 @@ signals: // for tests only private: static void saveActiveMode(Core::Id mode); void clearProjectFileCache(); - void updateProjectTree(Project *pro); static void configureEditor(Core::IEditor *editor, const QString &fileName); static void markSessionFileDirty(bool makeDefaultVirginDirty = true); static void configureEditors(Project *project); From 58214f09e349a409bfd8c8642840d6a05b968983 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 21 Mar 2017 10:35:50 +0100 Subject: [PATCH 19/36] QbsProjectManager: Code cosmetics Remove unused QbsProductNode::findGroupNode and productPath. Also, simplify setup of static icons. Change-Id: Ibfaa1398eefcf3f764173d5b37aa4382b68976c9 Reviewed-by: Tobias Hunger --- src/plugins/qbsprojectmanager/qbsnodes.cpp | 43 ++++--------------- src/plugins/qbsprojectmanager/qbsnodes.h | 22 +--------- .../qbsprojectmanager/qbsnodetreebuilder.cpp | 2 + 3 files changed, 13 insertions(+), 54 deletions(-) diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index b942a1be22a..730c63ef7f2 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -42,6 +42,7 @@ #include #include +#include #include // ---------------------------------------------------------------------- @@ -64,10 +65,6 @@ static QIcon generateIcon(const QString &overlay) namespace QbsProjectManager { namespace Internal { -QIcon QbsGroupNode::m_groupIcon; -QIcon QbsProjectNode::m_projectIcon; -QIcon QbsProductNode::m_productIcon; - static QbsProjectNode *parentQbsProjectNode(ProjectExplorer::Node *node) { for (ProjectExplorer::FolderNode *pn = node->managingProject(); pn; pn = pn->parentProjectNode()) { @@ -263,9 +260,8 @@ QString QbsFileNode::displayName() const QbsFolderNode::QbsFolderNode(const Utils::FileName &folderPath, ProjectExplorer::NodeType nodeType, - const QString &displayName, bool isGeneratedFilesFolder) - : ProjectExplorer::FolderNode(folderPath, nodeType, displayName), - m_isGeneratedFilesFolder(isGeneratedFilesFolder) + const QString &displayName) + : ProjectExplorer::FolderNode(folderPath, nodeType, displayName) { } @@ -300,10 +296,8 @@ QList QbsBaseProjectNode::supportedActions(Proje QbsGroupNode::QbsGroupNode(const qbs::GroupData &grp, const QString &productPath) : QbsBaseProjectNode(Utils::FileName()) { - if (m_groupIcon.isNull()) - m_groupIcon = QIcon(QString::fromLatin1(Constants::QBS_GROUP_ICON)); - - setIcon(m_groupIcon); + static QIcon groupIcon = QIcon(QString(Constants::QBS_GROUP_ICON)); + setIcon(groupIcon); m_productPath = productPath; m_qbsGroupData = grp; @@ -379,10 +373,8 @@ QbsProductNode::QbsProductNode(const qbs::ProductData &prd) : QbsBaseProjectNode(Utils::FileName::fromString(prd.location().filePath())), m_qbsProductData(prd) { - if (m_productIcon.isNull()) - m_productIcon = generateIcon(QString::fromLatin1(Constants::QBS_PRODUCT_OVERLAY_ICON)); - - setIcon(m_productIcon); + static QIcon productIcon = generateIcon(QString(Constants::QBS_PRODUCT_OVERLAY_ICON)); + setIcon(productIcon); } bool QbsProductNode::showInSimpleTree() const @@ -464,16 +456,6 @@ QList QbsProductNode::runConfigurations() c return result; } -QbsGroupNode *QbsProductNode::findGroupNode(const QString &name) -{ - for (ProjectExplorer::Node *n : nodes()) { - if (QbsGroupNode *qn = dynamic_cast(n)) - if (qn->qbsGroupData().name() == name) - return qn; - } - return 0; -} - // -------------------------------------------------------------------- // QbsProjectNode: // -------------------------------------------------------------------- @@ -481,15 +463,8 @@ QbsGroupNode *QbsProductNode::findGroupNode(const QString &name) QbsProjectNode::QbsProjectNode(const Utils::FileName &projectDirectory) : QbsBaseProjectNode(projectDirectory) { - if (m_projectIcon.isNull()) - m_projectIcon = generateIcon(QString::fromLatin1(ProjectExplorer::Constants::FILEOVERLAY_QT)); - - setIcon(m_projectIcon); -} - -QbsProjectNode::~QbsProjectNode() -{ - // do not delete m_project + static QIcon projectIcon = generateIcon(QString(ProjectExplorer::Constants::FILEOVERLAY_QT)); + setIcon(projectIcon); } QbsProject *QbsProjectNode::project() const diff --git a/src/plugins/qbsprojectmanager/qbsnodes.h b/src/plugins/qbsprojectmanager/qbsnodes.h index 0627083c834..313fa2a6ff6 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.h +++ b/src/plugins/qbsprojectmanager/qbsnodes.h @@ -29,15 +29,11 @@ #include -#include - namespace QbsProjectManager { namespace Internal { -class FileTreeNode; class QbsNodeTreeBuilder; class QbsProject; -class QbsProjectFile; // ---------------------------------------------------------------------- // QbsFileNode: @@ -56,14 +52,10 @@ class QbsFolderNode : public ProjectExplorer::FolderNode { public: QbsFolderNode(const Utils::FileName &folderPath, ProjectExplorer::NodeType nodeType, - const QString &displayName, bool isGeneratedFilesFolder); - - bool isGeneratedFilesFolder() const { return m_isGeneratedFilesFolder; } + const QString &displayName); private: QList supportedActions(ProjectExplorer::Node *node) const override; - - const bool m_isGeneratedFilesFolder; }; // --------------------------------------------------------------------------- @@ -100,13 +92,9 @@ public: qbs::GroupData qbsGroupData() const { return m_qbsGroupData; } - QString productPath() const; - private: qbs::GroupData m_qbsGroupData; QString m_productPath; - - static QIcon m_groupIcon; }; // -------------------------------------------------------------------- @@ -129,10 +117,7 @@ public: QList runConfigurations() const override; private: - QbsGroupNode *findGroupNode(const QString &name); - const qbs::ProductData m_qbsProductData; - static QIcon m_productIcon; }; // --------------------------------------------------------------------------- @@ -143,18 +128,15 @@ class QbsProjectNode : public QbsBaseProjectNode { public: explicit QbsProjectNode(const Utils::FileName &projectDirectory); - ~QbsProjectNode() override; virtual QbsProject *project() const; const qbs::Project qbsProject() const; const qbs::ProjectData qbsProjectData() const { return m_projectData; } bool showInSimpleTree() const override; - - void setProjectData(const qbs::ProjectData &data); + void setProjectData(const qbs::ProjectData &data); // FIXME: Needed? private: - static QIcon m_projectIcon; qbs::ProjectData m_projectData; friend class QbsNodeTreeBuilder; diff --git a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp index 80308251074..1f2d1dc445b 100644 --- a/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodetreebuilder.cpp @@ -148,6 +148,8 @@ void setupProjectNode(QbsProjectManager::Internal::QbsProjectNode *node, const q node->setDisplayName(prjData.name()); else node->setDisplayName(node->project()->displayName()); + + node->setProjectData(prjData); } QSet referencedBuildSystemFiles(const qbs::ProjectData &data) From 09361075799f7fe29eb76e8e45500e43d4ab3688 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Tue, 21 Mar 2017 13:16:20 +0100 Subject: [PATCH 20/36] Doc: Describe the experimental Silver Searcher plugin Change-Id: I0a805a9f9a9f68175720eacd09ba7bdad9db92b0 Reviewed-by: Przemyslaw Gorszkowski Reviewed-by: Orgad Shaneh --- doc/src/editors/creator-editors.qdoc | 52 ++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/doc/src/editors/creator-editors.qdoc b/doc/src/editors/creator-editors.qdoc index 75c79adecb9..34ff10542b3 100644 --- a/doc/src/editors/creator-editors.qdoc +++ b/doc/src/editors/creator-editors.qdoc @@ -1583,13 +1583,25 @@ \image qtcreator-search-filesystem.png - In the \uicontrol {Search engine} field, select - \uicontrol Internal to use the \QC search engine. Select - \uicontrol {Git Grep} to use Git to only search tracked - files in the Git work tree. To restrict the search to the - HEAD, a tag, a local or remote branch, or a commit hash, - enter a reference. Leave the field empty to search through - the file system. + In the \uicontrol {Search engine} field, select the search + engine to use: + + \list + \li Select \uicontrol Internal to use the \QC search + engine. + + \li Select \uicontrol {Git Grep} to use Git to only + search tracked files in the Git work tree. To + restrict the search to the HEAD, a tag, a local or + remote branch, or a commit hash, enter a reference. + Leave the field empty to search through the file + system. + + \li Select \uicontrol {Silver Searcher} to use the + experimental Silver Searcher plugin. For more + information, see \l{Enabling Silver Searcher}. + + \endlist \li \uicontrol {Current File} searches only from the current file. @@ -1634,6 +1646,32 @@ \note You can use \uicontrol {Advanced Find} also to search for symbols. For more information, see \l{Finding Symbols}. + \section1 Enabling Silver Searcher + + You can use Silver Searcher as a search engine in \QC if you install + Silver Searcher on the development PC and enable the experimental plugin. + + To use Silver Searcher: + + \list 1 + + \li Download and install Silver Searcher from + \l {https://geoff.greer.fm/ag/}{The Silver Searcher} or + \l {https://github.com/ggreer/the_silver_searcher}{GitHub}. + + You might have to build Silver Searcher from sources for some + platforms. + + \li Select \uicontrol Help > \uicontrol {About Plugins} > + \uicontrol {Utilities} > \uicontrol {SilverSearcher} to enable the + plugin. + + \li Restart \QC to be able to use the plugin. + + \li When searching, select \uicontrol {Silver Searcher} in the + \uicontrol {Search engine} field. + + \endlist */ From 8f94691ad6db53112c9b032d7776927aa573de5e Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Tue, 21 Mar 2017 13:24:02 +0100 Subject: [PATCH 21/36] BinEditor: Avoid overflows in dataLastIndexOf Change-Id: I1f248f0c11209c60714f949d8f052326e86c9354 Reviewed-by: hjk --- src/plugins/bineditor/bineditorwidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/bineditor/bineditorwidget.cpp b/src/plugins/bineditor/bineditorwidget.cpp index 1814614296b..e647432723c 100644 --- a/src/plugins/bineditor/bineditorwidget.cpp +++ b/src/plugins/bineditor/bineditorwidget.cpp @@ -645,7 +645,7 @@ int BinEditorWidget::dataLastIndexOf(const QByteArray &pattern, qint64 from, boo int block = from / m_blockSize; const int lowerBound = qMax(qint64(0), from - SearchStride); while (from > lowerBound) { - if (!requestDataAt(block * m_blockSize)) + if (!requestDataAt(qint64(block) * m_blockSize)) return -1; QByteArray data = blockData(block); ::memcpy(b + m_blockSize, b, trailing); @@ -658,7 +658,7 @@ int BinEditorWidget::dataLastIndexOf(const QByteArray &pattern, qint64 from, boo if (pos >= 0) return pos + block * m_blockSize; --block; - from = block * m_blockSize + (m_blockSize-1) + trailing; + from = qint64(block) * m_blockSize + (m_blockSize-1) + trailing; } return lowerBound == 0 ? -1 : -2; } From f51d554bd18f5378f3b3d9b00bb7404594fdcf80 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 20 Mar 2017 11:51:18 +0100 Subject: [PATCH 22/36] Qml Debugger: Properly handle JavaScript null The QML engine might (in the future) actually send the right message to indicate a JavaScript null, that is: { type: "object", value: null } This piece of JSON is then transformed into a QVariantMap. The QVariant that signifies the null is unfortunately different across various Qt versions. We can, however, detect it. Change-Id: I3db42bb35a936bc02c749ab3a136b1d297aefdfe Reviewed-by: hjk --- src/plugins/debugger/qml/qmlengine.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 2b95e64cb73..dea2dc1a43f 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -1696,10 +1696,16 @@ QmlV8ObjectData QmlEnginePrivate::extractData(const QVariant &data) const if (dataMap.contains("value")) { QVariant value = dataMap.value("value"); - if (value.isNull()) + // The QVariant representation of null has changed across various Qt versions + // 5.6, 5.7: QVariant::Invalid + // 5.8: isValid(), !isNull(), type() == 51; only typeName() is unique: "std::nullptr_t" + // 5.9: isValid(), isNull(); We can then use isNull() + if (!value.isValid() || value.isNull() + || strcmp(value.typeName(), "std::nullptr_t") == 0) { objectData.value = "null"; // Yes, null is an object. - else if (value.isValid()) + } else if (value.isValid()) { objectData.expectedProperties = value.toInt(); + } } if (dataMap.contains("properties")) From 00a02dc1f8eed35f4ea5f1502ba256fb9f1ffb91 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 21 Mar 2017 14:42:24 +0100 Subject: [PATCH 23/36] ProjectExplorer: Fix crash when setting root project node Change-Id: I13954bffd06bee2aaf248d26cf358a0cc674d139 Reviewed-by: hjk --- src/plugins/projectexplorer/project.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp index fee9f07f354..e8b68a4560e 100644 --- a/src/plugins/projectexplorer/project.cpp +++ b/src/plugins/projectexplorer/project.cpp @@ -463,12 +463,13 @@ void Project::setRootProjectNode(ProjectNode *root) ProjectTree::applyTreeManager(root); + ProjectNode *oldNode = d->m_rootProjectNode; d->m_rootProjectNode = root; if (root) - d->m_rootProjectNode->setParentFolderNode(&d->m_containerNode); - ProjectTree::emitSubtreeChanged(d->m_rootProjectNode); + root->setParentFolderNode(&d->m_containerNode); + ProjectTree::emitSubtreeChanged(root); - delete d->m_rootProjectNode; + delete oldNode; } Target *Project::restoreTarget(const QVariantMap &data) From 9df203f314c26bdb975f1701d0df87a8807f0e97 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 21 Mar 2017 14:07:34 +0100 Subject: [PATCH 24/36] AutoTest: Add missing CMake build system to wizard Task-number: QTCREATORBUG-16916 Change-Id: I4dca90dd458789b7385013229d8447d6a8e6d360 Reviewed-by: Tobias Hunger --- .../templates/wizards/autotest/files/tst.txt | 57 +++++++++++++++++++ .../templates/wizards/autotest/wizard.json | 21 ++++++- 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 share/qtcreator/templates/wizards/autotest/files/tst.txt diff --git a/share/qtcreator/templates/wizards/autotest/files/tst.txt b/share/qtcreator/templates/wizards/autotest/files/tst.txt new file mode 100644 index 00000000000..8c13344d41c --- /dev/null +++ b/share/qtcreator/templates/wizards/autotest/files/tst.txt @@ -0,0 +1,57 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.1) + +PROJECT(%{TestCaseName} + LANGUAGES CXX) + +@if "%{TestFrameWork}" == "QtTest" + +find_package(Qt5Test REQUIRED) +@if "%{RequireGUI}" == "true" +find_package(Qt5Gui REQUIRED) +@endif + +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_INCLUDE_CURRENT_DIR ON) +SET(CMAKE_CXX_STANDARD 11) +ENABLE_TESTING() + +add_executable(${PROJECT_NAME} %{TestCaseFileWithCppSuffix}) +add_test(${PROJECT_NAME} COMMAND ${PROJECT_NAME}) + +@if "%{RequireGUI}" == "true" +target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Gui Qt5::Test) +@else +target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Test) +@endif + +@else + +@if "%{GTestCXX11}" == "true" +add_definitions(-DGTEST_LANGUAGE_CXX11) +@endif + +find_package(Threads REQUIRED) + +if ($ENV{GOOGLETEST_DIR}) + SET(GOOGLETEST_DIR $ENV{GOOGLETEST_DIR}) +else () + message(WARNING "Using googletest src dir specified at Qt Creator wizard") + SET(GOOGLETEST_DIR "%{GTestRepository}") +endif () +if (EXISTS ${GOOGLETEST_DIR}) + SET(GTestSrc ${GOOGLETEST_DIR}/googletest) + SET(GMockSrc ${GOOGLETEST_DIR}/googlemock) +else () + message( FATAL_ERROR "No googletest src dir found - set GOOGLETEST_DIR to enable!") +endif () + + +include_directories(${GTestSrc} ${GTestSrc}/include ${GMockSrc} ${GMockSrc}/include) + +add_executable(${PROJECT_NAME} %{MainCppName} %{TestCaseFileWithHeaderSuffix} + ${GTestSrc}/src/gtest-all.cc + ${GMockSrc}/src/gmock-all.cc) +add_test(${PROJECT_NAME} COMMAND ${PROJECT_NAME}) +target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads) + +@endif diff --git a/share/qtcreator/templates/wizards/autotest/wizard.json b/share/qtcreator/templates/wizards/autotest/wizard.json index f1490a1dc9a..8e593342d1b 100644 --- a/share/qtcreator/templates/wizards/autotest/wizard.json +++ b/share/qtcreator/templates/wizards/autotest/wizard.json @@ -13,7 +13,7 @@ "options": [ { "key": "ProjectFilePath", - "value": "%{JS: '%{BuildSystem}' == 'qmake' ? '%{ProFileName}' : '%{QbsFileName}' }" + "value": "%{JS: '%{BuildSystem}' == 'qmake' ? '%{ProFileName}' : ('%{BuildSystem}' == 'qbs' ? '%{QbsFileName}' : '%{CMakeFileName}') }" }, { "key": "ProFileName", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'pro')}" @@ -22,6 +22,10 @@ "key": "QbsFileName", "value": "%{JS: Util.fileName('%{ProjectDirectory}/%{ProjectName}', 'qbs')}" }, + { + "key": "CMakeFileName", + "value": "%{ProjectDirectory}/CMakeLists.txt" + }, { "key": "IsTopLevelProject", "value": "%{JS: !'%{Exists:ProjectExplorer.Profile.Ids}' }" }, @@ -159,6 +163,11 @@ "trKey": "Qbs", "value": "qbs", "condition": "%{JS: [ %{Plugins} ].indexOf('QbsProjectManager') >= 0}" + }, + { + "trKey": "CMake", + "value": "cmake", + "condition": "%{JS: [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}" } ] } @@ -171,7 +180,8 @@ "typeId": "Kits", "enabled": "%{IsTopLevelProject}", "data": { - "projectFilePath": "%{ProjectFilePath}" + "projectFilePath": "%{ProjectFilePath}", + "requiredFeatures": [ "%{JS: ('%{BuildSystem}' == 'cmake' && '%{TestFrameWork}' == 'QtTest') ? 'QtSupport.Wizards.FeatureQt.5' : 'QtSupport.Wizards.FeatureQt' }" ] } }, { @@ -212,6 +222,13 @@ "openInEditor": false, "openAsProject": true }, + { + "source": "files/tst.txt", + "target": "CMakeLists.txt", + "condition": "%{JS: '%{BuildSystem}' == 'cmake'}", + "openInEditor": false, + "openAsProject": true + }, { "source": "files/tst_src.h", "target": "%{TestCaseFileWithHeaderSuffix}", From b1826c2f7f0b9974911e0f7059b3e4b6b7dcfa99 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Tue, 21 Mar 2017 15:05:14 +0100 Subject: [PATCH 25/36] CMake: Fix file list for "AllFiles" Change-Id: I7f3e9d7169227483cf50bfed4659cc93372fca51 Reviewed-by: hjk --- src/plugins/cmakeprojectmanager/cmakeproject.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index 7310697596c..c04d237f387 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -313,9 +313,9 @@ QStringList CMakeProject::files(FilesMode fileMode) const if (ProjectNode *rpn = rootProjectNode()) { rpn->forEachNode([&](const FileNode *fn) { const bool isGenerated = fn->isGenerated(); - if (fileMode == Project::SourceFiles && !isGenerated) + if ((fileMode & Project::SourceFiles) && !isGenerated) result.append(fn->filePath().toString()); - if (fileMode == Project::GeneratedFiles && isGenerated) + if ((fileMode & Project::GeneratedFiles) && isGenerated) result.append(fn->filePath().toString()); }); } From e8a481744d385bc94923c07a45190104e1c21c74 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 20 Mar 2017 16:18:41 +0100 Subject: [PATCH 26/36] QmlProfiler: Don't crash if a statistics entry is empty In pathological cases we might get event types without any calls. Change-Id: Id5c9f02c95b60fe49a7cbbac511c3727ade71db0 Task-number: QTCREATORBUG-17885 Reviewed-by: hjk --- src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp index ab3e36c5399..428b98b2d2c 100644 --- a/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerstatisticsview.cpp @@ -638,7 +638,7 @@ void QmlProfilerStatisticsMainView::parseModel() newRow << new StatisticsViewItem(QString::number(stats.calls), stats.calls); if (d->m_fieldShown[TimePerCall]) { - const qint64 timePerCall = stats.duration / stats.calls; + const qint64 timePerCall = stats.calls > 0 ? stats.duration / stats.calls : 0; newRow << new StatisticsViewItem(Timeline::formatTime(timePerCall), timePerCall); } From b82f26d3b8890873c72cb50d21346d401aa2a797 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 21 Mar 2017 14:52:57 +0100 Subject: [PATCH 27/36] Doc: Adjust documentation for AutoTest wizard Change-Id: I2483c4270bbcce22182034f974ec4b053e515274 Reviewed-by: Leena Miettinen --- doc/src/howto/creator-autotest.qdoc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/src/howto/creator-autotest.qdoc b/doc/src/howto/creator-autotest.qdoc index 22335df2719..b4cebaaac26 100644 --- a/doc/src/howto/creator-autotest.qdoc +++ b/doc/src/howto/creator-autotest.qdoc @@ -85,10 +85,9 @@ \endlist - \QC creates the test in the \c{tests\auto} directory in the project - directory. Edit the .cpp file to add private slots for each test - function in your test. For more information about creating Qt tests, see - \l{Creating a Test}. + \QC creates the test in the specified project directory. Edit the .cpp file + to add private slots for each test function in your test. For more information + about creating Qt tests, see \l{Creating a Test}. \section2 Creating Google Tests @@ -133,8 +132,7 @@ \endlist - \QC creates the test in the \c{tests\auto} directory in the project - directory. + \QC creates the test in the specified project directory. \section1 Setting Up the Google C++ Testing Framework From 91e9ba7edeae9cec5c66d1e1c786c9fcd9d21218 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 9 Mar 2017 10:50:39 +0200 Subject: [PATCH 28/36] Dumper: Remove unused function Change-Id: Ibc8cf420170b084c05fdaf1d6a7b26594bcb3f24 Reviewed-by: hjk Reviewed-by: Orgad Shaneh --- share/qtcreator/debugger/creatortypes.py | 7 +++---- share/qtcreator/debugger/dumper.py | 4 ---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/share/qtcreator/debugger/creatortypes.py b/share/qtcreator/debugger/creatortypes.py index 652c30bc0a8..8b7d5d67e10 100644 --- a/share/qtcreator/debugger/creatortypes.py +++ b/share/qtcreator/debugger/creatortypes.py @@ -37,7 +37,7 @@ def extractPointerType(d, value): postfix = "" while stripTypeName(value) == "CPlusPlus::PointerType": postfix += "*" - value = d.downcast(value["_elementType"]["_type"]) + value = value["_elementType"]["_type"] try: return readLiteral(d, value["_name"]) + postfix except: @@ -60,7 +60,7 @@ def readTemplateName(d, value): for i in range(int(size)): if i > 0: name += ", " - name += extractPointerType(d, d.downcast(start[i]["_type"])) + name += extractPointerType(d, start[i]["_type"]) except: return "" name += ">" @@ -69,7 +69,6 @@ def readTemplateName(d, value): def readLiteral(d, value): if d.isNull(value): return "" - value = d.downcast(value) type = value.type.unqualified() try: type = type.target() @@ -147,7 +146,7 @@ def qdump__CPlusPlus__IntegerType(d, value): d.putPlainChildren(value) def qdump__CPlusPlus__FullySpecifiedType(d, value): - type = d.downcast(value["_type"]) + type = value["_type"] typeName = stripTypeName(type) if typeName == "CPlusPlus::NamedType": dumpLiteral(d, type["_name"]) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 6a09b0f6ff3..aaad6180b03 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -3158,10 +3158,6 @@ class DumperBase: val.type = self.dumper.createType(typish) return val - def downcast(self): - self.check() - return self - def address(self): self.check() return self.laddress From 384a2a0866614a6376d9fe8e83f334a52d6b15cb Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Mon, 20 Mar 2017 18:01:41 +0100 Subject: [PATCH 29/36] ModelEditor: Remove dead code Change-Id: I7997edc25242c7c8ed65dfb6675e7c21cf6c70b3 Reviewed-by: Jochen Becher Reviewed-by: Tobias Hunger --- src/libs/modelinglib/qmt/controller/namecontroller.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libs/modelinglib/qmt/controller/namecontroller.cpp b/src/libs/modelinglib/qmt/controller/namecontroller.cpp index 6871bc035a8..2285fb39716 100644 --- a/src/libs/modelinglib/qmt/controller/namecontroller.cpp +++ b/src/libs/modelinglib/qmt/controller/namecontroller.cpp @@ -62,10 +62,7 @@ QString NameController::convertFileNameToElementName(const QString &fileName) elementName += baseName.at(i).toTitleCase(); makeTitlecase = false; } else { - if (insertSpace) { - elementName += QLatin1Char(' '); - insertSpace = false; - } + // insertSpace must be false here elementName += baseName.at(i); } } From a79701e8fff24e475ac2335eb0433087619d1a67 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Tue, 21 Mar 2017 13:08:41 +0100 Subject: [PATCH 30/36] fix unused warning at release builds Change-Id: I0b48f27bf86538c88b57cb85e54e9552aa89b62f Reviewed-by: Tobias Hunger --- src/plugins/qtsupport/qtprojectimporter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/qtsupport/qtprojectimporter.cpp b/src/plugins/qtsupport/qtprojectimporter.cpp index f2901f02c78..cee4b38057b 100644 --- a/src/plugins/qtsupport/qtprojectimporter.cpp +++ b/src/plugins/qtsupport/qtprojectimporter.cpp @@ -243,6 +243,7 @@ Kit *TestQtProjectImporter::createKit(void *directoryData) const QList TestQtProjectImporter::buildInfoListForKit(const Kit *k, void *directoryData) const { + Q_UNUSED(directoryData); assert(m_testData.contains(directoryData)); assert(!m_deletedTestData.contains(directoryData)); assert(static_cast(directoryData)->importPath == m_path); From 2b09fc7885dbed5d4f86858a5e6891cd0018f024 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 20 Mar 2017 12:17:26 +0100 Subject: [PATCH 31/36] QmlDesigner: Make reset action aware of states Change-Id: Idc4eb8b0f3f90d97ef3d2cd6ef64a6c49b2fcbc6 Reviewed-by: Tim Jenssen --- .../componentcore/modelnodeoperations.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp index 0568ec509e9..9375f405038 100644 --- a/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp +++ b/src/plugins/qmldesigner/components/componentcore/modelnodeoperations.cpp @@ -325,8 +325,9 @@ void resetSize(const SelectionContext &selectionState) try { RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|resetSize")); foreach (ModelNode node, selectionState.selectedModelNodes()) { - node.removeProperty("width"); - node.removeProperty("height"); + QmlItemNode itemNode(node); + itemNode.removeProperty("width"); + itemNode.removeProperty("height"); } } catch (const RewritingException &e) { //better save then sorry e.showException(); @@ -341,8 +342,9 @@ void resetPosition(const SelectionContext &selectionState) try { RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|resetPosition")); foreach (ModelNode node, selectionState.selectedModelNodes()) { - node.removeProperty("x"); - node.removeProperty("y"); + QmlItemNode itemNode(node); + itemNode.removeProperty("x"); + itemNode.removeProperty("y"); } transaction.commit(); } catch (const RewritingException &e) { //better save then sorry @@ -366,7 +368,8 @@ void resetZ(const SelectionContext &selectionState) RewriterTransaction transaction(selectionState.view(), QByteArrayLiteral("DesignerActionManager|resetZ")); foreach (ModelNode node, selectionState.selectedModelNodes()) { - node.removeProperty("z"); + QmlItemNode itemNode(node); + itemNode.removeProperty("z"); } } From 0dbec5a90417eb5c9d6dc16902c726d276a38c81 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Mon, 20 Mar 2017 16:53:47 +0100 Subject: [PATCH 32/36] QmlDesigner: Fix crash We have to ensure the modal dialog is actually visible before calling process events later. Task-number: QTCREATORBUG-16722 Change-Id: I4362a2887ee95483df082305b024232366eb074d Reviewed-by: Tim Jenssen --- .../designercore/instances/puppetcreator.cpp | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp index 84b4cef69c4..b21e45ef797 100644 --- a/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp +++ b/src/plugins/qmldesigner/designercore/instances/puppetcreator.cpp @@ -66,6 +66,25 @@ static Q_LOGGING_CATEGORY(puppetBuild, "qtc.puppet.build") namespace QmlDesigner { +class EventFilter : public QObject { + +public: + EventFilter() + {} + + bool eventFilter(QObject *o, QEvent *event) + { + if (event->type() == QEvent::MouseButtonPress + || event->type() == QEvent::MouseButtonRelease + || event->type() == QEvent::KeyPress + || event->type() == QEvent::KeyRelease) { + return true; + } + + return QObject::eventFilter(o, event); + } +}; + QHash PuppetCreator::m_qml2PuppetForKitPuppetHash; QByteArray PuppetCreator::qtHash() const @@ -241,6 +260,7 @@ static QString idealProcessCount() bool PuppetCreator::build(const QString &qmlPuppetProjectFilePath) const { PuppetBuildProgressDialog progressDialog; + progressDialog.setParent(Core::ICore::mainWindow()); m_compileLog.clear(); @@ -248,6 +268,16 @@ bool PuppetCreator::build(const QString &qmlPuppetProjectFilePath) const bool buildSucceeded = false; + + /* Ensure the model dialog is shown and no events are delivered to the rest of Qt Creator. */ + EventFilter eventFilter; + QCoreApplication::instance()->installEventFilter(&eventFilter); + progressDialog.show(); + QCoreApplication::processEvents(); + QCoreApplication::instance()->removeEventFilter(&eventFilter); + /* Now the modal dialog will block input to the rest of Qt Creator. + We can call process events without risking a mode change. */ + if (qtIsSupported()) { if (buildDirectory.isValid()) { QStringList qmakeArguments; From e8b3b8140bd5d1ce6dc5b3874c508643656928f7 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 21 Mar 2017 10:33:02 +0100 Subject: [PATCH 33/36] QmlDesigner: Ensure design mode is registered We have to call registerDesignWidget() in extensionsInitialized() and not delayedInitialize(), because the setup of Qt Creator is already done when delayedInitialize() is called. Because of this, if the original widget designer was disabled, no design mode was available. Change-Id: I8b02fcb10aa5305aff3c700f7831012ccf009b33 Reviewed-by: Orgad Shaneh Reviewed-by: Tim Jenssen --- src/plugins/qmldesigner/qmldesignerplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/qmldesignerplugin.cpp b/src/plugins/qmldesigner/qmldesignerplugin.cpp index c1a48b95ad7..366e69bd641 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.cpp +++ b/src/plugins/qmldesigner/qmldesignerplugin.cpp @@ -188,7 +188,6 @@ bool QmlDesignerPlugin::initialize(const QStringList & /*arguments*/, QString *e bool QmlDesignerPlugin::delayedInitialize() { - integrateIntoQtCreator(d->mainWidget); // adding default path to item library plugins const QString pluginPath = Utils::HostOsInfo::isMacHost() ? QString(QCoreApplication::applicationDirPath() + "/../PlugIns/QmlDesigner") @@ -210,6 +209,7 @@ bool QmlDesignerPlugin::delayedInitialize() void QmlDesignerPlugin::extensionsInitialized() { + integrateIntoQtCreator(d->mainWidget); } static QStringList allUiQmlFilesforCurrentProject(const Utils::FileName &fileName) From 204970fc0ca21538b04fe54f5795738843788c88 Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 21 Mar 2017 17:03:17 +0100 Subject: [PATCH 34/36] QmlDesigner: Only show warnings when opening document Otherwise the warnings become too annoying, since they are also triggered by undo/redo. Do not disable the form editor in case of warnings. Task-number: QTCREATORBUG-16306 Change-Id: Ieb1d6072269935e420e9cf988c900e1af792686f Reviewed-by: Tim Jenssen --- .../qmldesigner/components/formeditor/formeditorview.cpp | 3 --- .../qmldesigner/components/formeditor/formeditorwidget.cpp | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index af1ffeebd38..fc37d0b99b6 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -307,9 +307,6 @@ void FormEditorView::documentMessagesChanged(const QList &error formEditorWidget()->showErrorMessageBox(errors); else formEditorWidget()->hideErrorMessageBox(); - - if (!warnings.isEmpty()) - formEditorWidget()->showWarningMessageBox(warnings); } void FormEditorView::customNotification(const AbstractView * /*view*/, const QString &identifier, const QList &/*nodeList*/, const QList &/*data*/) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp index 12bb8245e41..3c2b516746c 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp @@ -286,8 +286,6 @@ void FormEditorWidget::showWarningMessageBox(const QList &warni errorWidget()->setWarnings(warnings); errorWidget()->setVisible(true); - m_graphicsView->setDisabled(true); - m_toolBox->setDisabled(true); } ZoomAction *FormEditorWidget::zoomAction() const From 505cf814b98194def4a5dcb4a62ae9998002049a Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 21 Mar 2017 17:46:26 +0100 Subject: [PATCH 35/36] QmlDesigner: Fix warning Change-Id: Iaa207dec5ea869833750eb9fc18f70f404d08572 Reviewed-by: Tim Jenssen --- .../qmldesigner/components/formeditor/formeditorview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index fc37d0b99b6..e4ee007bf7c 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -301,7 +301,7 @@ void FormEditorView::selectedNodesChanged(const QList &selectedNodeLi m_scene->update(); } -void FormEditorView::documentMessagesChanged(const QList &errors, const QList &warnings) +void FormEditorView::documentMessagesChanged(const QList &errors, const QList &) { if (!errors.isEmpty()) formEditorWidget()->showErrorMessageBox(errors); From 991f5eb6a5699c07c6471fcd6c148e507c694adf Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 21 Mar 2017 11:14:10 +0100 Subject: [PATCH 36/36] Prepare for upcoming compile breakage Qt 5.9 is going to break source compatibility by making the QStringRef(QString *) constructor explicit. Since the use of that constructor rather looks unintentional here, replace its use. Change-Id: I6f5f2e79f7d92f6e80a1ea0aa12126d9c88b499e Reviewed-by: Jochen Becher Reviewed-by: Eike Ziller --- src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp | 2 +- src/libs/utils/stringutils.cpp | 2 +- 2 files changed, 2 insertions(+), 2 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..276176a6917 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp @@ -628,7 +628,7 @@ void ClassItem::updateMembers(const Style *style) } *currentVisibility = member.visibility(); } - if (member.group() != currentGroup) { + if (currentGroup && member.group() != *currentGroup) { if (addSpace) *text += QStringLiteral(" "); *text += QString(QStringLiteral("[%1]")).arg(member.group()); diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp index 3b2de69ec72..85813004dec 100644 --- a/src/libs/utils/stringutils.cpp +++ b/src/libs/utils/stringutils.cpp @@ -183,7 +183,7 @@ bool AbstractMacroExpander::expandNestedMacros(const QString &str, int *pos, QSt if (!expandNestedMacros(str, &i, ret)) return false; varName.chop(1); - varName += ret; + varName += *ret; } else if (currArg == &varName && c == '-' && prev == ':' && validateVarName(varName)) { varName.chop(1); currArg = &defaultValue;