From ca660c796cba7af467c75608f30870411f690574 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 13 Jul 2017 16:41:13 +0200 Subject: [PATCH 01/35] ClangStaticAnalyzer: Fix rampdown Stop button wasn't doing anything. Change-Id: I84f3d5dccdbdd5a7a800ecc86c3938b01eaa0550 Reviewed-by: Nikolai Kosjar --- .../clangstaticanalyzerruncontrol.cpp | 15 ++++++++------- .../clangstaticanalyzerruncontrol.h | 1 - 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 612a35c52ec..94c855efda7 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -79,6 +79,7 @@ ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runCont RunConfiguration *runConfiguration = runControl->runConfiguration(); auto tool = ClangStaticAnalyzerTool::instance(); + tool->stopAction()->disconnect(); connect(tool->stopAction(), &QAction::triggered, runControl, &RunControl::initiateStop); ProjectInfo projectInfoBeforeBuild = tool->projectInfoBeforeBuild(); @@ -495,6 +496,10 @@ void ClangStaticAnalyzerToolRunner::start() m_success = false; ClangStaticAnalyzerTool::instance()->onEngineIsStarting(); + connect(runControl(), &RunControl::finished, this, [this] { + ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success); + }); + QTC_ASSERT(m_projectInfo.isValid(), reportFailure(); return); const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath(); appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput()) @@ -602,12 +607,8 @@ void ClangStaticAnalyzerToolRunner::stop() appendMessage(tr("Clang Static Analyzer stopped by user.") + QLatin1Char('\n'), Utils::NormalMessageFormat); m_progress.reportFinished(); - reportStopped(); -} - -void ClangStaticAnalyzerToolRunner::onFinished() -{ ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success); + reportStopped(); } void ClangStaticAnalyzerToolRunner::analyzeNextFile() @@ -699,7 +700,7 @@ void ClangStaticAnalyzerToolRunner::handleFinished() void ClangStaticAnalyzerToolRunner::onProgressCanceled() { m_progress.reportCanceled(); - stop(); + runControl()->initiateStop(); } void ClangStaticAnalyzerToolRunner::updateProgressValue() @@ -723,7 +724,7 @@ void ClangStaticAnalyzerToolRunner::finalize() } m_progress.reportFinished(); - reportStopped(); + runControl()->initiateStop(); } } // namespace Internal diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h index 9719c421167..e75660287ff 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h @@ -56,7 +56,6 @@ public: void start() override; void stop() override; - void onFinished() override; bool success() const { return m_success; } // For testing. From 700fc468c7ef7aed028d7d6de5cbd1b9fafbef82 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 14 Jul 2017 13:06:51 +0200 Subject: [PATCH 02/35] Doc: Describe new Clang Code Model options The controls in the Options view have been rearranged, so the text was rearranged accordingly. Updated and added screenshots. Change-Id: Ideb8fbd43d7872091980fc1b17d6593ed2f356eb Reviewed-by: Alessandro Portale Reviewed-by: Nikolai Kosjar --- ...reator-clang-code-model-build-settings.png | Bin 0 -> 43490 bytes .../qtcreator-clang-code-model-options.png | Bin 16323 -> 58844 bytes doc/src/editors/creator-clang-codemodel.qdoc | 43 ++++++++++++------ 3 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 doc/images/qtcreator-clang-code-model-build-settings.png diff --git a/doc/images/qtcreator-clang-code-model-build-settings.png b/doc/images/qtcreator-clang-code-model-build-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..cc7d3d8cf92973d559003083d14e66b58b8218b8 GIT binary patch literal 43490 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 + \uicontrol {Clang Code Model}. In addition to configuring the diagnostics, + you can select the \uicontrol {Enable MSVC-compliant template parsing} check + box to parse templates in a MSVC-compliant way. This enables Clang to parse + headers for example from Active Template Library (ATL) or Windows Runtime + Library (WRL). However, using the relaxed and extended rules means that no + highlighting or completion can be provided within template functions. + + \image qtcreator-clang-code-model-build-settings.png + */ From 892026a6196b9d69fe0946afedab8b4eaf6c5208 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 14 Jul 2017 17:15:59 +0200 Subject: [PATCH 03/35] ClangStaticAnalyzer: Compile fix due to unsubmitted dependency This patch needs to be reverted later. Change-Id: Ia120e225ec1086eca786f668999a48e5ee19ec7e Reviewed-by: Christian Kandeler --- .../clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 94c855efda7..ff078f612e6 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -496,7 +496,7 @@ void ClangStaticAnalyzerToolRunner::start() m_success = false; ClangStaticAnalyzerTool::instance()->onEngineIsStarting(); - connect(runControl(), &RunControl::finished, this, [this] { + connect(runControl(), &RunControl::stopped, this, [this] { ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success); }); From 635750aa11db284d5ee3b0e97f6d1e035a8c54e3 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 12 Jul 2017 09:34:30 +0200 Subject: [PATCH 04/35] Clang: delay text mark update Reducing display of unwanted line annotations while typing in small files. Change-Id: I51864bbc3056ad792d5ee4b96f63e954dfba79dd Reviewed-by: Ivan Donchevskii Reviewed-by: Nikolai Kosjar --- .../clangcodemodel/clangdiagnosticmanager.cpp | 15 ++++++++++++++- .../clangcodemodel/clangdiagnosticmanager.h | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp index c8da6e6c6a2..1dd003c7c11 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp @@ -278,6 +278,8 @@ namespace Internal { ClangDiagnosticManager::ClangDiagnosticManager(TextEditor::TextDocument *textDocument) : m_textDocument(textDocument) { + m_textMarkDelay.setInterval(1500); + m_textMarkDelay.setSingleShot(true); } ClangDiagnosticManager::~ClangDiagnosticManager() @@ -295,6 +297,7 @@ void ClangDiagnosticManager::cleanMarks() } void ClangDiagnosticManager::generateTextMarks() { + QObject::disconnect(&m_textMarkDelay, &QTimer::timeout, 0, 0); cleanMarks(); m_clangTextMarks.reserve(m_warningDiagnostics.size() + m_errorDiagnostics.size()); addClangTextMarks(m_warningDiagnostics); @@ -350,6 +353,7 @@ ClangDiagnosticManager::diagnosticsAt(uint line, uint column) const void ClangDiagnosticManager::invalidateDiagnostics() { + m_textMarkDelay.start(); if (m_diagnosticsInvalidated) return; @@ -383,9 +387,18 @@ void ClangDiagnosticManager::processNewDiagnostics( m_showTextMarkAnnotations = showTextMarkAnnotations; filterDiagnostics(allDiagnostics); - generateTextMarks(); generateEditorSelections(); generateFixItAvailableMarkers(); + if (m_firstDiagnostics) { + m_firstDiagnostics = false; + generateTextMarks(); + } else if (!m_textMarkDelay.isActive()) { + generateTextMarks(); + } else { + QObject::connect(&m_textMarkDelay, &QTimer::timeout, [this]() { + generateTextMarks(); + }); + } } const QVector & diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.h b/src/plugins/clangcodemodel/clangdiagnosticmanager.h index 16b1c16d2d9..1321702c99c 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.h +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -82,8 +83,10 @@ private: QList m_extraSelections; TextEditor::RefactorMarkers m_fixItAvailableMarkers; std::vector m_clangTextMarks; + bool m_firstDiagnostics = true; bool m_diagnosticsInvalidated = false; bool m_showTextMarkAnnotations = false; + QTimer m_textMarkDelay; }; } // namespace Internal From c9301e80bb960ba5df93fdd22932257542693154 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 14 Jul 2017 13:11:22 +0200 Subject: [PATCH 05/35] Clang: Hide the # button in the editor tool bar ...since this is not yet implemented and confuses users. Change-Id: I16e41f3308607aeaf1fb4a8d38ca276781c88952 Reviewed-by: David Schulz --- src/plugins/cppeditor/cppeditor.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 677cd1ebc3f..65d0c42abf2 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -245,13 +245,19 @@ void CppEditorWidget::finalizeInitialization() }); // Toolbar: '#' Button - d->m_preprocessorButton = new QToolButton(this); - d->m_preprocessorButton->setText(QLatin1String("#")); - Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG); - connect(cmd, &Command::keySequenceChanged, this, &CppEditorWidget::updatePreprocessorButtonTooltip); - updatePreprocessorButtonTooltip(); - connect(d->m_preprocessorButton, &QAbstractButton::clicked, this, &CppEditorWidget::showPreProcessorWidget); - insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton); + // TODO: Make "Additional Preprocessor Directives" also useful with Clang Code Model. + if (!d->m_modelManager->isClangCodeModelActive()) { + d->m_preprocessorButton = new QToolButton(this); + d->m_preprocessorButton->setText(QLatin1String("#")); + Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG); + connect(cmd, &Command::keySequenceChanged, + this, &CppEditorWidget::updatePreprocessorButtonTooltip); + updatePreprocessorButtonTooltip(); + connect(d->m_preprocessorButton, &QAbstractButton::clicked, + this, &CppEditorWidget::showPreProcessorWidget); + + insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton); + } // Toolbar: Actions to show minimized info bars d->m_showInfoBarActions = MinimizableInfoBars::createShowInfoBarActions([this](QWidget *w) { @@ -429,13 +435,16 @@ bool CppEditorWidget::selectBlockDown() void CppEditorWidget::updateWidgetHighlighting(QWidget *widget, bool highlight) { + if (!widget) + return; + widget->setProperty("highlightWidget", highlight); widget->update(); } bool CppEditorWidget::isWidgetHighlighted(QWidget *widget) { - return widget->property("highlightWidget").toBool(); + return widget ? widget->property("highlightWidget").toBool() : false; } void CppEditorWidget::renameSymbolUnderCursor() @@ -586,7 +595,9 @@ void CppEditorWidget::renameSymbolUnderCursorClang() void CppEditorWidget::updatePreprocessorButtonTooltip() { - QTC_ASSERT(d->m_preprocessorButton, return); + if (!d->m_preprocessorButton) + return; + Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG); QTC_ASSERT(cmd, return); d->m_preprocessorButton->setToolTip(cmd->action()->toolTip()); From be2b3c91ae4ddb97c35237da11b350c99cc6fd3b Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Fri, 14 Jul 2017 13:44:33 +0200 Subject: [PATCH 06/35] Add Q_FALLTHROUGH for Qt < 5.8 ... and make use of it. With gcc 7, the new option -Wimplicit-fallthrough is introduced and added to the -Wextra set, triggering dozens of warnings in our sources. Therefore, we annotate all obviously intended fall-throughs. The ones that are still left are unclear and need to be checked by the respective maintainer. Change-Id: I44ead33cd42a4b41c28ee5fcb5a31db272710bbc Reviewed-by: Nikita Baryshnikov Reviewed-by: hjk Reviewed-by: Eike Ziller --- src/libs/3rdparty/cplusplus/Parser.cpp | 4 +- src/libs/utils/qtcfallthrough.h | 54 +++++++++++++++++++ src/libs/utils/utils-lib.pri | 1 + src/libs/utils/utils.qbs | 1 + src/plugins/cppeditor/cppquickfixes.cpp | 3 +- .../cpptools/compileroptionsbuilder.cpp | 10 ++-- src/plugins/debugger/gdb/attachgdbadapter.cpp | 3 +- .../debugger/gdb/remotegdbserveradapter.cpp | 3 +- src/plugins/debugger/qml/qmlengine.cpp | 3 +- src/plugins/debugger/watchutils.cpp | 4 ++ src/plugins/ios/iostoolhandler.cpp | 7 +-- .../components/formeditor/formeditorscene.cpp | 2 + src/plugins/qmlprofiler/qmlprofilertool.cpp | 3 ++ .../qmlprofiler/qmlprofilertraceview.cpp | 5 +- .../scxmleditor/common/structuremodel.cpp | 3 ++ src/plugins/vcsbase/vcsbaseclientsettings.cpp | 2 + 16 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 src/libs/utils/qtcfallthrough.h diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 8754206a0b5..16f351077a1 100644 --- a/src/libs/3rdparty/cplusplus/Parser.cpp +++ b/src/libs/3rdparty/cplusplus/Parser.cpp @@ -27,6 +27,8 @@ #include "ObjectiveCTypeQualifiers.h" #include "QtContextKeywords.h" +#include + #include #include @@ -442,7 +444,7 @@ bool Parser::skipUntilStatement() case T_AT_THROW: if (_languageFeatures.objCEnabled) return true; - + Q_FALLTHROUGH(); default: consumeToken(); } diff --git a/src/libs/utils/qtcfallthrough.h b/src/libs/utils/qtcfallthrough.h new file mode 100644 index 00000000000..6eba622837f --- /dev/null +++ b/src/libs/utils/qtcfallthrough.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include + +#ifndef Q_FALLTHROUGH +#ifndef QT_HAS_CPP_ATTRIBUTE +#ifdef __has_cpp_attribute +# define QT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define QT_HAS_CPP_ATTRIBUTE(x) 0 +#endif +#endif +#if defined(__cplusplus) +#if QT_HAS_CPP_ATTRIBUTE(fallthrough) +# define Q_FALLTHROUGH() [[fallthrough]] +#elif QT_HAS_CPP_ATTRIBUTE(clang::fallthrough) +# define Q_FALLTHROUGH() [[clang::fallthrough]] +#elif QT_HAS_CPP_ATTRIBUTE(gnu::fallthrough) +# define Q_FALLTHROUGH() [[gnu::fallthrough]] +#endif +#endif +#ifndef Q_FALLTHROUGH +# if (defined(Q_CC_GNU) && Q_CC_GNU >= 700) && !defined(Q_CC_INTEL) +# define Q_FALLTHROUGH() __attribute__((fallthrough)) +# else +# define Q_FALLTHROUGH() (void)0 +#endif +#endif +#endif diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index bfc9d6084e1..3a6aa0a09af 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -239,6 +239,7 @@ HEADERS += \ $$PWD/asconst.h \ $$PWD/smallstringfwd.h \ $$PWD/optional.h \ + $$PWD/qtcfallthrough.h \ $$PWD/../3rdparty/optional/optional.hpp FORMS += $$PWD/filewizardpage.ui \ diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index 559129df164..6d68683fdd5 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -175,6 +175,7 @@ Project { "proxycredentialsdialog.cpp", "proxycredentialsdialog.h", "proxycredentialsdialog.ui", + "qtcfallthrough.h", "qtcassert.cpp", "qtcassert.h", "qtcolorbutton.cpp", diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 67d360c3bb5..640fa794ef0 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -56,6 +56,7 @@ #include #include +#include #include #include @@ -4119,7 +4120,7 @@ public: break; case FromReference: removeReferenceOperator(changes); - // fallthrough intended + Q_FALLTHROUGH(); case FromVariable: convertToPointer(changes); break; diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 8f5fd397fb7..170279c9b8f 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -26,6 +26,7 @@ #include "compileroptionsbuilder.h" #include +#include #include #include @@ -201,7 +202,8 @@ static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objc if (!objcExt) { opts += QLatin1String("c++-header"); break; - } // else: fall-through! + } + Q_FALLTHROUGH(); case ProjectFile::ObjCHeader: case ProjectFile::ObjCXXHeader: opts += QLatin1String("objective-c++-header"); @@ -211,7 +213,8 @@ static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objc if (!objcExt) { opts += QLatin1String("c"); break; - } // else: fall-through! + } + Q_FALLTHROUGH(); case ProjectFile::ObjCSource: opts += QLatin1String("objective-c"); break; @@ -220,7 +223,8 @@ static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objc if (!objcExt) { opts += QLatin1String("c++"); break; - } // else: fall-through! + } + Q_FALLTHROUGH(); case ProjectFile::ObjCXXSource: opts += QLatin1String("objective-c++"); break; diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp index 11566a51be5..519647d7035 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.cpp +++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp @@ -31,6 +31,7 @@ #include #include +#include namespace Debugger { namespace Internal { @@ -102,7 +103,7 @@ void GdbAttachEngine::handleAttach(const DebuggerResponse &response) notifyEngineIll(); break; } - // if msg != "ptrace: ..." fall through + Q_FALLTHROUGH(); // if msg != "ptrace: ..." default: showStatusMessage(tr("Failed to attach to application: %1") .arg(QString(response.data["msg"].data()))); diff --git a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp index a36aa11bef0..cf55a82dc6b 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -367,7 +368,7 @@ void GdbRemoteServerEngine::handleAttach(const DebuggerResponse &response) notifyInferiorSetupFailed(msgPtraceError(runParameters().startMode)); break; } - // if msg != "ptrace: ..." fall through + Q_FALLTHROUGH(); // if msg != "ptrace: ..." default: notifyInferiorSetupFailed(response.data["msg"].data()); } diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 87b4a039d05..0a0ed1d5166 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include @@ -505,7 +506,7 @@ void QmlEngine::errorMessageBoxFinished(int result) } case QMessageBox::Help: { HelpManager::handleHelpRequest("qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html"); - // fall through + Q_FALLTHROUGH(); } default: if (state() == InferiorRunOk) { diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp index f6e8dfeb456..2275807d22c 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -29,6 +29,8 @@ #include "watchutils.h" #include "watchdata.h" +#include + #include #include @@ -231,8 +233,10 @@ QString formatToolTipAddress(quint64 a) switch (rc.size()) { case 16: rc.insert(12, colon); + Q_FALLTHROUGH(); case 12: rc.insert(8, colon); + Q_FALLTHROUGH(); case 8: rc.insert(4, colon); } diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index f2afa714337..317c1f6f594 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "utils/runextensions.h" #include "utils/synchronousprocess.h" @@ -606,7 +607,7 @@ void IosDeviceToolHandlerPrivate::subprocessHasData() switch (state) { case NonStarted: qCWarning(toolHandlerLog) << "IosToolHandler unexpected state in subprocessHasData: NonStarted"; - // pass + Q_FALLTHROUGH(); case Starting: case StartedInferior: // read some data @@ -771,7 +772,7 @@ void IosDeviceToolHandlerPrivate::stop(int errorCode) switch (oldState) { case NonStarted: qCWarning(toolHandlerLog) << "IosToolHandler::stop() when state was NonStarted"; - // pass + Q_FALLTHROUGH(); case Starting: switch (op){ case OpNone: @@ -786,7 +787,7 @@ void IosDeviceToolHandlerPrivate::stop(int errorCode) case OpDeviceInfo: break; } - // pass + Q_FALLTHROUGH(); case StartedInferior: case XmlEndProcessed: toolExited(errorCode); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp index 950028bf3be..3601db17535 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp @@ -44,6 +44,7 @@ #include #include +#include namespace QmlDesigner { @@ -358,6 +359,7 @@ bool FormEditorScene::event(QEvent * event) currentTool()->keyPressEvent(static_cast(event)); return true; } + Q_FALLTHROUGH(); default: return QGraphicsScene::event(event); } diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp index 227b6dff0b7..e246bf885c0 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp @@ -69,6 +69,8 @@ #include +#include + #include #include #include @@ -387,6 +389,7 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker) case QMessageBox::Help: HelpManager::handleHelpRequest( "qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html"); + Q_FALLTHROUGH(); case QMessageBox::Cancel: // The actual error message has already been logged. logState(tr("Failed to connect.")); diff --git a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp index 8519d124223..a2a00b4f983 100644 --- a/src/plugins/qmlprofiler/qmlprofilertraceview.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertraceview.cpp @@ -53,6 +53,7 @@ // Needed for the load&save actions in the context menu #include #include +#include #include #include @@ -103,7 +104,7 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManag qint64 end = modelManager->traceTime()->endTime(); d->m_zoomControl->setTrace(start, end); d->m_zoomControl->setRange(start, start + (end - start) / 10); - // Fall through + Q_FALLTHROUGH(); } case QmlProfilerModelManager::Empty: d->m_modelProxy->setModels(d->m_suspendedModels); @@ -116,7 +117,7 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManag d->m_zoomControl->clear(); if (!d->m_suspendedModels.isEmpty()) break; // Models are suspended already. AcquiringData was aborted. - // Fall through + Q_FALLTHROUGH(); case QmlProfilerModelManager::AcquiringData: // Temporarily remove the models, while we're changing them d->m_suspendedModels = d->m_modelProxy->models(); diff --git a/src/plugins/scxmleditor/common/structuremodel.cpp b/src/plugins/scxmleditor/common/structuremodel.cpp index f7b2e563e98..5f63319c167 100644 --- a/src/plugins/scxmleditor/common/structuremodel.cpp +++ b/src/plugins/scxmleditor/common/structuremodel.cpp @@ -27,6 +27,8 @@ #include "scxmldocument.h" #include "scxmltag.h" +#include + #include #include @@ -245,6 +247,7 @@ Qt::ItemFlags StructureModel::flags(const QModelIndex &index) const case Final: case History: defaultFlags |= Qt::ItemIsDragEnabled; + Q_FALLTHROUGH(); case Scxml: defaultFlags |= Qt::ItemIsDropEnabled; break; diff --git a/src/plugins/vcsbase/vcsbaseclientsettings.cpp b/src/plugins/vcsbase/vcsbaseclientsettings.cpp index 35c2a7c1199..ab67910c2f5 100644 --- a/src/plugins/vcsbase/vcsbaseclientsettings.cpp +++ b/src/plugins/vcsbase/vcsbaseclientsettings.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,7 @@ public: switch (v.type()) { case QVariant::UInt: m_type = QVariant::Int; + Q_FALLTHROUGH(); case QVariant::Int: m_comp.intValue = v.toInt(); break; From be3e12c8aff85e133f7a3cddb1c0a9ecf8607467 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 14 Jul 2017 12:38:06 +0200 Subject: [PATCH 07/35] CppEditor: Avoid auto insertion of '}' in empty line ...when typing '{'. Change-Id: Ia1d3bcd7440c96ed3c8c1479148dd74d3d291689 Reviewed-by: David Schulz --- src/libs/cplusplus/MatchingText.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libs/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp index f783d4c508e..3fdb573b918 100644 --- a/src/libs/cplusplus/MatchingText.cpp +++ b/src/libs/cplusplus/MatchingText.cpp @@ -143,9 +143,13 @@ bool MatchingText::contextAllowsAutoParentheses(const QTextCursor &cursor, if (!textToInsert.isEmpty()) ch = textToInsert.at(0); + if (ch == QLatin1Char('{') && cursor.block().text().trimmed().isEmpty()) + return false; // User just might want to wrap up some lines. + if (!shouldInsertMatchingText(cursor) && ch != QLatin1Char('\'') && ch != QLatin1Char('"')) return false; - else if (isInCommentHelper(cursor)) + + if (isInCommentHelper(cursor)) return false; return true; From db88225b0ea9531062d184f2e52492b3218980f3 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 6 Jul 2017 12:04:19 +0200 Subject: [PATCH 08/35] CppEditor: Fix invalidating diagnostics on reload Issue was: 1. Open some small file without any includes but with diagnostics 2. Switch to the shell and touch the file open in Qt Creator 3. Switch back to Qt Creator and confirm reload --> Ops, inline diagnostic stays invalidated/gray This is due to a race condition. The problematic sequence is: 1. CppEditorDocument::scheduleProcessDocument() // OK, because contents changed 2. ModelManagerSupportClang::onCppDocumentReloadFinishedOnTranslationUnit(bool) // OK, because we listen on TextDocument::contentsChangedWithPosition. // Because of the fast reparse, new diagnostics are processed with // ClangEditorDocumentProcessor::updateCodeWarnings(). 3. CppEditorDocument::processDocument() // Timeout, invalidates the already up to date diagnostics Avoid to trigger the process timer during a reload. Change-Id: I712d6b2fd5524d5fe6866dbdbb8cbca05e4aef2c Reviewed-by: David Schulz --- src/plugins/cppeditor/cppeditordocument.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp index c5a9d40e2ec..d31a4eb899c 100644 --- a/src/plugins/cppeditor/cppeditordocument.cpp +++ b/src/plugins/cppeditor/cppeditordocument.cpp @@ -201,12 +201,17 @@ void CppEditorDocument::onAboutToReload() { QTC_CHECK(!m_fileIsBeingReloaded); m_fileIsBeingReloaded = true; + + processor()->invalidateDiagnostics(); } void CppEditorDocument::onReloadFinished() { QTC_CHECK(m_fileIsBeingReloaded); m_fileIsBeingReloaded = false; + + m_processorRevision = document()->revision(); + processDocument(); } void CppEditorDocument::reparseWithPreferredParseContext(const QString &parseContextId) @@ -250,6 +255,9 @@ void CppEditorDocument::onFilePathChanged(const Utils::FileName &oldPath, void CppEditorDocument::scheduleProcessDocument() { + if (m_fileIsBeingReloaded) + return; + m_processorRevision = document()->revision(); m_processorTimer.start(); processor()->editorDocumentTimerRestarted(); From 8309e0c56a234f7ab1c2d658fcd680b801a5e2f4 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 14 Jul 2017 09:42:05 +0200 Subject: [PATCH 09/35] Clang: Avoid blocking UI if references are requested and clangbackend crashes The two cases in which the UI might be blocked are: * Invocation of the editor context menu * Rename Symbol Under Cursor Cancel the future if the backend is restarted and on the other side, check whether the future is cancelled. Change-Id: If2315da1f66f15eab1531fcd8da1dff851a9a4e6 Reviewed-by: Ivan Donchevskii Reviewed-by: David Schulz --- .../clangbackendipcintegration.cpp | 22 ++++++++++++------- .../clangbackendipcintegration.h | 4 ++-- .../cppeditor/cppuseselectionsupdater.cpp | 6 ++++- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 5ff5b1aa7e5..cfb52f15283 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -99,7 +99,7 @@ IpcReceiver::IpcReceiver() IpcReceiver::~IpcReceiver() { - deleteAndClearWaitingAssistProcessors(); + reset(); } void IpcReceiver::setAliveHandler(const IpcReceiver::AliveHandler &handler) @@ -116,12 +116,6 @@ void IpcReceiver::addExpectedCodeCompletedMessage( m_assistProcessorsTable.insert(ticket, processor); } -void IpcReceiver::deleteAndClearWaitingAssistProcessors() -{ - qDeleteAll(m_assistProcessorsTable.begin(), m_assistProcessorsTable.end()); - m_assistProcessorsTable.clear(); -} - void IpcReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget) { QMutableHashIterator it(m_assistProcessorsTable); @@ -155,6 +149,18 @@ bool IpcReceiver::isExpectingCodeCompletedMessage() const return !m_assistProcessorsTable.isEmpty(); } +void IpcReceiver::reset() +{ + // Clean up waiting assist processors + qDeleteAll(m_assistProcessorsTable.begin(), m_assistProcessorsTable.end()); + m_assistProcessorsTable.clear(); + + // Clean up futures for references + for (ReferencesEntry &entry : m_referencesTable) + entry.futureInterface.cancel(); + m_referencesTable.clear(); +} + void IpcReceiver::alive() { if (printAliveMessage()) @@ -719,7 +725,7 @@ void IpcCommunicator::onConnectedToBackend() if (m_connectedCount > 1) logRestartedDueToUnexpectedFinish(); - m_ipcReceiver.deleteAndClearWaitingAssistProcessors(); + m_ipcReceiver.reset(); m_ipcSender.reset(new IpcSender(m_connection)); initializeBackendWithCurrentData(); diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.h b/src/plugins/clangcodemodel/clangbackendipcintegration.h index 57a07e8097d..e98565f48c1 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.h +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.h @@ -73,14 +73,14 @@ public: void setAliveHandler(const AliveHandler &handler); void addExpectedCodeCompletedMessage(quint64 ticket, ClangCompletionAssistProcessor *processor); - void deleteAndClearWaitingAssistProcessors(); void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget); QFuture addExpectedReferencesMessage(quint64 ticket, QTextDocument *textDocument); - bool isExpectingCodeCompletedMessage() const; + void reset(); + private: void alive() override; void echo(const ClangBackEnd::EchoMessage &message) override; diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp index 5e03ebbe2de..81e1436ccde 100644 --- a/src/plugins/cppeditor/cppuseselectionsupdater.cpp +++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp @@ -98,8 +98,12 @@ void CppUseSelectionsUpdater::update(CallType callType) // QFuture::waitForFinished seems to block completely, not even // allowing to process events from QLocalSocket. - while (!future.isFinished()) + while (!future.isFinished()) { + if (future.isCanceled()) + return; + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); + } processResults(future.result()); } From 0b1eaacabba0c0b9366766b020597d9280ff19af Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Wed, 5 Jul 2017 16:22:10 +0200 Subject: [PATCH 10/35] DiffEditor: fix the cancellation of diff requests Change-Id: I36c4af4ec51473fb9da5d9f099f2251f75b2020a Reviewed-by: Orgad Shaneh --- src/plugins/diffeditor/diffeditorplugin.cpp | 6 +- .../vcsbase/vcsbasediffeditorcontroller.cpp | 133 +++++++++++++++--- 2 files changed, 119 insertions(+), 20 deletions(-) diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 232c2addaa2..6391c0ae0af 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -156,10 +156,12 @@ void DiffFilesController::reload() void DiffFilesController::reloaded() { - const QList fileDataList = m_futureWatcher.future().results(); + const bool success = !m_futureWatcher.future().isCanceled(); + const QList fileDataList = success + ? m_futureWatcher.future().results() : QList(); setDiffFiles(fileDataList); - reloadFinished(true); + reloadFinished(success); } void DiffFilesController::cancelReload() diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp index b92a35f854f..6b628cdb134 100644 --- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp +++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp @@ -48,6 +48,37 @@ static void readPatch(QFutureInterface> &futureInterface, futureInterface.reportResult(fileDataList); } +///////////////////// + +// We need a way to disconnect from signals posted from different thread +// so that signals that are already posted from the other thread and not delivered +// yet will be ignored. Unfortunately, simple QObject::disconnect() doesn't +// work like that, since signals that are already posted and are awaiting +// to be delivered WILL BE delivered later, even after a call to QObject::disconnect(). +// The delivery will happen when the control returns to the main event loop. + +// This proxy class solves the above problem. Instead of a call to +// QObject::disconnect(), which would still deliver posted signals, +// we delete the proxy object immediately. In this way signals which are +// already posted and are awaiting to be delivered won't be delivered to the +// destroyed object. + +// So the only reason for this proxy object is to be able to disconnect +// effectively from the signals posted from different threads. + +class VcsCommandResultProxy : public QObject { + Q_OBJECT +public: + VcsCommandResultProxy(VcsCommand *command, VcsBaseDiffEditorControllerPrivate *target); +private: + void storeOutput(const QString &output); + void commandFinished(bool success); + + VcsBaseDiffEditorControllerPrivate *m_target; +}; + +///////////////////// + class VcsBaseDiffEditorControllerPrivate { public: @@ -59,6 +90,7 @@ public: void processingFinished(); void processDiff(const QString &patch); void cancelReload(); + void storeOutput(const QString &output); void commandFinished(bool success); VcsBaseDiffEditorController *q; @@ -67,18 +99,43 @@ public: QString m_startupFile; QString m_output; QPointer m_command; - QFutureWatcher> m_processWatcher; + QPointer m_commandResultProxy; + QFutureWatcher> *m_processWatcher = nullptr; }; -VcsBaseDiffEditorControllerPrivate::VcsBaseDiffEditorControllerPrivate(VcsBaseDiffEditorController *controller, +///////////////////// + +VcsCommandResultProxy::VcsCommandResultProxy(VcsCommand *command, + VcsBaseDiffEditorControllerPrivate *target) + : QObject(target->q) + , m_target(target) +{ + connect(command, &VcsCommand::stdOutText, + this, &VcsCommandResultProxy::storeOutput); + connect(command, &VcsCommand::finished, + this, &VcsCommandResultProxy::commandFinished); + connect(command, &VcsCommand::destroyed, + this, &QObject::deleteLater); +} + +void VcsCommandResultProxy::storeOutput(const QString &output) +{ + m_target->storeOutput(output); +} + +void VcsCommandResultProxy::commandFinished(bool success) +{ + m_target->commandFinished(success); +} + +VcsBaseDiffEditorControllerPrivate::VcsBaseDiffEditorControllerPrivate( + VcsBaseDiffEditorController *controller, VcsBaseClientImpl *client, const QString &workingDirectory) : q(controller) , m_client(client) , m_directory(workingDirectory) { - QObject::connect(&m_processWatcher, &QFutureWatcher>::finished, q, - [this] () { processingFinished(); }); } VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate() @@ -88,9 +145,18 @@ VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate() void VcsBaseDiffEditorControllerPrivate::processingFinished() { - bool success = !m_processWatcher.future().isCanceled(); + QTC_ASSERT(m_processWatcher, return); + + // success is false when the user clicked the cancel micro button + // inside the progress indicator + const bool success = !m_processWatcher->future().isCanceled(); const QList fileDataList = success - ? m_processWatcher.future().result() : QList(); + ? m_processWatcher->future().result() : QList(); + + // Prevent direct deletion of m_processWatcher since + // processingFinished() is called directly by the m_processWatcher. + m_processWatcher->deleteLater(); + m_processWatcher = nullptr; q->setDiffFiles(fileDataList, q->workingDirectory(), q->startupFile()); q->reloadFinished(success); @@ -98,39 +164,67 @@ void VcsBaseDiffEditorControllerPrivate::processingFinished() void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch) { - m_processWatcher.setFuture(Utils::runAsync(&readPatch, patch)); + cancelReload(); - ProgressManager::addTask(m_processWatcher.future(), - q->tr("Processing diff"), "DiffEditor"); + m_processWatcher = new QFutureWatcher>(); + + QObject::connect(m_processWatcher, &QFutureWatcher>::finished, + [this] () { processingFinished(); } ); + + m_processWatcher->setFuture(Utils::runAsync(&readPatch, patch)); + + ProgressManager::addTask(m_processWatcher->future(), + q->tr("Processing diff"), "DiffEditor"); } void VcsBaseDiffEditorControllerPrivate::cancelReload() { if (m_command) { - m_command->disconnect(); m_command->cancel(); m_command.clear(); } - if (m_processWatcher.future().isRunning()) { - m_processWatcher.future().cancel(); - m_processWatcher.setFuture(QFuture>()); + // Disconnect effectively, don't deliver already posted signals + if (m_commandResultProxy) + delete m_commandResultProxy.data(); + + if (m_processWatcher) { + // Cancel the running process without the further processingFinished() + // notification for this process. + m_processWatcher->future().cancel(); + delete m_processWatcher; + m_processWatcher = nullptr; } + m_output = QString(); } +void VcsBaseDiffEditorControllerPrivate::storeOutput(const QString &output) +{ + m_output = output; +} + void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success) { if (m_command) m_command.clear(); + // Prevent direct deletion of m_commandResultProxy inside the possible + // subsequent synchronous calls to cancelReload() [called e.g. by + // processCommandOutput() overload], since + // commandFinished() is called directly by the m_commandResultProxy. + // m_commandResultProxy is removed via deleteLater right after + // a call to this commandFinished() is finished + if (m_commandResultProxy) + m_commandResultProxy.clear(); + if (!success) { cancelReload(); q->reloadFinished(success); return; } - q->processCommandOutput(m_output); + q->processCommandOutput(QString(m_output)); // pass a copy of m_output } ///////////////////// @@ -150,14 +244,15 @@ VcsBaseDiffEditorController::~VcsBaseDiffEditorController() void VcsBaseDiffEditorController::runCommand(const QList &args, unsigned flags, QTextCodec *codec) { + // Cancel the possible ongoing reload without the commandFinished() nor + // processingFinished() notifications, as right after that + // we re-reload it from scratch. So no intermediate "Retrieving data failed." + // and "Waiting for data..." will be shown. d->cancelReload(); d->m_command = new VcsCommand(workingDirectory(), d->m_client->processEnvironment()); d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec()); - connect(d->m_command.data(), &VcsCommand::stdOutText, this, - [this] (const QString &output) { d->m_output = output; }); - connect(d->m_command.data(), &VcsCommand::finished, this, - [this] (bool success) { d->commandFinished(success); }); + d->m_commandResultProxy = new VcsCommandResultProxy(d->m_command.data(), d); d->m_command->addFlags(flags); for (const QStringList &arg : args) { @@ -195,3 +290,5 @@ QString VcsBaseDiffEditorController::startupFile() const } } // namespace VcsBase + +#include "vcsbasediffeditorcontroller.moc" From d5342eff77a3857e3d4341bef045e2ab01c73175 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 13 Jul 2017 16:15:24 +0200 Subject: [PATCH 11/35] fix property spelling Change-Id: I00f84ec8d2c83d7f3937d2e21a24e02ba28991b3 Reviewed-by: Christian Stenger --- share/qtcreator/qml/qmlpuppet/qmlprivategate/metaobject.cpp | 6 +++--- .../qmldesigner/designercore/metainfo/nodemetainfo.cpp | 4 ++-- .../QtQuick/Controls/SplitView.qml | 2 +- .../QtQuick/Controls/SplitView.qml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/share/qtcreator/qml/qmlpuppet/qmlprivategate/metaobject.cpp b/share/qtcreator/qml/qmlpuppet/qmlprivategate/metaobject.cpp index 0b887fa0274..08caa703687 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlprivategate/metaobject.cpp +++ b/share/qtcreator/qml/qmlpuppet/qmlprivategate/metaobject.cpp @@ -304,9 +304,9 @@ int MetaObject::metaCall(QMetaObject::Call call, int id, void **a) && property(id).name() == QLatin1String("parent"))) { QObject *contextDummyObject = objectNodeInstance->nodeInstanceServer()->dummyContextObject(); - int properyIndex = contextDummyObject->metaObject()->indexOfProperty(propertyById.name()); - if (properyIndex >= 0) - metaCallReturnValue = contextDummyObject->qt_metacall(call, properyIndex, a); + int propertyIndex = contextDummyObject->metaObject()->indexOfProperty(propertyById.name()); + if (propertyIndex >= 0) + metaCallReturnValue = contextDummyObject->qt_metacall(call, propertyIndex, a); } } */ diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index a95c455134d..f5bb5d1ba68 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -1029,9 +1029,9 @@ bool NodeMetaInfoPrivate::cleverCheckType(const TypeName &otherType) const return typeName == convertedName.toUtf8(); } -QVariant::Type NodeMetaInfoPrivate::variantTypeId(const PropertyName &properyName) const +QVariant::Type NodeMetaInfoPrivate::variantTypeId(const PropertyName &propertyName) const { - TypeName typeName = propertyType(properyName); + TypeName typeName = propertyType(propertyName); if (typeName == "string") return QVariant::String; diff --git a/tests/auto/qml/codemodel/importscheck/005_compositeQmlCopyAndCpp/QtQuick/Controls/SplitView.qml b/tests/auto/qml/codemodel/importscheck/005_compositeQmlCopyAndCpp/QtQuick/Controls/SplitView.qml index 2e2ca6a7bff..e792762e7cc 100644 --- a/tests/auto/qml/codemodel/importscheck/005_compositeQmlCopyAndCpp/QtQuick/Controls/SplitView.qml +++ b/tests/auto/qml/codemodel/importscheck/005_compositeQmlCopyAndCpp/QtQuick/Controls/SplitView.qml @@ -157,7 +157,7 @@ Item { } /*! - This propery is \c true when the user is resizing any of the items by + This property is \c true when the user is resizing any of the items by dragging on the splitter handles. */ property bool resizing: false diff --git a/tests/auto/qml/codemodel/importscheck/007_compositeQmlCopyAndCppAndQml/QtQuick/Controls/SplitView.qml b/tests/auto/qml/codemodel/importscheck/007_compositeQmlCopyAndCppAndQml/QtQuick/Controls/SplitView.qml index 2e2ca6a7bff..e792762e7cc 100644 --- a/tests/auto/qml/codemodel/importscheck/007_compositeQmlCopyAndCppAndQml/QtQuick/Controls/SplitView.qml +++ b/tests/auto/qml/codemodel/importscheck/007_compositeQmlCopyAndCppAndQml/QtQuick/Controls/SplitView.qml @@ -157,7 +157,7 @@ Item { } /*! - This propery is \c true when the user is resizing any of the items by + This property is \c true when the user is resizing any of the items by dragging on the splitter handles. */ property bool resizing: false From a7e895166f9ca6aad1389a46913b6c83bb3d76d0 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 17 Jul 2017 10:36:24 +0200 Subject: [PATCH 12/35] Locator: Fix pressing return when no results are available yet In that case the first item will be activated as soon as it gets available. That behavior got lost during the recent refactoring. Task-number: QTCREATORBUG-18560 Change-Id: Ifda117f92f2adf23b499f50bdb4809c5e7830517 Reviewed-by: Orgad Shaneh --- .../coreplugin/locator/locatorwidget.cpp | 18 ++++++++++++++---- src/plugins/coreplugin/locator/locatorwidget.h | 4 +++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/plugins/coreplugin/locator/locatorwidget.cpp b/src/plugins/coreplugin/locator/locatorwidget.cpp index 76f0ac1f5b6..5073bcd33c3 100644 --- a/src/plugins/coreplugin/locator/locatorwidget.cpp +++ b/src/plugins/coreplugin/locator/locatorwidget.cpp @@ -483,6 +483,16 @@ void CompletionList::keyPressEvent(QKeyEvent *event) return; } break; + case Qt::Key_Return: + case Qt::Key_Enter: + // emit activated even if current index is not valid + // if there are no results yet, this allows activating the first entry when it is available + // (see LocatorWidget::addSearchResults) + if (event->modifiers() == 0) { + emit activated(currentIndex()); + return; + } + break; } Utils::TreeView::keyPressEvent(event); } @@ -795,9 +805,9 @@ void LocatorWidget::handleSearchFinished() m_showProgressTimer.stop(); setProgressIndicatorVisible(false); m_updateRequested = false; - if (m_rowRequestedForAccept >= 0) { - acceptEntry(m_rowRequestedForAccept); - m_rowRequestedForAccept = -1; + if (m_rowRequestedForAccept) { + acceptEntry(m_rowRequestedForAccept.value()); + m_rowRequestedForAccept.reset(); return; } if (m_entriesWatcher->future().isCanceled()) { @@ -892,7 +902,7 @@ void LocatorWidget::addSearchResults(int firstIndex, int endIndex) m_locatorModel->addEntries(entries); if (selectFirst) { emit selectRow(0); - if (m_rowRequestedForAccept >= 0) + if (m_rowRequestedForAccept) m_rowRequestedForAccept = 0; } } diff --git a/src/plugins/coreplugin/locator/locatorwidget.h b/src/plugins/coreplugin/locator/locatorwidget.h index 4484faefdde..c4ce3c4a14d 100644 --- a/src/plugins/coreplugin/locator/locatorwidget.h +++ b/src/plugins/coreplugin/locator/locatorwidget.h @@ -27,6 +27,8 @@ #include "locator.h" +#include + #include #include @@ -99,9 +101,9 @@ private: bool m_needsClearResult = true; bool m_updateRequested = false; bool m_possibleToolTipRequest = false; - int m_rowRequestedForAccept = -1; QWidget *m_progressIndicator; QTimer m_showProgressTimer; + Utils::optional m_rowRequestedForAccept; }; class LocatorPopup : public QWidget From c8054d9547ffffd9300340d48033e9f75f3f3e7b Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 14 Jul 2017 11:22:35 +0200 Subject: [PATCH 13/35] ProjectExplorer: Heed RunControlFactory priorities again This fixes the regression introduced in 5a848aa18872f and uses the feature to resolve the conflict between ClangStaticAnalyzer and Boot2Qt. Change-Id: I6cdec8261a457c399c11a4b2078a78088d4c56d1 Reviewed-by: Christian Kandeler --- .../clangstaticanalyzerplugin.cpp | 2 +- .../projectexplorer/runconfiguration.cpp | 24 +++++++++++++------ .../projectexplorer/runconfiguration.h | 9 +++---- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp index f10b2784bb8..e18b9747b81 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp @@ -143,7 +143,7 @@ bool ClangStaticAnalyzerPlugin::initialize(const QStringList &arguments, QString }; RunControl::registerWorker - (Constants::CLANGSTATICANALYZER_RUN_MODE, constraint); + (Constants::CLANGSTATICANALYZER_RUN_MODE, constraint, /*priority*/ -1); return true; } diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index d0984117068..093c261ad22 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -522,14 +522,24 @@ bool IRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id run RunControl *IRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id runMode, QString *) { + WorkerFactories candidates; for (const RunControl::WorkerFactory &factory : theWorkerFactories()) { - if (factory.canRun(runConfiguration, runMode)) { - auto runControl = new RunControl(runConfiguration, runMode); - factory.producer(runControl); - return runControl; - } - }; - return nullptr; + if (factory.canRun(runConfiguration, runMode)) + candidates.push_back(factory); + } + + if (candidates.empty()) + return nullptr; + + RunControl::WorkerFactory bestFactory = *candidates.begin(); + for (const RunControl::WorkerFactory &factory : candidates) { + if (factory.priority > bestFactory.priority) + bestFactory = factory; + } + + auto runControl = new RunControl(runConfiguration, runMode); + bestFactory.producer(runControl); + return runControl; } /*! diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index eb408c204a0..264ec4fd50a 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -450,23 +450,24 @@ public: addWorkerFactory({runMode, constraint, producer}); } template - static void registerWorker(Core::Id runMode, const Constraint &constraint) + static void registerWorker(Core::Id runMode, const Constraint &constraint, int priority = 0) { auto producer = [](RunControl *rc) { return new Worker(rc); }; - addWorkerFactory({runMode, constraint, producer}); + addWorkerFactory({runMode, constraint, producer, priority}); } template - static void registerWorker(Core::Id runMode) + static void registerWorker(Core::Id runMode, int priority = 0) { auto constraint = [](RunConfiguration *runConfig) { return qobject_cast(runConfig); }; auto producer = [](RunControl *rc) { return new Worker(rc); }; - addWorkerFactory({runMode, constraint, producer}); + addWorkerFactory({runMode, constraint, producer, priority}); } struct WorkerFactory { Core::Id runMode; Constraint constraint; WorkerCreator producer; + int priority = 0; bool canRun(RunConfiguration *runConfiguration, Core::Id runMode) const; }; From cd5ba755056a70f86fa6b9d7789090f9c84927de Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 13 Jul 2017 15:24:04 +0200 Subject: [PATCH 14/35] ProjectExplorer: Use a real 'finishing' phase for RunControls Instead of a blunt delete() RunControl::initiateFinish() is triggered by the closing of the application output instead. The rampdown process is basically the same as stop() now, except for the other success signal (new finished()) and the final self-destruction of the runcontrol. stop() itself triggers initiateStop() on all running workers in parallel (before it was in the order of start). This gives downstream complex worker combinations the flexibility to use any order it wants by ignoring stop() on 'uninteresting' workers, and centralizing rampdown e.g. in the main worker. That setup should be rare in practice, but seems needed in some profiler cases. Change-Id: I986a152a663754206709ed4df0d4568847afad17 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/appoutputpane.cpp | 8 +- src/plugins/projectexplorer/appoutputpane.h | 3 +- .../projectexplorer/runconfiguration.cpp | 180 +++++++++++++++--- .../projectexplorer/runconfiguration.h | 2 + src/plugins/valgrind/memchecktool.cpp | 1 + src/plugins/valgrind/valgrindengine.cpp | 1 - 6 files changed, 162 insertions(+), 33 deletions(-) diff --git a/src/plugins/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index 9e0617454bd..1e6ef0efd68 100644 --- a/src/plugins/projectexplorer/appoutputpane.cpp +++ b/src/plugins/projectexplorer/appoutputpane.cpp @@ -420,7 +420,8 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc) if (tabIndex != -1) { RunControlTab &tab = m_runControlTabs[tabIndex]; // Reuse this tab - delete tab.runControl; + if (tab.runControl) + tab.runControl->initiateFinish(); tab.runControl = rc; tab.window->setFormatter(rc ? rc->outputFormatter() : nullptr); @@ -559,7 +560,7 @@ bool AppOutputPane::closeTabs(CloseTabMode mode) QList AppOutputPane::allRunControls() const { return Utils::transform(m_runControlTabs,[](const RunControlTab &tab) { - return tab.runControl; + return tab.runControl.data(); }); } @@ -596,7 +597,8 @@ bool AppOutputPane::closeTab(int tabIndex, CloseTabMode closeTabMode) m_tabWidget->removeTab(tabIndex); delete m_runControlTabs[index].window; - delete m_runControlTabs[index].runControl; + m_runControlTabs[index].runControl->initiateFinish(); // Will self-destruct. + m_runControlTabs[index].runControl = 0; m_runControlTabs.removeAt(index); updateCloseActions(); diff --git a/src/plugins/projectexplorer/appoutputpane.h b/src/plugins/projectexplorer/appoutputpane.h index ba3839ca6af..b260447ba5a 100644 --- a/src/plugins/projectexplorer/appoutputpane.h +++ b/src/plugins/projectexplorer/appoutputpane.h @@ -25,6 +25,7 @@ #pragma once +#include #include #include @@ -124,7 +125,7 @@ private: public: explicit RunControlTab(RunControl *runControl = nullptr, Core::OutputWindow *window = nullptr); - RunControl *runControl; + QPointer runControl; Core::OutputWindow *window; BehaviorOnOutput behaviorOnOutput = Flash; }; diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 093c261ad22..8cbfaf7fd21 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -602,7 +602,7 @@ static QString stateName(RunWorkerState s) SN(RunWorkerState::Done) SN(RunWorkerState::Failed) } - return QLatin1String(""); + return QString("").arg(int(s)); # undef SN } @@ -616,7 +616,7 @@ public: RunWorker *q; RunWorkerState state = RunWorkerState::Initialized; - RunControl *runControl; + QPointer runControl; QList dependencies; QString id; @@ -635,6 +635,8 @@ enum class RunControlState Running, // All good and running. Stopping, // initiateStop() was called, stop application/tool Stopped, // all good, but stopped. Can possibly be re-started + Finishing, // Application tab manually closed + Finished // Final state, will self-destruct with deleteLater() }; static QString stateName(RunControlState s) @@ -646,8 +648,10 @@ static QString stateName(RunControlState s) SN(RunControlState::Running) SN(RunControlState::Stopping) SN(RunControlState::Stopped) + SN(RunControlState::Finishing) + SN(RunControlState::Finished) } - return QLatin1String(""); + return QString("").arg(int(s)); # undef SN } @@ -669,8 +673,11 @@ public: ~RunControlPrivate() { - QTC_CHECK(state == RunControlState::Stopped || state == RunControlState::Initialized); + QTC_CHECK(state == RunControlState::Finished || state == RunControlState::Initialized); + disconnect(); + q = nullptr; qDeleteAll(m_workers); + m_workers.clear(); delete outputFormatter; } @@ -685,7 +692,7 @@ public: void initiateReStart(); void continueStart(); void initiateStop(); - void continueStop(); + void initiateFinish(); void onWorkerStarted(RunWorker *worker); void onWorkerStopped(RunWorker *worker); @@ -704,7 +711,7 @@ public: Utils::Icon icon; const QPointer runConfiguration; // Not owned. QPointer project; // Not owned. - Utils::OutputFormatter *outputFormatter = nullptr; + QPointer outputFormatter = nullptr; std::function promptToStop; std::vector m_factories; @@ -769,6 +776,11 @@ void RunControl::initiateStop() d->initiateStop(); } +void RunControl::initiateFinish() +{ + d->initiateFinish(); +} + using WorkerCreators = QHash; static WorkerCreators &theWorkerCreators() @@ -890,15 +902,8 @@ void RunControlPrivate::initiateStop() { checkState(RunControlState::Running); setState(RunControlState::Stopping); - debugMessage("Queue: Stopping"); + debugMessage("Queue: Stopping for all workers"); - continueStop(); -} - -void RunControlPrivate::continueStop() -{ - debugMessage("Continue Stopping"); - checkState(RunControlState::Stopping); bool allDone = true; for (RunWorker *worker : m_workers) { if (worker) { @@ -914,17 +919,17 @@ void RunControlPrivate::continueStop() allDone = false; break; case RunWorkerState::Starting: - worker->d->state = RunWorkerState::Stopping; debugMessage(" " + workerId + " was Starting, queuing stop"); - allDone = false; + worker->d->state = RunWorkerState::Stopping; QTimer::singleShot(0, worker, &RunWorker::initiateStop); - return; // Sic. + allDone = false; + break; case RunWorkerState::Running: debugMessage(" " + workerId + " was Running, queuing stop"); worker->d->state = RunWorkerState::Stopping; allDone = false; QTimer::singleShot(0, worker, &RunWorker::initiateStop); - return; // Sic. + break; case RunWorkerState::Done: debugMessage(" " + workerId + " was Done. Good."); break; @@ -937,8 +942,59 @@ void RunControlPrivate::continueStop() } } if (allDone) { - debugMessage("All workers stopped. Set runControl to Stopped"); + debugMessage("All stopped."); setState(RunControlState::Stopped); + } else { + debugMessage("Not all workers stopped. Waiting..."); + } +} + +void RunControlPrivate::initiateFinish() +{ + setState(RunControlState::Finishing); + debugMessage("Ramping down"); + + bool allDone = true; + for (RunWorker *worker : m_workers) { + if (worker) { + const QString &workerId = worker->d->id; + debugMessage(" Examining worker " + workerId); + switch (worker->d->state) { + case RunWorkerState::Initialized: + debugMessage(" " + workerId + " was Initialized, setting to Done"); + worker->d->state = RunWorkerState::Done; + break; + case RunWorkerState::Stopping: + debugMessage(" " + workerId + " was already Stopping. Keeping it that way"); + allDone = false; + break; + case RunWorkerState::Starting: + debugMessage(" " + workerId + " was Starting, queuing stop"); + worker->d->state = RunWorkerState::Stopping; + QTimer::singleShot(0, worker, &RunWorker::initiateStop); + allDone = false; + break; + case RunWorkerState::Running: + debugMessage(" " + workerId + " was Running, queuing stop"); + worker->d->state = RunWorkerState::Stopping; + allDone = false; + QTimer::singleShot(0, worker, &RunWorker::initiateStop); + break; + case RunWorkerState::Done: + debugMessage(" " + workerId + " was Done. Good."); + break; + case RunWorkerState::Failed: + debugMessage(" " + workerId + " was Failed. Good"); + break; + } + } else { + debugMessage("Found unknown deleted worker"); + } + } + if (allDone) { + setState(RunControlState::Finished); + } else { + debugMessage("Not all workers finished. Waiting..."); } } @@ -954,7 +1010,6 @@ void RunControlPrivate::onWorkerStarted(RunWorker *worker) showError(tr("Unexpected run control state %1 when worker %2 started") .arg(stateName(state)) .arg(worker->d->id)); - //setState(RunControlState::Stopped); } void RunControlPrivate::onWorkerFailed(RunWorker *worker, const QString &msg) @@ -978,13 +1033,72 @@ void RunControlPrivate::onWorkerStopped(RunWorker *worker) worker->d->state = RunWorkerState::Done; debugMessage(workerId + " stopped expectedly."); break; + case RunWorkerState::Done: + worker->d->state = RunWorkerState::Done; + debugMessage(workerId + " stopped twice. Huh? But harmless."); + return; // Sic! default: debugMessage(workerId + " stopped unexpectedly in state" + stateName(worker->d->state)); worker->d->state = RunWorkerState::Failed; break; } - continueStop(); + + debugMessage("Checking whether all stopped"); + bool allDone = true; + for (RunWorker *worker : m_workers) { + if (worker) { + const QString &workerId = worker->d->id; + debugMessage(" Examining worker " + workerId); + switch (worker->d->state) { + case RunWorkerState::Initialized: + debugMessage(" " + workerId + " was Initialized, setting to Done"); + worker->d->state = RunWorkerState::Done; + break; + case RunWorkerState::Starting: + worker->d->state = RunWorkerState::Stopping; + debugMessage(" " + workerId + " was Starting, queuing stop"); + allDone = false; + break; + case RunWorkerState::Running: + debugMessage(" " + workerId + " was Running, queuing stop"); + worker->d->state = RunWorkerState::Stopping; + allDone = false; + break; + case RunWorkerState::Stopping: + debugMessage(" " + workerId + " was already Stopping. Keeping it that way"); + allDone = false; + break; + case RunWorkerState::Done: + debugMessage(" " + workerId + " was Done. Good."); + break; + case RunWorkerState::Failed: + debugMessage(" " + workerId + " was Failed. Good"); + break; + } + } else { + debugMessage("Found unknown deleted worker"); + } + } + if (state == RunControlState::Finishing) { + if (allDone) { + debugMessage("All finished. Deleting myself"); + setState(RunControlState::Finished); + } else { + debugMessage("Not all workers finished. Waiting..."); + } + } else { + if (allDone) { + if (state == RunControlState::Stopped) { + debugMessage("All workers stopped, but runControl was already stopped."); + } else { + debugMessage("All workers stopped. Set runControl to Stopped"); + setState(RunControlState::Stopped); + } + } else { + debugMessage("Not all workers stopped. Waiting..."); + } + } } void RunControlPrivate::showError(const QString &msg) @@ -1185,15 +1299,23 @@ bool RunControlPrivate::isAllowedTransition(RunControlState from, RunControlStat { switch (from) { case RunControlState::Initialized: - return to == RunControlState::Starting; + return to == RunControlState::Starting + || to == RunControlState::Finishing; case RunControlState::Starting: - return to == RunControlState::Running; + return to == RunControlState::Running + || to == RunControlState::Finishing; case RunControlState::Running: return to == RunControlState::Stopping - || to == RunControlState::Stopped; + || to == RunControlState::Stopped + || to == RunControlState::Finishing; case RunControlState::Stopping: - return to == RunControlState::Stopped; + return to == RunControlState::Stopped + || to == RunControlState::Finishing; case RunControlState::Stopped: + return to == RunControlState::Finishing; + case RunControlState::Finishing: + return to == RunControlState::Finished; + case RunControlState::Finished: return false; } return false; @@ -1223,11 +1345,13 @@ void RunControlPrivate::setState(RunControlState newState) break; case RunControlState::Stopped: q->setApplicationProcessHandle(Utils::ProcessHandle()); - foreach (auto worker, m_workers) - if (worker) - worker->onFinished(); emit q->stopped(); break; + case RunControlState::Finished: + emit q->finished(); + debugMessage("All finished. Deleting myself"); + deleteLater(); + break; default: break; } diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 264ec4fd50a..5a8fe5dbdc6 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -397,6 +397,7 @@ public: void initiateStart(); void initiateReStart(); void initiateStop(); + void initiateFinish(); bool promptToStop(bool *optionalPrompt = nullptr) const; void setPromptToStop(const std::function &promptToStop); @@ -480,6 +481,7 @@ signals: void aboutToStart(); void started(); void stopped(); + void finished(); void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle private: diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index a69e2eac606..cab6dea44c9 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -562,6 +562,7 @@ RunWorker *MemcheckTool::createRunWorker(RunControl *runControl) connect(runTool, &MemcheckToolRunner::internalParserError, this, &MemcheckTool::internalParserError); connect(runTool, &MemcheckToolRunner::stopped, this, &MemcheckTool::engineFinished); + m_stopAction->disconnect(); connect(m_stopAction, &QAction::triggered, runControl, &RunControl::initiateStop); m_toolBusy = true; diff --git a/src/plugins/valgrind/valgrindengine.cpp b/src/plugins/valgrind/valgrindengine.cpp index 3cb1a4245b2..13beca1fa06 100644 --- a/src/plugins/valgrind/valgrindengine.cpp +++ b/src/plugins/valgrind/valgrindengine.cpp @@ -106,7 +106,6 @@ void ValgrindToolRunner::stop() { m_isStopping = true; m_runner.stop(); - reportStopped(); // FIXME: Restrict to non-running scenarios? } QString ValgrindToolRunner::executable() const From cb0a09b74bb7279a9845955d6a85a0cfe95048c2 Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Mon, 17 Jul 2017 14:43:59 +0200 Subject: [PATCH 15/35] ProjectExplorer: Fix compile for older gcc/Qt5.6 Change-Id: I145f2fddb143b1e3149b4b850a7586115ac20df6 Reviewed-by: hjk --- src/plugins/projectexplorer/runconfiguration.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 5a8fe5dbdc6..57a39fe3742 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -470,6 +470,9 @@ public: WorkerCreator producer; int priority = 0; + WorkerFactory(const Core::Id &mode, Constraint constr, const WorkerCreator &prod, + int prio = 0) + : runMode(mode), constraint(constr), producer(prod), priority(prio) {} bool canRun(RunConfiguration *runConfiguration, Core::Id runMode) const; }; From 6c040996018bbcd32d17e45b82945fecb37352e1 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 14 Jul 2017 10:12:37 +0200 Subject: [PATCH 16/35] iOS: Dissolve IosRunControlFactory Follows suite. Change-Id: I2ef11d19d9a2d3d0f3f282a94f98a40478273fbc Reviewed-by: Vikas Pachdha --- src/plugins/ios/iosplugin.cpp | 19 +++++++++-- src/plugins/ios/iosrunfactories.cpp | 49 ----------------------------- src/plugins/ios/iosrunfactories.h | 17 ---------- src/plugins/ios/iosrunner.cpp | 20 ++++++++++++ 4 files changed, 37 insertions(+), 68 deletions(-) diff --git a/src/plugins/ios/iosplugin.cpp b/src/plugins/ios/iosplugin.cpp index 28e590167e0..b2b33d8ae32 100644 --- a/src/plugins/ios/iosplugin.cpp +++ b/src/plugins/ios/iosplugin.cpp @@ -36,17 +36,22 @@ #include "iosdsymbuildstep.h" #include "iosqtversionfactory.h" #include "iosrunfactories.h" +#include "iosrunner.h" #include "iossettingspage.h" #include "iossimulator.h" #include "iossimulatorfactory.h" #include "iostoolhandler.h" +#include "iosrunconfiguration.h" +#include #include +#include + #include #include -#include +using namespace ProjectExplorer; namespace Ios { namespace Internal { @@ -67,7 +72,6 @@ bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage) addAutoReleasedObject(new Internal::IosBuildConfigurationFactory); addAutoReleasedObject(new Internal::IosToolChainFactory); - addAutoReleasedObject(new Internal::IosRunControlFactory); addAutoReleasedObject(new Internal::IosRunConfigurationFactory); addAutoReleasedObject(new Internal::IosSettingsPage); addAutoReleasedObject(new Internal::IosQtVersionFactory); @@ -78,6 +82,17 @@ bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage) addAutoReleasedObject(new Internal::IosDsymBuildStepFactory); addAutoReleasedObject(new Internal::IosDeployConfigurationFactory); + auto constraint = [](RunConfiguration *runConfig) { + return qobject_cast(runConfig) != nullptr; + }; + + RunControl::registerWorker + (ProjectExplorer::Constants::NORMAL_RUN_MODE, constraint); + RunControl::registerWorker + (ProjectExplorer::Constants::DEBUG_RUN_MODE, constraint); + RunControl::registerWorker + (ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, constraint); + return true; } diff --git a/src/plugins/ios/iosrunfactories.cpp b/src/plugins/ios/iosrunfactories.cpp index b2d42b671b5..c41dcb8263f 100644 --- a/src/plugins/ios/iosrunfactories.cpp +++ b/src/plugins/ios/iosrunfactories.cpp @@ -27,7 +27,6 @@ #include "iosconstants.h" #include "iosrunconfiguration.h" -#include "iosrunner.h" #include "iosmanager.h" #include @@ -143,53 +142,5 @@ RunConfiguration *IosRunConfigurationFactory::doRestore(Target *parent, const QV return new IosRunConfiguration(parent, id, pathFromId(id)); } -IosRunControlFactory::IosRunControlFactory(QObject *parent) - : IRunControlFactory(parent) -{ -} - -bool IosRunControlFactory::canRun(RunConfiguration *runConfiguration, - Core::Id mode) const -{ - if (mode != ProjectExplorer::Constants::NORMAL_RUN_MODE - && mode != ProjectExplorer::Constants::DEBUG_RUN_MODE - && mode != ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { - return false; - } - - return qobject_cast(runConfiguration); -} - -RunControl *IosRunControlFactory::create(RunConfiguration *runConfig, - Core::Id mode, QString *errorMessage) -{ - Q_UNUSED(errorMessage); - Q_ASSERT(canRun(runConfig, mode)); - IosRunConfiguration *rc = qobject_cast(runConfig); - Q_ASSERT(rc); - Target *target = runConfig->target(); - QTC_ASSERT(target, return 0); - - Core::Id devId = DeviceKitInformation::deviceId(rc->target()->kit()); - // The device can only run an application at a time, if an app is running stop it. - if (m_activeRunControls.contains(devId)) { - if (QPointer activeRunControl = m_activeRunControls[devId]) - activeRunControl->initiateStop(); - m_activeRunControls.remove(devId); - } - auto runControl = new RunControl(runConfig, mode); - if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) { - (void) new Ios::Internal::IosRunSupport(runControl); - } else if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { - (void) new IosQmlProfilerSupport(runControl); - } else { - (void) new IosDebugSupport(runControl); - } - - if (devId.isValid()) - m_activeRunControls[devId] = runControl; - return runControl; -} - } // namespace Internal } // namespace Ios diff --git a/src/plugins/ios/iosrunfactories.h b/src/plugins/ios/iosrunfactories.h index 8e9b072639e..318e57e04ea 100644 --- a/src/plugins/ios/iosrunfactories.h +++ b/src/plugins/ios/iosrunfactories.h @@ -29,8 +29,6 @@ #include namespace ProjectExplorer { -class RunControl; -class RunConfigWidget; class Target; class Node; } // namespace ProjectExplorer @@ -68,20 +66,5 @@ private: const QVariantMap &map) override; }; -class IosRunControlFactory : public ProjectExplorer::IRunControlFactory -{ - Q_OBJECT - -public: - explicit IosRunControlFactory(QObject *parent = 0); - - bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, - Core::Id mode) const override; - ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration, - Core::Id mode, QString *) override; -private: - mutable QMap > m_activeRunControls; -}; - } // namespace Internal } // namespace Ios diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index 23400d34c74..0a09efe9336 100644 --- a/src/plugins/ios/iosrunner.cpp +++ b/src/plugins/ios/iosrunner.cpp @@ -74,9 +74,29 @@ using namespace Utils; namespace Ios { namespace Internal { +static void stopRunningRunControl(RunControl *runControl) +{ + static QMap> activeRunControls; + + RunConfiguration *runConfig = runControl->runConfiguration(); + Target *target = runConfig->target(); + Core::Id devId = DeviceKitInformation::deviceId(target->kit()); + + // The device can only run an application at a time, if an app is running stop it. + if (activeRunControls.contains(devId)) { + if (QPointer activeRunControl = activeRunControls[devId]) + activeRunControl->initiateStop(); + activeRunControls.remove(devId); + } + + if (devId.isValid()) + activeRunControls[devId] = runControl; +} + IosRunner::IosRunner(RunControl *runControl) : RunWorker(runControl) { + stopRunningRunControl(runControl); auto runConfig = qobject_cast(runControl->runConfiguration()); m_bundleDir = runConfig->bundleDirectory().toString(); m_arguments = QStringList(runConfig->commandLineArguments()); From b7babda68d1bfc162a4e5497e9645df9da221474 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 13 Jul 2017 17:00:29 +0200 Subject: [PATCH 17/35] iOS: Remove unneeded abortDebugger call Change-Id: Ib4a4897e61b74cfed54a77b367fcad8932a47b9f Reviewed-by: Vikas Pachdha --- src/plugins/ios/iosrunner.cpp | 5 ----- src/plugins/ios/iosrunner.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index 0a09efe9336..7ecd50b8367 100644 --- a/src/plugins/ios/iosrunner.cpp +++ b/src/plugins/ios/iosrunner.cpp @@ -533,10 +533,5 @@ void IosDebugSupport::start() DebuggerRunTool::start(); } -void IosDebugSupport::onFinished() -{ - abortDebugger(); -} - } // namespace Internal } // namespace Ios diff --git a/src/plugins/ios/iosrunner.h b/src/plugins/ios/iosrunner.h index 203ae879092..2db7cf8c0da 100644 --- a/src/plugins/ios/iosrunner.h +++ b/src/plugins/ios/iosrunner.h @@ -135,7 +135,6 @@ public: private: void start() override; - void onFinished() override; const QString m_dumperLib; IosRunner *m_runner; From d93da5f5f1f5cbc15c093e05a5a22829322e5685 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 14 Jul 2017 09:36:09 +0200 Subject: [PATCH 18/35] ProjectExplorer: Add and use a RunConfiguration::registerAspect<> ... to register RunConfigurationAspect creating functions. Change-Id: I9e7a2cef0bc134ac6a7becbd0b5ecb40c26ef118 Reviewed-by: hjk --- src/plugins/debugger/debuggerplugin.cpp | 14 +--------- .../projectexplorer/runconfiguration.cpp | 26 +++++-------------- .../projectexplorer/runconfiguration.h | 10 ++++--- src/plugins/qmlprofiler/qmlprofilerplugin.cpp | 13 ++-------- src/plugins/valgrind/valgrindplugin.cpp | 12 ++------- 5 files changed, 18 insertions(+), 57 deletions(-) diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 832a3435400..38d867c878b 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -421,18 +421,6 @@ namespace Internal { void addCdbOptionPages(QList *opts); void addGdbOptionPages(QList *opts); -/// DebuggerRunControlFactory - -class DebuggerRunControlFactory : public IRunControlFactory -{ -public: - IRunConfigurationAspect *createRunConfigurationAspect(RunConfiguration *rc) override - { - return new DebuggerRunConfigurationAspect(rc); - } -}; - - static QIcon visibleStartIcon(Id id, bool toolBarStyle) { if (id == Id(Constants::DEBUG)) { @@ -1495,7 +1483,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, m_localsAndExpressionsWindow->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS)); m_localsAndExpressionsWindow->setWindowTitle(m_localsWindow->windowTitle()); - m_plugin->addAutoReleasedObject(new DebuggerRunControlFactory); + RunConfiguration::registerAspect(); // The main "Start Debugging" action. act = m_startAction = new QAction(this); diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 8cbfaf7fd21..345cbcd5cc3 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -183,13 +183,16 @@ void IRunConfigurationAspect::resetProjectToGlobalSettings() for a target, but still be runnable via the output tab. */ +static std::vector theAspectFactories; + RunConfiguration::RunConfiguration(Target *target, Core::Id id) : ProjectConfiguration(target, id) { Q_ASSERT(target); ctor(); - addExtraAspects(); + for (const AspectFactory &factory : theAspectFactories) + addExtraAspect(factory(this)); } RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) : @@ -209,10 +212,9 @@ RunConfiguration::~RunConfiguration() qDeleteAll(m_aspects); } -void RunConfiguration::addExtraAspects() +void RunConfiguration::addAspectFactory(const AspectFactory &aspectFactory) { - foreach (IRunControlFactory *factory, ExtensionSystem::PluginManager::getObjects()) - addExtraAspect(factory->createRunConfigurationAspect(this)); + theAspectFactories.push_back(aspectFactory); } void RunConfiguration::addExtraAspect(IRunConfigurationAspect *aspect) @@ -542,22 +544,6 @@ RunControl *IRunControlFactory::create(RunConfiguration *runConfiguration, Core: return runControl; } -/*! - Returns an IRunConfigurationAspect to carry options for RunControls this - factory can create. - - If no extra options are required, it is allowed to return null like the - default implementation does. This function is intended to be called from the - RunConfiguration constructor, so passing a RunConfiguration pointer makes - no sense because that object is under construction at the time. -*/ - -IRunConfigurationAspect *IRunControlFactory::createRunConfigurationAspect(RunConfiguration *rc) -{ - Q_UNUSED(rc); - return nullptr; -} - /*! \class ProjectExplorer::RunControl \brief The RunControl class instances represent one item that is run. diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 57a39fe3742..0b9b3618def 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -245,6 +245,12 @@ public: static RunConfiguration *startupRunConfiguration(); + using AspectFactory = std::function; + template static void registerAspect() + { + addAspectFactory([](RunConfiguration *rc) { return new T(rc); }); + } + signals: void enabledChanged(); void requestRunActionsUpdate(); @@ -260,7 +266,7 @@ protected: private: void ctor(); - void addExtraAspects(); + static void addAspectFactory(const AspectFactory &aspectFactory); QList m_aspects; }; @@ -304,8 +310,6 @@ public: virtual bool canRun(RunConfiguration *runConfiguration, Core::Id runMode) const; virtual RunControl *create(RunConfiguration *runConfiguration, Core::Id runMode, QString *errorMessage); - virtual IRunConfigurationAspect *createRunConfigurationAspect(RunConfiguration *rc); - int priority() const; protected: void setPriority(int priority); // Higher values will be preferred. diff --git a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp index 777a042fc18..ea89b6b6dc0 100644 --- a/src/plugins/qmlprofiler/qmlprofilerplugin.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp @@ -76,16 +76,6 @@ namespace Internal { Q_GLOBAL_STATIC(QmlProfilerSettings, qmlProfilerGlobalSettings) - -class QmlProfilerRunControlFactory : public IRunControlFactory -{ -public: - IRunConfigurationAspect *createRunConfigurationAspect(RunConfiguration *rc) override - { - return new QmlProfilerRunConfigurationAspect(rc); - } -}; - bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorString) { Q_UNUSED(arguments) @@ -101,7 +91,8 @@ void QmlProfilerPlugin::extensionsInitialized() (void) new QmlProfilerTool(this); addAutoReleasedObject(new QmlProfilerOptionsPage); - addAutoReleasedObject(new QmlProfilerRunControlFactory); + + RunConfiguration::registerAspect(); auto constraint = [](RunConfiguration *runConfiguration) { Target *target = runConfiguration ? runConfiguration->target() : nullptr; diff --git a/src/plugins/valgrind/valgrindplugin.cpp b/src/plugins/valgrind/valgrindplugin.cpp index 4cb71eab681..4e250b8b19d 100644 --- a/src/plugins/valgrind/valgrindplugin.cpp +++ b/src/plugins/valgrind/valgrindplugin.cpp @@ -110,15 +110,6 @@ public: } }; -class ValgrindRunControlFactory : public IRunControlFactory -{ -public: - IRunConfigurationAspect *createRunConfigurationAspect(RunConfiguration *rc) override - { - return new ValgrindRunConfigurationAspect(rc); - } -}; - ValgrindPlugin::~ValgrindPlugin() { delete theGlobalSettings; @@ -131,7 +122,8 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *) theGlobalSettings->readSettings(); addAutoReleasedObject(new ValgrindOptionsPage); - addAutoReleasedObject(new ValgrindRunControlFactory); + + RunConfiguration::registerAspect(); return true; } From 528b0918bf943256ed41bfec8ca18bcace408ce5 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 13 Jul 2017 17:39:42 +0200 Subject: [PATCH 19/35] ProjectExplorer: Remove RunControl::bringApplicationToForeground ... and replace it by direct uses of ProcessHandle::activate(). Change-Id: I7beffba7bfbeff72a81b8699ff54a311a74ce1a3 Reviewed-by: Christian Stenger --- src/plugins/debugger/debuggerengine.cpp | 8 +------- src/plugins/debugger/qml/qmlengine.cpp | 2 +- .../projectexplorer/runconfiguration.cpp | 17 +++-------------- src/plugins/projectexplorer/runconfiguration.h | 1 - 4 files changed, 5 insertions(+), 23 deletions(-) diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index e60af1faa8b..efc1680458e 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -292,12 +292,6 @@ public: } } - void raiseApplication() - { - QTC_ASSERT(runControl(), return); - runControl()->bringApplicationToForeground(); - } - void scheduleResetLocation() { m_stackHandler.scheduleResetLocation(); @@ -1323,7 +1317,7 @@ void DebuggerEngine::notifyInferiorPid(const ProcessHandle &pid) showMessage(tr("Taking notice of pid %1").arg(pid.pid())); DebuggerStartMode sm = runParameters().startMode; if (sm == StartInternal || sm == StartExternal || sm == AttachExternal) - QTimer::singleShot(0, d, &DebuggerEnginePrivate::raiseApplication); + d->m_inferiorPid.activate(); } } diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 0a0ed1d5166..10e6d4f3b21 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -377,7 +377,7 @@ void QmlEngine::handleLauncherStarted() { // FIXME: The QmlEngine never calls notifyInferiorPid() triggering the // raising, so do it here manually for now. - runControl()->bringApplicationToForeground(); + runControl()->applicationProcessHandle().activate(); d->noDebugOutputTimer.start(); } diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 345cbcd5cc3..566ecc69129 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -1348,18 +1348,6 @@ void RunControlPrivate::debugMessage(const QString &msg) qCDebug(statesLog()) << msg; } -/*! - Brings the application determined by this RunControl's \c applicationProcessHandle - to the foreground. - - The default implementation raises the application on Mac, and does - nothing elsewhere. -*/ -void RunControl::bringApplicationToForeground() -{ - d->applicationProcessHandle.activate(); -} - void RunControl::appendMessage(const QString &msg, Utils::OutputFormat format) { emit appendMessageRequested(this, msg, format); @@ -1478,8 +1466,9 @@ void SimpleTargetRunner::stop() void SimpleTargetRunner::onProcessStarted() { // Console processes only know their pid after being started - runControl()->setApplicationProcessHandle(m_launcher.applicationPID()); - runControl()->bringApplicationToForeground(); + ProcessHandle pid = m_launcher.applicationPID(); + runControl()->setApplicationProcessHandle(pid); + pid.activate(); reportStarted(); } diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 0b9b3618def..4d49d434ea4 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -435,7 +435,6 @@ public: void setRunnable(const Runnable &runnable); virtual void appendMessage(const QString &msg, Utils::OutputFormat format); - virtual void bringApplicationToForeground(); static bool showPromptToStopDialog(const QString &title, const QString &text, const QString &stopButtonText = QString(), From 6906ee0dbb58f1cef2ea03de6312cff4d3f180d6 Mon Sep 17 00:00:00 2001 From: Robert Loehning Date: Mon, 17 Jul 2017 12:51:55 +0200 Subject: [PATCH 20/35] Squish: Update menu in tst_session_handling Change-Id: Ia9d05a89fe8e7eb6028c9f69e77fa3f7dc001168 Reviewed-by: Christian Stenger --- tests/system/suite_general/tst_session_handling/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/suite_general/tst_session_handling/test.py b/tests/system/suite_general/tst_session_handling/test.py index 19cbfbaa186..03a9114263f 100644 --- a/tests/system/suite_general/tst_session_handling/test.py +++ b/tests/system/suite_general/tst_session_handling/test.py @@ -83,7 +83,7 @@ def prepareTestExamples(): def switchSession(toSession): test.log("Switching to session '%s'" % toSession) - invokeMenuItem("File", "Session Manager...") + invokeMenuItem("File", "Sessions", "Manage...") clickItem(waitForObject("{name='sessionView' type='ProjectExplorer::Internal::SessionView' visible='1' " "window=':Session Manager_ProjectExplorer::Internal::SessionDialog'}"), toSession, 5, 5, 0, Qt.LeftButton) @@ -94,7 +94,7 @@ def createAndSwitchToSession(toSession): sessionInputDialog = ("{type='ProjectExplorer::Internal::SessionNameInputDialog' unnamed='1' " "visible='1' windowTitle='New Session Name'}") test.log("Switching to session '%s' after creating it." % toSession) - invokeMenuItem("File", "Session Manager...") + invokeMenuItem("File", "Sessions", "Manage...") clickButton(waitForObject("{name='btCreateNew' text='New' type='QPushButton' visible='1' " "window=':Session Manager_ProjectExplorer::Internal::SessionDialog'}")) lineEdit = waitForObject("{type='QLineEdit' unnamed='1' visible='1' window=%s}" From eebac87be558c9a269a748c09da75a97de643183 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Mon, 17 Jul 2017 13:36:39 +0300 Subject: [PATCH 21/35] ProjectTree: Enable Synchronize with Editor by default Changed by 4943510b60acc320dff8f2c31af69cfbfa331203. Change-Id: I359c4abd77009b22bc1a7143002563f66a3b5fd0 Reviewed-by: Tobias Hunger --- src/plugins/projectexplorer/projecttreewidget.cpp | 2 +- src/plugins/projectexplorer/projecttreewidget.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/projectexplorer/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp index 372dbdb7576..2a98fbe86e7 100644 --- a/src/plugins/projectexplorer/projecttreewidget.cpp +++ b/src/plugins/projectexplorer/projecttreewidget.cpp @@ -489,5 +489,5 @@ void ProjectTreeWidgetFactory::restoreSettings(QSettings *settings, int position const QString baseKey = QLatin1String("ProjectTreeWidget.") + QString::number(position); ptw->setProjectFilter(settings->value(baseKey + QLatin1String(".ProjectFilter"), false).toBool()); ptw->setGeneratedFilesFilter(settings->value(baseKey + QLatin1String(".GeneratedFilter"), true).toBool()); - ptw->setAutoSynchronization(settings->value(baseKey + QLatin1String(".SyncWithEditor")).toBool()); + ptw->setAutoSynchronization(settings->value(baseKey + QLatin1String(".SyncWithEditor"), true).toBool()); } diff --git a/src/plugins/projectexplorer/projecttreewidget.h b/src/plugins/projectexplorer/projecttreewidget.h index 072cc1f1ab2..69102fedb0d 100644 --- a/src/plugins/projectexplorer/projecttreewidget.h +++ b/src/plugins/projectexplorer/projecttreewidget.h @@ -87,7 +87,7 @@ private: QToolButton *m_toggleSync; QString m_modelId; - bool m_autoSync = false; + bool m_autoSync = true; Utils::FileName m_delayedRename; static QList m_projectTreeWidgets; From a196170df9e1decf9fb5e755b9ae411ae4ef7b9e Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 18 Jul 2017 08:51:26 +0200 Subject: [PATCH 22/35] Debugger: Fix removing items from modules model Change-Id: Icce09b890e9a4a5cca142ee5307fd6f42bd5c839 Reviewed-by: hjk --- src/plugins/debugger/moduleshandler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/debugger/moduleshandler.cpp b/src/plugins/debugger/moduleshandler.cpp index 94d558851af..e37c44ccbba 100644 --- a/src/plugins/debugger/moduleshandler.cpp +++ b/src/plugins/debugger/moduleshandler.cpp @@ -327,7 +327,8 @@ void ModulesHandler::endUpdateAll() if (!item->updated) toDestroy.append(item); }); - qDeleteAll(toDestroy); + for (TreeItem *item : toDestroy) + m_model->destroyItem(item); } } // namespace Internal From 862dd4c6bffc7b9b4b0465f5edb7e673331b54a5 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Wed, 5 Jul 2017 11:09:07 +0200 Subject: [PATCH 23/35] TextEditor: Simplify annotation rectangle computation Change-Id: Ie04f545d24696d66645c367b2c25d643c3691908 Reviewed-by: Nikolai Kosjar --- src/plugins/texteditor/texteditor.cpp | 2 +- src/plugins/texteditor/textmark.cpp | 52 ++++++++++++++++----------- src/plugins/texteditor/textmark.h | 10 +++++- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 4c9711a67ca..7e8c1c2345d 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -3821,7 +3821,7 @@ void TextEditorWidgetPrivate::drawLineAnnotation(QPainter &painter, const QTextB QRectF annotationRect(x, lineRect.top(), q->viewport()->width() - x, lineRect.height()); if (annotationRect.width() <= 0) break; - mark->paintAnnotation(&painter, &annotationRect, q->fontMetrics()); + mark->paintAnnotation(&painter, &annotationRect); x += annotationRect.width() + itemOffset; m_annotationRects[block.blockNumber()].append({annotationRect, mark}); } diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp index 15939a3f44d..254999f1b31 100644 --- a/src/plugins/texteditor/textmark.cpp +++ b/src/plugins/texteditor/textmark.cpp @@ -123,42 +123,52 @@ void TextMark::paintIcon(QPainter *painter, const QRect &rect) const m_icon.paint(painter, rect, Qt::AlignCenter); } -void TextMark::paintAnnotation(QPainter *painter, - QRectF *annotationRect, - const QFontMetrics &fm) const +void TextMark::paintAnnotation(QPainter *painter, QRectF *annotationRect) const { QString text = lineAnnotation(); if (text.isEmpty()) return; - const bool drawIcon = !m_icon.isNull(); - int textWidth = fm.width(text); - constexpr qreal margin = 1; - const qreal iconHeight = annotationRect->height() - 2 * margin; - const qreal iconWidth = iconHeight * m_widthFactor + 2 * margin; - qreal annotationWidth = (drawIcon ? textWidth + iconWidth : textWidth) + margin; - if (annotationRect->left() + annotationWidth > annotationRect->right()) { - textWidth = int(annotationRect->width() - (drawIcon ? iconWidth + margin : margin)); - text = fm.elidedText(text, Qt::ElideRight, textWidth); - annotationWidth = annotationRect->width(); - } + const AnnotationRects &rects = annotationRects(*annotationRect, painter->fontMetrics()); + const QColor markColor = m_hasColor ? Utils::creatorTheme()->color(m_color).toHsl() : painter->pen().color(); const AnnotationColors &colors = AnnotationColors::getAnnotationColors(markColor, painter->background().color()); painter->save(); - annotationRect->setWidth(annotationWidth); painter->setPen(colors.rectColor); painter->setBrush(colors.rectColor); - painter->drawRect(*annotationRect); + painter->drawRect(rects.annotationRect); painter->setPen(colors.textColor); - if (drawIcon) { - paintIcon(painter, annotationRect->adjusted( - margin, margin, -(textWidth + 2 * margin), -margin).toAlignedRect()); - } - painter->drawText(annotationRect->adjusted(iconWidth, 0, 0, 0), Qt::AlignLeft, text); + paintIcon(painter, rects.iconRect.toAlignedRect()); + painter->drawText(rects.textRect, Qt::AlignLeft, rects.text); painter->restore(); + *annotationRect = rects.annotationRect; +} + +TextMark::AnnotationRects TextMark::annotationRects(const QRectF &boundingRect, + const QFontMetrics &fm) const +{ + AnnotationRects rects; + rects.annotationRect = boundingRect; + rects.text = lineAnnotation(); + const bool drawIcon = !m_icon.isNull(); + constexpr qreal margin = 1; + rects.iconRect = QRectF(boundingRect.left() + margin, boundingRect.top() + margin, 0, 0); + if (drawIcon) { + rects.iconRect.setHeight(boundingRect.height() - 2 * margin); + rects.iconRect.setWidth(rects.iconRect.height() * m_widthFactor); + } + rects.textRect = QRectF(rects.iconRect.right() + margin, boundingRect.top(), + qreal(fm.width(rects.text)), boundingRect.height()); + rects.annotationRect.setRight(rects.textRect.right() + margin); + if (rects.annotationRect.right() > boundingRect.right()) { + rects.textRect.setRight(boundingRect.right() - margin); + rects.text = fm.elidedText(rects.text, Qt::ElideRight, int(rects.textRect.width())); + rects.annotationRect.setRight(boundingRect.right()); + } + return rects; } void TextMark::updateLineNumber(int lineNumber) diff --git a/src/plugins/texteditor/textmark.h b/src/plugins/texteditor/textmark.h index 89d3d96e023..ca484a85388 100644 --- a/src/plugins/texteditor/textmark.h +++ b/src/plugins/texteditor/textmark.h @@ -64,7 +64,15 @@ public: int lineNumber() const; virtual void paintIcon(QPainter *painter, const QRect &rect) const; - virtual void paintAnnotation(QPainter *painter, QRectF *annotationRect, const QFontMetrics &fm) const; + virtual void paintAnnotation(QPainter *painter, QRectF *annotationRect) const; + struct AnnotationRects + { + QRectF annotationRect; + QRectF iconRect; + QRectF textRect; + QString text; + }; + virtual AnnotationRects annotationRects(const QRectF &boundingRect, const QFontMetrics &fm) const; /// called if the filename of the document changed virtual void updateFileName(const QString &fileName); virtual void updateLineNumber(int lineNumber); From 3b22cd3e203c3dac2975984bf7ae2a0fa6656bc8 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 17 Jul 2017 09:37:34 +0200 Subject: [PATCH 24/35] Debugger: Describe the "Override server address/channel" field better Change-Id: I2bd112d1d2f46904513fa668a17f0a07ebe26e12 Reviewed-by: Leena Miettinen Reviewed-by: Rainer Keller --- src/plugins/debugger/debuggerdialogs.cpp | 36 +++++++++++++++++------- src/plugins/debugger/debuggerdialogs.h | 1 + 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/plugins/debugger/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index c247c22a43c..f9017a7f41d 100644 --- a/src/plugins/debugger/debuggerdialogs.cpp +++ b/src/plugins/debugger/debuggerdialogs.cpp @@ -71,8 +71,8 @@ class StartApplicationDialogPrivate public: KitChooser *kitChooser; QLabel *serverPortLabel; - QLabel *serverAddressLabel; - QLineEdit *serverAddressEdit; + QLabel *channelOverrideLabel; + QLineEdit *channelOverrideEdit; QSpinBox *serverPortSpinBox; PathChooser *localExecutablePathChooser; FancyLineEdit *arguments; @@ -235,8 +235,11 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent) d->serverPortSpinBox = new QSpinBox(this); d->serverPortSpinBox->setRange(1, 65535); - d->serverAddressLabel = new QLabel(tr("Override server address"), this); - d->serverAddressEdit = new QLineEdit(this); + d->channelOverrideLabel = new QLabel(tr("Override server channel:"), this); + d->channelOverrideEdit = new QLineEdit(this); + //: "For example, /dev/ttyS0, COM1, 127.0.0.1:1234" + d->channelOverrideEdit->setPlaceholderText( + tr("For example, %1").arg("/dev/ttyS0, COM1, 127.0.0.1:1234")); d->localExecutablePathChooser = new PathChooser(this); d->localExecutablePathChooser->setExpectedKind(PathChooser::File); @@ -292,7 +295,6 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent) formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); formLayout->addRow(tr("&Kit:"), d->kitChooser); formLayout->addRow(d->serverPortLabel, d->serverPortSpinBox); - formLayout->addRow(d->serverAddressLabel, d->serverAddressEdit); formLayout->addRow(tr("Local &executable:"), d->localExecutablePathChooser); formLayout->addRow(tr("Command line &arguments:"), d->arguments); formLayout->addRow(tr("&Working directory:"), d->workingDirectory); @@ -300,6 +302,11 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent) formLayout->addRow(tr("Break at \"&main\":"), d->breakAtMainCheckBox); formLayout->addRow(d->serverStartScriptLabel, d->serverStartScriptPathChooser); formLayout->addRow(tr("Debug &information:"), d->debuginfoPathChooser); + formLayout->addRow(new QLabel(tr("Normally, the running server is identified by the IP of the " + "device in the kit and the server port selected above.\n" + "You can choose another communication channel here, such as " + "a serial line or custom ip:port."))); + formLayout->addRow(d->channelOverrideLabel, d->channelOverrideEdit); formLayout->addRow(line2); formLayout->addRow(tr("&Recent:"), d->historyComboBox); @@ -316,6 +323,9 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent) connect(d->historyComboBox, static_cast(&QComboBox::currentIndexChanged), this, &StartApplicationDialog::historyIndexChanged); + connect(d->channelOverrideEdit, &QLineEdit::textChanged, + this, &StartApplicationDialog::onChannelOverrideChanged); + updateState(); } @@ -334,6 +344,12 @@ void StartApplicationDialog::setHistory(const QList } } +void StartApplicationDialog::onChannelOverrideChanged(const QString &channel) +{ + d->serverPortSpinBox->setEnabled(channel.isEmpty()); + d->serverPortLabel->setEnabled(channel.isEmpty()); +} + void StartApplicationDialog::historyIndexChanged(int index) { if (index < 0) @@ -379,8 +395,8 @@ bool StartApplicationDialog::run(QWidget *parent, DebuggerRunParameters *rp, Kit dialog.d->serverStartScriptLabel->setVisible(false); dialog.d->serverPortSpinBox->setVisible(false); dialog.d->serverPortLabel->setVisible(false); - dialog.d->serverAddressLabel->setVisible(false); - dialog.d->serverAddressEdit->setVisible(false); + dialog.d->channelOverrideLabel->setVisible(false); + dialog.d->channelOverrideEdit->setVisible(false); } if (dialog.exec() != QDialog::Accepted) return false; @@ -404,7 +420,7 @@ bool StartApplicationDialog::run(QWidget *parent, DebuggerRunParameters *rp, Kit } rp->inferior.executable = newParameters.runnable.executable; - const QString inputAddress = dialog.d->serverAddressEdit->text(); + const QString inputAddress = dialog.d->channelOverrideEdit->text(); if (!inputAddress.isEmpty()) rp->remoteChannel = inputAddress; else @@ -430,7 +446,7 @@ StartApplicationParameters StartApplicationDialog::parameters() const { StartApplicationParameters result; result.serverPort = d->serverPortSpinBox->value(); - result.serverAddress = d->serverAddressEdit->text(); + result.serverAddress = d->channelOverrideEdit->text(); result.runnable.executable = d->localExecutablePathChooser->path(); result.serverStartScript = d->serverStartScriptPathChooser->path(); result.kitId = d->kitChooser->currentKitId(); @@ -447,7 +463,7 @@ void StartApplicationDialog::setParameters(const StartApplicationParameters &p) { d->kitChooser->setCurrentKitId(p.kitId); d->serverPortSpinBox->setValue(p.serverPort); - d->serverAddressEdit->setText(p.serverAddress); + d->channelOverrideEdit->setText(p.serverAddress); d->localExecutablePathChooser->setPath(p.runnable.executable); d->serverStartScriptPathChooser->setPath(p.serverStartScript); d->debuginfoPathChooser->setPath(p.debugInfoLocation); diff --git a/src/plugins/debugger/debuggerdialogs.h b/src/plugins/debugger/debuggerdialogs.h index 60cdedefeba..b291dbbe26d 100644 --- a/src/plugins/debugger/debuggerdialogs.h +++ b/src/plugins/debugger/debuggerdialogs.h @@ -80,6 +80,7 @@ private: StartApplicationParameters parameters() const; void setParameters(const StartApplicationParameters &p); void setHistory(const QList &l); + void onChannelOverrideChanged(const QString &channel); StartApplicationDialogPrivate *d; }; From 220132e7c58c09e2beac1fbbde40dcc383ef2186 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Thu, 6 Jul 2017 20:09:22 +0200 Subject: [PATCH 25/35] Add changes file for 4.4 Change-Id: I655ce9fc0f82cd6632334d88fcac25aef6e150b8 Reviewed-by: Leena Miettinen Reviewed-by: Orgad Shaneh --- dist/changes-4.4.0.md | 186 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 dist/changes-4.4.0.md diff --git a/dist/changes-4.4.0.md b/dist/changes-4.4.0.md new file mode 100644 index 00000000000..ce33689bc41 --- /dev/null +++ b/dist/changes-4.4.0.md @@ -0,0 +1,186 @@ +Qt Creator version 4.4 contains bug fixes and new features. + +The most important changes are listed in this document. For a complete +list of changes, see the Git log for the Qt Creator sources that +you can check out from the public Git repository. For example: + + git clone git://code.qt.io/qt-creator/qt-creator.git + git log --cherry-pick --pretty=oneline origin/4.3..v4.4.0 + +General + +* Added highlighting of search term in Locator results +* Added larger icons to `New` dialog +* Added locator input to extra editor and help windows (QTCREATORBUG-9696) +* Fixed theming of Debugger Console and TODO pane (QTCREATORBUG-17532) + +Editing + +* Added inline annotations for errors, warnings and bookmarks +* Added optional smooth scrolling when navigating within the same file + (for example with Locator or `Follow Symbol Under Cursor`) +* Added overridable `DeleteStartOfLine` and `DeleteEndOfLine` actions + (QTCREATORBUG-18095) +* Added support for relative path to active project to `Advanced Find` > + `Files in File System` (QTCREATORBUG-18139) +* Added colors to default text editor scheme (the previous default is + available as `Default Classic`) +* FakeVim + * Fixed `gt`/`gT`/`:tabnext`/`:tabprevious` + +All Projects + +* Improved detection of cross-compilers + +CMake Projects + +* Added option to filter for CMake variables in build configuration + (QTCREATORBUG-17973) +* Added warning when detecting `CMakeCache.txt` in source directory even though + build is configured for out-of-source build (QTCREATORBUG-18381) +* CMake >= 3.7 + * Fixed that headers from top level directory were not shown in project tree + (QTCREATORBUG-17760) + * Improved handling of `CMAKE_RUNTIME_OUTPUT_DIRECTORY` (QTCREATORBUG-18158) + +Qbs Projects + +* Re-added `Qbs install` deploy step (QTCREATORBUG-17958) +* Added `rebuild` and `clean` actions to products and subprojects + (QTCREATORBUG-15919) + +C++ Support + +* Added option to rename files when renaming symbol using same name + (QTCREATORBUG-14696) +* Added auto-insertion of matching curly brace (QTCREATORBUG-15073) +* Fixed that C++ and Qt keywords were considered keywords in C files + (QTCREATORBUG-2818, QTCREATORBUG-18004) +* Fixed highlighting of raw string literals (QTCREATORBUG-17720) +* Fixed `Add #include` refactoring action for static functions +* Clang Code Model + * Added highlighting of identifier under cursor, which was still + delegated to built-in code model + * Improved order of items in completion list + (QTCREATORBUG-18319, QTCREATORBUG-15445) + * Fixed function signature hint when completing constructors and functors + (QTCREATORBUG-14882) + * Fixed that completing function pointer was adding parentheses + (QTCREATORBUG-17578) + * Fixed completion inside function template (QTCREATORBUG-17222) + * Fixed wrong column number with non-ASCII characters (QTCREATORBUG-16775) + * Fixed highlighting of primitive types and operators (QTCREATORBUG-17867) + * Fixed highlighting of partial template specializations + * Fixed highlighting of functions in `using` declarations + * Fixed that keywords were highlighted in preprocessor directives + (QTCREATORBUG-15516) +* Built-in Code Model + * Fixed completion of STL containers (QTCREATORBUG-1892) + +QML Support + +* Updated QML parser to newer QML version (QTCREATORBUG-17842) + +Debugging + +* Fixed support for `long double` (QTCREATORBUG-18023) +* CDB + * Added support for extra debugging helpers and debugging helper + customization + * Added warning if run configuration uses unsupported shell command + +Version Control Systems + +* Fixed format of visual whitespace in blame, log and git rebase editors + (QTCREATORBUG-17735) +* Git + * Improved branch listing in `Show` (QTCREATORBUG-16949) +* Gerrit + * Added validation of server certificate when using REST API + * Fixed that non-Gerrit remotes were shown in `Push to Gerrit` dialog + (QTCREATORBUG-16367) +* ClearCase + * Disabled by default + +Diff Viewer + +* Fixed state of actions in `Edit` menu +* Fixed that context information for chunks was not shown in side-by-side view + (QTCREATORBUG-18289) +* Fixed that UI blocked when showing very large diffs + +Test Integration + +* Added view with complete, unprocessed test output +* Made it possible to enable and disable all tests using a specific test + framework +* QTest + * Added option to run verbose and with logging of signals and slots + (`-vb` and `-vs`) + +Beautifier + +* Added option for using a different AStyle configuration file +* Added option for fallback style for `clang-format` + +Platform Specific + +Windows + +* Removed support for Windows CE + +Android + +* Added option to run commands before app starts and after app stopped +* Fixed state of actions in `Edit` menu in text based manifest editor + +iOS + +* Added UI for managing simulator devices (QTCREATORBUG-17602) + +Remote Linux + +* Added support for `ssh-agent` (QTCREATORBUG-16245) + +Credits for these changes go to: +Alessandro Portale +Alexander Drozdov +Andre Hartmann +André Pönitz +Christian Kandeler +Christian Stenger +Daniel Teske +David Schulz +Eike Ziller +Felix Kälberer +Florian Apolloner +Friedemann Kleint +Ivan Donchevskii +Jake Petroules +Jaroslaw Kobus +Jesus Fernandez +Jochen Becher +Jörg Bornemann +Kai Köhne +Leandro T. C. Melo +Leena Miettinen +Lorenz Haas +Marco Benelli +Marco Bubke +Mitch Curtis +Montel Laurent +Nikita Baryshnikov +Nikolai Kosjar +Orgad Shaneh +Przemyslaw Gorszkowski +Robert Löhning +Serhii Moroz +Tasuku Suzuki +Thiago Macieira +Thomas Hartmann +Tim Jenssen +Tobias Hunger +Tomasz Olszak +Tor Arne Vestbø +Ulf Hermann +Vikas Pachdha From ba7f7bcf0f8a89d0f1ca9cf8a619b9cb5f2c7918 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 13 Jul 2017 16:57:04 +0200 Subject: [PATCH 26/35] ClangStaticAnalyzer: Remove a few + QLatinChar('\n') It's implicit in appendMessage nowadays. Change-Id: I4f1bdde4d4127579d4b26cd275def59c65f18f2f Reviewed-by: Nikolai Kosjar --- .../clangstaticanalyzerruncontrol.cpp | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index ff078f612e6..33b7f4f8073 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -502,8 +502,8 @@ void ClangStaticAnalyzerToolRunner::start() QTC_ASSERT(m_projectInfo.isValid(), reportFailure(); return); const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath(); - appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput()) - + QLatin1Char('\n'), Utils::NormalMessageFormat); + appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput()), + Utils::NormalMessageFormat); // Check clang executable bool isValidClangExecutable; @@ -512,7 +512,7 @@ void ClangStaticAnalyzerToolRunner::start() if (!isValidClangExecutable) { const QString errorMessage = tr("Clang Static Analyzer: Invalid executable \"%1\", stop.") .arg(executable); - appendMessage(errorMessage + QLatin1Char('\n'), Utils::ErrorMessageFormat); + appendMessage(errorMessage, Utils::ErrorMessageFormat); TaskHub::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); reportFailure(); @@ -527,7 +527,7 @@ void ClangStaticAnalyzerToolRunner::start() = tr("Clang Static Analyzer: Running with possibly unsupported version, " "could not determine version from executable \"%1\".") .arg(versionCheckExecutable); - appendMessage(warningMessage + QLatin1Char('\n'), Utils::StdErrFormat); + appendMessage(warningMessage, Utils::StdErrFormat); TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); } else if (!version.isSupportedVersion()) { @@ -536,7 +536,7 @@ void ClangStaticAnalyzerToolRunner::start() "supported version is %2.") .arg(version.toString()) .arg(ClangExecutableVersion::supportedVersionAsString()); - appendMessage(warningMessage + QLatin1Char('\n'), Utils::StdErrFormat); + appendMessage(warningMessage, Utils::StdErrFormat); TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); } @@ -549,7 +549,7 @@ void ClangStaticAnalyzerToolRunner::start() if (!temporaryDir.isValid()) { const QString errorMessage = tr("Clang Static Analyzer: Failed to create temporary dir, stop."); - appendMessage(errorMessage + QLatin1Char('\n'), Utils::ErrorMessageFormat); + appendMessage(errorMessage, Utils::ErrorMessageFormat); TaskHub::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::requestPopup(); reportFailure(errorMessage); @@ -604,7 +604,7 @@ void ClangStaticAnalyzerToolRunner::stop() } m_runners.clear(); m_unitsToProcess.clear(); - appendMessage(tr("Clang Static Analyzer stopped by user.") + QLatin1Char('\n'), + appendMessage(tr("Clang Static Analyzer stopped by user."), Utils::NormalMessageFormat); m_progress.reportFinished(); ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success); @@ -630,7 +630,7 @@ void ClangStaticAnalyzerToolRunner::analyzeNextFile() QTC_ASSERT(runner->run(unit.file, unit.arguments), return); appendMessage(tr("Analyzing \"%1\".").arg( - Utils::FileName::fromString(unit.file).toUserOutput()) + QLatin1Char('\n'), + Utils::FileName::fromString(unit.file).toUserOutput()), Utils::StdOutFormat); } @@ -659,9 +659,8 @@ void ClangStaticAnalyzerToolRunner::onRunnerFinishedWithSuccess(const QString &l if (!errorMessage.isEmpty()) { qCDebug(LOG) << "onRunnerFinishedWithSuccess: Error reading log file:" << errorMessage; const QString filePath = qobject_cast(sender())->filePath(); - appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage) - + QLatin1Char('\n') - , Utils::StdErrFormat); + appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage), + Utils::StdErrFormat); } else { ++m_filesAnalyzed; if (!diagnostics.isEmpty()) @@ -680,9 +679,8 @@ void ClangStaticAnalyzerToolRunner::onRunnerFinishedWithFailure(const QString &e ++m_filesNotAnalyzed; m_success = false; const QString filePath = qobject_cast(sender())->filePath(); - appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage) - + QLatin1Char('\n') - , Utils::StdErrFormat); + appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage), + Utils::StdErrFormat); appendMessage(errorDetails, Utils::StdErrFormat); TaskHub::addTask(Task::Warning, errorMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::addTask(Task::Warning, errorDetails, Debugger::Constants::ANALYZERTASK_ID); @@ -712,9 +710,7 @@ void ClangStaticAnalyzerToolRunner::finalize() { appendMessage(tr("Clang Static Analyzer finished: " "Processed %1 files successfully, %2 failed.") - .arg(m_filesAnalyzed) - .arg(m_filesNotAnalyzed) - + QLatin1Char('\n'), + .arg(m_filesAnalyzed).arg(m_filesNotAnalyzed), Utils::NormalMessageFormat); if (m_filesNotAnalyzed != 0) { From c5cc3e25947a1e215627142b9947f83bad948869 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 4 Jul 2017 13:24:38 +0200 Subject: [PATCH 27/35] ClangStaticAnalyzer: Don't get stuck if project is not buildable Task-number: QTCREATORBUG-18495 Change-Id: I6621ceebd05be2fabcdcd3061e41e4674e5fbb26 Reviewed-by: Nikolai Kosjar --- .../clangstaticanalyzerruncontrol.cpp | 1 + .../clangstaticanalyzertool.cpp | 19 ++++++++++++------- .../clangstaticanalyzertool.h | 3 ++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 33b7f4f8073..98a0788ebcd 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -81,6 +81,7 @@ ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runCont auto tool = ClangStaticAnalyzerTool::instance(); tool->stopAction()->disconnect(); connect(tool->stopAction(), &QAction::triggered, runControl, &RunControl::initiateStop); + tool->handleWorkerStart(this); ProjectInfo projectInfoBeforeBuild = tool->projectInfoBeforeBuild(); QTC_ASSERT(projectInfoBeforeBuild.isValid(), return); diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp index c8f1f6c8ba2..461f31049b4 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp @@ -145,7 +145,6 @@ ClangStaticAnalyzerTool::ClangStaticAnalyzerTool() {{ClangStaticAnalyzerDockId, m_diagnosticView, {}, Perspective::SplitVertical}} )); - //Debugger::registerAction(Constants::CLANGSTATICANALYZER_RUN_MODE, {}); action = new QAction(tr("Clang Static Analyzer"), this); action->setToolTip(toolTip); menu->addAction(ActionManager::registerAction(action, "ClangStaticAnalyzer.Action"), @@ -211,14 +210,12 @@ static bool dontStartAfterHintForDebugMode(Project *project) return false; } -void ClangStaticAnalyzerTool::startTool() +void ClangStaticAnalyzerTool::handleWorkerStart(RunWorker *runWorker) { - Project *project = SessionManager::startupProject(); + RunControl *runControl = runWorker->runControl(); + Project *project = runControl->project(); QTC_ASSERT(project, emit finished(false); return); - if (dontStartAfterHintForDebugMode(project)) - return; - Debugger::selectPerspective(ClangStaticAnalyzerPerspectiveId); m_diagnosticModel->clear(); setBusyCursor(true); @@ -230,8 +227,13 @@ void ClangStaticAnalyzerTool::startTool() m_toolBusy = true; updateRunActions(); +} - Target * const target = project->activeTarget(); +void ClangStaticAnalyzerTool::startTool() +{ + Project *project = SessionManager::startupProject(); + QTC_ASSERT(project, return); + Target *target = project->activeTarget(); QTC_ASSERT(target, return); DummyRunConfiguration *& rc = m_runConfigs[target]; if (!rc) { @@ -245,6 +247,9 @@ void ClangStaticAnalyzerTool::startTool() connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, this, onProjectRemoved, Qt::UniqueConnection); } + if (dontStartAfterHintForDebugMode(project)) + return; + ProjectExplorerPlugin::runRunConfiguration(rc, Constants::CLANGSTATICANALYZER_RUN_MODE); } diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h index b3f05843d69..06550bce315 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h @@ -58,9 +58,10 @@ public: // For testing. QList diagnostics() const; - void startTool(); + void handleWorkerStart(ProjectExplorer::RunWorker *runWorker); + void onEngineIsStarting(); void onNewDiagnosticsAvailable(const QList &diagnostics); void onEngineFinished(bool success); From dbb67fd5c3219e6d2c92df67d57d3d376bc5f7c1 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Mon, 17 Jul 2017 12:29:38 +0200 Subject: [PATCH 28/35] Wizards: remove empty line and replace tabs with spaces Change-Id: I5decd680f92ee78a036be894aee42226b73dd053 Reviewed-by: Christian Stenger --- src/plugins/coreplugin/dialogs/newdialog.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/coreplugin/dialogs/newdialog.cpp b/src/plugins/coreplugin/dialogs/newdialog.cpp index f38a43e73b2..45fe813a979 100644 --- a/src/plugins/coreplugin/dialogs/newdialog.cpp +++ b/src/plugins/coreplugin/dialogs/newdialog.cpp @@ -125,14 +125,14 @@ public: return sourceModel()->columnCount(mapToSource(index)); } - QModelIndex mapFromSource (const QModelIndex &index) const + QModelIndex mapFromSource (const QModelIndex &index) const { if (!index.isValid()) return QModelIndex(); return createIndex(index.row(), index.column(), index.internalPointer()); } - QModelIndex mapToSource (const QModelIndex &index) const + QModelIndex mapToSource (const QModelIndex &index) const { if (!index.isValid()) return QModelIndex(); @@ -172,7 +172,6 @@ public: { QSize size = QItemDelegate::sizeHint(option, index); - size = size.expandedTo(QSize(0, ROW_HEIGHT)); return size; From ca49ff1f876911a3aa44590e6eccbcdbc71a6c83 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Mon, 17 Jul 2017 12:34:41 +0200 Subject: [PATCH 29/35] Wizards: sprinkle some overrides Change-Id: I52bd759f9c91f36192b147a1e6579be2b4b54a82 Reviewed-by: Christian Stenger --- src/plugins/coreplugin/dialogs/newdialog.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plugins/coreplugin/dialogs/newdialog.cpp b/src/plugins/coreplugin/dialogs/newdialog.cpp index 45fe813a979..cdfff0d9892 100644 --- a/src/plugins/coreplugin/dialogs/newdialog.cpp +++ b/src/plugins/coreplugin/dialogs/newdialog.cpp @@ -79,7 +79,7 @@ public: invalidateFilter(); } - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override { if (!sourceParent.isValid()) return true; @@ -101,18 +101,18 @@ class TwoLevelProxyModel : public QAbstractProxyModel public: TwoLevelProxyModel(QObject *parent = 0): QAbstractProxyModel(parent) {} - QModelIndex index(int row, int column, const QModelIndex &parent) const + QModelIndex index(int row, int column, const QModelIndex &parent) const override { QModelIndex ourModelIndex = sourceModel()->index(row, column, mapToSource(parent)); return createIndex(row, column, ourModelIndex.internalPointer()); } - QModelIndex parent(const QModelIndex &index) const + QModelIndex parent(const QModelIndex &index) const override { return mapFromSource(mapToSource(index).parent()); } - int rowCount(const QModelIndex &index) const + int rowCount(const QModelIndex &index) const override { if (index.isValid() && index.parent().isValid() && !index.parent().parent().isValid()) return 0; @@ -120,19 +120,19 @@ public: return sourceModel()->rowCount(mapToSource(index)); } - int columnCount(const QModelIndex &index) const + int columnCount(const QModelIndex &index) const override { return sourceModel()->columnCount(mapToSource(index)); } - QModelIndex mapFromSource (const QModelIndex &index) const + QModelIndex mapFromSource (const QModelIndex &index) const override { if (!index.isValid()) return QModelIndex(); return createIndex(index.row(), index.column(), index.internalPointer()); } - QModelIndex mapToSource (const QModelIndex &index) const + QModelIndex mapToSource (const QModelIndex &index) const override { if (!index.isValid()) return QModelIndex(); @@ -148,7 +148,7 @@ public: FancyTopLevelDelegate(QObject *parent = 0) : QItemDelegate(parent) {} - void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const + void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const override { QStyleOptionViewItem newoption = option; if (!(option.state & QStyle::State_Enabled)) { @@ -168,7 +168,7 @@ public: QItemDelegate::drawDisplay(painter, newoption, rect, text); } - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override { QSize size = QItemDelegate::sizeHint(option, index); From c77e76dd6d288b0341ad00da8245b53b46408362 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Mon, 17 Jul 2017 18:52:02 +0200 Subject: [PATCH 30/35] Nim: Update the Nim wizard icon The icon should have the same size and look as the other icons. Task-number: QTCREATORBUG-18550 Change-Id: I16ee48196a14878858f02cabe0678342b4abb44f Reviewed-by: Filippo Cucchetto Reviewed-by: Christian Stenger --- .../templates/wizards/files/nim/icon.png | Bin 1511 -> 0 bytes .../templates/wizards/files/nim/wizard.json | 2 +- .../wizards/files/nimscript/icon.png | Bin 1511 -> 0 bytes .../wizards/files/nimscript/wizard.json | 2 +- .../templates/wizards/projects/nim/icon.png | Bin 1511 -> 1819 bytes .../wizards/projects/nim/icon@2x.png | Bin 0 -> 3658 bytes src/tools/icons/qtcreatoricons.svg | 22 ++++++++++++++++++ 7 files changed, 24 insertions(+), 2 deletions(-) delete mode 100644 share/qtcreator/templates/wizards/files/nim/icon.png delete mode 100644 share/qtcreator/templates/wizards/files/nimscript/icon.png create mode 100644 share/qtcreator/templates/wizards/projects/nim/icon@2x.png diff --git a/share/qtcreator/templates/wizards/files/nim/icon.png b/share/qtcreator/templates/wizards/files/nim/icon.png deleted file mode 100644 index a08e474e6dc4be7e2434851c152d742af3e74716..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1511 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJo*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xP1>rMq>17#JAXOFVsD+3&N8^Ghqm&d~H{U|=orba4#vIKFghc23Mu z$+r2H>H7EHtlN9e%FNGc7I)ul({06uBJ7V^x;t|N6DMbMvoNr~P_-W2Z>4 z!=6hM)6UJTy!SJ0-_O2^mq+g_@v>@631aDI4PanmNpt38bW)bF@^(zroB zPQ;1PN%71~jimuX3_6!4{9txJ%da+Zr{9l9;tW5y>Rr5Ftod2>O^~aJ(LR(voIx$7 za5a;o{h}2Q^p*s5%vOufS($FPR&!7L+Nq%&EKIGgnk^>JxqKU0mNH(t)9Y}ce_6w` zX;p`GznW~nQm?ybL4~sA>8_05=S5o#oO#*)ZeFlh<8aHlgUyWgGr9xLte0n=zhUX7 zSsODwGhCj%z5nxtne(cduhiqMH!Qt#TbQffuP{+lwfwHVwDkfJk50)xr!(#Mw*D^v z^J=;1arU;wy$9>R?%DXPZ%uoV_)hbjozc}{UWqloDzomt$S}Eb)3WBpL0|3q`Aof;ojuq*#hQow?4||v9tJcK0ahx-+ryB2UCo+pOyIRx|E}tc=b@jxgH&bLf`Po zm$}vM_6bfmc~ev3^Y`Tcdkgo75RQ`)&g-N<7FIqpmBrdZ@`Ugh%mXWLzNemNHoUT%l5 zb6UriuUQkZ>A};I=>5mj-ncKl$NoFZK+Vyg{VwaRHH{((DhGEkMFbfCK5>D^|7P3# zH(e@4>aWg6mV0YnEKQW^;Vb`C<}2MlUH^4~D&G`|YYelLZ?`0=&-9t?u`I{gxXqM} zqdP4&WBZLwxnb?Xw!FUQk9o))^T<51Z2mi0Njdk+EL@pV3?*~_DQ|QM^LhmNyr%=jg!31UuVlD7wA~Niry%hyDPfSx988(r`yfm{mky3o2xxJ!)Kwo z-u1ih&fa;m#j^iv{I*NKmTrF)GPnJ0fBL+WQ7^QP7RraOi<8}Q`|P5HQ=H}-OT5Wl z`r+NC)32}P{khq6hW$#qulBpj#PfdJrmlbfceD6f`}&mRqw{3@|0c$6eE%;)<&lTl zGASb?ogN|4g&BX1?UVeI1ZTack?8mOGKj-cH zw{WBI*7QBji<8%UUR$^M#Pt719^H{KKj84+Va>{gE7!daN}qat_lK2dpYs3FE&rH% zE+F~ED`Wq6Cyc`NIpeeby^^&MvbdQd(H7*ja^uI2SMOfWpEu8M#s8~Uu1tCL`lYvv zlHk%QK`TSNuF9Dlfc zzV_y&r>EU|{!3U`_{+C1d(tkJI^{lm{dmjHV^5!L&TzVL(e}sdZ|B}|+z*s}E1TTB z_iz5oUu%yZEGk}ZUek8{aC*c>i{I1dm0aI)_hn~n+r(MACFUmj z4|e?b$f%4!W@)Z<;g5)lzS|cld!68@=}Swqv{WO1G75Ezj}tQRiU!YqG7*H2a8o zYy7^gv*w-S4#}^V+I~A!C*a-6iamOAy^p@jFWr=+%~;>S{Z_XoU3X`#>HYA}ZUwg| z*_h?l2`H+Hbsu{ftUlwf_ochHKmO&Jx1x@3rkCPUMvXPI4&+_Dkj8#}o|R{K{B`rD g&(oeNwmjNzTix}zb-QR00|Nttr>mdKI;Vst01|cVdjJ3c diff --git a/share/qtcreator/templates/wizards/files/nim/wizard.json b/share/qtcreator/templates/wizards/files/nim/wizard.json index 7d20f7ebbd7..953df6a847a 100644 --- a/share/qtcreator/templates/wizards/files/nim/wizard.json +++ b/share/qtcreator/templates/wizards/files/nim/wizard.json @@ -6,7 +6,7 @@ "trDescription": "Creates an empty Nim file using UTF-8 charset.", "trDisplayName": "Nim File", "trDisplayCategory": "Nim", - "icon": "icon.png", + "icon": "../../projects/nim/icon.png", "enabled": "%{JS: [ %{Plugins} ].indexOf('Nim') >= 0}", "pages" : diff --git a/share/qtcreator/templates/wizards/files/nimscript/icon.png b/share/qtcreator/templates/wizards/files/nimscript/icon.png deleted file mode 100644 index a08e474e6dc4be7e2434851c152d742af3e74716..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1511 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJo*pj^6T^Rm@;DWu&Co?cG za29w(7Bet#3xP1>rMq>17#JAXOFVsD+3&N8^Ghqm&d~H{U|=orba4#vIKFghc23Mu z$+r2H>H7EHtlN9e%FNGc7I)ul({06uBJ7V^x;t|N6DMbMvoNr~P_-W2Z>4 z!=6hM)6UJTy!SJ0-_O2^mq+g_@v>@631aDI4PanmNpt38bW)bF@^(zroB zPQ;1PN%71~jimuX3_6!4{9txJ%da+Zr{9l9;tW5y>Rr5Ftod2>O^~aJ(LR(voIx$7 za5a;o{h}2Q^p*s5%vOufS($FPR&!7L+Nq%&EKIGgnk^>JxqKU0mNH(t)9Y}ce_6w` zX;p`GznW~nQm?ybL4~sA>8_05=S5o#oO#*)ZeFlh<8aHlgUyWgGr9xLte0n=zhUX7 zSsODwGhCj%z5nxtne(cduhiqMH!Qt#TbQffuP{+lwfwHVwDkfJk50)xr!(#Mw*D^v z^J=;1arU;wy$9>R?%DXPZ%uoV_)hbjozc}{UWqloDzomt$S}Eb)3WBpL0|3q`Aof;ojuq*#hQow?4||v9tJcK0ahx-+ryB2UCo+pOyIRx|E}tc=b@jxgH&bLf`Po zm$}vM_6bfmc~ev3^Y`Tcdkgo75RQ`)&g-N<7FIqpmBrdZ@`Ugh%mXWLzNemNHoUT%l5 zb6UriuUQkZ>A};I=>5mj-ncKl$NoFZK+Vyg{VwaRHH{((DhGEkMFbfCK5>D^|7P3# zH(e@4>aWg6mV0YnEKQW^;Vb`C<}2MlUH^4~D&G`|YYelLZ?`0=&-9t?u`I{gxXqM} zqdP4&WBZLwxnb?Xw!FUQk9o))^T<51Z2mi0Njdk+EL@pV3?*~_DQ|QM^LhmNyr%=jg!31UuVlD7wA~Niry%hyDPfSx988(r`yfm{mky3o2xxJ!)Kwo z-u1ih&fa;m#j^iv{I*NKmTrF)GPnJ0fBL+WQ7^QP7RraOi<8}Q`|P5HQ=H}-OT5Wl z`r+NC)32}P{khq6hW$#qulBpj#PfdJrmlbfceD6f`}&mRqw{3@|0c$6eE%;)<&lTl zGASb?ogN|4g&BX1?UVeI1ZTack?8mOGKj-cH zw{WBI*7QBji<8%UUR$^M#Pt719^H{KKj84+Va>{gE7!daN}qat_lK2dpYs3FE&rH% zE+F~ED`Wq6Cyc`NIpeeby^^&MvbdQd(H7*ja^uI2SMOfWpEu8M#s8~Uu1tCL`lYvv zlHk%QK`TSNuF9Dlfc zzV_y&r>EU|{!3U`_{+C1d(tkJI^{lm{dmjHV^5!L&TzVL(e}sdZ|B}|+z*s}E1TTB z_iz5oUu%yZEGk}ZUek8{aC*c>i{I1dm0aI)_hn~n+r(MACFUmj z4|e?b$f%4!W@)Z<;g5)lzS|cld!68@=}Swqv{WO1G75Ezj}tQRiU!YqG7*H2a8o zYy7^gv*w-S4#}^V+I~A!C*a-6iamOAy^p@jFWr=+%~;>S{Z_XoU3X`#>HYA}ZUwg| z*_h?l2`H+Hbsu{ftUlwf_ochHKmO&Jx1x@3rkCPUMvXPI4&+_Dkj8#}o|R{K{B`rD g&(oeNwmjNzTix}zb-QR00|Nttr>mdKI;Vst01|cVdjJ3c diff --git a/share/qtcreator/templates/wizards/files/nimscript/wizard.json b/share/qtcreator/templates/wizards/files/nimscript/wizard.json index 1b0233f7540..62aba314cd1 100644 --- a/share/qtcreator/templates/wizards/files/nimscript/wizard.json +++ b/share/qtcreator/templates/wizards/files/nimscript/wizard.json @@ -6,7 +6,7 @@ "trDescription": "Creates an empty Nim script file using UTF-8 charset.", "trDisplayName": "Nim Script File", "trDisplayCategory": "Nim", - "icon": "icon.png", + "icon": "../../projects/nim/icon.png", "enabled": "%{JS: [ %{Plugins} ].indexOf('Nim') >= 0}", "pages" : diff --git a/share/qtcreator/templates/wizards/projects/nim/icon.png b/share/qtcreator/templates/wizards/projects/nim/icon.png index a08e474e6dc4be7e2434851c152d742af3e74716..4d285bbfbb53f497db20f3e97a777b818f4d77dd 100644 GIT binary patch literal 1819 zcmeAS@N?(olHy`uVBq!ia0y~yV2EL0U~u7JV_;z5$qHJ>z`*v%)5S5Q;?~>f>>lAz z5k3B=iW(hKg3R_cM;6qdVJo?%JNMnXJuEESwtIUh9C`7m+5JjNr{VI>9AKEKGP?CGf@WVK{d28sft9t(P5oq~$Yl5u2@T4ckb5Fdxu=z*5Xw;1xyS@g* z2X@tR+&NQpQMao|!_y-|V9|HcEtQIuHrFiIJC(J^wd~bwy&=F-X>sl6Qs&J|7tNXD zulOWILuPKt;^$>=Zktc&QgmITa&&pnlEk&FTnk^GeCP9vsj6+>Qqv6GsL#jplS_mW z_vGzmGQSXUNOfmm>x8nv9^Lip{l6@FZ({aNmMKZCE3r~?&TqX)4q>a8oJZMmCi-sj zmEhn`4BAjyyX>M;tV>Cb+VhF+u7Aq+_dQ8l{d;o6rMmW-jZRiSZ?dFhE&0e+T&^a# z^Nd}J`hAZdDOQWh-~HJuA9p_L$qDW?$3#>g<*K zTI{n6asthjepQJ+F1^l|Qtf@K<~cH+;o zN|t4!RSdg$`SKcqvjdI80$LV&tl#skyi)l?ZTI^(I$64m?owjMeoSVYc$*_SpZU*a zg|ZM8p`EJXYj&4!zvFe3_iL)&wW!|SPANx=!X=Uqn+iUd&Fy+@xr$q1xs^$4oLak`Jyvn3Y;L$=UYO$0WsX znbRDicxPI_FuUCU^YWeft9lFUFY=z4rptRijq#Dr*9&^x+{ZTE%UL%6NN1ixR#q6# zogY8V-HjPCj%$CLa$3#lsDbcJ=~w&htm^CDuHDtNqAu}co2`?HY{&OlGhvsX?pgb| z7G^x!S?PW4HQ#~P^DWoqU7eMjwN}3B_U*TB6~V!m6MlTlU$wt9f9=oH(T2ry7zMJb zr}fXTO{qRSZ_3NaoSmnaG5x>y;?3*6wtz)RkJcRS*%;Tx@ZrP3^0-x%f8S4#@Xh)4 z>i3cC()V-cTkkhZ2tTx1Trc&B@=q_j$?uOeCNk_WGQ0Jde_P^o;k=Q!yJq2%CBM{c-%k70G&%7#!xxU{ z{AZ52@A|9K`~2s<4V%|?&)=|qdF)q>?;BIK92}|&TJ>ChM{=5dSsqd?bH1!Nl`)nt za?bpBjH}Y;_D*VSP*c+FPpvN4$8h-b{#4(R@JIg(en*zt8|x&0g;~GQ{B$uy*t8)kC;X7@ zz5}b5NhfLrzDs7$_4vVf+4cK>_rI$G87gkNrNlc56zUmsGuY+Nb~?%aEb394%G(#$ zyee;>pBD8hic5HVtCifHgA- z?xbGg-PMYzQ*Mv)F29~@cO}tc_B%HF?F*PW%#xHjL>9IO-8ysaNxD*P`)Aha t7mWLRSJoUzyddZrMq>17#JAXOFVsD+3&N8^Ghqm&d~H{U|=orba4#vIKFghc23Mu z$+r2H>H7EHtlN9e%FNGc7I)ul({06uBJ7V^x;t|N6DMbMvoNr~P_-W2Z>4 z!=6hM)6UJTy!SJ0-_O2^mq+g_@v>@631aDI4PanmNpt38bW)bF@^(zroB zPQ;1PN%71~jimuX3_6!4{9txJ%da+Zr{9l9;tW5y>Rr5Ftod2>O^~aJ(LR(voIx$7 za5a;o{h}2Q^p*s5%vOufS($FPR&!7L+Nq%&EKIGgnk^>JxqKU0mNH(t)9Y}ce_6w` zX;p`GznW~nQm?ybL4~sA>8_05=S5o#oO#*)ZeFlh<8aHlgUyWgGr9xLte0n=zhUX7 zSsODwGhCj%z5nxtne(cduhiqMH!Qt#TbQffuP{+lwfwHVwDkfJk50)xr!(#Mw*D^v z^J=;1arU;wy$9>R?%DXPZ%uoV_)hbjozc}{UWqloDzomt$S}Eb)3WBpL0|3q`Aof;ojuq*#hQow?4||v9tJcK0ahx-+ryB2UCo+pOyIRx|E}tc=b@jxgH&bLf`Po zm$}vM_6bfmc~ev3^Y`Tcdkgo75RQ`)&g-N<7FIqpmBrdZ@`Ugh%mXWLzNemNHoUT%l5 zb6UriuUQkZ>A};I=>5mj-ncKl$NoFZK+Vyg{VwaRHH{((DhGEkMFbfCK5>D^|7P3# zH(e@4>aWg6mV0YnEKQW^;Vb`C<}2MlUH^4~D&G`|YYelLZ?`0=&-9t?u`I{gxXqM} zqdP4&WBZLwxnb?Xw!FUQk9o))^T<51Z2mi0Njdk+EL@pV3?*~_DQ|QM^LhmNyr%=jg!31UuVlD7wA~Niry%hyDPfSx988(r`yfm{mky3o2xxJ!)Kwo z-u1ih&fa;m#j^iv{I*NKmTrF)GPnJ0fBL+WQ7^QP7RraOi<8}Q`|P5HQ=H}-OT5Wl z`r+NC)32}P{khq6hW$#qulBpj#PfdJrmlbfceD6f`}&mRqw{3@|0c$6eE%;)<&lTl zGASb?ogN|4g&BX1?UVeI1ZTack?8mOGKj-cH zw{WBI*7QBji<8%UUR$^M#Pt719^H{KKj84+Va>{gE7!daN}qat_lK2dpYs3FE&rH% zE+F~ED`Wq6Cyc`NIpeeby^^&MvbdQd(H7*ja^uI2SMOfWpEu8M#s8~Uu1tCL`lYvv zlHk%QK`TSNuF9Dlfc zzV_y&r>EU|{!3U`_{+C1d(tkJI^{lm{dmjHV^5!L&TzVL(e}sdZ|B}|+z*s}E1TTB z_iz5oUu%yZEGk}ZUek8{aC*c>i{I1dm0aI)_hn~n+r(MACFUmj z4|e?b$f%4!W@)Z<;g5)lzS|cld!68@=}Swqv{WO1G75Ezj}tQRiU!YqG7*H2a8o zYy7^gv*w-S4#}^V+I~A!C*a-6iamOAy^p@jFWr=+%~;>S{Z_XoU3X`#>HYA}ZUwg| z*_h?l2`H+Hbsu{ftUlwf_ochHKmO&Jx1x@3rkCPUMvXPI4&+_Dkj8#}o|R{K{B`rD g&(oeNwmjNzTix}zb-QR00|Nttr>mdKI;Vst01|cVdjJ3c diff --git a/share/qtcreator/templates/wizards/projects/nim/icon@2x.png b/share/qtcreator/templates/wizards/projects/nim/icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c1217306a1b8fd65f07d2e0be417489661675dc3 GIT binary patch literal 3658 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 literal 0 HcmV?d00001 diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index e24903e09e6..0534a08b94a 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -1670,6 +1670,28 @@ inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccccccc" /> + + + + + From 3be1af37e6ce4a67e2e0ade7ec67cbba25008283 Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Fri, 14 Jul 2017 13:20:15 +0200 Subject: [PATCH 31/35] Wizards: Use the new icons for the Qt Quick Application Wizard Task-number: QTCREATORBUG-18550 Change-Id: Ic91979393a8e2ea54a0d0ab10135028b42efba97 Reviewed-by: Alessandro Portale --- .../projects/qtquickapplication/qml_wizard.png | Bin 586 -> 0 bytes .../projects/qtquickapplication/wizard.json | 2 +- .../qtquickcontrols2application/wizard.json | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 share/qtcreator/templates/wizards/projects/qtquickapplication/qml_wizard.png diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/qml_wizard.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/qml_wizard.png deleted file mode 100644 index 23c023687188b55833eabab4f79ecefeb49e2f95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 586 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rag4rT@hhR<1ZI2jliWdnRdTp1V`{{R2)>+9P< z15jIAo1dSL%itR~ZuIu{ZriqP>C&b5@893Lb?c^0n=W6zeD2)2OP4MkKYskeg$uWC z-P*f%@9y2ZA3b`sapT4_XU;STU z`}XbEu3c+yZ(p%u#k_g*HgDd1_Uzf6J9kc=Jo)h9!#zDc6DCYpym;}FB}*18STJkW zthH;`?%%(E)v8sMm6bPd-aLQ){F*gu9z1w(=gyrYM~;XpYWp!TFld$p`2{mDFdWvs z^zcTGM9Vjx$+y)#IE9unSBJkkf5y1?kB#WhqsNlX+Mhi4-p*s|X~@99u-VhaF{C1H z?S-T34kZY*J#^~cy<2|u?#J)+j=%qJm0h8*qCDqzV2Lqf9EEXP4*iWShOA4e{^x<;d8xa z$^ZZHb7|kVlv=&o=Dx#C+xAaCdM9hf#wSKQ-dLHk*fW)9`^22SjIGwOo{J7P9=(*| zlQ3EHElc@yd+n>YPQU)eo5HfQ=ILMNO)HFFUKfwPW<5=ifq{X+)78&qol`;+0C!q4 ALI3~& diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json index 94b40dec18b..5f8be506997 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json @@ -6,7 +6,7 @@ "trDescription": "Creates a deployable Qt Quick 2 application.", "trDisplayName": "Qt Quick Application", "trDisplayCategory": "Application", - "icon": "qml_wizard.png", + "icon": "icon-empty.png", "featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.3" ], "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}", diff --git a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/wizard.json index 4593ef8dbb0..6b694b4a495 100644 --- a/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/wizard.json +++ b/share/qtcreator/templates/wizards/projects/qtquickcontrols2application/wizard.json @@ -6,7 +6,7 @@ "trDescription": "Creates a deployable Qt Quick 2 application using Qt Quick Controls 2.

Note: Qt Quick Controls 2 are available with Qt 5.7 and later.", "trDisplayName": "Qt Quick Controls 2 Application", "trDisplayCategory": "Application", - "icon": "../qtquickapplication/qml_wizard.png", + "icon": "../qtquickapplication/icon-swipe.png", "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.2" ], "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}", From 1646510ffadd8d8990fa67d1b377a881e0e58ab7 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Mon, 17 Jul 2017 12:30:15 +0200 Subject: [PATCH 32/35] Wizards: scale smaller icons if necessary Change-Id: I26b51668b1f2d1be1b96e43bbc42f49d39249e83 Reviewed-by: hjk --- src/plugins/coreplugin/dialogs/newdialog.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/plugins/coreplugin/dialogs/newdialog.cpp b/src/plugins/coreplugin/dialogs/newdialog.cpp index cdfff0d9892..80f8eb8d4d2 100644 --- a/src/plugins/coreplugin/dialogs/newdialog.cpp +++ b/src/plugins/coreplugin/dialogs/newdialog.cpp @@ -91,6 +91,21 @@ public: return true; } + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override + { + if (role == Qt::DecorationRole) { + // scale too small icons to have one size for all + QIcon icon = qvariant_cast(QSortFilterProxyModel::data(index, role)); + if (!icon.isNull()) { + QPixmap pixmap(icon.pixmap(ICON_SIZE, ICON_SIZE)); + if (pixmap.size() != QSize(ICON_SIZE, ICON_SIZE)) + return pixmap.scaled(ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + } + + return QSortFilterProxyModel::data(index, role); + } + private: Core::Id m_platform; }; From b3f13f9620af33bdd4c57f4201e109f923170d2c Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 18 Jul 2017 10:39:03 +0200 Subject: [PATCH 33/35] ProjectExplorer: Move RunWorker priority handling to worker selection This fixes the temporary regression introduced by 5a848aa1. After having RunWorker registration in RunControl and RunConfigurationAspect registration in RunConfiguration, this was effectively the only remaining code in IRunControlFactory, so this can go now. Change-Id: I38b51bb00058b90d30f0260660b040f788920008 Reviewed-by: Christian Stenger --- .../projectexplorer/projectexplorer.cpp | 11 --- src/plugins/projectexplorer/projectexplorer.h | 1 - .../projectexplorer/runconfiguration.cpp | 88 ++++--------------- .../projectexplorer/runconfiguration.h | 14 --- 4 files changed, 16 insertions(+), 98 deletions(-) diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 12c3e5f678e..5380acb4783 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -1995,17 +1995,6 @@ static RunControlFactory findRunControlFactory(RunConfiguration *config, Core::I }; } - IRunControlFactory *runControlFactory = ExtensionSystem::PluginManager::getObject( - [&config, &mode](IRunControlFactory *factory) { - return factory->canRun(config, mode); - }); - - if (runControlFactory) { - return [runControlFactory](RunConfiguration *rc, Id runMode, QString *errorMessage) { - return runControlFactory->create(rc, runMode, errorMessage); - }; - } - return {}; } diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h index 58958c08f2c..2ffb0d200d0 100644 --- a/src/plugins/projectexplorer/projectexplorer.h +++ b/src/plugins/projectexplorer/projectexplorer.h @@ -48,7 +48,6 @@ namespace Utils { class ProcessHandle; } namespace ProjectExplorer { class RunControl; class RunConfiguration; -class IRunControlFactory; class Project; class Node; class FolderNode; diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 566ecc69129..5e59a9e3d28 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -367,7 +367,7 @@ IRunConfigurationAspect *RunConfiguration::extraAspect(Core::Id id) const A target specific \l RunConfiguration implementation can specify what information it considers necessary to execute a process - on the target. Target specific) \n IRunControlFactory implementation + on the target. Target specific) \n RunWorker implementation can use that information either unmodified or tweak it or ignore it when setting up a RunControl. @@ -473,29 +473,6 @@ QList IRunConfigurationFactory::find(Target *parent) }); } -/*! - \class ProjectExplorer::IRunControlFactory - - \brief The IRunControlFactory class creates RunControl objects matching a - run configuration. -*/ - -/*! - \fn RunConfigWidget *ProjectExplorer::IRunConfigurationAspect::createConfigurationWidget() - - Returns a widget used to configure this runner. Ownership is transferred to - the caller. - - Returns null if @p \a runConfiguration is not suitable for RunControls from this - factory, or no user-accessible - configuration is required. -*/ - -IRunControlFactory::IRunControlFactory(QObject *parent) - : QObject(parent) -{ -} - using WorkerFactories = std::vector; static WorkerFactories &theWorkerFactories() @@ -513,37 +490,6 @@ bool RunControl::WorkerFactory::canRun(RunConfiguration *runConfiguration, Core: return constraint(runConfiguration); } -bool IRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id runMode) const -{ - for (const RunControl::WorkerFactory &factory : theWorkerFactories()) { - if (factory.canRun(runConfiguration, runMode)) - return true; - }; - return false; -} - -RunControl *IRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id runMode, QString *) -{ - WorkerFactories candidates; - for (const RunControl::WorkerFactory &factory : theWorkerFactories()) { - if (factory.canRun(runConfiguration, runMode)) - candidates.push_back(factory); - } - - if (candidates.empty()) - return nullptr; - - RunControl::WorkerFactory bestFactory = *candidates.begin(); - for (const RunControl::WorkerFactory &factory : candidates) { - if (factory.priority > bestFactory.priority) - bestFactory = factory; - } - - auto runControl = new RunControl(runConfiguration, runMode); - bestFactory.producer(runControl); - return runControl; -} - /*! \class ProjectExplorer::RunControl \brief The RunControl class instances represent one item that is run. @@ -558,18 +504,6 @@ RunControl *IRunControlFactory::create(RunConfiguration *runConfiguration, Core: */ -const char PRIORITY_KEY[] = "RunControlFactoryPriority"; - -int ProjectExplorer::IRunControlFactory::priority() const -{ - return property(PRIORITY_KEY).toInt(); // 0 by default. -} - -void IRunControlFactory::setPriority(int priority) -{ - setProperty(PRIORITY_KEY, priority); -} - namespace Internal { enum class RunWorkerState @@ -797,12 +731,22 @@ RunWorker *RunControl::createWorker(Core::Id id) RunControl::WorkerCreator RunControl::producer(RunConfiguration *runConfiguration, Core::Id runMode) { - for (const auto &factory : theWorkerFactories()) { - if (factory.runMode == runMode - && (!factory.constraint || factory.constraint(runConfiguration))) - return factory.producer; + WorkerFactories candidates; + for (const RunControl::WorkerFactory &factory : theWorkerFactories()) { + if (factory.canRun(runConfiguration, runMode)) + candidates.push_back(factory); } - return {}; + + if (candidates.empty()) + return {}; + + RunControl::WorkerFactory bestFactory = *candidates.begin(); + for (const RunControl::WorkerFactory &factory : candidates) { + if (factory.priority > bestFactory.priority) + bestFactory = factory; + } + + return bestFactory.producer; } void RunControl::addWorkerFactory(const RunControl::WorkerFactory &workerFactory) diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 4d49d434ea4..8fabadb6549 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -301,20 +301,6 @@ private: virtual RunConfiguration *doRestore(Target *parent, const QVariantMap &map) = 0; }; -class PROJECTEXPLORER_EXPORT IRunControlFactory : public QObject -{ - Q_OBJECT -public: - explicit IRunControlFactory(QObject *parent = nullptr); - - virtual bool canRun(RunConfiguration *runConfiguration, Core::Id runMode) const; - virtual RunControl *create(RunConfiguration *runConfiguration, Core::Id runMode, QString *errorMessage); - - int priority() const; -protected: - void setPriority(int priority); // Higher values will be preferred. -}; - class PROJECTEXPLORER_EXPORT RunConfigWidget : public QWidget { Q_OBJECT From 5a87c17c82092d6eadfa5b4bc842784c3fafb652 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 18 Jul 2017 14:07:25 +0200 Subject: [PATCH 34/35] Add debugger related items to ChangeLog Change-Id: I6b33f6c311983fdb2694f67bfed9e202028c2d64 Reviewed-by: Eike Ziller Reviewed-by: Leena Miettinen --- dist/changes-4.4.0.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dist/changes-4.4.0.md b/dist/changes-4.4.0.md index ce33689bc41..945158f57ca 100644 --- a/dist/changes-4.4.0.md +++ b/dist/changes-4.4.0.md @@ -83,6 +83,10 @@ QML Support Debugging +* Added `Alt+V` + letter shortcuts to open views +* Added dumper for `qfloat16` +* Added dumpers for `std::{optional,byte}`, `gsl::{span,byte}`, `boost::variant` +* Improved display of enum bitfields * Fixed support for `long double` (QTCREATORBUG-18023) * CDB * Added support for extra debugging helpers and debugging helper From 41ae823bda7cc1bad4b85861d9b0e3087c130e4a Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 18 Jul 2017 14:56:59 +0200 Subject: [PATCH 35/35] ProjectExplorer: Take run mode *really* into account Change-Id: Iab69e43a1c6e06dadb5a193d827b7673f09e87c9 Reviewed-by: Christian Kandeler --- src/plugins/projectexplorer/runconfiguration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 5e59a9e3d28..bc3eaac9117 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -483,7 +483,7 @@ static WorkerFactories &theWorkerFactories() bool RunControl::WorkerFactory::canRun(RunConfiguration *runConfiguration, Core::Id runMode) const { - if (runMode != runMode) + if (runMode != this->runMode) return false; if (!constraint) return true;