1 #include "servicewindow.h"
2 #include "ui_servicewindow.h"
4 ServiceWindow::ServiceWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::ServiceWindow)
8 manager = new QNetworkAccessManager(this);
9 connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(readResponse(QNetworkReply*)));
11 ui->scrollArea->setProperty("FingerScrollable", true);
16 * Initialises the progress dialog for the network request
18 void ServiceWindow::setupDialog()
20 dialog = new QDialog(0);
21 layout = new QHBoxLayout();
22 progress = new QProgressBar();
23 progress->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
24 cancelButton = new QPushButton("Cancel");
26 layout->addWidget(progress);
27 layout->addWidget(cancelButton);
28 dialog->setLayout(layout);
31 connect(cancelButton, SIGNAL(clicked()), dialog, SLOT(reject()));
32 connect(dialog, SIGNAL(rejected()), this, SLOT(cancel()));
36 * Loads the service window for the requested train
38 void ServiceWindow::show(QString sID)
41 //Load the departure board data.
44 //Note that QMainWindow::show() is absent here. Instead we show a progress dialog, then show the
45 //departure board only when we have loaded the data & created the display.
51 * Creates the network request, including the SOAP request XML.
53 void ServiceWindow::setupRequest()
55 QDomDocument document;
57 QDomElement env = document.createElement("soapenv:Envelope");
58 env.setAttribute("xmlns:soapenv", "http://schemas.xmlsoap.org/soap/envelope/");
59 env.setAttribute("xmlns:typ", "http://thalesgroup.com/RTTI/2007-10-10/ldb/types");
61 QDomElement header = document.createElement("soapenv:Header");
62 QDomElement body = document.createElement("soapenv:Body");
64 QDomElement typ = document.createElement("typ:GetServiceDetailsRequest");
66 QDomElement id = document.createElement("typ:serviceID");
67 id.appendChild(document.createTextNode(serviceID));
69 document.appendChild(env);
70 env.appendChild(header);
71 env.appendChild(body);
72 body.appendChild(typ);
75 requestData = document.toString(-1).prepend("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
77 request = QNetworkRequest(QUrl("http://realtime.nationalrail.co.uk/LDBWS/ldb2.asmx"));
78 request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("text/xml;charset=utf-8"));
79 request.setRawHeader("SOAPAction", "http://thalesgroup.com/RTTI/2008-02-20/ldb/GetServiceDetails");
83 * Sends the SOAP request
85 void ServiceWindow::sendRequest()
87 m_reply = manager->post(request, requestData.toUtf8().constData());
88 connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkError(QNetworkReply::NetworkError)));
89 connect(m_reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64, qint64)));
90 connect(m_reply, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(uploadProgress(qint64, qint64)));
94 * Cancel the current request
96 void ServiceWindow::cancel()
98 //Abort the request; an error signal will be emitted, so we don't need to delete the network reply here
103 * Updates the progress bar when making the request
105 void ServiceWindow::uploadProgress(qint64 rec, qint64 total)
107 dialog->setWindowTitle("Sending request");
108 progress->setRange(0, total);
109 progress->setValue(rec);
113 * Updates the progress bar when receiving the reply to the request
115 void ServiceWindow::downloadProgress(qint64 rec, qint64 total)
117 dialog->setWindowTitle("Receiving reply");
118 progress->setRange(0, total);
119 progress->setValue(rec);
123 * Slot for when there is a network error
125 void ServiceWindow::networkError(QNetworkReply::NetworkError error)
127 //If the request was cancelled, we show no error message
128 if(error == QNetworkReply::OperationCanceledError)
131 //Set the error flag to true, so that we can exit out of the readResponse method
136 //If this error is a result of the first network request, we assume there is no connection to the internet
146 msg.setText(QString("Network error: %1, %2").arg(m_reply->errorString()).arg(error));
155 * Attempt to wait for connection on either wifi or gprs
157 void ServiceWindow::ensureConnection()
159 dialog->setWindowTitle("Connecting");
161 QNetworkInterface wlan = QNetworkInterface::interfaceFromName("wlan0");
162 QNetworkInterface gprs = QNetworkInterface::interfaceFromName("gprs0");
164 //qDebug() << "wlan0" << wlan.flags().testFlag(QNetworkInterface::IsUp) << wlan.flags().testFlag(QNetworkInterface::IsRunning);
165 //qDebug() << "\tgprs0" << gprs.flags().testFlag(QNetworkInterface::IsUp) << gprs.flags().testFlag(QNetworkInterface::IsRunning);
167 if( (wlan.isValid() && wlan.flags().testFlag(QNetworkInterface::IsUp)) || (gprs.isValid() && gprs.flags().testFlag(QNetworkInterface::IsUp)) )
169 //We are connected, so try sending the network request again
175 QTimer::singleShot(100, this, SLOT(ensureConnection()));
179 #define NAMESPACE "declare namespace t=\"http://thalesgroup.com/RTTI/2007-10-10/ldb/types\";" \
180 "declare function local:if-absent( $arg as item()*, $value as item()* ) as item()* { if (exists($arg)) then $arg else $value } ;"
183 * Reads the response to the network request, and extracts the data we want.
185 void ServiceWindow::readResponse(QNetworkReply* reply)
187 QByteArray in = reply->readAll();
189 if(errorFlag == true)
191 m_reply->deleteLater();
195 received.setData(in);
196 received.open(QIODevice::ReadOnly);
199 query.bindVariable("data", &received);
201 QStringList previousNames = queryList(query, "for $x in doc($data)//t:previousCallingPoints/t:callingPointList/t:callingPoint return fn:string(local:if-absent($x/t:locationName, ''))");
202 QStringList previousST = queryList(query, "for $x in doc($data)//t:previousCallingPoints/t:callingPointList/t:callingPoint return fn:string(local:if-absent($x/t:st, ''))");
203 QStringList previousAT = queryList(query, "for $x in doc($data)//t:previousCallingPoints/t:callingPointList/t:callingPoint return fn:string(local:if-absent($x/t:at, ''))");
205 QStringList nextNames = queryList(query, "for $x in doc($data)//t:subsequentCallingPoints/t:callingPointList/t:callingPoint return fn:string(local:if-absent($x/t:locationName, ''))");
206 QStringList nextST = queryList(query, "for $x in doc($data)//t:subsequentCallingPoints/t:callingPointList/t:callingPoint return fn:string(local:if-absent($x/t:st, ''))");
207 QStringList nextET = queryList(query, "for $x in doc($data)//t:subsequentCallingPoints/t:callingPointList/t:callingPoint return fn:string(local:if-absent($x/t:at, ''))");
209 for(int i = 0; i < previousNames.size(); i++)
211 DepartureWidget * w = new DepartureWidget(previousST.at(i), previousNames.at(i), previousAT.at(i), "", "");
212 ui->scrollArea->widget()->layout()->addWidget(w);
213 w->setShowPlatform(false);
216 QString name = queryOne(query, "for $x in doc($data)//t:GetServiceDetailsResult return fn:string(local:if-absent($x/t:locationName, ''))");
217 QString platform = queryOne(query, "for $x in doc($data)//t:GetServiceDetailsResult return fn:string(local:if-absent($x/t:platform, '-'))");
218 QString std = queryOne(query, "for $x in doc($data)//t:GetServiceDetailsResult return fn:string(local:if-absent($x/t:std, '-'))");
219 QString etd = queryOne(query, "for $x in doc($data)//t:GetServiceDetailsResult return fn:string(local:if-absent($x/t:etd, '-'))");
221 DepartureWidget * w = new DepartureWidget(std, name, etd, platform, "");
222 ui->scrollArea->widget()->layout()->addWidget(w);
224 for(int i = 0; i < nextNames.size(); i++)
226 DepartureWidget * w = new DepartureWidget(nextST.at(i), nextNames.at(i), nextET.at(i), "", "");
227 ui->scrollArea->widget()->layout()->addWidget(w);
228 w->setShowPlatform(false);
232 m_reply->deleteLater();
238 QString ServiceWindow::queryOne(QXmlQuery & q, QString query)
242 q.setQuery(query.prepend(NAMESPACE));
243 q.evaluateTo(&output);
244 return (output.size() == 0) ? QString() : output.at(0);
247 QStringList ServiceWindow::queryList(QXmlQuery & q, QString query)
251 q.setQuery(query.prepend(NAMESPACE));
252 q.evaluateTo(&output);
256 ServiceWindow::~ServiceWindow()
263 void ServiceWindow::changeEvent(QEvent *e)
265 QMainWindow::changeEvent(e);
267 case QEvent::LanguageChange:
268 ui->retranslateUi(this);