From c0c210cbda26792ab1978f5dad45b17fc0ca4eb0 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Thu, 22 Jun 2017 13:53:21 +0200 Subject: [PATCH 01/28] CMake: Use tr in BuildStep Its a QObject, no need for QCoreApplication::translate here. Change-Id: I3375a70fe60b66e13de6b9a99c35c85f82b9151e Reviewed-by: Tim Jenssen --- src/plugins/cmakeprojectmanager/cmakebuildstep.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index 4bc51dd42ec..c5f1b6a8f38 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -193,9 +193,8 @@ bool CMakeBuildStep::init(QList &earlierSteps) CMakeTool *tool = CMakeKitInformation::cmakeTool(target()->kit()); if (!tool || !tool->isValid()) { emit addTask(Task(Task::Error, - QCoreApplication::translate("CMakeProjectManager::CMakeBuildStep", - "Qt Creator needs a CMake Tool set up to build. " - "Configure a CMake Tool in the kit options."), + tr("Qt Creator needs a CMake Tool set up to build. " + "Configure a CMake Tool in the kit options."), Utils::FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); canInit = false; From 543929cd2c0550314957b0db6a73bca2c04e7341 Mon Sep 17 00:00:00 2001 From: Tobias Hunger Date: Thu, 22 Jun 2017 13:53:48 +0200 Subject: [PATCH 02/28] CMake: Warn when doing out-of-source builds with in-source configuration Warn when attempting to do an out-of-source build while an in-source build is configured. This seems to confuse cmake. Task-number: QTCREATORBUG-18381 Change-Id: I1abd3be4129ba5af6439dcd60d16d429b93c0382 Reviewed-by: Tim Jenssen --- .../cmakeprojectmanager/cmakebuildstep.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index c5f1b6a8f38..ff2a3d2c9a6 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -217,6 +217,22 @@ bool CMakeBuildStep::init(QList &earlierSteps) return false; } + // Warn if doing out-of-source builds with a CMakeCache.txt is the source directory + const Utils::FileName projectDirectory = bc->target()->project()->projectDirectory(); + if (bc->buildDirectory() != projectDirectory) { + Utils::FileName cmc = projectDirectory; + cmc.appendPath("CMakeCache.txt"); + if (cmc.exists()) { + emit addTask(Task(Task::Warning, + tr("There is a CMakeCache.txt file in \"%1\", which suggest an " + "in-source build was done before. You are now building in \"%2\", " + "and the CMakeCache.txt file might confuse CMake.") + .arg(projectDirectory.toUserOutput(), bc->buildDirectory().toUserOutput()), + Utils::FileName(), -1, + ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)); + } + } + QString arguments = allArguments(rc); setIgnoreReturnValue(m_buildTarget == CMakeBuildStep::cleanTarget()); From 22829c1906850d66bb8d37247448b183a3d95109 Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Fri, 23 Jun 2017 13:11:32 +0200 Subject: [PATCH 03/28] Wizards: allow selection of inspect wizard variables dialog Change-Id: Ibc8085203f2d050de65124b2646628be784103fa Reviewed-by: Tobias Hunger --- src/libs/utils/wizard.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/utils/wizard.cpp b/src/libs/utils/wizard.cpp index aea1adc3064..7829744314f 100644 --- a/src/libs/utils/wizard.cpp +++ b/src/libs/utils/wizard.cpp @@ -430,6 +430,7 @@ void Wizard::showVariables() auto label = new QLabel(result); label->setWordWrap(true); + label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); scrollArea->setWidget(label); layout->addWidget(scrollArea); From d870bab95c04786dc0ee5d8d44d5fad484b89a48 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 27 Jun 2017 09:21:46 +0200 Subject: [PATCH 04/28] CppEditor: Cancel runner in ~CppUseSelectionsUpdater ...otherwise an already destructed QTextDocument might be accessed in the ClangCodeModel::Internal::IpcReceiver::references. Task-number: QTCREATORBUG-18459 Change-Id: I1868b2fd3a64341794f83eea6c4eeb7c2c1af812 Reviewed-by: Orgad Shaneh Reviewed-by: David Schulz --- src/plugins/clangcodemodel/clangbackendipcintegration.cpp | 4 ++-- src/plugins/clangcodemodel/clangbackendipcintegration.h | 3 ++- src/plugins/cppeditor/cppuseselectionsupdater.cpp | 6 ++++++ src/plugins/cppeditor/cppuseselectionsupdater.h | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp index 8dd45907de3..5ff5b1aa7e5 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.cpp +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.cpp @@ -248,9 +248,9 @@ void IpcReceiver::references(const ReferencesMessage &message) QTC_CHECK(futureInterface != QFutureInterface()); if (futureInterface.isCanceled()) - return; // A new request was issued making this one outdated. + return; // Editor document closed or a new request was issued making this result outdated. - QTC_CHECK(entry.textDocument); + QTC_ASSERT(entry.textDocument, return); futureInterface.reportResult(toCursorInfo(*entry.textDocument, message)); futureInterface.reportFinished(); } diff --git a/src/plugins/clangcodemodel/clangbackendipcintegration.h b/src/plugins/clangcodemodel/clangbackendipcintegration.h index e3842b2a26d..57a07e8097d 100644 --- a/src/plugins/clangcodemodel/clangbackendipcintegration.h +++ b/src/plugins/clangcodemodel/clangbackendipcintegration.h @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -102,7 +103,7 @@ private: : futureInterface(futureInterface) , textDocument(textDocument) {} QFutureInterface futureInterface; - QTextDocument *textDocument = nullptr; + QPointer textDocument; }; QHash m_referencesTable; }; diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp index 217a58fa1d2..47a036c7b94 100644 --- a/src/plugins/cppeditor/cppuseselectionsupdater.cpp +++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp @@ -49,6 +49,12 @@ CppUseSelectionsUpdater::CppUseSelectionsUpdater(TextEditor::TextEditorWidget *e connect(&m_timer, &QTimer::timeout, this, [this]() { update(); }); } +CppUseSelectionsUpdater::~CppUseSelectionsUpdater() +{ + if (m_runnerWatcher) + m_runnerWatcher->cancel(); +} + void CppUseSelectionsUpdater::scheduleUpdate() { m_timer.start(); diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.h b/src/plugins/cppeditor/cppuseselectionsupdater.h index b2474362850..478a816f980 100644 --- a/src/plugins/cppeditor/cppuseselectionsupdater.h +++ b/src/plugins/cppeditor/cppuseselectionsupdater.h @@ -44,6 +44,7 @@ class CppUseSelectionsUpdater : public QObject public: explicit CppUseSelectionsUpdater(TextEditor::TextEditorWidget *editorWidget); + ~CppUseSelectionsUpdater(); void scheduleUpdate(); void abortSchedule(); From 70283a9ea60c6bb02015800c614b5d5b4461d02e Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 28 Jun 2017 13:50:18 +0200 Subject: [PATCH 05/28] GLSLEditor: Remove GlslHoverHandler The BaseHoverHandler does the same job. Change-Id: I2708a87ed5cbc3b320766f52927be4a9670b522b Reviewed-by: David Schulz --- src/plugins/glsleditor/glsleditor.cpp | 3 -- src/plugins/glsleditor/glsleditor.pro | 2 - src/plugins/glsleditor/glsleditor.qbs | 2 - src/plugins/glsleditor/glslhoverhandler.cpp | 45 --------------------- src/plugins/glsleditor/glslhoverhandler.h | 44 -------------------- 5 files changed, 96 deletions(-) delete mode 100644 src/plugins/glsleditor/glslhoverhandler.cpp delete mode 100644 src/plugins/glsleditor/glslhoverhandler.h diff --git a/src/plugins/glsleditor/glsleditor.cpp b/src/plugins/glsleditor/glsleditor.cpp index 5160828b4bb..feb283f02a9 100644 --- a/src/plugins/glsleditor/glsleditor.cpp +++ b/src/plugins/glsleditor/glsleditor.cpp @@ -27,7 +27,6 @@ #include "glsleditorconstants.h" #include "glsleditorplugin.h" #include "glslhighlighter.h" -#include "glslhoverhandler.h" #include "glslautocompleter.h" #include "glslcompletionassist.h" #include "glslindenter.h" @@ -332,8 +331,6 @@ GlslEditorFactory::GlslEditorFactory() setEditorActionHandlers(TextEditorActionHandler::Format | TextEditorActionHandler::UnCommentSelection | TextEditorActionHandler::UnCollapseAll); - - addHoverHandler(new GlslHoverHandler); } } // namespace Internal diff --git a/src/plugins/glsleditor/glsleditor.pro b/src/plugins/glsleditor/glsleditor.pro index 8f588ecb566..5abc1069702 100644 --- a/src/plugins/glsleditor/glsleditor.pro +++ b/src/plugins/glsleditor/glsleditor.pro @@ -10,7 +10,6 @@ glsleditorplugin.h \ glslhighlighter.h \ glslautocompleter.h \ glslindenter.h \ -glslhoverhandler.h \ glslcompletionassist.h SOURCES += \ @@ -19,7 +18,6 @@ glsleditorplugin.cpp \ glslhighlighter.cpp \ glslautocompleter.cpp \ glslindenter.cpp \ -glslhoverhandler.cpp \ glslcompletionassist.cpp RESOURCES += glsleditor.qrc diff --git a/src/plugins/glsleditor/glsleditor.qbs b/src/plugins/glsleditor/glsleditor.qbs index 1d5003de46d..23f7b4f4293 100644 --- a/src/plugins/glsleditor/glsleditor.qbs +++ b/src/plugins/glsleditor/glsleditor.qbs @@ -25,8 +25,6 @@ QtcPlugin { "glsleditorplugin.h", "glslhighlighter.cpp", "glslhighlighter.h", - "glslhoverhandler.cpp", - "glslhoverhandler.h", "glslindenter.cpp", "glslindenter.h", ] diff --git a/src/plugins/glsleditor/glslhoverhandler.cpp b/src/plugins/glsleditor/glslhoverhandler.cpp deleted file mode 100644 index 305852f0742..00000000000 --- a/src/plugins/glsleditor/glslhoverhandler.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "glslhoverhandler.h" -#include "glsleditor.h" - -namespace GlslEditor { -namespace Internal { - -void GlslHoverHandler::identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos) -{ - if (!editorWidget->extraSelectionTooltip(pos).isEmpty()) - setToolTip(editorWidget->extraSelectionTooltip(pos)); -} - -void GlslHoverHandler::decorateToolTip() -{ - if (Qt::mightBeRichText(toolTip())) - setToolTip(toolTip().toHtmlEscaped()); -} - -} // namespace Internal -} // namespace GlslEditor diff --git a/src/plugins/glsleditor/glslhoverhandler.h b/src/plugins/glsleditor/glslhoverhandler.h deleted file mode 100644 index 5d1f29067e1..00000000000 --- a/src/plugins/glsleditor/glslhoverhandler.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include - -namespace GlslEditor { -namespace Internal { - -class GlslHoverHandler : public TextEditor::BaseHoverHandler -{ -public: - GlslHoverHandler() {} - -private: - void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos) override; - void decorateToolTip() override; -}; - -} // namespace Internal -} // namespace GlslEditor From 218457786df392a02f93dd019d1c91203bd4dc1c Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 28 Jun 2017 16:08:45 +0200 Subject: [PATCH 06/28] DiffEditor: Fix build diffutils.cpp: In function 'QList DiffEditor::readLines(QStringRef, bool, bool*, bool*)': diffutils.cpp:585:53: error: no match for 'operator+' (operand types are 'QStringRef' and 'const QChar') Change-Id: I44ad2237c033266d3832ce95174ec056ff7cae9f Reviewed-by: Orgad Shaneh --- src/plugins/diffeditor/diffutils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/diffeditor/diffutils.cpp b/src/plugins/diffeditor/diffutils.cpp index a7e6b322197..87931329160 100644 --- a/src/plugins/diffeditor/diffutils.cpp +++ b/src/plugins/diffeditor/diffutils.cpp @@ -582,7 +582,7 @@ static QList readLines(QStringRef patch, break; } - Diff diffToBeAdded(command, line.mid(1) + newLine); + Diff diffToBeAdded(command, line.mid(1).toString() + newLine); if (!diffList.isEmpty() && diffList.last().command == command) diffList.last().text.append(diffToBeAdded.text); From 3610b2a8250b8de5709f8c10b45a372d77cb7b58 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 28 Jun 2017 14:53:21 +0200 Subject: [PATCH 07/28] Valgrind: Fix Memcheck startup on remote linux Remote CallGrind is still dysfunctional. Change-Id: Ib9ab537dc068c94c7e61ac48b1a4b9d655ccb60f Reviewed-by: Christian Kandeler --- src/plugins/debugger/debuggerruncontrol.cpp | 16 +- .../callgrind/callgrindcontroller.cpp | 18 +- src/plugins/valgrind/memcheckengine.cpp | 48 +++- src/plugins/valgrind/memcheckengine.h | 1 + src/plugins/valgrind/valgrindengine.cpp | 1 + src/plugins/valgrind/valgrindprocess.cpp | 235 ++++++------------ src/plugins/valgrind/valgrindprocess.h | 24 +- src/plugins/valgrind/valgrindrunner.cpp | 64 +++-- src/plugins/valgrind/valgrindrunner.h | 3 +- 9 files changed, 184 insertions(+), 226 deletions(-) diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index ebb839fc907..2195708fd9f 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -468,12 +468,24 @@ static DebuggerRunConfigurationAspect *debuggerAspect(const RunControl *runContr return runControl->runConfiguration()->extraAspect(); } +static bool cppDebugging(const RunControl *runControl) +{ + auto aspect = debuggerAspect(runControl); + return aspect ? aspect->useCppDebugger() : true; // For cases like valgrind-with-gdb. +} + +static bool qmlDebugging(const RunControl *runControl) +{ + auto aspect = debuggerAspect(runControl); + return aspect ? aspect->useCppDebugger() : false; // For cases like valgrind-with-gdb. +} + /// DebuggerRunTool DebuggerRunTool::DebuggerRunTool(RunControl *runControl) : RunWorker(runControl), - m_isCppDebugging(debuggerAspect(runControl)->useCppDebugger()), - m_isQmlDebugging(debuggerAspect(runControl)->useQmlDebugger()) + m_isCppDebugging(cppDebugging(runControl)), + m_isQmlDebugging(qmlDebugging(runControl)) { setDisplayName("DebuggerRunTool"); } diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp index faf1c980b4d..b28c5a98af7 100644 --- a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp +++ b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp @@ -192,15 +192,15 @@ void CallgrindController::getLocalDataFile() QString fileName = workingDir.isEmpty() ? baseFileName : (workingDir + QLatin1Char('/') + baseFileName); if (!m_valgrindProc->isLocal()) { - ///TODO: error handling - emit statusMessage(tr("Downloading remote profile data...")); - m_ssh = m_valgrindProc->connection(); - // if there are files like callgrind.out.PID.NUM, set it to the most recent one of those - QString cmd = QString::fromLatin1("ls -t %1* | head -n 1").arg(fileName); - m_findRemoteFile = m_ssh->createRemoteProcess(cmd.toUtf8()); - connect(m_findRemoteFile.data(), &QSsh::SshRemoteProcess::readyReadStandardOutput, - this, &CallgrindController::foundRemoteFile); - m_findRemoteFile->start(); +// ///TODO: error handling +// emit statusMessage(tr("Downloading remote profile data...")); +// m_ssh = m_valgrindProc->connection(); +// // if there are files like callgrind.out.PID.NUM, set it to the most recent one of those +// QString cmd = QString::fromLatin1("ls -t %1* | head -n 1").arg(fileName); +// m_findRemoteFile = m_ssh->createRemoteProcess(cmd.toUtf8()); +// connect(m_findRemoteFile.data(), &QSsh::SshRemoteProcess::readyReadStandardOutput, +// this, &CallgrindController::foundRemoteFile); +// m_findRemoteFile->start(); } else { QDir dir(workingDir, QString::fromLatin1("%1.*").arg(baseFileName), QDir::Time); QStringList outputFiles = dir.entryList(); diff --git a/src/plugins/valgrind/memcheckengine.cpp b/src/plugins/valgrind/memcheckengine.cpp index d6f44798e29..918abbcb2a3 100644 --- a/src/plugins/valgrind/memcheckengine.cpp +++ b/src/plugins/valgrind/memcheckengine.cpp @@ -51,8 +51,33 @@ using namespace Valgrind::XmlProtocol; namespace Valgrind { namespace Internal { +class LocalAddressFinder : public RunWorker +{ +public: + LocalAddressFinder(RunControl *runControl, QHostAddress *localServerAddress) + : RunWorker(runControl), connection(device()->sshParameters()) + { + connect(&connection, &QSsh::SshConnection::connected, this, [this, localServerAddress] { + *localServerAddress = connection.connectionInfo().localAddress; + reportStarted(); + }); + connect(&connection, &QSsh::SshConnection::error, this, [this] { + reportFailure(); + }); + } + + void start() override + { + connection.connectToHost(); + } + + QSsh::SshConnection connection; +}; + MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb) - : ValgrindToolRunner(runControl), m_withGdb(withGdb) + : ValgrindToolRunner(runControl), + m_withGdb(withGdb), + m_localServerAddress(QHostAddress::LocalHost) { setDisplayName("MemcheckToolRunner"); connect(m_runner.parser(), &XmlProtocol::ThreadedParser::error, @@ -65,11 +90,15 @@ MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb) this, &MemcheckToolRunner::startDebugger); connect(&m_runner, &ValgrindRunner::logMessageReceived, this, &MemcheckToolRunner::appendLog); - m_runner.disableXml(); +// m_runner.disableXml(); } else { connect(m_runner.parser(), &XmlProtocol::ThreadedParser::internalError, this, &MemcheckToolRunner::internalParserError); } + + // We need a real address to connect to from the outside. + if (device()->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) + addDependency(new LocalAddressFinder(runControl, &m_localServerAddress)); } QString MemcheckToolRunner::progressTitle() const @@ -79,10 +108,7 @@ QString MemcheckToolRunner::progressTitle() const void MemcheckToolRunner::start() { -// MemcheckTool::engineStarting(this); - - appendMessage(tr("Analyzing memory of %1").arg(executable()) + QLatin1Char('\n'), - Utils::NormalMessageFormat); + m_runner.setLocalServerAddress(m_localServerAddress); ValgrindToolRunner::start(); } @@ -149,12 +175,10 @@ void MemcheckToolRunner::startDebugger() sp.useContinueInsteadOfRun = true; sp.expectedSignals.append("SIGTRAP"); - QString errorMessage; - auto gdbRunControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE); - (void) new Debugger::DebuggerRunTool(gdbRunControl, sp, &errorMessage); - connect(gdbRunControl, &RunControl::finished, - gdbRunControl, &RunControl::deleteLater); - gdbRunControl->initiateStart(); + auto gdbWorker = new Debugger::DebuggerRunTool(runControl()); + gdbWorker->setStartParameters(sp); + gdbWorker->initiateStart(); + connect(runControl(), &RunControl::finished, gdbWorker, &RunControl::deleteLater); } void MemcheckToolRunner::appendLog(const QByteArray &data) diff --git a/src/plugins/valgrind/memcheckengine.h b/src/plugins/valgrind/memcheckengine.h index e77d4ec02d6..40d97ac7038 100644 --- a/src/plugins/valgrind/memcheckengine.h +++ b/src/plugins/valgrind/memcheckengine.h @@ -60,6 +60,7 @@ private: void appendLog(const QByteArray &data); const bool m_withGdb; + QHostAddress m_localServerAddress; }; } // namespace Internal diff --git a/src/plugins/valgrind/valgrindengine.cpp b/src/plugins/valgrind/valgrindengine.cpp index 649a1d75948..b87728ba482 100644 --- a/src/plugins/valgrind/valgrindengine.cpp +++ b/src/plugins/valgrind/valgrindengine.cpp @@ -106,6 +106,7 @@ void ValgrindToolRunner::stop() { m_isStopping = true; m_runner.stop(); + reportStopped(); // FIXME: Restrict to non-running scenarios? } QString ValgrindToolRunner::executable() const diff --git a/src/plugins/valgrind/valgrindprocess.cpp b/src/plugins/valgrind/valgrindprocess.cpp index 5f45c90bb15..e0fa607c282 100644 --- a/src/plugins/valgrind/valgrindprocess.cpp +++ b/src/plugins/valgrind/valgrindprocess.cpp @@ -39,26 +39,18 @@ using namespace ProjectExplorer; namespace Valgrind { -ValgrindProcess::ValgrindProcess(const IDevice::ConstPtr &device, - QObject *parent) +ValgrindProcess::ValgrindProcess(const IDevice::ConstPtr &device, QObject *parent) : QObject(parent), m_device(device) { - m_remote.m_connection = 0; - m_remote.m_error = QProcess::UnknownError; - m_pid = 0; } ValgrindProcess::~ValgrindProcess() { - if (m_remote.m_connection) - QSsh::releaseConnection(m_remote.m_connection); } void ValgrindProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode) { - if (isLocal()) - m_localProcess.setProcessChannelMode(mode); - ///TODO: remote support this by handling the mode internally + m_valgrindProcess.setProcessChannelMode(mode); } QString ValgrindProcess::workingDirectory() const @@ -68,10 +60,7 @@ QString ValgrindProcess::workingDirectory() const bool ValgrindProcess::isRunning() const { - if (isLocal()) - return m_localProcess.isRunning(); - else - return m_remote.m_process && m_remote.m_process->isRunning(); + return m_valgrindProcess.isRunning(); } void ValgrindProcess::setValgrindExecutable(const QString &valgrindExecutable) @@ -91,94 +80,53 @@ void ValgrindProcess::setValgrindArguments(const QStringList &valgrindArguments) void ValgrindProcess::close() { - if (isLocal()) { - m_localProcess.stop(); - } else { - QTC_ASSERT(m_remote.m_connection->state() == QSsh::SshConnection::Connected, return); - if (m_remote.m_process) { - if (m_pid) { - const QString killTemplate = QString::fromLatin1("kill -%2 %1" // kill - ).arg(m_pid); - - const QString niceKill = killTemplate.arg(QLatin1String("SIGTERM")); - const QString brutalKill = killTemplate.arg(QLatin1String("SIGKILL")); - const QString remoteCall = niceKill + QLatin1String("; sleep 1; ") + brutalKill; - - QSsh::SshRemoteProcess::Ptr cleanup = m_remote.m_connection->createRemoteProcess(remoteCall.toUtf8()); - cleanup->start(); - } - } - } + m_valgrindProcess.stop(); } void ValgrindProcess::run(ApplicationLauncher::Mode runMode) { + connect(&m_valgrindProcess, &ApplicationLauncher::processExited, + this, &ValgrindProcess::finished); + connect(&m_valgrindProcess, &ApplicationLauncher::processStarted, + this, &ValgrindProcess::localProcessStarted); + connect(&m_valgrindProcess, &ApplicationLauncher::error, + this, &ValgrindProcess::error); + connect(&m_valgrindProcess, &ApplicationLauncher::appendMessage, + this, &ValgrindProcess::processOutput); + + connect(&m_valgrindProcess, &ApplicationLauncher::remoteStderr, + this, &ValgrindProcess::handleRemoteStderr); + connect(&m_valgrindProcess, &ApplicationLauncher::remoteStdout, + this, &ValgrindProcess::handleRemoteStdout); + connect(&m_valgrindProcess, &ApplicationLauncher::finished, + this, &ValgrindProcess::closed); + connect(&m_valgrindProcess, &ApplicationLauncher::remoteProcessStarted, + this, &ValgrindProcess::remoteProcessStarted); + + StandardRunnable valgrind; + valgrind.executable = m_valgrindExecutable; + valgrind.workingDirectory = m_debuggee.workingDirectory; + valgrind.environment = m_debuggee.environment; + valgrind.runMode = runMode; + valgrind.device = m_device; + if (isLocal()) { - connect(&m_localProcess, &ApplicationLauncher::processExited, - this, &ValgrindProcess::finished); - connect(&m_localProcess, &ApplicationLauncher::processStarted, - this, &ValgrindProcess::localProcessStarted); - connect(&m_localProcess, &ApplicationLauncher::error, - this, &ValgrindProcess::error); - connect(&m_localProcess, &ApplicationLauncher::appendMessage, - this, &ValgrindProcess::processOutput); - - StandardRunnable valgrind; - valgrind.executable = m_valgrindExecutable; - valgrind.runMode = runMode; valgrind.commandLineArguments = argumentString(Utils::HostOsInfo::hostOs()); - valgrind.workingDirectory = m_debuggee.workingDirectory; - valgrind.environment = m_debuggee.environment; - m_localProcess.start(valgrind); - + m_valgrindProcess.start(valgrind); } else { - // connect to host and wait for connection - if (!m_remote.m_connection) - m_remote.m_connection = QSsh::acquireConnection(m_device->sshParameters()); - - if (m_remote.m_connection->state() != QSsh::SshConnection::Connected) { - connect(m_remote.m_connection, &QSsh::SshConnection::connected, - this, &ValgrindProcess::connected); - connect(m_remote.m_connection, &QSsh::SshConnection::error, - this, &ValgrindProcess::handleError); - if (m_remote.m_connection->state() == QSsh::SshConnection::Unconnected) - m_remote.m_connection->connectToHost(); - } else { - connected(); - } + valgrind.commandLineArguments = argumentString(Utils::OsTypeLinux); + m_valgrindProcess.start(valgrind, m_device); } } QString ValgrindProcess::errorString() const { - if (isLocal()) - return m_localProcess.errorString(); - else - return m_remote.m_errorString; + return m_valgrindProcess.errorString(); } QProcess::ProcessError ValgrindProcess::processError() const { - if (isLocal()) - return m_localProcess.processError(); - else - return m_remote.m_error; -} - -void ValgrindProcess::handleError(QSsh::SshError error) -{ - if (!isLocal()) { - switch (error) { - case QSsh::SshTimeoutError: - m_remote.m_error = QProcess::Timedout; - break; - default: - m_remote.m_error = QProcess::FailedToStart; - break; - } - } - m_remote.m_errorString = m_remote.m_connection->errorString(); - emit this->error(m_remote.m_error); + return m_valgrindProcess.processError(); } qint64 ValgrindProcess::pid() const @@ -186,53 +134,16 @@ qint64 ValgrindProcess::pid() const return m_pid; } -void ValgrindProcess::handleRemoteStderr() +void ValgrindProcess::handleRemoteStderr(const QByteArray &b) { - const QString b = QString::fromUtf8(m_remote.m_process->readAllStandardError()); if (!b.isEmpty()) - emit processOutput(b, Utils::StdErrFormat); + emit processOutput(QString::fromUtf8(b), Utils::StdErrFormat); } -void ValgrindProcess::handleRemoteStdout() +void ValgrindProcess::handleRemoteStdout(const QByteArray &b) { - const QString b = QString::fromUtf8(m_remote.m_process->readAllStandardOutput()); if (!b.isEmpty()) - emit processOutput(b, Utils::StdOutFormat); -} - -/// Remote -void ValgrindProcess::connected() -{ - QTC_ASSERT(m_remote.m_connection->state() == QSsh::SshConnection::Connected, return); - - emit localHostAddressRetrieved(m_remote.m_connection->connectionInfo().localAddress); - - // connected, run command - QString cmd; - - if (!m_debuggee.workingDirectory.isEmpty()) - cmd += QString::fromLatin1("cd '%1' && ").arg(m_debuggee.workingDirectory); - - cmd += m_valgrindExecutable + QLatin1Char(' ') + argumentString(Utils::OsTypeLinux); - - m_remote.m_process = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); - for (auto it = m_debuggee.environment.constBegin(); it != m_debuggee.environment.constEnd(); ++it) - m_remote.m_process->addToEnvironment(it.key().toUtf8(), it.value().toUtf8()); - - connect(m_remote.m_process.data(), &QSsh::SshRemoteProcess::readyReadStandardError, - this, &ValgrindProcess::handleRemoteStderr); - connect(m_remote.m_process.data(), &QSsh::SshRemoteProcess::readyReadStandardOutput, - this, &ValgrindProcess::handleRemoteStdout); - connect(m_remote.m_process.data(), &QSsh::SshRemoteProcess::closed, - this, &ValgrindProcess::closed); - connect(m_remote.m_process.data(), &QSsh::SshRemoteProcess::started, - this, &ValgrindProcess::remoteProcessStarted); - m_remote.m_process->start(); -} - -QSsh::SshConnection *ValgrindProcess::connection() const -{ - return m_remote.m_connection; + emit processOutput(QString::fromUtf8(b), Utils::StdOutFormat); } bool ValgrindProcess::isLocal() const @@ -242,14 +153,12 @@ bool ValgrindProcess::isLocal() const void ValgrindProcess::localProcessStarted() { - m_pid = m_localProcess.applicationPID().pid(); + m_pid = m_valgrindProcess.applicationPID().pid(); emit started(); } void ValgrindProcess::remoteProcessStarted() { - QTC_ASSERT(m_remote.m_connection->state() == QSsh::SshConnection::Connected, return); - // find out what PID our process has // NOTE: valgrind cloaks its name, @@ -259,34 +168,40 @@ void ValgrindProcess::remoteProcessStarted() // hence we need to do something more complex... // plain path to exe, m_valgrindExe contains e.g. env vars etc. pp. - const QString proc = m_valgrindExecutable.split(QLatin1Char(' ')).last(); + const QString proc = m_valgrindExecutable.split(' ').last(); + + StandardRunnable findPid; + findPid.executable = "/bin/sh"; // sleep required since otherwise we might only match "bash -c..." // and not the actual valgrind run - const QString cmd = QString::fromLatin1("sleep 1; ps ax" // list all processes with aliased name - " | grep '\\b%1.*%2'" // find valgrind process - " | tail -n 1" // limit to single process - // we pick the last one, first would be "bash -c ..." - " | awk '{print $1;}'" // get pid - ).arg(proc, Utils::FileName::fromString(m_debuggee.executable).fileName()); + findPid.commandLineArguments = QString("-c \"" + "sleep 1; ps ax" // list all processes with aliased name + " | grep '\\b%1.*%2'" // find valgrind process + " | tail -n 1" // limit to single process + // we pick the last one, first would be "bash -c ..." + " | awk '{print $1;}'" // get pid + "\"" + ).arg(proc, Utils::FileName::fromString(m_debuggee.executable).fileName()); - m_remote.m_findPID = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); - connect(m_remote.m_findPID.data(), &QSsh::SshRemoteProcess::readyReadStandardError, +// m_remote.m_findPID = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); + connect(&m_findPID, &ApplicationLauncher::remoteStderr, this, &ValgrindProcess::handleRemoteStderr); - connect(m_remote.m_findPID.data(), &QSsh::SshRemoteProcess::readyReadStandardOutput, + connect(&m_findPID, &ApplicationLauncher::remoteStdout, this, &ValgrindProcess::findPIDOutputReceived); - m_remote.m_findPID->start(); + m_findPID.start(findPid, m_device); } -void ValgrindProcess::findPIDOutputReceived() +void ValgrindProcess::findPIDOutputReceived(const QByteArray &out) { + if (out.isEmpty()) + return; bool ok; - m_pid = m_remote.m_findPID->readAllStandardOutput().trimmed().toLongLong(&ok); + m_pid = out.trimmed().toLongLong(&ok); if (!ok) { m_pid = 0; - m_remote.m_errorString = tr("Could not determine remote PID."); - m_remote.m_error = QProcess::FailedToStart; - emit ValgrindProcess::error(QProcess::FailedToStart); - close(); +// m_remote.m_errorString = tr("Could not determine remote PID."); +// emit ValgrindProcess::error(QProcess::FailedToStart); +// close(); } else { emit started(); } @@ -301,20 +216,22 @@ QString ValgrindProcess::argumentString(Utils::OsType osType) const return arguments; } -void ValgrindProcess::closed(int status) +void ValgrindProcess::closed(bool success) { - QTC_ASSERT(m_remote.m_process, return); + Q_UNUSED(success); +// QTC_ASSERT(m_remote.m_process, return); - m_remote.m_errorString = m_remote.m_process->errorString(); - if (status == QSsh::SshRemoteProcess::FailedToStart) { - m_remote.m_error = QProcess::FailedToStart; - emit ValgrindProcess::error(QProcess::FailedToStart); - } else if (status == QSsh::SshRemoteProcess::NormalExit) { - emit finished(m_remote.m_process->exitCode(), QProcess::NormalExit); - } else if (status == QSsh::SshRemoteProcess::CrashExit) { - m_remote.m_error = QProcess::Crashed; - emit finished(m_remote.m_process->exitCode(), QProcess::CrashExit); - } +// m_remote.m_errorString = m_remote.m_process->errorString(); +// if (status == QSsh::SshRemoteProcess::FailedToStart) { +// m_remote.m_error = QProcess::FailedToStart; +// emit ValgrindProcess::error(QProcess::FailedToStart); +// } else if (status == QSsh::SshRemoteProcess::NormalExit) { +// emit finished(m_remote.m_process->exitCode(), QProcess::NormalExit); +// } else if (status == QSsh::SshRemoteProcess::CrashExit) { +// m_remote.m_error = QProcess::Crashed; +// emit finished(m_remote.m_process->exitCode(), QProcess::CrashExit); +// } + emit finished(0, QProcess::NormalExit); } } // namespace Valgrind diff --git a/src/plugins/valgrind/valgrindprocess.h b/src/plugins/valgrind/valgrindprocess.h index b85214e0954..50182eb1a2e 100644 --- a/src/plugins/valgrind/valgrindprocess.h +++ b/src/plugins/valgrind/valgrindprocess.h @@ -66,7 +66,6 @@ public: ProjectExplorer::IDevice::ConstPtr device() const { return m_device; } qint64 pid() const; - QSsh::SshConnection *connection() const; bool isLocal() const; signals: @@ -74,33 +73,24 @@ signals: void finished(int, QProcess::ExitStatus); void error(QProcess::ProcessError); void processOutput(const QString &, Utils::OutputFormat format); - void localHostAddressRetrieved(const QHostAddress &localHostAddress); private: - void handleRemoteStderr(); - void handleRemoteStdout(); - void handleError(QSsh::SshError); + void handleRemoteStderr(const QByteArray &b); + void handleRemoteStdout(const QByteArray &b); - void closed(int); - void connected(); + void closed(bool success); void localProcessStarted(); void remoteProcessStarted(); - void findPIDOutputReceived(); + void findPIDOutputReceived(const QByteArray &out); QString argumentString(Utils::OsType osType) const; ProjectExplorer::StandardRunnable m_debuggee; - ProjectExplorer::ApplicationLauncher m_localProcess; - qint64 m_pid; + ProjectExplorer::ApplicationLauncher m_valgrindProcess; + qint64 m_pid = 0; ProjectExplorer::IDevice::ConstPtr m_device; - struct Remote { - QSsh::SshConnection *m_connection; - QSsh::SshRemoteProcess::Ptr m_process; - QString m_errorString; - QProcess::ProcessError m_error; - QSsh::SshRemoteProcess::Ptr m_findPID; - } m_remote; + ProjectExplorer::ApplicationLauncher m_findPID; QSsh::SshConnectionParameters m_params; QString m_valgrindExecutable; diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index 5f348cb3536..e85a872aef8 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -39,6 +39,7 @@ #include #include +#include #include #include @@ -49,6 +50,7 @@ namespace Valgrind { class ValgrindRunner::Private { public: + QHostAddress localServerAddress; ValgrindProcess *process = nullptr; QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels; bool finished = false; @@ -125,6 +127,11 @@ void ValgrindRunner::setProcessChannelMode(QProcess::ProcessChannelMode mode) d->channelMode = mode; } +void ValgrindRunner::setLocalServerAddress(const QHostAddress &localServerAddress) +{ + d->localServerAddress = localServerAddress; +} + void ValgrindRunner::setDevice(const IDevice::ConstPtr &device) { d->device = device; @@ -152,10 +159,8 @@ void ValgrindRunner::setToolName(const QString &toolName) bool ValgrindRunner::start() { - // FIXME: Remove hack. - if (d->tool == "memcheck" - && device()->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { - if (!startServers(QHostAddress::LocalHost)) + if (!d->localServerAddress.isNull()) { + if (!startServers()) return false; setValgrindArguments(memcheckLogArguments() + valgrindArguments()); } @@ -176,8 +181,6 @@ bool ValgrindRunner::start() this, &ValgrindRunner::processFinished); QObject::connect(d->process, &ValgrindProcess::error, this, &ValgrindRunner::processError); - QObject::connect(d->process, &ValgrindProcess::localHostAddressRetrieved, - this, &ValgrindRunner::localHostAddressRetrieved); d->process->run(d->debuggee.runMode); @@ -214,14 +217,6 @@ void ValgrindRunner::processFinished(int ret, QProcess::ExitStatus status) emit processErrorReceived(errorString(), d->process->processError()); } -void ValgrindRunner::localHostAddressRetrieved(const QHostAddress &localHostAddress) -{ - if (startServers(localHostAddress)) { - setValgrindArguments(memcheckLogArguments() + valgrindArguments()); - valgrindProcess()->setValgrindArguments(fullValgrindArguments()); - } -} - QString ValgrindRunner::errorString() const { return d->process ? d->process->errorString() : QString(); @@ -274,10 +269,10 @@ void ValgrindRunner::readLogSocket() emit logMessageReceived(d->logSocket->readAll()); } -bool ValgrindRunner::startServers(const QHostAddress &localHostAddress) +bool ValgrindRunner::startServers() { - bool check = d->xmlServer.listen(localHostAddress); - const QString ip = localHostAddress.toString(); + bool check = d->xmlServer.listen(d->localServerAddress); + const QString ip = d->localServerAddress.toString(); if (!check) { emit processErrorReceived(tr("XmlServer on %1:").arg(ip) + ' ' + d->xmlServer.errorString(), QProcess::FailedToStart ); @@ -286,7 +281,7 @@ bool ValgrindRunner::startServers(const QHostAddress &localHostAddress) d->xmlServer.setMaxPendingConnections(1); connect(&d->xmlServer, &QTcpServer::newConnection, this, &ValgrindRunner::xmlSocketConnected); - check = d->logServer.listen(localHostAddress); + check = d->logServer.listen(d->localServerAddress); if (!check) { emit processErrorReceived(tr("LogServer on %1:").arg(ip) + ' ' + d->logServer.errorString(), QProcess::FailedToStart ); @@ -298,16 +293,33 @@ bool ValgrindRunner::startServers(const QHostAddress &localHostAddress) return true; } +static void handleSocketParameter(const QString &prefix, const QTcpServer &tcpServer, + bool *useXml, QStringList *arguments) +{ + QHostAddress serverAddress = tcpServer.serverAddress(); + if (serverAddress.protocol() != QAbstractSocket::IPv4Protocol) { + // Report will end up in the Application Output pane, i.e. not have + // clickable items, but that's better than nothing. + qWarning("Need IPv4 for valgrind"); + *useXml = false; + } else { + *arguments << QString("%1=%2:%3").arg(prefix).arg(serverAddress.toString()) + .arg(tcpServer.serverPort()); + } +} + QStringList ValgrindRunner::memcheckLogArguments() const { - QStringList arguments; - if (!d->disableXml) - arguments << QLatin1String("--xml=yes"); - arguments << QString::fromLatin1("--xml-socket=%1:%2") - .arg(d->xmlServer.serverAddress().toString()).arg(d->xmlServer.serverPort()) - << QLatin1String("--child-silent-after-fork=yes") - << QString::fromLatin1("--log-socket=%1:%2") - .arg(d->logServer.serverAddress().toString()).arg(d->logServer.serverPort()); + bool enableXml = !d->disableXml; + + QStringList arguments = {"--child-silent-after-fork=yes"}; + + handleSocketParameter("--xml-socket", d->xmlServer, &enableXml, &arguments); + handleSocketParameter("--log-socket", d->logServer, &enableXml, &arguments); + + if (enableXml) + arguments << "--xml=yes"; + return arguments; } diff --git a/src/plugins/valgrind/valgrindrunner.h b/src/plugins/valgrind/valgrindrunner.h index 9732d093567..371ec7d5790 100644 --- a/src/plugins/valgrind/valgrindrunner.h +++ b/src/plugins/valgrind/valgrindrunner.h @@ -56,6 +56,7 @@ public: void setValgrindArguments(const QStringList &toolArguments); void setDebuggee(const ProjectExplorer::StandardRunnable &debuggee) ; void setProcessChannelMode(QProcess::ProcessChannelMode mode); + void setLocalServerAddress(const QHostAddress &localServerAddress); void setDevice(const ProjectExplorer::IDevice::ConstPtr &device); ProjectExplorer::IDevice::ConstPtr device() const; @@ -84,7 +85,7 @@ signals: void extraProcessFinished(); private: - bool startServers(const QHostAddress &localHostAddress); + bool startServers(); QStringList memcheckLogArguments() const; void processError(QProcess::ProcessError); From 7bc88000d95da05d4ee9761deebe4022d67ce383 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 28 Jun 2017 17:16:07 +0200 Subject: [PATCH 08/28] ProjectExplorer: Introduce a Utils::OsType IDevice::osType() function E.g. for easier construction of command lines in situations like if (isLocal()) runnable.commandLineArguments = argumentString(Utils::HostOsInfo::hostOs()); else runnable.commandLineArguments = argumentString(Utils::OsTypeLinux); Change-Id: I5a35304e5d1b5a042952201f39f4134a5cd0ce24 Reviewed-by: Christian Kandeler --- src/plugins/android/androiddevice.cpp | 5 +++++ src/plugins/android/androiddevice.h | 1 + src/plugins/baremetal/baremetaldevice.cpp | 5 +++++ src/plugins/baremetal/baremetaldevice.h | 1 + src/plugins/ios/iosdevice.cpp | 5 +++++ src/plugins/ios/iosdevice.h | 1 + src/plugins/ios/iossimulator.cpp | 5 +++++ src/plugins/ios/iossimulator.h | 1 + src/plugins/projectexplorer/devicesupport/desktopdevice.cpp | 5 +++++ src/plugins/projectexplorer/devicesupport/desktopdevice.h | 1 + src/plugins/projectexplorer/devicesupport/devicemanager.cpp | 1 + src/plugins/projectexplorer/devicesupport/idevice.cpp | 5 +++++ src/plugins/projectexplorer/devicesupport/idevice.h | 2 ++ src/plugins/qnx/qnxdevice.cpp | 5 +++++ src/plugins/qnx/qnxdevice.h | 1 + src/plugins/remotelinux/linuxdevice.cpp | 5 +++++ src/plugins/remotelinux/linuxdevice.h | 1 + src/plugins/winrt/winrtdevice.cpp | 5 +++++ src/plugins/winrt/winrtdevice.h | 1 + 19 files changed, 56 insertions(+) diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index c3717ed6fdc..23c5716ff21 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -94,6 +94,11 @@ DeviceProcessSignalOperation::Ptr AndroidDevice::signalOperation() const return DeviceProcessSignalOperation::Ptr(new AndroidSignalOperation()); } +Utils::OsType AndroidDevice::osType() const +{ + return Utils::OsTypeOtherUnix; +} + IDevice::Ptr AndroidDevice::clone() const { return IDevice::Ptr(new AndroidDevice(*this)); diff --git a/src/plugins/android/androiddevice.h b/src/plugins/android/androiddevice.h index f050b445373..3a59e297981 100644 --- a/src/plugins/android/androiddevice.h +++ b/src/plugins/android/androiddevice.h @@ -44,6 +44,7 @@ public: void executeAction(Core::Id actionId, QWidget *parent = 0) override; bool canAutoDetectPorts() const override; ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override; + Utils::OsType osType() const override; ProjectExplorer::IDevice::Ptr clone() const override; ProjectExplorer::Connection toolControlChannel(const ControlChannelHint &) const override; diff --git a/src/plugins/baremetal/baremetaldevice.cpp b/src/plugins/baremetal/baremetaldevice.cpp index b0e2c20db35..7852011fb5e 100644 --- a/src/plugins/baremetal/baremetaldevice.cpp +++ b/src/plugins/baremetal/baremetaldevice.cpp @@ -176,6 +176,11 @@ void BareMetalDevice::executeAction(Core::Id actionId, QWidget *parent) Q_UNUSED(parent); } +Utils::OsType BareMetalDevice::osType() const +{ + return Utils::OsTypeOther; +} + DeviceProcess *BareMetalDevice::createProcess(QObject *parent) const { return new GdbServerProviderProcess(sharedFromThis(), parent); diff --git a/src/plugins/baremetal/baremetaldevice.h b/src/plugins/baremetal/baremetaldevice.h index a82cdfea0e6..1a2fdbe8c5d 100644 --- a/src/plugins/baremetal/baremetaldevice.h +++ b/src/plugins/baremetal/baremetaldevice.h @@ -50,6 +50,7 @@ public: QList actionIds() const override; QString displayNameForActionId(Core::Id actionId) const override; void executeAction(Core::Id actionId, QWidget *parent) override; + Utils::OsType osType() const override; ProjectExplorer::IDevice::Ptr clone() const override; ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override; diff --git a/src/plugins/ios/iosdevice.cpp b/src/plugins/ios/iosdevice.cpp index 4945b4cd0a7..00dd86b64c3 100644 --- a/src/plugins/ios/iosdevice.cpp +++ b/src/plugins/ios/iosdevice.cpp @@ -213,6 +213,11 @@ bool IosDevice::canAutoDetectPorts() const return true; } +Utils::OsType IosDevice::osType() const +{ + return Utils::OsTypeMac; +} + // IosDeviceManager diff --git a/src/plugins/ios/iosdevice.h b/src/plugins/ios/iosdevice.h index e2dd5cafd56..e0b7b4024bd 100644 --- a/src/plugins/ios/iosdevice.h +++ b/src/plugins/ios/iosdevice.h @@ -68,6 +68,7 @@ public: QString osVersion() const; Utils::Port nextPort() const; bool canAutoDetectPorts() const override; + Utils::OsType osType() const override; static QString name(); diff --git a/src/plugins/ios/iossimulator.cpp b/src/plugins/ios/iossimulator.cpp index 3f41bd84c13..681fe27f55d 100644 --- a/src/plugins/ios/iossimulator.cpp +++ b/src/plugins/ios/iossimulator.cpp @@ -154,6 +154,11 @@ bool IosSimulator::canAutoDetectPorts() const return true; } +Utils::OsType IosSimulator::osType() const +{ + return Utils::OsTypeMac; +} + IosSimulator::ConstPtr IosKitInformation::simulator(Kit *kit) { if (!kit) diff --git a/src/plugins/ios/iossimulator.h b/src/plugins/ios/iossimulator.h index b661821a3d0..ecbf2de776b 100644 --- a/src/plugins/ios/iossimulator.h +++ b/src/plugins/ios/iossimulator.h @@ -77,6 +77,7 @@ public: QVariantMap toMap() const override; Utils::Port nextPort() const; bool canAutoDetectPorts() const override; + Utils::OsType osType() const override; ProjectExplorer::IDevice::Ptr clone() const override; protected: diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp index 400548bd12b..3c494afd7d9 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.cpp @@ -142,6 +142,11 @@ Connection DesktopDevice::toolControlChannel(const ControlChannelHint &) const return HostName("localhost"); } +Utils::OsType DesktopDevice::osType() const +{ + return Utils::HostOsInfo::hostOs(); +} + IDevice::Ptr DesktopDevice::clone() const { return Ptr(new DesktopDevice(*this)); diff --git a/src/plugins/projectexplorer/devicesupport/desktopdevice.h b/src/plugins/projectexplorer/devicesupport/desktopdevice.h index 752bd20075f..80731edad31 100644 --- a/src/plugins/projectexplorer/devicesupport/desktopdevice.h +++ b/src/plugins/projectexplorer/devicesupport/desktopdevice.h @@ -53,6 +53,7 @@ public: DeviceProcessSignalOperation::Ptr signalOperation() const override; DeviceEnvironmentFetcher::Ptr environmentFetcher() const override; Connection toolControlChannel(const ControlChannelHint &) const override; + Utils::OsType osType() const override; IDevice::Ptr clone() const override; diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index 39b17a6444d..2d1e161d2cc 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -441,6 +441,7 @@ private: { return DeviceProcessSignalOperation::Ptr(); } + Utils::OsType osType() const override { return Utils::HostOsInfo::hostOs(); } }; void ProjectExplorerPlugin::testDeviceManager() diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index e4cc56c4278..d4f0f87576a 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -278,6 +278,11 @@ DeviceTester *IDevice::createDeviceTester() const return 0; } +Utils::OsType IDevice::osType() const +{ + return Utils::OsTypeOther; +} + DeviceProcess *IDevice::createProcess(QObject * /* parent */) const { QTC_CHECK(false); diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index a93a0298213..2f5270b7ea0 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -28,6 +28,7 @@ #include "../projectexplorer_export.h" #include +#include #include #include @@ -160,6 +161,7 @@ public: virtual DeviceProcessList *createProcessListModel(QObject *parent = 0) const; virtual bool hasDeviceTester() const { return false; } virtual DeviceTester *createDeviceTester() const; + virtual Utils::OsType osType() const; virtual bool canCreateProcess() const { return false; } virtual DeviceProcess *createProcess(QObject *parent) const; diff --git a/src/plugins/qnx/qnxdevice.cpp b/src/plugins/qnx/qnxdevice.cpp index 26275bb3b88..994f74a8392 100644 --- a/src/plugins/qnx/qnxdevice.cpp +++ b/src/plugins/qnx/qnxdevice.cpp @@ -122,6 +122,11 @@ QString QnxDevice::displayType() const return tr("QNX"); } +OsType QnxDevice::osType() const +{ + return OsTypeOtherUnix; +} + int QnxDevice::qnxVersion() const { if (m_versionNumber == 0) diff --git a/src/plugins/qnx/qnxdevice.h b/src/plugins/qnx/qnxdevice.h index eac1802a80f..3c5ae0965b2 100644 --- a/src/plugins/qnx/qnxdevice.h +++ b/src/plugins/qnx/qnxdevice.h @@ -56,6 +56,7 @@ public: void executeAction(Core::Id actionId, QWidget *parent) override; QString displayType() const override; + Utils::OsType osType() const override; int qnxVersion() const; diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index c3ad42f3b27..1e6fe89993a 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -203,6 +203,11 @@ void LinuxDevice::executeAction(Core::Id actionId, QWidget *parent) delete d; } +Utils::OsType LinuxDevice::osType() const +{ + return Utils::OsTypeLinux; +} + LinuxDevice::LinuxDevice(const QString &name, Core::Id type, MachineType machineType, Origin origin, Core::Id id) : IDevice(type, origin, machineType, id) diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h index f9469abeb50..5b1a764aef0 100644 --- a/src/plugins/remotelinux/linuxdevice.h +++ b/src/plugins/remotelinux/linuxdevice.h @@ -54,6 +54,7 @@ public: QList actionIds() const; QString displayNameForActionId(Core::Id actionId) const; void executeAction(Core::Id actionId, QWidget *parent); + Utils::OsType osType() const override; ProjectExplorer::IDevice::Ptr clone() const; bool canCreateProcess() const { return true; } diff --git a/src/plugins/winrt/winrtdevice.cpp b/src/plugins/winrt/winrtdevice.cpp index 2f5ef04ae55..f6519bf94ab 100644 --- a/src/plugins/winrt/winrtdevice.cpp +++ b/src/plugins/winrt/winrtdevice.cpp @@ -119,6 +119,11 @@ QVariantMap WinRtDevice::toMap() const return map; } +Utils::OsType WinRtDevice::osType() const +{ + return Utils::OsTypeWindows; +} + IDevice::Ptr WinRtDevice::clone() const { return IDevice::Ptr(new WinRtDevice(*this)); diff --git a/src/plugins/winrt/winrtdevice.h b/src/plugins/winrt/winrtdevice.h index 5915ac73f70..694badf32a8 100644 --- a/src/plugins/winrt/winrtdevice.h +++ b/src/plugins/winrt/winrtdevice.h @@ -45,6 +45,7 @@ public: ProjectExplorer::DeviceProcessSignalOperation::Ptr signalOperation() const override; void fromMap(const QVariantMap &map) override; QVariantMap toMap() const override; + Utils::OsType osType() const override; ProjectExplorer::IDevice::Ptr clone() const override; static QString displayNameForType(Core::Id type); From 3afbd1e5ccc4cb674f687092687f2533be57c34c Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 28 Jun 2017 14:26:52 +0200 Subject: [PATCH 09/28] De-qobjectify BaseHoverHandler and derivatives Change-Id: I9bc1d849349f85b5c7fd6013396b8b15b6cb1568 Reviewed-by: David Schulz --- src/plugins/cppeditor/resourcepreviewhoverhandler.h | 2 -- src/plugins/qmakeprojectmanager/profilehoverhandler.h | 2 -- src/plugins/qmljseditor/qmljshoverhandler.h | 3 ++- src/plugins/texteditor/basehoverhandler.h | 10 +++++----- src/plugins/texteditor/colorpreviewhoverhandler.h | 3 --- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/plugins/cppeditor/resourcepreviewhoverhandler.h b/src/plugins/cppeditor/resourcepreviewhoverhandler.h index 7f10db83d87..2ccb261c2a8 100644 --- a/src/plugins/cppeditor/resourcepreviewhoverhandler.h +++ b/src/plugins/cppeditor/resourcepreviewhoverhandler.h @@ -34,8 +34,6 @@ namespace Internal { class ResourcePreviewHoverHandler : public TextEditor::BaseHoverHandler { -public: - private: void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos) override; void operateTooltip(TextEditor::TextEditorWidget *editorWidget, const QPoint &point) override; diff --git a/src/plugins/qmakeprojectmanager/profilehoverhandler.h b/src/plugins/qmakeprojectmanager/profilehoverhandler.h index 7f067b345b1..6e5b6ac03b1 100644 --- a/src/plugins/qmakeprojectmanager/profilehoverhandler.h +++ b/src/plugins/qmakeprojectmanager/profilehoverhandler.h @@ -37,8 +37,6 @@ namespace Internal { class ProFileHoverHandler : public TextEditor::BaseHoverHandler { - Q_OBJECT - public: explicit ProFileHoverHandler(const TextEditor::Keywords &keywords); diff --git a/src/plugins/qmljseditor/qmljshoverhandler.h b/src/plugins/qmljseditor/qmljshoverhandler.h index e9f2d80ec80..fde05c7e4a6 100644 --- a/src/plugins/qmljseditor/qmljshoverhandler.h +++ b/src/plugins/qmljseditor/qmljshoverhandler.h @@ -29,6 +29,7 @@ #include #include +#include QT_BEGIN_NAMESPACE template class QList; @@ -49,7 +50,7 @@ class QmlJSEditorWidget; class QmlJSHoverHandler : public TextEditor::BaseHoverHandler { - Q_OBJECT + Q_DECLARE_TR_FUNCTIONS(QmlJSHoverHandler) public: QmlJSHoverHandler(); diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h index 7a5334e3a8e..cf9c8d7f90e 100644 --- a/src/plugins/texteditor/basehoverhandler.h +++ b/src/plugins/texteditor/basehoverhandler.h @@ -28,7 +28,9 @@ #include "texteditor_global.h" #include "helpitem.h" -#include +QT_BEGIN_NAMESPACE +class QPoint; +QT_END_NAMESPACE namespace Core { class IEditor; } @@ -37,13 +39,11 @@ namespace TextEditor { class BaseTextEditor; class TextEditorWidget; -class TEXTEDITOR_EXPORT BaseHoverHandler : public QObject +class TEXTEDITOR_EXPORT BaseHoverHandler { - Q_OBJECT - public: BaseHoverHandler(); - ~BaseHoverHandler(); + virtual ~BaseHoverHandler(); QString contextHelpId(TextEditorWidget *widget, int pos); int checkToolTip(TextEditorWidget *widget, int pos); diff --git a/src/plugins/texteditor/colorpreviewhoverhandler.h b/src/plugins/texteditor/colorpreviewhoverhandler.h index 2e956027dcc..8677bf009a2 100644 --- a/src/plugins/texteditor/colorpreviewhoverhandler.h +++ b/src/plugins/texteditor/colorpreviewhoverhandler.h @@ -38,9 +38,6 @@ class TextEditorWidget; class TEXTEDITOR_EXPORT ColorPreviewHoverHandler : public BaseHoverHandler { - Q_OBJECT -public: - private: void identifyMatch(TextEditorWidget *editorWidget, int pos) override; void operateTooltip(TextEditorWidget *editorWidget, const QPoint &point) override; From 658e468d80b1741cd96f92f64f51c4f2a171d253 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 28 Jun 2017 14:33:54 +0200 Subject: [PATCH 10/28] TextEditor: Clean up BaseHoverHandler Change-Id: Ie2f0c8c0a46377ae18ff4e31c7e43b1242cb7372 Reviewed-by: David Schulz --- src/plugins/texteditor/basehoverhandler.cpp | 9 ------- src/plugins/texteditor/basehoverhandler.h | 28 +++++++++------------ 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp index 5e2ffac50f9..b5c1a46fb60 100644 --- a/src/plugins/texteditor/basehoverhandler.cpp +++ b/src/plugins/texteditor/basehoverhandler.cpp @@ -26,19 +26,10 @@ #include "basehoverhandler.h" #include "texteditor.h" -#include #include -#include - -using namespace Core; - namespace TextEditor { -BaseHoverHandler::BaseHoverHandler() : m_diagnosticTooltip(false), m_priority(-1) -{ -} - BaseHoverHandler::~BaseHoverHandler() {} diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h index cf9c8d7f90e..fe686ddcd4f 100644 --- a/src/plugins/texteditor/basehoverhandler.h +++ b/src/plugins/texteditor/basehoverhandler.h @@ -32,26 +32,30 @@ QT_BEGIN_NAMESPACE class QPoint; QT_END_NAMESPACE -namespace Core { class IEditor; } - namespace TextEditor { -class BaseTextEditor; class TextEditorWidget; class TEXTEDITOR_EXPORT BaseHoverHandler { public: - BaseHoverHandler(); virtual ~BaseHoverHandler(); QString contextHelpId(TextEditorWidget *widget, int pos); + int checkToolTip(TextEditorWidget *widget, int pos); void showToolTip(TextEditorWidget *widget, const QPoint &point, int pos); +protected: + enum { + Priority_None = 0, + Priority_Tooltip = 5, + Priority_Help = 10, + Priority_Diagnostic = 20 + }; + void setPriority(int priority); int priority() const; -protected: void setToolTip(const QString &tooltip); void appendToolTip(const QString &extension); const QString &toolTip() const; @@ -62,26 +66,18 @@ protected: void setLastHelpItemIdentified(const HelpItem &help); const HelpItem &lastHelpItemIdentified() const; + virtual void identifyMatch(TextEditorWidget *editorWidget, int pos); virtual void decorateToolTip(); virtual void operateTooltip(TextEditorWidget *editorWidget, const QPoint &point); - enum { - Priority_None = 0, - Priority_Tooltip = 5, - Priority_Help = 10, - Priority_Diagnostic = 20 - }; - void setPriority(int priority); private: void clear(); void process(TextEditorWidget *widget, int pos); - virtual void identifyMatch(TextEditorWidget *editorWidget, int pos); - - bool m_diagnosticTooltip; + bool m_diagnosticTooltip = false; QString m_toolTip; HelpItem m_lastHelpItemIdentified; - int m_priority; + int m_priority = -1; }; } // namespace TextEditor From a7e8406ced48818682e52ca208af94c18c8c837e Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Wed, 28 Jun 2017 14:43:13 +0200 Subject: [PATCH 11/28] TextEditor: Remove unneeded functions in BaseHoverHandler Change-Id: Ic61babb48cca0711812256b766f1db62895901f6 Reviewed-by: David Schulz --- src/plugins/cppeditor/cpphoverhandler.cpp | 10 +++++---- src/plugins/texteditor/basehoverhandler.cpp | 25 +++------------------ src/plugins/texteditor/basehoverhandler.h | 5 ----- 3 files changed, 9 insertions(+), 31 deletions(-) diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index 3f0ee1fdc4d..75b5913f17b 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -97,7 +97,7 @@ void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos) m_positionForEditorDocumentProcessor = -1; if (editorDocumentProcessorHasDiagnosticAt(editorWidget, pos)) { - setIsDiagnosticTooltip(true); + setPriority(Priority_Diagnostic); m_positionForEditorDocumentProcessor = pos; } else if (!editorWidget->extraSelectionTooltip(pos).isEmpty()) { setToolTip(editorWidget->extraSelectionTooltip(pos)); @@ -110,12 +110,14 @@ void CppHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos) evaluator.execute(); if (evaluator.hasDiagnosis()) { setToolTip(evaluator.diagnosis()); - setIsDiagnosticTooltip(true); + setPriority(Priority_Diagnostic); } if (evaluator.identifiedCppElement()) { const QSharedPointer &cppElement = evaluator.cppElement(); - if (!isDiagnosticTooltip()) + if (priority() != Priority_Diagnostic) { setToolTip(cppElement->tooltip); + setPriority(cppElement->tooltip.isEmpty() ? Priority_None : Priority_Tooltip); + } QStringList candidates = cppElement->helpIdCandidates; candidates.removeDuplicates(); foreach (const QString &helpId, candidates) { @@ -143,7 +145,7 @@ void CppHoverHandler::decorateToolTip() if (Qt::mightBeRichText(toolTip())) setToolTip(toolTip().toHtmlEscaped()); - if (isDiagnosticTooltip()) + if (priority() != Priority_Diagnostic) return; const HelpItem &help = lastHelpItemIdentified(); diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp index b5c1a46fb60..7764f12dbdd 100644 --- a/src/plugins/texteditor/basehoverhandler.cpp +++ b/src/plugins/texteditor/basehoverhandler.cpp @@ -55,9 +55,6 @@ int BaseHoverHandler::priority() const if (m_priority >= 0) return m_priority; - if (isDiagnosticTooltip()) - return Priority_Diagnostic; - if (lastHelpItemIdentified().isValid()) return Priority_Help; @@ -94,21 +91,6 @@ const QString &BaseHoverHandler::toolTip() const return m_toolTip; } -void BaseHoverHandler::appendToolTip(const QString &extension) -{ - m_toolTip.append(extension); -} - -void BaseHoverHandler::setIsDiagnosticTooltip(bool isDiagnosticTooltip) -{ - m_diagnosticTooltip = isDiagnosticTooltip; -} - -bool BaseHoverHandler::isDiagnosticTooltip() const -{ - return m_diagnosticTooltip; -} - void BaseHoverHandler::setLastHelpItemIdentified(const HelpItem &help) { m_lastHelpItemIdentified = help; @@ -121,7 +103,6 @@ const HelpItem &BaseHoverHandler::lastHelpItemIdentified() const void BaseHoverHandler::clear() { - m_diagnosticTooltip = false; m_toolTip.clear(); m_priority = -1; m_lastHelpItemIdentified = HelpItem(); @@ -146,11 +127,11 @@ void BaseHoverHandler::decorateToolTip() if (Qt::mightBeRichText(toolTip())) setToolTip(toolTip().toHtmlEscaped()); - if (!isDiagnosticTooltip() && lastHelpItemIdentified().isValid()) { + if (priority() != Priority_Diagnostic && lastHelpItemIdentified().isValid()) { const QString &contents = lastHelpItemIdentified().extractContent(false); if (!contents.isEmpty()) { - setToolTip(toolTip().toHtmlEscaped()); - appendToolTip(contents); + m_toolTip = toolTip().toHtmlEscaped(); + m_toolTip.append(contents); } } } diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h index fe686ddcd4f..351d8df490a 100644 --- a/src/plugins/texteditor/basehoverhandler.h +++ b/src/plugins/texteditor/basehoverhandler.h @@ -57,12 +57,8 @@ protected: int priority() const; void setToolTip(const QString &tooltip); - void appendToolTip(const QString &extension); const QString &toolTip() const; - void setIsDiagnosticTooltip(bool isDiagnosticTooltip); - bool isDiagnosticTooltip() const; - void setLastHelpItemIdentified(const HelpItem &help); const HelpItem &lastHelpItemIdentified() const; @@ -74,7 +70,6 @@ private: void clear(); void process(TextEditorWidget *widget, int pos); - bool m_diagnosticTooltip = false; QString m_toolTip; HelpItem m_lastHelpItemIdentified; int m_priority = -1; From 50790f61872b4b2fadf103f946561406b6732318 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Mon, 19 Jun 2017 12:17:59 +0200 Subject: [PATCH 12/28] TextEditor: Avoid unneeded calls in BaseHoverHandler In checkToolTip(), the call to decorateToolTip() is not needed since it does not affect the priority. In showToolTip(), we can assume that checkToolTip() was called and thus avoid a call to identifyMatch(). TextEditorWidgetPrivate::processTooltipRequest() is the only caller of checkToolTip() and showToolTip(). Change-Id: I362c697754b6a29c9c0b34f85d3022f00e3e1031 Reviewed-by: David Schulz --- src/plugins/texteditor/basehoverhandler.cpp | 13 +++---------- src/plugins/texteditor/basehoverhandler.h | 3 +-- src/plugins/texteditor/texteditor.cpp | 2 +- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp index 7764f12dbdd..abbf2154abf 100644 --- a/src/plugins/texteditor/basehoverhandler.cpp +++ b/src/plugins/texteditor/basehoverhandler.cpp @@ -33,11 +33,9 @@ namespace TextEditor { BaseHoverHandler::~BaseHoverHandler() {} -void BaseHoverHandler::showToolTip(TextEditorWidget *widget, const QPoint &point, int pos) +void BaseHoverHandler::showToolTip(TextEditorWidget *widget, const QPoint &point) { - widget->setContextHelpId(QString()); - - process(widget, pos); + decorateToolTip(); operateTooltip(widget, point); } @@ -101,18 +99,13 @@ const HelpItem &BaseHoverHandler::lastHelpItemIdentified() const return m_lastHelpItemIdentified; } -void BaseHoverHandler::clear() +void BaseHoverHandler::process(TextEditorWidget *widget, int pos) { m_toolTip.clear(); m_priority = -1; m_lastHelpItemIdentified = HelpItem(); -} -void BaseHoverHandler::process(TextEditorWidget *widget, int pos) -{ - clear(); identifyMatch(widget, pos); - decorateToolTip(); } void BaseHoverHandler::identifyMatch(TextEditorWidget *editorWidget, int pos) diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h index 351d8df490a..f5c8d757b7a 100644 --- a/src/plugins/texteditor/basehoverhandler.h +++ b/src/plugins/texteditor/basehoverhandler.h @@ -44,7 +44,7 @@ public: QString contextHelpId(TextEditorWidget *widget, int pos); int checkToolTip(TextEditorWidget *widget, int pos); - void showToolTip(TextEditorWidget *widget, const QPoint &point, int pos); + void showToolTip(TextEditorWidget *widget, const QPoint &point); protected: enum { @@ -67,7 +67,6 @@ protected: virtual void operateTooltip(TextEditorWidget *editorWidget, const QPoint &point); private: - void clear(); void process(TextEditorWidget *widget, int pos); QString m_toolTip; diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index e1652a8241e..7156ca120f4 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -3143,7 +3143,7 @@ void TextEditorWidgetPrivate::processTooltipRequest(const QTextCursor &c) } if (highest) - highest->showToolTip(q, toolTipPoint, c.position()); + highest->showToolTip(q, toolTipPoint); } bool TextEditorWidget::viewportEvent(QEvent *event) From 1f18848ee76d2f385c261e4fe984db62204063d4 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Tue, 13 Jun 2017 18:23:05 +0200 Subject: [PATCH 13/28] Clang: Cleanup more PrintTo functions Change-Id: If1389462479ae10b067904f05cf785c3d8fb9638 Reviewed-by: David Schulz Reviewed-by: Nikolai Kosjar --- src/libs/clangbackendipc/codecompletion.h | 4 ++-- .../clangbackend/ipcsource/clangdocument.cpp | 13 +++++++----- .../clangbackend/ipcsource/clangdocument.h | 2 +- .../clangbackend/ipcsource/clangstring.h | 7 ++----- .../clangbackend/ipcsource/clangtype.cpp | 13 +++++++----- src/tools/clangbackend/ipcsource/clangtype.h | 4 ++-- .../ipcsource/codecompletionsextractor.cpp | 18 +++++++---------- .../ipcsource/codecompletionsextractor.h | 6 +++--- src/tools/clangbackend/ipcsource/cursor.cpp | 20 ++++++++++--------- src/tools/clangbackend/ipcsource/cursor.h | 5 +++-- .../clangbackend/ipcsource/sourcelocation.cpp | 12 ++++++----- .../clangbackend/ipcsource/sourcelocation.h | 2 +- .../clangbackend/ipcsource/sourcerange.cpp | 13 ++++++------ .../clangbackend/ipcsource/sourcerange.h | 2 +- .../clangbackend/ipcsource/unsavedfile.cpp | 12 ++++++----- .../clangbackend/ipcsource/unsavedfile.h | 2 +- 16 files changed, 71 insertions(+), 64 deletions(-) diff --git a/src/libs/clangbackendipc/codecompletion.h b/src/libs/clangbackendipc/codecompletion.h index 4b9b2ed7c21..bd63115da09 100644 --- a/src/libs/clangbackendipc/codecompletion.h +++ b/src/libs/clangbackendipc/codecompletion.h @@ -208,6 +208,6 @@ private: CMBIPC_EXPORT QDebug operator<<(QDebug debug, CodeCompletion::Kind kind); -std::ostream &operator<<(std::ostream &os, const CodeCompletion::Kind kind); -std::ostream &operator<<(std::ostream &os, const CodeCompletion::Availability availability); +CMBIPC_EXPORT std::ostream &operator<<(std::ostream &os, const CodeCompletion::Kind kind); +CMBIPC_EXPORT std::ostream &operator<<(std::ostream &os, const CodeCompletion::Availability availability); } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangdocument.cpp b/src/tools/clangbackend/ipcsource/clangdocument.cpp index 117a77a8481..3cfcfabe092 100644 --- a/src/tools/clangbackend/ipcsource/clangdocument.cpp +++ b/src/tools/clangbackend/ipcsource/clangdocument.cpp @@ -423,12 +423,15 @@ bool operator==(const Document &first, const Document &second) && first.projectPart().id() == second.projectPart().id(); } -void PrintTo(const Document &document, ::std::ostream *os) +std::ostream &operator<<(std::ostream &os, const Document &document) { - *os << "Document(" - << document.filePath().constData() << ", " - << document.projectPart().id().constData() << ", " - << document.documentRevision() << ")"; + os << "(" + << document.filePath() << ", " + << document.projectPart().id() << ", " + << document.documentRevision() + << ")"; + + return os; } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangdocument.h b/src/tools/clangbackend/ipcsource/clangdocument.h index 138e96a9460..15555ace101 100644 --- a/src/tools/clangbackend/ipcsource/clangdocument.h +++ b/src/tools/clangbackend/ipcsource/clangdocument.h @@ -133,5 +133,5 @@ private: }; bool operator==(const Document &first, const Document &second); -void PrintTo(const Document &document, ::std::ostream *os); +std::ostream &operator<<(std::ostream &os, const Document &document); } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/clangstring.h b/src/tools/clangbackend/ipcsource/clangstring.h index 09049153abb..685055cff03 100644 --- a/src/tools/clangbackend/ipcsource/clangstring.h +++ b/src/tools/clangbackend/ipcsource/clangstring.h @@ -107,7 +107,6 @@ public: { return second == first; } - template::value>::type > @@ -124,11 +123,9 @@ public: return second == first; } - friend std::ostream &operator<<(std::ostream &out, const ClangString &string) + friend std::ostream &operator<<(std::ostream &os, const ClangString &string) { - out << string.cString(); - - return out; + return os << string.cString(); } private: diff --git a/src/tools/clangbackend/ipcsource/clangtype.cpp b/src/tools/clangbackend/ipcsource/clangtype.cpp index 6b14b38dd84..dd0e192f7a3 100644 --- a/src/tools/clangbackend/ipcsource/clangtype.cpp +++ b/src/tools/clangbackend/ipcsource/clangtype.cpp @@ -144,17 +144,20 @@ bool operator==(Type first, Type second) return clang_equalTypes(first.cxType, second.cxType); } -void PrintTo(CXTypeKind typeKind, ::std::ostream* os) +std::ostream &operator<<(std::ostream &os, CXTypeKind typeKind) { ClangString typeKindSpelling(clang_getTypeKindSpelling(typeKind)); - *os << typeKindSpelling.cString(); + + return os << typeKindSpelling.cString(); } -void PrintTo(const Type &type, ::std::ostream* os) +std::ostream &operator<<(std::ostream &os, const Type &type) { ClangString typeKindSpelling(clang_getTypeKindSpelling(type.kind())); - *os << typeKindSpelling.cString() - << ": \"" << type.spelling().cString() << "\""; + os << typeKindSpelling + << ": \"" << type.spelling() << "\""; + + return os; } diff --git a/src/tools/clangbackend/ipcsource/clangtype.h b/src/tools/clangbackend/ipcsource/clangtype.h index 71ea1506ee5..f26fe080f6b 100644 --- a/src/tools/clangbackend/ipcsource/clangtype.h +++ b/src/tools/clangbackend/ipcsource/clangtype.h @@ -77,6 +77,6 @@ private: bool operator==(Type first, Type second); -void PrintTo(CXTypeKind typeKind, ::std::ostream* os); -void PrintTo(const Type &type, ::std::ostream* os); +std::ostream &operator<<(std::ostream &os, CXTypeKind typeKind); +std::ostream &operator<<(std::ostream &os, const Type &type); } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp b/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp index cac1f50e290..1c810e50698 100644 --- a/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp +++ b/src/tools/clangbackend/ipcsource/codecompletionsextractor.cpp @@ -28,10 +28,6 @@ #include "clangstring.h" #include "codecompletionchunkconverter.h" -#ifdef CLANGBACKEND_TESTS -#include -#endif - #include namespace ClangBackEnd { @@ -344,15 +340,15 @@ const CodeCompletion &CodeCompletionsExtractor::currentCodeCompletion() const return currentCodeCompletion_; } -#ifdef CLANGBACKEND_TESTS -void PrintTo(const CodeCompletionsExtractor &extractor, std::ostream *os) +std::ostream &operator<<(std::ostream &os, const CodeCompletionsExtractor &extractor) { - *os << "name: " << ::testing::PrintToString(extractor.currentCodeCompletion().text()) - << ", kind: " << ::testing::PrintToString(extractor.currentCodeCompletion().completionKind()) - << ", priority: " << extractor.currentCodeCompletion().priority() - << ", kind: " << ::testing::PrintToString(extractor.currentCodeCompletion().availability()); + os << "name: " << extractor.currentCodeCompletion().text() + << ", kind: " << extractor.currentCodeCompletion().completionKind() + << ", priority: " << extractor.currentCodeCompletion().priority() + << ", kind: " << extractor.currentCodeCompletion().availability(); + + return os; } -#endif } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/codecompletionsextractor.h b/src/tools/clangbackend/ipcsource/codecompletionsextractor.h index 8a4c7c03ab1..57e9bd5afcf 100644 --- a/src/tools/clangbackend/ipcsource/codecompletionsextractor.h +++ b/src/tools/clangbackend/ipcsource/codecompletionsextractor.h @@ -31,6 +31,8 @@ #include +#include + namespace ClangBackEnd { class CodeCompletionsExtractor @@ -78,7 +80,5 @@ private: uint cxCodeCompleteResultIndex = -1; }; -#ifdef CLANGBACKEND_TESTS -void PrintTo(const CodeCompletionsExtractor &extractor, ::std::ostream* os); -#endif +std::ostream &operator<<(std::ostream &os, const CodeCompletionsExtractor &extractor); } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/cursor.cpp b/src/tools/clangbackend/ipcsource/cursor.cpp index c9f8dd5ab81..518fd013d24 100644 --- a/src/tools/clangbackend/ipcsource/cursor.cpp +++ b/src/tools/clangbackend/ipcsource/cursor.cpp @@ -403,29 +403,31 @@ bool operator!=(const Cursor &first, const Cursor &second) return !(first == second); } -void PrintTo(CXCursorKind cursorKind, ::std::ostream *os) +std::ostream &operator<<(std::ostream &os, CXCursorKind cursorKind) { ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursorKind)); - *os << cursorKindSpelling.cString(); + return os << cursorKindSpelling.cString(); } -void PrintTo(const Cursor &cursor, ::std::ostream*os) +std::ostream &operator<<(std::ostream &os, const Cursor &cursor) { if (cursor.isValid()) { ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursor.kind())); - *os << cursorKindSpelling.cString() << " "; + os << cursorKindSpelling << " "; auto identifier = cursor.displayName(); if (identifier.hasContent()) { - *os << "\"" - << identifier - << "\": "; + os << "\"" + << identifier + << "\": "; } - PrintTo(cursor.sourceLocation(), os); + os << cursor.sourceLocation(); } else { - *os << "Invalid cursor!"; + os << "Invalid cursor!"; } + + return os; } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/cursor.h b/src/tools/clangbackend/ipcsource/cursor.h index 234ad900f9e..0187d8448b1 100644 --- a/src/tools/clangbackend/ipcsource/cursor.h +++ b/src/tools/clangbackend/ipcsource/cursor.h @@ -130,6 +130,7 @@ void Cursor::visit(VisitorCallback visitorCallback) const bool operator==(const Cursor &first, const Cursor &second); bool operator!=(const Cursor &first, const Cursor &second); -void PrintTo(CXCursorKind cursorKind, ::std::ostream *os); -void PrintTo(const Cursor &cursor, ::std::ostream* os); +std::ostream &operator<<(std::ostream &os, CXCursorKind cursorKind); +std::ostream &operator<<(std::ostream &os, const Cursor &cursor); + } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/sourcelocation.cpp b/src/tools/clangbackend/ipcsource/sourcelocation.cpp index 5d54600c3c5..161ed5b0a50 100644 --- a/src/tools/clangbackend/ipcsource/sourcelocation.cpp +++ b/src/tools/clangbackend/ipcsource/sourcelocation.cpp @@ -114,15 +114,17 @@ SourceLocation::operator CXSourceLocation() const return cxSourceLocation; } -void PrintTo(const SourceLocation &sourceLocation, std::ostream *os) +std::ostream &operator<<(std::ostream &os, const SourceLocation &sourceLocation) { auto filePath = sourceLocation.filePath(); if (filePath.hasContent()) - *os << filePath.constData() << ", "; + os << filePath << ", "; - *os << "line: " << sourceLocation.line() - << ", column: "<< sourceLocation.column() - << ", offset: "<< sourceLocation.offset(); + os << "line: " << sourceLocation.line() + << ", column: "<< sourceLocation.column() + << ", offset: "<< sourceLocation.offset(); + + return os; } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/sourcelocation.h b/src/tools/clangbackend/ipcsource/sourcelocation.h index 7379773e500..65c3ec69ad6 100644 --- a/src/tools/clangbackend/ipcsource/sourcelocation.h +++ b/src/tools/clangbackend/ipcsource/sourcelocation.h @@ -72,6 +72,6 @@ private: bool operator==(const SourceLocation &first, const SourceLocation &second); -void PrintTo(const SourceLocation &sourceLocation, ::std::ostream* os); +std::ostream &operator<<(std::ostream &os, const SourceLocation &sourceLocation); } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/sourcerange.cpp b/src/tools/clangbackend/ipcsource/sourcerange.cpp index 86029cfd3ee..20c6efb5e65 100644 --- a/src/tools/clangbackend/ipcsource/sourcerange.cpp +++ b/src/tools/clangbackend/ipcsource/sourcerange.cpp @@ -100,13 +100,14 @@ bool operator==(const SourceRange &first, const SourceRange &second) return clang_equalRanges(first.cxSourceRange, second.cxSourceRange); } -void PrintTo(const SourceRange &sourceRange, ::std::ostream* os) +std::ostream &operator<<(std::ostream &os, const SourceRange &sourceRange) { - *os << "["; - PrintTo(sourceRange.start(), os); - *os << ", "; - PrintTo(sourceRange.end(), os); - *os << "]"; + os << "[" + << sourceRange.start() << ", " + << sourceRange.end() + << "]"; + + return os; } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/sourcerange.h b/src/tools/clangbackend/ipcsource/sourcerange.h index 955896ccfb0..b8083e86955 100644 --- a/src/tools/clangbackend/ipcsource/sourcerange.h +++ b/src/tools/clangbackend/ipcsource/sourcerange.h @@ -61,5 +61,5 @@ private: }; bool operator==(const SourceRange &first, const SourceRange &second); -void PrintTo(const SourceRange &sourceRange, ::std::ostream* os); +std::ostream &operator<<(std::ostream &os, const SourceRange &sourceRange); } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/unsavedfile.cpp b/src/tools/clangbackend/ipcsource/unsavedfile.cpp index 8822e2939ef..923d4456e8a 100644 --- a/src/tools/clangbackend/ipcsource/unsavedfile.cpp +++ b/src/tools/clangbackend/ipcsource/unsavedfile.cpp @@ -97,12 +97,14 @@ bool UnsavedFile::replaceAt(uint position, uint length, const Utf8String &replac return false; } -void PrintTo(const UnsavedFile &unsavedFile, std::ostream *os) +std::ostream &operator<<(std::ostream &os, const UnsavedFile &unsavedFile) { - *os << "UnsavedFile(" - << unsavedFile.m_filePath.constData() << ", " - << unsavedFile.m_fileContent.constData() << ", " - << unsavedFile.m_fileContent.byteSize() << ")"; + os << "UnsavedFile(" + << unsavedFile.m_filePath << ", " + << unsavedFile.m_fileContent << ", " + << unsavedFile.m_fileContent << ")"; + + return os; } } // namespace ClangBackEnd diff --git a/src/tools/clangbackend/ipcsource/unsavedfile.h b/src/tools/clangbackend/ipcsource/unsavedfile.h index ff1f354c878..3021da89b5c 100644 --- a/src/tools/clangbackend/ipcsource/unsavedfile.h +++ b/src/tools/clangbackend/ipcsource/unsavedfile.h @@ -34,7 +34,7 @@ using uint = unsigned int; class UnsavedFile { public: - friend void PrintTo(const UnsavedFile &unsavedFile, std::ostream *os); + friend std::ostream &operator<<(std::ostream &os, const UnsavedFile &unsavedFile); UnsavedFile(); UnsavedFile(const Utf8String &filePath, const Utf8String &fileContent); From 202d4a52a0940d6e2ee34d75f39c8c6c2812ae84 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 29 Jun 2017 10:37:51 +0200 Subject: [PATCH 14/28] Clang: Fix build with QTC_NO_CLANG_LIBTOOLING ...caused by commit f5d68398d51116bb8dc61e8699dd607076862d96 Clang: Fix canceling of clang query Change-Id: Ic48485aed1d23e1ddd2f7bc1e37a797d2c2498c6 Reviewed-by: Tim Jenssen --- .../source/clangrefactoringbackend-source.pri | 12 +++++------- tests/unit/unittest/unittest.pro | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri index 37d503f210c..7a695e5ca4d 100644 --- a/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri +++ b/src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri @@ -1,8 +1,7 @@ INCLUDEPATH += $$PWD HEADERS += \ - $$PWD/clangrefactoringbackend_global.h \ - $$PWD/clangquerygatherer.h + $$PWD/clangrefactoringbackend_global.h !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ @@ -15,7 +14,8 @@ SOURCES += \ $$PWD/clangquery.cpp \ $$PWD/clangtool.cpp \ $$PWD/sourcerangeextractor.cpp \ - $$PWD/locationsourcefilecallbacks.cpp + $$PWD/locationsourcefilecallbacks.cpp \ + $$PWD/clangquerygatherer.cpp HEADERS += \ $$PWD/refactoringcompilationdatabase.h \ @@ -30,8 +30,6 @@ HEADERS += \ $$PWD/clangquery.h \ $$PWD/clangtool.h \ $$PWD/sourcerangeextractor.h \ - $$PWD/locationsourcefilecallbacks.h + $$PWD/locationsourcefilecallbacks.h \ + $$PWD/clangquerygatherer.h } - -SOURCES += \ - $$PWD/clangquerygatherer.cpp diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index 054ae386e59..73e0ed31a3f 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -63,7 +63,6 @@ SOURCES += \ projectupdater-test.cpp \ pchmanagerserver-test.cpp \ pchmanagerclientserverinprocess-test.cpp \ - clangquerygatherer-test.cpp !isEmpty(LIBCLANG_LIBS) { SOURCES += \ @@ -125,6 +124,7 @@ SOURCES += \ !isEmpty(LIBTOOLING_LIBS) { SOURCES += \ clangquery-test.cpp \ + clangquerygatherer-test.cpp \ clangqueryprojectfindfilter-test.cpp \ refactoringclientserverinprocess-test.cpp \ refactoringclient-test.cpp \ From ba1a657227e8673da709b32f81b428b0441ff31b Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Thu, 2 Feb 2017 15:05:32 +0100 Subject: [PATCH 15/28] AutoTest: Make test tree root items checkable This allows (de)selecting of all test cases of a specific test framework. Change-Id: I21357d3dbcfce73387f157b1b40686f437fa260b Reviewed-by: David Schulz --- src/plugins/autotest/gtest/gtesttreeitem.cpp | 1 + src/plugins/autotest/qtest/qttesttreeitem.cpp | 1 - src/plugins/autotest/quick/quicktesttreeitem.cpp | 1 - src/plugins/autotest/testtreeitem.cpp | 15 +++++++++------ src/plugins/autotest/testtreeitem.h | 2 ++ src/plugins/autotest/testtreemodel.cpp | 8 ++++++++ src/plugins/autotest/testtreeview.cpp | 4 ++++ 7 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/plugins/autotest/gtest/gtesttreeitem.cpp b/src/plugins/autotest/gtest/gtesttreeitem.cpp index 5e2766cb30d..b9308a4e737 100644 --- a/src/plugins/autotest/gtest/gtesttreeitem.cpp +++ b/src/plugins/autotest/gtest/gtesttreeitem.cpp @@ -57,6 +57,7 @@ QVariant GTestTreeItem::data(int column, int role) const } case Qt::CheckStateRole: switch (type()) { + case Root: case TestCase: case TestFunctionOrSet: return checked(); diff --git a/src/plugins/autotest/qtest/qttesttreeitem.cpp b/src/plugins/autotest/qtest/qttesttreeitem.cpp index 2b4ad6d6c2d..48fa4a9de9e 100644 --- a/src/plugins/autotest/qtest/qttesttreeitem.cpp +++ b/src/plugins/autotest/qtest/qttesttreeitem.cpp @@ -49,7 +49,6 @@ QVariant QtTestTreeItem::data(int column, int role) const return QVariant(name() + nameSuffix()); case Qt::CheckStateRole: switch (type()) { - case Root: case TestDataFunction: case TestSpecialFunction: return QVariant(); diff --git a/src/plugins/autotest/quick/quicktesttreeitem.cpp b/src/plugins/autotest/quick/quicktesttreeitem.cpp index 5576f97b09f..c4de28c6915 100644 --- a/src/plugins/autotest/quick/quicktesttreeitem.cpp +++ b/src/plugins/autotest/quick/quicktesttreeitem.cpp @@ -50,7 +50,6 @@ QVariant QuickTestTreeItem::data(int column, int role) const break; case Qt::CheckStateRole: switch (type()) { - case Root: case TestDataFunction: case TestSpecialFunction: case TestDataTag: diff --git a/src/plugins/autotest/testtreeitem.cpp b/src/plugins/autotest/testtreeitem.cpp index 7f1992ae583..3bfa4400c5e 100644 --- a/src/plugins/autotest/testtreeitem.cpp +++ b/src/plugins/autotest/testtreeitem.cpp @@ -42,7 +42,8 @@ TestTreeItem::TestTreeItem(const QString &name, const QString &filePath, Type ty m_filePath(filePath), m_type(type) { - m_checked = (m_type == TestCase || m_type == TestFunctionOrSet) ? Qt::Checked : Qt::Unchecked; + m_checked = (m_type == TestCase || m_type == TestFunctionOrSet || m_type == Root) + ? Qt::Checked : Qt::Unchecked; } static QIcon testTreeIcon(TestTreeItem::Type type) @@ -103,7 +104,7 @@ Qt::ItemFlags TestTreeItem::flags(int /*column*/) const static const Qt::ItemFlags defaultFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; switch (m_type) { case Root: - return Qt::ItemIsEnabled; + return Qt::ItemIsEnabled | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable; case TestCase: return defaultFlags | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable; case TestFunctionOrSet: @@ -161,13 +162,14 @@ void TestTreeItem::setChecked(const Qt::CheckState checkState) parent->revalidateCheckState(); break; } + case Root: case TestFunctionOrSet: case TestCase: { Qt::CheckState usedState = (checkState == Qt::Unchecked ? Qt::Unchecked : Qt::Checked); for (int row = 0, count = childCount(); row < count; ++row) childItem(row)->setChecked(usedState); m_checked = usedState; - if (m_type == TestFunctionOrSet) { + if (m_type != Root) { if (auto parent = parentItem()) parent->revalidateCheckState(); } @@ -181,6 +183,7 @@ void TestTreeItem::setChecked(const Qt::CheckState checkState) Qt::CheckState TestTreeItem::checked() const { switch (m_type) { + case Root: case TestCase: case TestFunctionOrSet: case TestDataTag: @@ -295,7 +298,7 @@ QSet TestTreeItem::internalTargets() const void TestTreeItem::revalidateCheckState() { const Type ttiType = type(); - if (ttiType != TestCase && ttiType != TestFunctionOrSet) + if (ttiType != TestCase && ttiType != TestFunctionOrSet && ttiType != Root) return; if (childCount() == 0) // can this happen? (we're calling revalidateCS() on parentItem() return; @@ -317,13 +320,13 @@ void TestTreeItem::revalidateCheckState() foundPartiallyChecked |= (child->checked() == Qt::PartiallyChecked); if (foundPartiallyChecked || (foundChecked && foundUnchecked)) { m_checked = Qt::PartiallyChecked; - if (ttiType == TestFunctionOrSet) + if (ttiType == TestFunctionOrSet || ttiType == TestCase) parentItem()->revalidateCheckState(); return; } } m_checked = (foundUnchecked ? Qt::Unchecked : Qt::Checked); - if (ttiType == TestFunctionOrSet) + if (ttiType == TestFunctionOrSet || ttiType == TestCase) parentItem()->revalidateCheckState(); } diff --git a/src/plugins/autotest/testtreeitem.h b/src/plugins/autotest/testtreeitem.h index 530a105e275..2c2c728a2c7 100644 --- a/src/plugins/autotest/testtreeitem.h +++ b/src/plugins/autotest/testtreeitem.h @@ -135,6 +135,8 @@ private: unsigned m_column = 0; QString m_proFile; Status m_status = NewlyAdded; + + friend class TestTreeModel; // grant access to (private) revalidateCheckState() }; class TestCodeLocationAndType diff --git a/src/plugins/autotest/testtreemodel.cpp b/src/plugins/autotest/testtreemodel.cpp index d3cba6c76d1..cd27377b071 100644 --- a/src/plugins/autotest/testtreemodel.cpp +++ b/src/plugins/autotest/testtreemodel.cpp @@ -110,6 +110,7 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int emit dataChanged(index, index); if (role == Qt::CheckStateRole) { switch (item->type()) { + case TestTreeItem::Root: case TestTreeItem::TestCase: if (item->childCount() > 0) emit dataChanged(index.child(0, 0), index.child(item->childCount() - 1, 0)); @@ -228,6 +229,7 @@ bool TestTreeModel::sweepChildren(TestTreeItem *item) if (child->type() != TestTreeItem::Root && child->markedForRemoval()) { destroyItem(child); + item->revalidateCheckState(); hasChanged = true; } else if (child->hasChildren()) { hasChanged |= sweepChildren(child); @@ -266,6 +268,12 @@ void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeIte TestTreeItem *newItem = result->createTestTreeItem(); QTC_ASSERT(newItem, return); parentNode->appendChild(newItem); + // new items are checked by default - revalidation of parents might be necessary + if (parentNode->checked() != Qt::Checked) { + parentNode->revalidateCheckState(); + const QModelIndex &idx = indexForItem(parentNode); + emit dataChanged(idx, idx); + } } void TestTreeModel::removeAllTestItems() diff --git a/src/plugins/autotest/testtreeview.cpp b/src/plugins/autotest/testtreeview.cpp index 9cd20644f83..a6bbe91b909 100644 --- a/src/plugins/autotest/testtreeview.cpp +++ b/src/plugins/autotest/testtreeview.cpp @@ -82,6 +82,10 @@ void TestTreeView::changeCheckStateAll(const Qt::CheckState checkState) item->setChecked(checkState); } } + if (count == 0) { + if (auto item = static_cast(currentRootIndex.internalPointer())) + item->setChecked(checkState); + } emit dataChanged(currentRootIndex, last); } } From f501c19ebc8dba4cc1ee2dfb481e9297d7e0d5ab Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 15 Jun 2017 11:15:24 +0200 Subject: [PATCH 16/28] Wizards: factor out registerFieldName() for later use Change-Id: Iaca37b246339b1329b7f3364e0686f25615e0e6b Reviewed-by: Tobias Hunger --- src/libs/utils/wizardpage.cpp | 8 ++++++-- src/libs/utils/wizardpage.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libs/utils/wizardpage.cpp b/src/libs/utils/wizardpage.cpp index ff342665e5b..42cb46ba4dd 100644 --- a/src/libs/utils/wizardpage.cpp +++ b/src/libs/utils/wizardpage.cpp @@ -55,14 +55,18 @@ void WizardPage::pageWasAdded() void WizardPage::registerFieldWithName(const QString &name, QWidget *widget, const char *property, const char *changedSignal) +{ + registerFieldName(name); + registerField(name, widget, property, changedSignal); +} + +void WizardPage::registerFieldName(const QString &name) { Wizard *wiz = qobject_cast(wizard()); if (wiz) wiz->registerFieldName(name); else m_toRegister.insert(name); - - registerField(name, widget, property, changedSignal); } bool WizardPage::handleReject() diff --git a/src/libs/utils/wizardpage.h b/src/libs/utils/wizardpage.h index c9f9a462eca..16944668ea1 100644 --- a/src/libs/utils/wizardpage.h +++ b/src/libs/utils/wizardpage.h @@ -54,6 +54,8 @@ signals: void reportError(const QString &errorMessage); private: + void registerFieldName(const QString &name); + QSet m_toRegister; }; From ef7c633de2692f2c4e909a1a8f1a24ef0772256d Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 14 Jun 2017 14:59:23 +0200 Subject: [PATCH 17/28] Android: Re-enable QmlProfiler Change-Id: Icd73475be421e6813b0d496020461e7020b547dd Reviewed-by: hjk Reviewed-by: Christian Stenger --- src/libs/qmldebug/qmldebugclient.cpp | 2 +- src/plugins/android/androidanalyzesupport.cpp | 61 +++++-------------- src/plugins/android/androidanalyzesupport.h | 12 ++-- src/plugins/android/androidrunfactories.cpp | 4 +- src/plugins/android/androidrunner.cpp | 22 ++++++- src/plugins/android/androidrunner.h | 10 ++- .../projectexplorer/runconfiguration.cpp | 3 +- .../projectexplorer/runconfiguration.h | 1 - .../qmlprofiler/qmlprofilerruncontrol.cpp | 4 +- 9 files changed, 55 insertions(+), 64 deletions(-) diff --git a/src/libs/qmldebug/qmldebugclient.cpp b/src/libs/qmldebug/qmldebugclient.cpp index a1ac4ecddf2..597281ab258 100644 --- a/src/libs/qmldebug/qmldebugclient.cpp +++ b/src/libs/qmldebug/qmldebugclient.cpp @@ -365,7 +365,7 @@ void QmlDebugConnection::connectToHost(const QString &hostName, quint16 port) }); connect(socket, &QAbstractSocket::connected, this, &QmlDebugConnection::socketConnected); connect(socket, &QAbstractSocket::disconnected, this, &QmlDebugConnection::socketDisconnected); - socket->connectToHost(hostName, port); + socket->connectToHost(hostName.isEmpty() ? QString("localhost") : hostName, port); } void QmlDebugConnection::startLocalServer(const QString &fileName) diff --git a/src/plugins/android/androidanalyzesupport.cpp b/src/plugins/android/androidanalyzesupport.cpp index 38d84d48630..eaea7196ba9 100644 --- a/src/plugins/android/androidanalyzesupport.cpp +++ b/src/plugins/android/androidanalyzesupport.cpp @@ -24,66 +24,37 @@ ****************************************************************************/ #include "androidanalyzesupport.h" - #include "androidrunner.h" -#include "androidmanager.h" -#include - -#include -#include -#include - -#include - -using namespace Debugger; using namespace ProjectExplorer; namespace Android { namespace Internal { -AndroidAnalyzeSupport::AndroidAnalyzeSupport(RunControl *runControl) +AndroidQmlProfilerSupport::AndroidQmlProfilerSupport(RunControl *runControl) : RunWorker(runControl) { - setDisplayName("AndroidAnalyzeSupport"); - - RunConfiguration *runConfig = runControl->runConfiguration(); - runControl->setDisplayName(AndroidManager::packageName(runConfig->target())); - runControl->setConnection(UrlConnection::localHostWithoutPort()); + setDisplayName("AndroidQmlProfilerSupport"); auto runner = new AndroidRunner(runControl); + addDependency(runner); - connect(runControl, &RunControl::finished, runner, [runner] { runner->stop(); }); + auto profiler = runControl->createWorker(runControl->runMode()); + profiler->addDependency(this); - connect(runControl, &RunControl::starting, runner, [runner] { runner->start(); }); + connect(runner, &AndroidRunner::qmlServerReady, [this, runner, profiler](const QUrl &server) { + profiler->recordData("QmlServerUrl", server); + reportStarted(); + }); +} - connect(&m_outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort, this, - [this, runControl](Utils::Port) { - runControl->notifyRemoteSetupDone(m_qmlPort); - }); +void AndroidQmlProfilerSupport::start() +{ +} -// connect(runner, &AndroidRunner::handleRemoteProcessStarted, this, -// [this](Utils::Port, Utils::Port qmlPort) { -// m_qmlPort = qmlPort; -// }); - -// connect(runner, &AndroidRunner::handleRemoteProcessFinished, this, -// [this, runControl](const QString &errorMsg) { -// runControl->notifyRemoteFinished(); -// appendMessage(errorMsg, Utils::NormalMessageFormat); -// }); - - connect(runner, &AndroidRunner::remoteErrorOutput, this, - [this, runControl](const QString &msg) { - appendMessage(msg, Utils::StdErrFormatSameLine); - m_outputParser.processOutput(msg); - }); - - connect(runner, &AndroidRunner::remoteOutput, this, - [this, runControl](const QString &msg) { - appendMessage(msg, Utils::StdOutFormatSameLine); - m_outputParser.processOutput(msg); - }); +void AndroidQmlProfilerSupport::stop() +{ + reportStopped(); } } // namespace Internal diff --git a/src/plugins/android/androidanalyzesupport.h b/src/plugins/android/androidanalyzesupport.h index c9ceb45146c..b788bf40a6b 100644 --- a/src/plugins/android/androidanalyzesupport.h +++ b/src/plugins/android/androidanalyzesupport.h @@ -25,25 +25,21 @@ #pragma once -#include "androidrunconfiguration.h" - #include -#include - namespace Android { namespace Internal { -class AndroidAnalyzeSupport : public ProjectExplorer::RunWorker +class AndroidQmlProfilerSupport : public ProjectExplorer::RunWorker { Q_OBJECT public: - explicit AndroidAnalyzeSupport(ProjectExplorer::RunControl *runControl); + explicit AndroidQmlProfilerSupport(ProjectExplorer::RunControl *runControl); private: - QmlDebug::QmlOutputParser m_outputParser; - Utils::Port m_qmlPort; + void start() override; + void stop() override; }; } // namespace Internal diff --git a/src/plugins/android/androidrunfactories.cpp b/src/plugins/android/androidrunfactories.cpp index 7d4e4a79452..3f894783c71 100644 --- a/src/plugins/android/androidrunfactories.cpp +++ b/src/plugins/android/androidrunfactories.cpp @@ -71,9 +71,7 @@ RunControl *AndroidRunControlFactory::create(RunConfiguration *runConfig, Core:: } if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { auto runControl = new RunControl(runConfig, mode); - auto profiler = runControl->createWorker(mode); - auto profilee = new AndroidAnalyzeSupport(runControl); - profiler->addDependency(profilee); + (void) new AndroidQmlProfilerSupport(runControl); return runControl; } QTC_CHECK(false); // The other run modes are not supported diff --git a/src/plugins/android/androidrunner.cpp b/src/plugins/android/androidrunner.cpp index f6d4ce20325..4a62e028fe9 100644 --- a/src/plugins/android/androidrunner.cpp +++ b/src/plugins/android/androidrunner.cpp @@ -34,6 +34,7 @@ #include "androidavdmanager.h" #include +#include #include #include #include @@ -632,7 +633,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid) // Don't write to m_psProc from a different thread QTC_ASSERT(QThread::currentThread() == thread(), return); m_processPID = pid; - if (m_processPID == -1) { + if (pid == -1) { emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.") .arg(m_packageName)); // App died/killed. Reset log and monitor processes. @@ -714,6 +715,9 @@ AndroidRunner::AndroidRunner(RunControl *runControl) connect(m_worker.data(), &AndroidRunnerWorker::remoteErrorOutput, this, &AndroidRunner::remoteErrorOutput); + connect(&m_outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort, + this, &AndroidRunner::qmlServerPortReady); + m_thread.start(); } @@ -749,14 +753,28 @@ void AndroidRunner::stop() emit asyncStop(m_androidRunnable); } +void AndroidRunner::qmlServerPortReady(Port port) +{ + // FIXME: Note that the passed is nonsense, as the port is on the + // device side. It only happens to work since we redirect + // host port n to target port n via adb. + QUrl serverUrl; + serverUrl.setPort(port.number()); + emit qmlServerReady(serverUrl); +} + void AndroidRunner::remoteOutput(const QString &output) { + Core::MessageManager::write("LOGCAT: " + output, Core::MessageManager::Silent); appendMessage(output, Utils::StdOutFormatSameLine); + m_outputParser.processOutput(output); } void AndroidRunner::remoteErrorOutput(const QString &output) { + Core::MessageManager::write("LOGCAT: " + output, Core::MessageManager::Silent); appendMessage(output, Utils::StdErrFormatSameLine); + m_outputParser.processOutput(output); } void AndroidRunner::handleRemoteProcessStarted(Utils::Port gdbServerPort, Utils::Port qmlServerPort, int pid) @@ -770,6 +788,8 @@ void AndroidRunner::handleRemoteProcessStarted(Utils::Port gdbServerPort, Utils: void AndroidRunner::handleRemoteProcessFinished(const QString &errString) { appendMessage(errString, Utils::DebugFormat); + if (runControl()->isRunning()) + runControl()->initiateStop(); reportStopped(); } diff --git a/src/plugins/android/androidrunner.h b/src/plugins/android/androidrunner.h index 9c5f3dd7814..cf24d8423bf 100644 --- a/src/plugins/android/androidrunner.h +++ b/src/plugins/android/androidrunner.h @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -62,18 +63,20 @@ public: void start() override; void stop() override; - virtual void remoteOutput(const QString &output); - virtual void remoteErrorOutput(const QString &output); - signals: void asyncStart(const AndroidRunnable &runnable); void asyncStop(const AndroidRunnable &runnable); void remoteDebuggerRunning(); + void qmlServerReady(const QUrl &serverUrl); void adbParametersChanged(const QString &packageName, const QStringList &selector); void avdDetected(); private: + void qmlServerPortReady(Utils::Port port); + void remoteOutput(const QString &output); + void remoteErrorOutput(const QString &output); + void gotRemoteOutput(const QString &output); void handleRemoteProcessStarted(Utils::Port gdbServerPort, Utils::Port qmlServerPort, int pid); void handleRemoteProcessFinished(const QString &errString = QString()); void checkAVD(); @@ -88,6 +91,7 @@ private: Utils::Port m_gdbServerPort; Utils::Port m_qmlServerPort; Utils::ProcessHandle m_pid; + QmlDebug::QmlOutputParser m_outputParser; }; } // namespace Internal diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index 76f4dbcffec..338681ce854 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include @@ -1178,7 +1179,7 @@ void RunControlPrivate::setState(RunControlState newState) void RunControlPrivate::debugMessage(const QString &msg) { - //q->appendMessage(msg + '\n', Utils::DebugFormat); + Core::MessageManager::write(msg, Core::MessageManager::Silent); qCDebug(statesLog()) << msg; } diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index a1f48e904c0..4d7f927f81b 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -523,7 +523,6 @@ signals: void appendMessageRequested(ProjectExplorer::RunControl *runControl, const QString &msg, Utils::OutputFormat format); void aboutToStart(); - void starting(); void started(); void finished(); void applicationProcessHandleChanged(QPrivateSignal); // Use setApplicationProcessHandle diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp index f84b435fe1c..4525b72e11e 100644 --- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp +++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp @@ -114,7 +114,7 @@ void QmlProfilerRunner::start() QUrl serverUrl = this->serverUrl(); if (serverUrl.port() != -1) { - auto clientManager = Internal::QmlProfilerTool::clientManager(); + QmlProfilerClientManager *clientManager = Internal::QmlProfilerTool::clientManager(); clientManager->setServerUrl(serverUrl); clientManager->connectToTcpServer(); } @@ -149,6 +149,7 @@ void QmlProfilerRunner::stop() } break; } + reportStopped(); } void QmlProfilerRunner::notifyRemoteFinished() @@ -232,6 +233,7 @@ void QmlProfilerRunner::notifyRemoteSetupDone(Utils::Port port) auto clientManager = Internal::QmlProfilerTool::clientManager(); clientManager->setServerUrl(serverUrl); clientManager->connectToTcpServer(); + reportStarted(); } } From 3418070a4f40046c3b464f57f0987f7d3c095c7e Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 28 Jun 2017 18:45:57 +0200 Subject: [PATCH 18/28] Valgrind: Remove CallgrindController's use of ValgrindProcess It's simply one-shot command execution, using (only some part of) the ValgrindProcess machinery that just happens to also to wrap a process is conceptually different from ValgrindProcess that "is" the valgrind-with-debuggee entity (and an unneeded dependency) Change-Id: I57a2c3d1cab6b15e59cb41b8e131948c170297b6 Reviewed-by: Christian Kandeler --- .../callgrind/callgrindcontroller.cpp | 124 +++++++++++------- .../valgrind/callgrind/callgrindcontroller.h | 47 ++++--- src/plugins/valgrind/callgrindengine.cpp | 31 +++-- src/plugins/valgrind/memcheckengine.cpp | 6 +- src/plugins/valgrind/memcheckengine.h | 2 +- src/plugins/valgrind/valgrindprocess.cpp | 22 ++-- src/plugins/valgrind/valgrindprocess.h | 7 +- src/plugins/valgrind/valgrindrunner.cpp | 44 ++++--- src/plugins/valgrind/valgrindrunner.h | 4 +- 9 files changed, 158 insertions(+), 129 deletions(-) diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp index b28c5a98af7..5bc4b2515d0 100644 --- a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp +++ b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp @@ -24,28 +24,31 @@ ****************************************************************************/ #include "callgrindcontroller.h" -#include "../valgrindprocess.h" + +#include +#include + +#include +#include +#include +#include +#include #include #include - -#include -#include -#include -#include +#include #define CALLGRIND_CONTROL_DEBUG 0 -const QLatin1String CALLGRIND_CONTROL_BINARY("callgrind_control"); +using namespace ProjectExplorer; +using namespace Utils; namespace Valgrind { namespace Callgrind { -CallgrindController::CallgrindController(QObject *parent) - : QObject(parent) - , m_process(0) - , m_valgrindProc(0) - , m_lastOption(Unknown) +const QLatin1String CALLGRIND_CONTROL_BINARY("callgrind_control"); + +CallgrindController::CallgrindController() { } @@ -54,7 +57,7 @@ CallgrindController::~CallgrindController() cleanupTempFile(); } -QString toOptionString(CallgrindController::Option option) +static QString toOptionString(CallgrindController::Option option) { /* callgrind_control help from v3.9.0 @@ -86,23 +89,15 @@ QString toOptionString(CallgrindController::Option option) void CallgrindController::run(Option option) { - if (m_process) { + if (m_controllerProcess) { emit statusMessage(tr("Previous command has not yet finished.")); return; } - QTC_ASSERT(m_valgrindProc, return); - - m_process = new ValgrindProcess(m_valgrindProc->device(), this); - - connect(m_process, &ValgrindProcess::finished, - this, &CallgrindController::processFinished); - connect(m_process, &ValgrindProcess::error, - this, &CallgrindController::processError); // save back current running operation m_lastOption = option; - const QString optionString = toOptionString(option); + m_controllerProcess = new ApplicationLauncher; switch (option) { case CallgrindController::Dump: @@ -122,31 +117,49 @@ void CallgrindController::run(Option option) } #if CALLGRIND_CONTROL_DEBUG - m_process->setProcessChannelMode(QProcess::ForwardedChannels); + m_controllerProcess->setProcessChannelMode(QProcess::ForwardedChannels); #endif - const int pid = Utils::HostOsInfo::isWindowsHost() ? 0 : m_valgrindProc->pid(); - m_process->setValgrindExecutable(CALLGRIND_CONTROL_BINARY); - m_process->setValgrindArguments(QStringList() << optionString << QString::number(pid)); - m_process->run(ProjectExplorer::ApplicationLauncher::Gui); + connect(m_controllerProcess, &ApplicationLauncher::processExited, + this, &CallgrindController::controllerProcessFinished); + connect(m_controllerProcess, &ApplicationLauncher::error, + this, &CallgrindController::handleControllerProcessError); + connect(m_controllerProcess, &ApplicationLauncher::finished, + this, &CallgrindController::controllerProcessClosed); + + StandardRunnable controller = m_valgrindRunnable; + controller.executable = CALLGRIND_CONTROL_BINARY; + controller.runMode = ApplicationLauncher::Gui; + controller.commandLineArguments = QString("%1 %2").arg(toOptionString(option)).arg(m_pid); + + if (!m_valgrindRunnable.device + || m_valgrindRunnable.device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) + m_controllerProcess->start(controller); + else + m_controllerProcess->start(controller, m_valgrindRunnable.device); } -void CallgrindController::processError(QProcess::ProcessError) +void CallgrindController::setValgrindPid(qint64 pid) { - QTC_ASSERT(m_process, return); - const QString error = m_process->errorString(); + m_pid = pid; +} + +void CallgrindController::handleControllerProcessError(QProcess::ProcessError) +{ + QTC_ASSERT(m_controllerProcess, return); + const QString error = m_controllerProcess->errorString(); emit statusMessage(tr("An error occurred while trying to run %1: %2").arg(CALLGRIND_CONTROL_BINARY).arg(error)); - m_process->deleteLater(); - m_process = 0; + m_controllerProcess->deleteLater(); + m_controllerProcess = nullptr; } -void CallgrindController::processFinished(int rc, QProcess::ExitStatus status) +void CallgrindController::controllerProcessFinished(int rc, QProcess::ExitStatus status) { - QTC_ASSERT(m_process, return); - const QString error = m_process->errorString(); + QTC_ASSERT(m_controllerProcess, return); + const QString error = m_controllerProcess->errorString(); - m_process->deleteLater(); // Called directly from finished() signal in m_process - m_process = 0; + m_controllerProcess->deleteLater(); // Called directly from finished() signal in m_process + m_controllerProcess = nullptr; if (rc != 0 || status != QProcess::NormalExit) { qWarning() << "Controller exited abnormally:" << error; @@ -175,23 +188,34 @@ void CallgrindController::processFinished(int rc, QProcess::ExitStatus status) m_lastOption = Unknown; } -void CallgrindController::setValgrindProcess(ValgrindProcess *proc) +void CallgrindController::controllerProcessClosed(bool success) { - m_valgrindProc = proc; + Q_UNUSED(success); + // QTC_ASSERT(m_remote.m_process, return); + +// m_remote.m_errorString = m_remote.m_process->errorString(); +// if (status == QSsh::SshRemoteProcess::FailedToStart) { +// m_remote.m_error = QProcess::FailedToStart; +// emit ValgrindProcessX::error(QProcess::FailedToStart); +// } else if (status == QSsh::SshRemoteProcess::NormalExit) { +// emit finished(m_remote.m_process->exitCode(), QProcess::NormalExit); +// } else if (status == QSsh::SshRemoteProcess::CrashExit) { +// m_remote.m_error = QProcess::Crashed; +// emit finished(m_remote.m_process->exitCode(), QProcess::CrashExit); +// } + controllerProcessFinished(0, QProcess::NormalExit); } void CallgrindController::getLocalDataFile() { - QTC_ASSERT(m_valgrindProc, return); - // we look for callgrind.out.PID, but there may be updated ones called ~.PID.NUM - QString baseFileName = QString::fromLatin1("callgrind.out.%1"). - arg(m_valgrindProc->pid()); - const QString workingDir = m_valgrindProc->workingDirectory(); + const QString baseFileName = QString("callgrind.out.%1").arg(m_pid); + const QString workingDir = m_valgrindRunnable.workingDirectory; // first, set the to-be-parsed file to callgrind.out.PID - QString fileName = workingDir.isEmpty() ? baseFileName : (workingDir + QLatin1Char('/') + baseFileName); + QString fileName = workingDir.isEmpty() ? baseFileName : (workingDir + '/' + baseFileName); - if (!m_valgrindProc->isLocal()) { + if (m_valgrindRunnable.device + && m_valgrindRunnable.device->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { // ///TODO: error handling // emit statusMessage(tr("Downloading remote profile data...")); // m_ssh = m_valgrindProc->connection(); @@ -254,5 +278,11 @@ void CallgrindController::cleanupTempFile() m_tempDataFile.clear(); } +void CallgrindController::setValgrindRunnable(const Runnable &runnable) +{ + QTC_ASSERT(runnable.is(), return); + m_valgrindRunnable = runnable.as(); +} + } // namespace Callgrind } // namespace Valgrind diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.h b/src/plugins/valgrind/callgrind/callgrindcontroller.h index a1e06fe4456..50e4490adf8 100644 --- a/src/plugins/valgrind/callgrind/callgrindcontroller.h +++ b/src/plugins/valgrind/callgrind/callgrindcontroller.h @@ -25,18 +25,15 @@ #pragma once -#include - -#include - -#include #include #include +#include + +#include + +#include namespace Valgrind { - -class ValgrindProcess; - namespace Callgrind { class CallgrindController : public QObject @@ -49,16 +46,14 @@ public: Unknown, Dump, ResetEventCounters, - Pause, UnPause + Pause, + UnPause }; - explicit CallgrindController(QObject *parent = 0); - virtual ~CallgrindController(); + CallgrindController(); + ~CallgrindController() override; - void run(Valgrind::Callgrind::CallgrindController::Option option); - - void setValgrindProcess(ValgrindProcess *process); - ValgrindProcess *valgrindProcess() { return m_valgrindProc; } + void run(Option option); /** * Make data file available locally, triggers @c localParseDataAvailable. @@ -67,32 +62,34 @@ public: * downloads the data file first and returns a local path. */ void getLocalDataFile(); + void setValgrindPid(qint64 pid); + void setValgrindRunnable(const ProjectExplorer::Runnable &runnable); signals: void finished(Valgrind::Callgrind::CallgrindController::Option option); - void localParseDataAvailable(const QString &file); - void statusMessage(const QString &msg); private: - void processError(QProcess::ProcessError); - void processFinished(int, QProcess::ExitStatus); + void handleControllerProcessError(QProcess::ProcessError); void foundRemoteFile(); void sftpInitialized(); void sftpJobFinished(QSsh::SftpJobId job, const QString &error); void cleanupTempFile(); - // callgrind_control process - Valgrind::ValgrindProcess *m_process; - // valgrind process - Valgrind::ValgrindProcess *m_valgrindProc; + void controllerProcessFinished(int, QProcess::ExitStatus); + void controllerProcessError(QProcess::ProcessError); + void controllerProcessClosed(bool success); - Option m_lastOption; + ProjectExplorer::ApplicationLauncher *m_controllerProcess; + ProjectExplorer::StandardRunnable m_valgrindRunnable; + qint64 m_pid = 0; + + Option m_lastOption = Unknown; // remote callgrind support - QSsh::SshConnection *m_ssh; + QSsh::SshConnection *m_ssh = nullptr; QString m_tempDataFile; QSsh::SshRemoteProcess::Ptr m_findRemoteFile; QSsh::SftpChannel::Ptr m_sftp; diff --git a/src/plugins/valgrind/callgrindengine.cpp b/src/plugins/valgrind/callgrindengine.cpp index 42b6f7e274e..c1000398398 100644 --- a/src/plugins/valgrind/callgrindengine.cpp +++ b/src/plugins/valgrind/callgrindengine.cpp @@ -30,17 +30,21 @@ #include #include +#include +#include #include #include using namespace Debugger; -using namespace Valgrind; -using namespace Valgrind::Internal; +using namespace ProjectExplorer; using namespace Valgrind::Callgrind; -CallgrindToolRunner::CallgrindToolRunner(ProjectExplorer::RunControl *runControl) +namespace Valgrind { +namespace Internal { + +CallgrindToolRunner::CallgrindToolRunner(RunControl *runControl) : ValgrindToolRunner(runControl) { setDisplayName("CallgrindToolRunner"); @@ -58,14 +62,14 @@ CallgrindToolRunner::CallgrindToolRunner(ProjectExplorer::RunControl *runControl connect(&m_controller, &CallgrindController::statusMessage, this, &CallgrindToolRunner::showStatusMessage); - connect(&m_runner, &ValgrindRunner::extraStart, this, [this] { - m_controller.setValgrindProcess(m_runner.valgrindProcess()); - }); + connect(m_runner.valgrindProcess(), &ValgrindProcess::valgrindStarted, + &m_controller, &CallgrindController::setValgrindPid); connect(&m_runner, &ValgrindRunner::extraProcessFinished, this, [this] { triggerParse(); - m_controller.setValgrindProcess(nullptr); }); + + m_controller.setValgrindRunnable(runnable()); } QStringList CallgrindToolRunner::toolArguments() const @@ -120,12 +124,10 @@ void CallgrindToolRunner::setPaused(bool paused) m_markAsPaused = paused; // call controller only if it is attached to a valgrind process - if (m_controller.valgrindProcess()) { - if (paused) - pause(); - else - unpause(); - } + if (paused) + pause(); + else + unpause(); } void CallgrindToolRunner::setToggleCollectFunction(const QString &toggleCollectFunction) @@ -202,3 +204,6 @@ void CallgrindToolRunner::controllerFinished(CallgrindController::Option option) break; // do nothing } } + +} // Internal +} // Valgrind diff --git a/src/plugins/valgrind/memcheckengine.cpp b/src/plugins/valgrind/memcheckengine.cpp index 918abbcb2a3..ddd96f4d5ee 100644 --- a/src/plugins/valgrind/memcheckengine.cpp +++ b/src/plugins/valgrind/memcheckengine.cpp @@ -86,7 +86,7 @@ MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb) this, &MemcheckToolRunner::suppressionCount); if (withGdb) { - connect(&m_runner, &ValgrindRunner::started, + connect(&m_runner, &ValgrindRunner::valgrindStarted, this, &MemcheckToolRunner::startDebugger); connect(&m_runner, &ValgrindRunner::logMessageReceived, this, &MemcheckToolRunner::appendLog); @@ -163,10 +163,8 @@ QStringList MemcheckToolRunner::suppressionFiles() const return m_settings->suppressionFiles(); } -void MemcheckToolRunner::startDebugger() +void MemcheckToolRunner::startDebugger(qint64 valgrindPid) { - const qint64 valgrindPid = m_runner.valgrindProcess()->pid(); - Debugger::DebuggerStartParameters sp; sp.inferior = runnable().as(); sp.startMode = Debugger::AttachToRemoteServer; diff --git a/src/plugins/valgrind/memcheckengine.h b/src/plugins/valgrind/memcheckengine.h index 40d97ac7038..edcb9a8087d 100644 --- a/src/plugins/valgrind/memcheckengine.h +++ b/src/plugins/valgrind/memcheckengine.h @@ -56,7 +56,7 @@ private: QString progressTitle() const override; QStringList toolArguments() const override; - void startDebugger(); + void startDebugger(qint64 valgrindPid); void appendLog(const QByteArray &data); const bool m_withGdb; diff --git a/src/plugins/valgrind/valgrindprocess.cpp b/src/plugins/valgrind/valgrindprocess.cpp index e0fa607c282..228983773b3 100644 --- a/src/plugins/valgrind/valgrindprocess.cpp +++ b/src/plugins/valgrind/valgrindprocess.cpp @@ -39,8 +39,7 @@ using namespace ProjectExplorer; namespace Valgrind { -ValgrindProcess::ValgrindProcess(const IDevice::ConstPtr &device, QObject *parent) - : QObject(parent), m_device(device) +ValgrindProcess::ValgrindProcess() { } @@ -129,11 +128,6 @@ QProcess::ProcessError ValgrindProcess::processError() const return m_valgrindProcess.processError(); } -qint64 ValgrindProcess::pid() const -{ - return m_pid; -} - void ValgrindProcess::handleRemoteStderr(const QByteArray &b) { if (!b.isEmpty()) @@ -153,8 +147,8 @@ bool ValgrindProcess::isLocal() const void ValgrindProcess::localProcessStarted() { - m_pid = m_valgrindProcess.applicationPID().pid(); - emit started(); + qint64 pid = m_valgrindProcess.applicationPID().pid(); + emit valgrindStarted(pid); } void ValgrindProcess::remoteProcessStarted() @@ -196,14 +190,13 @@ void ValgrindProcess::findPIDOutputReceived(const QByteArray &out) if (out.isEmpty()) return; bool ok; - m_pid = out.trimmed().toLongLong(&ok); + qint64 pid = out.trimmed().toLongLong(&ok); if (!ok) { - m_pid = 0; // m_remote.m_errorString = tr("Could not determine remote PID."); // emit ValgrindProcess::error(QProcess::FailedToStart); // close(); } else { - emit started(); + emit valgrindStarted(pid); } } @@ -216,6 +209,11 @@ QString ValgrindProcess::argumentString(Utils::OsType osType) const return arguments; } +void ValgrindProcess::setDevice(const ProjectExplorer::IDevice::ConstPtr &device) +{ + m_device = device; +} + void ValgrindProcess::closed(bool success) { Q_UNUSED(success); diff --git a/src/plugins/valgrind/valgrindprocess.h b/src/plugins/valgrind/valgrindprocess.h index 50182eb1a2e..338bba57086 100644 --- a/src/plugins/valgrind/valgrindprocess.h +++ b/src/plugins/valgrind/valgrindprocess.h @@ -45,7 +45,7 @@ class ValgrindProcess : public QObject Q_OBJECT public: - ValgrindProcess(const ProjectExplorer::IDevice::ConstPtr &device, QObject *parent); + ValgrindProcess(); ~ValgrindProcess(); bool isRunning() const; @@ -64,12 +64,12 @@ public: QString workingDirectory() const; ProjectExplorer::IDevice::ConstPtr device() const { return m_device; } + void setDevice(const ProjectExplorer::IDevice::ConstPtr &device); - qint64 pid() const; bool isLocal() const; signals: - void started(); + void valgrindStarted(qint64 pid); void finished(int, QProcess::ExitStatus); void error(QProcess::ProcessError); void processOutput(const QString &, Utils::OutputFormat format); @@ -87,7 +87,6 @@ private: ProjectExplorer::StandardRunnable m_debuggee; ProjectExplorer::ApplicationLauncher m_valgrindProcess; - qint64 m_pid = 0; ProjectExplorer::IDevice::ConstPtr m_device; ProjectExplorer::ApplicationLauncher m_findPID; diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index e85a872aef8..2be9ed01c21 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -51,7 +51,7 @@ class ValgrindRunner::Private { public: QHostAddress localServerAddress; - ValgrindProcess *process = nullptr; + ValgrindProcess process; QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels; bool finished = false; QString valgrindExecutable; @@ -75,7 +75,7 @@ ValgrindRunner::ValgrindRunner(QObject *parent) ValgrindRunner::~ValgrindRunner() { - if (d->process && d->process->isRunning()) { + if (d->process.isRunning()) { // make sure we don't delete the thread while it's still running waitForFinished(); } @@ -144,7 +144,7 @@ IDevice::ConstPtr ValgrindRunner::device() const void ValgrindRunner::waitForFinished() const { - if (d->finished || !d->process) + if (d->finished) return; QEventLoop loop; @@ -165,26 +165,24 @@ bool ValgrindRunner::start() setValgrindArguments(memcheckLogArguments() + valgrindArguments()); } - d->process = new ValgrindProcess(d->device, this); - d->process->setProcessChannelMode(d->channelMode); + d->process.setProcessChannelMode(d->channelMode); + d->process.setDevice(d->device); // consider appending our options last so they override any interfering user-supplied options // -q as suggested by valgrind manual - d->process->setValgrindExecutable(d->valgrindExecutable); - d->process->setValgrindArguments(fullValgrindArguments()); - d->process->setDebuggee(d->debuggee); + d->process.setValgrindExecutable(d->valgrindExecutable); + d->process.setValgrindArguments(fullValgrindArguments()); + d->process.setDebuggee(d->debuggee); - QObject::connect(d->process, &ValgrindProcess::processOutput, + QObject::connect(&d->process, &ValgrindProcess::processOutput, this, &ValgrindRunner::processOutputReceived); - QObject::connect(d->process, &ValgrindProcess::started, - this, &ValgrindRunner::started); - QObject::connect(d->process, &ValgrindProcess::finished, + QObject::connect(&d->process, &ValgrindProcess::valgrindStarted, + this, &ValgrindRunner::onValgrindStarted); + QObject::connect(&d->process, &ValgrindProcess::finished, this, &ValgrindRunner::processFinished); - QObject::connect(d->process, &ValgrindProcess::error, + QObject::connect(&d->process, &ValgrindProcess::error, this, &ValgrindRunner::processError); - d->process->run(d->debuggee.runMode); - - emit extraStart(); + d->process.run(d->debuggee.runMode); return true; } @@ -214,23 +212,22 @@ void ValgrindRunner::processFinished(int ret, QProcess::ExitStatus status) emit finished(); if (ret != 0 || status == QProcess::CrashExit) - emit processErrorReceived(errorString(), d->process->processError()); + emit processErrorReceived(errorString(), d->process.processError()); } QString ValgrindRunner::errorString() const { - return d->process ? d->process->errorString() : QString(); + return d->process.errorString(); } void ValgrindRunner::stop() { - QTC_ASSERT(d->process, finished(); return); - d->process->close(); + d->process.close(); } ValgrindProcess *ValgrindRunner::valgrindProcess() const { - return d->process; + return &d->process; } XmlProtocol::ThreadedParser *ValgrindRunner::parser() const @@ -246,6 +243,11 @@ void ValgrindRunner::disableXml() d->disableXml = true; } +void ValgrindRunner::onValgrindStarted(qint64 pid) +{ + emit valgrindStarted(pid); +} + void ValgrindRunner::xmlSocketConnected() { QTcpSocket *socket = d->xmlServer.nextPendingConnection(); diff --git a/src/plugins/valgrind/valgrindrunner.h b/src/plugins/valgrind/valgrindrunner.h index 371ec7d5790..3c94a9f5aff 100644 --- a/src/plugins/valgrind/valgrindrunner.h +++ b/src/plugins/valgrind/valgrindrunner.h @@ -76,17 +76,17 @@ public: signals: void logMessageReceived(const QByteArray &); - void extraStart(); void processOutputReceived(const QString &, Utils::OutputFormat); void processErrorReceived(const QString &, QProcess::ProcessError); - void started(); + void valgrindStarted(qint64 pid); void finished(); void extraProcessFinished(); private: bool startServers(); QStringList memcheckLogArguments() const; + void onValgrindStarted(qint64 pid); void processError(QProcess::ProcessError); void processFinished(int, QProcess::ExitStatus); From 844f9f47de7e5b610fda477784494cf6dc195c52 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 25 Jun 2017 19:56:01 +0300 Subject: [PATCH 19/28] Git: Move "Include tags" to branches dialog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Icc06dbf8b80a55c3962967c1f37a9c506b8e5bd8 Reviewed-by: André Hartmann --- src/plugins/git/branchdialog.cpp | 6 ++++++ src/plugins/git/branchdialog.ui | 7 +++++++ src/plugins/git/settingspage.cpp | 2 -- src/plugins/git/settingspage.ui | 10 +--------- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/plugins/git/branchdialog.cpp b/src/plugins/git/branchdialog.cpp index eb71c73531a..8b7e5b1ccc1 100644 --- a/src/plugins/git/branchdialog.cpp +++ b/src/plugins/git/branchdialog.cpp @@ -66,6 +66,8 @@ BranchDialog::BranchDialog(QWidget *parent) : m_ui->includeOldCheckBox->setToolTip( tr("Include branches and tags that have not been active for %n days.", 0, Constants::OBSOLETE_COMMIT_AGE_IN_DAYS)); + m_ui->includeTagsCheckBox->setChecked(GitPlugin::client()->settings().boolValue( + GitSettings::showTagsKey)); connect(m_ui->refreshButton, &QAbstractButton::clicked, this, &BranchDialog::refreshCurrentRepository); connect(m_ui->addButton, &QAbstractButton::clicked, this, &BranchDialog::add); @@ -83,6 +85,10 @@ BranchDialog::BranchDialog(QWidget *parent) : m_model->setOldBranchesIncluded(value); refreshCurrentRepository(); }); + connect(m_ui->includeTagsCheckBox, &QCheckBox::toggled, this, [this](bool value) { + GitPlugin::client()->settings().setValue(GitSettings::showTagsKey, value); + refreshCurrentRepository(); + }); m_ui->branchView->setModel(m_model); m_ui->branchView->setFocus(); diff --git a/src/plugins/git/branchdialog.ui b/src/plugins/git/branchdialog.ui index 2ea2a762ecf..5335fecedbe 100644 --- a/src/plugins/git/branchdialog.ui +++ b/src/plugins/git/branchdialog.ui @@ -65,6 +65,13 @@ + + + + Include ta&gs + + + diff --git a/src/plugins/git/settingspage.cpp b/src/plugins/git/settingspage.cpp index 24ccf66ab5b..1f28de70f0f 100644 --- a/src/plugins/git/settingspage.cpp +++ b/src/plugins/git/settingspage.cpp @@ -76,7 +76,6 @@ VcsBaseClientSettings SettingsPageWidget::settings() const rc.setValue(GitSettings::logCountKey, m_ui.logCountSpinBox->value()); rc.setValue(GitSettings::timeoutKey, m_ui.timeoutSpinBox->value()); rc.setValue(GitSettings::pullRebaseKey, m_ui.pullRebaseCheckBox->isChecked()); - rc.setValue(GitSettings::showTagsKey, m_ui.showTagsCheckBox->isChecked()); rc.setValue(GitSettings::winSetHomeEnvironmentKey, m_ui.winHomeCheckBox->isChecked()); rc.setValue(GitSettings::gitkOptionsKey, m_ui.gitkOptionsLineEdit->text().trimmed()); rc.setValue(GitSettings::repositoryBrowserCmd, m_ui.repBrowserCommandPathChooser->path().trimmed()); @@ -90,7 +89,6 @@ void SettingsPageWidget::setSettings(const VcsBaseClientSettings &s) m_ui.logCountSpinBox->setValue(s.intValue(GitSettings::logCountKey)); m_ui.timeoutSpinBox->setValue(s.intValue(GitSettings::timeoutKey)); m_ui.pullRebaseCheckBox->setChecked(s.boolValue(GitSettings::pullRebaseKey)); - m_ui.showTagsCheckBox->setChecked(s.boolValue(GitSettings::showTagsKey)); m_ui.winHomeCheckBox->setChecked(s.boolValue(GitSettings::winSetHomeEnvironmentKey)); m_ui.gitkOptionsLineEdit->setText(s.stringValue(GitSettings::gitkOptionsKey)); m_ui.repBrowserCommandPathChooser->setPath(s.stringValue(GitSettings::repositoryBrowserCmd)); diff --git a/src/plugins/git/settingspage.ui b/src/plugins/git/settingspage.ui index 88ad0106892..86c95e02bfc 100644 --- a/src/plugins/git/settingspage.ui +++ b/src/plugins/git/settingspage.ui @@ -7,7 +7,7 @@ 0 0 705 - 427 + 403 @@ -123,13 +123,6 @@ - - - - Show tags in Branches dialog - - - @@ -214,7 +207,6 @@ logCountSpinBox timeoutSpinBox pullRebaseCheckBox - showTagsCheckBox gitkOptionsLineEdit From c9d898ed6d26140daa8142c47d81cb3e887be315 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Mon, 26 Jun 2017 08:17:29 +0200 Subject: [PATCH 20/28] TextEditor: Fix jumping over nested auto inserted characters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTCREATORBUG-16946 Change-Id: Ic652147d76ecc93ff5607b3af733762b0d5c2738 Reviewed-by: André Hartmann --- src/plugins/texteditor/texteditor.cpp | 73 ++++++++++++++++----------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 7156ca120f4..6fe57755a80 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include @@ -470,7 +471,8 @@ public: bool m_skipAutoCompletedText = true; bool m_removeAutoCompletedText = true; bool m_keepAutoCompletionHighlight = false; - QTextCursor m_autoCompleteHighlightPos; + QList m_autoCompleteHighlightPos; + void updateAutoCompleteHighlight(); int m_cursorBlockNumber = -1; int m_blockCount = 0; @@ -943,6 +945,21 @@ int TextEditorWidgetPrivate::visualIndent(const QTextBlock &block) const return 0; } +void TextEditorWidgetPrivate::updateAutoCompleteHighlight() +{ + const QTextCharFormat &matchFormat + = q->textDocument()->fontSettings().toTextCharFormat(C_PARENTHESES); + + QList extraSelections; + for (QTextCursor cursor : Utils::asConst(m_autoCompleteHighlightPos)) { + QTextEdit::ExtraSelection sel; + sel.cursor = cursor; + sel.format.setBackground(matchFormat.background()); + extraSelections.append(sel); + } + q->setExtraSelections(TextEditorWidget::AutoCompleteSelection, extraSelections); +} + void TextEditorWidget::selectEncoding() { TextDocument *doc = d->m_document.data(); @@ -2366,8 +2383,10 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e) QTextCursor cursor = textCursor(); QString autoText; if (!inOverwriteMode) { - autoText = autoCompleter()->autoComplete(cursor, eventText, - d->m_skipAutoCompletedText && cursor == d->m_autoCompleteHighlightPos); + const bool skipChar = d->m_skipAutoCompletedText + && !d->m_autoCompleteHighlightPos.isEmpty() + && cursor == d->m_autoCompleteHighlightPos.last(); + autoText = autoCompleter()->autoComplete(cursor, eventText, skipChar); } const bool cursorWithinSnippet = d->snippetCheckCursor(cursor); @@ -4732,13 +4751,17 @@ void TextEditorWidgetPrivate::updateHighlights() } } - if (m_highlightAutoComplete && !m_autoCompleteHighlightPos.isNull()) { + if (m_highlightAutoComplete && !m_autoCompleteHighlightPos.isEmpty()) { QTimer::singleShot(0, this, [this](){ - if ((!m_keepAutoCompletionHighlight && !q->hasFocus()) - || m_autoCompleteHighlightPos != q->textCursor()) { - q->setExtraSelections(TextEditorWidget::AutoCompleteSelection, - QList()); // clear - m_autoCompleteHighlightPos = QTextCursor(); + const QTextCursor &cursor = q->textCursor(); + auto popAutoCompletion = [&]() { + return !m_autoCompleteHighlightPos.isEmpty() + && m_autoCompleteHighlightPos.last() != cursor; + }; + if (!m_keepAutoCompletionHighlight && !q->hasFocus() && popAutoCompletion()) { + while (popAutoCompletion()) + m_autoCompleteHighlightPos.pop_back(); + updateAutoCompleteHighlight(); } }); } @@ -5405,8 +5428,11 @@ void TextEditorWidgetPrivate::handleBackspaceKey() const TabSettings &tabSettings = m_document->tabSettings(); const TypingSettings &typingSettings = m_document->typingSettings(); - if (typingSettings.m_autoIndent && (m_autoCompleteHighlightPos == cursor) - && m_removeAutoCompletedText && m_autoCompleter->autoBackspace(cursor)) { + if (typingSettings.m_autoIndent + && !m_autoCompleteHighlightPos.isEmpty() + && (m_autoCompleteHighlightPos.last() == cursor) + && m_removeAutoCompletedText + && m_autoCompleter->autoBackspace(cursor)) { return; } @@ -6082,25 +6108,14 @@ void TextEditorWidgetPrivate::_q_highlightBlocks() void TextEditorWidgetPrivate::autocompleterHighlight(const QTextCursor &cursor) { - QList extraSelections; if ((!m_animateAutoComplete && !m_highlightAutoComplete) || q->isReadOnly() || !cursor.hasSelection()) { - q->setExtraSelections(TextEditorWidget::AutoCompleteSelection, extraSelections); // clear - return; - } - - const QTextCharFormat &matchFormat - = q->textDocument()->fontSettings().toTextCharFormat(C_AUTOCOMPLETE); - - if (m_highlightAutoComplete) { - QTextEdit::ExtraSelection sel; - sel.cursor = cursor; - sel.format.setBackground(matchFormat.background()); - extraSelections.append(sel); - m_autoCompleteHighlightPos = cursor; - m_autoCompleteHighlightPos.movePosition(QTextCursor::PreviousCharacter); - } - if (m_animateAutoComplete) { + m_autoCompleteHighlightPos.clear(); + } else if (m_highlightAutoComplete) { + m_autoCompleteHighlightPos.push_back(cursor); + } else if (m_animateAutoComplete) { + const QTextCharFormat &matchFormat + = q->textDocument()->fontSettings().toTextCharFormat(C_AUTOCOMPLETE); cancelCurrentAnimations();// one animation is enough QPalette pal; pal.setBrush(QPalette::Text, matchFormat.foreground()); @@ -6110,7 +6125,7 @@ void TextEditorWidgetPrivate::autocompleterHighlight(const QTextCursor &cursor) connect(m_autocompleteAnimator.data(), &TextEditorAnimator::updateRequest, this, &TextEditorWidgetPrivate::_q_animateUpdate); } - q->setExtraSelections(TextEditorWidget::AutoCompleteSelection, extraSelections); + updateAutoCompleteHighlight(); } void TextEditorWidgetPrivate::updateAnimator(QPointer animator, From 4506acbffc08cab4ad2a4f0425fd62c0e0a03f1b Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 29 Jun 2017 21:51:42 +0300 Subject: [PATCH 21/28] QmakePM: Remove unused signal Fixes compilation with GCC7.1 and Qt 5.7.1. Change-Id: Ia902ac1abf65810ee9d86ee0d3fca05717816f3a Reviewed-by: Nikolai Kosjar --- src/plugins/qmakeprojectmanager/profilehoverhandler.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/qmakeprojectmanager/profilehoverhandler.h b/src/plugins/qmakeprojectmanager/profilehoverhandler.h index 6e5b6ac03b1..2fa1fb250e0 100644 --- a/src/plugins/qmakeprojectmanager/profilehoverhandler.h +++ b/src/plugins/qmakeprojectmanager/profilehoverhandler.h @@ -40,9 +40,6 @@ class ProFileHoverHandler : public TextEditor::BaseHoverHandler public: explicit ProFileHoverHandler(const TextEditor::Keywords &keywords); -signals: - void creatorHelpRequested(const QUrl &url); - private: void identifyMatch(TextEditor::TextEditorWidget *editorWidget, int pos) override; void identifyQMakeKeyword(const QString &text, int pos); From 6591a01452918ce40ca101bb6cfe9770a44d16be Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 20 Jun 2017 08:28:10 +0200 Subject: [PATCH 22/28] TextEditor: Add line annotations Displaying short descriptive text of a TextMark at line end. Currently implemented for ClangTextMark and BookMark. Change-Id: Idc6b579bda0382ad94b2e236b715696396b10460 Reviewed-by: Nikolai Kosjar --- src/plugins/bookmarks/bookmark.cpp | 2 + src/plugins/clangcodemodel/clangtextmark.cpp | 3 +- src/plugins/clangcodemodel/clangtextmark.h | 2 +- .../qmlprofiler/qmlprofilertextmark.cpp | 4 +- src/plugins/qmlprofiler/qmlprofilertextmark.h | 4 +- src/plugins/texteditor/displaysettings.cpp | 4 + src/plugins/texteditor/displaysettings.h | 1 + .../texteditor/displaysettingspage.cpp | 2 + src/plugins/texteditor/displaysettingspage.ui | 75 +++++++----- src/plugins/texteditor/textdocument.cpp | 12 +- src/plugins/texteditor/textdocument.h | 1 + src/plugins/texteditor/texteditor.cpp | 114 +++++++++++++++++- src/plugins/texteditor/texteditor.h | 2 + src/plugins/texteditor/textmark.cpp | 90 +++++++++++++- src/plugins/texteditor/textmark.h | 11 +- src/plugins/valgrind/callgrindtextmark.cpp | 2 +- src/plugins/valgrind/callgrindtextmark.h | 2 +- 17 files changed, 275 insertions(+), 56 deletions(-) diff --git a/src/plugins/bookmarks/bookmark.cpp b/src/plugins/bookmarks/bookmark.cpp index 8834ccab00b..e24f734ee44 100644 --- a/src/plugins/bookmarks/bookmark.cpp +++ b/src/plugins/bookmarks/bookmark.cpp @@ -84,6 +84,8 @@ void Bookmark::updateFileName(const QString &fileName) void Bookmark::setNote(const QString ¬e) { setToolTip(note); + setLineAnnotation(note); + updateMarker(); } void Bookmark::updateNote(const QString ¬e) diff --git a/src/plugins/clangcodemodel/clangtextmark.cpp b/src/plugins/clangcodemodel/clangtextmark.cpp index c066db538ad..1e53bce06e2 100644 --- a/src/plugins/clangcodemodel/clangtextmark.cpp +++ b/src/plugins/clangcodemodel/clangtextmark.cpp @@ -79,6 +79,7 @@ ClangTextMark::ClangTextMark(const QString &fileName, setPriority(warning ? TextEditor::TextMark::NormalPriority : TextEditor::TextMark::HighPriority); setIcon(diagnostic.severity()); + setLineAnnotation(diagnostic.text().toString()); } void ClangTextMark::setIcon(ClangBackEnd::DiagnosticSeverity severity) @@ -96,7 +97,7 @@ void ClangTextMark::setIcon(ClangBackEnd::DiagnosticSeverity severity) TextMark::setIcon(errorIcon); } -bool ClangTextMark::addToolTipContent(QLayout *target) +bool ClangTextMark::addToolTipContent(QLayout *target) const { using Internal::ClangDiagnosticWidget; diff --git a/src/plugins/clangcodemodel/clangtextmark.h b/src/plugins/clangcodemodel/clangtextmark.h index 6b504c69143..f1a1b9078ba 100644 --- a/src/plugins/clangcodemodel/clangtextmark.h +++ b/src/plugins/clangcodemodel/clangtextmark.h @@ -45,7 +45,7 @@ public: private: void setIcon(ClangBackEnd::DiagnosticSeverity severity); - bool addToolTipContent(QLayout *target) override; + bool addToolTipContent(QLayout *target) const override; void removedFromEditor() override; private: diff --git a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp index a0bdaed6cc1..bbc0bf3fc0b 100644 --- a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp +++ b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp @@ -44,7 +44,7 @@ void QmlProfilerTextMark::addTypeId(int typeId) m_typeIds.append(typeId); } -void QmlProfilerTextMark::paint(QPainter *painter, const QRect &paintRect) const +void QmlProfilerTextMark::paintIcon(QPainter *painter, const QRect &paintRect) const { painter->save(); painter->setPen(Qt::black); @@ -108,7 +108,7 @@ void QmlProfilerTextMarkModel::createMarks(QmlProfilerTool *tool, const QString } } -bool QmlProfilerTextMark::addToolTipContent(QLayout *target) +bool QmlProfilerTextMark::addToolTipContent(QLayout *target) const { QGridLayout *layout = new QGridLayout; layout->setHorizontalSpacing(10); diff --git a/src/plugins/qmlprofiler/qmlprofilertextmark.h b/src/plugins/qmlprofiler/qmlprofilertextmark.h index b3772aea134..894e5fc5178 100644 --- a/src/plugins/qmlprofiler/qmlprofilertextmark.h +++ b/src/plugins/qmlprofiler/qmlprofilertextmark.h @@ -37,10 +37,10 @@ public: QmlProfilerTextMark(QmlProfilerTool *tool, int typeId, const QString &fileName, int lineNumber); void addTypeId(int typeId); - void paint(QPainter *painter, const QRect &rect) const override; + void paintIcon(QPainter *painter, const QRect &rect) const override; void clicked() override; bool isClickable() const override { return true; } - bool addToolTipContent(QLayout *target) override; + bool addToolTipContent(QLayout *target) const override; private: QmlProfilerTool *m_tool; diff --git a/src/plugins/texteditor/displaysettings.cpp b/src/plugins/texteditor/displaysettings.cpp index d15cf52dcad..196b9434c2f 100644 --- a/src/plugins/texteditor/displaysettings.cpp +++ b/src/plugins/texteditor/displaysettings.cpp @@ -44,6 +44,7 @@ static const char displayFileEncodingKey[] = "DisplayFileEncoding"; static const char scrollBarHighlightsKey[] = "ScrollBarHighlights"; static const char animateNavigationWithinFileKey[] = "AnimateNavigationWithinFile"; static const char animateWithinFileTimeMaxKey[] = "AnimateWithinFileTimeMax"; +static const char displayAnnotationsKey[] = "DisplayAnnotations"; static const char groupPostfix[] = "DisplaySettings"; namespace TextEditor { @@ -69,6 +70,7 @@ void DisplaySettings::toSettings(const QString &category, QSettings *s) const s->setValue(QLatin1String(displayFileEncodingKey), m_displayFileEncoding); s->setValue(QLatin1String(scrollBarHighlightsKey), m_scrollBarHighlights); s->setValue(QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile); + s->setValue(QLatin1String(displayAnnotationsKey), m_displayAnnotations); s->endGroup(); } @@ -97,6 +99,7 @@ void DisplaySettings::fromSettings(const QString &category, const QSettings *s) m_scrollBarHighlights = s->value(group + QLatin1String(scrollBarHighlightsKey), m_scrollBarHighlights).toBool(); m_animateNavigationWithinFile = s->value(group + QLatin1String(animateNavigationWithinFileKey), m_animateNavigationWithinFile).toBool(); m_animateWithinFileTimeMax = s->value(group + QLatin1String(animateWithinFileTimeMaxKey), m_animateWithinFileTimeMax).toInt(); + m_displayAnnotations = s->value(group + QLatin1String(displayAnnotationsKey), m_displayAnnotations).toBool(); } bool DisplaySettings::equals(const DisplaySettings &ds) const @@ -118,6 +121,7 @@ bool DisplaySettings::equals(const DisplaySettings &ds) const && m_scrollBarHighlights == ds.m_scrollBarHighlights && m_animateNavigationWithinFile == ds.m_animateNavigationWithinFile && m_animateWithinFileTimeMax == ds.m_animateWithinFileTimeMax + && m_displayAnnotations == ds.m_displayAnnotations ; } diff --git a/src/plugins/texteditor/displaysettings.h b/src/plugins/texteditor/displaysettings.h index fabebd96d8c..a37343bb486 100644 --- a/src/plugins/texteditor/displaysettings.h +++ b/src/plugins/texteditor/displaysettings.h @@ -58,6 +58,7 @@ public: bool m_scrollBarHighlights = true; bool m_animateNavigationWithinFile = false; int m_animateWithinFileTimeMax = 333; // read only setting + bool m_displayAnnotations = true; bool equals(const DisplaySettings &ds) const; }; diff --git a/src/plugins/texteditor/displaysettingspage.cpp b/src/plugins/texteditor/displaysettingspage.cpp index 147fa970804..7ae27e11d73 100644 --- a/src/plugins/texteditor/displaysettingspage.cpp +++ b/src/plugins/texteditor/displaysettingspage.cpp @@ -119,6 +119,7 @@ void DisplaySettingsPage::settingsFromUI(DisplaySettings &displaySettings, displaySettings.m_displayFileEncoding = d->m_page->displayFileEncoding->isChecked(); displaySettings.m_scrollBarHighlights = d->m_page->scrollBarHighlights->isChecked(); displaySettings.m_animateNavigationWithinFile = d->m_page->animateNavigationWithinFile->isChecked(); + displaySettings.m_displayAnnotations = d->m_page->displayAnnotations->isChecked(); } void DisplaySettingsPage::settingsToUI() @@ -142,6 +143,7 @@ void DisplaySettingsPage::settingsToUI() d->m_page->displayFileEncoding->setChecked(displaySettings.m_displayFileEncoding); d->m_page->scrollBarHighlights->setChecked(displaySettings.m_scrollBarHighlights); d->m_page->animateNavigationWithinFile->setChecked(displaySettings.m_animateNavigationWithinFile); + d->m_page->displayAnnotations->setChecked(displaySettings.m_displayAnnotations); } const DisplaySettings &DisplaySettingsPage::displaySettings() const diff --git a/src/plugins/texteditor/displaysettingspage.ui b/src/plugins/texteditor/displaysettingspage.ui index b91965a192c..1663840272e 100644 --- a/src/plugins/texteditor/displaysettingspage.ui +++ b/src/plugins/texteditor/displaysettingspage.ui @@ -80,17 +80,10 @@ Display - - + + - Display &folding markers - - - - - - - Center &cursor on scroll + &Highlight matching parentheses @@ -101,20 +94,6 @@ - - - - Auto-fold first &comment - - - - - - - &Animate matching parentheses - - - @@ -129,6 +108,20 @@ + + + + Auto-fold first &comment + + + + + + + &Animate matching parentheses + + + @@ -143,6 +136,13 @@ + + + + Center &cursor on scroll + + + @@ -153,17 +153,17 @@ - - + + - &Highlight matching parentheses + Display &folding markers - - + + - Mark &text changes + Animate navigation within file @@ -174,10 +174,17 @@ - - + + - Animate navigation within file + Mark &text changes + + + + + + + Display annotations behind lines @@ -197,12 +204,14 @@ centerOnScroll autoFoldFirstComment scrollBarHighlights + displayAnnotations highlightCurrentLine highlightBlocks animateMatchingParentheses highlightMatchingParentheses openLinksInNextSplit displayFileEncoding + animateNavigationWithinFile diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index f146507e4c0..7c53c812962 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -845,6 +845,13 @@ void TextDocument::modificationChanged(bool modified) emit changed(); } +void TextDocument::updateLayout() const +{ + auto documentLayout = qobject_cast(d->m_document.documentLayout()); + QTC_ASSERT(documentLayout, return); + documentLayout->requestUpdate(); +} + TextMarks TextDocument::marks() const { return d->m_marksCache; @@ -953,6 +960,7 @@ void TextDocument::removeMark(TextMark *mark) removeMarkFromMarksCache(mark); mark->setBaseTextDocument(0); + updateLayout(); } void TextDocument::updateMark(TextMark *mark) @@ -964,9 +972,7 @@ void TextDocument::updateMark(TextMark *mark) userData->removeMark(mark); userData->addMark(mark); } - auto documentLayout = qobject_cast(d->m_document.documentLayout()); - QTC_ASSERT(documentLayout, return); - documentLayout->requestUpdate(); + updateLayout(); } void TextDocument::moveMark(TextMark *mark, int previousLine) diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 38719dd8486..63c1f78a421 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -154,6 +154,7 @@ private: void cleanWhitespace(QTextCursor &cursor, bool cleanIndentation, bool inEntireDocument); void ensureFinalNewLine(QTextCursor &cursor); void modificationChanged(bool modified); + void updateLayout() const; TextDocumentPrivate *d; }; diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 6fe57755a80..474e71fb504 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -73,6 +73,7 @@ #include #include #include +#include #include #include #include @@ -279,6 +280,7 @@ public: bool expanded, bool active, bool hovered) const; + void drawLineAnnotation(QPainter &painter, const QTextBlock &block); void toggleBlockVisible(const QTextBlock &block); QRect foldBox(); @@ -297,6 +299,7 @@ public: bool camelCaseLeft(QTextCursor &cursor, QTextCursor::MoveMode mode); void processTooltipRequest(const QTextCursor &c); + bool processAnnotaionTooltipRequest(const QTextBlock &block, const QPoint &pos) const; void transformSelection(TransformationMethod method); void transformBlockSelection(TransformationMethod method); @@ -384,6 +387,13 @@ public: bool snippetCheckCursor(const QTextCursor &cursor); void snippetTabOrBacktab(bool forward); + struct AnnotationRect + { + QRectF rect; + const TextMark *mark; + }; + QMap> m_annotationRects; + RefactorOverlay *m_refactorOverlay = nullptr; QString m_contextHelpId; @@ -3165,6 +3175,42 @@ void TextEditorWidgetPrivate::processTooltipRequest(const QTextCursor &c) highest->showToolTip(q, toolTipPoint); } +bool TextEditorWidgetPrivate::processAnnotaionTooltipRequest(const QTextBlock &block, + const QPoint &pos) const +{ + TextBlockUserData *blockUserData = TextDocumentLayout::testUserData(block); + if (!blockUserData) + return false; + + for (const AnnotationRect &annotationRect : m_annotationRects[block.blockNumber()]) { + if (annotationRect.rect.contains(pos)) { + auto layout = new QGridLayout; + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(2); + annotationRect.mark->addToToolTipLayout(layout); + TextMarks marks = blockUserData->marks(); + if (marks.size() > 1) { + QFrame* separator = new QFrame(); + separator->setFrameShape(QFrame::HLine); + layout->addWidget(separator, 2, 0, 1, layout->columnCount()); + layout->addWidget(new QLabel(tr("Other annotations:")), 3, 0, 1, + layout->columnCount()); + + Utils::sort(marks, [](const TextMark* mark1, const TextMark* mark2){ + return mark1->priority() > mark2->priority(); + }); + for (const TextMark *mark : Utils::asConst(marks)) { + if (mark != annotationRect.mark) + mark->addToToolTipLayout(layout); + } + } + ToolTip::show(q->mapToGlobal(pos), layout, q); + return true; + } + } + return false; +} + bool TextEditorWidget::viewportEvent(QEvent *event) { d->m_contentsChanged = false; @@ -3192,10 +3238,14 @@ bool TextEditorWidget::viewportEvent(QEvent *event) QTC_CHECK(line.isValid()); // Only handle tool tip for text cursor if mouse is within the block for the text cursor, // and not if the mouse is e.g. in the empty space behind a short line. - if (line.isValid() - && pos.x() <= blockBoundingGeometry(block).left() + line.naturalTextRect().right()) { - d->processTooltipRequest(tc); - return true; + if (line.isValid()) { + if (pos.x() <= blockBoundingGeometry(block).left() + line.naturalTextRect().right()) { + d->processTooltipRequest(tc); + return true; + } else if (d->processAnnotaionTooltipRequest(block, pos)) { + return true; + } + ToolTip::hide(); } } return QPlainTextEdit::viewportEvent(event); @@ -3632,6 +3682,52 @@ static QTextLayout::FormatRange createBlockCursorCharFormatRange(int pos, const return o; } +void TextEditorWidgetPrivate::drawLineAnnotation(QPainter &painter, const QTextBlock &block) +{ + if (!m_displaySettings.m_displayAnnotations) + return; + + TextBlockUserData *blockUserData = TextDocumentLayout::testUserData(block); + if (!blockUserData) + return; + + TextMarks marks = blockUserData->marks(); + if (marks.isEmpty()) + return; + + const QTextLayout *layout = block.layout(); + const int lineCount = layout->lineCount(); + if (lineCount < 1) + return; + const QTextLine line = layout->lineAt(lineCount - 1); + const QPointF contentOffset = q->contentOffset(); + const qreal top = q->blockBoundingGeometry(block).translated(contentOffset).top(); + const QRectF lineRect = + line.naturalTextRect().translated(contentOffset.x(), top).adjusted(0, 0, -1, -1); + + Utils::sort(marks, [](const TextMark* mark1, const TextMark* mark2){ + return mark1->priority() > mark2->priority(); + }); + + constexpr qreal itemOffset = 10; + qreal x = lineRect.right() + itemOffset; + + const RefactorMarkers refactorMarkers = m_refactorOverlay->markers(); + for (auto refactorMark : refactorMarkers) { + if (refactorMark.cursor.block() == block) + x = qMax(x, refactorMark.rect.right() + itemOffset); + } + + for (const TextMark *mark : marks) { + QRectF annotationRect(x, lineRect.top(), q->viewport()->width() - x, lineRect.height()); + if (annotationRect.width() <= 0) + break; + mark->paintAnnotation(&painter, &annotationRect, q->fontMetrics()); + x += annotationRect.width() + itemOffset; + m_annotationRects[block.blockNumber()].append({annotationRect, mark}); + } +} + void TextEditorWidget::paintEvent(QPaintEvent *e) { // draw backgrond to the right of the wrap column before everything else @@ -3757,6 +3853,7 @@ void TextEditorWidget::paintEvent(QPaintEvent *e) int cursor_cpos = 0; QPen cursor_pen; + d->m_annotationRects.clear(); d->m_searchResultOverlay->clear(); if (!d->m_searchExpr.isEmpty()) { // first pass for the search result overlays @@ -4272,6 +4369,7 @@ void TextEditorWidget::paintEvent(QPaintEvent *e) painter.restore(); } } + d->drawLineAnnotation(painter, block); block = nextVisibleBlock; top = bottom; @@ -4557,7 +4655,7 @@ void TextEditorWidget::extraAreaPaintEvent(QPaintEvent *e) const int height = fmLineSpacing - 1; const int width = int(.5 + height * mark->widthFactor()); const QRect r(xoffset, top, width, height); - mark->paint(&painter, r); + mark->paintIcon(&painter, r); xoffset += 2; } } @@ -8075,7 +8173,11 @@ IEditor *BaseTextEditor::duplicate() return 0; } - } // namespace TextEditor +uint qHash(const QColor &color) +{ + return color.rgba(); +} + #include "texteditor.moc" diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index 841324891c6..1613de4ed02 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -672,4 +672,6 @@ private: } // namespace TextEditor +uint qHash(const QColor &color); + Q_DECLARE_METATYPE(TextEditor::TextEditorWidget::Link) diff --git a/src/plugins/texteditor/textmark.cpp b/src/plugins/texteditor/textmark.cpp index 975cc7a41c5..15939a3f44d 100644 --- a/src/plugins/texteditor/textmark.cpp +++ b/src/plugins/texteditor/textmark.cpp @@ -33,6 +33,7 @@ #include #include +#include using namespace Core; using namespace Utils; @@ -57,6 +58,24 @@ private: QHash > m_marks; }; +class AnnotationColors +{ +public: + static AnnotationColors &getAnnotationColors(const QColor &markColor, + const QColor &backgroundColor); + +public: + using SourceColors = QPair; + QColor rectColor; + QColor textColor; + +private: + static double clipHsl(double value); + +private: + static QHash m_colorCache; +}; + TextMarkRegistry *m_instance = nullptr; TextMark::TextMark(const QString &fileName, int lineNumber, Id category, double widthFactor) @@ -99,11 +118,49 @@ int TextMark::lineNumber() const return m_lineNumber; } -void TextMark::paint(QPainter *painter, const QRect &rect) const +void TextMark::paintIcon(QPainter *painter, const QRect &rect) const { m_icon.paint(painter, rect, Qt::AlignCenter); } +void TextMark::paintAnnotation(QPainter *painter, + QRectF *annotationRect, + const QFontMetrics &fm) const +{ + QString text = lineAnnotation(); + if (text.isEmpty()) + return; + + const bool drawIcon = !m_icon.isNull(); + int textWidth = fm.width(text); + constexpr qreal margin = 1; + const qreal iconHeight = annotationRect->height() - 2 * margin; + const qreal iconWidth = iconHeight * m_widthFactor + 2 * margin; + qreal annotationWidth = (drawIcon ? textWidth + iconWidth : textWidth) + margin; + if (annotationRect->left() + annotationWidth > annotationRect->right()) { + textWidth = int(annotationRect->width() - (drawIcon ? iconWidth + margin : margin)); + text = fm.elidedText(text, Qt::ElideRight, textWidth); + annotationWidth = annotationRect->width(); + } + const QColor markColor = m_hasColor ? Utils::creatorTheme()->color(m_color).toHsl() + : painter->pen().color(); + const AnnotationColors &colors = + AnnotationColors::getAnnotationColors(markColor, painter->background().color()); + + painter->save(); + annotationRect->setWidth(annotationWidth); + painter->setPen(colors.rectColor); + painter->setBrush(colors.rectColor); + painter->drawRect(*annotationRect); + painter->setPen(colors.textColor); + if (drawIcon) { + paintIcon(painter, annotationRect->adjusted( + margin, margin, -(textWidth + 2 * margin), -margin).toAlignedRect()); + } + painter->drawText(annotationRect->adjusted(iconWidth, 0, 0, 0), Qt::AlignLeft, text); + painter->restore(); +} + void TextMark::updateLineNumber(int lineNumber) { m_lineNumber = lineNumber; @@ -176,7 +233,7 @@ void TextMark::dragToLine(int lineNumber) Q_UNUSED(lineNumber); } -void TextMark::addToToolTipLayout(QGridLayout *target) +void TextMark::addToToolTipLayout(QGridLayout *target) const { auto *contentLayout = new QVBoxLayout; addToolTipContent(contentLayout); @@ -191,7 +248,7 @@ void TextMark::addToToolTipLayout(QGridLayout *target) } } -bool TextMark::addToolTipContent(QLayout *target) +bool TextMark::addToolTipContent(QLayout *target) const { QString text = m_toolTip; if (text.isEmpty()) { @@ -304,6 +361,33 @@ void TextMarkRegistry::allDocumentsRenamed(const QString &oldName, const QString mark->updateFileName(newName); } +QHash AnnotationColors::m_colorCache; + +AnnotationColors &AnnotationColors::getAnnotationColors(const QColor &markColor, + const QColor &backgroundColor) +{ + AnnotationColors &colors = m_colorCache[{markColor, backgroundColor}]; + if (!colors.rectColor.isValid() || !colors.textColor.isValid()) { + const double backgroundSaturation = clipHsl(markColor.hslSaturationF() / 2); + const double backgroundLightness = clipHsl(backgroundColor.lightnessF()); + const double foregroundLightness = clipHsl(backgroundLightness > 0.5 + ? backgroundLightness - 0.5 + : backgroundLightness + 0.5); + colors.rectColor.setHslF(markColor.hslHueF(), + backgroundSaturation, + backgroundLightness); + colors.textColor.setHslF(markColor.hslHueF(), + markColor.hslSaturationF(), + foregroundLightness); + } + return colors; +} + +double AnnotationColors::clipHsl(double value) +{ + return std::max(0.15, std::min(0.85, value)); +} + } // namespace TextEditor #include "textmark.moc" diff --git a/src/plugins/texteditor/textmark.h b/src/plugins/texteditor/textmark.h index 162ac2f7943..89d3d96e023 100644 --- a/src/plugins/texteditor/textmark.h +++ b/src/plugins/texteditor/textmark.h @@ -63,7 +63,8 @@ public: QString fileName() const; int lineNumber() const; - virtual void paint(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; /// called if the filename of the document changed virtual void updateFileName(const QString &fileName); virtual void updateLineNumber(int lineNumber); @@ -74,8 +75,8 @@ public: virtual void clicked(); virtual bool isDraggable() const; virtual void dragToLine(int lineNumber); - void addToToolTipLayout(QGridLayout *target); - virtual bool addToolTipContent(QLayout *target); + void addToToolTipLayout(QGridLayout *target) const; + virtual bool addToolTipContent(QLayout *target) const; void setIcon(const QIcon &icon) { m_icon = icon; } const QIcon &icon() const { return m_icon; } @@ -99,6 +100,9 @@ public: TextDocument *baseTextDocument() const { return m_baseTextDocument; } void setBaseTextDocument(TextDocument *baseTextDocument) { m_baseTextDocument = baseTextDocument; } + QString lineAnnotation() const { return m_lineAnnotation; } + void setLineAnnotation(const QString &lineAnnotation) { m_lineAnnotation = lineAnnotation; } + QString toolTip() const { return m_toolTip; } void setToolTip(const QString &toolTip) { m_toolTip = toolTip; } @@ -115,6 +119,7 @@ private: bool m_hasColor = false; Core::Id m_category; double m_widthFactor = 1.0; + QString m_lineAnnotation; QString m_toolTip; QString m_defaultToolTip; }; diff --git a/src/plugins/valgrind/callgrindtextmark.cpp b/src/plugins/valgrind/callgrindtextmark.cpp index cfd19c7a0ce..e08d42f0400 100644 --- a/src/plugins/valgrind/callgrindtextmark.cpp +++ b/src/plugins/valgrind/callgrindtextmark.cpp @@ -48,7 +48,7 @@ CallgrindTextMark::CallgrindTextMark(const QPersistentModelIndex &index, setPriority(TextEditor::TextMark::HighPriority); } -void CallgrindTextMark::paint(QPainter *painter, const QRect &paintRect) const +void CallgrindTextMark::paintIcon(QPainter *painter, const QRect &paintRect) const { if (!m_modelIndex.isValid()) return; diff --git a/src/plugins/valgrind/callgrindtextmark.h b/src/plugins/valgrind/callgrindtextmark.h index f5f1699a257..828dc7f5bd6 100644 --- a/src/plugins/valgrind/callgrindtextmark.h +++ b/src/plugins/valgrind/callgrindtextmark.h @@ -49,7 +49,7 @@ public: const Valgrind::Callgrind::Function *function() const; - virtual void paint(QPainter *painter, const QRect &paintRect) const; + virtual void paintIcon(QPainter *painter, const QRect &paintRect) const; private: QPersistentModelIndex m_modelIndex; From 0f7e69034e0b800b559d777085d58f6fb2006036 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Fri, 23 Jun 2017 08:44:00 +0200 Subject: [PATCH 23/28] Bookmark: make bookmarks draggable Task-number: QTCREATORBUG-9721 Change-Id: I157e2c4a15ae9d7e4942d3be378ecd01ef493155 Reviewed-by: Orgad Shaneh --- src/plugins/bookmarks/bookmark.cpp | 11 +++++++++++ src/plugins/bookmarks/bookmark.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/src/plugins/bookmarks/bookmark.cpp b/src/plugins/bookmarks/bookmark.cpp index e24f734ee44..dd8f71fb03e 100644 --- a/src/plugins/bookmarks/bookmark.cpp +++ b/src/plugins/bookmarks/bookmark.cpp @@ -50,6 +50,16 @@ void Bookmark::removedFromEditor() m_manager->deleteBookmark(this); } +bool Bookmark::isDraggable() const +{ + return true; +} + +void Bookmark::dragToLine(int lineNumber) +{ + move(lineNumber); +} + void Bookmark::updateLineNumber(int line) { if (line != lineNumber()) { @@ -63,6 +73,7 @@ void Bookmark::move(int line) if (line != lineNumber()) { TextMark::move(line); m_manager->updateBookmark(this); + updateMarker(); } } diff --git a/src/plugins/bookmarks/bookmark.h b/src/plugins/bookmarks/bookmark.h index 6d818946ff3..ad9a1d7f53d 100644 --- a/src/plugins/bookmarks/bookmark.h +++ b/src/plugins/bookmarks/bookmark.h @@ -43,6 +43,9 @@ public: void updateFileName(const QString &fileName) override; void removedFromEditor() override; + bool isDraggable() const override; + void dragToLine(int lineNumber) override; + void setNote(const QString ¬e); void updateNote(const QString ¬e); From 7a09bb441853667de80f911a36c75d8b49a38c18 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 29 Jun 2017 16:35:48 +0200 Subject: [PATCH 24/28] TextEditor: Reduce BaseHoverHandler::identifyMatch() calls ...because they are potentially expensive. Change-Id: Iaa235ea1fa864a0a67f3ed10b7f89d23179c642b Reviewed-by: David Schulz --- .../cppeditor/cppuseselectionsupdater.cpp | 24 +++---------- src/plugins/texteditor/basehoverhandler.cpp | 5 +-- src/plugins/texteditor/basehoverhandler.h | 2 +- src/plugins/texteditor/convenience.cpp | 26 ++++++++++++++ src/plugins/texteditor/convenience.h | 2 ++ src/plugins/texteditor/texteditor.cpp | 34 ++++++++++++++++++- 6 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/plugins/cppeditor/cppuseselectionsupdater.cpp b/src/plugins/cppeditor/cppuseselectionsupdater.cpp index 47a036c7b94..5e03ebbe2de 100644 --- a/src/plugins/cppeditor/cppuseselectionsupdater.cpp +++ b/src/plugins/cppeditor/cppuseselectionsupdater.cpp @@ -29,6 +29,7 @@ #include "cppeditordocument.h" #include +#include #include #include @@ -65,23 +66,6 @@ void CppUseSelectionsUpdater::abortSchedule() m_timer.stop(); } -static QTextCursor cursorAtWordStart(const QTextCursor &textCursor) -{ - const int originalPosition = textCursor.position(); - QTextCursor cursor(textCursor); - cursor.movePosition(QTextCursor::StartOfWord); - const int wordStartPosition = cursor.position(); - - if (originalPosition == wordStartPosition) { - // Cursor is not on an identifier, check whether we are right after one. - const QChar c = textCursor.document()->characterAt(originalPosition - 1); - if (CppTools::isValidIdentifierChar(c)) - cursor.movePosition(QTextCursor::PreviousWord); - } - - return cursor; -} - void CppUseSelectionsUpdater::update(CallType callType) { auto *cppEditorWidget = qobject_cast(m_editorWidget); @@ -92,7 +76,7 @@ void CppUseSelectionsUpdater::update(CallType callType) CppTools::CursorInfoParams params; params.semanticInfo = cppEditorWidget->semanticInfo(); - params.textCursor = cursorAtWordStart(cppEditorWidget->textCursor()); + params.textCursor = TextEditor::Convenience::wordStartCursor(cppEditorWidget->textCursor()); if (callType == Asynchronous) { if (isSameIdentifierAsBefore(params.textCursor)) @@ -150,8 +134,10 @@ void CppUseSelectionsUpdater::onFindUsesFinished() return; if (m_runnerRevision != m_editorWidget->document()->revision()) return; - if (m_runnerWordStartPosition != cursorAtWordStart(m_editorWidget->textCursor()).position()) + if (m_runnerWordStartPosition + != TextEditor::Convenience::wordStartCursor(m_editorWidget->textCursor()).position()) { return; + } processResults(m_runnerWatcher->result()); diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp index abbf2154abf..56ad0c0ddb8 100644 --- a/src/plugins/texteditor/basehoverhandler.cpp +++ b/src/plugins/texteditor/basehoverhandler.cpp @@ -33,9 +33,10 @@ namespace TextEditor { BaseHoverHandler::~BaseHoverHandler() {} -void BaseHoverHandler::showToolTip(TextEditorWidget *widget, const QPoint &point) +void BaseHoverHandler::showToolTip(TextEditorWidget *widget, const QPoint &point, bool decorate) { - decorateToolTip(); + if (decorate) + decorateToolTip(); operateTooltip(widget, point); } diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h index f5c8d757b7a..44dfc61e922 100644 --- a/src/plugins/texteditor/basehoverhandler.h +++ b/src/plugins/texteditor/basehoverhandler.h @@ -44,7 +44,7 @@ public: QString contextHelpId(TextEditorWidget *widget, int pos); int checkToolTip(TextEditorWidget *widget, int pos); - void showToolTip(TextEditorWidget *widget, const QPoint &point); + void showToolTip(TextEditorWidget *widget, const QPoint &point, bool decorate = true); protected: enum { diff --git a/src/plugins/texteditor/convenience.cpp b/src/plugins/texteditor/convenience.cpp index 22dcb99e9ba..8ee92147ddc 100644 --- a/src/plugins/texteditor/convenience.cpp +++ b/src/plugins/texteditor/convenience.cpp @@ -86,5 +86,31 @@ QTextCursor flippedCursor(const QTextCursor &cursor) return flipped; } +static bool isValidIdentifierChar(const QChar &c) +{ + return c.isLetter() + || c.isNumber() + || c == QLatin1Char('_') + || c.isHighSurrogate() + || c.isLowSurrogate(); +} + +QTextCursor wordStartCursor(const QTextCursor &textCursor) +{ + const int originalPosition = textCursor.position(); + QTextCursor cursor(textCursor); + cursor.movePosition(QTextCursor::StartOfWord); + const int wordStartPosition = cursor.position(); + + if (originalPosition == wordStartPosition) { + // Cursor is not on an identifier, check whether we are right after one. + const QChar c = textCursor.document()->characterAt(originalPosition - 1); + if (isValidIdentifierChar(c)) + cursor.movePosition(QTextCursor::PreviousWord); + } + + return cursor; +} + } // Util } // TextEditor diff --git a/src/plugins/texteditor/convenience.h b/src/plugins/texteditor/convenience.h index 5cbff33bef1..e4f5f0480bc 100644 --- a/src/plugins/texteditor/convenience.h +++ b/src/plugins/texteditor/convenience.h @@ -47,5 +47,7 @@ TEXTEDITOR_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint c TEXTEDITOR_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor); +TEXTEDITOR_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor); + } // Util } // TextEditor diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 474e71fb504..aa794ad63ce 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -468,6 +468,26 @@ public: CodeAssistant m_codeAssistant; bool m_assistRelevantContentAdded = false; + + struct LastHoverHandlerInfo { + LastHoverHandlerInfo() = default; + LastHoverHandlerInfo(BaseHoverHandler *handler, int documentRevision, int cursorPosition) + : handler(handler) + , documentRevision(documentRevision) + , cursorPosition(cursorPosition) + {} + + bool applies(int documentRevision, int cursorPosition) const + { + return handler + && documentRevision == this->documentRevision + && cursorPosition == this->cursorPosition; + } + + BaseHoverHandler *handler = nullptr; + int documentRevision = -1; + int cursorPosition = -1; + } m_lastHoverHandlerInfo; QList m_hoverHandlers; // Not owned QPointer m_navigationAnimation; @@ -3161,6 +3181,15 @@ void TextEditorWidgetPrivate::processTooltipRequest(const QTextCursor &c) return; } + // Does the last handler still applies? + const int documentRevision = m_document->document()->revision(); + const int cursorPosition = Convenience::wordStartCursor(c).position(); + if (m_lastHoverHandlerInfo.applies(documentRevision, cursorPosition)) { + m_lastHoverHandlerInfo.handler->showToolTip(q, toolTipPoint, /*decorate=*/ false); + return; + } + + // Determine best handler int highestPriority = -1; BaseHoverHandler *highest = 0; foreach (BaseHoverHandler *handler, m_hoverHandlers) { @@ -3171,8 +3200,11 @@ void TextEditorWidgetPrivate::processTooltipRequest(const QTextCursor &c) } } - if (highest) + // Let the best handler show the tooltip + if (highest) { + m_lastHoverHandlerInfo = LastHoverHandlerInfo{highest, documentRevision, cursorPosition}; highest->showToolTip(q, toolTipPoint); + } } bool TextEditorWidgetPrivate::processAnnotaionTooltipRequest(const QTextBlock &block, From 8678117572af475df747bf99645ba93ab36c9f36 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 29 Jun 2017 15:03:06 +0200 Subject: [PATCH 25/28] Valgrind: Merge ValgrindRunner and ValgrindProcess There was a 1:1 matching remaining. Change-Id: I619bedcda867b642eab37396a0bd48bcb3a5829a Reviewed-by: Christian Kandeler --- src/plugins/valgrind/callgrindengine.cpp | 3 +- src/plugins/valgrind/memcheckengine.cpp | 1 - src/plugins/valgrind/memcheckengine.h | 2 + src/plugins/valgrind/valgrind.pro | 2 - src/plugins/valgrind/valgrind.qbs | 1 - src/plugins/valgrind/valgrind_test.pri | 6 +- src/plugins/valgrind/valgrindprocess.cpp | 235 ---------------- src/plugins/valgrind/valgrindprocess.h | 99 ------- src/plugins/valgrind/valgrindrunner.cpp | 324 ++++++++++++++--------- src/plugins/valgrind/valgrindrunner.h | 18 +- tests/auto/valgrind/valgrindautotest.qbs | 1 - 11 files changed, 209 insertions(+), 483 deletions(-) delete mode 100644 src/plugins/valgrind/valgrindprocess.cpp delete mode 100644 src/plugins/valgrind/valgrindprocess.h diff --git a/src/plugins/valgrind/callgrindengine.cpp b/src/plugins/valgrind/callgrindengine.cpp index c1000398398..468bc0c6bbf 100644 --- a/src/plugins/valgrind/callgrindengine.cpp +++ b/src/plugins/valgrind/callgrindengine.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include @@ -62,7 +61,7 @@ CallgrindToolRunner::CallgrindToolRunner(RunControl *runControl) connect(&m_controller, &CallgrindController::statusMessage, this, &CallgrindToolRunner::showStatusMessage); - connect(m_runner.valgrindProcess(), &ValgrindProcess::valgrindStarted, + connect(&m_runner, &ValgrindRunner::valgrindStarted, &m_controller, &CallgrindController::setValgrindPid); connect(&m_runner, &ValgrindRunner::extraProcessFinished, this, [this] { diff --git a/src/plugins/valgrind/memcheckengine.cpp b/src/plugins/valgrind/memcheckengine.cpp index ddd96f4d5ee..64fadb80e61 100644 --- a/src/plugins/valgrind/memcheckengine.cpp +++ b/src/plugins/valgrind/memcheckengine.cpp @@ -26,7 +26,6 @@ #include "memcheckengine.h" #include "memchecktool.h" -#include "valgrindprocess.h" #include "valgrindsettings.h" #include "xmlprotocol/error.h" #include "xmlprotocol/status.h" diff --git a/src/plugins/valgrind/memcheckengine.h b/src/plugins/valgrind/memcheckengine.h index edcb9a8087d..6113390e91c 100644 --- a/src/plugins/valgrind/memcheckengine.h +++ b/src/plugins/valgrind/memcheckengine.h @@ -31,6 +31,8 @@ #include "valgrindrunner.h" #include "xmlprotocol/threadedparser.h" +#include + namespace Valgrind { namespace Internal { diff --git a/src/plugins/valgrind/valgrind.pro b/src/plugins/valgrind/valgrind.pro index aa431013297..592fe8338b4 100644 --- a/src/plugins/valgrind/valgrind.pro +++ b/src/plugins/valgrind/valgrind.pro @@ -11,7 +11,6 @@ HEADERS += \ valgrindconfigwidget.h \ valgrindsettings.h \ valgrindrunner.h \ - valgrindprocess.h \ callgrindcostdelegate.h \ callgrindcostview.h \ callgrindhelper.h \ @@ -33,7 +32,6 @@ SOURCES += \ valgrindconfigwidget.cpp \ valgrindsettings.cpp \ valgrindrunner.cpp \ - valgrindprocess.cpp \ callgrindcostdelegate.cpp \ callgrindcostview.cpp \ callgrindhelper.cpp \ diff --git a/src/plugins/valgrind/valgrind.qbs b/src/plugins/valgrind/valgrind.qbs index d7e4874365c..963fa2265db 100644 --- a/src/plugins/valgrind/valgrind.qbs +++ b/src/plugins/valgrind/valgrind.qbs @@ -34,7 +34,6 @@ QtcPlugin { "valgrindconfigwidget.cpp", "valgrindconfigwidget.h", "valgrindconfigwidget.ui", "valgrindengine.cpp", "valgrindengine.h", "valgrindplugin.cpp", "valgrindplugin.h", - "valgrindprocess.cpp", "valgrindprocess.h", "valgrindruncontrolfactory.cpp", "valgrindruncontrolfactory.h", "valgrindrunner.cpp", "valgrindrunner.h", "valgrindsettings.cpp", "valgrindsettings.h", diff --git a/src/plugins/valgrind/valgrind_test.pri b/src/plugins/valgrind/valgrind_test.pri index 7ddd22d6a83..cb00a02fc97 100644 --- a/src/plugins/valgrind/valgrind_test.pri +++ b/src/plugins/valgrind/valgrind_test.pri @@ -27,8 +27,7 @@ HEADERS += \ $$PWD/callgrind/callgrindcycledetection.h \ $$PWD/callgrind/callgrindproxymodel.h \ $$PWD/callgrind/callgrindstackbrowser.h \ - $$PWD/valgrindrunner.h \ - $$PWD/valgrindprocess.h + $$PWD/valgrindrunner.h SOURCES += $$PWD/xmlprotocol/error.cpp \ $$PWD/xmlprotocol/frame.cpp \ @@ -53,7 +52,6 @@ SOURCES += $$PWD/xmlprotocol/error.cpp \ $$PWD/callgrind/callgrindcycledetection.cpp \ $$PWD/callgrind/callgrindproxymodel.cpp \ $$PWD/callgrind/callgrindstackbrowser.cpp \ - $$PWD/valgrindrunner.cpp \ - $$PWD/valgrindprocess.cpp + $$PWD/valgrindrunner.cpp LIBS += -L$$IDE_PLUGIN_PATH/QtProject diff --git a/src/plugins/valgrind/valgrindprocess.cpp b/src/plugins/valgrind/valgrindprocess.cpp deleted file mode 100644 index 228983773b3..00000000000 --- a/src/plugins/valgrind/valgrindprocess.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "valgrindprocess.h" - -#include - -#include -#include -#include - -#include -#include - -using namespace ProjectExplorer; - -namespace Valgrind { - -ValgrindProcess::ValgrindProcess() -{ -} - -ValgrindProcess::~ValgrindProcess() -{ -} - -void ValgrindProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode) -{ - m_valgrindProcess.setProcessChannelMode(mode); -} - -QString ValgrindProcess::workingDirectory() const -{ - return m_debuggee.workingDirectory; -} - -bool ValgrindProcess::isRunning() const -{ - return m_valgrindProcess.isRunning(); -} - -void ValgrindProcess::setValgrindExecutable(const QString &valgrindExecutable) -{ - m_valgrindExecutable = valgrindExecutable; -} - -void ValgrindProcess::setDebuggee(const StandardRunnable &debuggee) -{ - m_debuggee = debuggee; -} - -void ValgrindProcess::setValgrindArguments(const QStringList &valgrindArguments) -{ - m_valgrindArguments = valgrindArguments; -} - -void ValgrindProcess::close() -{ - m_valgrindProcess.stop(); -} - -void ValgrindProcess::run(ApplicationLauncher::Mode runMode) -{ - connect(&m_valgrindProcess, &ApplicationLauncher::processExited, - this, &ValgrindProcess::finished); - connect(&m_valgrindProcess, &ApplicationLauncher::processStarted, - this, &ValgrindProcess::localProcessStarted); - connect(&m_valgrindProcess, &ApplicationLauncher::error, - this, &ValgrindProcess::error); - connect(&m_valgrindProcess, &ApplicationLauncher::appendMessage, - this, &ValgrindProcess::processOutput); - - connect(&m_valgrindProcess, &ApplicationLauncher::remoteStderr, - this, &ValgrindProcess::handleRemoteStderr); - connect(&m_valgrindProcess, &ApplicationLauncher::remoteStdout, - this, &ValgrindProcess::handleRemoteStdout); - connect(&m_valgrindProcess, &ApplicationLauncher::finished, - this, &ValgrindProcess::closed); - connect(&m_valgrindProcess, &ApplicationLauncher::remoteProcessStarted, - this, &ValgrindProcess::remoteProcessStarted); - - StandardRunnable valgrind; - valgrind.executable = m_valgrindExecutable; - valgrind.workingDirectory = m_debuggee.workingDirectory; - valgrind.environment = m_debuggee.environment; - valgrind.runMode = runMode; - valgrind.device = m_device; - - if (isLocal()) { - valgrind.commandLineArguments = argumentString(Utils::HostOsInfo::hostOs()); - m_valgrindProcess.start(valgrind); - } else { - valgrind.commandLineArguments = argumentString(Utils::OsTypeLinux); - m_valgrindProcess.start(valgrind, m_device); - } -} - -QString ValgrindProcess::errorString() const -{ - return m_valgrindProcess.errorString(); -} - -QProcess::ProcessError ValgrindProcess::processError() const -{ - return m_valgrindProcess.processError(); -} - -void ValgrindProcess::handleRemoteStderr(const QByteArray &b) -{ - if (!b.isEmpty()) - emit processOutput(QString::fromUtf8(b), Utils::StdErrFormat); -} - -void ValgrindProcess::handleRemoteStdout(const QByteArray &b) -{ - if (!b.isEmpty()) - emit processOutput(QString::fromUtf8(b), Utils::StdOutFormat); -} - -bool ValgrindProcess::isLocal() const -{ - return m_device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE; -} - -void ValgrindProcess::localProcessStarted() -{ - qint64 pid = m_valgrindProcess.applicationPID().pid(); - emit valgrindStarted(pid); -} - -void ValgrindProcess::remoteProcessStarted() -{ - // find out what PID our process has - - // NOTE: valgrind cloaks its name, - // e.g.: valgrind --tool=memcheck foobar - // => ps aux, pidof will see valgrind.bin - // => pkill/killall/top... will see memcheck-amd64-linux or similar - // hence we need to do something more complex... - - // plain path to exe, m_valgrindExe contains e.g. env vars etc. pp. - const QString proc = m_valgrindExecutable.split(' ').last(); - - StandardRunnable findPid; - findPid.executable = "/bin/sh"; - // sleep required since otherwise we might only match "bash -c..." - // and not the actual valgrind run - findPid.commandLineArguments = QString("-c \"" - "sleep 1; ps ax" // list all processes with aliased name - " | grep '\\b%1.*%2'" // find valgrind process - " | tail -n 1" // limit to single process - // we pick the last one, first would be "bash -c ..." - " | awk '{print $1;}'" // get pid - "\"" - ).arg(proc, Utils::FileName::fromString(m_debuggee.executable).fileName()); - -// m_remote.m_findPID = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); - connect(&m_findPID, &ApplicationLauncher::remoteStderr, - this, &ValgrindProcess::handleRemoteStderr); - connect(&m_findPID, &ApplicationLauncher::remoteStdout, - this, &ValgrindProcess::findPIDOutputReceived); - m_findPID.start(findPid, m_device); -} - -void ValgrindProcess::findPIDOutputReceived(const QByteArray &out) -{ - if (out.isEmpty()) - return; - bool ok; - qint64 pid = out.trimmed().toLongLong(&ok); - if (!ok) { -// m_remote.m_errorString = tr("Could not determine remote PID."); -// emit ValgrindProcess::error(QProcess::FailedToStart); -// close(); - } else { - emit valgrindStarted(pid); - } -} - -QString ValgrindProcess::argumentString(Utils::OsType osType) const -{ - QString arguments = Utils::QtcProcess::joinArgs(m_valgrindArguments, osType); - if (!m_debuggee.executable.isEmpty()) - Utils::QtcProcess::addArg(&arguments, m_debuggee.executable, osType); - Utils::QtcProcess::addArgs(&arguments, m_debuggee.commandLineArguments); - return arguments; -} - -void ValgrindProcess::setDevice(const ProjectExplorer::IDevice::ConstPtr &device) -{ - m_device = device; -} - -void ValgrindProcess::closed(bool success) -{ - Q_UNUSED(success); -// QTC_ASSERT(m_remote.m_process, return); - -// m_remote.m_errorString = m_remote.m_process->errorString(); -// if (status == QSsh::SshRemoteProcess::FailedToStart) { -// m_remote.m_error = QProcess::FailedToStart; -// emit ValgrindProcess::error(QProcess::FailedToStart); -// } else if (status == QSsh::SshRemoteProcess::NormalExit) { -// emit finished(m_remote.m_process->exitCode(), QProcess::NormalExit); -// } else if (status == QSsh::SshRemoteProcess::CrashExit) { -// m_remote.m_error = QProcess::Crashed; -// emit finished(m_remote.m_process->exitCode(), QProcess::CrashExit); -// } - emit finished(0, QProcess::NormalExit); -} - -} // namespace Valgrind diff --git a/src/plugins/valgrind/valgrindprocess.h b/src/plugins/valgrind/valgrindprocess.h deleted file mode 100644 index 338bba57086..00000000000 --- a/src/plugins/valgrind/valgrindprocess.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Author: Milian Wolff, KDAB (milian.wolff@kdab.com) -** 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 -#include -#include - -#include -#include -#include -#include - -namespace Valgrind { - -/** - * Process for supplying local and remote valgrind runs - */ -class ValgrindProcess : public QObject -{ - Q_OBJECT - -public: - ValgrindProcess(); - ~ValgrindProcess(); - - bool isRunning() const; - - void setValgrindExecutable(const QString &valgrindExecutable); - void setValgrindArguments(const QStringList &valgrindArguments); - void setDebuggee(const ProjectExplorer::StandardRunnable &debuggee); - - void run(ProjectExplorer::ApplicationLauncher::Mode runMode); - void close(); - - QString errorString() const; - QProcess::ProcessError processError() const; - - void setProcessChannelMode(QProcess::ProcessChannelMode mode); - QString workingDirectory() const; - - ProjectExplorer::IDevice::ConstPtr device() const { return m_device; } - void setDevice(const ProjectExplorer::IDevice::ConstPtr &device); - - bool isLocal() const; - -signals: - void valgrindStarted(qint64 pid); - void finished(int, QProcess::ExitStatus); - void error(QProcess::ProcessError); - void processOutput(const QString &, Utils::OutputFormat format); - -private: - void handleRemoteStderr(const QByteArray &b); - void handleRemoteStdout(const QByteArray &b); - - void closed(bool success); - void localProcessStarted(); - void remoteProcessStarted(); - void findPIDOutputReceived(const QByteArray &out); - - QString argumentString(Utils::OsType osType) const; - - ProjectExplorer::StandardRunnable m_debuggee; - ProjectExplorer::ApplicationLauncher m_valgrindProcess; - ProjectExplorer::IDevice::ConstPtr m_device; - - ProjectExplorer::ApplicationLauncher m_findPID; - - QSsh::SshConnectionParameters m_params; - QString m_valgrindExecutable; - QStringList m_valgrindArguments; -}; - -} // namespace Valgrind diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index 2be9ed01c21..b39562555e4 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -25,57 +25,199 @@ ****************************************************************************/ #include "valgrindrunner.h" -#include "valgrindprocess.h" #include "xmlprotocol/threadedparser.h" -#include - -#include #include #include - -#include -#include +#include #include -#include #include #include using namespace ProjectExplorer; +using namespace Utils; namespace Valgrind { -class ValgrindRunner::Private +class ValgrindRunner::Private : public QObject { public: + Private(ValgrindRunner *owner) : q(owner) {} + + void run(); + + void handleRemoteStderr(const QByteArray &b); + void handleRemoteStdout(const QByteArray &b); + + void closed(bool success); + void localProcessStarted(); + void remoteProcessStarted(); + void findPIDOutputReceived(const QByteArray &out); + + ValgrindRunner *q; + StandardRunnable m_debuggee; + ApplicationLauncher m_valgrindProcess; + IDevice::ConstPtr m_device; + + ApplicationLauncher m_findPID; + + QString m_valgrindExecutable; + QStringList m_valgrindArguments; + QHostAddress localServerAddress; - ValgrindProcess process; QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels; - bool finished = false; - QString valgrindExecutable; - QStringList valgrindArguments; - StandardRunnable debuggee; - IDevice::ConstPtr device; - QString tool; + bool m_finished = false; + QString m_tool; QTcpServer xmlServer; XmlProtocol::ThreadedParser parser; QTcpServer logServer; QTcpSocket *logSocket = nullptr; + + // Workaround for valgrind bug when running vgdb with xml output + // https://bugs.kde.org/show_bug.cgi?id=343902 bool disableXml = false; }; +void ValgrindRunner::Private::run() +{ + connect(&m_valgrindProcess, &ApplicationLauncher::processExited, + this, &ValgrindRunner::Private::closed); + connect(&m_valgrindProcess, &ApplicationLauncher::processStarted, + this, &ValgrindRunner::Private::localProcessStarted); + connect(&m_valgrindProcess, &ApplicationLauncher::error, + q, &ValgrindRunner::processError); + connect(&m_valgrindProcess, &ApplicationLauncher::appendMessage, + q, &ValgrindRunner::processOutputReceived); + connect(&m_valgrindProcess, &ApplicationLauncher::finished, + q, &ValgrindRunner::finished); + + connect(&m_valgrindProcess, &ApplicationLauncher::remoteStderr, + this, &ValgrindRunner::Private::handleRemoteStderr); + connect(&m_valgrindProcess, &ApplicationLauncher::remoteStdout, + this, &ValgrindRunner::Private::handleRemoteStdout); + connect(&m_valgrindProcess, &ApplicationLauncher::remoteProcessStarted, + this, &ValgrindRunner::Private::remoteProcessStarted); + + QStringList fullArgs = m_valgrindArguments; + fullArgs << QString("--tool=%1").arg(m_tool); + if (HostOsInfo::isMacHost()) + // May be slower to start but without it we get no filenames for symbols. + fullArgs << "--dsymutil=yes"; + fullArgs << m_debuggee.executable; + + StandardRunnable valgrind; + valgrind.executable = m_valgrindExecutable; + valgrind.workingDirectory = m_debuggee.workingDirectory; + valgrind.environment = m_debuggee.environment; + valgrind.runMode = m_debuggee.runMode; + valgrind.device = m_device; + valgrind.commandLineArguments = QtcProcess::joinArgs(fullArgs, m_device->osType()); + Utils::QtcProcess::addArgs(&valgrind.commandLineArguments, m_debuggee.commandLineArguments); + + if (m_device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) + m_valgrindProcess.start(valgrind); + else + m_valgrindProcess.start(valgrind, m_device); +} + +void ValgrindRunner::Private::handleRemoteStderr(const QByteArray &b) +{ + if (!b.isEmpty()) + q->processOutputReceived(QString::fromUtf8(b), Utils::StdErrFormat); +} + +void ValgrindRunner::Private::handleRemoteStdout(const QByteArray &b) +{ + if (!b.isEmpty()) + q->processOutputReceived(QString::fromUtf8(b), Utils::StdOutFormat); +} + +void ValgrindRunner::Private::localProcessStarted() +{ + qint64 pid = m_valgrindProcess.applicationPID().pid(); + emit q->valgrindStarted(pid); +} + +void ValgrindRunner::Private::remoteProcessStarted() +{ + // find out what PID our process has + + // NOTE: valgrind cloaks its name, + // e.g.: valgrind --tool=memcheck foobar + // => ps aux, pidof will see valgrind.bin + // => pkill/killall/top... will see memcheck-amd64-linux or similar + // hence we need to do something more complex... + + // plain path to exe, m_valgrindExe contains e.g. env vars etc. pp. + const QString proc = m_valgrindExecutable.split(' ').last(); + + StandardRunnable findPid; + findPid.executable = "/bin/sh"; + // sleep required since otherwise we might only match "bash -c..." + // and not the actual valgrind run + findPid.commandLineArguments = QString("-c \"" + "sleep 1; ps ax" // list all processes with aliased name + " | grep '\\b%1.*%2'" // find valgrind process + " | tail -n 1" // limit to single process + // we pick the last one, first would be "bash -c ..." + " | awk '{print $1;}'" // get pid + "\"" + ).arg(proc, Utils::FileName::fromString(m_debuggee.executable).fileName()); + +// m_remote.m_findPID = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); + connect(&m_findPID, &ApplicationLauncher::remoteStderr, + this, &ValgrindRunner::Private::handleRemoteStderr); + connect(&m_findPID, &ApplicationLauncher::remoteStdout, + this, &ValgrindRunner::Private::findPIDOutputReceived); + m_findPID.start(findPid, m_device); +} + +void ValgrindRunner::Private::findPIDOutputReceived(const QByteArray &out) +{ + if (out.isEmpty()) + return; + bool ok; + qint64 pid = out.trimmed().toLongLong(&ok); + if (!ok) { +// m_remote.m_errorString = tr("Could not determine remote PID."); +// emit ValgrindRunner::Private::error(QProcess::FailedToStart); +// close(); + } else { + emit q->valgrindStarted(pid); + } +} + +void ValgrindRunner::Private::closed(bool success) +{ + Q_UNUSED(success); +// QTC_ASSERT(m_remote.m_process, return); + +// m_remote.m_errorString = m_remote.m_process->errorString(); +// if (status == QSsh::SshRemoteProcess::FailedToStart) { +// m_remote.m_error = QProcess::FailedToStart; +// q->processError(QProcess::FailedToStart); +// } else if (status == QSsh::SshRemoteProcess::NormalExit) { +// q->processFinished(m_remote.m_process->exitCode(), QProcess::NormalExit); +// } else if (status == QSsh::SshRemoteProcess::CrashExit) { +// m_remote.m_error = QProcess::Crashed; +// q->processFinished(m_remote.m_process->exitCode(), QProcess::CrashExit); +// } + q->processFinished(0, QProcess::NormalExit); +} + + ValgrindRunner::ValgrindRunner(QObject *parent) - : QObject(parent), d(new Private) + : QObject(parent), d(new Private(this)) { setToolName("memcheck"); } ValgrindRunner::~ValgrindRunner() { - if (d->process.isRunning()) { + if (d->m_valgrindProcess.isRunning()) { // make sure we don't delete the thread while it's still running waitForFinished(); } @@ -89,37 +231,17 @@ ValgrindRunner::~ValgrindRunner() void ValgrindRunner::setValgrindExecutable(const QString &executable) { - d->valgrindExecutable = executable; -} - -QString ValgrindRunner::valgrindExecutable() const -{ - return d->valgrindExecutable; + d->m_valgrindExecutable = executable; } void ValgrindRunner::setValgrindArguments(const QStringList &toolArguments) { - d->valgrindArguments = toolArguments; -} - -QStringList ValgrindRunner::valgrindArguments() const -{ - return d->valgrindArguments; -} - -QStringList ValgrindRunner::fullValgrindArguments() const -{ - QStringList fullArgs = valgrindArguments(); - fullArgs << QString("--tool=%1").arg(d->tool); - if (Utils::HostOsInfo::isMacHost()) - // May be slower to start but without it we get no filenames for symbols. - fullArgs << QLatin1String("--dsymutil=yes"); - return fullArgs; + d->m_valgrindArguments = toolArguments; } void ValgrindRunner::setDebuggee(const StandardRunnable &debuggee) { - d->debuggee = debuggee; + d->m_debuggee = debuggee; } void ValgrindRunner::setProcessChannelMode(QProcess::ProcessChannelMode mode) @@ -134,17 +256,12 @@ void ValgrindRunner::setLocalServerAddress(const QHostAddress &localServerAddres void ValgrindRunner::setDevice(const IDevice::ConstPtr &device) { - d->device = device; -} - -IDevice::ConstPtr ValgrindRunner::device() const -{ - return d->device; + d->m_device = device; } void ValgrindRunner::waitForFinished() const { - if (d->finished) + if (d->m_finished) return; QEventLoop loop; @@ -154,7 +271,22 @@ void ValgrindRunner::waitForFinished() const void ValgrindRunner::setToolName(const QString &toolName) { - d->tool = toolName; + d->m_tool = toolName; +} + +static void handleSocketParameter(const QString &prefix, const QTcpServer &tcpServer, + bool *useXml, QStringList *arguments) +{ + QHostAddress serverAddress = tcpServer.serverAddress(); + if (serverAddress.protocol() != QAbstractSocket::IPv4Protocol) { + // Report will end up in the Application Output pane, i.e. not have + // clickable items, but that's better than nothing. + qWarning("Need IPv4 for valgrind"); + *useXml = false; + } else { + *arguments << QString("%1=%2:%3").arg(prefix).arg(serverAddress.toString()) + .arg(tcpServer.serverPort()); + } } bool ValgrindRunner::start() @@ -162,37 +294,35 @@ bool ValgrindRunner::start() if (!d->localServerAddress.isNull()) { if (!startServers()) return false; - setValgrindArguments(memcheckLogArguments() + valgrindArguments()); + + bool enableXml = !d->disableXml; + + QStringList arguments = {"--child-silent-after-fork=yes"}; + + handleSocketParameter("--xml-socket", d->xmlServer, &enableXml, &arguments); + handleSocketParameter("--log-socket", d->logServer, &enableXml, &arguments); + + if (enableXml) + arguments << "--xml=yes"; + + d->m_valgrindArguments = arguments + d->m_valgrindArguments; } - d->process.setProcessChannelMode(d->channelMode); - d->process.setDevice(d->device); + d->m_valgrindProcess.setProcessChannelMode(d->channelMode); // consider appending our options last so they override any interfering user-supplied options // -q as suggested by valgrind manual - d->process.setValgrindExecutable(d->valgrindExecutable); - d->process.setValgrindArguments(fullValgrindArguments()); - d->process.setDebuggee(d->debuggee); - - QObject::connect(&d->process, &ValgrindProcess::processOutput, - this, &ValgrindRunner::processOutputReceived); - QObject::connect(&d->process, &ValgrindProcess::valgrindStarted, - this, &ValgrindRunner::onValgrindStarted); - QObject::connect(&d->process, &ValgrindProcess::finished, - this, &ValgrindRunner::processFinished); - QObject::connect(&d->process, &ValgrindProcess::error, - this, &ValgrindRunner::processError); - - d->process.run(d->debuggee.runMode); + d->m_valgrindExecutable = d->m_valgrindExecutable; + d->run(); return true; } void ValgrindRunner::processError(QProcess::ProcessError e) { - if (d->finished) + if (d->m_finished) return; - d->finished = true; + d->m_finished = true; // make sure we don't wait for the connection anymore emit processErrorReceived(errorString(), e); @@ -203,31 +333,26 @@ void ValgrindRunner::processFinished(int ret, QProcess::ExitStatus status) { emit extraProcessFinished(); - if (d->finished) + if (d->m_finished) return; - d->finished = true; + d->m_finished = true; // make sure we don't wait for the connection anymore emit finished(); if (ret != 0 || status == QProcess::CrashExit) - emit processErrorReceived(errorString(), d->process.processError()); + emit processErrorReceived(errorString(), d->m_valgrindProcess.processError()); } QString ValgrindRunner::errorString() const { - return d->process.errorString(); + return d->m_valgrindProcess.errorString(); } void ValgrindRunner::stop() { - d->process.close(); -} - -ValgrindProcess *ValgrindRunner::valgrindProcess() const -{ - return &d->process; + d->m_valgrindProcess.stop(); } XmlProtocol::ThreadedParser *ValgrindRunner::parser() const @@ -235,19 +360,6 @@ XmlProtocol::ThreadedParser *ValgrindRunner::parser() const return &d->parser; } - -// Workaround for valgrind bug when running vgdb with xml output -// https://bugs.kde.org/show_bug.cgi?id=343902 -void ValgrindRunner::disableXml() -{ - d->disableXml = true; -} - -void ValgrindRunner::onValgrindStarted(qint64 pid) -{ - emit valgrindStarted(pid); -} - void ValgrindRunner::xmlSocketConnected() { QTcpSocket *socket = d->xmlServer.nextPendingConnection(); @@ -295,34 +407,4 @@ bool ValgrindRunner::startServers() return true; } -static void handleSocketParameter(const QString &prefix, const QTcpServer &tcpServer, - bool *useXml, QStringList *arguments) -{ - QHostAddress serverAddress = tcpServer.serverAddress(); - if (serverAddress.protocol() != QAbstractSocket::IPv4Protocol) { - // Report will end up in the Application Output pane, i.e. not have - // clickable items, but that's better than nothing. - qWarning("Need IPv4 for valgrind"); - *useXml = false; - } else { - *arguments << QString("%1=%2:%3").arg(prefix).arg(serverAddress.toString()) - .arg(tcpServer.serverPort()); - } -} - -QStringList ValgrindRunner::memcheckLogArguments() const -{ - bool enableXml = !d->disableXml; - - QStringList arguments = {"--child-silent-after-fork=yes"}; - - handleSocketParameter("--xml-socket", d->xmlServer, &enableXml, &arguments); - handleSocketParameter("--log-socket", d->logServer, &enableXml, &arguments); - - if (enableXml) - arguments << "--xml=yes"; - - return arguments; -} - } // namespace Valgrind diff --git a/src/plugins/valgrind/valgrindrunner.h b/src/plugins/valgrind/valgrindrunner.h index 3c94a9f5aff..4f61b206e32 100644 --- a/src/plugins/valgrind/valgrindrunner.h +++ b/src/plugins/valgrind/valgrindrunner.h @@ -31,7 +31,6 @@ #include #include -#include #include @@ -39,8 +38,6 @@ namespace Valgrind { namespace XmlProtocol { class ThreadedParser; } -class ValgrindProcess; - class ValgrindRunner : public QObject { Q_OBJECT @@ -49,17 +46,12 @@ public: explicit ValgrindRunner(QObject *parent = 0); ~ValgrindRunner(); - QString valgrindExecutable() const; void setValgrindExecutable(const QString &executable); - QStringList valgrindArguments() const; - QStringList fullValgrindArguments() const; void setValgrindArguments(const QStringList &toolArguments); - void setDebuggee(const ProjectExplorer::StandardRunnable &debuggee) ; + void setDebuggee(const ProjectExplorer::StandardRunnable &debuggee); void setProcessChannelMode(QProcess::ProcessChannelMode mode); void setLocalServerAddress(const QHostAddress &localServerAddress); - void setDevice(const ProjectExplorer::IDevice::ConstPtr &device); - ProjectExplorer::IDevice::ConstPtr device() const; void waitForFinished() const; void setToolName(const QString &toolName); @@ -69,14 +61,10 @@ public: bool start(); void stop(); - ValgrindProcess *valgrindProcess() const; - XmlProtocol::ThreadedParser *parser() const; - void disableXml(); signals: void logMessageReceived(const QByteArray &); - void processOutputReceived(const QString &, Utils::OutputFormat); void processErrorReceived(const QString &, QProcess::ProcessError); void valgrindStarted(qint64 pid); @@ -85,13 +73,9 @@ signals: private: bool startServers(); - QStringList memcheckLogArguments() const; - void onValgrindStarted(qint64 pid); - void processError(QProcess::ProcessError); void processFinished(int, QProcess::ExitStatus); - void localHostAddressRetrieved(const QHostAddress &localHostAddress); void xmlSocketConnected(); void logSocketConnected(); void readLogSocket(); diff --git a/tests/auto/valgrind/valgrindautotest.qbs b/tests/auto/valgrind/valgrindautotest.qbs index 7e7760bd396..78f546144f1 100644 --- a/tests/auto/valgrind/valgrindautotest.qbs +++ b/tests/auto/valgrind/valgrindautotest.qbs @@ -27,7 +27,6 @@ QtcAutotest { name: "Other files from plugin" prefix: product.pluginDir + "/" files: [ - "valgrindprocess.h", "valgrindprocess.cpp", "valgrindrunner.h", "valgrindrunner.cpp", ] } From 95300f08e3ab166151321df3a9caba52697bea63 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 29 Jun 2017 15:38:43 +0200 Subject: [PATCH 26/28] Valgrind: Keep tool names in the *ToolRunners only Slightly less convoluted. Change-Id: I07410b49db05ea862fb82f3bffc25a5d7fb5a104 Reviewed-by: Christian Kandeler --- src/plugins/valgrind/callgrindengine.cpp | 4 +--- src/plugins/valgrind/memcheckengine.cpp | 3 +-- src/plugins/valgrind/valgrindrunner.cpp | 8 -------- src/plugins/valgrind/valgrindrunner.h | 3 --- 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/plugins/valgrind/callgrindengine.cpp b/src/plugins/valgrind/callgrindengine.cpp index 468bc0c6bbf..9a0781e72d6 100644 --- a/src/plugins/valgrind/callgrindengine.cpp +++ b/src/plugins/valgrind/callgrindengine.cpp @@ -36,7 +36,6 @@ #include -using namespace Debugger; using namespace ProjectExplorer; using namespace Valgrind::Callgrind; @@ -47,7 +46,6 @@ CallgrindToolRunner::CallgrindToolRunner(RunControl *runControl) : ValgrindToolRunner(runControl) { setDisplayName("CallgrindToolRunner"); - m_runner.setToolName("callgrind"); connect(&m_runner, &ValgrindRunner::finished, this, &CallgrindToolRunner::slotFinished); @@ -73,7 +71,7 @@ CallgrindToolRunner::CallgrindToolRunner(RunControl *runControl) QStringList CallgrindToolRunner::toolArguments() const { - QStringList arguments; + QStringList arguments = {"--tool=callgrind"}; QTC_ASSERT(m_settings, return arguments); diff --git a/src/plugins/valgrind/memcheckengine.cpp b/src/plugins/valgrind/memcheckengine.cpp index 64fadb80e61..5be26e86bd2 100644 --- a/src/plugins/valgrind/memcheckengine.cpp +++ b/src/plugins/valgrind/memcheckengine.cpp @@ -120,8 +120,7 @@ void MemcheckToolRunner::stop() QStringList MemcheckToolRunner::toolArguments() const { - QStringList arguments; - arguments << "--gen-suppressions=all"; + QStringList arguments = {"--tool=memcheck", "--gen-suppressions=all"}; QTC_ASSERT(m_settings, return arguments); diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index b39562555e4..dec6098c688 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -69,7 +69,6 @@ public: QHostAddress localServerAddress; QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels; bool m_finished = false; - QString m_tool; QTcpServer xmlServer; XmlProtocol::ThreadedParser parser; @@ -102,7 +101,6 @@ void ValgrindRunner::Private::run() this, &ValgrindRunner::Private::remoteProcessStarted); QStringList fullArgs = m_valgrindArguments; - fullArgs << QString("--tool=%1").arg(m_tool); if (HostOsInfo::isMacHost()) // May be slower to start but without it we get no filenames for symbols. fullArgs << "--dsymutil=yes"; @@ -212,7 +210,6 @@ void ValgrindRunner::Private::closed(bool success) ValgrindRunner::ValgrindRunner(QObject *parent) : QObject(parent), d(new Private(this)) { - setToolName("memcheck"); } ValgrindRunner::~ValgrindRunner() @@ -269,11 +266,6 @@ void ValgrindRunner::waitForFinished() const loop.exec(); } -void ValgrindRunner::setToolName(const QString &toolName) -{ - d->m_tool = toolName; -} - static void handleSocketParameter(const QString &prefix, const QTcpServer &tcpServer, bool *useXml, QStringList *arguments) { diff --git a/src/plugins/valgrind/valgrindrunner.h b/src/plugins/valgrind/valgrindrunner.h index 4f61b206e32..e567cd88399 100644 --- a/src/plugins/valgrind/valgrindrunner.h +++ b/src/plugins/valgrind/valgrindrunner.h @@ -26,8 +26,6 @@ #pragma once -#include - #include #include @@ -54,7 +52,6 @@ public: void setDevice(const ProjectExplorer::IDevice::ConstPtr &device); void waitForFinished() const; - void setToolName(const QString &toolName); QString errorString() const; From 04b03f79d96fe6c095e12e74f0c0d4471b6c258f Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 29 Jun 2017 16:42:18 +0200 Subject: [PATCH 27/28] Valgrind: Use Runnable to pass device information ... in case of "External Application" starts. Change-Id: I6a5c215831f16c51e3cf98c35dbb792f53128d42 Reviewed-by: Christian Kandeler --- src/plugins/debugger/analyzer/startremotedialog.cpp | 12 ++---------- src/plugins/debugger/analyzer/startremotedialog.h | 2 -- src/plugins/valgrind/callgrindtool.cpp | 1 - src/plugins/valgrind/memchecktool.cpp | 1 - 4 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/plugins/debugger/analyzer/startremotedialog.cpp b/src/plugins/debugger/analyzer/startremotedialog.cpp index 89b03b8f2d8..13dcf456a42 100644 --- a/src/plugins/debugger/analyzer/startremotedialog.cpp +++ b/src/plugins/debugger/analyzer/startremotedialog.cpp @@ -128,19 +128,11 @@ void StartRemoteDialog::validate() d->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(valid); } -QUrl StartRemoteDialog::serverUrl() const -{ - QUrl url; - Kit *kit = d->kitChooser->currentKit(); - IDevice::ConstPtr device = DeviceKitInformation::device(kit); - url.setHost(device->sshParameters().host); - url.setPort(device->sshParameters().port); - return url; -} - StandardRunnable StartRemoteDialog::runnable() const { + Kit *kit = d->kitChooser->currentKit(); StandardRunnable r; + r.device = DeviceKitInformation::device(kit); r.executable = d->executable->text(); r.commandLineArguments = d->arguments->text(); r.workingDirectory = d->workingDirectory->text(); diff --git a/src/plugins/debugger/analyzer/startremotedialog.h b/src/plugins/debugger/analyzer/startremotedialog.h index 91e61873162..1a9df377fa4 100644 --- a/src/plugins/debugger/analyzer/startremotedialog.h +++ b/src/plugins/debugger/analyzer/startremotedialog.h @@ -28,7 +28,6 @@ #include #include -#include namespace ProjectExplorer { class StandardRunnable; } @@ -44,7 +43,6 @@ public: explicit StartRemoteDialog(QWidget *parent = 0); ~StartRemoteDialog() override; - QUrl serverUrl() const; ProjectExplorer::StandardRunnable runnable() const; private: diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index 2419985b838..c93a406c900 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -289,7 +289,6 @@ CallgrindTool::CallgrindTool(QObject *parent) auto runControl = new RunControl(runConfig, CALLGRIND_RUN_MODE); const auto runnable = dlg.runnable(); runControl->setRunnable(runnable); - runControl->setConnection(UrlConnection(dlg.serverUrl())); runControl->setDisplayName(runnable.executable); createRunTool(runControl); ProjectExplorerPlugin::startRunControl(runControl); diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index 16977250a69..e6c70188340 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -454,7 +454,6 @@ MemcheckTool::MemcheckTool(QObject *parent) rc->createWorker(MEMCHECK_RUN_MODE); const auto runnable = dlg.runnable(); rc->setRunnable(runnable); - rc->setConnection(UrlConnection(dlg.serverUrl())); rc->setDisplayName(runnable.executable); ProjectExplorerPlugin::startRunControl(rc); }); From df61f129702245161d86d6e84796dd96111cd577 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 20 Jun 2017 12:41:19 +0200 Subject: [PATCH 28/28] Android: Simplify run control construction Take advantage of new infrastructure. Change-Id: If2d2f839b8be1fad2be3b79e21de3c0e475d88cf Reviewed-by: Christian Stenger --- src/plugins/android/android.pro | 2 - src/plugins/android/android.qbs | 2 - src/plugins/android/androidplugin.cpp | 26 ++++-- src/plugins/android/androidrunfactories.cpp | 82 ------------------- src/plugins/android/androidrunfactories.h | 56 ------------- .../qmakeandroidrunfactories.h | 3 - 6 files changed, 18 insertions(+), 153 deletions(-) delete mode 100644 src/plugins/android/androidrunfactories.cpp delete mode 100644 src/plugins/android/androidrunfactories.h diff --git a/src/plugins/android/android.pro b/src/plugins/android/android.pro index 6ef13cc781a..702bb4d7cf7 100644 --- a/src/plugins/android/android.pro +++ b/src/plugins/android/android.pro @@ -12,7 +12,6 @@ HEADERS += \ androidmanager.h \ androidrunconfiguration.h \ androidruncontrol.h \ - androidrunfactories.h \ androidsettingspage.h \ androidsettingswidget.h \ androidtoolchain.h \ @@ -58,7 +57,6 @@ SOURCES += \ androidmanager.cpp \ androidrunconfiguration.cpp \ androidruncontrol.cpp \ - androidrunfactories.cpp \ androidsettingspage.cpp \ androidsettingswidget.cpp \ androidtoolchain.cpp \ diff --git a/src/plugins/android/android.qbs b/src/plugins/android/android.qbs index 5e5d5a45742..fcc2e9e52ee 100644 --- a/src/plugins/android/android.qbs +++ b/src/plugins/android/android.qbs @@ -83,8 +83,6 @@ Project { "androidrunconfigurationwidget.ui", "androidruncontrol.cpp", "androidruncontrol.h", - "androidrunfactories.cpp", - "androidrunfactories.h", "androidrunnable.cpp", "androidrunnable.h", "androidrunner.cpp", diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp index 5619958ac11..e2636cd4548 100644 --- a/src/plugins/android/androidplugin.cpp +++ b/src/plugins/android/androidplugin.cpp @@ -25,22 +25,26 @@ #include "androidplugin.h" -#include "androidconstants.h" +#include "androidanalyzesupport.h" #include "androidconfigurations.h" +#include "androidconstants.h" +#include "androiddebugsupport.h" +#include "androiddeployconfiguration.h" #include "androiddeployqtstep.h" #include "androiddevice.h" #include "androiddevicefactory.h" -#include "androidmanager.h" -#include "androidrunfactories.h" -#include "androidsettingspage.h" -#include "androidtoolchain.h" -#include "androidqtversionfactory.h" -#include "androiddeployconfiguration.h" #include "androidgdbserverkitinformation.h" +#include "androidmanager.h" #include "androidmanifesteditorfactory.h" #include "androidpotentialkit.h" +#include "androidqtversionfactory.h" +#include "androidrunconfiguration.h" +#include "androidruncontrol.h" +#include "androidsettingspage.h" +#include "androidtoolchain.h" #include "javacompletionassistprovider.h" #include "javaeditor.h" + #ifdef HAVE_QBS # include "androidqbspropertyprovider.h" #endif @@ -55,6 +59,8 @@ #include using namespace ProjectExplorer; +using namespace ProjectExplorer::Constants; +using namespace Android::Internal; namespace Android { @@ -66,9 +72,13 @@ bool AndroidPlugin::initialize(const QStringList &arguments, QString *errorMessa Q_UNUSED(arguments); Q_UNUSED(errorMessage); + RunControl::registerWorker(NORMAL_RUN_MODE); + RunControl::registerWorker(DEBUG_RUN_MODE); + RunControl::registerWorker(DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN); + RunControl::registerWorker(QML_PROFILER_RUN_MODE); + new AndroidConfigurations(this); - addAutoReleasedObject(new Internal::AndroidRunControlFactory); addAutoReleasedObject(new Internal::AndroidDeployQtStepFactory); addAutoReleasedObject(new Internal::AndroidSettingsPage); addAutoReleasedObject(new Internal::AndroidQtVersionFactory); diff --git a/src/plugins/android/androidrunfactories.cpp b/src/plugins/android/androidrunfactories.cpp deleted file mode 100644 index 3f894783c71..00000000000 --- a/src/plugins/android/androidrunfactories.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 BogDan Vatra -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "androidrunfactories.h" - -#include "androidconstants.h" -#include "androiddebugsupport.h" -#include "androidanalyzesupport.h" -#include "androidrunconfiguration.h" -#include "androidruncontrol.h" -#include "androidmanager.h" - -#include - -using namespace ProjectExplorer; - -namespace Android { -namespace Internal { - -AndroidRunControlFactory::AndroidRunControlFactory(QObject *parent) - : IRunControlFactory(parent) -{ -} - -bool AndroidRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id mode) const -{ - if (mode != ProjectExplorer::Constants::NORMAL_RUN_MODE - && mode != ProjectExplorer::Constants::DEBUG_RUN_MODE - && mode != ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN - && mode != ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { - return false; - } - return qobject_cast(runConfiguration); -} - -RunControl *AndroidRunControlFactory::create(RunConfiguration *runConfig, Core::Id mode, QString *) -{ - Q_ASSERT(canRun(runConfig, mode)); - if (mode == ProjectExplorer::Constants::NORMAL_RUN_MODE) { - auto runControl = new RunControl(runConfig, mode); - (void) new AndroidRunSupport(runControl); - return runControl; - } - if (mode == ProjectExplorer::Constants::DEBUG_RUN_MODE - || mode == ProjectExplorer::Constants::DEBUG_RUN_MODE_WITH_BREAK_ON_MAIN) { - auto runControl = new RunControl(runConfig, mode); - (void) new AndroidDebugSupport(runControl); - return runControl; - } - if (mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE) { - auto runControl = new RunControl(runConfig, mode); - (void) new AndroidQmlProfilerSupport(runControl); - return runControl; - } - QTC_CHECK(false); // The other run modes are not supported - return 0; -} - -} // namespace Internal -} // namespace Android diff --git a/src/plugins/android/androidrunfactories.h b/src/plugins/android/androidrunfactories.h deleted file mode 100644 index 5556b44f487..00000000000 --- a/src/plugins/android/androidrunfactories.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 BogDan Vatra -** 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 "android_global.h" -#include - - -namespace ProjectExplorer { -class RunControl; -class RunConfigWidget; -class Target; -class Node; -} // namespace ProjectExplorer - -namespace Android { -namespace Internal { - -class AndroidRunControlFactory : public ProjectExplorer::IRunControlFactory -{ - Q_OBJECT - -public: - explicit AndroidRunControlFactory(QObject *parent = 0); - - bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, - Core::Id mode) const override; - ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration, - Core::Id mode, QString *errorMessage) override; -}; - -} // namespace Internal -} // namespace Android diff --git a/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.h b/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.h index 03c6702631a..0580e0f0171 100644 --- a/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.h +++ b/src/plugins/qmakeandroidsupport/qmakeandroidrunfactories.h @@ -25,13 +25,10 @@ #pragma once -#include #include #include namespace ProjectExplorer { -class RunControl; -class RunConfigWidget; class Target; class Node; } // namespace ProjectExplorer