[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-panel-devel
Subject:    Re: Review Request: Add city and country resolution to GPS
From:       Petri =?utf-8?q?Damst=C3=A9n?= <petri.damsten () gmail ! com>
Date:       2010-01-27 10:17:48
Message-ID: 201001271218.01290.petri.damsten () gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/signed)]

[Attachment #4 (multipart/mixed)]


On Sunday 24 January 2010 17:18:49 Beat Wolf wrote:
> > On 2009-04-14 18:59:59, Aaron Seigo wrote:
> > > other than a couple of code style comments, and that i can't test it
> > > with a gps for you either :/, my only question/concern is that it's
> > > doing look ups on the internet without checking to see if we're
> > > connected. it could be in a local cache, but i'm going to guess that
> > > in a fairly typical "i'm using gps" scenario one won't have an
> > > internet connection as well. should we query solid for network status?
> > > 
> > > rambling off-topic here: i also wonder if we aren't going to want some
> > > "can use the internet for ..." settings somewhere for the case where
> > > we have a system with gps, cheap wifi and expensive g3 connectivity ..
> > > somethings, like looking up the place name on the internet, may not be
> > > acceptible even if there is g3 service? not a use case we actually
> > > have to deal with now, but it's something that pops into my head every
> > > once in a while .. .. like when i see a patch like this :)
> > 
> > Petri Damstén wrote:
> >     Dataengine already checks network state but since it thinks gps does
> >     not need one it uses gps plugin. I think location -> place should be
> >     a separate plugin. It's not possible with current code though and I
> >     would like to evaluate all the other possibilities before doing
> >     rewrite (there were some wlan etc ideas as well). For 4.3 should it
> >     go like this, I'm not sure?
> >     
> >     For 4.4 is geoclue out of the question? It seems that we are
> >     implementing pretty much all the same things.
> 
> any progress on this patch?

Attached is this patch converted to separate plugin. Tries to also fix plugins 
marked as NetworkConnected only to not to update when there is no network.

Petri

["geolocation_name.diff" (text/x-patch)]

Index: location_ip.cpp
===================================================================
--- location_ip.cpp	(revision 1080874)
+++ location_ip.cpp	(working copy)
@@ -61,7 +61,6 @@
 
         // ordering of first three to preserve backwards compatibility
 
-        outd["accuracy"] = 40000;
         outd["country"] = country;
         outd["country code"] = countryCode;
         outd["city"] = city;
@@ -75,7 +74,8 @@
 Ip::Ip(QObject* parent, const QVariantList& args)
     : GeolocationProvider(parent, args), d(new Private())
 {
-    setUpdateTriggers(SourceEvent | NetworkConnected);
+    setUpdateTriggers(NetworkConnected);
+    setAccuracy(40000);
 }
 
 Ip::~Ip()
Index: geolocation.cpp
===================================================================
--- geolocation.cpp	(revision 1080874)
+++ geolocation.cpp	(working copy)
@@ -26,7 +26,7 @@
 
 Geolocation::Geolocation(QObject* parent, const QVariantList& args)
     : Plasma::DataEngine(parent, args),
-      m_networkStatus(false)
+      m_networkUp(false)
 {
     Q_UNUSED(args)
     setMinimumPollingInterval(500);
@@ -39,7 +39,12 @@
 
 void Geolocation::init()
 {
-    m_networkStatus = Solid::Networking::status();
+    int networkStatus = Solid::Networking::status();
+    if (networkStatus == Solid::Networking::Connected || networkStatus == \
Solid::Networking::Unknown) { +        m_networkUp = true;
+    } else {
+        m_networkUp = false;
+    }
 
     //TODO: should this be delayed even further, e.g. when the source is requested?
     const KService::List offers = \
KServiceTypeTrader::self()->query("Plasma/GeolocationProvider"); @@ -85,7 +90,7 @@
     bool changed = false;
 
     foreach (GeolocationProvider *plugin, m_plugins) {
-        changed = plugin->requestUpdate(triggers) || changed;
+        changed = plugin->requestUpdate(triggers, m_networkUp) || changed;
     }
 
     if (changed) {
@@ -97,7 +102,6 @@
 
 bool Geolocation::sourceRequestEvent(const QString &name)
 {
-    kDebug() << name;
     if (name == SOURCE) {
         updatePlugins(GeolocationProvider::ForcedUpdate);
         setData(SOURCE, m_data);
@@ -109,9 +113,12 @@
 
 void Geolocation::networkStatusChanged()
 {
-    m_networkStatus = Solid::Networking::status();
-    if (m_networkStatus == Solid::Networking::Connected || m_networkStatus == \
Solid::Networking::Unknown) { +    int networkStatus = Solid::Networking::status();
+    if (networkStatus == Solid::Networking::Connected || networkStatus == \
Solid::Networking::Unknown) { +        m_networkUp = true;
         updatePlugins(GeolocationProvider::NetworkConnected);
+    } else {
+        m_networkUp = false;
     }
 }
 
@@ -120,7 +127,7 @@
     m_data.clear();
     m_accuracy.clear();
 
-    provider->requestUpdate(GeolocationProvider::ForcedUpdate);
+    provider->requestUpdate(GeolocationProvider::ForcedUpdate, m_networkUp);
 
     bool changed = false;
     foreach (GeolocationProvider *plugin, m_plugins) {
@@ -139,6 +146,12 @@
 
 void Geolocation::actuallySetData()
 {
+    if (m_latitude != m_data["latitude"].toString() ||
+        m_longitude != m_data["longitude"].toString()) {
+        m_latitude = m_data["latitude"].toString();
+        m_longitude = m_data["longitude"].toString();
+        updatePlugins(GeolocationProvider::CoordinatesChanged);
+    }
     setData(SOURCE, m_data);
 }
 
Index: location_name.cpp
===================================================================
--- location_name.cpp	(revision 0)
+++ location_name.cpp	(revision 0)
@@ -0,0 +1,171 @@
+/*
+ *   Copyright (C) 2009 Andrew Coles  <andrew.coles@yahoo.co.uk>
+ *   Copyright (C) 2009 2009 Petri Damstén <damu@iki.fi>
+ *
+ *   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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "location_name.h"
+#include <KJob>
+#include <KIO/Job>
+#include <KIO/TransferJob>
+
+#include <QtXml/QXmlStreamReader>
+
+class Name::Private
+{
+public:
+    QXmlStreamReader m_xmlReader;
+    double lastLongitude;
+    double lastLatitude;
+    bool guardPlaceNameCheck;
+
+    Private()
+        : lastLongitude(-1.0)
+        , lastLatitude(-1.0)
+    {}
+
+    void populateDataEngineData(Plasma::DataEngine::Data & outd)
+    {
+        QString country, countryCode, city;
+        while (!m_xmlReader.atEnd()) {
+            m_xmlReader.readNext();
+            if (m_xmlReader.isEndElement() && m_xmlReader.name() == "geoname") {
+                break;
+            }
+
+            if (m_xmlReader.isStartElement()) {
+                if (m_xmlReader.name() == "countryCode") {
+                    countryCode = m_xmlReader.readElementText();
+                } else if (m_xmlReader.name() == "countryName") {
+                    country = m_xmlReader.readElementText();
+                } else if (m_xmlReader.name() == "name") {
+                    city = m_xmlReader.readElementText();
+                } else { // for the other fields
+                    m_xmlReader.readElementText();
+                }
+            }
+        }
+
+        // ordering of first three to preserve backwards compatibility
+        outd["country"] = country;
+        outd["country code"] = countryCode;
+        outd["city"] = city;
+    }
+};
+
+Name::Name(QObject* parent, const QVariantList& args)
+    : GeolocationProvider(parent, args)
+    , d(new Private())
+{
+    setUpdateTriggers(CoordinatesChanged | NetworkConnected);
+    setAccuracy(40000);
+}
+
+Name::~Name()
+{
+    delete d;
+}
+
+void Name::update()
+{
+    bool success;
+    const double latitude = data("latitude").toDouble(&success);
+    if (!success) {
+        setData(Plasma::DataEngine::Data());
+        return;
+    }
+
+    const double longitude = data("longitude").toDouble(&success);
+    if (!success) {
+        setData(Plasma::DataEngine::Data());
+        return;
+    }
+
+    bool refreshLocation = false;
+
+    if (d->lastLongitude < 0) {
+        refreshLocation = true;
+        d->lastLatitude = latitude;
+        d->lastLongitude = longitude;
+    } else {
+        const double xChange = 69.1 * (latitude - d->lastLatitude);
+        const double yChange = 53.0 * (longitude - d->lastLongitude);
+
+        if ((xChange * xChange + yChange * yChange) > 25) {  // if we have moved > 5 \
miles +            d->lastLatitude = latitude;
+            d->lastLongitude = longitude;
+            refreshLocation = true;
+        }
+    }
+
+    if (refreshLocation) {
+        d->m_xmlReader.clear();
+
+        KIO::TransferJob *job = KIO::get(
+                KUrl(QString("http://ws.geonames.org/findNearbyPlaceName?lat=%1&lng=%2")
 +                        .arg(latitude).arg(longitude)),
+                KIO::NoReload, KIO::HideProgressInfo);
+
+        if (job) {
+            d->guardPlaceNameCheck = true;
+            kDebug() << \
QString("http://ws.geonames.org/findNearbyPlaceName?lat=%1&lng=%2") +                 \
.arg(latitude).arg(longitude); +            connect(job, SIGNAL(data(KIO::Job *, \
const QByteArray &)), +                    this, SLOT(readData(KIO::Job *, const \
QByteArray &))); +            connect(job, SIGNAL(result(KJob *)), this, \
SLOT(result(KJob *))); +        } else {
+            setData(Plasma::DataEngine::Data());
+            kDebug() << "error";
+        }
+    }
+}
+
+void Name::readData(KIO::Job* job, const QByteArray& data)
+{
+    Q_UNUSED(job)
+
+    if (data.isEmpty()) {
+        return;
+    }
+
+    d->m_xmlReader.addData(data);
+}
+
+void Name::result(KJob* job)
+{
+    Plasma::DataEngine::Data outd;
+    d->guardPlaceNameCheck = false;
+
+    if(job && !job->error()) {
+
+        while (!d->m_xmlReader.atEnd()) {
+            d->m_xmlReader.readNext();
+
+            if (d->m_xmlReader.isStartElement()) {
+                if (d->m_xmlReader.name() == "geoname") {
+                    d->populateDataEngineData(outd);
+                    break;
+                }
+            }
+        }
+    } else {
+        kDebug() << "error";
+    }
+    setData(outd);
+}
+
+K_EXPORT_PLASMA_GEOLOCATIONPROVIDER(name, Name)
+
+#include "location_name.moc"
Index: geolocation.h
===================================================================
--- geolocation.h	(revision 1080874)
+++ geolocation.h	(working copy)
@@ -53,7 +53,9 @@
         EntryAccuracy m_accuracy;
         QList<GeolocationProvider *> m_plugins;
         QTimer m_updateTimer;
-        bool m_networkStatus;
+        bool m_networkUp;
+        QString m_latitude;
+        QString m_longitude;
 };
 
 K_EXPORT_PLASMA_DATAENGINE(geolocation, Geolocation)
Index: location_name.h
===================================================================
--- location_name.h	(revision 0)
+++ location_name.h	(revision 0)
@@ -0,0 +1,47 @@
+/*
+ *   Copyright (C) 2009 Petri Damstén <damu@iki.fi>
+ *
+ *   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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NAME_H
+#define NAME_H
+
+#include "geolocationprovider.h"
+
+class KJob;
+namespace KIO {
+    class Job;
+}
+
+class Name : public GeolocationProvider
+{
+    Q_OBJECT
+public:
+    explicit Name(QObject *parent = 0, const QVariantList &args = QVariantList());
+    ~Name();
+
+    virtual void update();
+
+protected slots:
+    void readData(KIO::Job *, const QByteArray& data);
+    void result(KJob* job);
+
+private:
+    class Private;
+    Private *const d;
+
+};
+
+#endif
Index: geolocationprovider.cpp
===================================================================
--- geolocationprovider.cpp	(revision 1080874)
+++ geolocationprovider.cpp	(working copy)
@@ -50,8 +50,11 @@
     return m_available;
 }
 
-bool GeolocationProvider::requestUpdate(GeolocationProvider::UpdateTriggers \
triggers) +bool GeolocationProvider::requestUpdate(GeolocationProvider::UpdateTriggers \
triggers, bool networkUp)  {
+    if ((m_updateTriggers & NetworkConnected) && !networkUp) {
+        return false;
+    }
     if (m_available && !m_updating && (triggers == ForcedUpdate || triggers & \
m_updateTriggers)) {  m_updating = true;
         update();
@@ -108,6 +111,11 @@
     }
 }
 
+QVariant GeolocationProvider::data(const QString &key)
+{
+    return m_sharedData->value(key);
+}
+
 void GeolocationProvider::setData(const QString &key, const QVariant &value)
 {
     m_updating = false;
Index: location_gps.cpp
===================================================================
--- location_gps.cpp	(revision 1080874)
+++ location_gps.cpp	(working copy)
@@ -56,7 +56,6 @@
                 //kDebug() << "online";
                 if (m_gpsdata->status != STATUS_NO_FIX) {
                     //kDebug() << "fix";
-                    d["accuracy"] = 30;
                     d["latitude"] = QString::number(m_gpsdata->fix.latitude);
                     d["longitude"] = QString::number(m_gpsdata->fix.longitude);
                 }
@@ -73,6 +72,7 @@
     : GeolocationProvider(parent, args),
       m_gpsd(0)
 {
+    setAccuracy(30);
     gps_data_t* gpsdata = gps_open("localhost", DEFAULT_GPSD_PORT);
     if (gpsdata) {
         kDebug() << "gpsd found.";
Index: plasma-geolocation-name.desktop
===================================================================
--- plasma-geolocation-name.desktop	(revision 0)
+++ plasma-geolocation-name.desktop	(revision 0)
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=Geolocation Name
+Comment=Geolocation name from coordinates.
+X-KDE-ServiceTypes=Plasma/GeolocationProvider
+X-KDE-ParentApp=geolocation
+Type=Service
+Icon=applications-internet
+X-KDE-Library=plasma-geolocation-name
+X-KDE-PluginInfo-Name=name
Index: geolocationprovider.h
===================================================================
--- geolocationprovider.h	(revision 1080874)
+++ geolocationprovider.h	(working copy)
@@ -33,7 +33,8 @@
     Q_OBJECT
 
 public:
-    enum UpdateTrigger { ForcedUpdate = 0, SourceEvent = 1, NetworkConnected = 2 };
+    enum UpdateTrigger { ForcedUpdate = 0, SourceEvent = 1, NetworkConnected = 2,
+                         CoordinatesChanged = 4 };
     Q_DECLARE_FLAGS(UpdateTriggers, UpdateTrigger)
 
     GeolocationProvider(QObject *parent = 0, const QVariantList &args = \
QVariantList()); @@ -42,7 +43,7 @@
     UpdateTriggers updateTriggers() const;
     int accuracy() const;
     bool isAvailable() const;
-    bool requestUpdate(UpdateTriggers trigger);
+    bool requestUpdate(UpdateTriggers trigger, bool networkUp);
     bool populateSharedData();
 
 Q_SIGNALS:
@@ -55,6 +56,7 @@
     void setUpdateTriggers(UpdateTriggers triggers);
     virtual void init();
     virtual void update();
+    QVariant data(const QString &key);
 
 protected Q_SLOTS:
     void setData(const Plasma::DataEngine::Data &data);
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 1080874)
+++ CMakeLists.txt	(working copy)
@@ -45,6 +45,14 @@
 
 # -------------------------------------------------------------------------------------------------
  
+set(plasma_geolocation_name_SRCS location_name.cpp)
+kde4_add_plugin(plasma-geolocation-name ${plasma_geolocation_name_SRCS})
+target_link_libraries(plasma-geolocation-name plasma-geolocation-interface)
+install(FILES plasma-geolocation-name.desktop DESTINATION ${SERVICES_INSTALL_DIR})
+install(TARGETS plasma-geolocation-name DESTINATION ${PLUGIN_INSTALL_DIR})
+
+# -------------------------------------------------------------------------------------------------
 +
 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules \
${CMAKE_MODULE_PATH})  find_package(libgps)
 macro_log_feature(LIBGPS_FOUND "libgps" "GPS support for geolocation" \
"http://gpsd.berlios.de/" FALSE "" "")


["signature.asc" (application/pgp-signature)]

_______________________________________________
Plasma-devel mailing list
Plasma-devel@kde.org
https://mail.kde.org/mailman/listinfo/plasma-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic