[gnome-weather] Adding feature to show weather conditions for current location



commit 30adaaebe80c2ccf4b2c5ff38d208c83069f52eb
Author: Saurabh_P <srp201201051 gmail com>
Date:   Sun Mar 9 03:31:07 2014 +0530

    Adding feature to show weather conditions for current location
    
    Use Geoclue to get the current place and find nearest weather station
    using it and find_nearest_city method of GWeather-location. Add this
    current location if the location does not exist already in the
    world_view. Don't add location to 'locations' value of settings. To
    handle this use one more column named AUTOMATIC that shows whether
    location is added automatically or not. Check this column on removing
    the location and if it is true then remove that 'iter' and return.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=704268

 src/currentLocationController.js                   |  141 ++++++++++++++++++++
 ...org.gnome.Weather.Application.src.gresource.xml |    1 +
 src/world.js                                       |   53 ++++++-
 3 files changed, 187 insertions(+), 8 deletions(-)
---
diff --git a/src/currentLocationController.js b/src/currentLocationController.js
new file mode 100644
index 0000000..d10383d
--- /dev/null
+++ b/src/currentLocationController.js
@@ -0,0 +1,141 @@
+// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
+//
+// Copyright (c) 2014 Saurabh Patel <srp201201051 gmail com>
+//
+// Gnome Weather 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.
+//
+// Gnome Weather 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 Gnome Weather; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
+const Gio = imports.gi.Gio;
+const Lang = imports.lang;
+const GWeather = imports.gi.GWeather;
+const Geocode = imports.gi.GeocodeGlib;
+
+const ManagerInterface = '<node> \
+<interface name="org.freedesktop.GeoClue2.Manager"> \
+    <method name="GetClient"> \
+        <arg name="client" type="o" direction="out"/> \
+    </method> \
+</interface> \
+</node>';
+const ManagerProxy = Gio.DBusProxy.makeProxyWrapper(ManagerInterface);
+
+const ClientInterface = '<node> \
+<interface name="org.freedesktop.GeoClue2.Client"> \
+    <property name="Location" type="o" access="read"/> \
+    <property name="DesktopId" type="s" access="readwrite"/> \
+    <property name="RequestedAccuracyLevel" type="u" access="readwrite"/> \
+    <property name="DistanceThreshold" type="u" access="readwrite"/> \
+    <method name="Start"/> \
+    <signal name="LocationUpdated"> \
+        <arg name="old" type="o"/> \
+        <arg name="new" type="o"/> \
+    </signal> \
+</interface> \
+</node>';
+const ClientProxy = Gio.DBusProxy.makeProxyWrapper(ClientInterface);
+
+const AccuracyLevel = {
+    COUNTRY: 1,
+    CITY: 4,
+    NEIGHBORHOOD: 5,
+    STREET: 6,
+    EXACT: 8,
+};
+
+const LocationInterface = '<node> \
+<interface name="org.freedesktop.GeoClue2.Location"> \
+    <property name="Latitude" type="d" access="read"/> \
+    <property name="Longitude" type="d" access="read"/> \
+    <property name="Accuracy" type="d" access="read"/> \
+    <property name="Description" type="s" access="read"/> \
+</interface> \
+</node>';
+const LocationProxy = Gio.DBusProxy.makeProxyWrapper(LocationInterface);
+
+const CurrentLocationController = new Lang.Class({
+    Name: 'CurrentLocationController',
+
+    _init: function(callback) {
+        this._callback = callback;
+        this._managerProxy = new ManagerProxy(Gio.DBus.system,
+                                               "org.freedesktop.GeoClue2",
+                                               "/org/freedesktop/GeoClue2/Manager");
+
+        this._managerProxy.GetClientRemote(this._onGetClientReady.bind(this));
+    },
+
+    _onGetClientReady: function(result, e) {
+        if (e) {
+            log ("Failed to connect to GeoClue2 service: " + e.message);
+            return;
+        }
+
+        let [clientPath] = result;
+
+        this._clientProxy = new ClientProxy(Gio.DBus.system,
+                                            "org.freedesktop.GeoClue2",
+                                            clientPath);
+        this._clientProxy.DesktopId = "gnome-weather";
+        this._clientProxy.RequestedAccuracyLevel = AccuracyLevel.CITY;
+        this._clientProxy.DistanceThreshold = 100;
+
+        this._findLocation();
+    },
+
+    _findLocation: function() {
+        this._locationUpdatedId =
+            this._clientProxy.connectSignal("LocationUpdated",
+                                            this._getCurrentLocation.bind(this));
+
+        this._clientProxy.StartRemote(function(result, e) {
+            if (e) {
+                log ("Failed to connect to GeoClue2 service: " + e.message);
+            }
+        });
+    },
+
+    _getCurrentLocation: function(proxy, sender, [oldPath, newPath]) {
+        let geoclueLocation = new LocationProxy(Gio.DBus.system,
+                                                "org.freedesktop.GeoClue2",
+                                                newPath);
+        let location = new Geocode.Location({ latitude: geoclueLocation.Latitude,
+                                              longitude: geoclueLocation.Longitude,
+                                              accuracy: geoclueLocation.Accuracy,
+                                              description: geoclueLocation.Description });
+
+        this.currentLocation = GWeather.Location.get_world().find_nearest_city (location.latitude, 
location.longitude);
+        if (this.currentLocation)
+            this._callback(this.currentLocation);
+    },
+
+    isLocationSimilar: function(location) {
+        if (this.currentLocation != null) {
+            let station_code = location.get_code ();
+            let currentLocationCode = this.currentLocation.get_code();
+
+            if (station_code && currentLocationCode && (station_code == currentLocationCode)) {
+                let name = location.get_name ();
+                let currentLocationName = this.currentLocation.get_name();
+
+                if (name && currentLocationName && (name == currentLocationName)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+});
diff --git a/src/org.gnome.Weather.Application.src.gresource.xml 
b/src/org.gnome.Weather.Application.src.gresource.xml
index a2f82f7..c22b280 100644
--- a/src/org.gnome.Weather.Application.src.gresource.xml
+++ b/src/org.gnome.Weather.Application.src.gresource.xml
@@ -2,6 +2,7 @@
 <gresources>
   <gresource prefix="/org/gnome/Weather/Application/js">
     <file>city.js</file>
+    <file>currentLocationController.js</file>
     <file>forecast.js</file>
     <file>main.js</file>
     <file>params.js</file>
diff --git a/src/world.js b/src/world.js
index 421e928..0566f67 100644
--- a/src/world.js
+++ b/src/world.js
@@ -26,6 +26,7 @@ const Lang = imports.lang;
 
 const Params = imports.params;
 const Util = imports.util;
+const CurrentLocationController = imports.currentLocationController;
 
 const Columns = {
     ID: Gd.MainColumns.ID,
@@ -37,7 +38,8 @@ const Columns = {
     SELECTED: Gd.MainColumns.SELECTED,
     PULSE: Gd.MainColumns.PULSE,
     LOCATION: Gd.MainColumns.LAST,
-    INFO: Gd.MainColumns.LAST+1
+    INFO: Gd.MainColumns.LAST+1,
+    AUTOMATIC: Gd.MainColumns.LAST+2
 };
 const ColumnTypes = {
     ID: String,
@@ -49,10 +51,11 @@ const ColumnTypes = {
     SELECTED: Boolean,
     PULSE: GObject.UInt,
     LOCATION: GWeather.Location,
-    INFO: GWeather.Info
+    INFO: GWeather.Info,
+    AUTOMATIC: Boolean
 };
 Util.assertEqual(Object.keys(Columns).length, Object.keys(ColumnTypes).length);
-Util.assertEqual(Gd.MainColumns.LAST+2, Object.keys(ColumnTypes).length);
+Util.assertEqual(Gd.MainColumns.LAST+3, Object.keys(ColumnTypes).length);
 
 const ICON_SIZE = 128;
 
@@ -87,10 +90,14 @@ const WorldModel = new Lang.Class({
         for (let i = 0; i < locations.length; i++) {
             let variant = locations[i];
             let location = this._world.deserialize(variant);
-            this._addLocationInternal(location);
+            this._addLocationInternal(location, false);
         }
 
         this._settings.connect('changed::locations', Lang.bind(this, this._onChanged));
+
+        let currentLocationController = new 
CurrentLocationController.CurrentLocationController(Lang.bind(this,
+                                                                                                          
this._addCurrentLocation));
+        this._currentLocationController = currentLocationController;
     },
 
     _updateLoadingCount: function(delta) {
@@ -111,7 +118,7 @@ const WorldModel = new Lang.Class({
         return this._loadingCount > 0;
     },
 
-    _addLocationInternal: function(location) {
+    _addLocationInternal: function(location, automatic) {
         let info = new GWeather.Info({ location: location,
                                        enabled_providers: this._providers });
         let iter;
@@ -134,11 +141,13 @@ const WorldModel = new Lang.Class({
                                         [Columns.PRIMARY_TEXT,
                                          Columns.ICON,
                                          Columns.LOCATION,
-                                         Columns.INFO],
+                                         Columns.INFO,
+                                         Columns.AUTOMATIC],
                                         [primary_text,
                                          icon,
                                          location,
-                                         info]);
+                                         info,
+                                         automatic]);
     },
 
     _onChanged: function() {
@@ -147,6 +156,11 @@ const WorldModel = new Lang.Class({
 
         let [ok, iter] = this.get_iter_first();
         while (ok) {
+            let auto = this.get_value(iter, Columns.AUTOMATIC);
+            if (auto) {
+                ok = this.iter_next(iter);
+                continue;
+            }
             let location = this.get_value(iter, Columns.LOCATION);
 
             let found = false;
@@ -179,7 +193,7 @@ const WorldModel = new Lang.Class({
                 continue;
 
             let newLocation = this._world.deserialize(variant);
-            this._addLocationInternal(newLocation);
+            this._addLocationInternal(newLocation, false);
         }
     },
 
@@ -189,17 +203,40 @@ const WorldModel = new Lang.Class({
         this._settings.set_value('locations', new GLib.Variant('av', newLocations));
     },
 
+    _addCurrentLocation: function(currentLocation) {
+        let locations = this._settings.get_value('locations').deep_unpack();
+
+        for (let i = 0; i < locations.length; i++) {
+            let variant = locations[i];
+            if (variant == null)
+                continue;
+
+            let location = this._world.deserialize(variant);
+            if (this._currentLocationController.isLocationSimilar(location))
+                return;
+        }
+        this._addLocationInternal(currentLocation, true);
+    },
+
     removeLocation: function(iter) {
+        let auto = this.get_value(iter, Columns.AUTOMATIC);
+        if (auto) {
+            this.remove(iter);
+            return;
+        }
+
         let location = this.get_value(iter, Columns.LOCATION);
         let variant = location.serialize();
 
         let newLocations = this._settings.get_value('locations').deep_unpack();
+
         for (let i = 0; i < newLocations.length; i++) {
             if (newLocations[i].equal(variant)) {
                 newLocations.splice(i, 1);
                 break;
             }
         }
+
         this._settings.set_value('locations', new GLib.Variant('av', newLocations));
     },
 });


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]