[gnome-clocks] Refactor alarm and world clock thumbnail class



commit 7f173e4f0a72cbaecd6c1e8a3724be596cfbe08f
Author: Paolo Borelli <pborelli gnome org>
Date:   Sun Nov 18 12:55:49 2012 +0100

    Refactor alarm and world clock thumbnail class
    
    Make alarm and world clock internal structure more conistent, by
    splitting splitting in both cases a "Thumbnail" class that takes care of
    the representation in the iconview and a "Item" class which is the model
    for the thumbnail and the standalone classes

 gnomeclocks/alarm.py |   53 ++++++-------
 gnomeclocks/utils.py |   12 +++
 gnomeclocks/world.py |  201 +++++++++++++++++++++-----------------------------
 3 files changed, 120 insertions(+), 146 deletions(-)
---
diff --git a/gnomeclocks/alarm.py b/gnomeclocks/alarm.py
index 51e26a4..988b99d 100644
--- a/gnomeclocks/alarm.py
+++ b/gnomeclocks/alarm.py
@@ -97,7 +97,7 @@ class AlarmItem:
         # check if it can ring later today
         if dt.weekday() not in self.days or dt <= now:
             # otherwise if it can ring this week
-            next_days = [ d for d in self.days if d > dt.weekday() ]
+            next_days = [d for d in self.days if d > dt.weekday()]
             if next_days:
                 dt += timedelta(days=(next_days[0] - dt.weekday()))
             # otherwise next week
@@ -151,6 +151,9 @@ class AlarmItem:
         else:
             return False
 
+    def get_is_light(self):
+        return self.hour > 7 and self.hour < 19
+
 
 class AlarmDialog(Gtk.Dialog):
     def __init__(self, parent, alarm=None):
@@ -284,7 +287,7 @@ class AlarmDialog(Gtk.Dialog):
         return alarm
 
 
-class AlarmWidget():
+class AlarmThumbnail():
     def __init__(self, view, alarm, alert):
         self.view = view
         self.alarm = alarm
@@ -292,7 +295,7 @@ class AlarmWidget():
         timestr = alarm.get_time_as_string()
         repeat = alarm.get_alarm_repeat_string()
         self.drawing = DigitalClockDrawing()
-        is_light = self.get_is_light(int(timestr[:2]))
+        is_light = self.alarm.get_is_light()
         if is_light:
             img = os.path.join(Dirs.get_image_dir(), "cities", "day.png")
         else:
@@ -300,8 +303,8 @@ class AlarmWidget():
         self.drawing.render(timestr, img, is_light, repeat)
         self.standalone = None
 
-    def get_is_light(self, hours):
-        return hours > 7 and hours < 19
+    def get_alarm(self):
+        return self.alarm
 
     def get_pixbuf(self):
         return self.drawing.pixbuf
@@ -423,14 +426,13 @@ class Alarm(Clock):
         self.liststore = Gtk.ListStore(bool,
                                        GdkPixbuf.Pixbuf,
                                        str,
-                                       GObject.TYPE_PYOBJECT,
                                        GObject.TYPE_PYOBJECT)
 
         self.iconview = SelectableIconView(self.liststore, 0, 1, 2)
 
         contentview = ContentView(self.iconview,
-                "alarm-symbolic",
-                _("Select <b>New</b> to add an alarm"))
+                                  "alarm-symbolic",
+                                  _("Select <b>New</b> to add an alarm"))
         self.add(contentview)
 
         self.iconview.connect("item-activated", self._on_item_activated)
@@ -445,14 +447,13 @@ class Alarm(Clock):
 
     def _check_alarms(self):
         for i in self.liststore:
-            alarm = self.liststore.get_value(i.iter, 4)
-            if alarm.check_expired():
-                widget = self.liststore.get_value(i.iter, 3)
-                alert = widget.get_alert()
+            thumb = self.liststore.get_value(i.iter, 3)
+            if thumb.get_alarm().check_expired():
+                alert = thumb.get_alert()
                 alert.show()
-                standalone = widget.get_standalone_widget()
+                standalone = thumb.get_standalone_widget()
                 standalone.set_ringing(True)
-                self.emit("show-standalone", widget)
+                self.emit("show-standalone", thumb)
         return True
 
     def _on_notification_activated(self, notif, action, data):
@@ -460,8 +461,8 @@ class Alarm(Clock):
         win.show_clock(self)
 
     def _on_item_activated(self, iconview, path):
-        alarm = self.liststore[path][3]
-        self.emit("show-standalone", alarm)
+        thumb = self.liststore[path][3]
+        self.emit("show-standalone", thumb)
 
     def _on_selection_changed(self, iconview):
         self.emit("selection-changed")
@@ -478,32 +479,29 @@ class Alarm(Clock):
 
     def delete_selected(self):
         selection = self.get_selection()
-        alarms = []
-        for path in selection:
-            alarms.append(self.liststore[path][-1])
+        alarms = [self.liststore[path][3].get_alarm() for path in selection]
         self.delete_alarms(alarms)
 
     def load_alarms(self):
         self.alarms = self.storage.load()
         for alarm in self.alarms:
-            self.add_alarm_widget(alarm)
+            self.add_alarm_thumbnail(alarm)
 
     def add_alarm(self, alarm):
         self.alarms.append(alarm)
         self.storage.save(self.alarms)
-        self.add_alarm_widget(alarm)
+        self.add_alarm_thumbnail(alarm)
         self.show_all()
 
-    def add_alarm_widget(self, alarm):
+    def add_alarm_thumbnail(self, alarm):
         alert = Alert("alarm-clock-elapsed", alarm.name,
                       self._on_notification_activated)
-        widget = AlarmWidget(self, alarm, alert)
+        thumb = AlarmThumbnail(self, alarm, alert)
         label = GLib.markup_escape_text(alarm.name)
         view_iter = self.liststore.append([False,
-                                           widget.get_pixbuf(),
+                                           thumb.get_pixbuf(),
                                            "<b>%s</b>" % label,
-                                           widget,
-                                           alarm])
+                                           thumb])
         self.notify("can-select")
 
     def update_alarm(self, old_alarm, new_alarm):
@@ -517,8 +515,7 @@ class Alarm(Clock):
         return self.alarms[i]
 
     def delete_alarms(self, alarms):
-        for a in alarms:
-            self.alarms.remove(a)
+        self.alarms = [a for a in self.alarms if a not in alarms]
         self.storage.save(self.alarms)
         self.iconview.unselect_all()
         self.liststore.clear()
diff --git a/gnomeclocks/utils.py b/gnomeclocks/utils.py
index 8607821..8944ffd 100644
--- a/gnomeclocks/utils.py
+++ b/gnomeclocks/utils.py
@@ -65,6 +65,18 @@ class SystemSettings:
         return systemClockFormat
 
 
+class TimeString:
+    @staticmethod
+    def format_time(t):
+        if SystemSettings.get_clock_format() == "12h":
+            res = time.strftime("%I:%M %p", t)
+        else:
+            res = time.strftime("%H:%M", t)
+        if res.startswith("0"):
+            res = res[1:]
+        return res
+
+
 class LocalizedWeekdays:
     # translate them ourselves since we want plurals
     _plural = [
diff --git a/gnomeclocks/world.py b/gnomeclocks/world.py
index 71d87da..ecb60d8 100644
--- a/gnomeclocks/world.py
+++ b/gnomeclocks/world.py
@@ -23,7 +23,7 @@ import json
 from gi.repository import GLib, GObject, Gio, Gtk, GdkPixbuf
 from gi.repository import GWeather
 from clocks import Clock
-from utils import Dirs, SystemSettings
+from utils import Dirs, SystemSettings, TimeString
 from widgets import DigitalClockDrawing, SelectableIconView, ContentView
 
 
@@ -51,7 +51,7 @@ class WorldClockStorage():
             for l in location_codes:
                 location = GWeather.Location.find_by_station_code(gweather_world, l)
                 if location:
-                    clock = DigitalClock(location)
+                    clock = ClockItem(location)
                     clocks.append(clock)
         except IOError as e:
             if e.errno == errno.ENOENT:
@@ -115,24 +115,19 @@ class NewWorldClockDialog(Gtk.Dialog):
 
     def _icon_released(self, icon_pos, event, data):
         if self.entry.get_icon_gicon(
-            Gtk.EntryIconPosition.SECONDARY) == self.clear_gicon:
+                Gtk.EntryIconPosition.SECONDARY) == self.clear_gicon:
             self.entry.set_text('')
             self.entry.set_icon_from_gicon(
-              Gtk.EntryIconPosition.SECONDARY, self.find_gicon)
+                Gtk.EntryIconPosition.SECONDARY, self.find_gicon)
             self.set_response_sensitive(1, False)
 
 
-class DigitalClock():
+class ClockItem():
     def __init__(self, location):
         self.location = location
-        self._last_sunrise = time.strptime("197007:00", "%Y%H:%M")
-        self.sunrise = self._last_sunrise
-        self._last_sunset = time.strptime("197019:00", "%Y%H:%M")
-        self.sunset = self._last_sunset
-        self.get_sunrise_sunset()
-
-        self.path = None
-        self.list_store = None
+        self.sunrise = time.strptime("197007:00", "%Y%H:%M")
+        self.sunset = time.strptime("197019:00", "%Y%H:%M")
+        self._update_sunrise_sunset()
 
         weather_timezone = self.location.get_timezone()
         timezone = GLib.TimeZone.new(weather_timezone.get_tzid())
@@ -145,12 +140,6 @@ class DigitalClock():
 
         self.offset = location_offset - here_offset
 
-        self._last_time = None
-        self.drawing = DigitalClockDrawing()
-        self.standalone = None
-        self._standalone_is_new = False
-        self.update()
-
     def get_location_time(self, secs=None):
         if not secs:
             secs = time.time()
@@ -158,40 +147,7 @@ class DigitalClock():
         t = time.localtime(t)
         return t
 
-    def update(self):
-        clock_format = SystemSettings.get_clock_format()
-        location_time = self.get_location_time()
-        if clock_format == '12h':
-            t = time.strftime("%I:%M %p", location_time)
-        else:
-            t = time.strftime("%H:%M", location_time)
-        if t.startswith("0"):
-            t = t[1:]
-        if not t == self._last_time \
-                or not self.sunrise == self._last_sunrise \
-                or not self.sunset == self._last_sunset \
-                or self._standalone_is_new:
-            is_light = self.get_is_light(location_time)
-            if is_light:
-                img = os.path.join(Dirs.get_image_dir(), "cities", "day.png")
-            else:
-                img = os.path.join(Dirs.get_image_dir(), "cities", "night.png")
-            day = self.get_day()
-            if day == "Today":
-                self.drawing.render(t, img, is_light)
-            else:
-                self.drawing.render(t, img, is_light, day)
-            if self.path and self.list_store:
-                self.list_store[self.path][1] = self.drawing.pixbuf
-            if self.standalone:
-                self.standalone.update(img, t, self.sunrise, self.sunset)
-                self._standalone_is_new = False
-
-            self._last_time = t
-            self._last_sunrise = self.sunrise
-            self._last_sunset = self.sunset
-
-    def get_sunrise_sunset(self):
+    def _update_sunrise_sunset(self):
         self.weather = GWeather.Info(location=self.location, world=gweather_world)
         self.weather.connect('updated', self._on_weather_updated)
         self.weather.update()
@@ -202,17 +158,9 @@ class DigitalClock():
         ok, sunset = weather.get_value_sunset()
         self.sunrise = self.get_location_time(sunrise)
         self.sunset = self.get_location_time(sunset)
-        self.update()
 
-    def get_pixbuf(self):
-        return self.drawing.pixbuf
-
-    def get_standalone_widget(self):
-        if not self.standalone:
-            self.standalone = StandaloneClock(self.location, self.sunrise, self.sunset)
-            self._standalone_is_new = True
-        self.update()
-        return self.standalone
+    def get_time_as_string(self):
+        return TimeString.format_time(self.get_location_time())
 
     def get_day(self):
         clock_time_day = self.get_location_time().tm_yday
@@ -235,7 +183,13 @@ class DigitalClock():
             else:
                 return "Yesterday"
 
-    def get_is_light(self, current):
+    def get_sunrise_sunset_as_strings(self):
+        sunrise = TimeString.format_time(self.sunrise)
+        sunset = TimeString.format_time(self.sunset)
+        return (sunrise, sunset)
+
+    def get_is_light(self):
+        current = self.get_location_time()
         if current.tm_hour < self.sunrise.tm_hour \
                 or current.tm_hour > self.sunset.tm_hour:
             return False
@@ -253,21 +207,49 @@ class DigitalClock():
             else:
                 return False
 
-    def set_path(self, list_store, path):
-        self.path = path
-        self.list_store = list_store
+
+class ClockThumbnail():
+    def __init__(self, clock):
+        self.clock = clock
+        self.drawing = DigitalClockDrawing()
+        self.standalone = None
+        self.update()
+
+    def update(self):
+        timestr = self.clock.get_time_as_string()
+        is_light = self.clock.get_is_light()
+        if is_light:
+            img = os.path.join(Dirs.get_image_dir(), "cities", "day.png")
+        else:
+            img = os.path.join(Dirs.get_image_dir(), "cities", "night.png")
+        day = self.clock.get_day()
+        if day == "Today":
+            self.drawing.render(timestr, img, is_light)
+        else:
+            self.drawing.render(timestr, img, is_light, day)
+        if self.standalone:
+            self.standalone.update()
+
+    def get_clock(self):
+        return self.clock
+
+    def get_pixbuf(self):
+        return self.drawing.pixbuf
+
+    def get_standalone_widget(self):
+        if not self.standalone:
+            self.standalone = StandaloneClock(self.clock)
+        return self.standalone
 
 
 class StandaloneClock(Gtk.EventBox):
-    def __init__(self, location, sunrise, sunset):
+    def __init__(self, clock):
         Gtk.EventBox.__init__(self)
         self.get_style_context().add_class('view')
         self.get_style_context().add_class('content-view')
-        self.location = location
+        self.clock = clock
         self.can_edit = False
         self.time_label = Gtk.Label()
-        self.sunrise = sunrise
-        self.sunset = sunset
 
         self.clock_format = None
 
@@ -321,35 +303,21 @@ class StandaloneClock(Gtk.EventBox):
         hbox.pack_start(Gtk.Label(), True, True, 0)
         self.vbox.pack_end(hbox, False, False, 30)
 
+        self.update()
         self.show_all()
 
     def get_name(self):
-        return GLib.markup_escape_text(self.location.get_city_name())
+        return GLib.markup_escape_text(self.clock.location.get_city_name())
 
-    def update(self, img, text, sunrise, sunset):
-        size = 72000  # FIXME: (self.get_allocation().height / 300) * 72000
+    def update(self):
+        timestr = self.clock.get_time_as_string()
+        sunrisestr, sunsetstr = self.clock.get_sunrise_sunset_as_strings()
         self.time_label.set_markup(
-            "<span size='%i' color='dimgray'><b>%s</b></span>" % (size, text))
-        clock_format = SystemSettings.get_clock_format()
-        if clock_format != self.clock_format or \
-                sunrise != self.sunrise or sunset != self.sunset:
-            self.sunrise = sunrise
-            self.sunset = sunset
-            if clock_format == "12h":
-                sunrise_str = time.strftime("%I:%M %p", sunrise)
-                sunset_str = time.strftime("%I:%M %p", sunset)
-            else:
-                sunrise_str = time.strftime("%H:%M", sunrise)
-                sunset_str = time.strftime("%H:%M", sunset)
-            if sunrise_str.startswith("0"):
-                sunrise_str = sunrise_str[1:]
-            if sunset_str.startswith("0"):
-                sunset_str = sunset_str[1:]
-            self.sunrise_time_label.set_markup(
-                "<span size ='large'>%s</span>" % sunrise_str)
-            self.sunset_time_label.set_markup(
-                "<span size ='large'>%s</span>" % sunset_str)
-        self.clock_format = clock_format
+            "<span size='72000' color='dimgray'><b>%s</b></span>" % timestr)
+        self.sunrise_time_label.set_markup(
+            "<span size ='large'>%s</span>" % sunrisestr)
+        self.sunset_time_label.set_markup(
+            "<span size ='large'>%s</span>" % sunsetstr)
 
 
 class World(Clock):
@@ -365,8 +333,8 @@ class World(Clock):
         self.iconview = SelectableIconView(self.liststore, 0, 1, 2)
 
         contentview = ContentView(self.iconview,
-                "document-open-recent-symbolic",
-                 _("Select <b>New</b> to add a world clock"))
+                                  "document-open-recent-symbolic",
+                                  _("Select <b>New</b> to add a world clock"))
         self.add(contentview)
 
         self.iconview.connect("item-activated", self._on_item_activated)
@@ -380,13 +348,14 @@ class World(Clock):
         self.timeout_id = GLib.timeout_add(1000, self._update_clocks)
 
     def _update_clocks(self):
-        for c in self.clocks:
-            c.update()
+        for i in self.liststore:
+            thumb = self.liststore.get_value(i.iter, 3)
+            thumb.update()
         return True
 
     def _on_item_activated(self, iconview, path):
-        d = self.liststore[path][3]
-        self.emit("show-standalone", d)
+        thumb = self.liststore[path][3]
+        self.emit("show-standalone", thumb)
 
     def _on_selection_changed(self, iconview):
         self.emit("selection-changed")
@@ -403,41 +372,37 @@ class World(Clock):
 
     def delete_selected(self):
         selection = self.get_selection()
-        items = []
-        for treepath in selection:
-            items.append(self.liststore[treepath][3])
-        self.delete_clocks(items)
+        clocks = [self.liststore[path][3].get_clock() for path in selection]
+        self.delete_clocks(clocks)
 
     def load_clocks(self):
         self.clocks = self.storage.load()
         for clock in self.clocks:
-            self.add_clock_widget(clock)
+            self.add_clock_thumbnail(clock)
 
     def add_clock(self, location):
-        for c in self.clocks:
-            if c.location.get_code() == location.get_code():
-                # duplicate
-                return
-        clock = DigitalClock(location)
+        if location.get_code() in [c.location.get_code() for c in self.clocks]:
+            # duplicate
+            return
+        clock = ClockItem(location)
         self.clocks.append(clock)
         self.storage.save(self.clocks)
-        self.add_clock_widget(clock)
+        self.add_clock_thumbnail(clock)
         self.show_all()
 
-    def add_clock_widget(self, clock):
+    def add_clock_thumbnail(self, clock):
         name = clock.location.get_city_name()
+        thumb = ClockThumbnail(clock)
         label = GLib.markup_escape_text(name)
         view_iter = self.liststore.append([False,
-                                           clock.get_pixbuf(),
+                                           thumb.get_pixbuf(),
                                            "<b>%s</b>" % label,
-                                           clock])
+                                           thumb])
         path = self.liststore.get_path(view_iter)
-        clock.set_path(self.liststore, path)
         self.notify("can-select")
 
     def delete_clocks(self, clocks):
-        for c in clocks:
-            self.clocks.remove(c)
+        self.clocks = [c for c in self.clocks if c not in clocks]
         self.storage.save(self.clocks)
         self.iconview.unselect_all()
         self.liststore.clear()



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