Commit 9321967d authored by Benjamin Zeller's avatar Benjamin Zeller

QmlProfiler: Make creation of local RunControls more flexible

In order for plugins to create a RunControl for locally running
applications that do not use LocalApplicationRunConfiguration it is
required to export an API that takes care of the internal setup. Also this
removes the hard dependency on LocalApplicationRunConfiguration.

We don't want to expose Internal classes in public API, so we have to
make QmlProfiler::Internal::QmlProfilerRunControl and
QmlProfiler::Internal::QmlProfilerStateManager public.

Also, AbstractQmlProfilerRunner doesn't do anything useful and can be
removed.

Change-Id: I0403e5b17e14ac894addd818ad7b249c51a8ed8d
Reviewed-by: default avatarhjk <hjk@theqtcompany.com>
Reviewed-by: default avatarBenjamin Zeller <benjamin.zeller@canonical.com>
Reviewed-by: default avatarDaniel Teske <daniel.teske@theqtcompany.com>
parent 5c054dd2
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef ABSTRACTQMLPROFILERRUNNER_H
#define ABSTRACTQMLPROFILERRUNNER_H
#include <QObject>
#include <utils/outputformat.h>
namespace QmlProfiler {
namespace Internal {
class AbstractQmlProfilerRunner : public QObject
{
Q_OBJECT
public:
explicit AbstractQmlProfilerRunner(QObject *parent = 0) : QObject(parent) { }
virtual quint16 debugPort() const = 0;
public slots:
virtual void start() = 0;
virtual void stop() = 0;
signals:
void started();
void stopped();
void appendMessage(const QString &message, Utils::OutputFormat format);
};
} // namespace Internal
} // namespace QmlProfiler
#endif // ABSTRACTQMLPROFILERRUNNER_H
......@@ -32,31 +32,44 @@
#include "qmlprofilerplugin.h"
#include "qmlprofilerengine.h"
#include <analyzerbase/analyzermanager.h>
#include <analyzerbase/analyzerruncontrol.h>
#include <analyzerbase/analyzerstartparameters.h>
#include <projectexplorer/runconfiguration.h>
#include <projectexplorer/localapplicationrunconfiguration.h>
#include <projectexplorer/environmentaspect.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
#include <QTcpServer>
using namespace QmlProfiler;
using namespace QmlProfiler::Internal;
using namespace ProjectExplorer;
LocalQmlProfilerRunner *LocalQmlProfilerRunner::createLocalRunner(
Analyzer::AnalyzerRunControl *LocalQmlProfilerRunner::createLocalRunControl(
RunConfiguration *runConfiguration,
const Analyzer::AnalyzerStartParameters &sp,
QString *errorMessage,
QmlProfilerRunControl *engine)
QString *errorMessage)
{
LocalApplicationRunConfiguration *larc =
qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
QTC_ASSERT(larc, return 0);
EnvironmentAspect *environment = runConfiguration->extraAspect<EnvironmentAspect>();
QTC_ASSERT(environment, return 0);
// only desktop device is supported
const IDevice::ConstPtr device = DeviceKitInformation::device(
runConfiguration->target()->kit());
QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0);
Analyzer::AnalyzerRunControl *rc = Analyzer::AnalyzerManager::createRunControl(
sp, runConfiguration);
QmlProfilerRunControl *engine = qobject_cast<QmlProfilerRunControl *>(rc);
if (!engine) {
delete rc;
return 0;
}
Configuration conf;
conf.executable = larc->executable();
conf.executableArguments = larc->commandLineArguments();
conf.workingDirectory = larc->workingDirectory();
conf.environment = environment->environment();
conf.executable = sp.debuggee;
conf.executableArguments = sp.debuggeeArgs;
conf.workingDirectory = sp.workingDirectory;
conf.environment = sp.environment;
conf.port = sp.analyzerPort;
......@@ -65,12 +78,33 @@ LocalQmlProfilerRunner *LocalQmlProfilerRunner::createLocalRunner(
*errorMessage = tr("No executable file to launch.");
return 0;
}
return new LocalQmlProfilerRunner(conf, engine);
LocalQmlProfilerRunner *runner = new LocalQmlProfilerRunner(conf, engine);
QObject::connect(runner, SIGNAL(stopped()), engine, SLOT(notifyRemoteFinished()));
QObject::connect(runner, SIGNAL(appendMessage(QString,Utils::OutputFormat)),
engine, SLOT(logApplicationMessage(QString,Utils::OutputFormat)));
QObject::connect(engine, SIGNAL(starting(const Analyzer::AnalyzerRunControl*)), runner,
SLOT(start()));
QObject::connect(rc, SIGNAL(finished()), runner, SLOT(stop()));
return rc;
}
quint16 LocalQmlProfilerRunner::findFreePort(QString &host)
{
QTcpServer server;
if (!server.listen(QHostAddress::LocalHost)
&& !server.listen(QHostAddress::LocalHostIPv6)) {
qWarning() << "Cannot open port on host for QML profiling.";
return 0;
}
host = server.serverAddress().toString();
return server.serverPort();
}
LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration,
QmlProfilerRunControl *engine) :
AbstractQmlProfilerRunner(engine),
QObject(engine),
m_configuration(configuration),
m_engine(engine)
{
......@@ -132,8 +166,3 @@ void LocalQmlProfilerRunner::stop()
if (m_launcher.isRunning())
m_launcher.stop();
}
quint16 LocalQmlProfilerRunner::debugPort() const
{
return m_configuration.port;
}
......@@ -31,19 +31,20 @@
#ifndef LOCALQMLPROFILERRUNNER_H
#define LOCALQMLPROFILERRUNNER_H
#include "abstractqmlprofilerrunner.h"
#include "qmlprofiler_global.h"
#include <utils/environment.h>
#include <projectexplorer/applicationlauncher.h>
namespace ProjectExplorer { class RunConfiguration; }
namespace Analyzer { class AnalyzerStartParameters; }
namespace Analyzer {
class AnalyzerStartParameters;
class AnalyzerRunControl;
}
namespace QmlProfiler {
namespace Internal {
class QmlProfilerRunControl;
class LocalQmlProfilerRunner : public AbstractQmlProfilerRunner
class QMLPROFILER_EXPORT LocalQmlProfilerRunner : public QObject
{
Q_OBJECT
......@@ -56,31 +57,33 @@ public:
Utils::Environment environment;
};
static LocalQmlProfilerRunner *createLocalRunner(ProjectExplorer::RunConfiguration *runConfiguration,
const Analyzer::AnalyzerStartParameters &sp,
QString *errorMessage,
QmlProfilerRunControl *engine);
static Analyzer::AnalyzerRunControl *createLocalRunControl(
ProjectExplorer::RunConfiguration *runConfiguration,
const Analyzer::AnalyzerStartParameters &sp,
QString *errorMessage);
static quint16 findFreePort(QString &host);
~LocalQmlProfilerRunner();
// AbstractQmlProfilerRunner
virtual void start();
virtual void stop();
virtual quint16 debugPort() const;
signals:
void started();
void stopped();
void appendMessage(const QString &message, Utils::OutputFormat format);
private slots:
void spontaneousStop(int exitCode, QProcess::ExitStatus status);
void start();
void stop();
private:
LocalQmlProfilerRunner(const Configuration &configuration, QmlProfilerRunControl *engine);
private:
Configuration m_configuration;
ProjectExplorer::ApplicationLauncher m_launcher;
QmlProfilerRunControl *m_engine;
};
} // namespace Internal
} // namespace QmlProfiler
#endif // LOCALQMLPROFILERRUNNER_H
......@@ -32,7 +32,6 @@ SOURCES += \
qmlprofilerviewmanager.cpp
HEADERS += \
abstractqmlprofilerrunner.h \
localqmlprofilerrunner.h \
qmlprofiler_global.h \
qmlprofileranimationsmodel.h \
......
......@@ -58,7 +58,6 @@ using namespace Core;
using namespace ProjectExplorer;
namespace QmlProfiler {
namespace Internal {
//
// QmlProfilerEnginePrivate
......@@ -306,5 +305,4 @@ void QmlProfilerRunControl::profilerStateChanged()
}
}
} // namespace Internal
} // namespace QmlProfiler
......@@ -37,7 +37,6 @@
#include <utils/outputformat.h>
namespace QmlProfiler {
namespace Internal {
class QmlProfilerRunControl : public Analyzer::AnalyzerRunControl
{
......@@ -81,7 +80,6 @@ private:
QmlProfilerEnginePrivate *d;
};
} // namespace Internal
} // namespace QmlProfiler
#endif // QMLPROFILERENGINE_H
......@@ -33,9 +33,6 @@
#include "qmlprofilerengine.h"
#include <analyzerbase/ianalyzertool.h>
#include <analyzerbase/analyzermanager.h>
#include <analyzerbase/analyzerstartparameters.h>
#include <analyzerbase/analyzerruncontrol.h>
#include <debugger/debuggerrunconfigurationaspect.h>
......@@ -49,8 +46,6 @@
#include <utils/qtcassert.h>
#include <QTcpServer>
using namespace Analyzer;
using namespace ProjectExplorer;
......@@ -84,16 +79,11 @@ static AnalyzerStartParameters createQmlProfilerStartParameters(RunConfiguration
sp.debuggeeArgs = rc->commandLineArguments();
sp.displayName = rc->displayName();
const IDevice::ConstPtr device = DeviceKitInformation::device(runConfiguration->target()->kit());
if (device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
QTcpServer server;
if (!server.listen(QHostAddress::LocalHost) && !server.listen(QHostAddress::LocalHostIPv6)) {
qWarning() << "Cannot open port on host for QML profiling.";
return sp;
}
sp.analyzerHost = server.serverAddress().toString();
sp.analyzerPort = server.serverPort();
}
quint16 localPort = LocalQmlProfilerRunner::findFreePort(sp.analyzerHost);
if (localPort == 0)
return sp;
sp.analyzerPort = localPort;
sp.startMode = StartLocal;
return sp;
}
......@@ -104,27 +94,7 @@ RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfigurat
AnalyzerStartParameters sp = createQmlProfilerStartParameters(runConfiguration);
sp.runMode = mode;
// only desktop device is supported
const IDevice::ConstPtr device = DeviceKitInformation::device(runConfiguration->target()->kit());
QTC_ASSERT(device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE, return 0);
AnalyzerRunControl *rc = AnalyzerManager::createRunControl(sp, runConfiguration);
QmlProfilerRunControl *engine = qobject_cast<QmlProfilerRunControl *>(rc);
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::AnalyzerRunControl*)), runner,
SLOT(start()));
connect(rc, SIGNAL(finished()), runner, SLOT(stop()));
return rc;
return LocalQmlProfilerRunner::createLocalRunControl(runConfiguration, sp, errorMessage);
}
} // namespace Internal
......
......@@ -37,7 +37,6 @@
//#define _DEBUG_PROFILERSTATE_
namespace QmlProfiler {
namespace Internal {
inline QString stringForState(int state) {
switch (state) {
......@@ -190,4 +189,3 @@ void QmlProfilerStateManager::setRecordingFeatures(quint64 features)
}
}
}
......@@ -34,7 +34,6 @@
#include <QObject>
namespace QmlProfiler {
namespace Internal {
class QmlProfilerStateManager : public QObject
{
......@@ -78,7 +77,6 @@ private:
QmlProfilerStateManagerPrivate *d;
};
}
}
#endif // QMLPROFILERSTATEMANAGER_H
......@@ -41,9 +41,10 @@
namespace QmlProfiler {
class QmlProfilerModelManager;
class QmlProfilerStateManager;
namespace Internal {
class QmlProfilerStateManager;
class QmlProfilerTool;
class QmlProfilerViewManager;
......
......@@ -35,11 +35,11 @@
namespace QmlProfiler {
class QmlProfilerModelManager;
class QmlProfilerStateManager;
namespace Internal {
class QmlProfilerTool;
class QmlProfilerStateManager;
class QmlProfilerViewManager : public QObject
{
......
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