[gnome-clocks] Port to GSettings



commit 6dba72ecaac2254d7bc214825094bffc75a71ba4
Author: Paolo Borelli <pborelli gnome org>
Date:   Fri Feb 1 22:14:44 2013 +0100

    Port to GSettings
    
    This removes the dependency on json parsing and uses a data store more
    natural in the gnome world.
    Besides, GWeatherLocations are serialized as GVariants, so it becomes
    natural to store them in GSettings.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=689487

 Makefile.am                          |    5 ++
 configure.ac                         |    2 +
 data/org.gnome.clocks.gschema.xml.in |   18 ++++++++
 gnomeclocks/alarm.py                 |   78 +++++++++++---------------------
 gnomeclocks/world.py                 |   80 ++++++++++++++--------------------
 5 files changed, 85 insertions(+), 98 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4b88c4d..40beb4f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,6 +10,11 @@ applicationsdir = $(datadir)/applications
 applications_DATA = data/gnome-clocks.desktop
 dist_noinst_DATA = data/gnome-clocks.desktop.in
 
+# gsettings
+gsettings_SCHEMAS = data/org.gnome.clocks.gschema.xml
+ INTLTOOL_XML_NOMERGE_RULE@
+ GSETTINGS_RULES@
+
 # icons
 icon16dir = $(datadir)/icons/hicolor/16x16/apps
 icon16_DATA = data/icons/hicolor/16x16/apps/gnome-clocks.png
diff --git a/configure.ac b/configure.ac
index 7f97ab4..4af5fa1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,6 +19,8 @@ GETTEXT_PACKAGE=AC_PACKAGE_NAME
 AC_SUBST([GETTEXT_PACKAGE])
 AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[The name of the gettext domain])
 
+GLIB_GSETTINGS
+
 PKG_PROG_PKG_CONFIG([0.22])
 
 PKG_CHECK_MODULES(CLOCKS, [
diff --git a/data/org.gnome.clocks.gschema.xml.in b/data/org.gnome.clocks.gschema.xml.in
new file mode 100644
index 0000000..ec38d29
--- /dev/null
+++ b/data/org.gnome.clocks.gschema.xml.in
@@ -0,0 +1,18 @@
+<schemalist>
+  <schema id="org.gnome.clocks" path="/org/gnome/clocks/" gettext-domain="@GETTEXT_PACKAGE@">
+    <key name="world-clocks" type="aa{sv}">
+      <default>[]</default>
+      <_summary>Configured world clocks</_summary>
+      <_description>
+        List of world clocks to show.
+      </_description>
+    </key>
+    <key name="alarms" type="aa{sv}">
+      <default>[]</default>
+      <_summary>Configured alarms</_summary>
+      <_description>
+        List of alarms set.
+      </_description>
+    </key>
+  </schema>
+</schemalist>
diff --git a/gnomeclocks/alarm.py b/gnomeclocks/alarm.py
index 6211929..27e292a 100644
--- a/gnomeclocks/alarm.py
+++ b/gnomeclocks/alarm.py
@@ -20,7 +20,7 @@ import os
 import errno
 import json
 from datetime import timedelta
-from gi.repository import GLib, GObject, Gtk
+from gi.repository import GLib, Gio, GObject, Gtk
 from .clocks import Clock
 from .utils import Alert, Dirs, LocalizedWeekdays, SystemSettings, TimeString, WallClock
 from .widgets import Toolbar, ToolButton, SymbolicToolButton, SelectableIconView, ContentView
@@ -29,46 +29,6 @@ from .widgets import Toolbar, ToolButton, SymbolicToolButton, SelectableIconView
 wallclock = WallClock.get_default()
 
 
-class AlarmsStorage:
-    def __init__(self):
-        self.filename = os.path.join(Dirs.get_user_data_dir(), "alarms.json")
-
-    def save(self, alarms):
-        alarm_list = []
-        for a in alarms:
-            d = {
-                "name": a.name,
-                "hour": a.hour,
-                "minute": a.minute,
-                "days": a.days,
-                "active": a.active
-            }
-            alarm_list.append(d)
-        with open(self.filename, 'w', encoding='utf-8') as f:
-            json.dump(alarm_list, f, ensure_ascii=False)
-
-    def load(self):
-        alarms = []
-        try:
-            with open(self.filename, encoding='utf-8') as f:
-                alarm_list = json.load(f)
-            for a in alarm_list:
-                try:
-                    n, h, m, d = (a['name'], int(a['hour']), int(a['minute']), a['days'])
-                    # support the old format that didn't have the active key
-                    active = a['active'] if 'active' in a else True
-                except:
-                    # skip alarms which do not have the required fields
-                    continue
-                alarm = AlarmItem(n, h, m, d, active)
-                alarms.append(alarm)
-        except IOError as e:
-            if e.errno == errno.ENOENT:
-                # File does not exist yet, that's ok
-                pass
-        return alarms
-
-
 class AlarmItem:
     EVERY_DAY = [0, 1, 2, 3, 4, 5, 6]
     # TODO: For now the alarm never rings that long
@@ -187,6 +147,15 @@ class AlarmItem:
             self.stop()
         return self.state != last_state
 
+    def serialize(self):
+        return {
+            "name": GLib.Variant('s', self.name),
+            "hour": GLib.Variant('i', self.hour),
+            "minute": GLib.Variant('i', self.minute),
+            "days": GLib.Variant('ai', self.days),
+            "active": GLib.Variant('b', self.active)
+        }
+
 
 class AlarmDialog(Gtk.Dialog):
     def __init__(self, parent, alarm=None):
@@ -454,6 +423,8 @@ class Alarm(Clock):
     def __init__(self, toolbar, embed):
         Clock.__init__(self, _("Alarm"), toolbar, embed)
 
+        self.settings = Gio.Settings(schema='org.gnome.clocks')
+
         # Translators: "New" refers to an alarm
         self.new_button = ToolButton(_("New"))
         self.new_button.connect('clicked', self._on_new_clicked)
@@ -488,11 +459,22 @@ class Alarm(Clock):
         self.insert_page(self.standalone, Alarm.Page.STANDALONE)
         self.set_current_page(Alarm.Page.OVERVIEW)
 
-        self.storage = AlarmsStorage()
-        self.load_alarms()
+        self._load()
 
         wallclock.connect("time-changed", self._tick_alarms)
 
+    def _save(self):
+        v = GLib.Variant('aa{sv}', [a.serialize() for a in self.alarms])
+        self.settings.set_value('alarms', v)
+
+    def _load(self):
+        self.alarms = []
+        for a in self.settings.get_value('alarms'):
+            self.alarms.append(AlarmItem(**a))
+        for a in self.alarms:
+            self._add_alarm_item(a)
+        self.select_button.set_sensitive(self.alarms)
+
     def _on_new_clicked(self, button):
         self.activate_new()
 
@@ -556,16 +538,10 @@ class Alarm(Clock):
         else:
             self._embed.hide_floatingbar()
 
-    def load_alarms(self):
-        self.alarms = self.storage.load()
-        for alarm in self.alarms:
-            self._add_alarm_item(alarm)
-        self.select_button.set_sensitive(self.alarms)
-
     def save_alarms(self):
-        self.storage.save(self.alarms)
+        self._save()
         self.liststore.clear()
-        self.load_alarms()
+        self._load()
 
     def add_alarm(self, alarm):
         if alarm in self.alarms:
diff --git a/gnomeclocks/world.py b/gnomeclocks/world.py
index 6cb9fc4..9a2ac5c 100644
--- a/gnomeclocks/world.py
+++ b/gnomeclocks/world.py
@@ -33,42 +33,6 @@ gweather_world = GWeather.Location.new_world(True)
 wallclock = WallClock.get_default()
 
 
-class WorldClockStorage:
-    def __init__(self):
-        self.filename = os.path.join(Dirs.get_user_data_dir(), "clocks.json")
-
-    def save(self, clocks):
-        locations = [str(c.location.serialize()) for c in clocks]
-        with open(self.filename, 'w', encoding='utf-8') as f:
-            json.dump(locations, f, ensure_ascii=False)
-
-    def load(self):
-        clocks = []
-        try:
-            with open(self.filename, encoding='utf-8') as f:
-                locations = json.load(f)
-            for l in locations:
-                try:
-                    variant = GLib.Variant.parse(None, l, None, None)
-                    location = GWeather.Location.deserialize(gweather_world, variant)
-                except:
-                    location = None
-                if not location:
-                    # This is for backward compatibility importing the old clocks which
-                    # just saved the metar location code... for now we may end up here
-                    # both if deserialize fails of if variant parse throws an exception
-                    location = GWeather.Location.find_by_station_code(gweather_world, l)
-                if location:
-                    clock = ClockItem(location)
-                    clocks.append(clock)
-        except IOError as e:
-            if e.errno == errno.ENOENT:
-                # File does not exist yet, that's ok
-                pass
-
-        return clocks
-
-
 class NewWorldClockDialog(Gtk.Dialog):
     def __init__(self, parent):
         Gtk.Dialog.__init__(self, _("Add a New World Clock"), parent)
@@ -211,6 +175,9 @@ class ClockItem:
         self.day_string = self._get_day_string()
         self._update_sunrise_sunset()
 
+    def serialize(self):
+        return {"location": self.location.serialize()}
+
 
 class WorldStandalone(Gtk.EventBox):
     def __init__(self):
@@ -297,6 +264,8 @@ class World(Clock):
     def __init__(self, toolbar, embed):
         Clock.__init__(self, _("World"), toolbar, embed)
 
+        self.settings = Gio.Settings(schema='org.gnome.clocks')
+
         # Translators: "New" refers to a world clock
         self.new_button = ToolButton(_("New"))
         self.new_button.connect('clicked', self._on_new_clicked)
@@ -333,11 +302,34 @@ class World(Clock):
         self.insert_page(self.standalone, World.Page.STANDALONE)
         self.set_current_page(World.Page.OVERVIEW)
 
-        self.storage = WorldClockStorage()
-        self.load_clocks()
+        self._load()
 
         wallclock.connect("time-changed", self._tick_clocks)
 
+    def _save(self):
+        v = GLib.Variant('aa{sv}', [c.serialize() for c in self.clocks])
+        self.settings.set_value('world-clocks', v)
+
+    def _load(self):
+        self.clocks = []
+        # NOTE: we have to manually parse the variant because pygobject
+        # automatically unpacks all the variant to native python objects
+        # while we need to extract the variant object to pass to gweather
+        locations = self.settings.get_value('world-clocks')
+        for i in range(locations.n_children()):
+            l = {}
+            location_variant = locations.get_child_value(i)
+            for j in range(location_variant.n_children()):
+                v = location_variant.get_child_value(j)
+                l[v.get_child_value(0).get_string()] = v.get_child_value(1).get_child_value(0)
+            location = GWeather.Location.deserialize(gweather_world, l["location"])
+            if location:
+                self.clocks.append(ClockItem(location))
+
+        for clock in self.clocks:
+            self._add_clock_item(clock)
+        self.select_button.set_sensitive(self.clocks)
+
     def _on_new_clicked(self, button):
         self.activate_new()
 
@@ -391,19 +383,13 @@ class World(Clock):
         else:
             self._embed.hide_floatingbar()
 
-    def load_clocks(self):
-        self.clocks = self.storage.load()
-        for clock in self.clocks:
-            self._add_clock_item(clock)
-        self.select_button.set_sensitive(self.clocks)
-
     def add_clock(self, location):
         if any(c.location.equal(location) for c in self.clocks):
             # duplicate
             return
         clock = ClockItem(location)
         self.clocks.append(clock)
-        self.storage.save(self.clocks)
+        self._save()
         self._add_clock_item(clock)
         self.select_button.set_sensitive(True)
         self.show_all()
@@ -414,9 +400,9 @@ class World(Clock):
 
     def delete_clocks(self, clocks):
         self.clocks = [c for c in self.clocks if c not in clocks]
-        self.storage.save(self.clocks)
+        self._save()
         self.liststore.clear()
-        self.load_clocks()
+        self._load()
 
     def update_toolbar(self):
         self._toolbar.clear()



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