summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>2009-10-29 12:48:12 +0100
committerFriedemann Kleint <Friedemann.Kleint@nokia.com>2009-10-29 12:48:12 +0100
commitd749c1dc7186e87ffc4e729898ce8c6bc004c02c (patch)
tree5f53f30d79629fc10d1ea225c837136f93f74cb3 /src
parent7fc6a0ecc873eb1f54ee60f22fdd010ebe0ea990 (diff)
downloadqt-creator-d749c1dc7186e87ffc4e729898ce8c6bc004c02c.tar.gz
S60: Provide a message box prompting to start TRK
... with cancel, similar to the Bluetooth connect box. Reviewed-by: Robert Loehning <robert.loehning@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp67
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h11
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp97
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h9
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60manager.cpp3
-rw-r--r--src/plugins/qt4projectmanager/qt-s60/s60manager.h10
-rw-r--r--src/shared/trk/launcher.cpp61
-rw-r--r--src/shared/trk/launcher.h14
8 files changed, 203 insertions, 69 deletions
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
index 0804a9fe25..181fe4d192 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp
@@ -50,6 +50,9 @@
#include <debugger/debuggermanager.h>
+#include <QtGui/QMessageBox>
+#include <QtGui/QMainWindow>
+
using namespace ProjectExplorer;
using namespace Qt4ProjectManager::Internal;
@@ -446,6 +449,11 @@ S60DeviceRunControlBase::~S60DeviceRunControlBase()
void S60DeviceRunControlBase::start()
{
emit started();
+ if (m_serialPortName.isEmpty()) {
+ error(this, tr("There is no device plugged in."));
+ emit finished();
+ return;
+ }
emit addToOutputWindow(this, tr("Creating %1.sisx ...").arg(QDir::toNativeSeparators(m_baseFileName)));
emit addToOutputWindow(this, tr("Executable file: %1").arg(m_executableFileName));
@@ -472,10 +480,23 @@ void S60DeviceRunControlBase::start()
m_makesis->start(m_makesisTool, QStringList(m_packageFile), QIODevice::ReadOnly);
}
+static inline void stopProcess(QProcess *p)
+{
+ const int timeOutMS = 200;
+ if (p->state() != QProcess::Running)
+ return;
+ p->terminate();
+ if (p->waitForFinished(timeOutMS))
+ return;
+ p->kill();
+}
+
void S60DeviceRunControlBase::stop()
{
- m_makesis->kill();
- m_signsis->kill();
+ if (m_makesis)
+ stopProcess(m_makesis);
+ if (m_signsis)
+ stopProcess(m_signsis);
if (m_launcher)
m_launcher->terminate();
}
@@ -529,6 +550,7 @@ void S60DeviceRunControlBase::makesisProcessFinished()
{
if (m_makesis->exitCode() != 0) {
error(this, tr("An error occurred while creating the package."));
+ stop();
emit finished();
return;
}
@@ -557,6 +579,7 @@ void S60DeviceRunControlBase::signsisProcessFinished()
{
if (m_signsis->exitCode() != 0) {
error(this, tr("An error occurred while creating the package."));
+ stop();
emit finished();
return;
}
@@ -570,6 +593,7 @@ void S60DeviceRunControlBase::signsisProcessFinished()
connect(m_launcher, SIGNAL(installingStarted()), this, SLOT(printInstallingNotice()));
connect(m_launcher, SIGNAL(canNotInstall(QString,QString)), this, SLOT(printInstallFailed(QString,QString)));
connect(m_launcher, SIGNAL(copyProgress(int)), this, SLOT(printCopyProgress(int)));
+ connect(m_launcher, SIGNAL(stateChanged(int)), this, SLOT(slotLauncherStateChanged(int)));
//TODO sisx destination and file path user definable
m_launcher->setTrkServerName(m_serialPortName);
@@ -593,18 +617,17 @@ void S60DeviceRunControlBase::signsisProcessFinished()
break;
case trk::PromptStartCommunicationCanceled:
case trk::PromptStartCommunicationError:
- delete m_launcher;
- m_launcher = 0;
error(this, errorMessage);
+ stop();
emit finished();
return;
};
if (!m_launcher->startServer(&errorMessage)) {
- delete m_launcher;
- m_launcher = 0;
+
error(this, tr("Could not connect to phone on port '%1': %2\n"
"Check if the phone is connected and the TRK application is running.").arg(m_serialPortName, errorMessage));
+ stop();
emit finished();
}
}
@@ -657,6 +680,37 @@ void S60DeviceRunControlBase::launcherFinished()
handleLauncherFinished();
}
+QMessageBox *S60DeviceRunControlBase::createTrkWaitingMessageBox(const QString &port, QWidget *parent)
+{
+ const QString title = QCoreApplication::translate("Qt4ProjectManager::Internal::S60DeviceRunControlBase",
+ "Waiting for TRK");
+ const QString text = QCoreApplication::translate("Qt4ProjectManager::Internal::S60DeviceRunControlBase",
+ "Please start TRK on %1.").arg(port);
+ QMessageBox *rc = new QMessageBox(QMessageBox::Information, title, text,
+ QMessageBox::Cancel, parent);
+ return rc;
+}
+
+void S60DeviceRunControlBase::slotLauncherStateChanged(int s)
+{
+ if (s == trk::Launcher::WaitingForTrk) {
+ QMessageBox *mb = S60DeviceRunControlBase::createTrkWaitingMessageBox(m_launcher->trkServerName(),
+ Core::ICore::instance()->mainWindow());
+ connect(m_launcher, SIGNAL(stateChanged(int)), mb, SLOT(close()));
+ connect(mb, SIGNAL(finished(int)), this, SLOT(slotWaitingForTrkClosed()));
+ mb->open();
+ }
+}
+
+void S60DeviceRunControlBase::slotWaitingForTrkClosed()
+{
+ if (m_launcher && m_launcher->state() == trk::Launcher::WaitingForTrk) {
+ stop();
+ error(this, tr("Canceled."));
+ emit finished();
+ }
+}
+
void S60DeviceRunControlBase::processFailed(const QString &program, QProcess::ProcessError errorCode)
{
QString errorString;
@@ -671,6 +725,7 @@ void S60DeviceRunControlBase::processFailed(const QString &program, QProcess::Pr
errorString = tr("An error has occurred while running %1.");
}
error(this, errorString.arg(program));
+ stop();
emit finished();
}
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
index 444e8855f6..fa7651a2fb 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h
@@ -37,6 +37,11 @@
#include <QtCore/QProcess>
+QT_BEGIN_NAMESPACE
+class QMessageBox;
+class QWidget;
+QT_END_NAMESPACE
+
namespace Debugger {
class DebuggerStartParameters;
}
@@ -134,6 +139,8 @@ public:
virtual void stop();
virtual bool isRunning() const;
+ static QMessageBox *createTrkWaitingMessageBox(const QString &port, QWidget *parent = 0);
+
protected:
virtual void initLauncher(const QString &executable, trk::Launcher *) = 0;
virtual void handleLauncherFinished() = 0;
@@ -162,8 +169,10 @@ private slots:
void printInstallingNotice();
void printInstallFailed(const QString &filename, const QString &errorMessage);
void launcherFinished();
+ void slotLauncherStateChanged(int);
+ void slotWaitingForTrkClosed();
-private:
+private:
bool createPackageFileFromTemplate(QString *errorMessage);
QString m_serialPortName;
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
index a80c4200c9..7fbbf9f7fc 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp
@@ -54,6 +54,8 @@
#include <QtGui/QStyle>
#include <QtGui/QApplication>
#include <QtGui/QSpacerItem>
+#include <QtGui/QMainWindow>
+#include <QtGui/QMessageBox>
Q_DECLARE_METATYPE(Qt4ProjectManager::Internal::CommunicationDevice)
@@ -196,6 +198,7 @@ void S60DeviceRunConfigurationWidget::updateSerialDevices()
if (newPortName != previousRunConfigurationPortName)
m_runConfiguration->setSerialPortName(newPortName);
}
+ updateSummary();
}
CommunicationDevice S60DeviceRunConfigurationWidget::device(int i) const
@@ -288,66 +291,72 @@ void S60DeviceRunConfigurationWidget::setDeviceInfoLabel(const QString &message,
m_deviceInfoLabel->adjustSize();
}
-void S60DeviceRunConfigurationWidget::updateDeviceInfo()
+void S60DeviceRunConfigurationWidget::slotLauncherStateChanged(int s)
{
- QString message;
- setDeviceInfoLabel(tr("Connecting..."));
- const bool ok = getDeviceInfo(&message);
- setDeviceInfoLabel(message, !ok);
+ switch (s) {
+ case trk::Launcher::WaitingForTrk: {
+ // Entered trk wait state..open message box
+ QMessageBox *mb = S60DeviceRunControlBase::createTrkWaitingMessageBox(m_infoLauncher->trkServerName(), this);
+ connect(m_infoLauncher, SIGNAL(stateChanged(int)), mb, SLOT(close()));
+ connect(mb, SIGNAL(finished(int)), this, SLOT(slotWaitingForTrkClosed()));
+ mb->open();
+ }
+ break;
+ case trk::Launcher::DeviceDescriptionReceived: // All ok, done
+ setDeviceInfoLabel(m_infoLauncher->deviceDescription());
+ m_deviceInfoButton->setEnabled(true);
+ m_infoLauncher->deleteLater();
+ break;
+ }
}
-bool S60DeviceRunConfigurationWidget::getDeviceInfo(QString *message)
+void S60DeviceRunConfigurationWidget::slotWaitingForTrkClosed()
{
- message->clear();
- // Do a launcher run with the ping protocol. Instantiate launcher on heap
- // as not to introduce delays when destructing a device with timeout
- trk::Launcher *launcher = new trk::Launcher(trk::Launcher::ActionPingOnly, QSharedPointer<trk::TrkDevice>(), this);
+ if (m_infoLauncher && m_infoLauncher->state() == trk::Launcher::WaitingForTrk) {
+ m_infoLauncher->deleteLater();
+ clearDeviceInfo();
+ m_deviceInfoButton->setEnabled(true);
+ }
+}
+
+void S60DeviceRunConfigurationWidget::updateDeviceInfo()
+{
+ QTC_ASSERT(!m_infoLauncher, return)
+ setDeviceInfoLabel(tr("Connecting..."));
+ // Do a launcher run with the ping protocol. Prompt to connect and
+ // go asynchronous afterwards to pop up launch trk box if a timeout occurs.
+ m_infoLauncher = new trk::Launcher(trk::Launcher::ActionPingOnly, QSharedPointer<trk::TrkDevice>(), this);
+ connect(m_infoLauncher, SIGNAL(stateChanged(int)), this, SLOT(slotLauncherStateChanged(int)));
const CommunicationDevice commDev = currentDevice();
- launcher->setSerialFrame(commDev.type == SerialPortCommunication);
- launcher->setTrkServerName(commDev.portName);
+ m_infoLauncher->setSerialFrame(commDev.type == SerialPortCommunication);
+ m_infoLauncher->setTrkServerName(commDev.portName);
// Prompt user
+ QString message;
const trk::PromptStartCommunicationResult src =
- S60RunConfigBluetoothStarter::startCommunication(launcher->trkDevice(),
+ S60RunConfigBluetoothStarter::startCommunication(m_infoLauncher->trkDevice(),
commDev.portName,
commDev.type, this,
- message);
+ &message);
switch (src) {
case trk::PromptStartCommunicationConnected:
break;
case trk::PromptStartCommunicationCanceled:
- launcher->deleteLater();
- return true;
+ clearDeviceInfo();
+ m_infoLauncher->deleteLater();
+ return;
case trk::PromptStartCommunicationError:
- launcher->deleteLater();
- return false;
+ setDeviceInfoLabel(message, true);
+ m_infoLauncher->deleteLater();
+ return;
};
- if (!launcher->startServer(message)) {
- launcher->deleteLater();
- return false;
- }
- // Set up event loop in the foreground with a timer to quit in case of timeout.
- QEventLoop eventLoop;
- if (!m_infoTimeOutTimer) {
- m_infoTimeOutTimer = new QTimer(this);
- m_infoTimeOutTimer->setInterval(3000);
- m_infoTimeOutTimer->setSingleShot(true);
- }
- connect(m_infoTimeOutTimer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
- connect(launcher, SIGNAL(finished()), &eventLoop, SLOT(quit()));
- // Go!
- QApplication::setOverrideCursor(Qt::BusyCursor);
- m_infoTimeOutTimer->start();
- eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
- m_infoTimeOutTimer->disconnect();
- QApplication::restoreOverrideCursor();
- // Anything received?
- *message = launcher->deviceDescription();
- launcher->deleteLater();
- if (message->isEmpty()) {
- *message = tr("A timeout occurred while querying the device. Check whether Trk is running");
- return false;
+ if (!m_infoLauncher->startServer(&message)) {
+ setDeviceInfoLabel(message, true);
+ m_infoLauncher->deleteLater();
+ return;
}
- return true;
+ // Wait for either timeout or results
+ m_deviceInfoButton->setEnabled(false);
+ return;
}
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h
index 1863f5d5e5..18f736da73 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h
@@ -31,6 +31,7 @@
#define S60DEVICERUNCONFIGURATIONWIDGET_H
#include <QtGui/QWidget>
+#include <QtCore/QPointer>
QT_BEGIN_NAMESPACE
class QLabel;
@@ -44,6 +45,10 @@ namespace Utils {
class DetailsWidget;
}
+namespace trk {
+ class Launcher;
+}
+
namespace Qt4ProjectManager {
namespace Internal {
@@ -72,12 +77,13 @@ private slots:
void updateSummary();
void updateDeviceInfo();
void clearDeviceInfo();
+ void slotLauncherStateChanged(int);
+ void slotWaitingForTrkClosed();
private:
inline CommunicationDevice device(int i) const;
inline CommunicationDevice currentDevice() const;
- bool getDeviceInfo(QString *message);
void setDeviceInfoLabel(const QString &message, bool isError = false);
S60DeviceRunConfiguration *m_runConfiguration;
@@ -89,6 +95,7 @@ private:
QLabel *m_deviceInfoDescriptionLabel;
QLabel *m_deviceInfoLabel;
QTimer *m_infoTimeOutTimer;
+ QPointer<trk::Launcher> m_infoLauncher;
};
} // namespace Internal
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp
index 0c9084c88d..c2fe7ac617 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp
+++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.cpp
@@ -29,8 +29,8 @@
#include "s60manager.h"
-#include "s60devices.h"
#include "s60devicespreferencepane.h"
+#include "serialdevicelister.h"
#include "winscwtoolchain.h"
#include "gccetoolchain.h"
#include "rvcttoolchain.h"
@@ -40,6 +40,7 @@
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
+#include <projectexplorer/toolchain.h>
#include <debugger/debuggermanager.h>
#include <utils/qtcassert.h>
diff --git a/src/plugins/qt4projectmanager/qt-s60/s60manager.h b/src/plugins/qt4projectmanager/qt-s60/s60manager.h
index fe4078583d..77e93be3a9 100644
--- a/src/plugins/qt4projectmanager/qt-s60/s60manager.h
+++ b/src/plugins/qt4projectmanager/qt-s60/s60manager.h
@@ -31,17 +31,19 @@
#define S60MANAGER_H
#include "qtversionmanager.h"
-#include "serialdevicelister.h"
#include "s60devices.h"
-#include <extensionsystem/iplugin.h>
-#include <projectexplorer/toolchain.h>
-
#include <QtCore/QObject>
+namespace ProjectExplorer {
+class ToolChain;
+}
+
namespace Qt4ProjectManager {
namespace Internal {
+class SerialDeviceLister;
+
class S60Manager : public QObject
{
Q_OBJECT
diff --git a/src/shared/trk/launcher.cpp b/src/shared/trk/launcher.cpp
index f066ab4864..a554269f0e 100644
--- a/src/shared/trk/launcher.cpp
+++ b/src/shared/trk/launcher.cpp
@@ -56,6 +56,7 @@ struct LauncherPrivate {
TrkDevicePtr m_device;
QString m_trkServerName;
QByteArray m_trkReadBuffer;
+ Launcher::State m_state;
void logMessage(const QString &msg);
// Debuggee state
@@ -66,14 +67,13 @@ struct LauncherPrivate {
QString m_installFileName;
int m_verbose;
Launcher::Actions m_startupActions;
- bool m_connected;
bool m_closeDevice;
};
LauncherPrivate::LauncherPrivate(const TrkDevicePtr &d) :
m_device(d),
+ m_state(Launcher::Disconnected),
m_verbose(0),
- m_connected(false),
m_closeDevice(true)
{
if (m_device.isNull())
@@ -97,6 +97,19 @@ Launcher::~Launcher()
delete d;
}
+Launcher::State Launcher::state() const
+{
+ return d->m_state;
+}
+
+void Launcher::setState(State s)
+{
+ if (s != d->m_state) {
+ d->m_state = s;
+ emit stateChanged(s);
+ }
+}
+
void Launcher::addStartupActions(trk::Launcher::Actions startupActions)
{
d->m_startupActions = Actions(d->m_startupActions | startupActions);
@@ -186,7 +199,9 @@ bool Launcher::startServer(QString *errorMessage)
} else {
disconnect(this, SIGNAL(finished()), d->m_device.data(), 0);
}
-
+ setState(Connecting);
+ // Set up the temporary 'waiting' state if we do not get immediate connection
+ QTimer::singleShot(200, this, SLOT(slotWaitingForTrk()));
d->m_device->sendTrkInitialPing();
d->m_device->sendTrkMessage(TrkDisconnect); // Disconnect, as trk might be still connected
d->m_device->sendTrkMessage(TrkSupported, TrkCallback(this, &Launcher::handleSupportMask));
@@ -197,13 +212,20 @@ bool Launcher::startServer(QString *errorMessage)
return true;
}
+void Launcher::slotWaitingForTrk()
+{
+ // Set temporary state if we are still in connected state
+ if (state() == Connecting)
+ setState(WaitingForTrk);
+}
+
void Launcher::handleConnect(const TrkResult &result)
{
if (result.errorCode()) {
emit canNotConnect(result.errorString());
return;
}
- d->m_connected = true;
+ setState(Connected);
if (d->m_startupActions & ActionCopy)
copyFileToRemote();
else if (d->m_startupActions & ActionInstall)
@@ -226,17 +248,27 @@ void Launcher::logMessage(const QString &msg)
void Launcher::terminate()
{
- if (d->m_session.pid) {
- QByteArray ba;
- appendShort(&ba, 0x0000, TargetByteOrder);
- appendInt(&ba, d->m_session.pid, TargetByteOrder);
- d->m_device->sendTrkMessage(TrkDeleteItem, TrkCallback(this, &Launcher::handleRemoteProcessKilled), ba);
- } else if (d->m_connected) {
+ switch (state()) {
+ case DeviceDescriptionReceived:
+ case Connected:
+ if (d->m_session.pid) {
+ QByteArray ba;
+ appendShort(&ba, 0x0000, TargetByteOrder);
+ appendInt(&ba, d->m_session.pid, TargetByteOrder);
+ d->m_device->sendTrkMessage(TrkDeleteItem, TrkCallback(this, &Launcher::handleRemoteProcessKilled), ba);
+ return;
+ }
if (d->m_copyState.copyFileHandle)
closeRemoteFile(true);
disconnectTrk();
- } else {
+ break;
+ case Disconnected:
+ break;
+ case Connecting:
+ case WaitingForTrk:
+ setState(Disconnected);
emit finished();
+ break;
}
}
@@ -364,17 +396,21 @@ QString Launcher::deviceDescription(unsigned verbose) const
void Launcher::handleTrkVersion(const TrkResult &result)
{
if (result.errorCode() || result.data.size() < 5) {
- if (d->m_startupActions == ActionPingOnly)
+ if (d->m_startupActions == ActionPingOnly) {
+ setState(Disconnected);
emit finished();
+ }
return;
}
d->m_session.trkAppVersion.trkMajor = result.data.at(1);
d->m_session.trkAppVersion.trkMinor = result.data.at(2);
d->m_session.trkAppVersion.protocolMajor = result.data.at(3);
d->m_session.trkAppVersion.protocolMinor = result.data.at(4);
+ setState(DeviceDescriptionReceived);
// Ping mode: Log & Terminate
if (d->m_startupActions == ActionPingOnly) {
qWarning("%s", qPrintable(deviceDescription()));
+ setState(Disconnected);
emit finished();
}
}
@@ -501,6 +537,7 @@ void Launcher::handleCreateProcess(const TrkResult &result)
void Launcher::handleWaitForFinished(const TrkResult &result)
{
logMessage(" FINISHED: " + stringFromArray(result.data));
+ setState(Disconnected);
emit finished();
}
diff --git a/src/shared/trk/launcher.h b/src/shared/trk/launcher.h
index 2c4881de6d..538d367e74 100644
--- a/src/shared/trk/launcher.h
+++ b/src/shared/trk/launcher.h
@@ -61,10 +61,21 @@ public:
ActionCopyInstallRun = ActionCopy | ActionInstall | ActionRun
};
+ enum State { Disconnected, Connecting, Connected,
+ WaitingForTrk, // This occurs only if the initial ping times out after
+ // a reasonable timeout, indicating that Trk is not
+ // running. Note that this will never happen with
+ // Bluetooth as communication immediately starts
+ // after connecting.
+ DeviceDescriptionReceived };
+
explicit Launcher(trk::Launcher::Actions startupActions = trk::Launcher::ActionPingOnly,
const TrkDevicePtr &trkDevice = TrkDevicePtr(),
QObject *parent = 0);
~Launcher();
+
+ State state() const;
+
void addStartupActions(trk::Launcher::Actions startupActions);
void setTrkServerName(const QString &name);
QString trkServerName() const;
@@ -98,12 +109,14 @@ signals:
void finished();
void applicationOutputReceived(const QString &output);
void copyProgress(int percent);
+ void stateChanged(int);
public slots:
void terminate();
private slots:
void handleResult(const trk::TrkResult &data);
+ void slotWaitingForTrk();
private:
// kill process and breakpoints
@@ -130,6 +143,7 @@ private:
void startInferiorIfNeeded();
void logMessage(const QString &msg);
+ void setState(State s);
LauncherPrivate *d;
};