[gnome-shell/wip/fmuellner/calendar-refresh: 3/15] weather: Add WeatherClient



commit 666cb7250904f221f0e5425ba4a27e06a5974720
Author: Florian Müllner <fmuellner gnome org>
Date:   Thu Feb 23 22:55:33 2017 +0100

    weather: Add WeatherClient
    
    In preparation of integrating GNOME Weather, add a helper class that
    retrieves weather information according to Weather's configuration
    if the application is installed.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=754031

 js/js-resources.gresource.xml |    1 +
 js/ui/weather.js              |  178 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 179 insertions(+), 0 deletions(-)
---
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index 72cc4f8..0a70b3a 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -96,6 +96,7 @@
     <file>ui/unlockDialog.js</file>
     <file>ui/userWidget.js</file>
     <file>ui/viewSelector.js</file>
+    <file>ui/weather.js</file>
     <file>ui/windowAttentionHandler.js</file>
     <file>ui/windowMenu.js</file>
     <file>ui/windowManager.js</file>
diff --git a/js/ui/weather.js b/js/ui/weather.js
new file mode 100644
index 0000000..5a621a2
--- /dev/null
+++ b/js/ui/weather.js
@@ -0,0 +1,178 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Geoclue = imports.gi.Geoclue;
+const Gio = imports.gi.Gio;
+const GWeather = imports.gi.GWeather;
+const Lang = imports.lang;
+const Signals = imports.signals;
+
+const Util = imports.misc.util;
+
+const WeatherClient = new Lang.Class({
+    Name: 'WeatherClient',
+
+    _init: function() {
+        this._loading = false;
+
+        this._useAutoLocation = false;
+        this._mostRecentLocation = null;
+
+        this._gclueService = null;
+        this._gclueStarted = false;
+        this._gclueFailed = false;
+        this._gclueLocationChangedId = 0;
+
+        this._world = GWeather.Location.get_world();
+
+        let providers = GWeather.Provider.METAR |
+                        GWeather.Provider.YR_NO |
+                        GWeather.Provider.OWM;
+        this._weatherInfo = new GWeather.Info({ enabled_providers: providers });
+        this._weatherInfo.connect('updated', () => { this.emit('changed'); });
+
+        this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.Application.desktop',
+                                                          'org.gnome.Weather.Application');
+        this._weatherAppMon.connect('available-changed', () => { this.emit('changed'); });
+        this._weatherAppMon.watchSetting('automatic-location',
+                                         Lang.bind(this, this._onAutomaticLocationChanged));
+        this._weatherAppMon.watchSetting('locations',
+                                         Lang.bind(this, this._onLocationsChanged));
+    },
+
+    get available() {
+        return this._weatherAppMon.available;
+    },
+
+    get loading() {
+        return this._loading;
+    },
+
+    get info() {
+        return this._weatherInfo;
+    },
+
+    activateApp: function() {
+        this._weatherAppMon.activateApp();
+    },
+
+    update: function() {
+        this._loadInfo();
+    },
+
+    _loadInfo: function() {
+        let id = this._weatherInfo.connect('updated', () => {
+            this._weatherInfo.disconnect(id);
+
+            this._loading = false;
+            this.emit('changed');
+        });
+
+        this._loading = true;
+        this.emit('changed');
+
+        this._weatherInfo.update();
+    },
+
+    _locationsEqual: function(loc1, loc2) {
+        if (loc1 == loc2)
+            return true;
+
+        if (loc1 == null || loc2 == null)
+            return false;
+
+        return loc1.equal(loc2);
+    },
+
+    _setLocation: function(location) {
+        if (this._locationsEqual(this._weatherInfo.location, location))
+            return;
+
+        this._weatherInfo.abort();
+        this._weatherInfo.set_location(location);
+
+        if (location)
+            this._loadInfo();
+        else
+            this.emit('changed');
+    },
+
+    _updateLocationMonitoring: function() {
+        if (this._useAutoLocation) {
+            if (this._gclueLocationChangedId != 0 || this._gclueService == null)
+                return;
+
+            this._gclueLocationChangedId =
+                this._gclueService.connect('notify::location',
+                                           Lang.bind(this, this._onGClueLocationChanged));
+            this._onGClueLocationChanged();
+        } else {
+            if (this._gclueLocationChangedId)
+                this._gclueService.disconnect(this._gclueLocationChangedId);
+            this._gclueLocationChangedId = 0;
+        }
+    },
+
+    _startGClueService: function() {
+        if (this._gclueStarted)
+            return;
+
+        this._gclueStarted = true;
+        Geoclue.Simple.new('org.gnome.Shell', Geoclue.AccuracyLevel.CITY, null,
+            (o, res) => {
+                try {
+                    this._gclueService = Geoclue.Simple.new_finish(res);
+                } catch(e) {
+                    log('Failed to connect to Geoclue2 service: ' + e.message);
+                    this._gclueFailed = true;
+                    this._setLocation(this._mostRecentLocation);
+                    return;
+                }
+
+                this._gclueService.get_client().distance_threshold = 100;
+                this._updateLocationMonitoring();
+            });
+    },
+
+    _onGClueLocationChanged: function() {
+        let geoLocation = this._gclueService.location;
+        let location = GWeather.Location.new_detached(geoLocation.description,
+                                                      null,
+                                                      geoLocation.latitude,
+                                                      geoLocation.longitude);
+        this._setLocation(location);
+    },
+
+    _onAutomaticLocationChanged: function(settings, key) {
+        let useAutoLocation = settings.get_boolean(key);
+        if (this._useAutoLocation == useAutoLocation)
+            return;
+
+        this._useAutoLocation = useAutoLocation;
+
+        this._updateLocationMonitoring();
+
+        if (this._useAutoLocation) {
+            if (!this._gclueStarted)
+                this._startGClueService();
+        } else {
+            this._setLocation(this._mostRecentLocation);
+        }
+    },
+
+    _onLocationsChanged: function(settings, key) {
+        let serialized = settings.get_value(key).deep_unpack().shift();
+        let mostRecentLocation = null;
+
+        if (serialized)
+            mostRecentLocation = this._world.deserialize(serialized);
+
+        if (this._locationsEqual(this._mostRecentLocation, mostRecentLocation))
+            return;
+
+        this._mostRecentLocation = mostRecentLocation;
+
+        if (!this._useAutoLocation || this._gclueFailed)
+            this._setLocation(this._mostRecentLocation);
+    }
+});
+Signals.addSignalMethods(WeatherClient.prototype);


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