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>
This commit is contained in:
Friedemann Kleint
2009-10-29 12:48:12 +01:00
parent 7fc6a0ecc8
commit d749c1dc71
8 changed files with 203 additions and 69 deletions

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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;
if (!m_infoLauncher->startServer(&message)) {
setDeviceInfoLabel(message, true);
m_infoLauncher->deleteLater();
return;
}
// 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;
}
return true;
// Wait for either timeout or results
m_deviceInfoButton->setEnabled(false);
return;
}
} // namespace Internal

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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;
};