S60: Provide a MessageBox for starting serial communication as well.

Generalize the concept of the Bluetooth starter, extract base class
BaseCommunicationStarter that can be used to start a serial communication
without further resources (listener) as well. Introduce convenience
functions for both types.

Note: This will only work for COM-ports that are not used otherwise
by the operating system.
This commit is contained in:
Friedemann Kleint
2009-10-26 15:37:09 +01:00
parent c6e9c041a7
commit 4091efb47f
13 changed files with 291 additions and 145 deletions

View File

@@ -30,6 +30,7 @@
#include "s60debuggerbluetoothstarter.h" #include "s60debuggerbluetoothstarter.h"
#include "bluetoothlistener.h" #include "bluetoothlistener.h"
#include "debuggermanager.h" #include "debuggermanager.h"
#include "trkoptions.h"
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -48,5 +49,24 @@ trk::BluetoothListener *S60DebuggerBluetoothStarter::createListener()
return rc; return rc;
} }
trk::PromptStartCommunicationResult
S60DebuggerBluetoothStarter::startCommunication(const TrkDevicePtr &trkDevice,
const QString &device,
int communicationType,
QWidget *msgBoxParent,
QString *errorMessage)
{
// Bluetooth?
if (communicationType == TrkOptions::BlueTooth) {
S60DebuggerBluetoothStarter bluetoothStarter(trkDevice);
bluetoothStarter.setDevice(device);
return trk::promptStartBluetooth(bluetoothStarter, msgBoxParent, errorMessage);
}
// Serial
BaseCommunicationStarter serialStarter(trkDevice);
serialStarter.setDevice(device);
return trk::promptStartSerial(serialStarter, msgBoxParent, errorMessage);
}
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -31,6 +31,7 @@
#define S60DEBUGGERBLUETOOTHSTARTER_H #define S60DEBUGGERBLUETOOTHSTARTER_H
#include "communicationstarter.h" #include "communicationstarter.h"
#include "bluetoothlistener_gui.h"
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
@@ -38,15 +39,24 @@ namespace Internal {
/* S60DebuggerBluetoothStarter: Creates a listener in 'Listen' mode /* S60DebuggerBluetoothStarter: Creates a listener in 'Listen' mode
* parented on the Debugger manager which outputs to the debugger window. * parented on the Debugger manager which outputs to the debugger window.
* Note: This is a "last resort" starter, normally, the run configuration * Note: This is a "last resort" starter, normally, the run configuration
* should have already started a listener. */ * should have already started a listener.
* Provides a static convenience to prompt for both connection types. */
class S60DebuggerBluetoothStarter : public trk::AbstractBluetoothStarter class S60DebuggerBluetoothStarter : public trk::AbstractBluetoothStarter
{ {
public: public:
explicit S60DebuggerBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0); static trk::PromptStartCommunicationResult
startCommunication(const TrkDevicePtr &trkDevice,
const QString &device,
int communicationType,
QWidget *msgBoxParent,
QString *errorMessage);
protected: protected:
virtual trk::BluetoothListener *createListener(); virtual trk::BluetoothListener *createListener();
private:
explicit S60DebuggerBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
}; };
} // namespace Internal } // namespace Internal

View File

@@ -1512,30 +1512,22 @@ void TrkGdbAdapter::startAdapter()
debugMessage(_("TRYING TO START ADAPTER")); debugMessage(_("TRYING TO START ADAPTER"));
logMessage(QLatin1String("### Starting TrkGdbAdapter")); logMessage(QLatin1String("### Starting TrkGdbAdapter"));
m_trkDevice->setSerialFrame(effectiveTrkDeviceType() != TrkOptions::BlueTooth); m_trkDevice->setSerialFrame(effectiveTrkDeviceType() != TrkOptions::BlueTooth);
// Prompt the user for a bluetooth connection // Prompt the user to start communication
const QString device = effectiveTrkDevice(); QString message;
QString message; const trk::PromptStartCommunicationResult src =
if (effectiveTrkDeviceType() == TrkOptions::BlueTooth) { S60DebuggerBluetoothStarter::startCommunication(m_trkDevice,
S60DebuggerBluetoothStarter starter(m_trkDevice); effectiveTrkDevice(),
starter.setDevice(device); effectiveTrkDeviceType(),
const trk::StartBluetoothGuiResult src = trk::startBluetoothGui(starter, 0, &message); 0, &message);
switch (src) { switch (src) {
case trk::BluetoothGuiConnected: case trk::PromptStartCommunicationConnected:
break; break;
case trk::BluetoothGuiCanceled: case trk::PromptStartCommunicationCanceled:
emit adapterStartFailed(message, QString()); emit adapterStartFailed(message, QString());
return; return;
case trk::BluetoothGuiError: case trk::PromptStartCommunicationError:
emit adapterStartFailed(message, TrkOptionsPage::settingsId()); emit adapterStartFailed(message, TrkOptionsPage::settingsId());
return; return;
};
} else {
if (!m_trkDevice->isOpen() && !m_trkDevice->open(device, &message)) {
message = tr("Failed to connect to %1: %2\nCheck whether TRK is running.").arg(device).arg(message);
logMessage(message);
emit adapterStartFailed(message, TrkOptionsPage::settingsId());
return;
}
} }
QTC_ASSERT(m_gdbServer == 0, delete m_gdbServer); QTC_ASSERT(m_gdbServer == 0, delete m_gdbServer);

View File

@@ -46,6 +46,7 @@ namespace Internal {
struct TrkOptions struct TrkOptions
{ {
// Matches the communication enumeration from the S60 devices listener.
enum Mode { Serial, BlueTooth }; enum Mode { Serial, BlueTooth };
TrkOptions(); TrkOptions();

View File

@@ -582,21 +582,24 @@ void S60DeviceRunControlBase::signsisProcessFinished()
initLauncher(runFileName, m_launcher); initLauncher(runFileName, m_launcher);
emit addToOutputWindow(this, tr("Package: %1\nDeploying application to '%2'...").arg(lsFile(copySrc), m_serialPortFriendlyName)); emit addToOutputWindow(this, tr("Package: %1\nDeploying application to '%2'...").arg(lsFile(copySrc), m_serialPortFriendlyName));
QString errorMessage; QString errorMessage;
// Prompt the user to start up the Blue tooth connection // Prompt the user to start up the Blue tooth connection
if (m_communicationType == BlueToothCommunication) { const trk::PromptStartCommunicationResult src =
S60RunConfigBluetoothStarter starter(m_launcher->trkDevice()); S60RunConfigBluetoothStarter::startCommunication(m_launcher->trkDevice(),
switch (trk::startBluetoothGui(starter, 0, &errorMessage)) { m_serialPortName,
case trk::BluetoothGuiConnected: m_communicationType, 0,
break; &errorMessage);
case trk::BluetoothGuiCanceled: switch (src) {
case trk::BluetoothGuiError: case trk::PromptStartCommunicationConnected:
delete m_launcher; break;
m_launcher = 0; case trk::PromptStartCommunicationCanceled:
error(this, errorMessage); case trk::PromptStartCommunicationError:
emit finished(); delete m_launcher;
return; m_launcher = 0;
}; error(this, errorMessage);
} emit finished();
return;
};
if (!m_launcher->startServer(&errorMessage)) { if (!m_launcher->startServer(&errorMessage)) {
delete m_launcher; delete m_launcher;
m_launcher = 0; m_launcher = 0;

View File

@@ -302,22 +302,22 @@ bool S60DeviceRunConfigurationWidget::getDeviceInfo(QString *message)
const CommunicationDevice commDev = currentDevice(); const CommunicationDevice commDev = currentDevice();
launcher->setSerialFrame(commDev.type == SerialPortCommunication); launcher->setSerialFrame(commDev.type == SerialPortCommunication);
launcher->setTrkServerName(commDev.portName); launcher->setTrkServerName(commDev.portName);
// Prompt the user to start // Prompt user
if (commDev.type == BlueToothCommunication) { const trk::PromptStartCommunicationResult src =
S60RunConfigBluetoothStarter starter(launcher->trkDevice()); S60RunConfigBluetoothStarter::startCommunication(launcher->trkDevice(),
starter.setDevice(launcher->trkServerName()); commDev.portName,
const trk::StartBluetoothGuiResult src = trk::startBluetoothGui(starter, this, message); commDev.type, this,
switch (src) { message);
case trk::BluetoothGuiConnected: switch (src) {
break; case trk::PromptStartCommunicationConnected:
case trk::BluetoothGuiCanceled: break;
launcher->deleteLater(); case trk::PromptStartCommunicationCanceled:
return true; launcher->deleteLater();
case trk::BluetoothGuiError: return true;
launcher->deleteLater(); case trk::PromptStartCommunicationError:
return false; launcher->deleteLater();
}; return false;
} };
if (!launcher->startServer(message)) { if (!launcher->startServer(message)) {
launcher->deleteLater(); launcher->deleteLater();
return false; return false;

View File

@@ -29,6 +29,7 @@
#include "s60runconfigbluetoothstarter.h" #include "s60runconfigbluetoothstarter.h"
#include "bluetoothlistener.h" #include "bluetoothlistener.h"
#include "serialdevicelister.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
@@ -49,5 +50,25 @@ trk::BluetoothListener *S60RunConfigBluetoothStarter::createListener()
connect(rc, SIGNAL(message(QString)), core->messageManager(), SLOT(printToOutputPane(QString))); connect(rc, SIGNAL(message(QString)), core->messageManager(), SLOT(printToOutputPane(QString)));
return rc; return rc;
} }
trk::PromptStartCommunicationResult
S60RunConfigBluetoothStarter::startCommunication(const TrkDevicePtr &trkDevice,
const QString &device,
int communicationType,
QWidget *msgBoxParent,
QString *errorMessage)
{
// Bluetooth?
if (communicationType == BlueToothCommunication) {
S60RunConfigBluetoothStarter bluetoothStarter(trkDevice);
bluetoothStarter.setDevice(device);
return trk::promptStartBluetooth(bluetoothStarter, msgBoxParent, errorMessage);
}
// Serial
BaseCommunicationStarter serialStarter(trkDevice);
serialStarter.setDevice(device);
return trk::promptStartSerial(serialStarter, msgBoxParent, errorMessage);
}
} // namespace Internal } // namespace Internal
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager

View File

@@ -31,20 +31,34 @@
#define S60RUNCONFIGBLUETOOTHSTARTER_H #define S60RUNCONFIGBLUETOOTHSTARTER_H
#include "communicationstarter.h" #include "communicationstarter.h"
#include "bluetoothlistener_gui.h"
namespace Qt4ProjectManager { namespace Qt4ProjectManager {
namespace Internal { namespace Internal {
/* S60RunConfigBluetoothStarter: Creates a listener in 'Listen' mode /* S60RunConfigBluetoothStarter: Creates a listener in 'Listen' mode
* parented on the Qt Creator core which outputs to the message manager. */ * parented on the Qt Creator core which outputs to the message manager.
* Provides a static convenience to prompt for both connection types. */
class S60RunConfigBluetoothStarter : public trk::AbstractBluetoothStarter class S60RunConfigBluetoothStarter : public trk::AbstractBluetoothStarter
{ {
public: public:
explicit S60RunConfigBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0); typedef trk::AbstractBluetoothStarter::TrkDevicePtr TrkDevicePtr;
// Convenience function to start communication depending on type,
// passing on the right messages.
static trk::PromptStartCommunicationResult
startCommunication(const TrkDevicePtr &trkDevice,
const QString &device,
int communicationType,
QWidget *msgBoxParent,
QString *errorMessage);
protected: protected:
virtual trk::BluetoothListener *createListener(); virtual trk::BluetoothListener *createListener();
private:
explicit S60RunConfigBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
}; };
} // namespace Internal } // namespace Internal

View File

@@ -38,38 +38,62 @@
namespace trk { namespace trk {
StartBluetoothGuiResult PromptStartCommunicationResult
startBluetoothGui(AbstractBluetoothStarter &starter, promptStartCommunication(BaseCommunicationStarter &starter,
QWidget *msgBoxParent, const QString &msgBoxTitle,
QString *errorMessage) const QString &msgBoxText,
QWidget *msgBoxParent,
QString *errorMessage)
{ {
errorMessage->clear(); errorMessage->clear();
// Initial connection attempt.
switch (starter.start()) { switch (starter.start()) {
case AbstractBluetoothStarter::Started: case BaseCommunicationStarter::Started:
break; break;
case AbstractBluetoothStarter::ConnectionSucceeded: case BaseCommunicationStarter::ConnectionSucceeded:
return BluetoothGuiConnected; return PromptStartCommunicationConnected;
case AbstractBluetoothStarter::StartError: case BaseCommunicationStarter::StartError:
*errorMessage = starter.errorString(); *errorMessage = starter.errorString();
return BluetoothGuiError; return PromptStartCommunicationError;
} }
// Run the starter with the event loop of a message box, close it // Run the starter with the event loop of a message box, have the box
// with the finished signals. // closed by the signals of the starter.
const QString title = QCoreApplication::translate("trk::startBluetoothGui", "Waiting for Bluetooth Connection"); QMessageBox messageBox(QMessageBox::Information, msgBoxTitle, msgBoxText, QMessageBox::Cancel, msgBoxParent);
const QString message = QCoreApplication::translate("trk::startBluetoothGui", "Connecting to %1...").arg(starter.device());
QMessageBox messageBox(QMessageBox::Information, title, message, QMessageBox::Cancel, msgBoxParent);
QObject::connect(&starter, SIGNAL(connected()), &messageBox, SLOT(close())); QObject::connect(&starter, SIGNAL(connected()), &messageBox, SLOT(close()));
QObject::connect(&starter, SIGNAL(timeout()), &messageBox, SLOT(close())); QObject::connect(&starter, SIGNAL(timeout()), &messageBox, SLOT(close()));
messageBox.exec(); messageBox.exec();
// Only starter.state() is reliable here. // Only starter.state() is reliable here to obtain the state.
if (starter.state() == AbstractBluetoothStarter::Running) { switch (starter.state()) {
*errorMessage = QCoreApplication::translate("trk::startBluetoothGui", "Connection on %1 canceled.").arg(starter.device()); case AbstractBluetoothStarter::Running:
return BluetoothGuiCanceled; *errorMessage = QCoreApplication::translate("trk::promptStartCommunication", "Connection on %1 canceled.").arg(starter.device());
} return PromptStartCommunicationCanceled;
if (starter.state() != AbstractBluetoothStarter::Connected) { case AbstractBluetoothStarter::TimedOut:
*errorMessage = starter.errorString(); *errorMessage = starter.errorString();
return BluetoothGuiError; return PromptStartCommunicationError;
case AbstractBluetoothStarter::Connected:
break;
} }
return BluetoothGuiConnected; return PromptStartCommunicationConnected;
} }
PromptStartCommunicationResult
promptStartSerial(BaseCommunicationStarter &starter,
QWidget *msgBoxParent,
QString *errorMessage)
{
const QString title = QCoreApplication::translate("trk::promptStartCommunication", "Waiting for TRK");
const QString message = QCoreApplication::translate("trk::promptStartCommunication", "Waiting for TRK to start on %1...").arg(starter.device());
return promptStartCommunication(starter, title, message, msgBoxParent, errorMessage);
}
PromptStartCommunicationResult
promptStartBluetooth(BaseCommunicationStarter &starter,
QWidget *msgBoxParent,
QString *errorMessage)
{
const QString title = QCoreApplication::translate("trk::promptStartCommunication", "Waiting for Bluetooth Connection");
const QString message = QCoreApplication::translate("trk::promptStartCommunication", "Connecting to %1...").arg(starter.device());
return promptStartCommunication(starter, title, message, msgBoxParent, errorMessage);
}
} // namespace trk } // namespace trk

View File

@@ -37,22 +37,39 @@ class QWidget;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace trk { namespace trk {
class AbstractBluetoothStarter; class BaseCommunicationStarter;
/* startBluetoothGui(): Prompt the user to start a Bluetooth /* promptStartCommunication(): Convenience functions that
* connection with a message box he can cancel. Pass in * prompt the user to start a communication (launching or
* the starter with device and parameters set up. */ * connecting TRK) using a modal message box in which they can cancel.
* Pass in the starter with device and parameters set up. */
enum StartBluetoothGuiResult { enum PromptStartCommunicationResult {
BluetoothGuiConnected, PromptStartCommunicationConnected,
BluetoothGuiCanceled, PromptStartCommunicationCanceled,
BluetoothGuiError PromptStartCommunicationError
}; };
StartBluetoothGuiResult PromptStartCommunicationResult
startBluetoothGui(AbstractBluetoothStarter &starter, promptStartCommunication(BaseCommunicationStarter &starter,
const QString &msgBoxTitle,
const QString &msgBoxText,
QWidget *msgBoxParent,
QString *errorMessage);
// Convenience to start a serial connection (messages prompting
// to launch Trk).
PromptStartCommunicationResult
promptStartSerial(BaseCommunicationStarter &starter,
QWidget *msgBoxParent, QWidget *msgBoxParent,
QString *errorMessage); QString *errorMessage);
// Convenience to start blue tooth connection (messages
// prompting to connect).
PromptStartCommunicationResult
promptStartBluetooth(BaseCommunicationStarter &starter,
QWidget *msgBoxParent,
QString *errorMessage);
} // namespace trk } // namespace trk
#endif // BLUETOOTHLISTENER_GUI_H #endif // BLUETOOTHLISTENER_GUI_H

View File

@@ -35,11 +35,12 @@
#include <QtCore/QEventLoop> #include <QtCore/QEventLoop>
namespace trk { namespace trk {
// --------------- AbstractBluetoothStarter
struct AbstractBluetoothStarterPrivate {
explicit AbstractBluetoothStarterPrivate(const AbstractBluetoothStarter::TrkDevicePtr &d);
const AbstractBluetoothStarter::TrkDevicePtr trkDevice; // --------------- AbstractBluetoothStarter
struct BaseCommunicationStarterPrivate {
explicit BaseCommunicationStarterPrivate(const BaseCommunicationStarter::TrkDevicePtr &d);
const BaseCommunicationStarter::TrkDevicePtr trkDevice;
BluetoothListener *listener; BluetoothListener *listener;
QTimer *timer; QTimer *timer;
int intervalMS; int intervalMS;
@@ -47,11 +48,10 @@ struct AbstractBluetoothStarterPrivate {
int n; int n;
QString device; QString device;
QString errorString; QString errorString;
AbstractBluetoothStarter::State state; BaseCommunicationStarter::State state;
}; };
AbstractBluetoothStarterPrivate::AbstractBluetoothStarterPrivate(const AbstractBluetoothStarter::TrkDevicePtr &d) : BaseCommunicationStarterPrivate::BaseCommunicationStarterPrivate(const BaseCommunicationStarter::TrkDevicePtr &d) :
trkDevice(d), trkDevice(d),
listener(0), listener(0),
timer(0), timer(0),
@@ -59,32 +59,38 @@ AbstractBluetoothStarterPrivate::AbstractBluetoothStarterPrivate(const AbstractB
attempts(-1), attempts(-1),
n(0), n(0),
device(QLatin1String("/dev/rfcomm0")), device(QLatin1String("/dev/rfcomm0")),
state(AbstractBluetoothStarter::TimedOut) state(BaseCommunicationStarter::TimedOut)
{ {
} }
AbstractBluetoothStarter::AbstractBluetoothStarter(const TrkDevicePtr &trkDevice, QObject *parent) : BaseCommunicationStarter::BaseCommunicationStarter(const TrkDevicePtr &trkDevice, QObject *parent) :
QObject(parent), QObject(parent),
d(new AbstractBluetoothStarterPrivate(trkDevice)) d(new BaseCommunicationStarterPrivate(trkDevice))
{ {
} }
AbstractBluetoothStarter::~AbstractBluetoothStarter() BaseCommunicationStarter::~BaseCommunicationStarter()
{ {
stopTimer(); stopTimer();
delete d; delete d;
} }
void AbstractBluetoothStarter::stopTimer() void BaseCommunicationStarter::stopTimer()
{ {
if (d->timer && d->timer->isActive()) if (d->timer && d->timer->isActive())
d->timer->stop(); d->timer->stop();
} }
AbstractBluetoothStarter::StartResult AbstractBluetoothStarter::start() bool BaseCommunicationStarter::initializeStartupResources(QString *errorMessage)
{
errorMessage->clear();
return true;
}
BaseCommunicationStarter::StartResult BaseCommunicationStarter::start()
{ {
if (state() == Running) { if (state() == Running) {
d->errorString = QLatin1String("Internal error, attempt to re-start AbstractBluetoothStarter.\n"); d->errorString = QLatin1String("Internal error, attempt to re-start BaseCommunicationStarter.\n");
return StartError; return StartError;
} }
// Before we instantiate timers, and such, try to open the device, // Before we instantiate timers, and such, try to open the device,
@@ -92,10 +98,9 @@ AbstractBluetoothStarter::StartResult AbstractBluetoothStarter::start()
// 'Watch' mode // 'Watch' mode
if (d->trkDevice->open(d->device , &(d->errorString))) if (d->trkDevice->open(d->device , &(d->errorString)))
return ConnectionSucceeded; return ConnectionSucceeded;
// Fire up the listener // Pull up resources for next attempt
d->n = 0; d->n = 0;
d->listener = createListener(); if (!initializeStartupResources(&(d->errorString)))
if (!d->listener->start(d->device, &(d->errorString)))
return StartError; return StartError;
// Start timer // Start timer
if (!d->timer) { if (!d->timer) {
@@ -109,49 +114,49 @@ AbstractBluetoothStarter::StartResult AbstractBluetoothStarter::start()
return Started; return Started;
} }
AbstractBluetoothStarter::State AbstractBluetoothStarter::state() const BaseCommunicationStarter::State BaseCommunicationStarter::state() const
{ {
return d->state; return d->state;
} }
int AbstractBluetoothStarter::intervalMS() const int BaseCommunicationStarter::intervalMS() const
{ {
return d->intervalMS; return d->intervalMS;
} }
void AbstractBluetoothStarter::setIntervalMS(int i) void BaseCommunicationStarter::setIntervalMS(int i)
{ {
d->intervalMS = i; d->intervalMS = i;
if (d->timer) if (d->timer)
d->timer->setInterval(i); d->timer->setInterval(i);
} }
int AbstractBluetoothStarter::attempts() const int BaseCommunicationStarter::attempts() const
{ {
return d->attempts; return d->attempts;
} }
void AbstractBluetoothStarter::setAttempts(int a) void BaseCommunicationStarter::setAttempts(int a)
{ {
d->attempts = a; d->attempts = a;
} }
QString AbstractBluetoothStarter::device() const QString BaseCommunicationStarter::device() const
{ {
return d->device; return d->device;
} }
void AbstractBluetoothStarter::setDevice(const QString &dv) void BaseCommunicationStarter::setDevice(const QString &dv)
{ {
d->device = dv; d->device = dv;
} }
QString AbstractBluetoothStarter::errorString() const QString BaseCommunicationStarter::errorString() const
{ {
return d->errorString; return d->errorString;
} }
void AbstractBluetoothStarter::slotTimer() void BaseCommunicationStarter::slotTimer()
{ {
++d->n; ++d->n;
// Check for timeout // Check for timeout
@@ -166,17 +171,32 @@ void AbstractBluetoothStarter::slotTimer()
if (d->trkDevice->open(d->device , &(d->errorString))) { if (d->trkDevice->open(d->device , &(d->errorString))) {
stopTimer(); stopTimer();
const QString msg = tr("%1: Connection attempt %2 succeeded.").arg(d->device).arg(d->n); const QString msg = tr("%1: Connection attempt %2 succeeded.").arg(d->device).arg(d->n);
d->listener->emitMessage(msg); emit message(msg);
d->state = Connected; d->state = Connected;
emit connected(); emit connected();
} else { } else {
const QString msg = tr("%1: Connection attempt %2 failed: %3 (retrying)...") const QString msg = tr("%1: Connection attempt %2 failed: %3 (retrying)...")
.arg(d->device).arg(d->n).arg(d->errorString); .arg(d->device).arg(d->n).arg(d->errorString);
d->listener->emitMessage(msg); emit message(msg);
} }
} }
} }
// --------------- AbstractBluetoothStarter
AbstractBluetoothStarter::AbstractBluetoothStarter(const TrkDevicePtr &trkDevice, QObject *parent) :
BaseCommunicationStarter(trkDevice, parent)
{
}
bool AbstractBluetoothStarter::initializeStartupResources(QString *errorMessage)
{
// Create the listener and forward messages to it.
BluetoothListener *listener = createListener();
connect(this, SIGNAL(message(QString)), listener, SLOT(emitMessage(QString)));
return listener->start(device(), errorMessage);
}
// -------- ConsoleBluetoothStarter // -------- ConsoleBluetoothStarter
ConsoleBluetoothStarter::ConsoleBluetoothStarter(const TrkDevicePtr &trkDevice, ConsoleBluetoothStarter::ConsoleBluetoothStarter(const TrkDevicePtr &trkDevice,
QObject *listenerParent, QObject *listenerParent,

View File

@@ -36,25 +36,28 @@
namespace trk { namespace trk {
class TrkDevice; class TrkDevice;
class BluetoothListener; class BluetoothListener;
struct AbstractBluetoothStarterPrivate; struct BaseCommunicationStarterPrivate;
/* AbstractBluetoothStarter: Repeatedly tries to open a trk device /* BaseCommunicationStarter: A QObject that repeatedly tries to open a
* until a connection succeeds, allowing to do something else in the * trk device until a connection succeeds or a timeout occurs (emitting
* foreground (local event loop or asynchronous operation). * signals), allowing to do something else in the foreground (local event loop
* Note that in case a Listener is already running in watch mode, it might * [say QMessageBox] or some asynchronous operation). If the initial
* also happen that connection succeeds immediately. * connection attempt in start() fails, the
* Implementations must provide a factory function that creates and sets up the * virtual initializeStartupResources() is called to initialize resources
* listener (mode, message connection, etc). */ * required to pull up the communication (namely Bluetooth listeners).
* The base class can be used as is to prompt the user to launch TRK for a serial
* communication as this requires no further resource setup. */
class AbstractBluetoothStarter : public QObject { class BaseCommunicationStarter : public QObject {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY(AbstractBluetoothStarter) Q_DISABLE_COPY(BaseCommunicationStarter)
public: public:
typedef QSharedPointer<TrkDevice> TrkDevicePtr; typedef QSharedPointer<TrkDevice> TrkDevicePtr;
enum State { Running, Connected, TimedOut }; enum State { Running, Connected, TimedOut };
virtual ~AbstractBluetoothStarter(); explicit BaseCommunicationStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
virtual ~BaseCommunicationStarter();
int intervalMS() const; int intervalMS() const;
void setIntervalMS(int i); void setIntervalMS(int i);
@@ -80,19 +83,40 @@ public:
signals: signals:
void connected(); void connected();
void timeout(); void timeout();
void message(const QString &);
private slots: private slots:
void slotTimer(); void slotTimer();
protected: protected:
explicit AbstractBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0); virtual bool initializeStartupResources(QString *errorMessage);
// Overwrite to create and parametrize the listener.
virtual BluetoothListener *createListener() = 0;
private: private:
inline void stopTimer(); inline void stopTimer();
AbstractBluetoothStarterPrivate *d; BaseCommunicationStarterPrivate *d;
};
/* AbstractBluetoothStarter: Repeatedly tries to open a trk Bluetooth
* device. Note that in case a Listener is already running mode, the
* connection will succeed immediately.
* initializeStartupResources() is implemented to fire up the listener.
* Introduces a new virtual createListener() that derived classes must
* implement as a factory function that creates and sets up the
* listener (mode, message connection, etc). */
class AbstractBluetoothStarter : public BaseCommunicationStarter {
Q_OBJECT
Q_DISABLE_COPY(AbstractBluetoothStarter)
public:
protected:
explicit AbstractBluetoothStarter(const TrkDevicePtr& trkDevice, QObject *parent = 0);
// Implemented to fire up the listener.
virtual bool initializeStartupResources(QString *errorMessage);
// New virtual: Overwrite to create and parametrize the listener.
virtual BluetoothListener *createListener() = 0;
}; };
/* ConsoleBluetoothStarter: Convenience class for console processes. Creates a /* ConsoleBluetoothStarter: Convenience class for console processes. Creates a
@@ -102,12 +126,11 @@ class ConsoleBluetoothStarter : public AbstractBluetoothStarter {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY(ConsoleBluetoothStarter) Q_DISABLE_COPY(ConsoleBluetoothStarter)
public: public:
static bool startBluetooth(const TrkDevicePtr& trkDevice,
static bool startBluetooth(const TrkDevicePtr& trkDevice, QObject *listenerParent,
QObject *listenerParent, const QString &device,
const QString &device, int attempts,
int attempts, QString *errorMessage);
QString *errorMessage);
protected: protected:
virtual BluetoothListener *createListener(); virtual BluetoothListener *createListener();

View File

@@ -14,6 +14,7 @@ SOURCES += $$PWD/trkutils.cpp \
$$PWD/bluetoothlistener.cpp \ $$PWD/bluetoothlistener.cpp \
$$PWD/communicationstarter.cpp $$PWD/communicationstarter.cpp
# Tests/trklauncher is a console application
contains(QT, gui) { contains(QT, gui) {
HEADERS += $$PWD/bluetoothlistener_gui.h HEADERS += $$PWD/bluetoothlistener_gui.h
SOURCES += $$PWD/bluetoothlistener_gui.cpp SOURCES += $$PWD/bluetoothlistener_gui.cpp