diff --git a/batterylayer.cpp b/batterylayer.cpp index 8b02e62..9f41483 100644 --- a/batterylayer.cpp +++ b/batterylayer.cpp @@ -24,7 +24,6 @@ #include #include #include -#include BatteryLayer::BatteryLayer(MapWidget *map) : AbstractLayer(map), diff --git a/mainwidget.cpp b/mainwidget.cpp index 7513d0d..d3cc7e0 100644 --- a/mainwidget.cpp +++ b/mainwidget.cpp @@ -22,6 +22,7 @@ #include "downloadwidget.h" #include "mapwidget.h" #include "markerlist.h" +#include "routingwidget.h" #include "batterylayer.h" #include "gpslayer.h" @@ -38,7 +39,8 @@ MainWidget::MainWidget(QWidget *parent) m_stack(new QStackedWidget(this)), m_map(new MapWidget(this)), m_markerList(new MarkerList(this)), - m_dlWidget(new DownloadWidget(this)) + m_dlWidget(new DownloadWidget(this)), + m_routingWidget(new RoutingWidget(this)) { QString fileName; if (QApplication::arguments().count() > 1) { @@ -76,6 +78,7 @@ MainWidget::MainWidget(QWidget *parent) connect(m_map, SIGNAL(showMarkerList()), this, SLOT(showList())); connect(m_map, SIGNAL(downloadArea(int, QRectF)), this, SLOT(downloadArea(int, QRectF))); + connect(m_map, SIGNAL(route(QPointF, QPointF)), this, SLOT(findRoute(QPointF, QPointF))); m_stack->insertWidget(0, m_map); connect(m_markerList, SIGNAL(back()), this, SLOT(showMap())); @@ -85,6 +88,9 @@ MainWidget::MainWidget(QWidget *parent) connect(m_dlWidget, SIGNAL(back()), this, SLOT(showMap())); m_stack->insertWidget(2, m_dlWidget); + connect(m_routingWidget, SIGNAL(back()), this, SLOT(showMap())); + m_stack->insertWidget(3, m_routingWidget); + resize(320, 240); } @@ -114,3 +120,11 @@ void MainWidget::downloadArea(int level, const QRectF &rect) m_stack->setCurrentIndex(2); } +void MainWidget::findRoute(const QPointF &from, const QPointF &to) +{ + m_routingWidget->setFrom(from); + m_routingWidget->setTo(to); + + m_stack->setCurrentIndex(3); +} + diff --git a/mainwidget.h b/mainwidget.h index a1cf8e2..76e3fc5 100644 --- a/mainwidget.h +++ b/mainwidget.h @@ -27,6 +27,7 @@ class DownloadWidget; class MapWidget; class MarkerList; +class RoutingWidget; class MainWidget : public QWidget { @@ -40,12 +41,14 @@ private slots: void markerAdded(const QString &name); void showMap(); void downloadArea(int level, const QRectF &rect); + void findRoute(const QPointF &from, const QPointF &to); private: QStackedWidget *m_stack; MapWidget *m_map; MarkerList *m_markerList; DownloadWidget *m_dlWidget; + RoutingWidget *m_routingWidget; }; diff --git a/mapwidget.cpp b/mapwidget.cpp index 1ef1be7..d1bd3b1 100644 --- a/mapwidget.cpp +++ b/mapwidget.cpp @@ -40,6 +40,8 @@ MapWidget::MapWidget(QWidget *parent) : QWidget(parent), + m_routeStart(), + m_routeEnd(), m_usage(false), m_ui(true), m_zoomable(false), @@ -278,13 +280,25 @@ void MapWidget::keyPressEvent(QKeyEvent *event) m_usage = !m_usage; break; } + case Qt::Key_R: + { + emit route(m_routeStart, m_routeEnd); + break; + } case Qt::Key_S: { if (event->modifiers() == Qt::AltModifier) { m_takeScreenshot = true; + } else if (event->modifiers() == Qt::NoModifier) { + m_routeStart = geoPos(); } break; } + case Qt::Key_E: + { + m_routeEnd = geoPos(); + break; + } case Qt::Key_Q: case Qt::Key_Escape: { @@ -327,6 +341,19 @@ void MapWidget::paintEvent(QPaintEvent *event) } } + painter.save(); + QPoint p = geo2screen(m_routeStart.x(), m_routeStart.y()); + QPolygon tri; + tri << p << p+QPoint(-5, -9) << p+QPoint(5, -9) << p; + painter.setBrush(Qt::red); + painter.drawPolygon(tri); + p = geo2screen(m_routeEnd.x(), m_routeEnd.y()); + tri.clear(); + tri << p << p+QPoint(-5, -9) << p+QPoint(5, -9) << p; + painter.setBrush(Qt::blue); + painter.drawPolygon(tri); + painter.restore(); + QMapIterator i(m_layer); while (i.hasNext()) { i.next(); @@ -337,10 +364,8 @@ void MapWidget::paintEvent(QPaintEvent *event) painter.setBrush(QBrush(QColor(255, 255, 255, 210))); if (m_networkMode) { painter.drawRoundedRect(30, height() - 17, width() - 145, 16, 5, 5); - QPointF geo = geoPos(); - QString lon = geo.x() > 0 ? QString("E %1").arg(geo.x()) : QString("W %1").arg(-geo.x()); - QString lat = geo.y() > 0 ? QString("N %1").arg(geo.y()) : QString("S %1").arg(-geo.y()); - painter.drawText(35, height() - 15, width() - 155, 14, Qt::AlignCenter, lat+" "+lon); + painter.drawText(35, height() - 15, width() - 155, 14, Qt::AlignCenter, + Projection::geo2string(geoPos())); } if (m_zoomable) { painter.drawRoundedRect(5, 10, 20, 220, 10, 10); diff --git a/mapwidget.h b/mapwidget.h index 16a3c90..9157703 100644 --- a/mapwidget.h +++ b/mapwidget.h @@ -47,6 +47,7 @@ public slots: signals: void showMarkerList(); void downloadArea(int level, const QRectF &rect); + void route(const QPointF &from, const QPointF &to); protected: virtual void resizeEvent(QResizeEvent *event); @@ -71,6 +72,7 @@ private: void downloadTile(int x, int y, int level); void changeZoomLevel(int diff); + QPointF m_routeStart, m_routeEnd; bool m_usage, m_ui, m_zoomable; bool m_takeScreenshot; int m_screenshotNumber; diff --git a/nanomap.pro b/nanomap.pro index 7af5a5b..c1df52c 100644 --- a/nanomap.pro +++ b/nanomap.pro @@ -15,6 +15,7 @@ SOURCES += main.cpp \ mapwidget.cpp \ markerlist.cpp \ downloadwidget.cpp \ + routingwidget.cpp \ gpsclient.cpp HEADERS += mainwidget.h \ @@ -28,4 +29,5 @@ HEADERS += mainwidget.h \ mapwidget.h \ markerlist.h \ downloadwidget.h \ + routingwidget.h \ gpsclient.h diff --git a/projection.cpp b/projection.cpp index c982c35..23d34f4 100644 --- a/projection.cpp +++ b/projection.cpp @@ -52,3 +52,10 @@ qreal Projection::tiley2lat(qreal y, int z) return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); } +QString Projection::geo2string(const QPointF &geo) +{ + QString lat = geo.y() > 0 ? QString("N %1").arg(geo.y()) : QString("S %1").arg(-geo.y()); + QString lon = geo.x() > 0 ? QString("E %1").arg(geo.x()) : QString("W %1").arg(-geo.x()); + return lat+" "+lon; +} + diff --git a/projection.h b/projection.h index 79bee69..39528b6 100644 --- a/projection.h +++ b/projection.h @@ -21,6 +21,7 @@ #define PROJECTION_H #include +#include namespace Projection { @@ -30,6 +31,7 @@ namespace Projection qreal lat2tiley(qreal lat, int z); qreal tilex2lon(qreal x, int z); qreal tiley2lat(qreal y, int z); + QString geo2string(const QPointF &geo); }; #endif // PROJECTION_H diff --git a/routingwidget.cpp b/routingwidget.cpp new file mode 100644 index 0000000..aa98e7c --- /dev/null +++ b/routingwidget.cpp @@ -0,0 +1,170 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * 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 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "routingwidget.h" + +#include "projection.h" + +#include +#include +#include +#include +#include +#include +#include + +RoutingWidget::RoutingWidget(QWidget *parent) + : QWidget(parent), + m_name(new QLineEdit("route.gpx", this)), + m_transport(new QComboBox(this)), + m_quickest(new QRadioButton("Quickest", this)), + m_shortest(new QRadioButton("Shortest", this)), + m_routino(), + m_dir(), + m_prefix(), + m_profiles(), + m_swap(), + m_from(), + m_to(), + m_fromLabel(new QLabel(this)), + m_toLabel(new QLabel(this)) +{ + QGridLayout *layout = new QGridLayout(this); + layout->setContentsMargins(5, 5, 5, 5); + layout->setRowStretch(6, 1); + + QLabel *label = new QLabel("From:"); + layout->addWidget(label, 0, 0); + + layout->addWidget(m_fromLabel, 0, 1, 1, 2); + + label = new QLabel("To:"); + layout->addWidget(label, 1, 0); + + layout->addWidget(m_toLabel, 1, 1, 1, 2); + + label = new QLabel("Name:"); + layout->addWidget(label, 2, 0); + + layout->addWidget(m_name, 2, 1, 1, 2); + + label = new QLabel("Transport:"); + layout->addWidget(label, 3, 0); + + m_transport->addItems(QStringList() << "motorcar" << "motorbike" << "bicycle" << "foot"); + layout->addWidget(m_transport, 3, 1, 1, 2); + + label = new QLabel("Route:"); + layout->addWidget(label, 4, 0); + + m_shortest->setChecked(true); + layout->addWidget(m_shortest, 4, 1, 1, 2); + + layout->addWidget(m_quickest, 5, 1, 1, 2); + + QPushButton *back = new QPushButton("&Show map", this); + back->setShortcut(QKeySequence(Qt::ALT + Qt::Key_S)); + layout->addWidget(back, 7, 1); + connect(back, SIGNAL(clicked()), this, SIGNAL(back())); + + QPushButton *find = new QPushButton("&Find route", this); + find->setShortcut(QKeySequence(Qt::ALT + Qt::Key_F)); + layout->addWidget(find, 7, 2); + connect(find, SIGNAL(clicked()), this, SLOT(findRoute())); + + QFile run("/tmp/findroute.sh"); + if (run.open(QFile::WriteOnly)) { + QTextStream out(&run); + out << "#!/bin/sh\n"; + run.close(); + } + run.setPermissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner); + + loadConfig(); + + resize(320, 240); +} + +RoutingWidget::~RoutingWidget() +{ +} + +void RoutingWidget::setFrom(const QPointF &from) +{ + m_from = from; + m_fromLabel->setText(Projection::geo2string(from)); +} + +void RoutingWidget::setTo(const QPointF &to) +{ + m_to = to; + m_toLabel->setText(Projection::geo2string(to)); +} + +void RoutingWidget::findRoute() +{ + QFile run("/tmp/findroute.sh"); + if (run.open(QFile::WriteOnly)) { + QString file; + QString name = m_name->text(); + QString command; + QTextStream out(&run); + out << "#!/bin/sh\n"; + if (!m_swap.isEmpty()) { + out << "swapon "+m_swap+"\n"; + } + command = m_routino; + command.append(QString(" --dir=%1").arg(m_dir)); + command.append(QString(" --prefix=%1").arg(m_prefix)); + command.append(QString(" --profiles=%1").arg(m_profiles)); + command.append(QString(" --lon1=%1 --lat1=%2 --lon2=%3 --lat2=%4") + .arg(m_from.x()).arg(m_from.y()).arg(m_to.x()).arg(m_to.y())); + command.append(" --output-gpx-track"); + if (m_shortest->isChecked()) { + command.append(" --shortest"); + file = "shortest-track.gpx"; + } else { + command.append(" --quickest"); + file = "quickest-track.gpx"; + } + out << command+"\n"; + if (!m_swap.isEmpty()) { + out << "swapon "+m_swap+"\n"; + } + out << QString("mv %1 %2\n").arg(file).arg(name);; + out << QString("exec ./NanoMap.sh %1\n").arg(name); + qApp->quit(); + } +} + +void RoutingWidget::loadConfig() +{ + QSettings set(QDir::homePath()+"/Maps/nanomap.conf", QSettings::NativeFormat); + + set.beginGroup("routino"); + + m_routino = set.value("router", "router").toString(); + m_dir = set.value("dir", ".").toString(); + m_prefix = set.value("prefix", "world").toString(); + m_profiles = set.value("profiles", "/usr/share/routino/routino-profiles.xml").toString(); + m_swap = set.value("swap", "").toString(); + + set.endGroup(); +} + diff --git a/routingwidget.h b/routingwidget.h new file mode 100644 index 0000000..4eaf7da --- /dev/null +++ b/routingwidget.h @@ -0,0 +1,58 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * 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 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef ROUTINGWIDGET_H +#define ROUTINGWIDGET_H + +#include +#include +#include +#include +#include + +class RoutingWidget : public QWidget +{ + Q_OBJECT +public: + RoutingWidget(QWidget *parent = 0); + ~RoutingWidget(); + + void setFrom(const QPointF &from); + void setTo(const QPointF &to); + +signals: + void back(); + +private slots: + void findRoute(); + +private: + void loadConfig(); + + QLineEdit *m_name; + QComboBox *m_transport; + QRadioButton *m_quickest; + QRadioButton *m_shortest; + QString m_routino, m_dir, m_prefix, m_profiles, m_swap; + QPointF m_from, m_to; + QLabel *m_fromLabel, *m_toLabel; + +}; + +#endif // ROUTINGWIDGET_H