diff options
78 files changed, 933 insertions, 442 deletions
diff --git a/dist/changes-4.4.0.md b/dist/changes-4.4.0.md new file mode 100644 index 0000000000..945158f57c --- /dev/null +++ b/dist/changes-4.4.0.md @@ -0,0 +1,190 @@ +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 + +* 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 + 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 diff --git a/doc/images/qtcreator-clang-code-model-build-settings.png b/doc/images/qtcreator-clang-code-model-build-settings.png Binary files differnew file mode 100644 index 0000000000..cc7d3d8cf9 --- /dev/null +++ b/doc/images/qtcreator-clang-code-model-build-settings.png diff --git a/doc/images/qtcreator-clang-code-model-options.png b/doc/images/qtcreator-clang-code-model-options.png Binary files differindex ff9e367c02..c48856a201 100644 --- a/doc/images/qtcreator-clang-code-model-options.png +++ b/doc/images/qtcreator-clang-code-model-options.png diff --git a/doc/src/editors/creator-clang-codemodel.qdoc b/doc/src/editors/creator-clang-codemodel.qdoc index cdb7c2d2d1..24cf8be38d 100644 --- a/doc/src/editors/creator-clang-codemodel.qdoc +++ b/doc/src/editors/creator-clang-codemodel.qdoc @@ -129,14 +129,29 @@ \image qtcreator-clang-code-model-options.png - \li In the \uicontrol {Configuration to use} list, configure the - diagnostics that Clang should issue. + \li To instruct the code model to interpret ambiguous header files as C + language files if you develop mainly using C, select the + \uicontrol {Interpret ambiguous headers as C headers} check box. + + \li To process pre-compiled headers, deselect the + \uicontrol {Ignore pre-compiled headers} check box. - You can either select one of the predefined configurations, or - create a copy of a configuration and edit it to fit your needs: + \li To avoid out-of-memory crashes caused by indexing huge source files + that are typically auto-generated by scripts or code, the size of + files to index is limited to 5MB by default. To adjust the limit, + edit the value for the \uicontrol {Do not index files greater than} + check box. To index all files, deselect the check box. + + \li In the \uicontrol {Clang Code Model Warnings} group, configure the + diagnostics that Clang should issue. \list + \li In the \uicontrol {Configuration to use} list, select one of + the predefined configurations, or select \uicontrol Copy to + create a copy of a configuration and edit it to fit your + needs. + \li \uicontrol {Pedantic Warnings} uses the \c -Wpendantic option that requests all the warnings demanded by strict ISO C and ISO C++. @@ -160,15 +175,17 @@ {Options to Request or Suppress Warnings} or the GCC or Clang manual pages. - \li To process pre-compiled headers, deselect the - \uicontrol {Ignore pre-compiled headers} check box. + \endlist - \li To avoid out-of-memory crashes caused by indexing huge source files - that are typically auto-generated by scripts or code, the size of - files to index is limited to 5MB by default. To adjust the limit, - edit the value for the \uicontrol {Do not index files greater than} - check box. To index all files, deselect the check box. + You can specify Clang settings at project level in the build settings of + the project by selecting \uicontrol Projects > + \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. - \endlist + \image qtcreator-clang-code-model-build-settings.png */ diff --git a/share/qtcreator/qml/qmlpuppet/qmlprivategate/metaobject.cpp b/share/qtcreator/qml/qmlpuppet/qmlprivategate/metaobject.cpp index 0b887fa027..08caa70368 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/share/qtcreator/templates/wizards/files/nim/icon.png b/share/qtcreator/templates/wizards/files/nim/icon.png Binary files differdeleted file mode 100644 index a08e474e6d..0000000000 --- a/share/qtcreator/templates/wizards/files/nim/icon.png +++ /dev/null diff --git a/share/qtcreator/templates/wizards/files/nim/wizard.json b/share/qtcreator/templates/wizards/files/nim/wizard.json index 7d20f7ebbd..953df6a847 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 Binary files differdeleted file mode 100644 index a08e474e6d..0000000000 --- a/share/qtcreator/templates/wizards/files/nimscript/icon.png +++ /dev/null diff --git a/share/qtcreator/templates/wizards/files/nimscript/wizard.json b/share/qtcreator/templates/wizards/files/nimscript/wizard.json index 1b0233f754..62aba314cd 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 Binary files differindex a08e474e6d..4d285bbfbb 100644 --- a/share/qtcreator/templates/wizards/projects/nim/icon.png +++ b/share/qtcreator/templates/wizards/projects/nim/icon.png diff --git a/share/qtcreator/templates/wizards/projects/nim/icon@2x.png b/share/qtcreator/templates/wizards/projects/nim/icon@2x.png Binary files differnew file mode 100644 index 0000000000..c1217306a1 --- /dev/null +++ b/share/qtcreator/templates/wizards/projects/nim/icon@2x.png diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/qml_wizard.png b/share/qtcreator/templates/wizards/projects/qtquickapplication/qml_wizard.png Binary files differdeleted file mode 100644 index 23c0236871..0000000000 --- a/share/qtcreator/templates/wizards/projects/qtquickapplication/qml_wizard.png +++ /dev/null diff --git a/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qtquickapplication/wizard.json index 94b40dec18..5f8be50699 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 4593ef8dbb..6b694b4a49 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.<br/><br/><b>Note:</b> 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}", diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp index 8754206a0b..16f351077a 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 <utils/qtcfallthrough.h> + #include <unordered_map> #include <utility> @@ -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/cplusplus/MatchingText.cpp b/src/libs/cplusplus/MatchingText.cpp index f783d4c508..3fdb573b91 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; diff --git a/src/libs/utils/qtcfallthrough.h b/src/libs/utils/qtcfallthrough.h new file mode 100644 index 0000000000..6eba622837 --- /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 <QtGlobal> + +#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 bfc9d6084e..3a6aa0a09a 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 559129df16..6d68683fdd 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/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 5ff5b1aa7e..cfb52f1528 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<quint64, ClangCompletionAssistProcessor *> 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 57a07e8097..e98565f48c 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<CppTools::CursorInfo> 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/clangcodemodel/clangdiagnosticmanager.cpp b/src/plugins/clangcodemodel/clangdiagnosticmanager.cpp index c8da6e6c6a..1dd003c7c1 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<ClangBackEnd::DiagnosticContainer> & diff --git a/src/plugins/clangcodemodel/clangdiagnosticmanager.h b/src/plugins/clangcodemodel/clangdiagnosticmanager.h index 16b1c16d2d..1321702c99 100644 --- a/src/plugins/clangcodemodel/clangdiagnosticmanager.h +++ b/src/plugins/clangcodemodel/clangdiagnosticmanager.h @@ -34,6 +34,7 @@ #include <QList> #include <QSet> #include <QTextEdit> +#include <QTimer> #include <QVector> #include <vector> @@ -82,8 +83,10 @@ private: QList<QTextEdit::ExtraSelection> m_extraSelections; TextEditor::RefactorMarkers m_fixItAvailableMarkers; std::vector<ClangTextMark *> m_clangTextMarks; + bool m_firstDiagnostics = true; bool m_diagnosticsInvalidated = false; bool m_showTextMarkAnnotations = false; + QTimer m_textMarkDelay; }; } // namespace Internal diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerplugin.cpp index f10b2784bb..e18b9747b8 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<ClangStaticAnalyzerToolRunner> - (Constants::CLANGSTATICANALYZER_RUN_MODE, constraint); + (Constants::CLANGSTATICANALYZER_RUN_MODE, constraint, /*priority*/ -1); return true; } diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp index 612a35c52e..98a0788ebc 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp @@ -79,7 +79,9 @@ ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runCont RunConfiguration *runConfiguration = runControl->runConfiguration(); 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); @@ -495,10 +497,14 @@ void ClangStaticAnalyzerToolRunner::start() m_success = false; ClangStaticAnalyzerTool::instance()->onEngineIsStarting(); + connect(runControl(), &RunControl::stopped, 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()) - + QLatin1Char('\n'), Utils::NormalMessageFormat); + appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput()), + Utils::NormalMessageFormat); // Check clang executable bool isValidClangExecutable; @@ -507,7 +513,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(); @@ -522,7 +528,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()) { @@ -531,7 +537,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(); } @@ -544,7 +550,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); @@ -599,15 +605,11 @@ 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(); - reportStopped(); -} - -void ClangStaticAnalyzerToolRunner::onFinished() -{ ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success); + reportStopped(); } void ClangStaticAnalyzerToolRunner::analyzeNextFile() @@ -629,7 +631,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); } @@ -658,9 +660,8 @@ void ClangStaticAnalyzerToolRunner::onRunnerFinishedWithSuccess(const QString &l if (!errorMessage.isEmpty()) { qCDebug(LOG) << "onRunnerFinishedWithSuccess: Error reading log file:" << errorMessage; const QString filePath = qobject_cast<ClangStaticAnalyzerRunner *>(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()) @@ -679,9 +680,8 @@ void ClangStaticAnalyzerToolRunner::onRunnerFinishedWithFailure(const QString &e ++m_filesNotAnalyzed; m_success = false; const QString filePath = qobject_cast<ClangStaticAnalyzerRunner *>(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); @@ -699,7 +699,7 @@ void ClangStaticAnalyzerToolRunner::handleFinished() void ClangStaticAnalyzerToolRunner::onProgressCanceled() { m_progress.reportCanceled(); - stop(); + runControl()->initiateStop(); } void ClangStaticAnalyzerToolRunner::updateProgressValue() @@ -711,9 +711,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) { @@ -723,7 +721,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 9719c42116..e75660287f 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. diff --git a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp index c8f1f6c8ba..461f31049b 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 b3f05843d6..06550bce31 100644 --- a/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h +++ b/src/plugins/clangstaticanalyzer/clangstaticanalyzertool.h @@ -58,9 +58,10 @@ public: // For testing. QList<Diagnostic> diagnostics() const; - void startTool(); + void handleWorkerStart(ProjectExplorer::RunWorker *runWorker); + void onEngineIsStarting(); void onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics); void onEngineFinished(bool success); diff --git a/src/plugins/coreplugin/dialogs/newdialog.cpp b/src/plugins/coreplugin/dialogs/newdialog.cpp index f38a43e73b..80f8eb8d4d 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; @@ -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<QIcon>(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; }; @@ -101,18 +116,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 +135,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 +163,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,11 +183,10 @@ 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); - size = size.expandedTo(QSize(0, ROW_HEIGHT)); return size; diff --git a/src/plugins/coreplugin/locator/locatorwidget.cpp b/src/plugins/coreplugin/locator/locatorwidget.cpp index 76f0ac1f5b..5073bcd33c 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 4484faefdd..c4ce3c4a14 100644 --- a/src/plugins/coreplugin/locator/locatorwidget.h +++ b/src/plugins/coreplugin/locator/locatorwidget.h @@ -27,6 +27,8 @@ #include "locator.h" +#include <utils/optional.h> + #include <QPointer> #include <QWidget> @@ -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<int> m_rowRequestedForAccept; }; class LocatorPopup : public QWidget diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 677cd1ebc3..65d0c42abf 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()); diff --git a/src/plugins/cppeditor/cppeditordocument.cpp b/src/plugins/cppeditor/cppeditordocument.cpp index c5a9d40e2e..d31a4eb899 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(); diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 67d360c3bb..640fa794ef 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -56,6 +56,7 @@ #include <utils/fancylineedit.h> #include <utils/qtcassert.h> +#include <utils/qtcfallthrough.h> #include <QApplication> #include <QComboBox> @@ -4119,7 +4120,7 @@ public: break; case FromReference: removeReferenceOperator(changes); - // fallthrough intended + Q_FALLTHROUGH(); case FromVariable: convertToPointer(changes); break; diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp index 5e03ebbe2d..81e1436ccd 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()); } diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 8f5fd397fb..170279c9b8 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -26,6 +26,7 @@ #include "compileroptionsbuilder.h" #include <projectexplorer/projectexplorerconstants.h> +#include <utils/qtcfallthrough.h> #include <QDir> #include <QRegularExpression> @@ -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/debuggerdialogs.cpp b/src/plugins/debugger/debuggerdialogs.cpp index c247c22a43..f9017a7f41 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<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &StartApplicationDialog::historyIndexChanged); + connect(d->channelOverrideEdit, &QLineEdit::textChanged, + this, &StartApplicationDialog::onChannelOverrideChanged); + updateState(); } @@ -334,6 +344,12 @@ void StartApplicationDialog::setHistory(const QList<StartApplicationParameters> } } +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 60cdedefeb..b291dbbe26 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<StartApplicationParameters> &l); + void onChannelOverrideChanged(const QString &channel); StartApplicationDialogPrivate *d; }; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index e60af1faa8..efc1680458 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/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 832a343540..38d867c878 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -421,18 +421,6 @@ namespace Internal { void addCdbOptionPages(QList<IOptionsPage*> *opts); void addGdbOptionPages(QList<IOptionsPage*> *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<DebuggerRunConfigurationAspect>(); // The main "Start Debugging" action. act = m_startAction = new QAction(this); diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp index 11566a51be..519647d703 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.cpp +++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp @@ -31,6 +31,7 @@ #include <debugger/debuggerstartparameters.h> #include <utils/qtcassert.h> +#include <utils/qtcfallthrough.h> 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 a36aa11bef..cf55a82dc6 100644 --- a/src/plugins/debugger/gdb/remotegdbserveradapter.cpp +++ b/src/plugins/debugger/gdb/remotegdbserveradapter.cpp @@ -34,6 +34,7 @@ #include <coreplugin/messagebox.h> #include <utils/hostosinfo.h> +#include <utils/qtcfallthrough.h> #include <utils/qtcassert.h> #include <utils/qtcprocess.h> @@ -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/moduleshandler.cpp b/src/plugins/debugger/moduleshandler.cpp index 94d558851a..e37c44ccbb 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 diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 87b4a039d0..10e6d4f3b2 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -60,6 +60,7 @@ #include <utils/treemodel.h> #include <utils/basetreeview.h> #include <utils/qtcassert.h> +#include <utils/qtcfallthrough.h> #include <QDebug> #include <QDir> @@ -376,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(); } @@ -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 f6e8dfeb45..2275807d22 100644 --- a/src/plugins/debugger/watchutils.cpp +++ b/src/plugins/debugger/watchutils.cpp @@ -29,6 +29,8 @@ #include "watchutils.h" #include "watchdata.h" +#include <utils/qtcfallthrough.h> + #include <QDebug> #include <string.h> @@ -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/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 232c2addaa..6391c0ae0a 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<FileData> fileDataList = m_futureWatcher.future().results(); + const bool success = !m_futureWatcher.future().isCanceled(); + const QList<FileData> fileDataList = success + ? m_futureWatcher.future().results() : QList<FileData>(); setDiffFiles(fileDataList); - reloadFinished(true); + reloadFinished(success); } void DiffFilesController::cancelReload() diff --git a/src/plugins/ios/iosplugin.cpp b/src/plugins/ios/iosplugin.cpp index 28e590167e..b2b33d8ae3 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 <projectexplorer/devicesupport/devicemanager.h> #include <projectexplorer/kitmanager.h> +#include <projectexplorer/runconfiguration.h> + #include <qtsupport/qtversionmanager.h> #include <QtPlugin> -#include <projectexplorer/devicesupport/devicemanager.h> +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<Internal::IosRunConfiguration *>(runConfig) != nullptr; + }; + + RunControl::registerWorker<Internal::IosRunSupport> + (ProjectExplorer::Constants::NORMAL_RUN_MODE, constraint); + RunControl::registerWorker<Internal::IosDebugSupport> + (ProjectExplorer::Constants::DEBUG_RUN_MODE, constraint); + RunControl::registerWorker<Internal::IosQmlProfilerSupport> + (ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, constraint); + return true; } diff --git a/src/plugins/ios/iosrunfactories.cpp b/src/plugins/ios/iosrunfactories.cpp index b2d42b671b..c41dcb8263 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 <debugger/analyzer/analyzermanager.h> @@ -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<IosRunConfiguration *>(runConfiguration); -} - -RunControl *IosRunControlFactory::create(RunConfiguration *runConfig, - Core::Id mode, QString *errorMessage) -{ - Q_UNUSED(errorMessage); - Q_ASSERT(canRun(runConfig, mode)); - IosRunConfiguration *rc = qobject_cast<IosRunConfiguration *>(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<RunControl> 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 8e9b072639..318e57e04e 100644 --- a/src/plugins/ios/iosrunfactories.h +++ b/src/plugins/ios/iosrunfactories.h @@ -29,8 +29,6 @@ #include <qmakeprojectmanager/qmakerunconfigurationfactory.h> 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<Core::Id, QPointer<ProjectExplorer::RunControl> > m_activeRunControls; -}; - } // namespace Internal } // namespace Ios diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index 23400d34c7..7ecd50b836 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<Core::Id, QPointer<RunControl>> 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<RunControl> 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<IosRunConfiguration *>(runControl->runConfiguration()); m_bundleDir = runConfig->bundleDirectory().toString(); m_arguments = QStringList(runConfig->commandLineArguments()); @@ -513,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 203ae87909..2db7cf8c0d 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; diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index f2afa71433..317c1f6f59 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -33,6 +33,7 @@ #include <coreplugin/icore.h> #include <utils/qtcassert.h> #include <utils/fileutils.h> +#include <utils/qtcfallthrough.h> #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/projectexplorer/appoutputpane.cpp b/src/plugins/projectexplorer/appoutputpane.cpp index 9e0617454b..1e6ef0efd6 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<RunControl *> AppOutputPane::allRunControls() const { return Utils::transform<QList>(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 ba3839ca6a..b260447ba5 100644 --- a/src/plugins/projectexplorer/appoutputpane.h +++ b/src/plugins/projectexplorer/appoutputpane.h @@ -25,6 +25,7 @@ #pragma once +#include <QPointer> #include <QVector> #include <coreplugin/ioutputpane.h> @@ -124,7 +125,7 @@ private: public: explicit RunControlTab(RunControl *runControl = nullptr, Core::OutputWindow *window = nullptr); - RunControl *runControl; + QPointer<RunControl> runControl; Core::OutputWindow *window; BehaviorOnOutput behaviorOnOutput = Flash; }; diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index 12c3e5f678..5380acb478 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<IRunControlFactory>( - [&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 58958c08f2..2ffb0d200d 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/projecttreewidget.cpp b/src/plugins/projectexplorer/projecttreewidget.cpp index 372dbdb757..2a98fbe86e 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 072cc1f1ab..69102fedb0 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<ProjectTreeWidget *> m_projectTreeWidgets; diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index d098411706..bc3eaac911 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<RunConfiguration::AspectFactory> 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<IRunControlFactory>()) - addExtraAspect(factory->createRunConfigurationAspect(this)); + theAspectFactories.push_back(aspectFactory); } void RunConfiguration::addExtraAspect(IRunConfigurationAspect *aspect) @@ -365,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. @@ -471,29 +473,6 @@ QList<IRunConfigurationFactory *> 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<RunControl::WorkerFactory>; static WorkerFactories &theWorkerFactories() @@ -504,50 +483,13 @@ 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; 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 *) -{ - for (const RunControl::WorkerFactory &factory : theWorkerFactories()) { - if (factory.canRun(runConfiguration, runMode)) { - auto runControl = new RunControl(runConfiguration, runMode); - factory.producer(runControl); - return runControl; - } - }; - return nullptr; -} - -/*! - 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. @@ -562,18 +504,6 @@ IRunConfigurationAspect *IRunControlFactory::createRunConfigurationAspect(RunCon */ -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 @@ -592,7 +522,7 @@ static QString stateName(RunWorkerState s) SN(RunWorkerState::Done) SN(RunWorkerState::Failed) } - return QLatin1String("<unknown>"); + return QString("<unknown: %1>").arg(int(s)); # undef SN } @@ -606,7 +536,7 @@ public: RunWorker *q; RunWorkerState state = RunWorkerState::Initialized; - RunControl *runControl; + QPointer<RunControl> runControl; QList<RunWorker *> dependencies; QString id; @@ -625,6 +555,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) @@ -636,8 +568,10 @@ static QString stateName(RunControlState s) SN(RunControlState::Running) SN(RunControlState::Stopping) SN(RunControlState::Stopped) + SN(RunControlState::Finishing) + SN(RunControlState::Finished) } - return QLatin1String("<unknown>"); + return QString("<unknown: %1>").arg(int(s)); # undef SN } @@ -659,8 +593,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; } @@ -675,7 +612,7 @@ public: void initiateReStart(); void continueStart(); void initiateStop(); - void continueStop(); + void initiateFinish(); void onWorkerStarted(RunWorker *worker); void onWorkerStopped(RunWorker *worker); @@ -694,7 +631,7 @@ public: Utils::Icon icon; const QPointer<RunConfiguration> runConfiguration; // Not owned. QPointer<Project> project; // Not owned. - Utils::OutputFormatter *outputFormatter = nullptr; + QPointer<Utils::OutputFormatter> outputFormatter = nullptr; std::function<bool(bool*)> promptToStop; std::vector<RunControl::WorkerFactory> m_factories; @@ -759,6 +696,11 @@ void RunControl::initiateStop() d->initiateStop(); } +void RunControl::initiateFinish() +{ + d->initiateFinish(); +} + using WorkerCreators = QHash<Core::Id, RunControl::WorkerCreator>; static WorkerCreators &theWorkerCreators() @@ -789,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); + } + + if (candidates.empty()) + return {}; + + RunControl::WorkerFactory bestFactory = *candidates.begin(); + for (const RunControl::WorkerFactory &factory : candidates) { + if (factory.priority > bestFactory.priority) + bestFactory = factory; } - return {}; + + return bestFactory.producer; } void RunControl::addWorkerFactory(const RunControl::WorkerFactory &workerFactory) @@ -880,15 +832,58 @@ void RunControlPrivate::initiateStop() { checkState(RunControlState::Running); setState(RunControlState::Stopping); - debugMessage("Queue: Stopping"); + debugMessage("Queue: Stopping for all workers"); - continueStop(); + 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) { + debugMessage("All stopped."); + setState(RunControlState::Stopped); + } else { + debugMessage("Not all workers stopped. Waiting..."); + } } -void RunControlPrivate::continueStop() +void RunControlPrivate::initiateFinish() { - debugMessage("Continue Stopping"); - checkState(RunControlState::Stopping); + setState(RunControlState::Finishing); + debugMessage("Ramping down"); + bool allDone = true; for (RunWorker *worker : m_workers) { if (worker) { @@ -904,17 +899,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; @@ -927,8 +922,9 @@ void RunControlPrivate::continueStop() } } if (allDone) { - debugMessage("All workers stopped. Set runControl to Stopped"); - setState(RunControlState::Stopped); + setState(RunControlState::Finished); + } else { + debugMessage("Not all workers finished. Waiting..."); } } @@ -944,7 +940,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) @@ -968,13 +963,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) @@ -1175,15 +1229,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; @@ -1213,11 +1275,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; } @@ -1228,18 +1292,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); @@ -1358,8 +1410,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 eb408c204a..8fabadb654 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<IRunConfigurationAspect *(RunConfiguration *)>; + template <class T> 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<IRunConfigurationAspect *> m_aspects; }; @@ -295,22 +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); - - virtual IRunConfigurationAspect *createRunConfigurationAspect(RunConfiguration *rc); - - int priority() const; -protected: - void setPriority(int priority); // Higher values will be preferred. -}; - class PROJECTEXPLORER_EXPORT RunConfigWidget : public QWidget { Q_OBJECT @@ -397,6 +387,7 @@ public: void initiateStart(); void initiateReStart(); void initiateStop(); + void initiateFinish(); bool promptToStop(bool *optionalPrompt = nullptr) const; void setPromptToStop(const std::function<bool(bool *)> &promptToStop); @@ -430,7 +421,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(), @@ -450,24 +440,28 @@ public: addWorkerFactory({runMode, constraint, producer}); } template <class Worker> - 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 <class Config, class Worker> - static void registerWorker(Core::Id runMode) + static void registerWorker(Core::Id runMode, int priority = 0) { auto constraint = [](RunConfiguration *runConfig) { return qobject_cast<Config *>(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; + 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; }; @@ -479,6 +473,7 @@ signals: void aboutToStart(); void started(); void stopped(); + void finished(); void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle private: diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp index 950028bf3b..3601db1753 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorscene.cpp @@ -44,6 +44,7 @@ #include <utils/algorithm.h> #include <utils/qtcassert.h> +#include <utils/qtcfallthrough.h> namespace QmlDesigner { @@ -358,6 +359,7 @@ bool FormEditorScene::event(QEvent * event) currentTool()->keyPressEvent(static_cast<QKeyEvent*>(event)); return true; } + Q_FALLTHROUGH(); default: return QGraphicsScene::event(event); } diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index a95c455134..f5bb5d1ba6 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/src/plugins/qmlprofiler/qmlprofilerplugin.cpp b/src/plugins/qmlprofiler/qmlprofilerplugin.cpp index 777a042fc1..ea89b6b6dc 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<QmlProfilerRunConfigurationAspect>(); auto constraint = [](RunConfiguration *runConfiguration) { Target *target = runConfiguration ? runConfiguration->target() : nullptr; diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp index 227b6dff0b..e246bf885c 100644 --- a/src/plugins/qmlprofiler/qmlprofilertool.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp @@ -69,6 +69,8 @@ #include <qtsupport/qtkitinformation.h> +#include <utils/qtcfallthrough.h> + #include <QApplication> #include <QDockWidget> #include <QFileDialog> @@ -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 8519d12422..a2a00b4f98 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 <debugger/analyzer/analyzermanager.h> #include <coreplugin/findplaceholder.h> +#include <utils/qtcfallthrough.h> #include <utils/styledbar.h> #include <utils/algorithm.h> @@ -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 f7b2e563e9..5f63319c16 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 <utils/qtcfallthrough.h> + #include <QMimeData> #include <QUndoStack> @@ -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/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 4c9711a67c..7e8c1c2345 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 15939a3f44..254999f1b3 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); + 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) { - paintIcon(painter, annotationRect->adjusted( - margin, margin, -(textWidth + 2 * margin), -margin).toAlignedRect()); + rects.iconRect.setHeight(boundingRect.height() - 2 * margin); + rects.iconRect.setWidth(rects.iconRect.height() * m_widthFactor); } - painter->drawText(annotationRect->adjusted(iconWidth, 0, 0, 0), Qt::AlignLeft, text); - painter->restore(); + 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 89d3d96e02..ca484a8538 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); diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index a69e2eac60..cab6dea44c 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 3cb1a4245b..13beca1fa0 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 diff --git a/src/plugins/valgrind/valgrindplugin.cpp b/src/plugins/valgrind/valgrindplugin.cpp index 4cb71eab68..4e250b8b19 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<ValgrindRunConfigurationAspect>(); return true; } diff --git a/src/plugins/vcsbase/vcsbaseclientsettings.cpp b/src/plugins/vcsbase/vcsbaseclientsettings.cpp index 35c2a7c119..ab67910c2f 100644 --- a/src/plugins/vcsbase/vcsbaseclientsettings.cpp +++ b/src/plugins/vcsbase/vcsbaseclientsettings.cpp @@ -29,6 +29,7 @@ #include <utils/fileutils.h> #include <utils/hostosinfo.h> #include <utils/qtcassert.h> +#include <utils/qtcfallthrough.h> #include <QSettings> #include <QVariant> @@ -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; diff --git a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp index b92a35f854..6b628cdb13 100644 --- a/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp +++ b/src/plugins/vcsbase/vcsbasediffeditorcontroller.cpp @@ -48,6 +48,37 @@ static void readPatch(QFutureInterface<QList<FileData>> &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<VcsCommand> m_command; - QFutureWatcher<QList<FileData>> m_processWatcher; + QPointer<VcsCommandResultProxy> m_commandResultProxy; + QFutureWatcher<QList<FileData>> *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<QList<FileData>>::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<FileData> fileDataList = success - ? m_processWatcher.future().result() : QList<FileData>(); + ? m_processWatcher->future().result() : QList<FileData>(); + + // 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(); + + m_processWatcher = new QFutureWatcher<QList<FileData>>(); - ProgressManager::addTask(m_processWatcher.future(), - q->tr("Processing diff"), "DiffEditor"); + QObject::connect(m_processWatcher, &QFutureWatcher<QList<FileData>>::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<QList<FileData>>()); + // 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<QStringList> &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" diff --git a/src/tools/icons/qtcreatoricons.svg b/src/tools/icons/qtcreatoricons.svg index e24903e09e..0534a08b94 100644 --- a/src/tools/icons/qtcreatoricons.svg +++ b/src/tools/icons/qtcreatoricons.svg @@ -1671,6 +1671,28 @@ sodipodi:nodetypes="cccccccccccccccc" /> </g> <g + id="share/qtcreator/templates/wizards/projects/nim/icon"> + <rect + style="display:inline;fill:none" + id="rect5532-7-2-6-5-7" + width="92" + height="68" + x="190" + y="136" /> + <path + id="path3799" + style="fill:#cecfd5" + d="m 263.88612,170.56484 c -2.25619,-7.49215 -13.9354,-14.04789 -27.88611,-14.04789 -14.23027,0 -25.62993,6.55574 -27.88613,14.04789 l -2.69076,2.30637 -3.80901,-7.33845 -2.93538,-12.37053 5.03208,2.0967 c 1.376,-1.39235 2.35711,-2.47631 5.87076,-4.40307 l 3.35472,-6.91911 5.66109,4.40307 c 3.80983,-0.90692 7.59785,-1.85747 11.95119,-1.67736 L 236,141.42071 l 5.45142,5.24175 c 4.35334,-0.18011 8.14136,0.77044 11.95119,1.67736 l 5.66109,-4.40307 3.35472,6.91911 c 3.51365,1.92676 4.49476,3.01072 5.87076,4.40307 l 5.03208,-2.0967 -2.93538,12.37053 -3.80901,7.33845 z" + inkscape:connector-curvature="0" + sodipodi:nodetypes="csccccccccccccccccccc" /> + <path + id="path3801" + style="fill:#3a4055" + d="m 267.03116,171.19385 -3.14504,-0.83868 -5.6611,7.33846 L 250.46723,180 236,171.82286 221.53276,180 l -7.75779,-2.30637 -5.66109,-7.33846 -3.14505,0.83868 -3.35472,-5.87076 6.49977,18.45097 c 4.59209,9.55845 18.73642,14.25756 27.88613,14.25756 9.14969,0 23.29402,-4.69911 27.88611,-14.25756 l 6.49977,-18.45097 z" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccccccsccc" /> + </g> + <g id="src/libs/utils/images/wizardicon-file" transform="translate(-102.49412,8.5102807)"> <rect 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 2e2ca6a7bf..e792762e7c 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 2e2ca6a7bf..e792762e7c 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 diff --git a/tests/system/suite_general/tst_session_handling/test.py b/tests/system/suite_general/tst_session_handling/test.py index 19cbfbaa18..03a9114263 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}" |