From e0d5221957bf0d7857f924f1f2ae63d490de0a0a Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Wed, 22 Jun 2011 13:54:56 +0200 Subject: Move all other demos in qtbase to examples. Change-Id: Iab0e7364d1f6b348d0e3033ea9304139f5bd6d0d Reviewed-on: http://codereview.qt.nokia.com/617 Reviewed-by: Qt Sanity Bot Reviewed-by: David Boddie --- examples/embedded/flightinfo/flightinfo.cpp | 399 ++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 examples/embedded/flightinfo/flightinfo.cpp (limited to 'examples/embedded/flightinfo/flightinfo.cpp') diff --git a/examples/embedded/flightinfo/flightinfo.cpp b/examples/embedded/flightinfo/flightinfo.cpp new file mode 100644 index 0000000000..58e71c8376 --- /dev/null +++ b/examples/embedded/flightinfo/flightinfo.cpp @@ -0,0 +1,399 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +#include "ui_form.h" + +#define FLIGHTVIEW_URL "http://mobile.flightview.com/TrackByFlight.aspx" +#define FLIGHTVIEW_RANDOM "http://mobile.flightview.com/TrackSampleFlight.aspx" + +// strips all invalid constructs that might trip QXmlStreamReader +static QString sanitized(const QString &xml) +{ + QString data = xml; + + // anything up to the html tag + int i = data.indexOf(" 0) + data.remove(0, i - 1); + + // everything inside the head tag + i = data.indexOf(" 0) + data.remove(i, data.indexOf("") - i + 7); + + // invalid link for JavaScript code + while (true) { + i = data.indexOf("onclick=\"gotoUrl("); + if (i < 0) + break; + data.remove(i, data.indexOf('\"', i + 9) - i + 1); + } + + // all inline frames + while (true) { + i = data.indexOf("") - i + 8); + } + + // entities + data.remove(" "); + data.remove("©"); + + return data; +} + +class FlightInfo : public QMainWindow +{ + Q_OBJECT + +private: + + Ui_Form ui; + QUrl m_url; + QDate m_searchDate; + QPixmap m_map; + QNetworkAccessManager m_manager; + QList mapReplies; + +public: + + FlightInfo(QMainWindow *parent = 0): QMainWindow(parent) { + + QWidget *w = new QWidget(this); + ui.setupUi(w); + setCentralWidget(w); + + ui.searchBar->hide(); + ui.infoBox->hide(); + connect(ui.searchButton, SIGNAL(clicked()), SLOT(startSearch())); + connect(ui.flightEdit, SIGNAL(returnPressed()), SLOT(startSearch())); + + setWindowTitle("Flight Info"); + + // Rendered from the public-domain vectorized aircraft + // http://openclipart.org/media/people/Jarno + m_map = QPixmap(":/aircraft.png"); + + QAction *searchTodayAction = new QAction("Today's Flight", this); + QAction *searchYesterdayAction = new QAction("Yesterday's Flight", this); + QAction *randomAction = new QAction("Random Flight", this); + connect(searchTodayAction, SIGNAL(triggered()), SLOT(today())); + connect(searchYesterdayAction, SIGNAL(triggered()), SLOT(yesterday())); + connect(randomAction, SIGNAL(triggered()), SLOT(randomFlight())); + connect(&m_manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(handleNetworkData(QNetworkReply*))); +#if defined(Q_OS_SYMBIAN) + menuBar()->addAction(searchTodayAction); + menuBar()->addAction(searchYesterdayAction); + menuBar()->addAction(randomAction); +#else + addAction(searchTodayAction); + addAction(searchYesterdayAction); + addAction(randomAction); + setContextMenuPolicy(Qt::ActionsContextMenu); +#endif + } + +private slots: + + void handleNetworkData(QNetworkReply *networkReply) { + if (!networkReply->error()) { + if (!mapReplies.contains(networkReply)) { + // Assume UTF-8 encoded + QByteArray data = networkReply->readAll(); + QString xml = QString::fromUtf8(data); + digest(xml); + } else { + mapReplies.removeOne(networkReply); + m_map.loadFromData(networkReply->readAll()); + update(); + } + } + networkReply->deleteLater(); + } + + void today() { + QDateTime timestamp = QDateTime::currentDateTime(); + m_searchDate = timestamp.date(); + searchFlight(); + } + + void yesterday() { + QDateTime timestamp = QDateTime::currentDateTime(); + timestamp = timestamp.addDays(-1); + m_searchDate = timestamp.date(); + searchFlight(); + } + + void searchFlight() { + ui.searchBar->show(); + ui.infoBox->hide(); + ui.flightStatus->hide(); + ui.flightName->setText("Enter flight number"); + ui.flightEdit->setFocus(); +#ifdef QT_KEYPAD_NAVIGATION + ui.flightEdit->setEditFocus(true); +#endif + m_map = QPixmap(); + update(); + } + + void startSearch() { + ui.searchBar->hide(); + QString flight = ui.flightEdit->text().simplified(); + if (!flight.isEmpty()) + request(flight, m_searchDate); + } + + void randomFlight() { + request(QString(), QDate::currentDate()); + } + +public slots: + + void request(const QString &flightCode, const QDate &date) { + + setWindowTitle("Loading..."); + + QString code = flightCode.simplified(); + QString airlineCode = code.left(2).toUpper(); + QString flightNumber = code.mid(2, code.length()); + + ui.flightName->setText("Searching for " + code); + + m_url = QUrl(FLIGHTVIEW_URL); + m_url.addEncodedQueryItem("view", "detail"); + m_url.addEncodedQueryItem("al", QUrl::toPercentEncoding(airlineCode)); + m_url.addEncodedQueryItem("fn", QUrl::toPercentEncoding(flightNumber)); + m_url.addEncodedQueryItem("dpdat", QUrl::toPercentEncoding(date.toString("yyyyMMdd"))); + + if (code.isEmpty()) { + // random flight as sample + m_url = QUrl(FLIGHTVIEW_RANDOM); + ui.flightName->setText("Getting a random flight..."); + } + + m_manager.get(QNetworkRequest(m_url)); + } + + +private: + + void digest(const QString &content) { + + setWindowTitle("Flight Info"); + QString data = sanitized(content); + + // do we only get the flight list? + // we grab the first leg in the flight list + // then fetch another URL for the real flight info + int i = data.indexOf("a href=\"?view=detail"); + if (i > 0) { + QString href = data.mid(i, data.indexOf('\"', i + 8) - i + 1); + QRegExp regex("dpap=([A-Za-z0-9]+)"); + regex.indexIn(href); + QString airport = regex.cap(1); + m_url.addEncodedQueryItem("dpap", QUrl::toPercentEncoding(airport)); + m_manager.get(QNetworkRequest(m_url)); + return; + } + + QXmlStreamReader xml(data); + bool inFlightName = false; + bool inFlightStatus = false; + bool inFlightMap = false; + bool inFieldName = false; + bool inFieldValue = false; + + QString flightName; + QString flightStatus; + QStringList fieldNames; + QStringList fieldValues; + + while (!xml.atEnd()) { + xml.readNext(); + + if (xml.tokenType() == QXmlStreamReader::StartElement) { + QStringRef className = xml.attributes().value("class"); + inFlightName |= xml.name() == "h1"; + inFlightStatus |= className == "FlightDetailHeaderStatus"; + inFlightMap |= className == "flightMap"; + if (xml.name() == "td" && !className.isEmpty()) { + QString cn = className.toString(); + if (cn.contains("fieldTitle")) { + inFieldName = true; + fieldNames += QString(); + fieldValues += QString(); + } + if (cn.contains("fieldValue")) + inFieldValue = true; + } + if (xml.name() == "img" && inFlightMap) { + QString src = xml.attributes().value("src").toString(); + src.prepend("http://mobile.flightview.com/"); + QUrl url = QUrl::fromPercentEncoding(src.toAscii()); + mapReplies.append(m_manager.get(QNetworkRequest(url))); + } + } + + if (xml.tokenType() == QXmlStreamReader::EndElement) { + inFlightName &= xml.name() != "h1"; + inFlightStatus &= xml.name() != "div"; + inFlightMap &= xml.name() != "div"; + inFieldName &= xml.name() != "td"; + inFieldValue &= xml.name() != "td"; + } + + if (xml.tokenType() == QXmlStreamReader::Characters) { + if (inFlightName) + flightName += xml.text(); + if (inFlightStatus) + flightStatus += xml.text(); + if (inFieldName) + fieldNames.last() += xml.text(); + if (inFieldValue) + fieldValues.last() += xml.text(); + } + } + + if (fieldNames.isEmpty()) { + QString code = ui.flightEdit->text().simplified().left(10); + QString msg = QString("Flight %1 is not found").arg(code); + ui.flightName->setText(msg); + return; + } + + ui.flightName->setText(flightName); + flightStatus.remove("Status: "); + ui.flightStatus->setText(flightStatus); + ui.flightStatus->show(); + + QStringList whiteList; + whiteList << "Departure"; + whiteList << "Arrival"; + whiteList << "Scheduled"; + whiteList << "Takeoff"; + whiteList << "Estimated"; + whiteList << "Term-Gate"; + + QString text; + text = QString("").arg(width() - 25); + for (int i = 0; i < fieldNames.count(); i++) { + QString fn = fieldNames[i].simplified(); + if (fn.endsWith(':')) + fn = fn.left(fn.length() - 1); + if (!whiteList.contains(fn)) + continue; + + QString fv = fieldValues[i].simplified(); + bool special = false; + special |= fn.startsWith("Departure"); + special |= fn.startsWith("Arrival"); + text += ""; + if (special) { + text += ""; + } else { + text += ""; + text += ""; + } + text += ""; + } + text += "
"; + text += "" + fv + ""; + text += ""; + text += fn; + text += " : "; + text += " "; + text += ""; + text += fv; + text += "
"; + ui.detailedInfo->setText(text); + ui.infoBox->show(); + } + + void resizeEvent(QResizeEvent *event) { + Q_UNUSED(event); + ui.detailedInfo->setMaximumWidth(width() - 25); + } + + void paintEvent(QPaintEvent *event) { + QMainWindow::paintEvent(event); + QPainter p(this); + p.fillRect(rect(), QColor(131, 171, 210)); + if (!m_map.isNull()) { + int x = (width() - m_map.width()) / 2; + int space = ui.infoBox->pos().y(); + if (!ui.infoBox->isVisible()) + space = height(); + int top = ui.titleBox->height(); + int y = qMax(top, (space - m_map.height()) / 2); + p.drawPixmap(x, y, m_map); + } + p.end(); + } + +}; + + +#include "flightinfo.moc" + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(flightinfo); + + QApplication app(argc, argv); + + FlightInfo w; +#if defined(Q_OS_SYMBIAN) + w.showMaximized(); +#else + w.resize(360, 504); + w.show(); +#endif + + return app.exec(); +} -- cgit v1.2.3