Merge remote-tracking branch 'origin/4.4'

Change-Id: I778acc044ac105a11054b314aecac5b1c2cfee6a
This commit is contained in:
Eike Ziller
2017-07-18 15:23:29 +02:00
78 changed files with 937 additions and 446 deletions

190
dist/changes-4.4.0.md vendored Normal file
View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

@@ -129,14 +129,29 @@
\image qtcreator-clang-code-model-options.png \image qtcreator-clang-code-model-options.png
\li In the \uicontrol {Configuration to use} list, configure the \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.
\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. diagnostics that Clang should issue.
You can either select one of the predefined configurations, or
create a copy of a configuration and edit it to fit your needs:
\list \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 \li \uicontrol {Pedantic Warnings} uses the \c -Wpendantic
option that requests all the warnings demanded by strict option that requests all the warnings demanded by strict
ISO C and ISO C++. ISO C and ISO C++.
@@ -160,15 +175,17 @@
{Options to Request or Suppress Warnings} or the GCC or Clang {Options to Request or Suppress Warnings} or the GCC or Clang
manual pages. manual pages.
\li To process pre-compiled headers, deselect the
\uicontrol {Ignore pre-compiled headers} check box.
\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.
\endlist \endlist
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.
\image qtcreator-clang-code-model-build-settings.png
*/ */

View File

@@ -304,9 +304,9 @@ int MetaObject::metaCall(QMetaObject::Call call, int id, void **a)
&& property(id).name() == QLatin1String("parent"))) { && property(id).name() == QLatin1String("parent"))) {
QObject *contextDummyObject = objectNodeInstance->nodeInstanceServer()->dummyContextObject(); QObject *contextDummyObject = objectNodeInstance->nodeInstanceServer()->dummyContextObject();
int properyIndex = contextDummyObject->metaObject()->indexOfProperty(propertyById.name()); int propertyIndex = contextDummyObject->metaObject()->indexOfProperty(propertyById.name());
if (properyIndex >= 0) if (propertyIndex >= 0)
metaCallReturnValue = contextDummyObject->qt_metacall(call, properyIndex, a); metaCallReturnValue = contextDummyObject->qt_metacall(call, propertyIndex, a);
} }
} }
*/ */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -6,7 +6,7 @@
"trDescription": "Creates an empty Nim file using UTF-8 charset.", "trDescription": "Creates an empty Nim file using UTF-8 charset.",
"trDisplayName": "Nim File", "trDisplayName": "Nim File",
"trDisplayCategory": "Nim", "trDisplayCategory": "Nim",
"icon": "icon.png", "icon": "../../projects/nim/icon.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('Nim') >= 0}", "enabled": "%{JS: [ %{Plugins} ].indexOf('Nim') >= 0}",
"pages" : "pages" :

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -6,7 +6,7 @@
"trDescription": "Creates an empty Nim script file using UTF-8 charset.", "trDescription": "Creates an empty Nim script file using UTF-8 charset.",
"trDisplayName": "Nim Script File", "trDisplayName": "Nim Script File",
"trDisplayCategory": "Nim", "trDisplayCategory": "Nim",
"icon": "icon.png", "icon": "../../projects/nim/icon.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('Nim') >= 0}", "enabled": "%{JS: [ %{Plugins} ].indexOf('Nim') >= 0}",
"pages" : "pages" :

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

View File

@@ -6,7 +6,7 @@
"trDescription": "Creates a deployable Qt Quick 2 application.", "trDescription": "Creates a deployable Qt Quick 2 application.",
"trDisplayName": "Qt Quick Application", "trDisplayName": "Qt Quick Application",
"trDisplayCategory": "Application", "trDisplayCategory": "Application",
"icon": "qml_wizard.png", "icon": "icon-empty.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.3" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQt.5.3" ],
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}", "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",

View File

@@ -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.", "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", "trDisplayName": "Qt Quick Controls 2 Application",
"trDisplayCategory": "Application", "trDisplayCategory": "Application",
"icon": "../qtquickapplication/qml_wizard.png", "icon": "../qtquickapplication/icon-swipe.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.2" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.2" ],
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}", "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0 || [ %{Plugins} ].indexOf('QbsProjectManager') >= 0 || [ %{Plugins} ].indexOf('CMakeProjectManager') >= 0}",

View File

@@ -27,6 +27,8 @@
#include "ObjectiveCTypeQualifiers.h" #include "ObjectiveCTypeQualifiers.h"
#include "QtContextKeywords.h" #include "QtContextKeywords.h"
#include <utils/qtcfallthrough.h>
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
@@ -442,7 +444,7 @@ bool Parser::skipUntilStatement()
case T_AT_THROW: case T_AT_THROW:
if (_languageFeatures.objCEnabled) if (_languageFeatures.objCEnabled)
return true; return true;
Q_FALLTHROUGH();
default: default:
consumeToken(); consumeToken();
} }

View File

@@ -143,9 +143,13 @@ bool MatchingText::contextAllowsAutoParentheses(const QTextCursor &cursor,
if (!textToInsert.isEmpty()) if (!textToInsert.isEmpty())
ch = textToInsert.at(0); 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('"')) if (!shouldInsertMatchingText(cursor) && ch != QLatin1Char('\'') && ch != QLatin1Char('"'))
return false; return false;
else if (isInCommentHelper(cursor))
if (isInCommentHelper(cursor))
return false; return false;
return true; return true;

View File

@@ -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

View File

@@ -239,6 +239,7 @@ HEADERS += \
$$PWD/asconst.h \ $$PWD/asconst.h \
$$PWD/smallstringfwd.h \ $$PWD/smallstringfwd.h \
$$PWD/optional.h \ $$PWD/optional.h \
$$PWD/qtcfallthrough.h \
$$PWD/../3rdparty/optional/optional.hpp $$PWD/../3rdparty/optional/optional.hpp
FORMS += $$PWD/filewizardpage.ui \ FORMS += $$PWD/filewizardpage.ui \

View File

@@ -175,6 +175,7 @@ Project {
"proxycredentialsdialog.cpp", "proxycredentialsdialog.cpp",
"proxycredentialsdialog.h", "proxycredentialsdialog.h",
"proxycredentialsdialog.ui", "proxycredentialsdialog.ui",
"qtcfallthrough.h",
"qtcassert.cpp", "qtcassert.cpp",
"qtcassert.h", "qtcassert.h",
"qtcolorbutton.cpp", "qtcolorbutton.cpp",

View File

@@ -99,7 +99,7 @@ IpcReceiver::IpcReceiver()
IpcReceiver::~IpcReceiver() IpcReceiver::~IpcReceiver()
{ {
deleteAndClearWaitingAssistProcessors(); reset();
} }
void IpcReceiver::setAliveHandler(const IpcReceiver::AliveHandler &handler) void IpcReceiver::setAliveHandler(const IpcReceiver::AliveHandler &handler)
@@ -116,12 +116,6 @@ void IpcReceiver::addExpectedCodeCompletedMessage(
m_assistProcessorsTable.insert(ticket, processor); m_assistProcessorsTable.insert(ticket, processor);
} }
void IpcReceiver::deleteAndClearWaitingAssistProcessors()
{
qDeleteAll(m_assistProcessorsTable.begin(), m_assistProcessorsTable.end());
m_assistProcessorsTable.clear();
}
void IpcReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget) void IpcReceiver::deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget)
{ {
QMutableHashIterator<quint64, ClangCompletionAssistProcessor *> it(m_assistProcessorsTable); QMutableHashIterator<quint64, ClangCompletionAssistProcessor *> it(m_assistProcessorsTable);
@@ -155,6 +149,18 @@ bool IpcReceiver::isExpectingCodeCompletedMessage() const
return !m_assistProcessorsTable.isEmpty(); 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() void IpcReceiver::alive()
{ {
if (printAliveMessage()) if (printAliveMessage())
@@ -719,7 +725,7 @@ void IpcCommunicator::onConnectedToBackend()
if (m_connectedCount > 1) if (m_connectedCount > 1)
logRestartedDueToUnexpectedFinish(); logRestartedDueToUnexpectedFinish();
m_ipcReceiver.deleteAndClearWaitingAssistProcessors(); m_ipcReceiver.reset();
m_ipcSender.reset(new IpcSender(m_connection)); m_ipcSender.reset(new IpcSender(m_connection));
initializeBackendWithCurrentData(); initializeBackendWithCurrentData();

View File

@@ -73,14 +73,14 @@ public:
void setAliveHandler(const AliveHandler &handler); void setAliveHandler(const AliveHandler &handler);
void addExpectedCodeCompletedMessage(quint64 ticket, ClangCompletionAssistProcessor *processor); void addExpectedCodeCompletedMessage(quint64 ticket, ClangCompletionAssistProcessor *processor);
void deleteAndClearWaitingAssistProcessors();
void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget); void deleteProcessorsOfEditorWidget(TextEditor::TextEditorWidget *textEditorWidget);
QFuture<CppTools::CursorInfo> addExpectedReferencesMessage(quint64 ticket, QFuture<CppTools::CursorInfo> addExpectedReferencesMessage(quint64 ticket,
QTextDocument *textDocument); QTextDocument *textDocument);
bool isExpectingCodeCompletedMessage() const; bool isExpectingCodeCompletedMessage() const;
void reset();
private: private:
void alive() override; void alive() override;
void echo(const ClangBackEnd::EchoMessage &message) override; void echo(const ClangBackEnd::EchoMessage &message) override;

View File

@@ -278,6 +278,8 @@ namespace Internal {
ClangDiagnosticManager::ClangDiagnosticManager(TextEditor::TextDocument *textDocument) ClangDiagnosticManager::ClangDiagnosticManager(TextEditor::TextDocument *textDocument)
: m_textDocument(textDocument) : m_textDocument(textDocument)
{ {
m_textMarkDelay.setInterval(1500);
m_textMarkDelay.setSingleShot(true);
} }
ClangDiagnosticManager::~ClangDiagnosticManager() ClangDiagnosticManager::~ClangDiagnosticManager()
@@ -295,6 +297,7 @@ void ClangDiagnosticManager::cleanMarks()
} }
void ClangDiagnosticManager::generateTextMarks() void ClangDiagnosticManager::generateTextMarks()
{ {
QObject::disconnect(&m_textMarkDelay, &QTimer::timeout, 0, 0);
cleanMarks(); cleanMarks();
m_clangTextMarks.reserve(m_warningDiagnostics.size() + m_errorDiagnostics.size()); m_clangTextMarks.reserve(m_warningDiagnostics.size() + m_errorDiagnostics.size());
addClangTextMarks(m_warningDiagnostics); addClangTextMarks(m_warningDiagnostics);
@@ -350,6 +353,7 @@ ClangDiagnosticManager::diagnosticsAt(uint line, uint column) const
void ClangDiagnosticManager::invalidateDiagnostics() void ClangDiagnosticManager::invalidateDiagnostics()
{ {
m_textMarkDelay.start();
if (m_diagnosticsInvalidated) if (m_diagnosticsInvalidated)
return; return;
@@ -383,9 +387,18 @@ void ClangDiagnosticManager::processNewDiagnostics(
m_showTextMarkAnnotations = showTextMarkAnnotations; m_showTextMarkAnnotations = showTextMarkAnnotations;
filterDiagnostics(allDiagnostics); filterDiagnostics(allDiagnostics);
generateTextMarks();
generateEditorSelections(); generateEditorSelections();
generateFixItAvailableMarkers(); 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> & const QVector<ClangBackEnd::DiagnosticContainer> &

View File

@@ -34,6 +34,7 @@
#include <QList> #include <QList>
#include <QSet> #include <QSet>
#include <QTextEdit> #include <QTextEdit>
#include <QTimer>
#include <QVector> #include <QVector>
#include <vector> #include <vector>
@@ -82,8 +83,10 @@ private:
QList<QTextEdit::ExtraSelection> m_extraSelections; QList<QTextEdit::ExtraSelection> m_extraSelections;
TextEditor::RefactorMarkers m_fixItAvailableMarkers; TextEditor::RefactorMarkers m_fixItAvailableMarkers;
std::vector<ClangTextMark *> m_clangTextMarks; std::vector<ClangTextMark *> m_clangTextMarks;
bool m_firstDiagnostics = true;
bool m_diagnosticsInvalidated = false; bool m_diagnosticsInvalidated = false;
bool m_showTextMarkAnnotations = false; bool m_showTextMarkAnnotations = false;
QTimer m_textMarkDelay;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -143,7 +143,7 @@ bool ClangStaticAnalyzerPlugin::initialize(const QStringList &arguments, QString
}; };
RunControl::registerWorker<ClangStaticAnalyzerToolRunner> RunControl::registerWorker<ClangStaticAnalyzerToolRunner>
(Constants::CLANGSTATICANALYZER_RUN_MODE, constraint); (Constants::CLANGSTATICANALYZER_RUN_MODE, constraint, /*priority*/ -1);
return true; return true;
} }

View File

@@ -79,7 +79,9 @@ ClangStaticAnalyzerToolRunner::ClangStaticAnalyzerToolRunner(RunControl *runCont
RunConfiguration *runConfiguration = runControl->runConfiguration(); RunConfiguration *runConfiguration = runControl->runConfiguration();
auto tool = ClangStaticAnalyzerTool::instance(); auto tool = ClangStaticAnalyzerTool::instance();
tool->stopAction()->disconnect();
connect(tool->stopAction(), &QAction::triggered, runControl, &RunControl::initiateStop); connect(tool->stopAction(), &QAction::triggered, runControl, &RunControl::initiateStop);
tool->handleWorkerStart(this);
ProjectInfo projectInfoBeforeBuild = tool->projectInfoBeforeBuild(); ProjectInfo projectInfoBeforeBuild = tool->projectInfoBeforeBuild();
QTC_ASSERT(projectInfoBeforeBuild.isValid(), return); QTC_ASSERT(projectInfoBeforeBuild.isValid(), return);
@@ -495,10 +497,14 @@ void ClangStaticAnalyzerToolRunner::start()
m_success = false; m_success = false;
ClangStaticAnalyzerTool::instance()->onEngineIsStarting(); ClangStaticAnalyzerTool::instance()->onEngineIsStarting();
connect(runControl(), &RunControl::stopped, this, [this] {
ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success);
});
QTC_ASSERT(m_projectInfo.isValid(), reportFailure(); return); QTC_ASSERT(m_projectInfo.isValid(), reportFailure(); return);
const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath(); const Utils::FileName projectFile = m_projectInfo.project()->projectFilePath();
appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput()) appendMessage(tr("Running Clang Static Analyzer on %1").arg(projectFile.toUserOutput()),
+ QLatin1Char('\n'), Utils::NormalMessageFormat); Utils::NormalMessageFormat);
// Check clang executable // Check clang executable
bool isValidClangExecutable; bool isValidClangExecutable;
@@ -507,7 +513,7 @@ void ClangStaticAnalyzerToolRunner::start()
if (!isValidClangExecutable) { if (!isValidClangExecutable) {
const QString errorMessage = tr("Clang Static Analyzer: Invalid executable \"%1\", stop.") const QString errorMessage = tr("Clang Static Analyzer: Invalid executable \"%1\", stop.")
.arg(executable); .arg(executable);
appendMessage(errorMessage + QLatin1Char('\n'), Utils::ErrorMessageFormat); appendMessage(errorMessage, Utils::ErrorMessageFormat);
TaskHub::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup(); TaskHub::requestPopup();
reportFailure(); reportFailure();
@@ -522,7 +528,7 @@ void ClangStaticAnalyzerToolRunner::start()
= tr("Clang Static Analyzer: Running with possibly unsupported version, " = tr("Clang Static Analyzer: Running with possibly unsupported version, "
"could not determine version from executable \"%1\".") "could not determine version from executable \"%1\".")
.arg(versionCheckExecutable); .arg(versionCheckExecutable);
appendMessage(warningMessage + QLatin1Char('\n'), Utils::StdErrFormat); appendMessage(warningMessage, Utils::StdErrFormat);
TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup(); TaskHub::requestPopup();
} else if (!version.isSupportedVersion()) { } else if (!version.isSupportedVersion()) {
@@ -531,7 +537,7 @@ void ClangStaticAnalyzerToolRunner::start()
"supported version is %2.") "supported version is %2.")
.arg(version.toString()) .arg(version.toString())
.arg(ClangExecutableVersion::supportedVersionAsString()); .arg(ClangExecutableVersion::supportedVersionAsString());
appendMessage(warningMessage + QLatin1Char('\n'), Utils::StdErrFormat); appendMessage(warningMessage, Utils::StdErrFormat);
TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup(); TaskHub::requestPopup();
} }
@@ -544,7 +550,7 @@ void ClangStaticAnalyzerToolRunner::start()
if (!temporaryDir.isValid()) { if (!temporaryDir.isValid()) {
const QString errorMessage const QString errorMessage
= tr("Clang Static Analyzer: Failed to create temporary dir, stop."); = 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::addTask(Task::Error, errorMessage, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup(); TaskHub::requestPopup();
reportFailure(errorMessage); reportFailure(errorMessage);
@@ -599,15 +605,11 @@ void ClangStaticAnalyzerToolRunner::stop()
} }
m_runners.clear(); m_runners.clear();
m_unitsToProcess.clear(); m_unitsToProcess.clear();
appendMessage(tr("Clang Static Analyzer stopped by user.") + QLatin1Char('\n'), appendMessage(tr("Clang Static Analyzer stopped by user."),
Utils::NormalMessageFormat); Utils::NormalMessageFormat);
m_progress.reportFinished(); m_progress.reportFinished();
reportStopped();
}
void ClangStaticAnalyzerToolRunner::onFinished()
{
ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success); ClangStaticAnalyzerTool::instance()->onEngineFinished(m_success);
reportStopped();
} }
void ClangStaticAnalyzerToolRunner::analyzeNextFile() void ClangStaticAnalyzerToolRunner::analyzeNextFile()
@@ -629,7 +631,7 @@ void ClangStaticAnalyzerToolRunner::analyzeNextFile()
QTC_ASSERT(runner->run(unit.file, unit.arguments), return); QTC_ASSERT(runner->run(unit.file, unit.arguments), return);
appendMessage(tr("Analyzing \"%1\".").arg( appendMessage(tr("Analyzing \"%1\".").arg(
Utils::FileName::fromString(unit.file).toUserOutput()) + QLatin1Char('\n'), Utils::FileName::fromString(unit.file).toUserOutput()),
Utils::StdOutFormat); Utils::StdOutFormat);
} }
@@ -658,9 +660,8 @@ void ClangStaticAnalyzerToolRunner::onRunnerFinishedWithSuccess(const QString &l
if (!errorMessage.isEmpty()) { if (!errorMessage.isEmpty()) {
qCDebug(LOG) << "onRunnerFinishedWithSuccess: Error reading log file:" << errorMessage; qCDebug(LOG) << "onRunnerFinishedWithSuccess: Error reading log file:" << errorMessage;
const QString filePath = qobject_cast<ClangStaticAnalyzerRunner *>(sender())->filePath(); const QString filePath = qobject_cast<ClangStaticAnalyzerRunner *>(sender())->filePath();
appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage) appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage),
+ QLatin1Char('\n') Utils::StdErrFormat);
, Utils::StdErrFormat);
} else { } else {
++m_filesAnalyzed; ++m_filesAnalyzed;
if (!diagnostics.isEmpty()) if (!diagnostics.isEmpty())
@@ -679,9 +680,8 @@ void ClangStaticAnalyzerToolRunner::onRunnerFinishedWithFailure(const QString &e
++m_filesNotAnalyzed; ++m_filesNotAnalyzed;
m_success = false; m_success = false;
const QString filePath = qobject_cast<ClangStaticAnalyzerRunner *>(sender())->filePath(); const QString filePath = qobject_cast<ClangStaticAnalyzerRunner *>(sender())->filePath();
appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage) appendMessage(tr("Failed to analyze \"%1\": %2").arg(filePath, errorMessage),
+ QLatin1Char('\n') Utils::StdErrFormat);
, Utils::StdErrFormat);
appendMessage(errorDetails, Utils::StdErrFormat); appendMessage(errorDetails, Utils::StdErrFormat);
TaskHub::addTask(Task::Warning, errorMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::addTask(Task::Warning, errorMessage, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::addTask(Task::Warning, errorDetails, Debugger::Constants::ANALYZERTASK_ID); TaskHub::addTask(Task::Warning, errorDetails, Debugger::Constants::ANALYZERTASK_ID);
@@ -699,7 +699,7 @@ void ClangStaticAnalyzerToolRunner::handleFinished()
void ClangStaticAnalyzerToolRunner::onProgressCanceled() void ClangStaticAnalyzerToolRunner::onProgressCanceled()
{ {
m_progress.reportCanceled(); m_progress.reportCanceled();
stop(); runControl()->initiateStop();
} }
void ClangStaticAnalyzerToolRunner::updateProgressValue() void ClangStaticAnalyzerToolRunner::updateProgressValue()
@@ -711,9 +711,7 @@ void ClangStaticAnalyzerToolRunner::finalize()
{ {
appendMessage(tr("Clang Static Analyzer finished: " appendMessage(tr("Clang Static Analyzer finished: "
"Processed %1 files successfully, %2 failed.") "Processed %1 files successfully, %2 failed.")
.arg(m_filesAnalyzed) .arg(m_filesAnalyzed).arg(m_filesNotAnalyzed),
.arg(m_filesNotAnalyzed)
+ QLatin1Char('\n'),
Utils::NormalMessageFormat); Utils::NormalMessageFormat);
if (m_filesNotAnalyzed != 0) { if (m_filesNotAnalyzed != 0) {
@@ -723,7 +721,7 @@ void ClangStaticAnalyzerToolRunner::finalize()
} }
m_progress.reportFinished(); m_progress.reportFinished();
reportStopped(); runControl()->initiateStop();
} }
} // namespace Internal } // namespace Internal

View File

@@ -56,7 +56,6 @@ public:
void start() override; void start() override;
void stop() override; void stop() override;
void onFinished() override;
bool success() const { return m_success; } // For testing. bool success() const { return m_success; } // For testing.

View File

@@ -145,7 +145,6 @@ ClangStaticAnalyzerTool::ClangStaticAnalyzerTool()
{{ClangStaticAnalyzerDockId, m_diagnosticView, {}, Perspective::SplitVertical}} {{ClangStaticAnalyzerDockId, m_diagnosticView, {}, Perspective::SplitVertical}}
)); ));
//Debugger::registerAction(Constants::CLANGSTATICANALYZER_RUN_MODE, {});
action = new QAction(tr("Clang Static Analyzer"), this); action = new QAction(tr("Clang Static Analyzer"), this);
action->setToolTip(toolTip); action->setToolTip(toolTip);
menu->addAction(ActionManager::registerAction(action, "ClangStaticAnalyzer.Action"), menu->addAction(ActionManager::registerAction(action, "ClangStaticAnalyzer.Action"),
@@ -211,14 +210,12 @@ static bool dontStartAfterHintForDebugMode(Project *project)
return false; 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); QTC_ASSERT(project, emit finished(false); return);
if (dontStartAfterHintForDebugMode(project))
return;
Debugger::selectPerspective(ClangStaticAnalyzerPerspectiveId); Debugger::selectPerspective(ClangStaticAnalyzerPerspectiveId);
m_diagnosticModel->clear(); m_diagnosticModel->clear();
setBusyCursor(true); setBusyCursor(true);
@@ -230,8 +227,13 @@ void ClangStaticAnalyzerTool::startTool()
m_toolBusy = true; m_toolBusy = true;
updateRunActions(); 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); QTC_ASSERT(target, return);
DummyRunConfiguration *& rc = m_runConfigs[target]; DummyRunConfiguration *& rc = m_runConfigs[target];
if (!rc) { if (!rc) {
@@ -245,6 +247,9 @@ void ClangStaticAnalyzerTool::startTool()
connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, this, connect(SessionManager::instance(), &SessionManager::aboutToRemoveProject, this,
onProjectRemoved, Qt::UniqueConnection); onProjectRemoved, Qt::UniqueConnection);
} }
if (dontStartAfterHintForDebugMode(project))
return;
ProjectExplorerPlugin::runRunConfiguration(rc, Constants::CLANGSTATICANALYZER_RUN_MODE); ProjectExplorerPlugin::runRunConfiguration(rc, Constants::CLANGSTATICANALYZER_RUN_MODE);
} }

View File

@@ -58,9 +58,10 @@ public:
// For testing. // For testing.
QList<Diagnostic> diagnostics() const; QList<Diagnostic> diagnostics() const;
void startTool(); void startTool();
void handleWorkerStart(ProjectExplorer::RunWorker *runWorker);
void onEngineIsStarting(); void onEngineIsStarting();
void onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics); void onNewDiagnosticsAvailable(const QList<Diagnostic> &diagnostics);
void onEngineFinished(bool success); void onEngineFinished(bool success);

View File

@@ -79,7 +79,7 @@ public:
invalidateFilter(); invalidateFilter();
} }
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
{ {
if (!sourceParent.isValid()) if (!sourceParent.isValid())
return true; return true;
@@ -91,6 +91,21 @@ public:
return true; 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: private:
Core::Id m_platform; Core::Id m_platform;
}; };
@@ -101,18 +116,18 @@ class TwoLevelProxyModel : public QAbstractProxyModel
public: public:
TwoLevelProxyModel(QObject *parent = 0): QAbstractProxyModel(parent) {} 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)); QModelIndex ourModelIndex = sourceModel()->index(row, column, mapToSource(parent));
return createIndex(row, column, ourModelIndex.internalPointer()); return createIndex(row, column, ourModelIndex.internalPointer());
} }
QModelIndex parent(const QModelIndex &index) const QModelIndex parent(const QModelIndex &index) const override
{ {
return mapFromSource(mapToSource(index).parent()); 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()) if (index.isValid() && index.parent().isValid() && !index.parent().parent().isValid())
return 0; return 0;
@@ -120,19 +135,19 @@ public:
return sourceModel()->rowCount(mapToSource(index)); return sourceModel()->rowCount(mapToSource(index));
} }
int columnCount(const QModelIndex &index) const int columnCount(const QModelIndex &index) const override
{ {
return sourceModel()->columnCount(mapToSource(index)); return sourceModel()->columnCount(mapToSource(index));
} }
QModelIndex mapFromSource (const QModelIndex &index) const QModelIndex mapFromSource (const QModelIndex &index) const override
{ {
if (!index.isValid()) if (!index.isValid())
return QModelIndex(); return QModelIndex();
return createIndex(index.row(), index.column(), index.internalPointer()); return createIndex(index.row(), index.column(), index.internalPointer());
} }
QModelIndex mapToSource (const QModelIndex &index) const QModelIndex mapToSource (const QModelIndex &index) const override
{ {
if (!index.isValid()) if (!index.isValid())
return QModelIndex(); return QModelIndex();
@@ -148,7 +163,7 @@ public:
FancyTopLevelDelegate(QObject *parent = 0) FancyTopLevelDelegate(QObject *parent = 0)
: QItemDelegate(parent) {} : 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; QStyleOptionViewItem newoption = option;
if (!(option.state & QStyle::State_Enabled)) { if (!(option.state & QStyle::State_Enabled)) {
@@ -168,11 +183,10 @@ public:
QItemDelegate::drawDisplay(painter, newoption, rect, text); 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); QSize size = QItemDelegate::sizeHint(option, index);
size = size.expandedTo(QSize(0, ROW_HEIGHT)); size = size.expandedTo(QSize(0, ROW_HEIGHT));
return size; return size;

View File

@@ -483,6 +483,16 @@ void CompletionList::keyPressEvent(QKeyEvent *event)
return; return;
} }
break; 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); Utils::TreeView::keyPressEvent(event);
} }
@@ -795,9 +805,9 @@ void LocatorWidget::handleSearchFinished()
m_showProgressTimer.stop(); m_showProgressTimer.stop();
setProgressIndicatorVisible(false); setProgressIndicatorVisible(false);
m_updateRequested = false; m_updateRequested = false;
if (m_rowRequestedForAccept >= 0) { if (m_rowRequestedForAccept) {
acceptEntry(m_rowRequestedForAccept); acceptEntry(m_rowRequestedForAccept.value());
m_rowRequestedForAccept = -1; m_rowRequestedForAccept.reset();
return; return;
} }
if (m_entriesWatcher->future().isCanceled()) { if (m_entriesWatcher->future().isCanceled()) {
@@ -892,7 +902,7 @@ void LocatorWidget::addSearchResults(int firstIndex, int endIndex)
m_locatorModel->addEntries(entries); m_locatorModel->addEntries(entries);
if (selectFirst) { if (selectFirst) {
emit selectRow(0); emit selectRow(0);
if (m_rowRequestedForAccept >= 0) if (m_rowRequestedForAccept)
m_rowRequestedForAccept = 0; m_rowRequestedForAccept = 0;
} }
} }

View File

@@ -27,6 +27,8 @@
#include "locator.h" #include "locator.h"
#include <utils/optional.h>
#include <QPointer> #include <QPointer>
#include <QWidget> #include <QWidget>
@@ -99,9 +101,9 @@ private:
bool m_needsClearResult = true; bool m_needsClearResult = true;
bool m_updateRequested = false; bool m_updateRequested = false;
bool m_possibleToolTipRequest = false; bool m_possibleToolTipRequest = false;
int m_rowRequestedForAccept = -1;
QWidget *m_progressIndicator; QWidget *m_progressIndicator;
QTimer m_showProgressTimer; QTimer m_showProgressTimer;
Utils::optional<int> m_rowRequestedForAccept;
}; };
class LocatorPopup : public QWidget class LocatorPopup : public QWidget

View File

@@ -245,13 +245,19 @@ void CppEditorWidget::finalizeInitialization()
}); });
// Toolbar: '#' Button // Toolbar: '#' Button
d->m_preprocessorButton = new QToolButton(this); // TODO: Make "Additional Preprocessor Directives" also useful with Clang Code Model.
d->m_preprocessorButton->setText(QLatin1String("#")); if (!d->m_modelManager->isClangCodeModelActive()) {
Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG); d->m_preprocessorButton = new QToolButton(this);
connect(cmd, &Command::keySequenceChanged, this, &CppEditorWidget::updatePreprocessorButtonTooltip); d->m_preprocessorButton->setText(QLatin1String("#"));
updatePreprocessorButtonTooltip(); Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
connect(d->m_preprocessorButton, &QAbstractButton::clicked, this, &CppEditorWidget::showPreProcessorWidget); connect(cmd, &Command::keySequenceChanged,
insertExtraToolBarWidget(TextEditorWidget::Left, d->m_preprocessorButton); 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 // Toolbar: Actions to show minimized info bars
d->m_showInfoBarActions = MinimizableInfoBars::createShowInfoBarActions([this](QWidget *w) { d->m_showInfoBarActions = MinimizableInfoBars::createShowInfoBarActions([this](QWidget *w) {
@@ -429,13 +435,16 @@ bool CppEditorWidget::selectBlockDown()
void CppEditorWidget::updateWidgetHighlighting(QWidget *widget, bool highlight) void CppEditorWidget::updateWidgetHighlighting(QWidget *widget, bool highlight)
{ {
if (!widget)
return;
widget->setProperty("highlightWidget", highlight); widget->setProperty("highlightWidget", highlight);
widget->update(); widget->update();
} }
bool CppEditorWidget::isWidgetHighlighted(QWidget *widget) bool CppEditorWidget::isWidgetHighlighted(QWidget *widget)
{ {
return widget->property("highlightWidget").toBool(); return widget ? widget->property("highlightWidget").toBool() : false;
} }
void CppEditorWidget::renameSymbolUnderCursor() void CppEditorWidget::renameSymbolUnderCursor()
@@ -586,7 +595,9 @@ void CppEditorWidget::renameSymbolUnderCursorClang()
void CppEditorWidget::updatePreprocessorButtonTooltip() void CppEditorWidget::updatePreprocessorButtonTooltip()
{ {
QTC_ASSERT(d->m_preprocessorButton, return); if (!d->m_preprocessorButton)
return;
Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG); Command *cmd = ActionManager::command(Constants::OPEN_PREPROCESSOR_DIALOG);
QTC_ASSERT(cmd, return); QTC_ASSERT(cmd, return);
d->m_preprocessorButton->setToolTip(cmd->action()->toolTip()); d->m_preprocessorButton->setToolTip(cmd->action()->toolTip());

View File

@@ -201,12 +201,17 @@ void CppEditorDocument::onAboutToReload()
{ {
QTC_CHECK(!m_fileIsBeingReloaded); QTC_CHECK(!m_fileIsBeingReloaded);
m_fileIsBeingReloaded = true; m_fileIsBeingReloaded = true;
processor()->invalidateDiagnostics();
} }
void CppEditorDocument::onReloadFinished() void CppEditorDocument::onReloadFinished()
{ {
QTC_CHECK(m_fileIsBeingReloaded); QTC_CHECK(m_fileIsBeingReloaded);
m_fileIsBeingReloaded = false; m_fileIsBeingReloaded = false;
m_processorRevision = document()->revision();
processDocument();
} }
void CppEditorDocument::reparseWithPreferredParseContext(const QString &parseContextId) void CppEditorDocument::reparseWithPreferredParseContext(const QString &parseContextId)
@@ -250,6 +255,9 @@ void CppEditorDocument::onFilePathChanged(const Utils::FileName &oldPath,
void CppEditorDocument::scheduleProcessDocument() void CppEditorDocument::scheduleProcessDocument()
{ {
if (m_fileIsBeingReloaded)
return;
m_processorRevision = document()->revision(); m_processorRevision = document()->revision();
m_processorTimer.start(); m_processorTimer.start();
processor()->editorDocumentTimerRestarted(); processor()->editorDocumentTimerRestarted();

View File

@@ -56,6 +56,7 @@
#include <utils/fancylineedit.h> #include <utils/fancylineedit.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcfallthrough.h>
#include <QApplication> #include <QApplication>
#include <QComboBox> #include <QComboBox>
@@ -4119,7 +4120,7 @@ public:
break; break;
case FromReference: case FromReference:
removeReferenceOperator(changes); removeReferenceOperator(changes);
// fallthrough intended Q_FALLTHROUGH();
case FromVariable: case FromVariable:
convertToPointer(changes); convertToPointer(changes);
break; break;

View File

@@ -98,8 +98,12 @@ void CppUseSelectionsUpdater::update(CallType callType)
// QFuture::waitForFinished seems to block completely, not even // QFuture::waitForFinished seems to block completely, not even
// allowing to process events from QLocalSocket. // allowing to process events from QLocalSocket.
while (!future.isFinished()) while (!future.isFinished()) {
if (future.isCanceled())
return;
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
}
processResults(future.result()); processResults(future.result());
} }

View File

@@ -26,6 +26,7 @@
#include "compileroptionsbuilder.h" #include "compileroptionsbuilder.h"
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcfallthrough.h>
#include <QDir> #include <QDir>
#include <QRegularExpression> #include <QRegularExpression>
@@ -201,7 +202,8 @@ static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objc
if (!objcExt) { if (!objcExt) {
opts += QLatin1String("c++-header"); opts += QLatin1String("c++-header");
break; break;
} // else: fall-through! }
Q_FALLTHROUGH();
case ProjectFile::ObjCHeader: case ProjectFile::ObjCHeader:
case ProjectFile::ObjCXXHeader: case ProjectFile::ObjCXXHeader:
opts += QLatin1String("objective-c++-header"); opts += QLatin1String("objective-c++-header");
@@ -211,7 +213,8 @@ static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objc
if (!objcExt) { if (!objcExt) {
opts += QLatin1String("c"); opts += QLatin1String("c");
break; break;
} // else: fall-through! }
Q_FALLTHROUGH();
case ProjectFile::ObjCSource: case ProjectFile::ObjCSource:
opts += QLatin1String("objective-c"); opts += QLatin1String("objective-c");
break; break;
@@ -220,7 +223,8 @@ static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objc
if (!objcExt) { if (!objcExt) {
opts += QLatin1String("c++"); opts += QLatin1String("c++");
break; break;
} // else: fall-through! }
Q_FALLTHROUGH();
case ProjectFile::ObjCXXSource: case ProjectFile::ObjCXXSource:
opts += QLatin1String("objective-c++"); opts += QLatin1String("objective-c++");
break; break;

View File

@@ -71,8 +71,8 @@ class StartApplicationDialogPrivate
public: public:
KitChooser *kitChooser; KitChooser *kitChooser;
QLabel *serverPortLabel; QLabel *serverPortLabel;
QLabel *serverAddressLabel; QLabel *channelOverrideLabel;
QLineEdit *serverAddressEdit; QLineEdit *channelOverrideEdit;
QSpinBox *serverPortSpinBox; QSpinBox *serverPortSpinBox;
PathChooser *localExecutablePathChooser; PathChooser *localExecutablePathChooser;
FancyLineEdit *arguments; FancyLineEdit *arguments;
@@ -235,8 +235,11 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent)
d->serverPortSpinBox = new QSpinBox(this); d->serverPortSpinBox = new QSpinBox(this);
d->serverPortSpinBox->setRange(1, 65535); d->serverPortSpinBox->setRange(1, 65535);
d->serverAddressLabel = new QLabel(tr("Override server address"), this); d->channelOverrideLabel = new QLabel(tr("Override server channel:"), this);
d->serverAddressEdit = new QLineEdit(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 = new PathChooser(this);
d->localExecutablePathChooser->setExpectedKind(PathChooser::File); d->localExecutablePathChooser->setExpectedKind(PathChooser::File);
@@ -292,7 +295,6 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent)
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
formLayout->addRow(tr("&Kit:"), d->kitChooser); formLayout->addRow(tr("&Kit:"), d->kitChooser);
formLayout->addRow(d->serverPortLabel, d->serverPortSpinBox); formLayout->addRow(d->serverPortLabel, d->serverPortSpinBox);
formLayout->addRow(d->serverAddressLabel, d->serverAddressEdit);
formLayout->addRow(tr("Local &executable:"), d->localExecutablePathChooser); formLayout->addRow(tr("Local &executable:"), d->localExecutablePathChooser);
formLayout->addRow(tr("Command line &arguments:"), d->arguments); formLayout->addRow(tr("Command line &arguments:"), d->arguments);
formLayout->addRow(tr("&Working directory:"), d->workingDirectory); 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(tr("Break at \"&main\":"), d->breakAtMainCheckBox);
formLayout->addRow(d->serverStartScriptLabel, d->serverStartScriptPathChooser); formLayout->addRow(d->serverStartScriptLabel, d->serverStartScriptPathChooser);
formLayout->addRow(tr("Debug &information:"), d->debuginfoPathChooser); 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(line2);
formLayout->addRow(tr("&Recent:"), d->historyComboBox); formLayout->addRow(tr("&Recent:"), d->historyComboBox);
@@ -316,6 +323,9 @@ StartApplicationDialog::StartApplicationDialog(QWidget *parent)
connect(d->historyComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), connect(d->historyComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &StartApplicationDialog::historyIndexChanged); this, &StartApplicationDialog::historyIndexChanged);
connect(d->channelOverrideEdit, &QLineEdit::textChanged,
this, &StartApplicationDialog::onChannelOverrideChanged);
updateState(); 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) void StartApplicationDialog::historyIndexChanged(int index)
{ {
if (index < 0) if (index < 0)
@@ -379,8 +395,8 @@ bool StartApplicationDialog::run(QWidget *parent, DebuggerRunParameters *rp, Kit
dialog.d->serverStartScriptLabel->setVisible(false); dialog.d->serverStartScriptLabel->setVisible(false);
dialog.d->serverPortSpinBox->setVisible(false); dialog.d->serverPortSpinBox->setVisible(false);
dialog.d->serverPortLabel->setVisible(false); dialog.d->serverPortLabel->setVisible(false);
dialog.d->serverAddressLabel->setVisible(false); dialog.d->channelOverrideLabel->setVisible(false);
dialog.d->serverAddressEdit->setVisible(false); dialog.d->channelOverrideEdit->setVisible(false);
} }
if (dialog.exec() != QDialog::Accepted) if (dialog.exec() != QDialog::Accepted)
return false; return false;
@@ -404,7 +420,7 @@ bool StartApplicationDialog::run(QWidget *parent, DebuggerRunParameters *rp, Kit
} }
rp->inferior.executable = newParameters.runnable.executable; rp->inferior.executable = newParameters.runnable.executable;
const QString inputAddress = dialog.d->serverAddressEdit->text(); const QString inputAddress = dialog.d->channelOverrideEdit->text();
if (!inputAddress.isEmpty()) if (!inputAddress.isEmpty())
rp->remoteChannel = inputAddress; rp->remoteChannel = inputAddress;
else else
@@ -430,7 +446,7 @@ StartApplicationParameters StartApplicationDialog::parameters() const
{ {
StartApplicationParameters result; StartApplicationParameters result;
result.serverPort = d->serverPortSpinBox->value(); result.serverPort = d->serverPortSpinBox->value();
result.serverAddress = d->serverAddressEdit->text(); result.serverAddress = d->channelOverrideEdit->text();
result.runnable.executable = d->localExecutablePathChooser->path(); result.runnable.executable = d->localExecutablePathChooser->path();
result.serverStartScript = d->serverStartScriptPathChooser->path(); result.serverStartScript = d->serverStartScriptPathChooser->path();
result.kitId = d->kitChooser->currentKitId(); result.kitId = d->kitChooser->currentKitId();
@@ -447,7 +463,7 @@ void StartApplicationDialog::setParameters(const StartApplicationParameters &p)
{ {
d->kitChooser->setCurrentKitId(p.kitId); d->kitChooser->setCurrentKitId(p.kitId);
d->serverPortSpinBox->setValue(p.serverPort); d->serverPortSpinBox->setValue(p.serverPort);
d->serverAddressEdit->setText(p.serverAddress); d->channelOverrideEdit->setText(p.serverAddress);
d->localExecutablePathChooser->setPath(p.runnable.executable); d->localExecutablePathChooser->setPath(p.runnable.executable);
d->serverStartScriptPathChooser->setPath(p.serverStartScript); d->serverStartScriptPathChooser->setPath(p.serverStartScript);
d->debuginfoPathChooser->setPath(p.debugInfoLocation); d->debuginfoPathChooser->setPath(p.debugInfoLocation);

View File

@@ -80,6 +80,7 @@ private:
StartApplicationParameters parameters() const; StartApplicationParameters parameters() const;
void setParameters(const StartApplicationParameters &p); void setParameters(const StartApplicationParameters &p);
void setHistory(const QList<StartApplicationParameters> &l); void setHistory(const QList<StartApplicationParameters> &l);
void onChannelOverrideChanged(const QString &channel);
StartApplicationDialogPrivate *d; StartApplicationDialogPrivate *d;
}; };

View File

@@ -292,12 +292,6 @@ public:
} }
} }
void raiseApplication()
{
QTC_ASSERT(runControl(), return);
runControl()->bringApplicationToForeground();
}
void scheduleResetLocation() void scheduleResetLocation()
{ {
m_stackHandler.scheduleResetLocation(); m_stackHandler.scheduleResetLocation();
@@ -1323,7 +1317,7 @@ void DebuggerEngine::notifyInferiorPid(const ProcessHandle &pid)
showMessage(tr("Taking notice of pid %1").arg(pid.pid())); showMessage(tr("Taking notice of pid %1").arg(pid.pid()));
DebuggerStartMode sm = runParameters().startMode; DebuggerStartMode sm = runParameters().startMode;
if (sm == StartInternal || sm == StartExternal || sm == AttachExternal) if (sm == StartInternal || sm == StartExternal || sm == AttachExternal)
QTimer::singleShot(0, d, &DebuggerEnginePrivate::raiseApplication); d->m_inferiorPid.activate();
} }
} }

View File

@@ -421,18 +421,6 @@ namespace Internal {
void addCdbOptionPages(QList<IOptionsPage*> *opts); void addCdbOptionPages(QList<IOptionsPage*> *opts);
void addGdbOptionPages(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) static QIcon visibleStartIcon(Id id, bool toolBarStyle)
{ {
if (id == Id(Constants::DEBUG)) { if (id == Id(Constants::DEBUG)) {
@@ -1495,7 +1483,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
m_localsAndExpressionsWindow->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS)); m_localsAndExpressionsWindow->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS));
m_localsAndExpressionsWindow->setWindowTitle(m_localsWindow->windowTitle()); m_localsAndExpressionsWindow->setWindowTitle(m_localsWindow->windowTitle());
m_plugin->addAutoReleasedObject(new DebuggerRunControlFactory); RunConfiguration::registerAspect<DebuggerRunConfigurationAspect>();
// The main "Start Debugging" action. // The main "Start Debugging" action.
act = m_startAction = new QAction(this); act = m_startAction = new QAction(this);

View File

@@ -31,6 +31,7 @@
#include <debugger/debuggerstartparameters.h> #include <debugger/debuggerstartparameters.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcfallthrough.h>
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -102,7 +103,7 @@ void GdbAttachEngine::handleAttach(const DebuggerResponse &response)
notifyEngineIll(); notifyEngineIll();
break; break;
} }
// if msg != "ptrace: ..." fall through Q_FALLTHROUGH(); // if msg != "ptrace: ..."
default: default:
showStatusMessage(tr("Failed to attach to application: %1") showStatusMessage(tr("Failed to attach to application: %1")
.arg(QString(response.data["msg"].data()))); .arg(QString(response.data["msg"].data())));

View File

@@ -34,6 +34,7 @@
#include <coreplugin/messagebox.h> #include <coreplugin/messagebox.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/qtcfallthrough.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcprocess.h> #include <utils/qtcprocess.h>
@@ -367,7 +368,7 @@ void GdbRemoteServerEngine::handleAttach(const DebuggerResponse &response)
notifyInferiorSetupFailed(msgPtraceError(runParameters().startMode)); notifyInferiorSetupFailed(msgPtraceError(runParameters().startMode));
break; break;
} }
// if msg != "ptrace: ..." fall through Q_FALLTHROUGH(); // if msg != "ptrace: ..."
default: default:
notifyInferiorSetupFailed(response.data["msg"].data()); notifyInferiorSetupFailed(response.data["msg"].data());
} }

View File

@@ -327,7 +327,8 @@ void ModulesHandler::endUpdateAll()
if (!item->updated) if (!item->updated)
toDestroy.append(item); toDestroy.append(item);
}); });
qDeleteAll(toDestroy); for (TreeItem *item : toDestroy)
m_model->destroyItem(item);
} }
} // namespace Internal } // namespace Internal

View File

@@ -60,6 +60,7 @@
#include <utils/treemodel.h> #include <utils/treemodel.h>
#include <utils/basetreeview.h> #include <utils/basetreeview.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcfallthrough.h>
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
@@ -376,7 +377,7 @@ void QmlEngine::handleLauncherStarted()
{ {
// FIXME: The QmlEngine never calls notifyInferiorPid() triggering the // FIXME: The QmlEngine never calls notifyInferiorPid() triggering the
// raising, so do it here manually for now. // raising, so do it here manually for now.
runControl()->bringApplicationToForeground(); runControl()->applicationProcessHandle().activate();
d->noDebugOutputTimer.start(); d->noDebugOutputTimer.start();
} }
@@ -505,7 +506,7 @@ void QmlEngine::errorMessageBoxFinished(int result)
} }
case QMessageBox::Help: { case QMessageBox::Help: {
HelpManager::handleHelpRequest("qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html"); HelpManager::handleHelpRequest("qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html");
// fall through Q_FALLTHROUGH();
} }
default: default:
if (state() == InferiorRunOk) { if (state() == InferiorRunOk) {

View File

@@ -29,6 +29,8 @@
#include "watchutils.h" #include "watchutils.h"
#include "watchdata.h" #include "watchdata.h"
#include <utils/qtcfallthrough.h>
#include <QDebug> #include <QDebug>
#include <string.h> #include <string.h>
@@ -231,8 +233,10 @@ QString formatToolTipAddress(quint64 a)
switch (rc.size()) { switch (rc.size()) {
case 16: case 16:
rc.insert(12, colon); rc.insert(12, colon);
Q_FALLTHROUGH();
case 12: case 12:
rc.insert(8, colon); rc.insert(8, colon);
Q_FALLTHROUGH();
case 8: case 8:
rc.insert(4, colon); rc.insert(4, colon);
} }

View File

@@ -156,10 +156,12 @@ void DiffFilesController::reload()
void DiffFilesController::reloaded() 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); setDiffFiles(fileDataList);
reloadFinished(true); reloadFinished(success);
} }
void DiffFilesController::cancelReload() void DiffFilesController::cancelReload()

View File

@@ -36,17 +36,22 @@
#include "iosdsymbuildstep.h" #include "iosdsymbuildstep.h"
#include "iosqtversionfactory.h" #include "iosqtversionfactory.h"
#include "iosrunfactories.h" #include "iosrunfactories.h"
#include "iosrunner.h"
#include "iossettingspage.h" #include "iossettingspage.h"
#include "iossimulator.h" #include "iossimulator.h"
#include "iossimulatorfactory.h" #include "iossimulatorfactory.h"
#include "iostoolhandler.h" #include "iostoolhandler.h"
#include "iosrunconfiguration.h"
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/kitmanager.h> #include <projectexplorer/kitmanager.h>
#include <projectexplorer/runconfiguration.h>
#include <qtsupport/qtversionmanager.h> #include <qtsupport/qtversionmanager.h>
#include <QtPlugin> #include <QtPlugin>
#include <projectexplorer/devicesupport/devicemanager.h> using namespace ProjectExplorer;
namespace Ios { namespace Ios {
namespace Internal { namespace Internal {
@@ -67,7 +72,6 @@ bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage)
addAutoReleasedObject(new Internal::IosBuildConfigurationFactory); addAutoReleasedObject(new Internal::IosBuildConfigurationFactory);
addAutoReleasedObject(new Internal::IosToolChainFactory); addAutoReleasedObject(new Internal::IosToolChainFactory);
addAutoReleasedObject(new Internal::IosRunControlFactory);
addAutoReleasedObject(new Internal::IosRunConfigurationFactory); addAutoReleasedObject(new Internal::IosRunConfigurationFactory);
addAutoReleasedObject(new Internal::IosSettingsPage); addAutoReleasedObject(new Internal::IosSettingsPage);
addAutoReleasedObject(new Internal::IosQtVersionFactory); addAutoReleasedObject(new Internal::IosQtVersionFactory);
@@ -78,6 +82,17 @@ bool IosPlugin::initialize(const QStringList &arguments, QString *errorMessage)
addAutoReleasedObject(new Internal::IosDsymBuildStepFactory); addAutoReleasedObject(new Internal::IosDsymBuildStepFactory);
addAutoReleasedObject(new Internal::IosDeployConfigurationFactory); 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; return true;
} }

View File

@@ -27,7 +27,6 @@
#include "iosconstants.h" #include "iosconstants.h"
#include "iosrunconfiguration.h" #include "iosrunconfiguration.h"
#include "iosrunner.h"
#include "iosmanager.h" #include "iosmanager.h"
#include <debugger/analyzer/analyzermanager.h> #include <debugger/analyzer/analyzermanager.h>
@@ -143,53 +142,5 @@ RunConfiguration *IosRunConfigurationFactory::doRestore(Target *parent, const QV
return new IosRunConfiguration(parent, id, pathFromId(id)); 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 Internal
} // namespace Ios } // namespace Ios

View File

@@ -29,8 +29,6 @@
#include <qmakeprojectmanager/qmakerunconfigurationfactory.h> #include <qmakeprojectmanager/qmakerunconfigurationfactory.h>
namespace ProjectExplorer { namespace ProjectExplorer {
class RunControl;
class RunConfigWidget;
class Target; class Target;
class Node; class Node;
} // namespace ProjectExplorer } // namespace ProjectExplorer
@@ -68,20 +66,5 @@ private:
const QVariantMap &map) override; 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 Internal
} // namespace Ios } // namespace Ios

View File

@@ -74,9 +74,29 @@ using namespace Utils;
namespace Ios { namespace Ios {
namespace Internal { 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) IosRunner::IosRunner(RunControl *runControl)
: RunWorker(runControl) : RunWorker(runControl)
{ {
stopRunningRunControl(runControl);
auto runConfig = qobject_cast<IosRunConfiguration *>(runControl->runConfiguration()); auto runConfig = qobject_cast<IosRunConfiguration *>(runControl->runConfiguration());
m_bundleDir = runConfig->bundleDirectory().toString(); m_bundleDir = runConfig->bundleDirectory().toString();
m_arguments = QStringList(runConfig->commandLineArguments()); m_arguments = QStringList(runConfig->commandLineArguments());
@@ -513,10 +533,5 @@ void IosDebugSupport::start()
DebuggerRunTool::start(); DebuggerRunTool::start();
} }
void IosDebugSupport::onFinished()
{
abortDebugger();
}
} // namespace Internal } // namespace Internal
} // namespace Ios } // namespace Ios

View File

@@ -135,7 +135,6 @@ public:
private: private:
void start() override; void start() override;
void onFinished() override;
const QString m_dumperLib; const QString m_dumperLib;
IosRunner *m_runner; IosRunner *m_runner;

View File

@@ -33,6 +33,7 @@
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/qtcfallthrough.h>
#include "utils/runextensions.h" #include "utils/runextensions.h"
#include "utils/synchronousprocess.h" #include "utils/synchronousprocess.h"
@@ -606,7 +607,7 @@ void IosDeviceToolHandlerPrivate::subprocessHasData()
switch (state) { switch (state) {
case NonStarted: case NonStarted:
qCWarning(toolHandlerLog) << "IosToolHandler unexpected state in subprocessHasData: NonStarted"; qCWarning(toolHandlerLog) << "IosToolHandler unexpected state in subprocessHasData: NonStarted";
// pass Q_FALLTHROUGH();
case Starting: case Starting:
case StartedInferior: case StartedInferior:
// read some data // read some data
@@ -771,7 +772,7 @@ void IosDeviceToolHandlerPrivate::stop(int errorCode)
switch (oldState) { switch (oldState) {
case NonStarted: case NonStarted:
qCWarning(toolHandlerLog) << "IosToolHandler::stop() when state was NonStarted"; qCWarning(toolHandlerLog) << "IosToolHandler::stop() when state was NonStarted";
// pass Q_FALLTHROUGH();
case Starting: case Starting:
switch (op){ switch (op){
case OpNone: case OpNone:
@@ -786,7 +787,7 @@ void IosDeviceToolHandlerPrivate::stop(int errorCode)
case OpDeviceInfo: case OpDeviceInfo:
break; break;
} }
// pass Q_FALLTHROUGH();
case StartedInferior: case StartedInferior:
case XmlEndProcessed: case XmlEndProcessed:
toolExited(errorCode); toolExited(errorCode);

View File

@@ -420,7 +420,8 @@ void AppOutputPane::createNewOutputWindow(RunControl *rc)
if (tabIndex != -1) { if (tabIndex != -1) {
RunControlTab &tab = m_runControlTabs[tabIndex]; RunControlTab &tab = m_runControlTabs[tabIndex];
// Reuse this tab // Reuse this tab
delete tab.runControl; if (tab.runControl)
tab.runControl->initiateFinish();
tab.runControl = rc; tab.runControl = rc;
tab.window->setFormatter(rc ? rc->outputFormatter() : nullptr); tab.window->setFormatter(rc ? rc->outputFormatter() : nullptr);
@@ -559,7 +560,7 @@ bool AppOutputPane::closeTabs(CloseTabMode mode)
QList<RunControl *> AppOutputPane::allRunControls() const QList<RunControl *> AppOutputPane::allRunControls() const
{ {
return Utils::transform<QList>(m_runControlTabs,[](const RunControlTab &tab) { 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); m_tabWidget->removeTab(tabIndex);
delete m_runControlTabs[index].window; 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); m_runControlTabs.removeAt(index);
updateCloseActions(); updateCloseActions();

View File

@@ -25,6 +25,7 @@
#pragma once #pragma once
#include <QPointer>
#include <QVector> #include <QVector>
#include <coreplugin/ioutputpane.h> #include <coreplugin/ioutputpane.h>
@@ -124,7 +125,7 @@ private:
public: public:
explicit RunControlTab(RunControl *runControl = nullptr, explicit RunControlTab(RunControl *runControl = nullptr,
Core::OutputWindow *window = nullptr); Core::OutputWindow *window = nullptr);
RunControl *runControl; QPointer<RunControl> runControl;
Core::OutputWindow *window; Core::OutputWindow *window;
BehaviorOnOutput behaviorOnOutput = Flash; BehaviorOnOutput behaviorOnOutput = Flash;
}; };

View File

@@ -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 {}; return {};
} }

View File

@@ -48,7 +48,6 @@ namespace Utils { class ProcessHandle; }
namespace ProjectExplorer { namespace ProjectExplorer {
class RunControl; class RunControl;
class RunConfiguration; class RunConfiguration;
class IRunControlFactory;
class Project; class Project;
class Node; class Node;
class FolderNode; class FolderNode;

View File

@@ -489,5 +489,5 @@ void ProjectTreeWidgetFactory::restoreSettings(QSettings *settings, int position
const QString baseKey = QLatin1String("ProjectTreeWidget.") + QString::number(position); const QString baseKey = QLatin1String("ProjectTreeWidget.") + QString::number(position);
ptw->setProjectFilter(settings->value(baseKey + QLatin1String(".ProjectFilter"), false).toBool()); ptw->setProjectFilter(settings->value(baseKey + QLatin1String(".ProjectFilter"), false).toBool());
ptw->setGeneratedFilesFilter(settings->value(baseKey + QLatin1String(".GeneratedFilter"), true).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());
} }

View File

@@ -87,7 +87,7 @@ private:
QToolButton *m_toggleSync; QToolButton *m_toggleSync;
QString m_modelId; QString m_modelId;
bool m_autoSync = false; bool m_autoSync = true;
Utils::FileName m_delayedRename; Utils::FileName m_delayedRename;
static QList<ProjectTreeWidget *> m_projectTreeWidgets; static QList<ProjectTreeWidget *> m_projectTreeWidgets;

View File

@@ -183,13 +183,16 @@ void IRunConfigurationAspect::resetProjectToGlobalSettings()
for a target, but still be runnable via the output tab. for a target, but still be runnable via the output tab.
*/ */
static std::vector<RunConfiguration::AspectFactory> theAspectFactories;
RunConfiguration::RunConfiguration(Target *target, Core::Id id) : RunConfiguration::RunConfiguration(Target *target, Core::Id id) :
ProjectConfiguration(target, id) ProjectConfiguration(target, id)
{ {
Q_ASSERT(target); Q_ASSERT(target);
ctor(); ctor();
addExtraAspects(); for (const AspectFactory &factory : theAspectFactories)
addExtraAspect(factory(this));
} }
RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) : RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) :
@@ -209,10 +212,9 @@ RunConfiguration::~RunConfiguration()
qDeleteAll(m_aspects); qDeleteAll(m_aspects);
} }
void RunConfiguration::addExtraAspects() void RunConfiguration::addAspectFactory(const AspectFactory &aspectFactory)
{ {
foreach (IRunControlFactory *factory, ExtensionSystem::PluginManager::getObjects<IRunControlFactory>()) theAspectFactories.push_back(aspectFactory);
addExtraAspect(factory->createRunConfigurationAspect(this));
} }
void RunConfiguration::addExtraAspect(IRunConfigurationAspect *aspect) void RunConfiguration::addExtraAspect(IRunConfigurationAspect *aspect)
@@ -365,7 +367,7 @@ IRunConfigurationAspect *RunConfiguration::extraAspect(Core::Id id) const
A target specific \l RunConfiguration implementation can specify A target specific \l RunConfiguration implementation can specify
what information it considers necessary to execute a process 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 can use that information either unmodified or tweak it or ignore
it when setting up a RunControl. 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>; using WorkerFactories = std::vector<RunControl::WorkerFactory>;
static WorkerFactories &theWorkerFactories() static WorkerFactories &theWorkerFactories()
@@ -504,50 +483,13 @@ static WorkerFactories &theWorkerFactories()
bool RunControl::WorkerFactory::canRun(RunConfiguration *runConfiguration, Core::Id runMode) const bool RunControl::WorkerFactory::canRun(RunConfiguration *runConfiguration, Core::Id runMode) const
{ {
if (runMode != runMode) if (runMode != this->runMode)
return false; return false;
if (!constraint) if (!constraint)
return true; return true;
return constraint(runConfiguration); 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 \class ProjectExplorer::RunControl
\brief The RunControl class instances represent one item that is run. \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 { namespace Internal {
enum class RunWorkerState enum class RunWorkerState
@@ -592,7 +522,7 @@ static QString stateName(RunWorkerState s)
SN(RunWorkerState::Done) SN(RunWorkerState::Done)
SN(RunWorkerState::Failed) SN(RunWorkerState::Failed)
} }
return QLatin1String("<unknown>"); return QString("<unknown: %1>").arg(int(s));
# undef SN # undef SN
} }
@@ -606,7 +536,7 @@ public:
RunWorker *q; RunWorker *q;
RunWorkerState state = RunWorkerState::Initialized; RunWorkerState state = RunWorkerState::Initialized;
RunControl *runControl; QPointer<RunControl> runControl;
QList<RunWorker *> dependencies; QList<RunWorker *> dependencies;
QString id; QString id;
@@ -625,6 +555,8 @@ enum class RunControlState
Running, // All good and running. Running, // All good and running.
Stopping, // initiateStop() was called, stop application/tool Stopping, // initiateStop() was called, stop application/tool
Stopped, // all good, but stopped. Can possibly be re-started 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) static QString stateName(RunControlState s)
@@ -636,8 +568,10 @@ static QString stateName(RunControlState s)
SN(RunControlState::Running) SN(RunControlState::Running)
SN(RunControlState::Stopping) SN(RunControlState::Stopping)
SN(RunControlState::Stopped) SN(RunControlState::Stopped)
SN(RunControlState::Finishing)
SN(RunControlState::Finished)
} }
return QLatin1String("<unknown>"); return QString("<unknown: %1>").arg(int(s));
# undef SN # undef SN
} }
@@ -659,8 +593,11 @@ public:
~RunControlPrivate() ~RunControlPrivate()
{ {
QTC_CHECK(state == RunControlState::Stopped || state == RunControlState::Initialized); QTC_CHECK(state == RunControlState::Finished || state == RunControlState::Initialized);
disconnect();
q = nullptr;
qDeleteAll(m_workers); qDeleteAll(m_workers);
m_workers.clear();
delete outputFormatter; delete outputFormatter;
} }
@@ -675,7 +612,7 @@ public:
void initiateReStart(); void initiateReStart();
void continueStart(); void continueStart();
void initiateStop(); void initiateStop();
void continueStop(); void initiateFinish();
void onWorkerStarted(RunWorker *worker); void onWorkerStarted(RunWorker *worker);
void onWorkerStopped(RunWorker *worker); void onWorkerStopped(RunWorker *worker);
@@ -694,7 +631,7 @@ public:
Utils::Icon icon; Utils::Icon icon;
const QPointer<RunConfiguration> runConfiguration; // Not owned. const QPointer<RunConfiguration> runConfiguration; // Not owned.
QPointer<Project> project; // Not owned. QPointer<Project> project; // Not owned.
Utils::OutputFormatter *outputFormatter = nullptr; QPointer<Utils::OutputFormatter> outputFormatter = nullptr;
std::function<bool(bool*)> promptToStop; std::function<bool(bool*)> promptToStop;
std::vector<RunControl::WorkerFactory> m_factories; std::vector<RunControl::WorkerFactory> m_factories;
@@ -759,6 +696,11 @@ void RunControl::initiateStop()
d->initiateStop(); d->initiateStop();
} }
void RunControl::initiateFinish()
{
d->initiateFinish();
}
using WorkerCreators = QHash<Core::Id, RunControl::WorkerCreator>; using WorkerCreators = QHash<Core::Id, RunControl::WorkerCreator>;
static WorkerCreators &theWorkerCreators() static WorkerCreators &theWorkerCreators()
@@ -789,12 +731,22 @@ RunWorker *RunControl::createWorker(Core::Id id)
RunControl::WorkerCreator RunControl::producer(RunConfiguration *runConfiguration, Core::Id runMode) RunControl::WorkerCreator RunControl::producer(RunConfiguration *runConfiguration, Core::Id runMode)
{ {
for (const auto &factory : theWorkerFactories()) { WorkerFactories candidates;
if (factory.runMode == runMode for (const RunControl::WorkerFactory &factory : theWorkerFactories()) {
&& (!factory.constraint || factory.constraint(runConfiguration))) if (factory.canRun(runConfiguration, runMode))
return factory.producer; candidates.push_back(factory);
} }
return {};
if (candidates.empty())
return {};
RunControl::WorkerFactory bestFactory = *candidates.begin();
for (const RunControl::WorkerFactory &factory : candidates) {
if (factory.priority > bestFactory.priority)
bestFactory = factory;
}
return bestFactory.producer;
} }
void RunControl::addWorkerFactory(const RunControl::WorkerFactory &workerFactory) void RunControl::addWorkerFactory(const RunControl::WorkerFactory &workerFactory)
@@ -880,15 +832,8 @@ void RunControlPrivate::initiateStop()
{ {
checkState(RunControlState::Running); checkState(RunControlState::Running);
setState(RunControlState::Stopping); setState(RunControlState::Stopping);
debugMessage("Queue: Stopping"); debugMessage("Queue: Stopping for all workers");
continueStop();
}
void RunControlPrivate::continueStop()
{
debugMessage("Continue Stopping");
checkState(RunControlState::Stopping);
bool allDone = true; bool allDone = true;
for (RunWorker *worker : m_workers) { for (RunWorker *worker : m_workers) {
if (worker) { if (worker) {
@@ -904,17 +849,17 @@ void RunControlPrivate::continueStop()
allDone = false; allDone = false;
break; break;
case RunWorkerState::Starting: case RunWorkerState::Starting:
worker->d->state = RunWorkerState::Stopping;
debugMessage(" " + workerId + " was Starting, queuing stop"); debugMessage(" " + workerId + " was Starting, queuing stop");
allDone = false; worker->d->state = RunWorkerState::Stopping;
QTimer::singleShot(0, worker, &RunWorker::initiateStop); QTimer::singleShot(0, worker, &RunWorker::initiateStop);
return; // Sic. allDone = false;
break;
case RunWorkerState::Running: case RunWorkerState::Running:
debugMessage(" " + workerId + " was Running, queuing stop"); debugMessage(" " + workerId + " was Running, queuing stop");
worker->d->state = RunWorkerState::Stopping; worker->d->state = RunWorkerState::Stopping;
allDone = false; allDone = false;
QTimer::singleShot(0, worker, &RunWorker::initiateStop); QTimer::singleShot(0, worker, &RunWorker::initiateStop);
return; // Sic. break;
case RunWorkerState::Done: case RunWorkerState::Done:
debugMessage(" " + workerId + " was Done. Good."); debugMessage(" " + workerId + " was Done. Good.");
break; break;
@@ -927,8 +872,59 @@ void RunControlPrivate::continueStop()
} }
} }
if (allDone) { if (allDone) {
debugMessage("All workers stopped. Set runControl to Stopped"); debugMessage("All stopped.");
setState(RunControlState::Stopped); setState(RunControlState::Stopped);
} else {
debugMessage("Not all workers stopped. Waiting...");
}
}
void RunControlPrivate::initiateFinish()
{
setState(RunControlState::Finishing);
debugMessage("Ramping down");
bool allDone = true;
for (RunWorker *worker : m_workers) {
if (worker) {
const QString &workerId = worker->d->id;
debugMessage(" Examining worker " + workerId);
switch (worker->d->state) {
case RunWorkerState::Initialized:
debugMessage(" " + workerId + " was Initialized, setting to Done");
worker->d->state = RunWorkerState::Done;
break;
case RunWorkerState::Stopping:
debugMessage(" " + workerId + " was already Stopping. Keeping it that way");
allDone = false;
break;
case RunWorkerState::Starting:
debugMessage(" " + workerId + " was Starting, queuing stop");
worker->d->state = RunWorkerState::Stopping;
QTimer::singleShot(0, worker, &RunWorker::initiateStop);
allDone = false;
break;
case RunWorkerState::Running:
debugMessage(" " + workerId + " was Running, queuing stop");
worker->d->state = RunWorkerState::Stopping;
allDone = false;
QTimer::singleShot(0, worker, &RunWorker::initiateStop);
break;
case RunWorkerState::Done:
debugMessage(" " + workerId + " was Done. Good.");
break;
case RunWorkerState::Failed:
debugMessage(" " + workerId + " was Failed. Good");
break;
}
} else {
debugMessage("Found unknown deleted worker");
}
}
if (allDone) {
setState(RunControlState::Finished);
} else {
debugMessage("Not all workers finished. Waiting...");
} }
} }
@@ -944,7 +940,6 @@ void RunControlPrivate::onWorkerStarted(RunWorker *worker)
showError(tr("Unexpected run control state %1 when worker %2 started") showError(tr("Unexpected run control state %1 when worker %2 started")
.arg(stateName(state)) .arg(stateName(state))
.arg(worker->d->id)); .arg(worker->d->id));
//setState(RunControlState::Stopped);
} }
void RunControlPrivate::onWorkerFailed(RunWorker *worker, const QString &msg) void RunControlPrivate::onWorkerFailed(RunWorker *worker, const QString &msg)
@@ -968,13 +963,72 @@ void RunControlPrivate::onWorkerStopped(RunWorker *worker)
worker->d->state = RunWorkerState::Done; worker->d->state = RunWorkerState::Done;
debugMessage(workerId + " stopped expectedly."); debugMessage(workerId + " stopped expectedly.");
break; break;
case RunWorkerState::Done:
worker->d->state = RunWorkerState::Done;
debugMessage(workerId + " stopped twice. Huh? But harmless.");
return; // Sic!
default: default:
debugMessage(workerId + " stopped unexpectedly in state" debugMessage(workerId + " stopped unexpectedly in state"
+ stateName(worker->d->state)); + stateName(worker->d->state));
worker->d->state = RunWorkerState::Failed; worker->d->state = RunWorkerState::Failed;
break; 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) void RunControlPrivate::showError(const QString &msg)
@@ -1175,15 +1229,23 @@ bool RunControlPrivate::isAllowedTransition(RunControlState from, RunControlStat
{ {
switch (from) { switch (from) {
case RunControlState::Initialized: case RunControlState::Initialized:
return to == RunControlState::Starting; return to == RunControlState::Starting
|| to == RunControlState::Finishing;
case RunControlState::Starting: case RunControlState::Starting:
return to == RunControlState::Running; return to == RunControlState::Running
|| to == RunControlState::Finishing;
case RunControlState::Running: case RunControlState::Running:
return to == RunControlState::Stopping return to == RunControlState::Stopping
|| to == RunControlState::Stopped; || to == RunControlState::Stopped
|| to == RunControlState::Finishing;
case RunControlState::Stopping: case RunControlState::Stopping:
return to == RunControlState::Stopped; return to == RunControlState::Stopped
|| to == RunControlState::Finishing;
case RunControlState::Stopped: case RunControlState::Stopped:
return to == RunControlState::Finishing;
case RunControlState::Finishing:
return to == RunControlState::Finished;
case RunControlState::Finished:
return false; return false;
} }
return false; return false;
@@ -1213,11 +1275,13 @@ void RunControlPrivate::setState(RunControlState newState)
break; break;
case RunControlState::Stopped: case RunControlState::Stopped:
q->setApplicationProcessHandle(Utils::ProcessHandle()); q->setApplicationProcessHandle(Utils::ProcessHandle());
foreach (auto worker, m_workers)
if (worker)
worker->onFinished();
emit q->stopped(); emit q->stopped();
break; break;
case RunControlState::Finished:
emit q->finished();
debugMessage("All finished. Deleting myself");
deleteLater();
break;
default: default:
break; break;
} }
@@ -1228,18 +1292,6 @@ void RunControlPrivate::debugMessage(const QString &msg)
qCDebug(statesLog()) << 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) void RunControl::appendMessage(const QString &msg, Utils::OutputFormat format)
{ {
emit appendMessageRequested(this, msg, format); emit appendMessageRequested(this, msg, format);
@@ -1358,8 +1410,9 @@ void SimpleTargetRunner::stop()
void SimpleTargetRunner::onProcessStarted() void SimpleTargetRunner::onProcessStarted()
{ {
// Console processes only know their pid after being started // Console processes only know their pid after being started
runControl()->setApplicationProcessHandle(m_launcher.applicationPID()); ProcessHandle pid = m_launcher.applicationPID();
runControl()->bringApplicationToForeground(); runControl()->setApplicationProcessHandle(pid);
pid.activate();
reportStarted(); reportStarted();
} }

View File

@@ -245,6 +245,12 @@ public:
static RunConfiguration *startupRunConfiguration(); static RunConfiguration *startupRunConfiguration();
using AspectFactory = std::function<IRunConfigurationAspect *(RunConfiguration *)>;
template <class T> static void registerAspect()
{
addAspectFactory([](RunConfiguration *rc) { return new T(rc); });
}
signals: signals:
void enabledChanged(); void enabledChanged();
void requestRunActionsUpdate(); void requestRunActionsUpdate();
@@ -260,7 +266,7 @@ protected:
private: private:
void ctor(); void ctor();
void addExtraAspects(); static void addAspectFactory(const AspectFactory &aspectFactory);
QList<IRunConfigurationAspect *> m_aspects; QList<IRunConfigurationAspect *> m_aspects;
}; };
@@ -295,22 +301,6 @@ private:
virtual RunConfiguration *doRestore(Target *parent, const QVariantMap &map) = 0; 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 class PROJECTEXPLORER_EXPORT RunConfigWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
@@ -397,6 +387,7 @@ public:
void initiateStart(); void initiateStart();
void initiateReStart(); void initiateReStart();
void initiateStop(); void initiateStop();
void initiateFinish();
bool promptToStop(bool *optionalPrompt = nullptr) const; bool promptToStop(bool *optionalPrompt = nullptr) const;
void setPromptToStop(const std::function<bool(bool *)> &promptToStop); void setPromptToStop(const std::function<bool(bool *)> &promptToStop);
@@ -430,7 +421,6 @@ public:
void setRunnable(const Runnable &runnable); void setRunnable(const Runnable &runnable);
virtual void appendMessage(const QString &msg, Utils::OutputFormat format); virtual void appendMessage(const QString &msg, Utils::OutputFormat format);
virtual void bringApplicationToForeground();
static bool showPromptToStopDialog(const QString &title, const QString &text, static bool showPromptToStopDialog(const QString &title, const QString &text,
const QString &stopButtonText = QString(), const QString &stopButtonText = QString(),
@@ -450,24 +440,28 @@ public:
addWorkerFactory({runMode, constraint, producer}); addWorkerFactory({runMode, constraint, producer});
} }
template <class Worker> 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); }; auto producer = [](RunControl *rc) { return new Worker(rc); };
addWorkerFactory({runMode, constraint, producer}); addWorkerFactory({runMode, constraint, producer, priority});
} }
template <class Config, class Worker> 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 constraint = [](RunConfiguration *runConfig) { return qobject_cast<Config *>(runConfig); };
auto producer = [](RunControl *rc) { return new Worker(rc); }; auto producer = [](RunControl *rc) { return new Worker(rc); };
addWorkerFactory({runMode, constraint, producer}); addWorkerFactory({runMode, constraint, producer, priority});
} }
struct WorkerFactory { struct WorkerFactory {
Core::Id runMode; Core::Id runMode;
Constraint constraint; Constraint constraint;
WorkerCreator producer; 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; bool canRun(RunConfiguration *runConfiguration, Core::Id runMode) const;
}; };
@@ -479,6 +473,7 @@ signals:
void aboutToStart(); void aboutToStart();
void started(); void started();
void stopped(); void stopped();
void finished();
void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle
private: private:

View File

@@ -44,6 +44,7 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcfallthrough.h>
namespace QmlDesigner { namespace QmlDesigner {
@@ -358,6 +359,7 @@ bool FormEditorScene::event(QEvent * event)
currentTool()->keyPressEvent(static_cast<QKeyEvent*>(event)); currentTool()->keyPressEvent(static_cast<QKeyEvent*>(event));
return true; return true;
} }
Q_FALLTHROUGH();
default: return QGraphicsScene::event(event); default: return QGraphicsScene::event(event);
} }

View File

@@ -1029,9 +1029,9 @@ bool NodeMetaInfoPrivate::cleverCheckType(const TypeName &otherType) const
return typeName == convertedName.toUtf8(); 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") if (typeName == "string")
return QVariant::String; return QVariant::String;

View File

@@ -76,16 +76,6 @@ namespace Internal {
Q_GLOBAL_STATIC(QmlProfilerSettings, qmlProfilerGlobalSettings) 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) bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorString)
{ {
Q_UNUSED(arguments) Q_UNUSED(arguments)
@@ -101,7 +91,8 @@ void QmlProfilerPlugin::extensionsInitialized()
(void) new QmlProfilerTool(this); (void) new QmlProfilerTool(this);
addAutoReleasedObject(new QmlProfilerOptionsPage); addAutoReleasedObject(new QmlProfilerOptionsPage);
addAutoReleasedObject(new QmlProfilerRunControlFactory);
RunConfiguration::registerAspect<QmlProfilerRunConfigurationAspect>();
auto constraint = [](RunConfiguration *runConfiguration) { auto constraint = [](RunConfiguration *runConfiguration) {
Target *target = runConfiguration ? runConfiguration->target() : nullptr; Target *target = runConfiguration ? runConfiguration->target() : nullptr;

View File

@@ -69,6 +69,8 @@
#include <qtsupport/qtkitinformation.h> #include <qtsupport/qtkitinformation.h>
#include <utils/qtcfallthrough.h>
#include <QApplication> #include <QApplication>
#include <QDockWidget> #include <QDockWidget>
#include <QFileDialog> #include <QFileDialog>
@@ -387,6 +389,7 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
case QMessageBox::Help: case QMessageBox::Help:
HelpManager::handleHelpRequest( HelpManager::handleHelpRequest(
"qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html"); "qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html");
Q_FALLTHROUGH();
case QMessageBox::Cancel: case QMessageBox::Cancel:
// The actual error message has already been logged. // The actual error message has already been logged.
logState(tr("Failed to connect.")); logState(tr("Failed to connect."));

View File

@@ -53,6 +53,7 @@
// Needed for the load&save actions in the context menu // Needed for the load&save actions in the context menu
#include <debugger/analyzer/analyzermanager.h> #include <debugger/analyzer/analyzermanager.h>
#include <coreplugin/findplaceholder.h> #include <coreplugin/findplaceholder.h>
#include <utils/qtcfallthrough.h>
#include <utils/styledbar.h> #include <utils/styledbar.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
@@ -103,7 +104,7 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManag
qint64 end = modelManager->traceTime()->endTime(); qint64 end = modelManager->traceTime()->endTime();
d->m_zoomControl->setTrace(start, end); d->m_zoomControl->setTrace(start, end);
d->m_zoomControl->setRange(start, start + (end - start) / 10); d->m_zoomControl->setRange(start, start + (end - start) / 10);
// Fall through Q_FALLTHROUGH();
} }
case QmlProfilerModelManager::Empty: case QmlProfilerModelManager::Empty:
d->m_modelProxy->setModels(d->m_suspendedModels); d->m_modelProxy->setModels(d->m_suspendedModels);
@@ -116,7 +117,7 @@ QmlProfilerTraceView::QmlProfilerTraceView(QWidget *parent, QmlProfilerViewManag
d->m_zoomControl->clear(); d->m_zoomControl->clear();
if (!d->m_suspendedModels.isEmpty()) if (!d->m_suspendedModels.isEmpty())
break; // Models are suspended already. AcquiringData was aborted. break; // Models are suspended already. AcquiringData was aborted.
// Fall through Q_FALLTHROUGH();
case QmlProfilerModelManager::AcquiringData: case QmlProfilerModelManager::AcquiringData:
// Temporarily remove the models, while we're changing them // Temporarily remove the models, while we're changing them
d->m_suspendedModels = d->m_modelProxy->models(); d->m_suspendedModels = d->m_modelProxy->models();

View File

@@ -27,6 +27,8 @@
#include "scxmldocument.h" #include "scxmldocument.h"
#include "scxmltag.h" #include "scxmltag.h"
#include <utils/qtcfallthrough.h>
#include <QMimeData> #include <QMimeData>
#include <QUndoStack> #include <QUndoStack>
@@ -245,6 +247,7 @@ Qt::ItemFlags StructureModel::flags(const QModelIndex &index) const
case Final: case Final:
case History: case History:
defaultFlags |= Qt::ItemIsDragEnabled; defaultFlags |= Qt::ItemIsDragEnabled;
Q_FALLTHROUGH();
case Scxml: case Scxml:
defaultFlags |= Qt::ItemIsDropEnabled; defaultFlags |= Qt::ItemIsDropEnabled;
break; break;

View File

@@ -3821,7 +3821,7 @@ void TextEditorWidgetPrivate::drawLineAnnotation(QPainter &painter, const QTextB
QRectF annotationRect(x, lineRect.top(), q->viewport()->width() - x, lineRect.height()); QRectF annotationRect(x, lineRect.top(), q->viewport()->width() - x, lineRect.height());
if (annotationRect.width() <= 0) if (annotationRect.width() <= 0)
break; break;
mark->paintAnnotation(&painter, &annotationRect, q->fontMetrics()); mark->paintAnnotation(&painter, &annotationRect);
x += annotationRect.width() + itemOffset; x += annotationRect.width() + itemOffset;
m_annotationRects[block.blockNumber()].append({annotationRect, mark}); m_annotationRects[block.blockNumber()].append({annotationRect, mark});
} }

View File

@@ -123,42 +123,52 @@ void TextMark::paintIcon(QPainter *painter, const QRect &rect) const
m_icon.paint(painter, rect, Qt::AlignCenter); m_icon.paint(painter, rect, Qt::AlignCenter);
} }
void TextMark::paintAnnotation(QPainter *painter, void TextMark::paintAnnotation(QPainter *painter, QRectF *annotationRect) const
QRectF *annotationRect,
const QFontMetrics &fm) const
{ {
QString text = lineAnnotation(); QString text = lineAnnotation();
if (text.isEmpty()) if (text.isEmpty())
return; return;
const bool drawIcon = !m_icon.isNull(); const AnnotationRects &rects = annotationRects(*annotationRect, painter->fontMetrics());
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 QColor markColor = m_hasColor ? Utils::creatorTheme()->color(m_color).toHsl() const QColor markColor = m_hasColor ? Utils::creatorTheme()->color(m_color).toHsl()
: painter->pen().color(); : painter->pen().color();
const AnnotationColors &colors = const AnnotationColors &colors =
AnnotationColors::getAnnotationColors(markColor, painter->background().color()); AnnotationColors::getAnnotationColors(markColor, painter->background().color());
painter->save(); painter->save();
annotationRect->setWidth(annotationWidth);
painter->setPen(colors.rectColor); painter->setPen(colors.rectColor);
painter->setBrush(colors.rectColor); painter->setBrush(colors.rectColor);
painter->drawRect(*annotationRect); painter->drawRect(rects.annotationRect);
painter->setPen(colors.textColor); painter->setPen(colors.textColor);
if (drawIcon) { paintIcon(painter, rects.iconRect.toAlignedRect());
paintIcon(painter, annotationRect->adjusted( painter->drawText(rects.textRect, Qt::AlignLeft, rects.text);
margin, margin, -(textWidth + 2 * margin), -margin).toAlignedRect());
}
painter->drawText(annotationRect->adjusted(iconWidth, 0, 0, 0), Qt::AlignLeft, text);
painter->restore(); painter->restore();
*annotationRect = rects.annotationRect;
}
TextMark::AnnotationRects TextMark::annotationRects(const QRectF &boundingRect,
const QFontMetrics &fm) const
{
AnnotationRects rects;
rects.annotationRect = boundingRect;
rects.text = lineAnnotation();
const bool drawIcon = !m_icon.isNull();
constexpr qreal margin = 1;
rects.iconRect = QRectF(boundingRect.left() + margin, boundingRect.top() + margin, 0, 0);
if (drawIcon) {
rects.iconRect.setHeight(boundingRect.height() - 2 * margin);
rects.iconRect.setWidth(rects.iconRect.height() * m_widthFactor);
}
rects.textRect = QRectF(rects.iconRect.right() + margin, boundingRect.top(),
qreal(fm.width(rects.text)), boundingRect.height());
rects.annotationRect.setRight(rects.textRect.right() + margin);
if (rects.annotationRect.right() > boundingRect.right()) {
rects.textRect.setRight(boundingRect.right() - margin);
rects.text = fm.elidedText(rects.text, Qt::ElideRight, int(rects.textRect.width()));
rects.annotationRect.setRight(boundingRect.right());
}
return rects;
} }
void TextMark::updateLineNumber(int lineNumber) void TextMark::updateLineNumber(int lineNumber)

View File

@@ -64,7 +64,15 @@ public:
int lineNumber() const; int lineNumber() const;
virtual void paintIcon(QPainter *painter, const QRect &rect) 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 /// called if the filename of the document changed
virtual void updateFileName(const QString &fileName); virtual void updateFileName(const QString &fileName);
virtual void updateLineNumber(int lineNumber); virtual void updateLineNumber(int lineNumber);

View File

@@ -562,6 +562,7 @@ RunWorker *MemcheckTool::createRunWorker(RunControl *runControl)
connect(runTool, &MemcheckToolRunner::internalParserError, this, &MemcheckTool::internalParserError); connect(runTool, &MemcheckToolRunner::internalParserError, this, &MemcheckTool::internalParserError);
connect(runTool, &MemcheckToolRunner::stopped, this, &MemcheckTool::engineFinished); connect(runTool, &MemcheckToolRunner::stopped, this, &MemcheckTool::engineFinished);
m_stopAction->disconnect();
connect(m_stopAction, &QAction::triggered, runControl, &RunControl::initiateStop); connect(m_stopAction, &QAction::triggered, runControl, &RunControl::initiateStop);
m_toolBusy = true; m_toolBusy = true;

View File

@@ -106,7 +106,6 @@ void ValgrindToolRunner::stop()
{ {
m_isStopping = true; m_isStopping = true;
m_runner.stop(); m_runner.stop();
reportStopped(); // FIXME: Restrict to non-running scenarios?
} }
QString ValgrindToolRunner::executable() const QString ValgrindToolRunner::executable() const

View File

@@ -110,15 +110,6 @@ public:
} }
}; };
class ValgrindRunControlFactory : public IRunControlFactory
{
public:
IRunConfigurationAspect *createRunConfigurationAspect(RunConfiguration *rc) override
{
return new ValgrindRunConfigurationAspect(rc);
}
};
ValgrindPlugin::~ValgrindPlugin() ValgrindPlugin::~ValgrindPlugin()
{ {
delete theGlobalSettings; delete theGlobalSettings;
@@ -131,7 +122,8 @@ bool ValgrindPlugin::initialize(const QStringList &, QString *)
theGlobalSettings->readSettings(); theGlobalSettings->readSettings();
addAutoReleasedObject(new ValgrindOptionsPage); addAutoReleasedObject(new ValgrindOptionsPage);
addAutoReleasedObject(new ValgrindRunControlFactory);
RunConfiguration::registerAspect<ValgrindRunConfigurationAspect>();
return true; return true;
} }

View File

@@ -29,6 +29,7 @@
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/qtcfallthrough.h>
#include <QSettings> #include <QSettings>
#include <QVariant> #include <QVariant>
@@ -56,6 +57,7 @@ public:
switch (v.type()) { switch (v.type()) {
case QVariant::UInt: case QVariant::UInt:
m_type = QVariant::Int; m_type = QVariant::Int;
Q_FALLTHROUGH();
case QVariant::Int: case QVariant::Int:
m_comp.intValue = v.toInt(); m_comp.intValue = v.toInt();
break; break;

View File

@@ -48,6 +48,37 @@ static void readPatch(QFutureInterface<QList<FileData>> &futureInterface,
futureInterface.reportResult(fileDataList); 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 class VcsBaseDiffEditorControllerPrivate
{ {
public: public:
@@ -59,6 +90,7 @@ public:
void processingFinished(); void processingFinished();
void processDiff(const QString &patch); void processDiff(const QString &patch);
void cancelReload(); void cancelReload();
void storeOutput(const QString &output);
void commandFinished(bool success); void commandFinished(bool success);
VcsBaseDiffEditorController *q; VcsBaseDiffEditorController *q;
@@ -67,18 +99,43 @@ public:
QString m_startupFile; QString m_startupFile;
QString m_output; QString m_output;
QPointer<VcsCommand> m_command; 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, VcsBaseClientImpl *client,
const QString &workingDirectory) const QString &workingDirectory)
: q(controller) : q(controller)
, m_client(client) , m_client(client)
, m_directory(workingDirectory) , m_directory(workingDirectory)
{ {
QObject::connect(&m_processWatcher, &QFutureWatcher<QList<FileData>>::finished, q,
[this] () { processingFinished(); });
} }
VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate() VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate()
@@ -88,9 +145,18 @@ VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate()
void VcsBaseDiffEditorControllerPrivate::processingFinished() 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 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->setDiffFiles(fileDataList, q->workingDirectory(), q->startupFile());
q->reloadFinished(success); q->reloadFinished(success);
@@ -98,39 +164,67 @@ void VcsBaseDiffEditorControllerPrivate::processingFinished()
void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch) void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch)
{ {
m_processWatcher.setFuture(Utils::runAsync(&readPatch, patch)); cancelReload();
ProgressManager::addTask(m_processWatcher.future(), m_processWatcher = new QFutureWatcher<QList<FileData>>();
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() void VcsBaseDiffEditorControllerPrivate::cancelReload()
{ {
if (m_command) { if (m_command) {
m_command->disconnect();
m_command->cancel(); m_command->cancel();
m_command.clear(); m_command.clear();
} }
if (m_processWatcher.future().isRunning()) { // Disconnect effectively, don't deliver already posted signals
m_processWatcher.future().cancel(); if (m_commandResultProxy)
m_processWatcher.setFuture(QFuture<QList<FileData>>()); 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(); m_output = QString();
} }
void VcsBaseDiffEditorControllerPrivate::storeOutput(const QString &output)
{
m_output = output;
}
void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success) void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success)
{ {
if (m_command) if (m_command)
m_command.clear(); 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) { if (!success) {
cancelReload(); cancelReload();
q->reloadFinished(success); q->reloadFinished(success);
return; 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) 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->cancelReload();
d->m_command = new VcsCommand(workingDirectory(), d->m_client->processEnvironment()); d->m_command = new VcsCommand(workingDirectory(), d->m_client->processEnvironment());
d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec()); d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec());
connect(d->m_command.data(), &VcsCommand::stdOutText, this, d->m_commandResultProxy = new VcsCommandResultProxy(d->m_command.data(), d);
[this] (const QString &output) { d->m_output = output; });
connect(d->m_command.data(), &VcsCommand::finished, this,
[this] (bool success) { d->commandFinished(success); });
d->m_command->addFlags(flags); d->m_command->addFlags(flags);
for (const QStringList &arg : args) { for (const QStringList &arg : args) {
@@ -195,3 +290,5 @@ QString VcsBaseDiffEditorController::startupFile() const
} }
} // namespace VcsBase } // namespace VcsBase
#include "vcsbasediffeditorcontroller.moc"

View File

@@ -1670,6 +1670,28 @@
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccc" /> sodipodi:nodetypes="cccccccccccccccc" />
</g> </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 <g
id="src/libs/utils/images/wizardicon-file" id="src/libs/utils/images/wizardicon-file"
transform="translate(-102.49412,8.5102807)"> transform="translate(-102.49412,8.5102807)">

Before

Width:  |  Height:  |  Size: 307 KiB

After

Width:  |  Height:  |  Size: 309 KiB

View File

@@ -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. dragging on the splitter handles.
*/ */
property bool resizing: false property bool resizing: false

View File

@@ -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. dragging on the splitter handles.
*/ */
property bool resizing: false property bool resizing: false

View File

@@ -83,7 +83,7 @@ def prepareTestExamples():
def switchSession(toSession): def switchSession(toSession):
test.log("Switching to session '%s'" % 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' " clickItem(waitForObject("{name='sessionView' type='ProjectExplorer::Internal::SessionView' visible='1' "
"window=':Session Manager_ProjectExplorer::Internal::SessionDialog'}"), "window=':Session Manager_ProjectExplorer::Internal::SessionDialog'}"),
toSession, 5, 5, 0, Qt.LeftButton) toSession, 5, 5, 0, Qt.LeftButton)
@@ -94,7 +94,7 @@ def createAndSwitchToSession(toSession):
sessionInputDialog = ("{type='ProjectExplorer::Internal::SessionNameInputDialog' unnamed='1' " sessionInputDialog = ("{type='ProjectExplorer::Internal::SessionNameInputDialog' unnamed='1' "
"visible='1' windowTitle='New Session Name'}") "visible='1' windowTitle='New Session Name'}")
test.log("Switching to session '%s' after creating it." % toSession) 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' " clickButton(waitForObject("{name='btCreateNew' text='New' type='QPushButton' visible='1' "
"window=':Session Manager_ProjectExplorer::Internal::SessionDialog'}")) "window=':Session Manager_ProjectExplorer::Internal::SessionDialog'}"))
lineEdit = waitForObject("{type='QLineEdit' unnamed='1' visible='1' window=%s}" lineEdit = waitForObject("{type='QLineEdit' unnamed='1' visible='1' window=%s}"