Marble

ReverseGeocodingRunnerManager.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2008 Henry de Valence <hdevalence@gmail.com>
4// SPDX-FileCopyrightText: 2010 Dennis Nienhüser <nienhueser@kde.org>
5// SPDX-FileCopyrightText: 2010-2013 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
6// SPDX-FileCopyrightText: 2011 Thibaut Gridel <tgridel@free.fr>
7
8#include "ReverseGeocodingRunnerManager.h"
9
10#include "GeoDataCoordinates.h"
11#include "GeoDataPlacemark.h"
12#include "MarbleDebug.h"
13#include "MarbleModel.h"
14#include "Planet.h"
15#include "PluginManager.h"
16#include "ReverseGeocodingRunnerPlugin.h"
17#include "RunnerTask.h"
18
19#include <QList>
20#include <QThreadPool>
21#include <QTimer>
22
23namespace Marble
24{
25
26class MarbleModel;
27
28class Q_DECL_HIDDEN ReverseGeocodingRunnerManager::Private
29{
30public:
31 Private(ReverseGeocodingRunnerManager *parent, const MarbleModel *marbleModel);
32
34
35 void addReverseGeocodingResult(const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark);
36 void cleanupReverseGeocodingTask(ReverseGeocodingTask *task);
37
38 ReverseGeocodingRunnerManager *const q;
39 const MarbleModel *const m_marbleModel;
40 const PluginManager *m_pluginManager;
41 QList<ReverseGeocodingTask *> m_reverseTasks;
42 QList<GeoDataCoordinates> m_reverseGeocodingResults;
43 QString m_reverseGeocodingResult;
44};
45
46ReverseGeocodingRunnerManager::Private::Private(ReverseGeocodingRunnerManager *parent, const MarbleModel *marbleModel)
47 : q(parent)
48 , m_marbleModel(marbleModel)
49 , m_pluginManager(marbleModel->pluginManager())
50{
51 qRegisterMetaType<GeoDataPlacemark>("GeoDataPlacemark");
52 qRegisterMetaType<GeoDataCoordinates>("GeoDataCoordinates");
53}
54
55QList<const ReverseGeocodingRunnerPlugin *> ReverseGeocodingRunnerManager::Private::plugins(const QList<const ReverseGeocodingRunnerPlugin *> &plugins) const
56{
58
59 for (const ReverseGeocodingRunnerPlugin *plugin : plugins) {
60 if ((m_marbleModel && m_marbleModel->workOffline() && !plugin->canWorkOffline())) {
61 continue;
62 }
63
64 if (!plugin->canWork()) {
65 continue;
66 }
67
68 if (m_marbleModel && !plugin->supportsCelestialBody(m_marbleModel->planet()->id())) {
69 continue;
70 }
71
72 result << plugin;
73 }
74
75 return result;
76}
77
78void ReverseGeocodingRunnerManager::Private::addReverseGeocodingResult(const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark)
79{
80 if (!m_reverseGeocodingResults.contains(coordinates) && !placemark.address().isEmpty()) {
81 m_reverseGeocodingResults.push_back(coordinates);
82 m_reverseGeocodingResult = placemark.address();
83 Q_EMIT q->reverseGeocodingFinished(coordinates, placemark);
84 }
85
86 if (m_reverseTasks.isEmpty()) {
87 Q_EMIT q->reverseGeocodingFinished();
88 }
89}
90
91void ReverseGeocodingRunnerManager::Private::cleanupReverseGeocodingTask(ReverseGeocodingTask *task)
92{
93 m_reverseTasks.removeAll(task);
94 mDebug() << "removing task " << m_reverseTasks.size() << " " << (quintptr)task;
95 if (m_reverseTasks.isEmpty()) {
96 Q_EMIT q->reverseGeocodingFinished();
97 }
98}
99
100ReverseGeocodingRunnerManager::ReverseGeocodingRunnerManager(const MarbleModel *marbleModel, QObject *parent)
101 : QObject(parent)
102 , d(new Private(this, marbleModel))
103{
104 if (QThreadPool::globalInstance()->maxThreadCount() < 4) {
106 }
107}
108
109ReverseGeocodingRunnerManager::~ReverseGeocodingRunnerManager()
110{
111 delete d;
112}
113
114void ReverseGeocodingRunnerManager::reverseGeocoding(const GeoDataCoordinates &coordinates)
115{
116 d->m_reverseTasks.clear();
117 d->m_reverseGeocodingResult.clear();
118 d->m_reverseGeocodingResults.removeAll(coordinates);
119
120 QList<const ReverseGeocodingRunnerPlugin *> plugins = d->plugins(d->m_pluginManager->reverseGeocodingRunnerPlugins());
121 for (const ReverseGeocodingRunnerPlugin *plugin : std::as_const(plugins)) {
122 auto task = new ReverseGeocodingTask(plugin->newRunner(), this, d->m_marbleModel, coordinates);
123 connect(task, SIGNAL(finished(ReverseGeocodingTask *)), this, SLOT(cleanupReverseGeocodingTask(ReverseGeocodingTask *)));
124 mDebug() << "reverse task " << plugin->nameId() << " " << (quintptr)task;
125 d->m_reverseTasks << task;
126 }
127
128 for (ReverseGeocodingTask *task : std::as_const(d->m_reverseTasks)) {
130 }
131
132 if (plugins.isEmpty()) {
133 GeoDataPlacemark anonymous;
134 anonymous.setCoordinate(coordinates);
135 Q_EMIT reverseGeocodingFinished(coordinates, anonymous);
136 d->cleanupReverseGeocodingTask(nullptr);
137 }
138}
139
140QString ReverseGeocodingRunnerManager::searchReverseGeocoding(const GeoDataCoordinates &coordinates, int timeout)
141{
142 QEventLoop localEventLoop;
143 QTimer watchdog;
144 watchdog.setSingleShot(true);
145 connect(&watchdog, &QTimer::timeout, &localEventLoop, &QEventLoop::quit);
146 connect(this, SIGNAL(reverseGeocodingFinished()), &localEventLoop, SLOT(quit()), Qt::QueuedConnection);
147
148 watchdog.start(timeout);
149 reverseGeocoding(coordinates);
150 localEventLoop.exec();
151 return d->m_reverseGeocodingResult;
152}
153
154}
155
156#include "moc_ReverseGeocodingRunnerManager.cpp"
This file contains the headers for MarbleModel.
KGuiItem quit()
Binds a QML item to a specific geodetic location in screen coordinates.
int exec(ProcessEventsFlags flags)
void quit()
bool isEmpty() const const
qsizetype removeAll(const AT &t)
QueuedConnection
QTaskBuilder< Task > task(Task &&task)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QThreadPool * globalInstance()
void setMaxThreadCount(int maxThreadCount)
void start(Callable &&callableToRun, int priority)
void setSingleShot(bool singleShot)
void start()
void timeout()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 8 2024 12:02:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.