Commit 76185b3b authored by hjk's avatar hjk

QmlProfiler: Convert to a RunWorker based setup

This also re-enables the remote linux case and enables
the recording of a single run of events.

Change-Id: I9ea55017c8e5f2f17e6f32c5453df48093e41931
Reviewed-by: Christian Kandeler's avatarChristian Kandeler <christian.kandeler@qt.io>
Reviewed-by: Christian Stenger's avatarChristian Stenger <christian.stenger@qt.io>
parent 2317d06a
......@@ -25,11 +25,13 @@
#include "localqmlprofilerrunner.h"
#include "qmlprofilerplugin.h"
#include "qmlprofilerruncontrol.h"
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/target.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
......@@ -67,14 +69,16 @@ Utils::Port LocalQmlProfilerRunner::findFreePort(QString &host)
}
LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration,
RunControl *runControl) :
QObject(runControl),
QmlProfilerRunner *runner) :
QObject(runner->runControl()),
m_runControl(runner->runControl()),
m_configuration(configuration)
{
auto runControl = runner->runControl();
connect(&m_launcher, &ApplicationLauncher::appendMessage,
this, &LocalQmlProfilerRunner::appendMessage);
connect(this, &LocalQmlProfilerRunner::stopped,
runControl, &RunControl::notifyRemoteFinished);
runner, &QmlProfilerRunner::notifyRemoteFinished);
connect(this, &LocalQmlProfilerRunner::appendMessage,
runControl, &RunControl::appendMessage);
connect(runControl, &RunControl::starting,
......@@ -92,23 +96,27 @@ LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuratio
});
connect(&m_outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
runControl, [this, runControl](Utils::Port port) {
runControl, [this, runControl, runner](Utils::Port port) {
runControl->notifyRemoteSetupDone(port);
runner->notifyRemoteSetupDone(port);
});
connect(&m_outputParser, &QmlDebug::QmlOutputParser::noOutputMessage,
runControl, [this, runControl]() {
runControl, [this, runControl, runner]() {
runControl->notifyRemoteSetupDone(Utils::Port());
runner->notifyRemoteSetupDone(Utils::Port());
});
connect(&m_outputParser, &QmlDebug::QmlOutputParser::connectingToSocketMessage,
runControl, [this, runControl]() {
runControl, [this, runControl, runner]() {
runControl->notifyRemoteSetupDone(Utils::Port());
runner->notifyRemoteSetupDone(Utils::Port());
});
connect(&m_outputParser, &QmlDebug::QmlOutputParser::errorMessage,
runControl, [this, runControl](const QString &message) {
runControl, [this, runControl, runner](const QString &message) {
runControl->notifyRemoteSetupFailed(message);
runner->notifyRemoteSetupFailed(message);
});
}
......
......@@ -34,6 +34,8 @@
namespace QmlProfiler {
class QmlProfilerRunner;
class QMLPROFILER_EXPORT LocalQmlProfilerRunner : public QObject
{
Q_OBJECT
......@@ -46,7 +48,7 @@ public:
};
LocalQmlProfilerRunner(const Configuration &configuration,
ProjectExplorer::RunControl *runControl);
QmlProfilerRunner *runner);
static Utils::Port findFreePort(QString &host);
static QString findFreeSocket();
......@@ -61,6 +63,7 @@ private:
void start();
void stop();
ProjectExplorer::RunControl *m_runControl;
Configuration m_configuration;
ProjectExplorer::ApplicationLauncher m_launcher;
QmlDebug::QmlOutputParser m_outputParser;
......
......@@ -251,6 +251,8 @@ void QmlProfilerModelManager::addEvents(const QVector<QmlEvent> &events)
void QmlProfilerModelManager::addEvent(const QmlEvent &event)
{
d->eventStream << event;
QTC_ASSERT(event.typeIndex() < d->eventTypes.size(),
d->eventTypes.resize(event.typeIndex() + 1));
d->dispatch(event, d->eventTypes.at(event.typeIndex()));
}
......
......@@ -64,7 +64,7 @@ namespace QmlProfiler {
// QmlProfilerRunControlPrivate
//
class QmlProfilerRunControl::QmlProfilerRunControlPrivate
class QmlProfilerRunner::QmlProfilerRunnerPrivate
{
public:
QmlProfilerStateManager *m_profilerState = 0;
......@@ -75,12 +75,12 @@ public:
// QmlProfilerRunControl
//
QmlProfilerRunControl::QmlProfilerRunControl(RunConfiguration *runConfiguration)
: RunControl(runConfiguration, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE)
, d(new QmlProfilerRunControlPrivate)
QmlProfilerRunner::QmlProfilerRunner(RunControl *runControl)
: RunWorker(runControl)
, d(new QmlProfilerRunnerPrivate)
{
setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
setSupportsReRunning(false);
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
runControl->setSupportsReRunning(false);
// Only wait 4 seconds for the 'Waiting for connection' on application output, then just try to connect
// (application output might be redirected / blocked)
......@@ -91,20 +91,20 @@ QmlProfilerRunControl::QmlProfilerRunControl(RunConfiguration *runConfiguration)
});
}
QmlProfilerRunControl::~QmlProfilerRunControl()
QmlProfilerRunner::~QmlProfilerRunner()
{
if (isRunning() && d->m_profilerState)
stop();
if (runControl()->isRunning() && d->m_profilerState)
runControl()->stop();
delete d;
}
void QmlProfilerRunControl::start()
void QmlProfilerRunner::start()
{
reportApplicationStart();
runControl()->reportApplicationStart();
Internal::QmlProfilerTool::instance()->finalizeRunControl(this);
QTC_ASSERT(d->m_profilerState, reportApplicationStop(); return);
QTC_ASSERT(d->m_profilerState, runControl()->reportApplicationStop(); return);
QTC_ASSERT(connection().is<AnalyzerConnection>(), reportApplicationStop(); return);
QTC_ASSERT(connection().is<AnalyzerConnection>(), runControl()->reportApplicationStop(); return);
auto conn = connection().as<AnalyzerConnection>();
if (conn.analyzerPort.isValid())
......@@ -113,10 +113,10 @@ void QmlProfilerRunControl::start()
d->m_noDebugOutputTimer.start();
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning);
emit starting();
emit runControl()->starting();
}
void QmlProfilerRunControl::stop()
void QmlProfilerRunner::stop()
{
QTC_ASSERT(d->m_profilerState, return);
......@@ -141,14 +141,14 @@ void QmlProfilerRunControl::stop()
}
}
void QmlProfilerRunControl::notifyRemoteFinished()
void QmlProfilerRunner::notifyRemoteFinished()
{
QTC_ASSERT(d->m_profilerState, return);
switch (d->m_profilerState->currentState()) {
case QmlProfilerStateManager::AppRunning:
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying);
reportApplicationStop();
runControl()->reportApplicationStop();
break;
case QmlProfilerStateManager::Idle:
break;
......@@ -160,7 +160,7 @@ void QmlProfilerRunControl::notifyRemoteFinished()
}
}
void QmlProfilerRunControl::cancelProcess()
void QmlProfilerRunner::cancelProcess()
{
QTC_ASSERT(d->m_profilerState, return);
......@@ -177,10 +177,10 @@ void QmlProfilerRunControl::cancelProcess()
return;
}
}
reportApplicationStop();
runControl()->reportApplicationStop();
}
void QmlProfilerRunControl::notifyRemoteSetupFailed(const QString &errorMessage)
void QmlProfilerRunner::notifyRemoteSetupFailed(const QString &errorMessage)
{
QMessageBox *infoBox = new QMessageBox(ICore::mainWindow());
infoBox->setIcon(QMessageBox::Critical);
......@@ -193,17 +193,17 @@ void QmlProfilerRunControl::notifyRemoteSetupFailed(const QString &errorMessage)
infoBox->setModal(true);
connect(infoBox, &QDialog::finished,
this, &QmlProfilerRunControl::wrongSetupMessageBoxFinished);
this, &QmlProfilerRunner::wrongSetupMessageBoxFinished);
infoBox->show();
// KILL
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying);
d->m_noDebugOutputTimer.stop();
reportApplicationStop();
runControl()->reportApplicationStop();
}
void QmlProfilerRunControl::wrongSetupMessageBoxFinished(int button)
void QmlProfilerRunner::wrongSetupMessageBoxFinished(int button)
{
if (button == QMessageBox::Help) {
HelpManager::handleHelpRequest(QLatin1String("qthelp://org.qt-project.qtcreator/doc/creator-debugging-qml.html"
......@@ -211,7 +211,7 @@ void QmlProfilerRunControl::wrongSetupMessageBoxFinished(int button)
}
}
void QmlProfilerRunControl::notifyRemoteSetupDone(Utils::Port port)
void QmlProfilerRunner::notifyRemoteSetupDone(Utils::Port port)
{
d->m_noDebugOutputTimer.stop();
......@@ -223,26 +223,26 @@ void QmlProfilerRunControl::notifyRemoteSetupDone(Utils::Port port)
emit processRunning(port);
}
void QmlProfilerRunControl::registerProfilerStateManager( QmlProfilerStateManager *profilerState )
void QmlProfilerRunner::registerProfilerStateManager( QmlProfilerStateManager *profilerState )
{
// disconnect old
if (d->m_profilerState)
disconnect(d->m_profilerState, &QmlProfilerStateManager::stateChanged,
this, &QmlProfilerRunControl::profilerStateChanged);
this, &QmlProfilerRunner::profilerStateChanged);
d->m_profilerState = profilerState;
// connect
if (d->m_profilerState)
connect(d->m_profilerState, &QmlProfilerStateManager::stateChanged,
this, &QmlProfilerRunControl::profilerStateChanged);
this, &QmlProfilerRunner::profilerStateChanged);
}
void QmlProfilerRunControl::profilerStateChanged()
void QmlProfilerRunner::profilerStateChanged()
{
switch (d->m_profilerState->currentState()) {
case QmlProfilerStateManager::Idle:
reportApplicationStop();
runControl()->reportApplicationStop();
d->m_noDebugOutputTimer.stop();
break;
default:
......
......@@ -32,22 +32,22 @@
namespace QmlProfiler {
class QmlProfilerRunControl : public ProjectExplorer::RunControl
class QmlProfilerRunner : public ProjectExplorer::RunWorker
{
Q_OBJECT
public:
QmlProfilerRunControl(ProjectExplorer::RunConfiguration *runConfiguration);
~QmlProfilerRunControl() override;
QmlProfilerRunner(ProjectExplorer::RunControl *runControl);
~QmlProfilerRunner() override;
void registerProfilerStateManager( QmlProfilerStateManager *profilerState );
void notifyRemoteSetupDone(Utils::Port port) override;
void notifyRemoteSetupFailed(const QString &errorMessage) override;
void notifyRemoteSetupDone(Utils::Port port);
void notifyRemoteSetupFailed(const QString &errorMessage);
void start() override;
void stop() override;
void cancelProcess();
void notifyRemoteFinished() override;
void notifyRemoteFinished();
signals:
void processRunning(Utils::Port port);
......@@ -56,8 +56,8 @@ private:
void wrongSetupMessageBoxFinished(int);
void profilerStateChanged();
class QmlProfilerRunControlPrivate;
QmlProfilerRunControlPrivate *d;
class QmlProfilerRunnerPrivate;
QmlProfilerRunnerPrivate *d;
};
} // namespace QmlProfiler
......@@ -92,7 +92,8 @@ RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfigurat
connection.analyzerPort = LocalQmlProfilerRunner::findFreePort(connection.analyzerHost);
}
auto runControl = new QmlProfilerRunControl(runConfiguration);
auto runControl = new RunControl(runConfiguration, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
auto runWorker = runControl->createWorker(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
runControl->setRunnable(runnable);
runControl->setConnection(connection);
......@@ -103,7 +104,7 @@ RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfigurat
conf.socket = connection.analyzerSocket;
conf.port = connection.analyzerPort;
(void) new LocalQmlProfilerRunner(conf, runControl);
(void) new LocalQmlProfilerRunner(conf, qobject_cast<QmlProfilerRunner *>(runWorker));
return runControl;
}
......
......@@ -248,8 +248,7 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
d->m_profilerModelManager->populateFileFinder();
auto runWorkerCreator = [this](RunControl *runControl) {
// return createRunControl(runConfiguration);
return nullptr; // FIXME
return createRunner(runControl, Debugger::startupRunConfiguration());
};
QString description = tr("The QML Profiler can be used to find performance "
......@@ -329,7 +328,7 @@ void QmlProfilerTool::updateRunActions()
}
}
RunControl *QmlProfilerTool::createRunControl(RunConfiguration *runConfiguration)
RunWorker *QmlProfilerTool::createRunner(RunControl *runControl, RunConfiguration *runConfiguration)
{
d->m_toolBusy = true;
if (runConfiguration) {
......@@ -344,27 +343,27 @@ RunControl *QmlProfilerTool::createRunControl(RunConfiguration *runConfiguration
}
}
auto runControl = new QmlProfilerRunControl(runConfiguration);
auto runWorker = new QmlProfilerRunner(runControl);
connect(runControl, &RunControl::finished, this, [this, runControl] {
d->m_toolBusy = false;
updateRunActions();
disconnect(d->m_stopAction, &QAction::triggered, runControl, &RunControl::stop);
});
connect(d->m_stopAction, &QAction::triggered, runControl, &QmlProfilerRunControl::stop);
connect(d->m_stopAction, &QAction::triggered, runControl, &RunControl::stop);
updateRunActions();
return runControl;
return runWorker;
}
void QmlProfilerTool::finalizeRunControl(QmlProfilerRunControl *runControl)
void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
{
runControl->registerProfilerStateManager(d->m_profilerState);
runWorker->registerProfilerStateManager(d->m_profilerState);
QmlProfilerClientManager *clientManager = d->m_profilerConnections;
QTC_ASSERT(runControl->connection().is<AnalyzerConnection>(), return);
QTC_ASSERT(runWorker->connection().is<AnalyzerConnection>(), return);
// FIXME: Check that there's something sensible in sp.connParams
auto connection = runControl->connection().as<AnalyzerConnection>();
auto connection = runWorker->connection().as<AnalyzerConnection>();
if (!connection.analyzerSocket.isEmpty()) {
clientManager->setLocalSocket(connection.analyzerSocket);
// We open the server and the application connects to it, so let's do that right away.
......@@ -377,6 +376,7 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunControl *runControl)
// Initialize m_projectFinder
//
auto runControl = runWorker->runControl();
RunConfiguration *runConfiguration = runControl->runConfiguration();
if (runConfiguration) {
d->m_profilerModelManager->populateFileFinder(runConfiguration);
......@@ -384,14 +384,14 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunControl *runControl)
if (connection.analyzerSocket.isEmpty()) {
QString host = connection.analyzerHost;
connect(runControl, &QmlProfilerRunControl::processRunning,
connect(runWorker, &QmlProfilerRunner::processRunning,
clientManager, [clientManager, host](Utils::Port port) {
clientManager->setTcpConnection(host, port);
clientManager->connectToTcpServer();
});
}
connect(clientManager, &QmlProfilerClientManager::connectionFailed,
runControl, [this, clientManager, runControl]() {
runWorker, [this, clientManager, runWorker]() {
QMessageBox *infoBox = new QMessageBox(ICore::mainWindow());
infoBox->setIcon(QMessageBox::Critical);
infoBox->setWindowTitle(tr("Qt Creator"));
......@@ -401,7 +401,7 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunControl *runControl)
infoBox->setDefaultButton(QMessageBox::Retry);
infoBox->setModal(true);
connect(infoBox, &QDialog::finished, runControl, [clientManager, runControl](int result) {
connect(infoBox, &QDialog::finished, runWorker, [clientManager, runWorker](int result) {
switch (result) {
case QMessageBox::Retry:
clientManager->retryConnect();
......@@ -412,7 +412,7 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunControl *runControl)
case QMessageBox::Cancel:
// The actual error message has already been logged.
logState(tr("Failed to connect."));
runControl->cancelProcess();
runWorker->cancelProcess();
break;
}
});
......@@ -612,7 +612,8 @@ void QmlProfilerTool::startRemoteTool()
Debugger::selectPerspective(Constants::QmlProfilerPerspectiveId);
RunConfiguration *rc = Debugger::startupRunConfiguration();
auto runControl = qobject_cast<QmlProfilerRunControl *>(createRunControl(rc));
auto runControl = new RunControl(rc, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
runControl->createWorker(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
runControl->setConnection(connection);
ProjectExplorerPlugin::startRunControl(runControl);
......
......@@ -37,7 +37,7 @@ QT_END_NAMESPACE
namespace QmlProfiler {
class QmlProfilerRunControl;
class QmlProfilerRunner;
namespace Internal {
......@@ -51,8 +51,9 @@ public:
static QmlProfilerTool *instance();
ProjectExplorer::RunControl *createRunControl(ProjectExplorer::RunConfiguration *runConfiguration = 0);
void finalizeRunControl(QmlProfilerRunControl *runControl);
ProjectExplorer::RunWorker *createRunner(ProjectExplorer::RunControl *runControl,
ProjectExplorer::RunConfiguration *runConfiguration = 0);
void finalizeRunControl(QmlProfilerRunner *runWorker);
bool prepareTool();
void startRemoteTool();
......
......@@ -60,9 +60,10 @@ void LocalQmlProfilerRunnerTest::testRunner()
// should not be used anywhere but cannot be empty
configuration.socket = connection.analyzerSocket = QString("invalid");
rc = new QmlProfilerRunControl(nullptr);
rc = new ProjectExplorer::RunControl(nullptr, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
auto worker = new QmlProfilerRunner(rc);
rc->setConnection(connection);
auto runner = new LocalQmlProfilerRunner(configuration, rc);
auto runner = new LocalQmlProfilerRunner(configuration, worker);
connectRunner(runner);
rc->initiateStart();
......@@ -81,9 +82,10 @@ void LocalQmlProfilerRunnerTest::testRunner1()
configuration.debuggee.commandLineArguments = QString("-test QmlProfiler,");
delete rc;
rc = new QmlProfilerRunControl(nullptr);
rc = new ProjectExplorer::RunControl(nullptr, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
auto worker = new QmlProfilerRunner(rc);
rc->setConnection(connection);
auto runner = new LocalQmlProfilerRunner(configuration, rc);
auto runner = new LocalQmlProfilerRunner(configuration, worker);
connectRunner(runner);
rc->initiateStart();
QTimer::singleShot(0, this, &LocalQmlProfilerRunnerTest::testRunner2);
......@@ -101,9 +103,10 @@ void LocalQmlProfilerRunnerTest::testRunner2()
connection.analyzerSocket.clear();
configuration.port = connection.analyzerPort =
LocalQmlProfilerRunner::findFreePort(connection.analyzerHost);
rc = new QmlProfilerRunControl(nullptr);
rc = new ProjectExplorer::RunControl(nullptr, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
auto worker = new QmlProfilerRunner(rc);
rc->setConnection(connection);
auto runner = new LocalQmlProfilerRunner(configuration, rc);
auto runner = new LocalQmlProfilerRunner(configuration, worker);
connectRunner(runner);
rc->initiateStart();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment