From bfb419717c3488065b8c032f72fea9c0694ae12d Mon Sep 17 00:00:00 2001 From: Aurindam Jana Date: Thu, 1 Aug 2013 16:28:36 +0200 Subject: QMLProfiler: Synchronise with 2.8 branch Change-Id: Ice486be6274cd9d1e54322a438d15305bba7dab1 Reviewed-by: Kai Koehne --- plugins/qmlprofiler/abstractqmlprofilerrunner.h | 5 +- plugins/qmlprofiler/localqmlprofilerrunner.cpp | 61 ++++++++++- plugins/qmlprofiler/localqmlprofilerrunner.h | 16 ++- plugins/qmlprofiler/qmlprofiler.pro | 2 + plugins/qmlprofiler/qmlprofiler.qbs | 2 + plugins/qmlprofiler/qmlprofilerengine.cpp | 117 +++++---------------- plugins/qmlprofiler/qmlprofilerengine.h | 4 +- plugins/qmlprofiler/qmlprofilerplugin.cpp | 3 + .../qmlprofiler/qmlprofilerruncontrolfactory.cpp | 104 ++++++++++++++++++ plugins/qmlprofiler/qmlprofilerruncontrolfactory.h | 57 ++++++++++ 10 files changed, 271 insertions(+), 100 deletions(-) create mode 100644 plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp create mode 100644 plugins/qmlprofiler/qmlprofilerruncontrolfactory.h diff --git a/plugins/qmlprofiler/abstractqmlprofilerrunner.h b/plugins/qmlprofiler/abstractqmlprofilerrunner.h index 233941ed962..6c2f1e7931c 100644 --- a/plugins/qmlprofiler/abstractqmlprofilerrunner.h +++ b/plugins/qmlprofiler/abstractqmlprofilerrunner.h @@ -43,11 +43,12 @@ class AbstractQmlProfilerRunner : public QObject public: explicit AbstractQmlProfilerRunner(QObject *parent = 0) : QObject(parent) { } + virtual quint16 debugPort() const = 0; + +public slots: virtual void start() = 0; virtual void stop() = 0; - virtual quint16 debugPort() const = 0; - signals: void started(); void stopped(); diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.cpp b/plugins/qmlprofiler/localqmlprofilerrunner.cpp index 529514c390f..6eb06223be9 100644 --- a/plugins/qmlprofiler/localqmlprofilerrunner.cpp +++ b/plugins/qmlprofiler/localqmlprofilerrunner.cpp @@ -29,13 +29,62 @@ #include "localqmlprofilerrunner.h" #include "qmlprofilerplugin.h" +#include "qmlprofilerengine.h" + +#include +#include +#include +#include +#include using namespace QmlProfiler; using namespace QmlProfiler::Internal; +using namespace ProjectExplorer; + +LocalQmlProfilerRunner *LocalQmlProfilerRunner::createLocalRunner( + RunConfiguration *runConfiguration, + const Analyzer::AnalyzerStartParameters &sp, + QString *errorMessage, + QmlProfilerEngine *engine) +{ + QmlProjectManager::QmlProjectRunConfiguration *rc1 = + qobject_cast(runConfiguration); + LocalApplicationRunConfiguration *rc2 = + qobject_cast(runConfiguration); + QTC_ASSERT(rc1 || rc2, return 0); + ProjectExplorer::EnvironmentAspect *environment + = runConfiguration->extraAspect(); + QTC_ASSERT(environment, return 0); + Configuration conf; + if (rc1) { + // This is a "plain" .qmlproject. + conf.executable = rc1->observerPath(); + conf.executableArguments = rc1->viewerArguments(); + conf.workingDirectory = rc1->workingDirectory(); + conf.environment = environment->environment(); + } else { + // FIXME: Check. + conf.executable = rc2->executable(); + conf.executableArguments = rc2->commandLineArguments(); + conf.workingDirectory = rc2->workingDirectory(); + conf.environment = environment->environment(); + } + + conf.port = sp.analyzerPort; -LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration, QObject *parent) : - AbstractQmlProfilerRunner(parent), - m_configuration(configuration) + if (conf.executable.isEmpty()) { + if (errorMessage) + *errorMessage = tr("No executable file to launch."); + return 0; + } + return new LocalQmlProfilerRunner(conf, engine); +} + +LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration, + QmlProfilerEngine *engine) : + AbstractQmlProfilerRunner(engine), + m_configuration(configuration), + m_engine(engine) { connect(&m_launcher, SIGNAL(appendMessage(QString,Utils::OutputFormat)), this, SIGNAL(appendMessage(QString,Utils::OutputFormat))); @@ -48,6 +97,9 @@ LocalQmlProfilerRunner::~LocalQmlProfilerRunner() void LocalQmlProfilerRunner::start() { + if (m_engine->mode() != Analyzer::StartQml) + return; + QString arguments = QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(m_configuration.port); if (!m_configuration.executableArguments.isEmpty()) @@ -78,6 +130,9 @@ void LocalQmlProfilerRunner::spontaneousStop(int exitCode) void LocalQmlProfilerRunner::stop() { + if (m_engine->mode() != Analyzer::StartQml) + return; + if (QmlProfilerPlugin::debugOutput) qWarning("QmlProfiler: Stopping application ..."); diff --git a/plugins/qmlprofiler/localqmlprofilerrunner.h b/plugins/qmlprofiler/localqmlprofilerrunner.h index 26a9b451618..37591917dae 100644 --- a/plugins/qmlprofiler/localqmlprofilerrunner.h +++ b/plugins/qmlprofiler/localqmlprofilerrunner.h @@ -35,9 +35,13 @@ #include #include +namespace ProjectExplorer { class RunConfiguration; } +namespace Analyzer { class AnalyzerStartParameters; } + namespace QmlProfiler { namespace Internal { +class QmlProfilerEngine; class LocalQmlProfilerRunner : public AbstractQmlProfilerRunner { Q_OBJECT @@ -51,7 +55,11 @@ public: Utils::Environment environment; }; - explicit LocalQmlProfilerRunner(const Configuration &configuration, QObject *parent = 0); + static LocalQmlProfilerRunner *createLocalRunner(ProjectExplorer::RunConfiguration *runConfiguration, + const Analyzer::AnalyzerStartParameters &sp, + QString *errorMessage, + QmlProfilerEngine *engine); + ~LocalQmlProfilerRunner(); // AbstractQmlProfilerRunner @@ -59,14 +67,16 @@ public: virtual void stop(); virtual quint16 debugPort() const; - bool hasExecutable() const { return !m_configuration.executable.isEmpty(); } - private slots: void spontaneousStop(int exitCode); +private: + LocalQmlProfilerRunner(const Configuration &configuration, QmlProfilerEngine *engine); + private: Configuration m_configuration; ProjectExplorer::ApplicationLauncher m_launcher; + QmlProfilerEngine *m_engine; }; } // namespace Internal diff --git a/plugins/qmlprofiler/qmlprofiler.pro b/plugins/qmlprofiler/qmlprofiler.pro index 322326b995c..c9f7ba7ed7f 100644 --- a/plugins/qmlprofiler/qmlprofiler.pro +++ b/plugins/qmlprofiler/qmlprofiler.pro @@ -21,6 +21,7 @@ SOURCES += \ qmlprofilerclientmanager.cpp \ qmlprofilerviewmanager.cpp \ qmlprofilerstatewidget.cpp \ + qmlprofilerruncontrolfactory.cpp \ qmlprofilermodelmanager.cpp \ qmlprofilersimplemodel.cpp \ qmlprofilerprocessedmodel.cpp \ @@ -51,6 +52,7 @@ HEADERS += \ qmlprofilerclientmanager.h \ qmlprofilerviewmanager.h \ qmlprofilerstatewidget.h \ + qmlprofilerruncontrolfactory.h \ qmlprofilermodelmanager.h \ qmlprofilersimplemodel.h \ qmlprofilerprocessedmodel.h \ diff --git a/plugins/qmlprofiler/qmlprofiler.qbs b/plugins/qmlprofiler/qmlprofiler.qbs index 8fca811be91..72288c3f264 100644 --- a/plugins/qmlprofiler/qmlprofiler.qbs +++ b/plugins/qmlprofiler/qmlprofiler.qbs @@ -46,6 +46,8 @@ QtcPlugin { "qmlprofilermodelmanager.h", "qmlprofilerplugin.cpp", "qmlprofilerplugin.h", + "qmlprofilerruncontrolfactory.cpp", + "qmlprofilerruncontrolfactory.h", "qmlprofilerprocessedmodel.cpp", "qmlprofilerprocessedmodel.h", "qmlprofilersimplemodel.cpp", diff --git a/plugins/qmlprofiler/qmlprofilerengine.cpp b/plugins/qmlprofiler/qmlprofilerengine.cpp index 05b702c2280..f8f4058e5a6 100644 --- a/plugins/qmlprofiler/qmlprofilerengine.cpp +++ b/plugins/qmlprofiler/qmlprofilerengine.cpp @@ -64,64 +64,20 @@ namespace Internal { class QmlProfilerEngine::QmlProfilerEnginePrivate { public: - QmlProfilerEnginePrivate(QmlProfilerEngine *qq, const AnalyzerStartParameters &sp) : q(qq), m_runner(0), sp(sp) {} - ~QmlProfilerEnginePrivate() { delete m_runner; } + QmlProfilerEnginePrivate(QmlProfilerEngine *qq, const AnalyzerStartParameters &sp) : q(qq), sp(sp), m_running(false) {} bool attach(const QString &address, uint port); - AbstractQmlProfilerRunner *createRunner(ProjectExplorer::RunConfiguration *runConfiguration, - QObject *parent); QmlProfilerEngine *q; QmlProfilerStateManager *m_profilerState; - AbstractQmlProfilerRunner *m_runner; QTimer m_noDebugOutputTimer; QmlDebug::QmlOutputParser m_outputParser; const AnalyzerStartParameters sp; + bool m_running; }; -AbstractQmlProfilerRunner * -QmlProfilerEngine::QmlProfilerEnginePrivate::createRunner(ProjectExplorer::RunConfiguration *runConfiguration, - QObject *parent) -{ - AbstractQmlProfilerRunner *runner = 0; - if (!runConfiguration) // attaching - return 0; - - QmlProjectManager::QmlProjectRunConfiguration *rc1 = - qobject_cast(runConfiguration); - LocalApplicationRunConfiguration *rc2 = - qobject_cast(runConfiguration); - // Supports only local run configurations - if (!rc1 && !rc2) - return 0; - - ProjectExplorer::EnvironmentAspect *environment - = runConfiguration->extraAspect(); - QTC_ASSERT(environment, return 0); - LocalQmlProfilerRunner::Configuration conf; - if (rc1) { - // This is a "plain" .qmlproject. - conf.executable = rc1->observerPath(); - conf.executableArguments = rc1->viewerArguments(); - conf.workingDirectory = rc1->workingDirectory(); - conf.environment = environment->environment(); - } else { - // FIXME: Check. - conf.executable = rc2->executable(); - conf.executableArguments = rc2->commandLineArguments(); - conf.workingDirectory = rc2->workingDirectory(); - conf.environment = environment->environment(); - } - const ProjectExplorer::IDevice::ConstPtr device = - ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); - QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); - conf.port = sp.analyzerPort; - runner = new LocalQmlProfilerRunner(conf, parent); - return runner; -} - // // QmlProfilerEngine // @@ -160,11 +116,6 @@ bool QmlProfilerEngine::start() { QTC_ASSERT(d->m_profilerState, return false); - if (d->m_runner) { - delete d->m_runner; - d->m_runner = 0; - } - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStarting); if (QmlProjectManager::QmlProjectRunConfiguration *rc = @@ -177,31 +128,14 @@ bool QmlProfilerEngine::start() } } - d->m_runner = d->createRunner(runConfiguration(), this); - - if (LocalQmlProfilerRunner *qmlRunner = qobject_cast(d->m_runner)) { - if (!qmlRunner->hasExecutable()) { - showNonmodalWarning(tr("No executable file to launch.")); - d->m_profilerState->setCurrentState(QmlProfilerStateManager::Idle); - AnalyzerManager::stopTool(); - return false; - } - } - - if (d->m_runner) { - connect(d->m_runner, SIGNAL(stopped()), this, SLOT(processEnded())); - connect(d->m_runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), - this, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); - d->m_runner->start(); - d->m_noDebugOutputTimer.start(); - } else if (d->sp.startMode == StartQmlRemote) { + if (d->sp.startMode == StartQmlRemote || d->sp.startMode == StartLocal) { d->m_noDebugOutputTimer.start(); } else { emit processRunning(startParameters().analyzerPort); } d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning); - emit starting(this); + engineStarted(); return true; } @@ -230,16 +164,19 @@ void QmlProfilerEngine::stop() } } -void QmlProfilerEngine::processEnded() +void QmlProfilerEngine::notifyRemoteFinished(bool success) { QTC_ASSERT(d->m_profilerState, return); switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppRunning : { - d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + if (success) + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying); + else + d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppKilled); AnalyzerManager::stopTool(); - emit finished(); + engineFinished(); break; } case QmlProfilerStateManager::AppStopped : @@ -259,10 +196,6 @@ void QmlProfilerEngine::cancelProcess() { QTC_ASSERT(d->m_profilerState, return); - // no process to be canceled? (there might be multiple engines, but only one runs a process) - if (!d->m_runner) - return; - switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppReadyToStop : { d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppStopped); @@ -279,10 +212,7 @@ void QmlProfilerEngine::cancelProcess() return; } } - - if (d->m_runner) - d->m_runner->stop(); - emit finished(); + engineFinished(); } void QmlProfilerEngine::logApplicationMessage(const QString &msg, Utils::OutputFormat format) @@ -345,10 +275,20 @@ void QmlProfilerEngine::processIsRunning(quint16 port) { d->m_noDebugOutputTimer.stop(); - if (port > 0) + if (port > 0 && mode() != StartQmlRemote) emit processRunning(port); - else if (d->m_runner) - emit processRunning(d->m_runner->debugPort()); +} + +void QmlProfilerEngine::engineStarted() +{ + d->m_running = true; + emit starting(this); +} + +void QmlProfilerEngine::engineFinished() +{ + d->m_running = false; + emit finished(); } //////////////////////////////////////////////////////////////// @@ -370,17 +310,12 @@ void QmlProfilerEngine::profilerStateChanged() { switch (d->m_profilerState->currentState()) { case QmlProfilerStateManager::AppReadyToStop : { - cancelProcess(); + if (d->m_running) + cancelProcess(); break; } case QmlProfilerStateManager::Idle : { - // When all the profiling is done, delete the profiler runner - // (a new one will be created at start) d->m_noDebugOutputTimer.stop(); - if (d->m_runner) { - delete d->m_runner; - d->m_runner = 0; - } break; } default: diff --git a/plugins/qmlprofiler/qmlprofilerengine.h b/plugins/qmlprofiler/qmlprofilerengine.h index fe8cc473137..aea3c8bf8d8 100644 --- a/plugins/qmlprofiler/qmlprofilerengine.h +++ b/plugins/qmlprofiler/qmlprofilerengine.h @@ -62,13 +62,15 @@ public slots: void stop(); private slots: - void processEnded(); + void notifyRemoteFinished(bool success = true); void cancelProcess(); void logApplicationMessage(const QString &msg, Utils::OutputFormat format); void wrongSetupMessageBox(const QString &errorMessage); void wrongSetupMessageBoxFinished(int); void processIsRunning(quint16 port = 0); + void engineStarted(); + void engineFinished(); private slots: void profilerStateChanged(); diff --git a/plugins/qmlprofiler/qmlprofilerplugin.cpp b/plugins/qmlprofiler/qmlprofilerplugin.cpp index 24a99772e39..9cd725b39c6 100644 --- a/plugins/qmlprofiler/qmlprofilerplugin.cpp +++ b/plugins/qmlprofiler/qmlprofilerplugin.cpp @@ -28,6 +28,7 @@ ****************************************************************************/ #include "qmlprofilerplugin.h" +#include "qmlprofilerruncontrolfactory.h" #include "qmlprofilertool.h" #include "abstracttimelinemodel.h" @@ -55,6 +56,8 @@ bool QmlProfilerPlugin::initialize(const QStringList &arguments, QString *errorS modes.append(StartMode(StartLocal)); modes.append(StartMode(StartRemote)); AnalyzerManager::addTool(new QmlProfilerTool(this), modes); + + addAutoReleasedObject(new QmlProfilerRunControlFactory()); QmlProfilerPlugin::instance = this; return true; diff --git a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp new file mode 100644 index 00000000000..6e3ab3ff6af --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Kläralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "qmlprofilerruncontrolfactory.h" +#include "localqmlprofilerrunner.h" +#include "qmlprofilerengine.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace Analyzer; +using namespace ProjectExplorer; + +namespace QmlProfiler { +namespace Internal { + +QmlProfilerRunControlFactory::QmlProfilerRunControlFactory(QObject *parent) : + IRunControlFactory(parent) +{ +} + +bool QmlProfilerRunControlFactory::canRun(RunConfiguration *runConfiguration, RunMode mode) const +{ + if (mode != QmlProfilerRunMode) + return false; + IAnalyzerTool *tool = AnalyzerManager::toolFromRunMode(mode); + if (tool) + return tool->canRun(runConfiguration, mode); + return false; +} + +RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfiguration, RunMode mode, QString *errorMessage) +{ + IAnalyzerTool *tool = AnalyzerManager::toolFromRunMode(mode); + if (!tool) { + if (errorMessage) + *errorMessage = tr("No analyzer tool selected"); // never happens + return 0; + } + + QTC_ASSERT(canRun(runConfiguration, mode), return 0); + + AnalyzerStartParameters sp = tool->createStartParameters(runConfiguration, mode); + sp.toolId = tool->id(); + + // only desktop device is supported + const ProjectExplorer::IDevice::ConstPtr device = + ProjectExplorer::DeviceKitInformation::device(runConfiguration->target()->kit()); + QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0); + + AnalyzerRunControl *rc = new AnalyzerRunControl(tool, sp, runConfiguration); + QmlProfilerEngine *engine = qobject_cast(rc->engine()); + if (!engine) { + delete rc; + return 0; + } + LocalQmlProfilerRunner *runner = LocalQmlProfilerRunner::createLocalRunner(runConfiguration, sp, errorMessage, engine); + if (!runner) + return 0; + connect(runner, SIGNAL(stopped()), engine, SLOT(notifyRemoteFinished())); + connect(runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)), + engine, SLOT(logApplicationMessage(QString,Utils::OutputFormat))); + connect(engine, SIGNAL(starting(const Analyzer::IAnalyzerEngine*)), runner, + SLOT(start())); + connect(rc, SIGNAL(finished()), runner, SLOT(stop())); + return rc; +} + +} // namespace Internal +} // namespace QmlProfiler diff --git a/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h new file mode 100644 index 00000000000..3973411d93a --- /dev/null +++ b/plugins/qmlprofiler/qmlprofilerruncontrolfactory.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Kläralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef QMLPROFILERRUNCONTROLFACTORY_H +#define QMLPROFILERRUNCONTROLFACTORY_H + +#include + +namespace QmlProfiler { +namespace Internal { + +class QmlProfilerRunControlFactory : public ProjectExplorer::IRunControlFactory +{ + Q_OBJECT +public: + typedef ProjectExplorer::RunConfiguration RunConfiguration; + + explicit QmlProfilerRunControlFactory(QObject *parent = 0); + + // IRunControlFactory implementation + bool canRun(RunConfiguration *runConfiguration, ProjectExplorer::RunMode mode) const; + + ProjectExplorer::RunControl *create(RunConfiguration *runConfiguration, + ProjectExplorer::RunMode mode, + QString *errorMessage); +}; + +} // namespace Internal +} // namespace QmlProfiler + +#endif // QMLPROFILERRUNCONTROLFACTORY_H -- cgit v1.2.3