diff --git a/src/plugins/runner/yours/CMakeLists.txt b/src/plugins/runner/yours/CMakeLists.txt index 437269deb..95b86a8a5 100644 --- a/src/plugins/runner/yours/CMakeLists.txt +++ b/src/plugins/runner/yours/CMakeLists.txt @@ -1,10 +1,14 @@ PROJECT( YoursPlugin ) INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) set( yours_SRCS YoursRunner.cpp YoursPlugin.cpp ) +set( yours_UI YoursConfigWidget.ui ) + +qt_wrap_ui( yours_SRCS ${yours_UI} ) + marble_add_plugin( YoursPlugin ${yours_SRCS} ) diff --git a/src/plugins/runner/yours/YoursConfigWidget.ui b/src/plugins/runner/yours/YoursConfigWidget.ui new file mode 100644 index 000000000..3ef4ad976 --- /dev/null +++ b/src/plugins/runner/yours/YoursConfigWidget.ui @@ -0,0 +1,51 @@ + + + YoursConfigWidget + + + + 0 + 0 + 273 + 196 + + + + + + + Transport: + + + + + + + + + + Method + + + + + + Fastest + + + + + + + Shortest + + + + + + + + + + + diff --git a/src/plugins/runner/yours/YoursPlugin.cpp b/src/plugins/runner/yours/YoursPlugin.cpp index bddd07066..d6ade0b33 100644 --- a/src/plugins/runner/yours/YoursPlugin.cpp +++ b/src/plugins/runner/yours/YoursPlugin.cpp @@ -1,73 +1,167 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2010 Dennis Nienhüser +// Copyright 2016 Piotr Wójcik // #include "YoursPlugin.h" #include "YoursRunner.h" +#include "ui_YoursConfigWidget.h" + namespace Marble { YoursPlugin::YoursPlugin( QObject *parent ) : RoutingRunnerPlugin( parent ) { setSupportedCelestialBodies(QStringList(QStringLiteral("earth"))); setCanWorkOffline( false ); setStatusMessage( tr ( "This service requires an Internet connection." ) ); } QString YoursPlugin::name() const { return tr( "Yours Routing" ); } QString YoursPlugin::guiString() const { return tr( "Yours" ); } QString YoursPlugin::nameId() const { return QStringLiteral("yours"); } QString YoursPlugin::version() const { - return QStringLiteral("1.0"); + return QStringLiteral("1.1"); } QString YoursPlugin::description() const { return tr( "Worldwide routing using a YOURS server" ); } QString YoursPlugin::copyrightYears() const { - return QStringLiteral("2010"); + return QStringLiteral("2010, 2016"); } QVector YoursPlugin::pluginAuthors() const { return QVector() - << PluginAuthor(QStringLiteral("Dennis Nienhüser"), QStringLiteral("nienhueser@kde.org")); + << PluginAuthor(QStringLiteral("Dennis Nienhüser"), QStringLiteral("nienhueser@kde.org")) + << PluginAuthor(QStringLiteral("Piotr Wójcik"), QStringLiteral("chocimier@tlen.pl")); } RoutingRunner *YoursPlugin::newRunner() const { return new YoursRunner; } +class YoursConfigWidget : public RoutingRunnerPlugin::ConfigWidget +{ +public: + YoursConfigWidget() + : RoutingRunnerPlugin::ConfigWidget() + { + ui_configWidget = new Ui::YoursConfigWidget; + ui_configWidget->setupUi( this ); + //TODO: read from profiles.xml + ui_configWidget->transport->addItem( tr( "Foot" ), "foot" ); + ui_configWidget->transport->addItem( tr( "Bicycle" ), "bicycle" ); + ui_configWidget->transport->addItem( tr( "Motorcar" ), "motorcar" ); + } + virtual ~YoursConfigWidget() + { + delete ui_configWidget; + } + virtual void loadSettings( const QHash &settings_ ) + { + QHash settings = settings_; + + // Check if all fields are filled and fill them with default values. + if (!settings.contains(QStringLiteral("transport"))) { + settings.insert(QStringLiteral("transport"), QStringLiteral("motorcar")); + } + ui_configWidget->transport->setCurrentIndex( + ui_configWidget->transport->findData(settings.value(QStringLiteral("transport")).toString())); + if (settings.value(QStringLiteral("method")).toString() == QLatin1String("shortest")) { + ui_configWidget->shortest->setChecked( true ); + } else { + ui_configWidget->fastest->setChecked( true ); + } + } + + virtual QHash settings() const + { + QHash settings; + settings.insert(QStringLiteral("transport"), + ui_configWidget->transport->itemData( ui_configWidget->transport->currentIndex() ) ); + + if ( ui_configWidget->shortest->isChecked() ) { + settings.insert(QStringLiteral("method"), QStringLiteral("shortest")); + } else { + settings.insert(QStringLiteral("method"), QStringLiteral("fastest")); + } + return settings; + } +private: + Ui::YoursConfigWidget *ui_configWidget; +}; + +RoutingRunnerPlugin::ConfigWidget *YoursPlugin::configWidget() +{ + return new YoursConfigWidget(); +} + bool YoursPlugin::supportsTemplate( RoutingProfilesModel::ProfileTemplate profileTemplate ) const { - return profileTemplate == RoutingProfilesModel::CarFastestTemplate; + QSet availableTemplates; + availableTemplates.insert( RoutingProfilesModel::CarFastestTemplate ); + availableTemplates.insert( RoutingProfilesModel::CarShortestTemplate ); + availableTemplates.insert( RoutingProfilesModel::BicycleTemplate ); + availableTemplates.insert( RoutingProfilesModel::PedestrianTemplate ); + return availableTemplates.contains( profileTemplate ); +} + +QHash< QString, QVariant > YoursPlugin::templateSettings(RoutingProfilesModel::ProfileTemplate profileTemplate) const +{ + QHash result; + switch ( profileTemplate ) { + case RoutingProfilesModel::CarFastestTemplate: + result.insert(QStringLiteral("transport"), QStringLiteral("motorcar")); + result.insert(QStringLiteral("method"), QStringLiteral("fastest")); + break; + case RoutingProfilesModel::CarShortestTemplate: + result.insert(QStringLiteral("transport"), QStringLiteral("motorcar")); + result.insert(QStringLiteral("method"), QStringLiteral("shortest")); + break; + case RoutingProfilesModel::CarEcologicalTemplate: + break; + case RoutingProfilesModel::BicycleTemplate: + result.insert(QStringLiteral("transport"), QStringLiteral("bicycle")); + result.insert(QStringLiteral("method"), QStringLiteral("shortest")); + break; + case RoutingProfilesModel::PedestrianTemplate: + result.insert(QStringLiteral("transport"), QStringLiteral("foot")); + result.insert(QStringLiteral("method"), QStringLiteral("shortest")); + break; + case RoutingProfilesModel::LastTemplate: + Q_ASSERT( false ); + break; + } + return result; } } #include "moc_YoursPlugin.cpp" diff --git a/src/plugins/runner/yours/YoursPlugin.h b/src/plugins/runner/yours/YoursPlugin.h index 348cf8e56..31f0669ca 100644 --- a/src/plugins/runner/yours/YoursPlugin.h +++ b/src/plugins/runner/yours/YoursPlugin.h @@ -1,50 +1,55 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2010 Dennis Nienhüser +// Copyright 2016 Piotr Wójcik // #ifndef MARBLE_YOURSPLUGIN_H #define MARBLE_YOURSPLUGIN_H #include "RoutingRunnerPlugin.h" namespace Marble { class YoursPlugin : public RoutingRunnerPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.kde.marble.YoursPlugin") Q_INTERFACES( Marble::RoutingRunnerPlugin ) public: explicit YoursPlugin( QObject *parent = 0 ); QString name() const; QString guiString() const; QString nameId() const; QString version() const; QString description() const; QString copyrightYears() const; QVector pluginAuthors() const override; virtual RoutingRunner *newRunner() const; + ConfigWidget* configWidget(); + virtual bool supportsTemplate(RoutingProfilesModel::ProfileTemplate profileTemplate) const; + + QHash< QString, QVariant > templateSettings(RoutingProfilesModel::ProfileTemplate profileTemplate) const; }; } #endif diff --git a/src/plugins/runner/yours/YoursRunner.cpp b/src/plugins/runner/yours/YoursRunner.cpp index 0b5d5ce02..0cce29b4c 100644 --- a/src/plugins/runner/yours/YoursRunner.cpp +++ b/src/plugins/runner/yours/YoursRunner.cpp @@ -1,162 +1,176 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2010 Dennis Nienhüser +// Copyright 2016 Piotr Wójcik // #include "YoursRunner.h" #include "MarbleDebug.h" #include "MarbleLocale.h" #include "GeoDataDocument.h" #include "GeoDataPlacemark.h" #include "GeoDataParser.h" #include "GeoDataFolder.h" #include "GeoDataLineString.h" #include "routing/RouteRequest.h" #include #include #include #include #include #include namespace Marble { YoursRunner::YoursRunner( QObject *parent ) : RoutingRunner( parent ), m_networkAccessManager() { connect( &m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(retrieveData(QNetworkReply*)) ); } YoursRunner::~YoursRunner() { // nothing to do } void YoursRunner::retrieveRoute( const RouteRequest *route ) { if ( route->size() != 2 ) { return; } GeoDataCoordinates source = route->source(); GeoDataCoordinates destination = route->destination(); double fLon = source.longitude( GeoDataCoordinates::Degree ); double fLat = source.latitude( GeoDataCoordinates::Degree ); double tLon = destination.longitude( GeoDataCoordinates::Degree ); double tLat = destination.latitude( GeoDataCoordinates::Degree ); QString base = "http://www.yournavigation.org/api/1.0/gosmore.php"; //QString base = "http://nroets.dev.openstreetmap.org/demo/gosmore.php"; QString args = "?flat=%1&flon=%2&tlat=%3&tlon=%4"; args = args.arg( fLat, 0, 'f', 6 ).arg( fLon, 0, 'f', 6 ).arg( tLat, 0, 'f', 6 ).arg( tLon, 0, 'f', 6 ); - QString preferences = "&v=motorcar&fast=1&layer=mapnik"; + + QHash settings = route->routingProfile().pluginSettings()[QStringLiteral("yours")]; + QString transport = settings[QStringLiteral("transport")].toString(); + QString fast; + + if (settings[QStringLiteral("method")] == QLatin1String("shortest")) { + fast = "0"; + } else { + fast = "1"; + } + + QString preferences = "&v=%1&fast=%2&layer=mapnik;"; + preferences = preferences.arg(transport).arg(fast); QString request = base + args + preferences; // mDebug() << "GET: " << request; m_request = QNetworkRequest( QUrl( request ) ); + m_request.setRawHeader( "X-Yours-client", "Marble" ); QEventLoop eventLoop; QTimer timer; timer.setSingleShot( true ); timer.setInterval( 15000 ); connect( &timer, SIGNAL(timeout()), &eventLoop, SLOT(quit())); connect( this, SIGNAL(routeCalculated(GeoDataDocument*)), &eventLoop, SLOT(quit()) ); // @todo FIXME Must currently be done in the main thread, see bug 257376 QTimer::singleShot( 0, this, SLOT(get()) ); timer.start(); eventLoop.exec(); } void YoursRunner::get() { QNetworkReply *reply = m_networkAccessManager.get( m_request ); connect( reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleError(QNetworkReply::NetworkError)) ); } void YoursRunner::retrieveData( QNetworkReply *reply ) { if ( reply->isFinished() ) { QByteArray data = reply->readAll(); reply->deleteLater(); //mDebug() << "Download completed: " << data; GeoDataDocument* result = parse( data ); if ( result ) { QString name = "%1 %2 (Yours)"; QString unit = QLatin1String( "m" ); qreal length = distance( result ); if ( length == 0.0 ) { delete result; emit routeCalculated( 0 ); return; } else if ( length >= 1000 ) { length /= 1000.0; unit = "km"; } result->setName( name.arg( length, 0, 'f', 1 ).arg( unit ) ); } emit routeCalculated( result ); } } void YoursRunner::handleError( QNetworkReply::NetworkError error ) { mDebug() << " Error when retrieving yournavigation.org route: " << error; emit routeCalculated( 0 ); } GeoDataDocument* YoursRunner::parse( const QByteArray &content ) { GeoDataParser parser( GeoData_UNKNOWN ); // Open file in right mode QBuffer buffer; buffer.setData( content ); buffer.open( QIODevice::ReadOnly ); if ( !parser.read( &buffer ) ) { mDebug() << "Cannot parse kml data! Input is " << content ; return 0; } GeoDataDocument* document = static_cast( parser.releaseDocument() ); return document; } qreal YoursRunner::distance( const GeoDataDocument* document ) { QVector folders = document->folderList(); foreach( const GeoDataFolder *folder, folders ) { foreach( const GeoDataPlacemark *placemark, folder->placemarkList() ) { const GeoDataGeometry* geometry = placemark->geometry(); if ( geometry->geometryId() == GeoDataLineStringId ) { const GeoDataLineString* lineString = dynamic_cast( geometry ); Q_ASSERT( lineString && "Internal error: geometry ID does not match class type" ); return lineString->length( EARTH_RADIUS ); } } } return 0.0; } } // namespace Marble #include "moc_YoursRunner.cpp" diff --git a/src/plugins/runner/yours/YoursRunner.h b/src/plugins/runner/yours/YoursRunner.h index 847fa77c6..35fda2fce 100644 --- a/src/plugins/runner/yours/YoursRunner.h +++ b/src/plugins/runner/yours/YoursRunner.h @@ -1,56 +1,57 @@ // // This file is part of the Marble Virtual Globe. // // This program is free software licensed under the GNU LGPL. You can // find a copy of this license in LICENSE.txt in the top directory of // the source code. // // Copyright 2010 Dennis Nienhüser +// Copyright 2016 Piotr Wójcik // #ifndef MARBLE_YOURSRUNNER_H #define MARBLE_YOURSRUNNER_H #include "RoutingRunner.h" #include #include namespace Marble { class YoursRunner : public RoutingRunner { Q_OBJECT public: explicit YoursRunner( QObject *parent = 0 ); ~YoursRunner(); // Overriding MarbleAbstractRunner virtual void retrieveRoute( const RouteRequest *request ); private Q_SLOTS: /** Route data was retrieved via http */ void retrieveData( QNetworkReply *reply ); /** A network error occurred */ void handleError( QNetworkReply::NetworkError ); void get(); private: static GeoDataDocument* parse( const QByteArray &input ); static qreal distance( const GeoDataDocument* document ); QNetworkAccessManager m_networkAccessManager; QNetworkRequest m_request; }; } #endif