OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / src / shared / symbianutils / communicationstarter.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "communicationstarter.h"
35 #include "bluetoothlistener.h"
36 #include "trkdevice.h"
37
38 #include <QtCore/QTimer>
39 #include <QtCore/QEventLoop>
40
41 namespace trk {
42
43 // --------------- AbstractBluetoothStarter
44 struct BaseCommunicationStarterPrivate {
45     explicit BaseCommunicationStarterPrivate(const BaseCommunicationStarter::TrkDevicePtr &d);
46
47     const BaseCommunicationStarter::TrkDevicePtr trkDevice;
48     BluetoothListener *listener;
49     QTimer *timer;
50     int intervalMS;
51     int attempts;
52     int n;
53     QString errorString;
54     BaseCommunicationStarter::State state;
55 };
56
57 BaseCommunicationStarterPrivate::BaseCommunicationStarterPrivate(const BaseCommunicationStarter::TrkDevicePtr &d) :
58         trkDevice(d),
59         listener(0),
60         timer(0),
61         intervalMS(1000),
62         attempts(-1),
63         n(0),
64         state(BaseCommunicationStarter::TimedOut)
65 {
66 }
67
68 BaseCommunicationStarter::BaseCommunicationStarter(const TrkDevicePtr &trkDevice, QObject *parent) :
69         QObject(parent),
70         d(new BaseCommunicationStarterPrivate(trkDevice))
71 {
72 }
73
74 BaseCommunicationStarter::~BaseCommunicationStarter()
75 {
76     stopTimer();
77     delete d;
78 }
79
80 void BaseCommunicationStarter::stopTimer()
81 {
82     if (d->timer && d->timer->isActive())
83         d->timer->stop();
84 }
85
86 bool BaseCommunicationStarter::initializeStartupResources(QString *errorMessage)
87 {
88     errorMessage->clear();
89     return true;
90 }
91
92 BaseCommunicationStarter::StartResult BaseCommunicationStarter::start()
93 {
94     if (state() == Running) {
95         d->errorString = QLatin1String("Internal error, attempt to re-start BaseCommunicationStarter.\n");
96         return StartError;
97     }
98     // Before we instantiate timers, and such, try to open the device,
99     // which should succeed if another listener is already running in
100     // 'Watch' mode
101     if (d->trkDevice->open(&(d->errorString)))
102         return ConnectionSucceeded;
103     // Pull up resources for next attempt
104     d->n = 0;
105     if (!initializeStartupResources(&(d->errorString)))
106         return StartError;
107     // Start timer
108     if (!d->timer) {
109         d->timer = new QTimer;
110         connect(d->timer, SIGNAL(timeout()), this, SLOT(slotTimer()));
111     }
112     d->timer->setInterval(d->intervalMS);
113     d->timer->setSingleShot(false);
114     d->timer->start();
115     d->state = Running;
116     return Started;
117 }
118
119 BaseCommunicationStarter::State BaseCommunicationStarter::state() const
120 {
121     return d->state;
122 }
123
124 int BaseCommunicationStarter::intervalMS() const
125 {
126     return d->intervalMS;
127 }
128
129 void BaseCommunicationStarter::setIntervalMS(int i)
130 {
131     d->intervalMS = i;
132     if (d->timer)
133         d->timer->setInterval(i);
134 }
135
136 int BaseCommunicationStarter::attempts() const
137 {
138     return d->attempts;
139 }
140
141 void BaseCommunicationStarter::setAttempts(int a)
142 {
143     d->attempts = a;
144 }
145
146 QString BaseCommunicationStarter::device() const
147 {
148     return d->trkDevice->port();
149 }
150
151 QString BaseCommunicationStarter::errorString() const
152 {
153     return d->errorString;
154 }
155
156 void BaseCommunicationStarter::slotTimer()
157 {
158     ++d->n;
159     // Check for timeout
160     if (d->attempts >= 0 && d->n >= d->attempts) {
161         stopTimer();
162         d->errorString = tr("%1: timed out after %n attempts using an interval of %2ms.", 0, d->n)
163                          .arg(d->trkDevice->port()).arg(d->intervalMS);
164         d->state = TimedOut;
165         emit timeout();
166     } else {
167         // Attempt n to connect?
168         if (d->trkDevice->open(&(d->errorString))) {
169             stopTimer();
170             const QString msg = tr("%1: Connection attempt %2 succeeded.").arg(d->trkDevice->port()).arg(d->n);
171             emit message(msg);
172             d->state = Connected;
173             emit connected();
174         } else {
175             const QString msg = tr("%1: Connection attempt %2 failed: %3 (retrying)...")
176                                 .arg(d->trkDevice->port()).arg(d->n).arg(d->errorString);
177             emit message(msg);
178         }
179     }
180 }
181
182 // --------------- AbstractBluetoothStarter
183
184 AbstractBluetoothStarter::AbstractBluetoothStarter(const TrkDevicePtr &trkDevice, QObject *parent) :
185     BaseCommunicationStarter(trkDevice, parent)
186 {
187 }
188
189 bool AbstractBluetoothStarter::initializeStartupResources(QString *errorMessage)
190 {
191     // Create the listener and forward messages to it.
192     BluetoothListener *listener = createListener();
193     connect(this, SIGNAL(message(QString)), listener, SLOT(emitMessage(QString)));
194     return listener->start(device(), errorMessage);
195 }
196
197 // -------- ConsoleBluetoothStarter
198 ConsoleBluetoothStarter::ConsoleBluetoothStarter(const TrkDevicePtr &trkDevice,
199                                                  QObject *listenerParent,
200                                                  QObject *parent) :
201 AbstractBluetoothStarter(trkDevice, parent),
202 m_listenerParent(listenerParent)
203 {
204 }
205
206 BluetoothListener *ConsoleBluetoothStarter::createListener()
207 {
208     BluetoothListener *rc = new BluetoothListener(m_listenerParent);
209     rc->setMode(BluetoothListener::Listen);
210     rc->setPrintConsoleMessages(true);
211     return rc;
212 }
213
214 bool ConsoleBluetoothStarter::startBluetooth(const TrkDevicePtr &trkDevice,
215                                              QObject *listenerParent,
216                                              int attempts,
217                                              QString *errorMessage)
218 {
219     // Set up a console starter to print to stdout.
220     ConsoleBluetoothStarter starter(trkDevice, listenerParent);
221     starter.setAttempts(attempts);
222     switch (starter.start()) {
223     case Started:
224         break;
225     case ConnectionSucceeded:
226         return true;
227     case StartError:
228         *errorMessage = starter.errorString();
229         return false;
230     }
231     // Run the starter with an event loop. @ToDo: Implement
232     // some asynchronous keypress read to cancel.
233     QEventLoop eventLoop;
234     connect(&starter, SIGNAL(connected()), &eventLoop, SLOT(quit()));
235     connect(&starter, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
236     eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
237     if (starter.state() != AbstractBluetoothStarter::Connected) {
238         *errorMessage = starter.errorString();
239         return false;
240     }
241     return true;
242 }
243 } // namespace trk