commit eaf0ff61e2473ad73da7a9860b16fb23ed29f1f4 Author: Thomas Schwery Date: Wed May 4 10:57:35 2011 +0200 Imported from svn by Bitbucket diff --git a/bicimobile.pro b/bicimobile.pro new file mode 100644 index 0000000..7787757 --- /dev/null +++ b/bicimobile.pro @@ -0,0 +1,80 @@ +CONFIG += qt +CONFIG += silent +CONFIG += mobility + +QT += network + +MOBILITY = location + +TARGET = BiciMobile + +TRANSLATIONS = bicimobile_fr.ts + +QMAKE_CXXFLAGS+=-O3 -Wextra -fstack-protector -Wundef -Wpointer-arith +QMAKE_CXXFLAGS+=-Wconversion -Winit-self -Wuninitialized -Wstrict-null-sentinel + +QMAKE_LFLAGS+=-as-needed + +RESOURCES = translations.qrc + +# keep the tree clean +DESTDIR = build +OBJECTS_DIR = build +MOC_DIR = src/.tmp +# In Eclipse, "clean" removes binaries too. This is also needed to work around timestamp +# issues between host and VM in ESbox. +QMAKE_CLEAN += $$DESTDIR/BiciMaemo + +HEADERS = src/MainWindow.h \ + src/PageDownloader.h \ + src/PageParser.h \ + src/Station.h \ + src/StationDetail.h \ + src/StationsState.h \ + src/UpdaterThread.h \ + src/mapwidget.h \ + src/gpsposition.h + +SOURCES = src/MainWindow.cpp \ + src/PageDownloader.cpp \ + src/PageParser.cpp \ + src/Station.cpp \ + src/StationDetail.cpp \ + src/StationsState.cpp \ + src/UpdaterThread.cpp \ + src/main.cpp \ + src/mapwidget.cpp \ + src/gpsposition.cpp + +# TEMPLATE = app +# DESTDIR = /path/to/installation +# DEFINES += MACRO_1 ... + +# CONFIG += link_pkgconfig +# PKGCONFIG += ogg dbus-1 + +# install +target.path = /usr/bin +INSTALLS += target + +unix{ + #VARIABLES + isEmpty(PREFIX) { + PREFIX = /usr + } + BINDIR = $$PREFIX/bin + DATADIR =$$PREFIX/share + + DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\" + + #MAKE INSTALL + + INSTALLS += target desktop icon48 + target.path = $$BINDIR + + desktop.path = $$DATADIR/applications/hildon + desktop.files += data/bicimobile.desktop + + icon48.path = $$DATADIR/icons/hicolor/48x48/apps + icon48.files += data/bicimobile.png +} diff --git a/bicimobile_fr.ts b/bicimobile_fr.ts new file mode 100644 index 0000000..7a57bff --- /dev/null +++ b/bicimobile_fr.ts @@ -0,0 +1,70 @@ + + + + + MainWindow + + + &Update + &Update + + + + &Sort Network + Trier selon le &Réseau + + + + &Sort Numeric + Trier selon &Code station + + + + &Sort Name + Trier selon &Nom + + + + &Sort Distance + Trier selon &Distance + + + + Menu + Menu + + + + Station + + + Bikes: %1 + Vélos : %1 + + + + Stations: %1 + Stations: %1 + + + + Free bikes: %1 + Vélos libres: %1 + + + + Free stations: %1 + Stations libres: %1 + + + + %1 meters + %1 mètres + + + + %1 km + %1 km + + + diff --git a/data/bicimobile.desktop b/data/bicimobile.desktop new file mode 100644 index 0000000..55247ae --- /dev/null +++ b/data/bicimobile.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Type=Application +Name=BiciMobile +Exec=/usr/bin/BiciMobile +Icon=bicimobile +X-Window-Icon=bicimobile +X-Osso-Type=application/x-executable +X-HildonDesk-ShowInToolbar=true + diff --git a/data/bicimobile.png b/data/bicimobile.png new file mode 100644 index 0000000..038685b Binary files /dev/null and b/data/bicimobile.png differ diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..eb18bcc --- /dev/null +++ b/debian/changelog @@ -0,0 +1,24 @@ +bicimobile (0.1.2-1) unstable; urgency=low + + * Minor cosmetic changes + * Minor packaging changes + + -- Thomas Schwery Wed, 29 Dec 2010 16:38:46 +0100 + + +bicimobile (0.1.1-1) unstable; urgency=low + + * Corrected the desktop entry + * Added warnings to the compilation + * Added a refresh timer + * Changed layout of the buttons + * Added Distance To field in the station detail window + + -- Thomas Schwery Tue, 28 Dec 2010 22:03:23 +0100 + + +bicimobile (0.1-1) unstable; urgency=low + + * Initial release + + -- Thomas Schwery Sun, 26 Dec 2010 18:30:26 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..1bb90c0 --- /dev/null +++ b/debian/control @@ -0,0 +1,73 @@ +Source: bicimobile +Section: user/navigation +Priority: extra +Maintainer: Thomas Schwery +Build-Depends: debhelper (>= 7.0.50~), libqt4-dev, libqtm-dev, libqtm-location +Standards-Version: 3.8.4 + +Package: bicimobile +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: A Velopass / Bicincittà application + This application provides a simple way of checking for available bikes in the Velopass + (name given to Bicincittà in Switzerland) networks. +XSBC-Bugtracker: https://garage.maemo.org/tracker/?atid=6722&group_id=1942 +XSBC-Maemo-Display-Name: BiciMobile +XB-Maemo-Icon-26: + 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 + diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..de01ebd --- /dev/null +++ b/debian/copyright @@ -0,0 +1,39 @@ +This work was packaged for Debian by: + + Thomas Schwery on Sun, 26 Dec 2010 18:30:26 +0100 + +It was downloaded from: + + + +Upstream Author(s): + + Thomas Schwery + +Copyright: + + + +License: + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +On Debian systems, the complete text of the GNU General +Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". + +The Debian packaging is: + + Copyright (C) 2010 Thomas Schwery + +and is licensed under the GPL version 3, see above. diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e69de29 diff --git a/debian/optify b/debian/optify new file mode 100644 index 0000000..865faf1 --- /dev/null +++ b/debian/optify @@ -0,0 +1 @@ +auto diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..b973729 --- /dev/null +++ b/debian/rules @@ -0,0 +1,55 @@ +#!/usr/bin/make -f +APPNAME := bicimobile +builddir: + mkdir -p builddir + +builddir/Makefile: builddir + cd builddir && qmake-qt4 PREFIX=/usr ../$(APPNAME).pro + +build: build-stamp + +build-stamp: builddir/Makefile + dh_testdir + # Add here commands to compile the package. + cd builddir && $(MAKE) + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + # Add here commands to clean up after the build process. + rm -rf builddir + dh_clean +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/your_appname + cd builddir && $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/$(APPNAME) install +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installdocs + dh_installexamples + dh_installman + dh_link +# dh_strip --dbg-package=appname-dbg + dh_compress + dh_fixperms + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure + diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp new file mode 100644 index 0000000..31c873f --- /dev/null +++ b/src/MainWindow.cpp @@ -0,0 +1,101 @@ +/* + * MainWindow.cpp + * + * Created on: Nov 2, 2010 + * Author: Thomas Schwery + */ + +#include "MainWindow.h" +#include "StationDetail.h" + +MainWindow::MainWindow(StationsState * state, QWidget *parent) + : QMainWindow(parent) +{ + +#ifdef Q_WS_MAEMO_5 + setAttribute(Qt::WA_Maemo5StackedWindow); + setAttribute(Qt::WA_Maemo5AutoOrientation, true); +#endif + setWindowFlags(windowFlags() | Qt::Window); + this->state = state; + + QScrollArea *activityScroll = new QScrollArea(this); + QWidget *activitiesWidget = new QWidget(activityScroll); + mainLayout = new QVBoxLayout(activitiesWidget); + signalMapper = new QSignalMapper(this); + connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(popupStation(QString))); + + activityScroll->setWidgetResizable(true); + activityScroll->setWidget(activitiesWidget); + + QAction * updateAction = new QAction(tr("&Update"), this); + QAction * sortA = new QAction(tr("&Sort Network"), this); + QAction * sortB = new QAction(tr("&Sort Numeric"), this); + QAction * sortC = new QAction(tr("&Sort Name"), this); + QAction * sortD = new QAction(tr("&Sort Distance"), this); + + QMenu * menu = menuBar()->addMenu(tr("Menu")); + menu->addAction(updateAction); + menu->addAction(sortA); + menu->addAction(sortB); + menu->addAction(sortC); + menu->addAction(sortD); + + signalMapperMenu = new QSignalMapper(this); + + signalMapperMenu->setMapping(sortA, "network"); + signalMapperMenu->setMapping(sortB, "numeric"); + signalMapperMenu->setMapping(sortC, "name"); + signalMapperMenu->setMapping(sortD, "distance"); + + connect(updateAction, SIGNAL(triggered()), this , SLOT(update())); + connect(sortA, SIGNAL(triggered()), signalMapperMenu , SLOT(map())); + connect(sortB, SIGNAL(triggered()), signalMapperMenu , SLOT(map())); + connect(sortC, SIGNAL(triggered()), signalMapperMenu , SLOT(map())); + connect(sortD, SIGNAL(triggered()), signalMapperMenu , SLOT(map())); + + connect(signalMapperMenu, SIGNAL(mapped(QString)), state , SLOT(setSortType(QString))); + connect(signalMapperMenu, SIGNAL(mapped(QString)), this , SLOT(dataUpdated())); + + setCentralWidget(activityScroll); + + update(); +} + +MainWindow::~MainWindow() { + // TODO Auto-generated destructor stub +} + +void MainWindow::popupStation(QString key) { + Station * station = state->getStationMap()->value(key); + StationDetail * detail = new StationDetail(station, this); + detail->show(); +} + +void MainWindow::clearLayout() { + QPushButton * cb = NULL; + while (mainLayout->count() > 0) { + cb = dynamic_cast(mainLayout->takeAt(0)); + signalMapper->removeMappings(cb); + delete cb; + } +} + +void MainWindow::dataUpdated() { + clearLayout(); + QList::iterator i; + QList* stations = state->getStationList(); + QPushButton * cb = NULL; + + for (i = stations->begin(); i != stations->end(); ++i) { + cb = (*i)->getButton(); + mainLayout->addWidget(cb); + connect(cb, SIGNAL(clicked()), signalMapper, SLOT(map())); + signalMapper->setMapping(cb, (*i)->getName()); + } + mainLayout->update(); +} + +void MainWindow::update() { + emit updateData(); +} diff --git a/src/MainWindow.h b/src/MainWindow.h new file mode 100644 index 0000000..add0423 --- /dev/null +++ b/src/MainWindow.h @@ -0,0 +1,47 @@ +/* + * RequestSummary.h + * + * Created on: Nov 2, 2010 + * Author: Thomas Schwery + */ + +#ifndef REQUESTSUMMARY_H_ +#define REQUESTSUMMARY_H_ + +#include "StationsState.h" +#include "Station.h" + +#include +#include +#include +#include +#include +#include +#include + +class MainWindow : public QMainWindow +{ + Q_OBJECT; +public: + MainWindow(StationsState * state, QWidget *parent = 0); + virtual ~MainWindow(); + +public slots: + void popupStation(QString); + void dataUpdated(); + void update(); + +signals: + void updateData(); + +private: + StationsState * state; + QVBoxLayout * mainLayout; + QSignalMapper * signalMapper; + QSignalMapper * signalMapperMenu; + QProgressDialog * pd; + + void clearLayout(); +}; + +#endif /* REQUESTSUMMARY_H_ */ diff --git a/src/PageDownloader.cpp b/src/PageDownloader.cpp new file mode 100644 index 0000000..8d1e27d --- /dev/null +++ b/src/PageDownloader.cpp @@ -0,0 +1,28 @@ +/* + * PageDownloader.cpp + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#include "PageDownloader.h" + +PageDownloader::PageDownloader(QString urlString) : QObject() { + QUrl * url = new QUrl(); + url->setUrl(urlString); + + request = new QNetworkRequest(*url); + manager = new QNetworkAccessManager(this); +} + +PageDownloader::~PageDownloader() { + // TODO Auto-generated destructor stub +} + +void PageDownloader::get(UpdaterThread * object) { + reply = manager->get(*request); + connect(reply, SIGNAL(finished()), object, SLOT(dataArrived())); +} +QString PageDownloader::getData() { + return QString(reply->readAll()); +} diff --git a/src/PageDownloader.h b/src/PageDownloader.h new file mode 100644 index 0000000..0f0851e --- /dev/null +++ b/src/PageDownloader.h @@ -0,0 +1,34 @@ +/* + * PageDownloader.h + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#ifndef PAGEDOWNLOADER_H_ +#define PAGEDOWNLOADER_H_ + +class UpdaterThread; + +#include +#include +#include +#include + +#include "UpdaterThread.h" + +class PageDownloader : public QObject { + Q_OBJECT +public: + PageDownloader(QString); + virtual ~PageDownloader(); + + void get(UpdaterThread *); + QString getData(); +private: + QNetworkAccessManager * manager; + QNetworkRequest * request; + QNetworkReply * reply; +}; + +#endif /* PAGEDOWNLOADER_H_ */ diff --git a/src/PageParser.cpp b/src/PageParser.cpp new file mode 100644 index 0000000..174357e --- /dev/null +++ b/src/PageParser.cpp @@ -0,0 +1,62 @@ +/* + * PageParser.cpp + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#include "PageParser.h" +#include +#include +#include + +PageParser::PageParser() { + // TODO Auto-generated constructor stub + +} + +PageParser::~PageParser() { + // TODO Auto-generated destructor stub +} + + +QMap* PageParser::parsePage(QString data) { + QMap * stations = new QMap(); + + QStringList dataLines = data.split('\n').mid(20, 10); + + QString split_line = dataLines.filter(QRegExp("var d1 =", Qt::CaseSensitive, QRegExp::FixedString)).at(0); + QChar split_char('_'); + QRegExp regexSeparator("=.'(.)'"); + if (regexSeparator.indexIn(split_line) > -1) { + split_char = regexSeparator.cap(1).at(0); + } + + QStringList dataLines2 = dataLines.filter(QRegExp("var sita_", Qt::CaseInsensitive, QRegExp::FixedString)); + + dataLines2.replaceInStrings(QRegExp("\"\\+.*"), ""); + dataLines2.replaceInStrings(QRegExp("^.*= \""), ""); + dataLines2.replaceInStrings("\";", ""); + + QStringList name = dataLines2.at(2).split(split_char); + QStringList status = dataLines2.at(4).split(split_char); + QStringList network = dataLines2.at(6).split(split_char); + QStringList xList = dataLines2.at(0).split(split_char); + QStringList yList = dataLines2.at(1).split(split_char); + + name.replaceInStrings(QRegExp("^ +"), ""); + name.replaceInStrings("é","e"); + name.replaceInStrings("è","e"); + + for (int i =0; iinsert(name.at(i), newStation); + } + + return stations; +} diff --git a/src/PageParser.h b/src/PageParser.h new file mode 100644 index 0000000..6b6eacb --- /dev/null +++ b/src/PageParser.h @@ -0,0 +1,23 @@ +/* + * PageParser.h + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#ifndef PAGEPARSER_H_ +#define PAGEPARSER_H_ + +#include "Station.h" +#include +#include + +class PageParser { +public: + PageParser(); + virtual ~PageParser(); + + static QMap* parsePage(QString data); +}; + +#endif /* PAGEPARSER_H_ */ diff --git a/src/Station.cpp b/src/Station.cpp new file mode 100644 index 0000000..024397b --- /dev/null +++ b/src/Station.cpp @@ -0,0 +1,144 @@ +/* + * Station.cpp + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#include "Station.h" + +Station::Station(QString name, QString network, float gpsX, float gpsY, int freeBikes, int freeStations) + : QObject() { + this->name = name; + this->network = network; + this->xPosition = gpsX; + this->yPosition = gpsY; + this->freeBikes = freeBikes; + this->freeStations = freeStations; +} + +Station::~Station() { + // TODO Auto-generated destructor stub +} + +QPushButton * Station::getButton() { + QPushButton *cb = new QPushButton(QString("")); + + QString infoBikes = tr("Bikes: %1").arg(freeBikes); + + QString infoStations = tr("Stations: %1").arg(freeStations); + + QLabel * labelBikes = new QLabel(infoBikes); + QLabel * labelStations = new QLabel(infoStations); + + labelBikes->setAlignment(Qt::AlignRight); + labelStations->setAlignment(Qt::AlignRight); + + QLabel * labelNetwork = new QLabel(network); + QLabel * labelName = new QLabel(name); + + QHBoxLayout * layout = new QHBoxLayout(cb); + + QVBoxLayout * stationLayout = new QVBoxLayout(); + QVBoxLayout * infoLayout = new QVBoxLayout(); + + stationLayout->addWidget(labelName); + stationLayout->addWidget(labelNetwork); + + infoLayout->setAlignment(Qt::AlignRight); + infoLayout->addWidget(labelBikes); + infoLayout->addWidget(labelStations); + + layout->addLayout(stationLayout); + layout->addLayout(infoLayout); + + cb->setLayout(layout); + +#ifndef Q_WS_MAEMO_5 + cb->adjustSize(); +#endif + + return cb; +} + +qreal Station::getLatitude() const { + return qreal(xPosition); +} + +qreal Station::getLongitude() const { + return qreal(yPosition); +} + +QGeoCoordinate Station::getCoordinate() const { + return QGeoCoordinate(xPosition, yPosition); +} + +QLayout * Station::getLayout() { + QVBoxLayout * vbox = new QVBoxLayout(); + + QHBoxLayout * line1 = new QHBoxLayout(); + + QString stringName = QString("%1 (%2)").arg(name, network); + QLabel * labelName = new QLabel(stringName); + + QString stringDistance = getDistanceToUser(); + QLabel * labelDistance = new QLabel(stringDistance); + + line1->addWidget(labelName); + line1->addStretch(); + line1->addWidget(labelDistance); + + QHBoxLayout * line2 = new QHBoxLayout(); + + QString stringBikes = tr("Free bikes: %1").arg(freeBikes); + QLabel * labelBikes = new QLabel(stringBikes); + + QString stringStations = tr("Free stations: %1").arg(freeStations); + QLabel * labelStations = new QLabel(stringStations); + + line2->addWidget(labelBikes); + line2->addStretch(); + line2->addWidget(labelStations); + + vbox->addLayout(line1); + vbox->addLayout(line2); + + return vbox; +} + +QString Station::getName() const { + return name; +} + +QString Station::getNetwork() const { + return network; +} + +int Station::getFreeBikes() const { + return freeBikes; +} + +int Station::getFreeStations() const { + return freeStations; +} + +QString Station::getDistanceToUser() const { + QGeoCoordinate stationCoordinates(getLatitude(), getLongitude()); + QGeoCoordinate userCoordinates(GPSPosition::getInstance().getCoordinate()); + qreal distance = stationCoordinates.distanceTo(userCoordinates); + + QString labelDistance = ""; + if (distance < 1000) { + labelDistance += tr("%1 meters").arg(distance); + } else { + distance /= 1000; + labelDistance += tr("%1 km").arg(distance); + } + + return labelDistance; +} + +QTextStream &operator<<(QTextStream &out, const Station &station) { + out << station.getName() << "(" << station.getNetwork() << ") - Bikes:" << station.getFreeBikes() << ", Stations:" << station.getFreeStations(); + return out; +} diff --git a/src/Station.h b/src/Station.h new file mode 100644 index 0000000..8bf371a --- /dev/null +++ b/src/Station.h @@ -0,0 +1,51 @@ +/* + * Station.h + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#ifndef STATION_H_ +#define STATION_H_ + +#include +#include +#include + +#include +#include "gpsposition.h" + +QTM_USE_NAMESPACE; + +class Station : public QObject { + Q_OBJECT; +public: + Station(QString, QString, float, float, int, int); + virtual ~Station(); + + QPushButton * getButton(); + QLayout * getLayout(); + + QString getName() const; + QString getNetwork() const; + int getFreeBikes() const; + int getFreeStations() const; + + qreal getLatitude() const; + qreal getLongitude() const; + QGeoCoordinate getCoordinate() const; + +private: + QString name; + QString network; + float xPosition; + float yPosition; + int freeBikes; + int freeStations; + + QString getDistanceToUser() const; +}; + +QTextStream &operator<<(QTextStream &out, const Station &station); + +#endif /* STATION_H_ */ diff --git a/src/StationDetail.cpp b/src/StationDetail.cpp new file mode 100644 index 0000000..33a8f46 --- /dev/null +++ b/src/StationDetail.cpp @@ -0,0 +1,37 @@ +/* + * StationDetail.cpp + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#include "StationDetail.h" + +StationDetail::StationDetail(Station * station, QWidget *parent) + : QWidget(parent) +{ +#ifdef Q_WS_MAEMO_5 + setAttribute(Qt::WA_Maemo5StackedWindow); +#endif + setWindowFlags(windowFlags() | Qt::Window); + setWindowTitle("BiciMobile - " + station->getName()); + + QVBoxLayout * layout = new QVBoxLayout(this); + + layout->addLayout(station->getLayout()); + + layout->addStretch(); + + MapWidget * map = new MapWidget(station->getCoordinate(), GPSPosition::getInstance().getCoordinate(), this); + + QHBoxLayout * mapLayout = new QHBoxLayout(); + mapLayout->addStretch(); + mapLayout->addWidget(map); + mapLayout->addStretch(); + + layout->addLayout(mapLayout); +} + +StationDetail::~StationDetail() { + // TODO Auto-generated destructor stub +} diff --git a/src/StationDetail.h b/src/StationDetail.h new file mode 100644 index 0000000..a99c842 --- /dev/null +++ b/src/StationDetail.h @@ -0,0 +1,28 @@ +/* + * StationDetail.h + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#ifndef STATIONDETAIL_H_ +#define STATIONDETAIL_H_ + +#include +#include "Station.h" +#include "mapwidget.h" +#include "gpsposition.h" + +#include +#include + +QTM_USE_NAMESPACE; + +class StationDetail : public QWidget { + Q_OBJECT; +public: + StationDetail(Station * station, QWidget *parent = 0); + virtual ~StationDetail(); +}; + +#endif /* STATIONDETAIL_H_ */ diff --git a/src/StationsState.cpp b/src/StationsState.cpp new file mode 100644 index 0000000..b78cdf4 --- /dev/null +++ b/src/StationsState.cpp @@ -0,0 +1,88 @@ +/* + * StationsState.cpp + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#include "StationsState.h" + +StationsState::StationsState() { + stations = new QMap(); + sortType = numerical; +} + +StationsState::~StationsState() { + QMap::iterator i; + for (i=stations->begin(); i!=stations->end(); ++i) { + delete (*i); + } + delete stations; +} + +void StationsState::setSortType(StationSorting sorting) { + sortType = sorting; +} + +void StationsState::setSortType(QString sorting) { + if (sorting == "name") { + sortType = alpha_name; + } else if (sorting == "network") { + sortType = alpha_network; + } else if (sorting == "numeric") { + sortType = numerical; + } else { + sortType = distance_user; + } +} + +QMap * StationsState::getStationMap() { + return stations; +} + +QList * StationsState::getStationList() { + QList * stationsList = new QList(stations->values()); + if (sortType == distance_user) qSort(stationsList->begin(), stationsList->end(), compareDistance); + if (sortType == alpha_name) qSort(stationsList->begin(), stationsList->end(), compareName); + if (sortType == alpha_network) qSort(stationsList->begin(), stationsList->end(), compareNetwork); + if (sortType == numerical) qSort(stationsList->begin(), stationsList->end(), compareNumber); + return stationsList; +} + + +void StationsState::setStations(QMap* updatedStations) { + QMap::iterator i; + for (i=stations->begin(); i!=stations->end(); ++i) { + delete (*i); + } + delete stations; + stations = updatedStations; +} + +bool StationsState::compareDistance(Station *& s1, Station *& s2) { + QGeoCoordinate s1Coordinates(s1->getLatitude(), s1->getLongitude()); + QGeoCoordinate s2Coordinates(s2->getLatitude(), s2->getLongitude()); + QGeoCoordinate userCoordinates(GPSPosition::getInstance().getLatitude(), GPSPosition::getInstance().getLongitude()); + return (s1Coordinates.distanceTo(userCoordinates)) < (s2Coordinates.distanceTo(userCoordinates)); +} + +bool StationsState::compareName(Station *& s1, Station *& s2) { + QString code1 = s1->getName().split(" ").at(1); + QString code2 = s2->getName().split(" ").at(1); + return code1 < code2; +} + +bool StationsState::compareNetwork(Station *& s1, Station *& s2) { + QString code1 = s1->getNetwork(); + QString code2 = s2->getNetwork(); + if (code1 == code2) { + return compareNumber(s1, s2); + } + return code1 < code2; +} + +bool StationsState::compareNumber(Station*& s1, Station*& s2) { + int code1 = s1->getName().split(" ").at(0).toInt(); + int code2 = s2->getName().split(" ").at(0).toInt(); + return code1 < code2; +} diff --git a/src/StationsState.h b/src/StationsState.h new file mode 100644 index 0000000..61e2583 --- /dev/null +++ b/src/StationsState.h @@ -0,0 +1,50 @@ +/* + * StationsState.h + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#ifndef STATIONSSTATE_H_ +#define STATIONSSTATE_H_ + +#include +#include +#include + +#include "gpsposition.h" +#include "Station.h" + +enum StationSorting { + alpha_name, + alpha_network, + numerical, + distance_user +}; + +class StationsState : public QObject { + Q_OBJECT +public: + StationsState(); + virtual ~StationsState(); + + QMap * getStationMap(); + QList * getStationList(); + + void setStations(QMap* updatedStations); + void setSortType(StationSorting); + + static bool compareDistance(Station*&, Station*&); + static bool compareName(Station *&, Station *&); + static bool compareNetwork(Station *&, Station *&); + static bool compareNumber(Station *&, Station *&); + +public slots: + void setSortType(QString); + +private: + QMap * stations; + StationSorting sortType; +}; + +#endif /* STATIONSSTATE_H_ */ diff --git a/src/UpdaterThread.cpp b/src/UpdaterThread.cpp new file mode 100644 index 0000000..840282c --- /dev/null +++ b/src/UpdaterThread.cpp @@ -0,0 +1,32 @@ +/* + * UpdaterThread.cpp + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#include "UpdaterThread.h" + +UpdaterThread::UpdaterThread(StationsState * state) : QObject() { + this->state = state; + + pageDl = new PageDownloader("http://www.bicincitta.com/Citta_CH.asp"); + + QTimer * updaterTimer = new QTimer(); + QObject::connect(updaterTimer, SIGNAL(timeout()), this, SLOT(update())); + updaterTimer->start(60000); +} + +UpdaterThread::~UpdaterThread() { + +} + +void UpdaterThread::update() { + pageDl->get(this); +} + +void UpdaterThread::dataArrived() { + QString data = pageDl->getData(); + state->setStations(PageParser::parsePage(data)); + emit dataUpdated(); +} diff --git a/src/UpdaterThread.h b/src/UpdaterThread.h new file mode 100644 index 0000000..3c6d427 --- /dev/null +++ b/src/UpdaterThread.h @@ -0,0 +1,40 @@ +/* + * UpdaterThread.h + * + * Created on: Nov 3, 2010 + * Author: Thomas Schwery + */ + +#ifndef UPDATERTHREAD_H_ +#define UPDATERTHREAD_H_ + +#include +#include + +class PageDownloader; + +#include "Station.h" +#include "StationsState.h" +#include "PageDownloader.h" +#include "PageParser.h" + +class UpdaterThread : public QObject { + Q_OBJECT +public: + UpdaterThread(StationsState * state); + virtual ~UpdaterThread(); + +public slots: + void update(); + void dataArrived(); + +signals: + void dataUpdated(); + +private: + StationsState * state; + QTimer * updaterTimer; + PageDownloader * pageDl; +}; + +#endif /* UPDATERTHREAD_H_ */ diff --git a/src/gpsposition.cpp b/src/gpsposition.cpp new file mode 100644 index 0000000..33c8f09 --- /dev/null +++ b/src/gpsposition.cpp @@ -0,0 +1,45 @@ +#include "gpsposition.h" + +GPSPosition::GPSPosition(QObject *parent) : + QObject(parent) { + tolerance = 50; + location = QGeoPositionInfoSource::createDefaultSource(this); + connect(location, SIGNAL(positionUpdated(QGeoPositionInfo)), this, SLOT(onPositionUpdated(QGeoPositionInfo))); + location->startUpdates(); + location->setUpdateInterval(30000); + location->requestUpdate(); +} + +qreal GPSPosition::getLatitude() const { + return coordinate.latitude(); +} + +qreal GPSPosition::getLongitude() const { + return coordinate.longitude(); +} + +void GPSPosition::setTolerance(qreal newTolerance) { + tolerance = newTolerance; +} + +QGeoCoordinate GPSPosition::getCoordinate() const { + return coordinate; +} + +void GPSPosition::onPositionUpdated(QGeoPositionInfo position) { + coordinate = position.coordinate(); + if (coordinate.distanceTo(lastEmitted) > tolerance) { + lastEmitted = coordinate; + emit movedTolerance(); + } + qDebug() << "Position updated : " << coordinate; +} + +GPSPosition& GPSPosition::getInstance() { + static GPSPosition instance; + return instance; +} + +void GPSPosition::requestUpdate() { + location->requestUpdate(); +} diff --git a/src/gpsposition.h b/src/gpsposition.h new file mode 100644 index 0000000..764095d --- /dev/null +++ b/src/gpsposition.h @@ -0,0 +1,41 @@ +#ifndef GPSPOSITION_H +#define GPSPOSITION_H + +#include +#include +#include +#include +#include +#include +#include + +QTM_USE_NAMESPACE + +class GPSPosition : public QObject +{ + Q_OBJECT +public: + static GPSPosition& getInstance(); + qreal getLatitude() const; + qreal getLongitude() const; + QGeoCoordinate getCoordinate() const; + void setTolerance(qreal newTolerance); + +signals: + void movedTolerance(); + +public slots: + void requestUpdate(); + +private slots: + void onPositionUpdated(QGeoPositionInfo); + +private: + GPSPosition(QObject *parent = 0); + QGeoPositionInfoSource * location; + QGeoCoordinate coordinate; + QGeoCoordinate lastEmitted; + qreal tolerance; +}; + +#endif // GPSPOSITION_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..76b4095 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,40 @@ +#include + +#include "MainWindow.h" +#include "UpdaterThread.h" +#include "PageParser.h" + +#include "gpsposition.h" + +#include + +int main(int argc, char *argv[]) +{ + QTextStream out(stdout); + QApplication app(argc, argv); + +#ifdef Q_WS_MAEMO_5 + QApplication ::setOverrideCursor(QCursor(Qt::BlankCursor)); +#endif + + + QTranslator translator; + qDebug() << translator.load(":/bicimobile_fr"); + app.installTranslator(&translator); + + StationsState * state = new StationsState(); + + UpdaterThread * updaterThread = new UpdaterThread(state); + + GPSPosition::getInstance(); + + MainWindow window(state); + + QObject::connect(updaterThread, SIGNAL(dataUpdated()), &window, SLOT(dataUpdated())); + QObject::connect(&window, SIGNAL(updateData()), updaterThread, SLOT(update())); + + window.show(); + window.update(); + + return app.exec(); +} diff --git a/src/mapwidget.cpp b/src/mapwidget.cpp new file mode 100644 index 0000000..4b7010f --- /dev/null +++ b/src/mapwidget.cpp @@ -0,0 +1,72 @@ +#include "mapwidget.h" + +MapWidget::MapWidget(const QGeoCoordinate& station, const QGeoCoordinate& user, QWidget* parent) + : QWidget(parent) { + + QObject::connect(&networkAccessManager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(handleNetworkData(QNetworkReply*))); + + setMinimumSize(400,400); + + fetchMap(size(), station, user); + + QTimer * updateTimer = new QTimer(this); + connect(updateTimer, SIGNAL(timeout()), &GPSPosition::getInstance(), SLOT(requestUpdate())); + connect(&GPSPosition::getInstance(), SIGNAL(movedTolerance()), this, SLOT(fetchMap())); + updateTimer->start(15000); +} + +void MapWidget::fetchMap(const QSize& size, const QGeoCoordinate& station, const QGeoCoordinate& user) { + + qreal latitude = station.latitude(); + qreal longitude = station.longitude(); + + qreal user_latitude = user.latitude(); + qreal user_longitude = user.longitude(); + + qreal center_latitude = (latitude + user_latitude)/2; + qreal center_longitude = (longitude + user_longitude)/2; + + qreal distance_to_fit = station.distanceTo(user); + qreal logpartup = (6.28318531*6372.795*1000)/(distance_to_fit); // 2*PI*EARTH_SPHERE_RADIUS + + qreal logpartupval = log(logpartup); + + qreal logpartdownresult = log(2.0); + int zoom = int(logpartupval/logpartdownresult); + + if (zoom > 17) zoom = 17; + + const QString GOOGLE_MAPS_URL_TEMPLATE = + "http://maps.google.com/maps/api/staticmap?center=%1,%2&zoom=%7&size=%3x%4&maptype=mobile&markers=color:red|label:B|%8,%9&markers=color:blue|label:Y|%5,%6&sensor=false"; + + QUrl url = QUrl(GOOGLE_MAPS_URL_TEMPLATE.arg( + QString::number(center_latitude), QString::number(center_longitude), + QString::number(size.width()), QString::number(size.height()), + QString::number(user_latitude), QString::number(user_longitude), + QString::number(zoom), + QString::number(latitude), QString::number(longitude) + )); + + QNetworkRequest request; + request.setUrl(url); + networkAccessManager.get(request); +} + +void MapWidget::handleNetworkData(QNetworkReply* reply) { + QImage image; + if (reply->error() == QNetworkReply::NoError) { + image.load(reply, 0); + if (!image.isNull()) { + mapPixmap = QPixmap::fromImage(image); + } + } + reply->deleteLater(); + update(); +} + +void MapWidget::paintEvent(QPaintEvent* paintEvent) { + Q_UNUSED(paintEvent); + QPainter painter(this); + painter.drawPixmap(0, 0, mapPixmap); +} diff --git a/src/mapwidget.h b/src/mapwidget.h new file mode 100644 index 0000000..8248fc0 --- /dev/null +++ b/src/mapwidget.h @@ -0,0 +1,32 @@ +#ifndef MAPWIDGET_H +#define MAPWIDGET_H + +#include +#include +#include + +#include "gpsposition.h" + +#include + +QTM_USE_NAMESPACE + +class MapWidget : public QWidget +{ + Q_OBJECT + +public: + MapWidget(const QGeoCoordinate&, const QGeoCoordinate&, QWidget* parent = 0); + void paintEvent(QPaintEvent* paintEvent); + +public slots: + void handleNetworkData(QNetworkReply* reply); + +private: + void fetchMap(const QSize&, const QGeoCoordinate&, const QGeoCoordinate&); + + QNetworkAccessManager networkAccessManager; + QPixmap mapPixmap; +}; + +#endif // MAPWIDGET_H diff --git a/translations.qrc b/translations.qrc new file mode 100644 index 0000000..ae6fb00 --- /dev/null +++ b/translations.qrc @@ -0,0 +1,5 @@ + + + bicimobile_fr.qm + +