File indexing completed on 2023-05-30 09:05:52
0001 // SPDX-FileCopyrightText: 2011 Friedrich W. H. Kossebau <kossebau@kde.org> 0002 // SPDX-License-Identifier: LGPL-2.1-or-later 0003 0004 #include "plasmarunner.h" 0005 0006 // Marble 0007 #include <GeoDataCoordinates.h> 0008 #include <GeoDataFolder.h> 0009 #include <GeoDataLookAt.h> 0010 #include <GeoDataPlacemark.h> 0011 #include <BookmarkManager.h> 0012 #include <GeoDataTreeModel.h> 0013 0014 // KF 0015 #include <KLocalizedString> 0016 0017 // Qt 0018 #include <QProcess> 0019 0020 0021 #define TRANSLATION_DOMAIN "plasma_runner_marble" 0022 0023 namespace Marble 0024 { 0025 0026 static const int minContainsMatchLength = 3; 0027 0028 #if KRUNNER_VERSION >= QT_VERSION_CHECK(5, 77, 0) 0029 PlasmaRunner::PlasmaRunner(QObject *parent, const KPluginMetaData &pluginMetaData, const QVariantList &args) 0030 : AbstractRunner(parent, pluginMetaData, args) 0031 #else 0032 PlasmaRunner::PlasmaRunner(QObject *parent, const QVariantList &args) 0033 : AbstractRunner(parent, args) 0034 #endif 0035 { 0036 addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Shows the coordinates :q: in OpenStreetMap with Marble."))); 0037 addSyntax(Plasma::RunnerSyntax(QStringLiteral(":q:"), i18n("Shows the geo bookmark containing :q: in OpenStreetMap with Marble."))); 0038 } 0039 0040 void PlasmaRunner::match(Plasma::RunnerContext &context) 0041 { 0042 QList<Plasma::QueryMatch> matches; 0043 0044 const QString query = context.query(); 0045 0046 bool success = false; 0047 // TODO: how to estimate that input is in Degree, not Radian? 0048 GeoDataCoordinates coordinates = GeoDataCoordinates::fromString(query, success); 0049 0050 if (success) { 0051 const QVariant coordinatesData = QVariantList() 0052 << QVariant(coordinates.longitude(GeoDataCoordinates::Degree)) 0053 << QVariant(coordinates.latitude(GeoDataCoordinates::Degree)) 0054 << QVariant(0.1); // TODO: make this distance value configurable 0055 0056 Plasma::QueryMatch match(this); 0057 match.setIcon(QIcon::fromTheme(QStringLiteral("marble"))); 0058 match.setText(i18n("Show the coordinates %1 in OpenStreetMap with Marble", query)); 0059 match.setData(coordinatesData); 0060 match.setId(query); 0061 match.setRelevance(1.0); 0062 match.setType(Plasma::QueryMatch::ExactMatch); 0063 0064 matches << match; 0065 } 0066 0067 // TODO: BookmarkManager does not yet listen to updates, also does not sync between processes :( 0068 // So for now always load on demand, even if expensive possibly 0069 BookmarkManager bookmarkManager(new GeoDataTreeModel); 0070 bookmarkManager.loadFile( QStringLiteral("bookmarks/bookmarks.kml") ); 0071 0072 for (GeoDataFolder* folder: bookmarkManager.folders()) { 0073 collectMatches(matches, query, folder); 0074 } 0075 0076 if ( ! matches.isEmpty() ) { 0077 context.addMatches(matches); 0078 } 0079 } 0080 0081 void PlasmaRunner::collectMatches(QList<Plasma::QueryMatch> &matches, 0082 const QString &query, const GeoDataFolder *folder) 0083 { 0084 const QString queryLower = query.toLower(); 0085 0086 QVector<GeoDataFeature*>::const_iterator it = folder->constBegin(); 0087 QVector<GeoDataFeature*>::const_iterator end = folder->constEnd(); 0088 0089 for (; it != end; ++it) { 0090 GeoDataFolder *folder = dynamic_cast<GeoDataFolder*>(*it); 0091 if ( folder ) { 0092 collectMatches(matches, query, folder); 0093 continue; 0094 } 0095 0096 GeoDataPlacemark *placemark = dynamic_cast<GeoDataPlacemark*>( *it ); 0097 if ( placemark ) { 0098 // For short query strings only match exactly, to get a sane number of matches 0099 if (query.length() < minContainsMatchLength) { 0100 if ( placemark->name().toLower() != queryLower && 0101 ( placemark->descriptionIsCDATA() || // TODO: support also with CDATA 0102 placemark->description().toLower() != queryLower ) ) { 0103 continue; 0104 } 0105 } else { 0106 if ( ! placemark->name().toLower().contains(queryLower) && 0107 ( placemark->descriptionIsCDATA() || // TODO: support also with CDATA 0108 ! placemark->description().toLower().contains(queryLower) ) ) { 0109 continue; 0110 } 0111 } 0112 0113 const GeoDataCoordinates coordinates = placemark->coordinate(); 0114 const qreal lon = coordinates.longitude(GeoDataCoordinates::Degree); 0115 const qreal lat = coordinates.latitude(GeoDataCoordinates::Degree); 0116 const QVariant coordinatesData = QVariantList() 0117 << QVariant(lon) 0118 << QVariant(lat) 0119 << QVariant(placemark->lookAt()->range()*METER2KM); 0120 0121 Plasma::QueryMatch match(this); 0122 match.setIcon(QIcon::fromTheme(QStringLiteral("marble"))); 0123 match.setText(placemark->name()); 0124 match.setSubtext(i18n("Show in OpenStreetMap with Marble")); 0125 match.setData(coordinatesData); 0126 match.setId(placemark->name()+QString::number(lat)+QString::number(lon)); 0127 match.setRelevance(1.0); 0128 match.setType(Plasma::QueryMatch::ExactMatch); 0129 0130 matches << match; 0131 } 0132 } 0133 } 0134 0135 void PlasmaRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match) 0136 { 0137 Q_UNUSED(context) 0138 0139 const QVariantList data = match.data().toList(); 0140 0141 // pass in C locale, should be always understood 0142 const QString latLon = 0143 QString::number(data.at(1).toReal()) + QLatin1Char(' ') + QString::number(data.at(0).toReal()); 0144 0145 const QString distance = data.at(2).toString(); 0146 0147 const QStringList parameters = QStringList() 0148 << QStringLiteral( "--latlon" ) 0149 << latLon 0150 << QStringLiteral( "--distance" ) 0151 << distance 0152 << QStringLiteral( "--map" ) 0153 << QStringLiteral( "earth/openstreetmap/openstreetmap.dgml" ); 0154 QProcess::startDetached( QStringLiteral("marble"), parameters ); 0155 } 0156 0157 }