1 /*
2     SPDX-FileCopyrightText: 2009 Petri Damsten <damu@iki.fi>
3 
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "geolocation.h"
8 
9 #include <limits.h>
10 
11 #include <KPluginMetaData>
12 #include <NetworkManagerQt/Manager>
13 #include <QDebug>
14 #include <QNetworkConfigurationManager>
15 
16 static const char SOURCE[] = "location";
17 
Geolocation(QObject * parent,const QVariantList & args)18 Geolocation::Geolocation(QObject *parent, const QVariantList &args)
19     : Plasma::DataEngine(parent, args)
20 {
21     setMinimumPollingInterval(500);
22     connect(NetworkManager::notifier(), &NetworkManager::Notifier::networkingEnabledChanged, this, &Geolocation::networkStatusChanged);
23     connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessEnabledChanged, this, &Geolocation::networkStatusChanged);
24     m_updateTimer.setInterval(100);
25     m_updateTimer.setSingleShot(true);
26     connect(&m_updateTimer, &QTimer::timeout, this, &Geolocation::actuallySetData);
27     m_networkChangedTimer.setInterval(100);
28     m_networkChangedTimer.setSingleShot(true);
29     connect(&m_networkChangedTimer, &QTimer::timeout, this, [this] {
30         updatePlugins(GeolocationProvider::NetworkConnected);
31     });
32     init();
33 }
34 
init()35 void Geolocation::init()
36 {
37     // TODO: should this be delayed even further, e.g. when the source is requested?
38     const QVector<KPluginMetaData> offers = KPluginMetaData::findPlugins("plasma/geolocationprovider");
39     for (const auto &metaData : offers) {
40         auto result = KPluginFactory::instantiatePlugin<GeolocationProvider>(metaData, this);
41         if (result) {
42             GeolocationProvider *plugin = result.plugin;
43             m_plugins << plugin;
44             plugin->init(&m_data, &m_accuracy);
45             connect(plugin, &GeolocationProvider::updated, this, &Geolocation::pluginUpdated);
46             connect(plugin, &GeolocationProvider::availabilityChanged, this, &Geolocation::pluginAvailabilityChanged);
47         } else {
48             qDebug() << "Failed to load GeolocationProvider:" << metaData.fileName() << result.errorString;
49         }
50     }
51 }
52 
~Geolocation()53 Geolocation::~Geolocation()
54 {
55     qDeleteAll(m_plugins);
56 }
57 
sources() const58 QStringList Geolocation::sources() const
59 {
60     return QStringList() << SOURCE;
61 }
62 
updateSourceEvent(const QString & name)63 bool Geolocation::updateSourceEvent(const QString &name)
64 {
65     // qDebug() << name;
66     if (name == SOURCE) {
67         return updatePlugins(GeolocationProvider::SourceEvent);
68     }
69 
70     return false;
71 }
72 
updatePlugins(GeolocationProvider::UpdateTriggers triggers)73 bool Geolocation::updatePlugins(GeolocationProvider::UpdateTriggers triggers)
74 {
75     bool changed = false;
76 
77     for (GeolocationProvider *plugin : qAsConst(m_plugins)) {
78         changed = plugin->requestUpdate(triggers) || changed;
79     }
80 
81     if (changed) {
82         m_updateTimer.start();
83     }
84 
85     return changed;
86 }
87 
sourceRequestEvent(const QString & name)88 bool Geolocation::sourceRequestEvent(const QString &name)
89 {
90     qDebug() << name;
91     if (name == SOURCE) {
92         updatePlugins(GeolocationProvider::ForcedUpdate);
93         setData(SOURCE, m_data);
94         return true;
95     }
96 
97     return false;
98 }
99 
networkStatusChanged(bool isOnline)100 void Geolocation::networkStatusChanged(bool isOnline)
101 {
102     qDebug() << "network status changed";
103     if (isOnline) {
104         m_networkChangedTimer.start();
105     }
106 }
107 
pluginAvailabilityChanged(GeolocationProvider * provider)108 void Geolocation::pluginAvailabilityChanged(GeolocationProvider *provider)
109 {
110     m_data.clear();
111     m_accuracy.clear();
112 
113     provider->requestUpdate(GeolocationProvider::ForcedUpdate);
114 
115     bool changed = false;
116     for (GeolocationProvider *plugin : qAsConst(m_plugins)) {
117         changed = plugin->populateSharedData() || changed;
118     }
119 
120     if (changed) {
121         m_updateTimer.start();
122     }
123 }
124 
pluginUpdated()125 void Geolocation::pluginUpdated()
126 {
127     m_updateTimer.start();
128 }
129 
actuallySetData()130 void Geolocation::actuallySetData()
131 {
132     setData(SOURCE, m_data);
133 }
134 
135 K_PLUGIN_CLASS_WITH_JSON(Geolocation, "plasma-dataengine-geolocation.json")
136 
137 #include "geolocation.moc"
138