[gnome-clocks] Reorganize code



commit e4e79d757c40abb61305378b784d2655ef8a5312
Author: Paolo Borelli <pborelli gnome org>
Date:   Mon Aug 27 18:40:50 2012 +0200

    Reorganize code
    
    Split into four modules corresponding to the views of the application
    (world, alarm, stopwatch and timer).

 .gitignore               |    4 +-
 gnomeclocks/alarm.py     |  294 +++++++++++++++++++++++++++-
 gnomeclocks/app.py       |    8 +-
 gnomeclocks/clocks.py    |  468 ++------------------------------------------
 gnomeclocks/stopwatch.py |  134 +++++++++++++
 gnomeclocks/storage.py   |   86 --------
 gnomeclocks/timer.py     |  189 +++++++++++-------
 gnomeclocks/utils.py     |    8 -
 gnomeclocks/widgets.py   |  495 +++++-----------------------------------------
 gnomeclocks/world.py     |  483 ++++++++++++++++++++++++++++++++++++++++++++
 po/POTFILES.in           |    3 +
 11 files changed, 1096 insertions(+), 1076 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 2a45e02..f94e24d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-src/Makefile
-src/Makefile.in
+build
+*.pyc
 po/gnome-clocks.pot
 po/untitled.pot
diff --git a/gnomeclocks/alarm.py b/gnomeclocks/alarm.py
index 19c6970..68e2edf 100644
--- a/gnomeclocks/alarm.py
+++ b/gnomeclocks/alarm.py
@@ -17,10 +17,14 @@
 # Author: Seif Lotfy <seif lotfy collabora co uk>
 
 import os
-from datetime import datetime
 import vobject
-
-from utils import Dirs, SystemSettings
+import time
+from datetime import datetime
+from gi.repository import GLib, GObject, Gio, Gtk, GdkPixbuf
+from gi.repository import GWeather
+from clocks import Clock
+from utils import Dirs, SystemSettings, Alert
+from widgets import DigitalClockDrawing, SelectableIconView, ContentView
 
 
 class ICSHandler():
@@ -168,3 +172,287 @@ class AlarmItem:
             return False
         self.expired = datetime.now() > self.time
         return self.expired
+
+
+class AlarmDialog(Gtk.Dialog):
+    def __init__(self, alarm_view, parent, vevent=None):
+        self.vevent = vevent
+        if vevent:
+            Gtk.Dialog.__init__(self, _("Edit Alarm"), parent)
+        else:
+            Gtk.Dialog.__init__(self, _("New Alarm"), parent)
+        self.set_border_width(6)
+        self.parent = parent
+        self.set_transient_for(parent)
+        self.set_modal(True)
+        self.day_buttons = []
+
+        content_area = self.get_content_area()
+        self.add_buttons(Gtk.STOCK_CANCEL, 0, Gtk.STOCK_SAVE, 1)
+
+        self.cf = SystemSettings.get_clock_format()
+        grid = Gtk.Grid()
+        grid.set_row_spacing(9)
+        grid.set_column_spacing(6)
+        grid.set_border_width(6)
+        content_area.pack_start(grid, True, True, 0)
+
+        if vevent:
+            t = vevent.dtstart.value
+            h = int(t.strftime("%I"))
+            m = int(t.strftime("%m"))
+            p = t.strftime("%p")
+            name = vevent.summary.value
+            repeat = self.get_repeat_days_from_vevent(vevent)
+        else:
+            t = time.localtime()
+            h = t.tm_hour
+            m = t.tm_min
+            p = time.strftime("%p", t)
+            name = _("New Alarm")
+            repeat = []
+
+        label = Gtk.Label(_("Time"))
+        label.set_alignment(1.0, 0.5)
+        grid.attach(label, 0, 0, 1, 1)
+
+        self.hourselect = Gtk.SpinButton()
+        self.hourselect.set_increments(1.0, 1.0)
+        self.hourselect.set_wrap(True)
+        grid.attach(self.hourselect, 1, 0, 1, 1)
+
+        label = Gtk.Label(": ")
+        label.set_alignment(0.5, 0.5)
+        grid.attach(label, 2, 0, 1, 1)
+
+        self.minuteselect = Gtk.SpinButton()
+        self.minuteselect.set_increments(1.0, 1.0)
+        self.minuteselect.set_wrap(True)
+        self.minuteselect.connect('output', self.show_leading_zeros)
+        self.minuteselect.set_range(0.0, 59.0)
+        self.minuteselect.set_value(m)
+        grid.attach(self.minuteselect, 3, 0, 1, 1)
+
+        if self.cf == "12h":
+            self.ampm = Gtk.ComboBoxText()
+            self.ampm.append_text("AM")
+            self.ampm.append_text("PM")
+            if p == "PM":
+                h = h - 12
+                self.ampm.set_active(1)
+            else:
+                self.ampm.set_active(0)
+            grid.attach(self.ampm, 4, 0, 1, 1)
+            self.hourselect.set_range(1.0, 12.0)
+            self.hourselect.set_value(h)
+            gridcols = 5
+        else:
+            self.hourselect.set_range(0.0, 23.0)
+            self.hourselect.set_value(h)
+            gridcols = 4
+
+        label = Gtk.Label(_("Name"))
+        label.set_alignment(1.0, 0.5)
+        grid.attach(label, 0, 1, 1, 1)
+
+        self.entry = Gtk.Entry()
+        self.entry.set_text(name)
+        self.entry.set_editable(True)
+        grid.attach(self.entry, 1, 1, gridcols - 1, 1)
+
+        label = Gtk.Label(_("Repeat Every"))
+        label.set_alignment(1.0, 0.5)
+        grid.attach(label, 0, 2, 1, 1)
+
+        # create a box and put repeat days in it
+        box = Gtk.Box(True, 0)
+        box.get_style_context().add_class("linked")
+        for day in ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]:
+            btn = Gtk.ToggleButton(label=_(day))
+            if btn.get_label()[:2]  in repeat:
+                btn.set_active(True)
+            box.pack_start(btn, True, True, 0)
+            self.day_buttons.append(btn)
+        grid.attach(box, 1, 2, gridcols - 1, 1)
+
+    def show_leading_zeros(self, spin_button):
+        spin_button.set_text('{: 02d}'.format(spin_button.get_value_as_int()))
+        return True
+
+    def get_repeat_days_from_vevent(self, vevent):
+        rrule = vevent.rrule.value
+        repeat = []
+        if rrule[5] == 'W':
+            days = rrule[18:]
+            repeat = days.split(",")
+        return repeat
+
+    def get_alarm_item(self):
+        name = self.entry.get_text()
+        h = self.hourselect.get_value_as_int()
+        m = self.minuteselect.get_value_as_int()
+        if self.cf == "12h":
+            r = self.ampm.get_active()
+            if r == 0:
+                p = "AM"
+            else:
+                p = "PM"
+        else:
+            p = None
+        repeat = []
+        for btn in self.day_buttons:
+            if btn.get_active():
+                repeat.append(btn.get_label()[:2])
+        alarm_item = AlarmItem(name, repeat, h, m, p)
+        return alarm_item
+
+
+class AlarmWidget():
+    def __init__(self, time_given, repeat):
+        self.drawing = DigitalClockDrawing()
+        t = time_given
+        isDay = self.get_is_day(int(t[:2]))
+        if isDay:
+            img = os.path.join(Dirs.get_image_dir(), "cities", "day.png")
+        else:
+            img = os.path.join(Dirs.get_image_dir(), "cities", "night.png")
+        self.drawing.render(t, img, isDay, repeat)
+
+    def get_is_day(self, hours):
+        if hours > 7 and hours < 19:
+            return True
+        else:
+            return False
+
+    def get_pixbuf(self):
+        return self.drawing.pixbuf
+
+
+class Alarm(Clock):
+    def __init__(self):
+        Clock.__init__(self, _("Alarm"), True, True)
+
+        self.liststore = Gtk.ListStore(bool,
+                                       GdkPixbuf.Pixbuf,
+                                       str,
+                                       GObject.TYPE_PYOBJECT,
+                                       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"))
+        self.add(contentview)
+
+        self.iconview.connect("item-activated", self._on_item_activated)
+        self.iconview.connect("selection-changed", self._on_selection_changed)
+
+        self.load_alarms()
+        self.show_all()
+
+        self.timeout_id = GObject.timeout_add(1000, self._check_alarms)
+
+    def _check_alarms(self):
+        for i in self.liststore:
+            alarm = self.liststore.get_value(i.iter, 5)
+            if alarm.check_expired():
+                print alarm
+                alert = self.liststore.get_value(i.iter, 4)
+                alert.show()
+        return True
+
+    def _on_notification_activated(self, notif, action, data):
+        win = self.get_toplevel()
+        win.show_clock(self)
+
+    def _on_item_activated(self, iconview, path):
+        alarm = self.liststore[path][-1]
+        self.open_edit_dialog(alarm.get_vevent())
+
+    def _on_selection_changed(self, iconview):
+        self.emit("selection-changed")
+
+    def set_selection_mode(self, active):
+        self.iconview.set_selection_mode(active)
+
+    @GObject.Property(type=bool, default=False)
+    def can_select(self):
+        return len(self.liststore) != 0
+
+    def get_selection(self):
+        return self.iconview.get_selection()
+
+    def delete_selected(self):
+        selection = self.get_selection()
+        items = []
+        for treepath in selection:
+            v = self.liststore[treepath][-1].get_vevent()
+            items.append(v.uid.value)
+        self.delete_alarms(items)
+
+    def load_alarms(self):
+        handler = ICSHandler()
+        vevents = handler.load_vevents()
+        for vevent in vevents:
+            alarm = AlarmItem()
+            alarm.new_from_vevent(vevent)
+            self.add_alarm_widget(alarm)
+
+    def add_alarm(self, alarm):
+        handler = ICSHandler()
+        handler.add_vevent(alarm.get_vevent())
+        self.add_alarm_widget(alarm)
+        self.show_all()
+        vevents = handler.load_vevents()
+
+    def add_alarm_widget(self, alarm):
+        name = alarm.get_alarm_name()
+        timestr = alarm.get_time_as_string()
+        repeat = alarm.get_alarm_repeat_string()
+        widget = AlarmWidget(timestr, repeat)
+        alert = Alert("alarm-clock-elapsed", name,
+                      self._on_notification_activated)
+        label = GLib.markup_escape_text(name)
+        view_iter = self.liststore.append([False,
+                                           widget.get_pixbuf(),
+                                           "<b>%s</b>" % label,
+                                           widget,
+                                           alert,
+                                           alarm])
+        self.notify("can-select")
+
+    def edit_alarm(self, old_vevent, alarm):
+        handler = ICSHandler()
+        handler.update_vevent(old_vevent, alarm.get_vevent())
+        self.iconview.unselect_all()
+        self.liststore.clear()
+        self.load_alarms()
+
+    def delete_alarms(self, alarms):
+        handler = ICSHandler()
+        handler.remove_vevents(alarms)
+        self.iconview.unselect_all()
+        self.liststore.clear()
+        self.load_alarms()
+        self.notify("can-select")
+
+    def open_new_dialog(self):
+        window = AlarmDialog(self, self.get_toplevel())
+        window.connect("response", self.on_dialog_response, None)
+        window.show_all()
+
+    def open_edit_dialog(self, vevent):
+        window = AlarmDialog(self, self.get_toplevel(), vevent)
+        window.connect("response", self.on_dialog_response, vevent)
+        window.show_all()
+
+    def on_dialog_response(self, dialog, response, old_vevent):
+        if response == 1:
+            alarm = dialog.get_alarm_item()
+            if old_vevent:
+                self.edit_alarm(old_vevent, alarm)
+            else:
+                self.add_alarm(alarm)
+        dialog.destroy()
diff --git a/gnomeclocks/app.py b/gnomeclocks/app.py
index 08936d8..be2f697 100644
--- a/gnomeclocks/app.py
+++ b/gnomeclocks/app.py
@@ -20,7 +20,11 @@ import os
 import sys
 from gettext import ngettext
 from gi.repository import Gtk, Gdk, GObject, GLib, Gio, GtkClutter
-from clocks import Clock, World, Alarm, Timer, Stopwatch
+from clocks import Clock
+from world import World
+from alarm import Alarm
+from stopwatch import Stopwatch
+from timer import Timer
 from widgets import Embed
 from utils import Dirs
 from gnomeclocks import __version__, AUTHORS, COPYRIGHTS
@@ -50,7 +54,7 @@ class Window(Gtk.ApplicationWindow):
                                          Gtk.STYLE_PROVIDER_PRIORITY_USER)
 
         self.set_size_request(640, 480)
-        self.vbox = Gtk.VBox()
+        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
         self.embed = Embed(self.vbox)
         self.add(self.embed)
         self.notebook = Gtk.Notebook()
diff --git a/gnomeclocks/clocks.py b/gnomeclocks/clocks.py
index 0e1efbe..52772f3 100644
--- a/gnomeclocks/clocks.py
+++ b/gnomeclocks/clocks.py
@@ -16,31 +16,21 @@
 #
 # Author: Seif Lotfy <seif lotfy collabora co uk>
 
-from gi.repository import Gtk, GLib, GObject, Gio
-from gi.repository.GdkPixbuf import Pixbuf
-
-from widgets import NewWorldClockDialog, AlarmDialog
-from widgets import DigitalClock, AlarmWidget, SelectableIconView, ContentView
-from widgets import TogglePixbufRenderer
-from storage import worldclockstorage
-from utils import SystemSettings, Alert
-
-from timer import TimerWelcomeScreen, TimerScreen
-from alarm import AlarmItem, ICSHandler
-
-import time
-
-STOPWATCH_LABEL_MARKUP = "<span font_desc=\"64.0\">%02i:%02i</span>"
-STOPWATCH_BUTTON_MARKUP = "<span font_desc=\"18.0\">%s</span>"
+from gi.repository import GObject, Gtk
 
 
 class Clock(Gtk.EventBox):
-    __gsignals__ = {'show-requested': (GObject.SignalFlags.RUN_LAST,
-                    None, ()),
-                    'show-clock': (GObject.SignalFlags.RUN_LAST,
-                    None, (GObject.TYPE_PYOBJECT, )),
-                    'selection-changed': (GObject.SignalFlags.RUN_LAST,
-                    None, ())}
+    __gsignals__ = {
+        'show-requested': (GObject.SignalFlags.RUN_LAST,
+                           None,
+                           ()),
+        'show-clock': (GObject.SignalFlags.RUN_LAST,
+                       None,
+                       (GObject.TYPE_PYOBJECT, )),
+        'selection-changed': (GObject.SignalFlags.RUN_LAST,
+                              None,
+                              ())
+    }
 
     def __init__(self, label, hasNew=False, hasSelectionMode=False):
         Gtk.EventBox.__init__(self)
@@ -61,437 +51,3 @@ class Clock(Gtk.EventBox):
 
     def delete_selected(self):
         pass
-
-
-class World(Clock):
-    def __init__(self):
-        Clock.__init__(self, _("World"), True, True)
-
-        self.liststore = Gtk.ListStore(bool,
-                                       Pixbuf,
-                                       str,
-                                       GObject.TYPE_PYOBJECT)
-
-        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"))
-        self.add(contentview)
-
-        self.iconview.connect("item-activated", self._on_item_activated)
-        self.iconview.connect("selection-changed", self._on_selection_changed)
-
-        self.clocks = []
-        self.load_clocks()
-        self.show_all()
-
-    def _on_item_activated(self, iconview, path):
-        d = self.liststore[path][3]
-        self.emit("show-clock", d)
-
-    def _on_selection_changed(self, iconview):
-        self.emit("selection-changed")
-
-    def set_selection_mode(self, active):
-        self.iconview.set_selection_mode(active)
-
-    @GObject.Property(type=bool, default=False)
-    def can_select(self):
-        return len(self.liststore) != 0
-
-    def get_selection(self):
-        return self.iconview.get_selection()
-
-    def delete_selected(self):
-        selection = self.get_selection()
-        items = []
-        for treepath in selection:
-            items.append(self.liststore[treepath][3])
-        self.delete_clocks(items)
-
-    def load_clocks(self):
-        self.clocks = worldclockstorage.load_clocks()
-        for clock in self.clocks:
-            self.add_clock_widget(clock)
-
-    def add_clock(self, location):
-        location_id = location.id + "---" + location.location.get_code()
-        if not location_id in worldclockstorage.locations_dump:
-            self.clocks.append(location)
-            self.add_clock_widget(location)
-            self.show_all()
-        worldclockstorage.save_clocks(self.clocks)
-
-    def add_clock_widget(self, location):
-        d = DigitalClock(location)
-        name = d.location.get_city_name()
-        label = GLib.markup_escape_text(name)
-        view_iter = self.liststore.append([False,
-                                           d.get_pixbuf(),
-                                           "<b>%s</b>" % label,
-                                           d])
-        path = self.liststore.get_path(view_iter)
-        d.set_path(self.liststore, path)
-        self.notify("can-select")
-
-    def delete_clocks(self, clocks):
-        for d in clocks:
-            d.stop_update()
-            self.clocks.remove(d._location)
-        worldclockstorage.save_clocks(self.clocks)
-        self.iconview.unselect_all()
-        self.liststore.clear()
-        self.load_clocks()
-        self.notify("can-select")
-
-    def open_new_dialog(self):
-        window = NewWorldClockDialog(self.get_toplevel())
-        window.connect("response", self.on_dialog_response)
-        window.show_all()
-
-    def on_dialog_response(self, dialog, response):
-        if response == 1:
-            l = dialog.get_location()
-            self.add_clock(l)
-        dialog.destroy()
-
-
-class Alarm(Clock):
-    def __init__(self):
-        Clock.__init__(self, _("Alarm"), True, True)
-
-        self.liststore = Gtk.ListStore(bool,
-                                       Pixbuf,
-                                       str,
-                                       GObject.TYPE_PYOBJECT,
-                                       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"))
-        self.add(contentview)
-
-        self.iconview.connect("item-activated", self._on_item_activated)
-        self.iconview.connect("selection-changed", self._on_selection_changed)
-
-        self.load_alarms()
-        self.show_all()
-
-        self.timeout_id = GObject.timeout_add(1000, self._check_alarms)
-
-    def _check_alarms(self):
-        for i in self.liststore:
-            alarm = self.liststore.get_value(i.iter, 5)
-            if alarm.check_expired():
-                print alarm
-                alert = self.liststore.get_value(i.iter, 4)
-                alert.show()
-        return True
-
-    def _on_notification_activated(self, notif, action, data):
-        win = self.get_toplevel()
-        win.show_clock(self)
-
-    def _on_item_activated(self, iconview, path):
-        alarm = self.liststore[path][-1]
-        self.open_edit_dialog(alarm.get_vevent())
-
-    def _on_selection_changed(self, iconview):
-        self.emit("selection-changed")
-
-    def set_selection_mode(self, active):
-        self.iconview.set_selection_mode(active)
-
-    @GObject.Property(type=bool, default=False)
-    def can_select(self):
-        return len(self.liststore) != 0
-
-    def get_selection(self):
-        return self.iconview.get_selection()
-
-    def delete_selected(self):
-        selection = self.get_selection()
-        items = []
-        for treepath in selection:
-            v = self.liststore[treepath][-1].get_vevent()
-            items.append(v.uid.value)
-        self.delete_alarms(items)
-
-    def load_alarms(self):
-        handler = ICSHandler()
-        vevents = handler.load_vevents()
-        for vevent in vevents:
-            alarm = AlarmItem()
-            alarm.new_from_vevent(vevent)
-            self.add_alarm_widget(alarm)
-
-    def add_alarm(self, alarm):
-        handler = ICSHandler()
-        handler.add_vevent(alarm.get_vevent())
-        self.add_alarm_widget(alarm)
-        self.show_all()
-        vevents = handler.load_vevents()
-
-    def add_alarm_widget(self, alarm):
-        name = alarm.get_alarm_name()
-        timestr = alarm.get_time_as_string()
-        repeat = alarm.get_alarm_repeat_string()
-        widget = AlarmWidget(timestr, repeat)
-        alert = Alert("alarm-clock-elapsed", name,
-                      self._on_notification_activated)
-        label = GLib.markup_escape_text(name)
-        view_iter = self.liststore.append([False,
-                                           widget.get_pixbuf(),
-                                           "<b>%s</b>" % label,
-                                           widget,
-                                           alert,
-                                           alarm])
-        self.notify("can-select")
-
-    def edit_alarm(self, old_vevent, alarm):
-        handler = ICSHandler()
-        handler.update_vevent(old_vevent, alarm.get_vevent())
-        self.iconview.unselect_all()
-        self.liststore.clear()
-        self.load_alarms()
-
-    def delete_alarms(self, alarms):
-        handler = ICSHandler()
-        handler.remove_vevents(alarms)
-        self.iconview.unselect_all()
-        self.liststore.clear()
-        self.load_alarms()
-        self.notify("can-select")
-
-    def open_new_dialog(self):
-        window = AlarmDialog(self, self.get_toplevel())
-        window.connect("response", self.on_dialog_response, None)
-        window.show_all()
-
-    def open_edit_dialog(self, vevent):
-        window = AlarmDialog(self, self.get_toplevel(), vevent)
-        window.connect("response", self.on_dialog_response, vevent)
-        window.show_all()
-
-    def on_dialog_response(self, dialog, response, old_vevent):
-        if response == 1:
-            alarm = dialog.get_alarm_item()
-            if old_vevent:
-                self.edit_alarm(old_vevent, alarm)
-            else:
-                self.add_alarm(alarm)
-        dialog.destroy()
-
-
-class Stopwatch(Clock):
-
-    class State:
-        RESET = 0
-        RUNNING = 1
-        STOPPED = 2
-
-    def __init__(self):
-        Clock.__init__(self, _("Stopwatch"))
-        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-        self.add(vbox)
-
-        center = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-
-        self.stopwatchLabel = Gtk.Label()
-        self.stopwatchLabel.set_alignment(0.5, 0.5)
-        self.stopwatchLabel.set_markup(STOPWATCH_LABEL_MARKUP % (0, 0))
-
-        hbox = Gtk.Box()
-        self.leftButton = Gtk.Button()
-        self.leftButton.set_size_request(200, -1)
-        self.leftLabel = Gtk.Label()
-        self.leftButton.add(self.leftLabel)
-        self.rightButton = Gtk.Button()
-        self.rightButton.set_size_request(200, -1)
-        self.rightLabel = Gtk.Label()
-        self.rightButton.add(self.rightLabel)
-        self.rightButton.set_sensitive(False)
-        self.leftButton.get_style_context().add_class("clocks-go")
-        #self.rightButton.get_style_context().add_class("clocks-lap")
-
-        hbox.pack_start(Gtk.Box(), True, False, 0)
-        hbox.pack_start(self.leftButton, False, False, 0)
-        hbox.pack_start(Gtk.Box(), False, False, 24)
-        hbox.pack_start(self.rightButton, False, False, 0)
-        hbox.pack_start(Gtk.Box(), True, False, 0)
-
-        self.leftLabel.set_markup(STOPWATCH_BUTTON_MARKUP % (_("Start")))
-        self.leftLabel.set_padding(6, 0)
-        self.rightLabel.set_markup(STOPWATCH_BUTTON_MARKUP % (_("Reset")))
-        self.rightLabel.set_padding(6, 0)
-
-        center.pack_start(self.stopwatchLabel, False, False, 0)
-        center.pack_start(Gtk.Box(), True, True, 41)
-        center.pack_start(hbox, False, False, 0)
-
-        self.state = Stopwatch.State.RESET
-        self.g_id = 0
-        self.start_time = 0
-        self.time_diff = 0
-
-        vbox.pack_start(Gtk.Box(), True, True, 48)
-        vbox.pack_start(center, False, False, 0)
-        vbox.pack_start(Gtk.Box(), True, True, 1)
-        vbox.pack_start(Gtk.Box(), True, True, 41)
-
-        self.leftButton.connect("clicked", self._on_left_button_clicked)
-        self.rightButton.connect("clicked", self._on_right_button_clicked)
-
-    def _on_left_button_clicked(self, widget):
-        if self.state in (Stopwatch.State.RESET, Stopwatch.State.STOPPED):
-            self.state = Stopwatch.State.RUNNING
-            self.start()
-            self.leftLabel.set_markup(STOPWATCH_BUTTON_MARKUP % (_("Stop")))
-            self.leftButton.get_style_context().add_class("clocks-stop")
-            self.rightButton.set_sensitive(True)
-        elif self.state == Stopwatch.State.RUNNING:
-            self.state = Stopwatch.State.STOPPED
-            self.stop()
-            self.leftLabel.set_markup(STOPWATCH_BUTTON_MARKUP %
-                (_("Continue")))
-            self.rightLabel.set_markup(STOPWATCH_BUTTON_MARKUP %
-                (_("Reset")))
-            self.leftButton.get_style_context().remove_class("clocks-stop")
-            self.leftButton.get_style_context().add_class("clocks-go")
-
-    def _on_right_button_clicked(self, widget):
-        if self.state == Stopwatch.State.RUNNING:
-            pass
-        if self.state == Stopwatch.State.STOPPED:
-            self.state = Stopwatch.State.RESET
-            self.time_diff = 0
-            self.leftLabel.set_markup(STOPWATCH_BUTTON_MARKUP % (_("Start")))
-            self.leftButton.get_style_context().add_class("clocks-go")
-            #self.rightButton.get_style_context().add_class("clocks-lap")
-            self.stopwatchLabel.set_markup(STOPWATCH_LABEL_MARKUP % (0, 0))
-            self.rightButton.set_sensitive(False)
-
-    def start(self):
-        if self.g_id == 0:
-            self.start_time = time.time()
-            self.g_id = GObject.timeout_add(10, self.count)
-
-    def stop(self):
-        GObject.source_remove(self.g_id)
-        self.g_id = 0
-        self.time_diff = self.time_diff + (time.time() - self.start_time)
-
-    def reset(self):
-        self.time_diff = 0
-        GObject.source_remove(self.g_id)
-        self.g_id = 0
-
-    def count(self):
-        timediff = time.time() - self.start_time + self.time_diff
-        elapsed_minutes, elapsed_seconds = divmod(timediff, 60)
-        self.stopwatchLabel.set_markup(STOPWATCH_LABEL_MARKUP %
-            (elapsed_minutes, elapsed_seconds))
-        return True
-
-
-class Timer(Clock):
-
-    class State:
-        STOPPED = 0
-        RUNNING = 1
-        PAUSED = 2
-
-    def __init__(self):
-        Clock.__init__(self, _("Timer"))
-        self.state = Timer.State.STOPPED
-        self.g_id = 0
-
-        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-        box = Gtk.Box()
-        self.add(box)
-        box.pack_start(Gtk.Box(), True, True, 0)
-        box.pack_start(self.vbox, False, False, 0)
-        box.pack_end(Gtk.Box(), True, True, 0)
-
-        self.timerbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-        self.vbox.pack_start(Gtk.Box(), True, True, 0)
-        self.vbox.pack_start(self.timerbox, False, False, 0)
-        self.vbox.pack_start(Gtk.Box(), True, True, 0)
-        self.vbox.pack_start(Gtk.Box(), True, True, 46)
-
-        self.timer_welcome_screen = TimerWelcomeScreen(self)
-        self.timer_screen = TimerScreen(self)
-        self.show_timer_welcome_screen()
-
-        self.alert = Alert("complete", "Ta Da !",
-                           self._on_notification_activated)
-
-    def _on_notification_activated(self, notif, action, data):
-        win = self.get_toplevel()
-        win.show_clock(self)
-
-    def show_timer_welcome_screen(self):
-        self.timerbox.pack_start(self.timer_welcome_screen, True, True, 0)
-        self.timer_welcome_screen.update_start_button_status()
-
-    def start_timer_screen(self):
-        self.timerbox.remove(self.timer_welcome_screen)
-        self.timerbox.pack_start(self.timer_screen, True, True, 0)
-        self.timerbox.show_all()
-
-    def end_timer_screen(self):
-        self.timerbox.remove(self.timer_screen)
-        self.show_timer_welcome_screen()
-        self.timer_welcome_screen.hours.set_value(0)
-        self.timer_welcome_screen.minutes.set_value(0)
-        self.timer_welcome_screen.seconds.set_value(0)
-        self.timer_welcome_screen.update_start_button_status()
-
-    def start(self):
-        if self.g_id == 0:
-            hours = self.timer_welcome_screen.hours.get_value()
-            minutes = self.timer_welcome_screen.minutes.get_value()
-            seconds = self.timer_welcome_screen.seconds.get_value()
-            self.timer_screen.set_time(hours, minutes, seconds)
-            self.time = (hours * 60 * 60) + (minutes * 60) + seconds
-            self.state = Timer.State.RUNNING
-            self.g_id = GObject.timeout_add(1000, self.count)
-            self.start_timer_screen()
-
-    def reset(self):
-        self.state = Timer.State.STOPPED
-        self.end_timer_screen()
-        if self.g_id != 0:
-            GObject.source_remove(self.g_id)
-        self.g_id = 0
-
-    def pause(self):
-        self.state = Timer.State.PAUSED
-        GObject.source_remove(self.g_id)
-        self.g_id = 0
-
-    def cont(self):
-        self.state = Timer.State.RUNNING
-        self.g_id = GObject.timeout_add(1000, self.count)
-
-    def count(self):
-        self.time -= 1
-        minutes, seconds = divmod(self.time, 60)
-        hours, minutes = divmod(minutes, 60)
-
-        self.timer_screen.set_time(hours, minutes, seconds)
-        if hours == 00 and minutes == 00 and seconds == 00:
-            self.alert.show()
-            self.state = Timer.State.STOPPED
-            self.timerbox.remove(self.timer_screen)
-            self.show_timer_welcome_screen()
-            if self.g_id != 0:
-                GObject.source_remove(self.g_id)
-            self.g_id = 0
-            return False
-        else:
-            return True
diff --git a/gnomeclocks/stopwatch.py b/gnomeclocks/stopwatch.py
new file mode 100644
index 0000000..5b8daf7
--- /dev/null
+++ b/gnomeclocks/stopwatch.py
@@ -0,0 +1,134 @@
+# Copyright(c) 2011-2012 Collabora, Ltd.
+#
+# Gnome Clocks 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 Clocks 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 Clocks; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+# Author: Seif Lotfy <seif lotfy collabora co uk>
+
+import time
+from gi.repository import Gtk, GObject
+from clocks import Clock
+
+
+class Stopwatch(Clock):
+    LABEL_MARKUP = "<span font_desc=\"64.0\">%02i:%02i</span>"
+    BUTTON_MARKUP = "<span font_desc=\"18.0\">%s</span>"
+
+    class State:
+        RESET = 0
+        RUNNING = 1
+        STOPPED = 2
+
+    def __init__(self):
+        Clock.__init__(self, _("Stopwatch"))
+        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+        self.add(vbox)
+
+        center = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+
+        self.stopwatchLabel = Gtk.Label()
+        self.stopwatchLabel.set_alignment(0.5, 0.5)
+        self.stopwatchLabel.set_markup(Stopwatch.LABEL_MARKUP % (0, 0))
+
+        hbox = Gtk.Box()
+        self.leftButton = Gtk.Button()
+        self.leftButton.set_size_request(200, -1)
+        self.leftLabel = Gtk.Label()
+        self.leftButton.add(self.leftLabel)
+        self.rightButton = Gtk.Button()
+        self.rightButton.set_size_request(200, -1)
+        self.rightLabel = Gtk.Label()
+        self.rightButton.add(self.rightLabel)
+        self.rightButton.set_sensitive(False)
+        self.leftButton.get_style_context().add_class("clocks-go")
+        #self.rightButton.get_style_context().add_class("clocks-lap")
+
+        hbox.pack_start(Gtk.Box(), True, False, 0)
+        hbox.pack_start(self.leftButton, False, False, 0)
+        hbox.pack_start(Gtk.Box(), False, False, 24)
+        hbox.pack_start(self.rightButton, False, False, 0)
+        hbox.pack_start(Gtk.Box(), True, False, 0)
+
+        self.leftLabel.set_markup(Stopwatch.BUTTON_MARKUP % (_("Start")))
+        self.leftLabel.set_padding(6, 0)
+        self.rightLabel.set_markup(Stopwatch.BUTTON_MARKUP % (_("Reset")))
+        self.rightLabel.set_padding(6, 0)
+
+        center.pack_start(self.stopwatchLabel, False, False, 0)
+        center.pack_start(Gtk.Box(), True, True, 41)
+        center.pack_start(hbox, False, False, 0)
+
+        self.state = Stopwatch.State.RESET
+        self.g_id = 0
+        self.start_time = 0
+        self.time_diff = 0
+
+        vbox.pack_start(Gtk.Box(), True, True, 48)
+        vbox.pack_start(center, False, False, 0)
+        vbox.pack_start(Gtk.Box(), True, True, 1)
+        vbox.pack_start(Gtk.Box(), True, True, 41)
+
+        self.leftButton.connect("clicked", self._on_left_button_clicked)
+        self.rightButton.connect("clicked", self._on_right_button_clicked)
+
+    def _on_left_button_clicked(self, widget):
+        if self.state in (Stopwatch.State.RESET, Stopwatch.State.STOPPED):
+            self.state = Stopwatch.State.RUNNING
+            self.start()
+            self.leftLabel.set_markup(Stopwatch.BUTTON_MARKUP % (_("Stop")))
+            self.leftButton.get_style_context().add_class("clocks-stop")
+            self.rightButton.set_sensitive(True)
+        elif self.state == Stopwatch.State.RUNNING:
+            self.state = Stopwatch.State.STOPPED
+            self.stop()
+            self.leftLabel.set_markup(Stopwatch.BUTTON_MARKUP %
+                (_("Continue")))
+            self.rightLabel.set_markup(Stopwatch.BUTTON_MARKUP %
+                (_("Reset")))
+            self.leftButton.get_style_context().remove_class("clocks-stop")
+            self.leftButton.get_style_context().add_class("clocks-go")
+
+    def _on_right_button_clicked(self, widget):
+        if self.state == Stopwatch.State.RUNNING:
+            pass
+        if self.state == Stopwatch.State.STOPPED:
+            self.state = Stopwatch.State.RESET
+            self.time_diff = 0
+            self.leftLabel.set_markup(Stopwatch.BUTTON_MARKUP % (_("Start")))
+            self.leftButton.get_style_context().add_class("clocks-go")
+            #self.rightButton.get_style_context().add_class("clocks-lap")
+            self.stopwatchLabel.set_markup(Stopwatch.LABEL_MARKUP % (0, 0))
+            self.rightButton.set_sensitive(False)
+
+    def start(self):
+        if self.g_id == 0:
+            self.start_time = time.time()
+            self.g_id = GObject.timeout_add(10, self.count)
+
+    def stop(self):
+        GObject.source_remove(self.g_id)
+        self.g_id = 0
+        self.time_diff = self.time_diff + (time.time() - self.start_time)
+
+    def reset(self):
+        self.time_diff = 0
+        GObject.source_remove(self.g_id)
+        self.g_id = 0
+
+    def count(self):
+        timediff = time.time() - self.start_time + self.time_diff
+        elapsed_minutes, elapsed_seconds = divmod(timediff, 60)
+        self.stopwatchLabel.set_markup(Stopwatch.LABEL_MARKUP %
+            (elapsed_minutes, elapsed_seconds))
+        return True
diff --git a/gnomeclocks/timer.py b/gnomeclocks/timer.py
index f88cae9..d843348 100644
--- a/gnomeclocks/timer.py
+++ b/gnomeclocks/timer.py
@@ -16,67 +16,10 @@
 #
 # Author: Seif Lotfy <seif lotfy collabora co uk>
 
-from gi.repository import Gtk, Gio
-
-TIMER = "<span font_desc=\"64.0\">%02i</span>"
-TIMER_LABEL_MARKUP = "<span font_desc=\"64.0\">%02i:%02i:%02i</span>"
-TIMER_BUTTON_MARKUP = "<span font_desc=\"18.0\">% s</span>"
-
-
-class Spinner(Gtk.Box):
-    def __init__(self, max_value, timer_welcome_screen):
-        super(Spinner, self).__init__()
-        self.max_value = max_value
-        self.timer_welcome_screen = timer_welcome_screen
-        self.set_orientation(Gtk.Orientation.VERTICAL)
-        iconUp = Gio.ThemedIcon.new_with_default_fallbacks("go-up-symbolic")
-        iconDown = Gio.ThemedIcon.new_with_default_fallbacks(
-          "go-down-symbolic")
-        imageUp = Gtk.Image.new_from_gicon(iconUp, Gtk.IconSize.DND)
-        imageDown = Gtk.Image.new_from_gicon(iconDown, Gtk.IconSize.DND)
-        #Up Button
-        self.up = Gtk.Button()
-        self.up.set_image(imageUp)
-        self.up.set_relief(Gtk.ReliefStyle.NONE)
-        #Value
-        self.value = Gtk.Label('')
-        self.value.set_markup(TIMER % (0))
-        self.value.set_alignment(0.5, 0.5)
-        #Down Button
-        self.down = Gtk.Button()
-        self.down.set_image(imageDown)
-        self.down.set_relief(Gtk.ReliefStyle.NONE)
-        #
-        self.pack_start(self.up, False, False, 0)
-        self.pack_start(self.value, True, True, 0)
-        self.pack_start(self.down, False, False, 0)
-        #Signals
-        self.up.connect('clicked', self._increase)
-        self.down.connect('clicked', self._decrease)
-
-    def get_value(self):
-        return int(self.value.get_text())
-
-    def set_value(self, newValue):
-        self.value.set_markup(TIMER % (newValue))
-
-    def _increase(self, widget):
-        value = self.get_value()
-        if value == self.max_value:
-            value = 0
-        else:
-            value += 1
-        self.set_value(value)
-        self.timer_welcome_screen.update_start_button_status()
-
-    def _decrease(self, widget):
-        value = self.get_value()
-        if value == 0:
-            value = self.max_value
-        else:
-            value -= 1
-        self.set_value(value)
-        self.timer_welcome_screen.update_start_button_status()
+from gi.repository import Gtk, GObject, Gio
+from clocks import Clock
+from utils import Alert
+from widgets import Spinner
 
 
 class TimerScreen(Gtk.Box):
@@ -89,7 +32,7 @@ class TimerScreen(Gtk.Box):
 
         self.timerLabel = Gtk.Label()
         self.timerLabel.set_alignment(0.5, 0.5)
-        self.timerLabel.set_markup(TIMER_LABEL_MARKUP % (0, 0, 0))
+        self.timerLabel.set_markup(Timer.LABEL_MARKUP % (0, 0, 0))
 
         center.pack_start(Gtk.Label(""), False, True, 30)
         center.pack_start(self.timerLabel, False, True, 6)
@@ -109,9 +52,9 @@ class TimerScreen(Gtk.Box):
         hbox.pack_start(Gtk.Box(), True, True, 24)
         hbox.pack_start(self.rightButton, True, True, 0)
 
-        self.leftLabel.set_markup(TIMER_BUTTON_MARKUP % (_("Pause")))
+        self.leftLabel.set_markup(Timer.BUTTON_MARKUP % (_("Pause")))
         self.leftLabel.set_padding(6, 0)
-        self.rightLabel.set_markup(TIMER_BUTTON_MARKUP % (_("Reset")))
+        self.rightLabel.set_markup(Timer.BUTTON_MARKUP % (_("Reset")))
         self.rightLabel.set_padding(6, 0)
 
         self.leftButton.connect('clicked', self._on_left_button_clicked)
@@ -122,20 +65,20 @@ class TimerScreen(Gtk.Box):
         self.pack_start(hbox, False, False, 5)
 
     def set_time(self, h, m, s):
-        self.timerLabel.set_markup(TIMER_LABEL_MARKUP % (h, m, s))
+        self.timerLabel.set_markup(Timer.LABEL_MARKUP % (h, m, s))
 
     def _on_right_button_clicked(self, data):
-        self.leftLabel.set_markup(TIMER_BUTTON_MARKUP % (_("Pause")))
+        self.leftLabel.set_markup(Timer.BUTTON_MARKUP % (_("Pause")))
         self.timer.reset()
 
     def _on_left_button_clicked(self, widget):
-        if self.timer.state == 1:
+        if self.timer.state == Timer.State.RUNNING:
             self.timer.pause()
-            self.leftLabel.set_markup(TIMER_BUTTON_MARKUP % (_("Continue")))
+            self.leftLabel.set_markup(Timer.BUTTON_MARKUP % (_("Continue")))
             self.leftButton.get_style_context().add_class("clocks-go")
-        elif self.timer.state == 2:
+        elif self.timer.state == Timer.State.PAUSED:
             self.timer.cont()
-            self.leftLabel.set_markup(TIMER_BUTTON_MARKUP % (_("Pause")))
+            self.leftLabel.set_markup(Timer.BUTTON_MARKUP % (_("Pause")))
             self.leftButton.get_style_context().remove_class("clocks-go")
 
         # FIXME: work around the fact that gtk does recalculate the label style
@@ -172,7 +115,7 @@ class TimerWelcomeScreen(Gtk.Box):
         self.startButton.set_sensitive(False)
         self.startButton.set_size_request(200, -1)
         self.startLabel = Gtk.Label()
-        self.startLabel.set_markup(TIMER_BUTTON_MARKUP % (_("Start")))
+        self.startLabel.set_markup(Timer.BUTTON_MARKUP % (_("Start")))
         self.startLabel.set_padding(6, 0)
         self.startButton.add(self.startLabel)
         self.startButton.connect('clicked', self._on_start_clicked)
@@ -197,5 +140,105 @@ class TimerWelcomeScreen(Gtk.Box):
             self.startButton.get_style_context().add_class("clocks-go")
 
     def _on_start_clicked(self, data):
-        if self.timer.state == 0:
-            self.timer.start()
+        self.timer.start()
+
+
+class Timer(Clock):
+    LABEL_MARKUP = "<span font_desc=\"64.0\">%02i:%02i:%02i</span>"
+    BUTTON_MARKUP = "<span font_desc=\"18.0\">% s</span>"
+
+    class State:
+        STOPPED = 0
+        RUNNING = 1
+        PAUSED = 2
+
+    def __init__(self):
+        Clock.__init__(self, _("Timer"))
+        self.state = Timer.State.STOPPED
+        self.g_id = 0
+
+        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+        box = Gtk.Box()
+        self.add(box)
+        box.pack_start(Gtk.Box(), True, True, 0)
+        box.pack_start(self.vbox, False, False, 0)
+        box.pack_end(Gtk.Box(), True, True, 0)
+
+        self.timerbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+        self.vbox.pack_start(Gtk.Box(), True, True, 0)
+        self.vbox.pack_start(self.timerbox, False, False, 0)
+        self.vbox.pack_start(Gtk.Box(), True, True, 0)
+        self.vbox.pack_start(Gtk.Box(), True, True, 46)
+
+        self.timer_welcome_screen = TimerWelcomeScreen(self)
+        self.timer_screen = TimerScreen(self)
+        self.show_timer_welcome_screen()
+
+        self.alert = Alert("complete", "Ta Da !",
+                           self._on_notification_activated)
+
+    def _on_notification_activated(self, notif, action, data):
+        win = self.get_toplevel()
+        win.show_clock(self)
+
+    def show_timer_welcome_screen(self):
+        self.timerbox.pack_start(self.timer_welcome_screen, True, True, 0)
+        self.timer_welcome_screen.update_start_button_status()
+
+    def start_timer_screen(self):
+        self.timerbox.remove(self.timer_welcome_screen)
+        self.timerbox.pack_start(self.timer_screen, True, True, 0)
+        self.timerbox.show_all()
+
+    def end_timer_screen(self):
+        self.timerbox.remove(self.timer_screen)
+        self.show_timer_welcome_screen()
+        self.timer_welcome_screen.hours.set_value(0)
+        self.timer_welcome_screen.minutes.set_value(0)
+        self.timer_welcome_screen.seconds.set_value(0)
+        self.timer_welcome_screen.update_start_button_status()
+
+    def start(self):
+        if self.state == Timer.State.STOPPED and self.g_id == 0:
+            hours = self.timer_welcome_screen.hours.get_value()
+            minutes = self.timer_welcome_screen.minutes.get_value()
+            seconds = self.timer_welcome_screen.seconds.get_value()
+            self.timer_screen.set_time(hours, minutes, seconds)
+            self.time = (hours * 60 * 60) + (minutes * 60) + seconds
+            self.state = Timer.State.RUNNING
+            self.g_id = GObject.timeout_add(1000, self.count)
+            self.start_timer_screen()
+
+    def reset(self):
+        self.state = Timer.State.STOPPED
+        self.end_timer_screen()
+        if self.g_id != 0:
+            GObject.source_remove(self.g_id)
+        self.g_id = 0
+
+    def pause(self):
+        self.state = Timer.State.PAUSED
+        GObject.source_remove(self.g_id)
+        self.g_id = 0
+
+    def cont(self):
+        self.state = Timer.State.RUNNING
+        self.g_id = GObject.timeout_add(1000, self.count)
+
+    def count(self):
+        self.time -= 1
+        minutes, seconds = divmod(self.time, 60)
+        hours, minutes = divmod(minutes, 60)
+
+        self.timer_screen.set_time(hours, minutes, seconds)
+        if hours == 00 and minutes == 00 and seconds == 00:
+            self.alert.show()
+            self.state = Timer.State.STOPPED
+            self.timerbox.remove(self.timer_screen)
+            self.show_timer_welcome_screen()
+            if self.g_id != 0:
+                GObject.source_remove(self.g_id)
+            self.g_id = 0
+            return False
+        else:
+            return True
diff --git a/gnomeclocks/utils.py b/gnomeclocks/utils.py
index 3fef9e5..3f4ea16 100644
--- a/gnomeclocks/utils.py
+++ b/gnomeclocks/utils.py
@@ -17,7 +17,6 @@
 # Author: Seif Lotfy <seif lotfy collabora co uk>
 
 import os
-
 import pycanberra
 from xdg import BaseDirectory
 from gi.repository import Gio, Notify
@@ -84,10 +83,3 @@ class Alert:
             self.canberra.play(1, pycanberra.CA_PROP_EVENT_ID, self.soundid, None)
         if self.notification:
             self.notification.show()
-
-
-def get_is_day(hours):
-    if hours > 7 and hours < 19:
-        return True
-    else:
-        return False
diff --git a/gnomeclocks/widgets.py b/gnomeclocks/widgets.py
index c8ba641..d639c74 100644
--- a/gnomeclocks/widgets.py
+++ b/gnomeclocks/widgets.py
@@ -16,316 +16,11 @@
 #
 # Author: Seif Lotfy <seif lotfy collabora co uk>
 
-from gi.repository import GLib, Gio, GObject
-from gi.repository import Gtk, Gdk, GdkPixbuf, Pango, PangoCairo
-from gi.repository import GWeather, Clutter, GtkClutter
-
-from storage import Location
-from alarm import AlarmItem
-from utils import Dirs, SystemSettings, get_is_day
-
-import os
 import cairo
-import time
-
-
-class NewWorldClockDialog(Gtk.Dialog):
-    def __init__(self, parent):
-        Gtk.Dialog.__init__(self, _("Add a New World Clock"), parent)
-        self.set_transient_for(parent)
-        self.set_modal(True)
-        self.set_size_request(400, -1)
-        self.set_border_width(3)
-        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-        area = self.get_content_area()
-        area.pack_start(box, True, True, 0)
-
-        self.label = Gtk.Label()
-        self.label.set_markup(_("Search for a city:"))
-        self.label.set_alignment(0.0, 0.5)
-
-        world = GWeather.Location.new_world(True)
-        self.searchEntry = GWeather.LocationEntry.new(world)
-        self.find_gicon = Gio.ThemedIcon.new_with_default_fallbacks(
-            'edit-find-symbolic')
-        self.clear_gicon = Gio.ThemedIcon.new_with_default_fallbacks(
-            'edit-clear-symbolic')
-        self.searchEntry.set_icon_from_gicon(
-            Gtk.EntryIconPosition.SECONDARY, self.find_gicon)
-        self.searchEntry.set_activates_default(True)
-
-        self.add_buttons(Gtk.STOCK_CANCEL, 0, Gtk.STOCK_ADD, 1)
-        self.set_default_response(1)
-        self.set_response_sensitive(1, False)
-
-        box.pack_start(self.label, False, False, 6)
-        box.pack_start(self.searchEntry, False, False, 3)
-        box.set_border_width(5)
-
-        self.searchEntry.connect("activate", self._set_city)
-        self.searchEntry.connect("changed", self._set_city)
-        self.searchEntry.connect("icon-release", self._icon_released)
-        self.show_all()
-
-    def get_location(self):
-        location = self.searchEntry.get_location()
-        return Location(location)
-
-    def _set_city(self, widget):
-        location = self.searchEntry.get_location()
-        if self.searchEntry.get_text() == '':
-            self.searchEntry.set_icon_from_gicon(
-                Gtk.EntryIconPosition.SECONDARY, self.find_gicon)
-        else:
-            self.searchEntry.set_icon_from_gicon(
-                Gtk.EntryIconPosition.SECONDARY, self.clear_gicon)
-        if location:
-            self.set_response_sensitive(1, True)
-        else:
-            self.set_response_sensitive(1, False)
-
-    def _icon_released(self, icon_pos, event, data):
-        if self.searchEntry.get_icon_gicon(
-            Gtk.EntryIconPosition.SECONDARY) == self.clear_gicon:
-            self.searchEntry.set_text('')
-            self.searchEntry.set_icon_from_gicon(
-              Gtk.EntryIconPosition.SECONDARY, self.find_gicon)
-            self.set_response_sensitive(1, False)
-
-
-class DigitalClock():
-    def __init__(self, location):
-        self._location = location
-        self.location = 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.id = location.id
-        self.timezone = self.location.get_timezone()
-        self.offset = self.timezone.get_offset() * 60
-        self.isDay = None
-        self._last_time = None
-        self.drawing = DigitalClockDrawing()
-        self.standalone =\
-            DigitalClockStandalone(self.location, self.sunrise, self.sunset)
-        self.update()
-        self.timeout = GObject.timeout_add(1000, self.update)
-
-    def stop_update(self):
-        GObject.source_remove(self.timeout)
-        self.timeout = 0
-
-    def get_local_time(self, secs):
-         t = secs + time.timezone + self.offset
-         t = time.localtime(t)
-         return t
-
-    def get_local_time_text(self):
-        text = time.strftime("%I:%M%p", self.get_local_time(time.time()))
-        if text.startswith("0"):
-            text = text[1:]
-        return text
-
-    def update(self):
-        t = self.get_local_time_text()
-        systemClockFormat = SystemSettings.get_clock_format()
-        if systemClockFormat == '12h':
-            t = time.strftime("%I:%M%p", self.get_local_time(time.time()))
-        else:
-            t = time.strftime("%H:%M", self.get_local_time(time.time()))
-        if not t == self._last_time \
-                or not self.sunrise == self._last_sunrise \
-                or not self.sunset == self._last_sunset:
-            local_time = self.get_local_time(time.time())
-            #isDay = get_is_day(local_time.tm_hour)
-            isDay = self.get_is_light(local_time, self.sunrise, self.sunset)
-            if isDay:
-                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, isDay)
-            else:
-                self.drawing.render(t, img, isDay, day)
-            if self.path and self.list_store:
-                self.list_store[self.path][1] = self.drawing.pixbuf
-            self.standalone.update(img, t, systemClockFormat,
-                                   self.sunrise, self.sunset)
-
-        self._last_time = t
-        return True
-
-    def get_sunrise_sunset(self):
-        world = GWeather.Location.new_world(True)
-        self.weather = GWeather.Info(location=self.location, world=world)
-        self.weather.connect('updated', self.weather_updated_callback)
-        self.weather.update()
-        
-    def weather_updated_callback(self, weather):
-        # returned as the time here
-        ok, sunrise = weather.get_value_sunrise()
-        ok, sunset = weather.get_value_sunset()
-        self._last_sunrise = self.sunrise
-        self._last_sunset = self.sunset
-        self.sunrise = self.get_local_time(sunrise)
-        self.sunset = self.get_local_time(sunset)
-        self.update()
-
-    def get_pixbuf(self):
-        return self.drawing.pixbuf
-
-    def get_standalone_widget(self):
-        return self.standalone
-
-    def get_day(self):
-        clock_time_day = self.get_local_time(time.time()).tm_yday
-        local_time_day = time.localtime().tm_yday
-
-        if clock_time_day == local_time_day:
-            return "Today"
-        # if its 31st Dec here and 1st Jan there, clock_time_day = 1,
-        # local_time_day = 365/366
-        # if its 1st Jan here and 31st Dec there, clock_time_day = 365/366,
-        # local_time_day = 1
-        elif clock_time_day > local_time_day:
-            if local_time_day == 1:
-                return "Yesterday"
-            else:
-                return "Tomorrow"
-        elif clock_time_day < local_time_day:
-            if clock_time_day == 1:
-                return "Tomorrow"
-            else:
-                return "Yesterday"
-
-    def get_is_light(self, current, sunrise, sunset):
-        if current.tm_hour < sunrise.tm_hour \
-                or current.tm_hour > sunset.tm_hour:
-            return False
-        elif current.tm_hour > sunrise.tm_hour \
-                and current.tm_hour < sunset.tm_hour:
-            return True
-        elif current.tm_hour == sunrise.tm_hour:
-            if current.tm_min >= sunrise.tm_min:
-                return True
-            else:
-                return False
-        elif current.tm_hour == sunset.tm_hour:
-            if current.tm_min <= sunrise.tm_min:
-                return True
-            else:
-                return False
-
-    def set_path(self, list_store, path):
-        self.path = path
-        self.list_store = list_store
-
-
-class DigitalClockStandalone(Gtk.VBox):
-    def __init__(self, location, sunrise, sunset):
-        Gtk.VBox.__init__(self, False)
-        self.img = Gtk.Image()
-        self.time_label = Gtk.Label()
-        self.city_label = Gtk.Label()
-        label = GLib.markup_escape_text(location.get_city_name())
-        self.city_label.set_markup("<b>%s</b>" % label)
-        self.text = ""
-        self.sunrise = sunrise
-        self.sunset = sunset
-
-        self.systemClockFormat = None
-
-        self.connect("size-allocate", lambda x, y: self.update(None,
-            self.text, self.systemClockFormat, self.sunrise, self.sunset))
-
-        #imagebox = Gtk.VBox()
-        #imagebox.pack_start(self.img, False, False, 0)
-        #imagebox.pack_start(self.city_label, False, False, 0)
-        #imagebox.set_size_request(230, 230)
-
-        self.timebox = timebox = Gtk.VBox()
-        self.time_label.set_alignment(0.0, 0.5)
-        timebox.pack_start(self.time_label, True, True, 0)
-
-        self.hbox = hbox = Gtk.HBox()
-        self.hbox.set_homogeneous(False)
-
-        self.hbox.pack_start(Gtk.Label(), True, True, 0)
-        # self.hbox.pack_start(imagebox, False, False, 0)
-        # self.hbox.pack_start(Gtk.Label(), False, False, 30)
-        self.hbox.pack_start(timebox, False, False, 0)
-        self.hbox.pack_start(Gtk.Label(), True, True, 0)
-
-        self.pack_start(Gtk.Label(), True, True, 25)
-        self.pack_start(hbox, False, False, 0)
-        self.pack_start(Gtk.Label(), True, True, 0)
-
-        sunrise_label = Gtk.Label()
-        sunrise_label.set_markup(
-            "<span size ='large' color='dimgray'>%s</span>" % (_("Sunrise")))
-        sunrise_label.set_alignment(1.0, 0.5)
-        self.sunrise_time_label = Gtk.Label()
-        self.sunrise_time_label.set_alignment(0.0, 0.5)
-        sunrise_hbox = Gtk.Box(True, 9)
-        sunrise_hbox.pack_start(sunrise_label, False, False, 0)
-        sunrise_hbox.pack_start(self.sunrise_time_label, False, False, 0)
-
-        sunset_label = Gtk.Label()
-        sunset_label.set_markup(
-            "<span size ='large' color='dimgray'>%s</span>" % (_("Sunset")))
-        sunset_label.set_alignment(1.0, 0.5)
-        self.sunset_time_label = Gtk.Label()
-        self.sunset_time_label.set_alignment(0.0, 0.5)
-        sunset_hbox = Gtk.Box(True, 9)
-        sunset_hbox.pack_start(sunset_label, False, False, 0)
-        sunset_hbox.pack_start(self.sunset_time_label, False, False, 0)
-
-        sunbox = Gtk.VBox(True, 3)
-        sunbox.pack_start(sunrise_hbox, False, False, 3)
-        sunbox.pack_start(sunset_hbox, False, False, 3)
-
-        hbox = Gtk.HBox()
-        hbox.pack_start(Gtk.Label(), True, True, 0)
-        hbox.pack_start(sunbox, False, False, 0)
-        hbox.pack_start(Gtk.Label(), True, True, 0)
-        self.pack_end(hbox, False, False, 30)
-
-    def update(self, img, text, systemClockFormat, sunrise, sunset):
-        size = 72000  # FIXME: (self.get_allocation().height / 300) * 72000
-        if img:
-            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(img, 500, 380)
-            pixbuf = pixbuf.new_subpixbuf(0, 0, 208, 208)
-            self.img.set_from_pixbuf(pixbuf)
-        self.text = text
-        self.time_label.set_markup(
-            "<span size='%i' color='dimgray'><b>%s</b></span>" % (size, text))
-        if systemClockFormat != self.systemClockFormat or \
-                sunrise != self.sunrise or sunset != self.sunset:
-            self.sunrise = sunrise
-            self.sunset = sunset
-            sunrise_markup = ""
-            sunset_markup = ""
-            if systemClockFormat == "12h":
-                sunrise_markup = sunrise_markup + "<span size ='large'>" +\
-                    time.strftime("%I:%M%p", sunrise) + "</span>"
-
-                sunset_markup = sunset_markup + "<span size ='large'>" +\
-                    time.strftime("%H:%M", sunset) + "</span>"
-            else:
-                sunrise_markup = sunrise_markup + "<span size ='large'>" +\
-                    time.strftime("%H:%M", sunrise) + "</span>"
-                sunset_markup = sunset_markup + "<span size ='large'>" +\
-                    time.strftime("%H:%M", sunset) + "</span>"
-            self.sunrise_time_label.set_markup(sunrise_markup)
-            self.sunset_time_label.set_markup(sunset_markup)
-        self.systemClockFormat = systemClockFormat
+from gi.repository import GLib, Gio, GObject
+from gi.repository import Gtk, Gdk, GdkPixbuf
+from gi.repository import Pango, PangoCairo
+from gi.repository import Clutter, GtkClutter
 
 
 class DigitalClockDrawing(Gtk.DrawingArea):
@@ -334,8 +29,6 @@ class DigitalClockDrawing(Gtk.DrawingArea):
 
     def __init__(self):
         Gtk.DrawingArea.__init__(self)
-        #self.set_size_request(width, height)
-
         self.pango_context = None
         self.ctx = None
         self.pixbuf = None
@@ -430,152 +123,62 @@ class DigitalClockDrawing(Gtk.DrawingArea):
         return self.pixbuf
 
 
-class AlarmWidget():
-    def __init__(self, time_given, repeat):
-        self.drawing = DigitalClockDrawing()
-        t = time_given
-        isDay = get_is_day(int(t[:2]))
-        if isDay:
-            img = os.path.join(Dirs.get_image_dir(), "cities", "day.png")
-        else:
-            img = os.path.join(Dirs.get_image_dir(), "cities", "night.png")
-        self.drawing.render(t, img, isDay, repeat)
+class Spinner(Gtk.Box):
+    MARKUP = "<span font_desc=\"64.0\">%02i</span>"
 
-    def get_pixbuf(self):
-        return self.drawing.pixbuf
+    def __init__(self, max_value, timer_welcome_screen):
+        super(Spinner, self).__init__()
+        self.max_value = max_value
+        self.timer_welcome_screen = timer_welcome_screen
+        self.set_orientation(Gtk.Orientation.VERTICAL)
+        iconUp = Gio.ThemedIcon.new_with_default_fallbacks("go-up-symbolic")
+        iconDown = Gio.ThemedIcon.new_with_default_fallbacks(
+            "go-down-symbolic")
+        imageUp = Gtk.Image.new_from_gicon(iconUp, Gtk.IconSize.DND)
+        imageDown = Gtk.Image.new_from_gicon(iconDown, Gtk.IconSize.DND)
 
+        self.up = Gtk.Button()
+        self.up.set_image(imageUp)
+        self.up.set_relief(Gtk.ReliefStyle.NONE)
 
-class AlarmDialog(Gtk.Dialog):
-    def __init__(self, alarm_view, parent, vevent=None):
-        self.vevent = vevent
-        if vevent:
-            Gtk.Dialog.__init__(self, _("Edit Alarm"), parent)
-        else:
-            Gtk.Dialog.__init__(self, _("New Alarm"), parent)
-        self.set_border_width(6)
-        self.parent = parent
-        self.set_transient_for(parent)
-        self.set_modal(True)
-        self.day_buttons = []
-
-        content_area = self.get_content_area()
-        self.add_buttons(Gtk.STOCK_CANCEL, 0, Gtk.STOCK_SAVE, 1)
-
-        self.cf = SystemSettings.get_clock_format()
-        grid = Gtk.Grid()
-        grid.set_row_spacing(9)
-        grid.set_column_spacing(6)
-        grid.set_border_width(6)
-        content_area.pack_start(grid, True, True, 0)
-
-        if vevent:
-            t = vevent.dtstart.value
-            h = int(t.strftime("%I"))
-            m = int(t.strftime("%m"))
-            p = t.strftime("%p")
-            name = vevent.summary.value
-            repeat = self.get_repeat_days_from_vevent(vevent)
-        else:
-            t = time.localtime()
-            h = t.tm_hour
-            m = t.tm_min
-            p = time.strftime("%p", t)
-            name = _("New Alarm")
-            repeat = []
-
-        label = Gtk.Label(_("Time"))
-        label.set_alignment(1.0, 0.5)
-        grid.attach(label, 0, 0, 1, 1)
-
-        self.hourselect = Gtk.SpinButton()
-        self.hourselect.set_increments(1.0, 1.0)
-        self.hourselect.set_wrap(True)
-        grid.attach(self.hourselect, 1, 0, 1, 1)
-
-        label = Gtk.Label(": ")
-        label.set_alignment(0.5, 0.5)
-        grid.attach(label, 2, 0, 1, 1)
-
-        self.minuteselect = Gtk.SpinButton()
-        self.minuteselect.set_increments(1.0, 1.0)
-        self.minuteselect.set_wrap(True)
-        self.minuteselect.connect('output', self.show_leading_zeros)
-        self.minuteselect.set_range(0.0, 59.0)
-        self.minuteselect.set_value(m)
-        grid.attach(self.minuteselect, 3, 0, 1, 1)
-
-        if self.cf == "12h":
-            self.ampm = Gtk.ComboBoxText()
-            self.ampm.append_text("AM")
-            self.ampm.append_text("PM")
-            if p == "PM":
-                h = h - 12
-                self.ampm.set_active(1)
-            else:
-                self.ampm.set_active(0)
-            grid.attach(self.ampm, 4, 0, 1, 1)
-            self.hourselect.set_range(1.0, 12.0)
-            self.hourselect.set_value(h)
-            gridcols = 5
+        self.value = Gtk.Label('')
+        self.value.set_markup(Spinner.MARKUP % (0))
+        self.value.set_alignment(0.5, 0.5)
+
+        self.down = Gtk.Button()
+        self.down.set_image(imageDown)
+        self.down.set_relief(Gtk.ReliefStyle.NONE)
+
+        self.pack_start(self.up, False, False, 0)
+        self.pack_start(self.value, True, True, 0)
+        self.pack_start(self.down, False, False, 0)
+
+        self.up.connect('clicked', self._increase)
+        self.down.connect('clicked', self._decrease)
+
+    def get_value(self):
+        return int(self.value.get_text())
+
+    def set_value(self, newValue):
+        self.value.set_markup(Spinner.MARKUP % (newValue))
+
+    def _increase(self, widget):
+        value = self.get_value()
+        if value == self.max_value:
+            value = 0
         else:
-            self.hourselect.set_range(0.0, 23.0)
-            self.hourselect.set_value(h)
-            gridcols = 4
-
-        label = Gtk.Label(_("Name"))
-        label.set_alignment(1.0, 0.5)
-        grid.attach(label, 0, 1, 1, 1)
-
-        self.entry = Gtk.Entry()
-        self.entry.set_text(name)
-        self.entry.set_editable(True)
-        grid.attach(self.entry, 1, 1, gridcols - 1, 1)
-
-        label = Gtk.Label(_("Repeat Every"))
-        label.set_alignment(1.0, 0.5)
-        grid.attach(label, 0, 2, 1, 1)
-
-        # create a box and put repeat days in it
-        box = Gtk.Box(True, 0)
-        box.get_style_context().add_class("linked")
-        for day in ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]:
-            btn = Gtk.ToggleButton(label=_(day))
-            if btn.get_label()[:2]  in repeat:
-                btn.set_active(True)
-            box.pack_start(btn, True, True, 0)
-            self.day_buttons.append(btn)
-        grid.attach(box, 1, 2, gridcols - 1, 1)
-
-    def show_leading_zeros(self, spin_button):
-        spin_button.set_text('{: 02d}'.format(spin_button.get_value_as_int()))
-        return True
-
-    def get_repeat_days_from_vevent(self, vevent):
-        rrule = vevent.rrule.value
-        repeat = []
-        if rrule[5] == 'W':
-            days = rrule[18:]
-            repeat = days.split(",")
-        return repeat
-
-    def get_alarm_item(self):
-        name = self.entry.get_text()
-        h = self.hourselect.get_value_as_int()
-        m = self.minuteselect.get_value_as_int()
-        if self.cf == "12h":
-            r = self.ampm.get_active()
-            if r == 0:
-                p = "AM"
-            else:
-                p = "PM"
+            value += 1
+        self.set_value(value)
+        self.timer_welcome_screen.update_start_button_status()
+
+    def _decrease(self, widget):
+        value = self.get_value()
+        if value == 0:
+            value = self.max_value
         else:
-            p = None
-        repeat = []
-        for btn in self.day_buttons:
-            if btn.get_active():
-                repeat.append(btn.get_label()[:2])
-        alarm_item = AlarmItem(name, repeat, h, m, p)
-        return alarm_item
+            value -= 1
+        self.set_value(value)
+        self.timer_welcome_screen.update_start_button_status()
 
 
 class EmptyPlaceholder(Gtk.Box):
diff --git a/gnomeclocks/world.py b/gnomeclocks/world.py
new file mode 100644
index 0000000..27f6bac
--- /dev/null
+++ b/gnomeclocks/world.py
@@ -0,0 +1,483 @@
+# Copyright(c) 2011-2012 Collabora, Ltd.
+#
+# Gnome Clocks 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 Clocks 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 Clocks; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+# Author: Seif Lotfy <seif lotfy collabora co uk>
+
+import os
+import errno
+import pickle
+import time
+from gi.repository import GLib, GObject, Gio, Gtk, GdkPixbuf
+from gi.repository import GWeather
+from clocks import Clock
+from utils import Dirs, SystemSettings
+from widgets import DigitalClockDrawing, SelectableIconView, ContentView
+
+
+class Location():
+    def __init__(self, location):
+        self._id = location.get_city_name()
+        self._location = location
+
+    @property
+    def id(self):
+        return self._id
+
+    @property
+    def location(self):
+        return self._location
+
+
+class WorldClockStorage():
+    def __init__(self):
+        self.filename = os.path.join(Dirs.get_user_data_dir(), "clocks")
+        world = GWeather.Location.new_world(True)
+        self.searchEntry = GWeather.LocationEntry.new(world)
+        self.searchEntry.show_all()
+        self.locations_dump = ""
+        pass
+
+    def save_clocks(self, locations):
+        self.locations_dump = locations = "|".join(
+          [location.id +\
+              "---" + location.location.get_code() for location in locations])
+        f = open(self.filename, "wb")
+        pickle.dump(locations, f)
+        f.close()
+
+    def load_clocks(self):
+        clocks = []
+        try:
+            f = open(self.filename, "rb")
+            self.locations_dump = locations = pickle.load(f)
+            f.close()
+            locations = locations.split("|")
+            for location in locations:
+                loc = location.split("---")
+                if self.searchEntry.set_city(loc[0], loc[1]):
+                    loc = self.searchEntry.get_location()
+                    loc = Location(self.searchEntry.get_location())
+                    clocks.append(loc)
+        except IOError as e:
+            if e.errno == errno.ENOENT:
+                # File does not exist yet, that's ok
+                pass
+            else:
+                print "--", e
+        except Exception, e:
+            print "--", e
+
+        return clocks
+
+    def delete_all_clocks(self):
+        f = open(DATA_PATH, "w")
+        f.write("")
+        f.close()
+
+
+class NewWorldClockDialog(Gtk.Dialog):
+    def __init__(self, parent):
+        Gtk.Dialog.__init__(self, _("Add a New World Clock"), parent)
+        self.set_transient_for(parent)
+        self.set_modal(True)
+        self.set_size_request(400, -1)
+        self.set_border_width(3)
+        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+        area = self.get_content_area()
+        area.pack_start(box, True, True, 0)
+
+        self.label = Gtk.Label()
+        self.label.set_markup(_("Search for a city:"))
+        self.label.set_alignment(0.0, 0.5)
+
+        world = GWeather.Location.new_world(True)
+        self.searchEntry = GWeather.LocationEntry.new(world)
+        self.find_gicon = Gio.ThemedIcon.new_with_default_fallbacks(
+            'edit-find-symbolic')
+        self.clear_gicon = Gio.ThemedIcon.new_with_default_fallbacks(
+            'edit-clear-symbolic')
+        self.searchEntry.set_icon_from_gicon(
+            Gtk.EntryIconPosition.SECONDARY, self.find_gicon)
+        self.searchEntry.set_activates_default(True)
+
+        self.add_buttons(Gtk.STOCK_CANCEL, 0, Gtk.STOCK_ADD, 1)
+        self.set_default_response(1)
+        self.set_response_sensitive(1, False)
+
+        box.pack_start(self.label, False, False, 6)
+        box.pack_start(self.searchEntry, False, False, 3)
+        box.set_border_width(5)
+
+        self.searchEntry.connect("activate", self._set_city)
+        self.searchEntry.connect("changed", self._set_city)
+        self.searchEntry.connect("icon-release", self._icon_released)
+        self.show_all()
+
+    def get_location(self):
+        location = self.searchEntry.get_location()
+        return Location(location)
+
+    def _set_city(self, widget):
+        location = self.searchEntry.get_location()
+        if self.searchEntry.get_text() == '':
+            self.searchEntry.set_icon_from_gicon(
+                Gtk.EntryIconPosition.SECONDARY, self.find_gicon)
+        else:
+            self.searchEntry.set_icon_from_gicon(
+                Gtk.EntryIconPosition.SECONDARY, self.clear_gicon)
+        if location:
+            self.set_response_sensitive(1, True)
+        else:
+            self.set_response_sensitive(1, False)
+
+    def _icon_released(self, icon_pos, event, data):
+        if self.searchEntry.get_icon_gicon(
+            Gtk.EntryIconPosition.SECONDARY) == self.clear_gicon:
+            self.searchEntry.set_text('')
+            self.searchEntry.set_icon_from_gicon(
+              Gtk.EntryIconPosition.SECONDARY, self.find_gicon)
+            self.set_response_sensitive(1, False)
+
+class DigitalClock():
+    def __init__(self, location):
+        self._location = location
+        self.location = 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.id = location.id
+        self.timezone = self.location.get_timezone()
+        self.offset = self.timezone.get_offset() * 60
+        self.isDay = None
+        self._last_time = None
+        self.drawing = DigitalClockDrawing()
+        self.standalone =\
+            DigitalClockStandalone(self.location, self.sunrise, self.sunset)
+        self.update()
+        self.timeout = GObject.timeout_add(1000, self.update)
+
+    def stop_update(self):
+        GObject.source_remove(self.timeout)
+        self.timeout = 0
+
+    def get_local_time(self, secs):
+         t = secs + time.timezone + self.offset
+         t = time.localtime(t)
+         return t
+
+    def get_local_time_text(self):
+        text = time.strftime("%I:%M%p", self.get_local_time(time.time()))
+        if text.startswith("0"):
+            text = text[1:]
+        return text
+
+    def update(self):
+        t = self.get_local_time_text()
+        systemClockFormat = SystemSettings.get_clock_format()
+        if systemClockFormat == '12h':
+            t = time.strftime("%I:%M%p", self.get_local_time(time.time()))
+        else:
+            t = time.strftime("%H:%M", self.get_local_time(time.time()))
+        if not t == self._last_time \
+                or not self.sunrise == self._last_sunrise \
+                or not self.sunset == self._last_sunset:
+            local_time = self.get_local_time(time.time())
+            #isDay = get_is_day(local_time.tm_hour)
+            isDay = self.get_is_light(local_time, self.sunrise, self.sunset)
+            if isDay:
+                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, isDay)
+            else:
+                self.drawing.render(t, img, isDay, day)
+            if self.path and self.list_store:
+                self.list_store[self.path][1] = self.drawing.pixbuf
+            self.standalone.update(img, t, systemClockFormat,
+                                   self.sunrise, self.sunset)
+
+        self._last_time = t
+        return True
+
+    def get_sunrise_sunset(self):
+        world = GWeather.Location.new_world(True)
+        self.weather = GWeather.Info(location=self.location, world=world)
+        self.weather.connect('updated', self.weather_updated_callback)
+        self.weather.update()
+        
+    def weather_updated_callback(self, weather):
+        # returned as the time here
+        ok, sunrise = weather.get_value_sunrise()
+        ok, sunset = weather.get_value_sunset()
+        self._last_sunrise = self.sunrise
+        self._last_sunset = self.sunset
+        self.sunrise = self.get_local_time(sunrise)
+        self.sunset = self.get_local_time(sunset)
+        self.update()
+
+    def get_pixbuf(self):
+        return self.drawing.pixbuf
+
+    def get_standalone_widget(self):
+        return self.standalone
+
+    def get_day(self):
+        clock_time_day = self.get_local_time(time.time()).tm_yday
+        local_time_day = time.localtime().tm_yday
+
+        if clock_time_day == local_time_day:
+            return "Today"
+        # if its 31st Dec here and 1st Jan there, clock_time_day = 1,
+        # local_time_day = 365/366
+        # if its 1st Jan here and 31st Dec there, clock_time_day = 365/366,
+        # local_time_day = 1
+        elif clock_time_day > local_time_day:
+            if local_time_day == 1:
+                return "Yesterday"
+            else:
+                return "Tomorrow"
+        elif clock_time_day < local_time_day:
+            if clock_time_day == 1:
+                return "Tomorrow"
+            else:
+                return "Yesterday"
+
+    def get_is_light(self, current, sunrise, sunset):
+        if current.tm_hour < sunrise.tm_hour \
+                or current.tm_hour > sunset.tm_hour:
+            return False
+        elif current.tm_hour > sunrise.tm_hour \
+                and current.tm_hour < sunset.tm_hour:
+            return True
+        elif current.tm_hour == sunrise.tm_hour:
+            if current.tm_min >= sunrise.tm_min:
+                return True
+            else:
+                return False
+        elif current.tm_hour == sunset.tm_hour:
+            if current.tm_min <= sunrise.tm_min:
+                return True
+            else:
+                return False
+
+    def set_path(self, list_store, path):
+        self.path = path
+        self.list_store = list_store
+
+
+class World(Clock):
+    def __init__(self):
+        Clock.__init__(self, _("World"), True, True)
+
+        self.liststore = Gtk.ListStore(bool,
+                                       GdkPixbuf.Pixbuf,
+                                       str,
+                                       GObject.TYPE_PYOBJECT)
+
+        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"))
+        self.add(contentview)
+
+        self.iconview.connect("item-activated", self._on_item_activated)
+        self.iconview.connect("selection-changed", self._on_selection_changed)
+
+        self.storage = WorldClockStorage()
+        self.clocks = []
+        self.load_clocks()
+        self.show_all()
+
+    def _on_item_activated(self, iconview, path):
+        d = self.liststore[path][3]
+        self.emit("show-clock", d)
+
+    def _on_selection_changed(self, iconview):
+        self.emit("selection-changed")
+
+    def set_selection_mode(self, active):
+        self.iconview.set_selection_mode(active)
+
+    @GObject.Property(type=bool, default=False)
+    def can_select(self):
+        return len(self.liststore) != 0
+
+    def get_selection(self):
+        return self.iconview.get_selection()
+
+    def delete_selected(self):
+        selection = self.get_selection()
+        items = []
+        for treepath in selection:
+            items.append(self.liststore[treepath][3])
+        self.delete_clocks(items)
+
+    def load_clocks(self):
+        self.clocks = self.storage.load_clocks()
+        for clock in self.clocks:
+            self.add_clock_widget(clock)
+
+    def add_clock(self, location):
+        location_id = location.id + "---" + location.location.get_code()
+        if not location_id in self.storage.locations_dump:
+            self.clocks.append(location)
+            self.add_clock_widget(location)
+            self.show_all()
+        self.storage.save_clocks(self.clocks)
+
+    def add_clock_widget(self, location):
+        d = DigitalClock(location)
+        name = d.location.get_city_name()
+        label = GLib.markup_escape_text(name)
+        view_iter = self.liststore.append([False,
+                                           d.get_pixbuf(),
+                                           "<b>%s</b>" % label,
+                                           d])
+        path = self.liststore.get_path(view_iter)
+        d.set_path(self.liststore, path)
+        self.notify("can-select")
+
+    def delete_clocks(self, clocks):
+        for d in clocks:
+            d.stop_update()
+            self.clocks.remove(d._location)
+        self.storage.save_clocks(self.clocks)
+        self.iconview.unselect_all()
+        self.liststore.clear()
+        self.load_clocks()
+        self.notify("can-select")
+
+    def open_new_dialog(self):
+        window = NewWorldClockDialog(self.get_toplevel())
+        window.connect("response", self.on_dialog_response)
+        window.show_all()
+
+    def on_dialog_response(self, dialog, response):
+        if response == 1:
+            l = dialog.get_location()
+            self.add_clock(l)
+        dialog.destroy()
+
+
+class DigitalClockStandalone(Gtk.Box):
+    def __init__(self, location, sunrise, sunset):
+        Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
+        self.img = Gtk.Image()
+        self.time_label = Gtk.Label()
+        self.city_label = Gtk.Label()
+        label = GLib.markup_escape_text(location.get_city_name())
+        self.city_label.set_markup("<b>%s</b>" % label)
+        self.text = ""
+        self.sunrise = sunrise
+        self.sunset = sunset
+
+        self.systemClockFormat = None
+
+        self.connect("size-allocate", lambda x, y: self.update(None,
+            self.text, self.systemClockFormat, self.sunrise, self.sunset))
+
+        #imagebox = Gtk.VBox()
+        #imagebox.pack_start(self.img, False, False, 0)
+        #imagebox.pack_start(self.city_label, False, False, 0)
+        #imagebox.set_size_request(230, 230)
+
+        self.timebox = timebox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+        self.time_label.set_alignment(0.0, 0.5)
+        timebox.pack_start(self.time_label, True, True, 0)
+
+        self.hbox = hbox = Gtk.HBox()
+        self.hbox.set_homogeneous(False)
+
+        self.hbox.pack_start(Gtk.Label(), True, True, 0)
+        # self.hbox.pack_start(imagebox, False, False, 0)
+        # self.hbox.pack_start(Gtk.Label(), False, False, 30)
+        self.hbox.pack_start(timebox, False, False, 0)
+        self.hbox.pack_start(Gtk.Label(), True, True, 0)
+
+        self.pack_start(Gtk.Label(), True, True, 25)
+        self.pack_start(hbox, False, False, 0)
+        self.pack_start(Gtk.Label(), True, True, 0)
+
+        sunrise_label = Gtk.Label()
+        sunrise_label.set_markup(
+            "<span size ='large' color='dimgray'>%s</span>" % (_("Sunrise")))
+        sunrise_label.set_alignment(1.0, 0.5)
+        self.sunrise_time_label = Gtk.Label()
+        self.sunrise_time_label.set_alignment(0.0, 0.5)
+        sunrise_hbox = Gtk.Box(True, 9)
+        sunrise_hbox.pack_start(sunrise_label, False, False, 0)
+        sunrise_hbox.pack_start(self.sunrise_time_label, False, False, 0)
+
+        sunset_label = Gtk.Label()
+        sunset_label.set_markup(
+            "<span size ='large' color='dimgray'>%s</span>" % (_("Sunset")))
+        sunset_label.set_alignment(1.0, 0.5)
+        self.sunset_time_label = Gtk.Label()
+        self.sunset_time_label.set_alignment(0.0, 0.5)
+        sunset_hbox = Gtk.Box(True, 9)
+        sunset_hbox.pack_start(sunset_label, False, False, 0)
+        sunset_hbox.pack_start(self.sunset_time_label, False, False, 0)
+
+        sunbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+        sunbox.set_homogeneous(True)
+        sunbox.set_spacing(3)
+        sunbox.pack_start(sunrise_hbox, False, False, 3)
+        sunbox.pack_start(sunset_hbox, False, False, 3)
+
+        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
+        hbox.pack_start(Gtk.Label(), True, True, 0)
+        hbox.pack_start(sunbox, False, False, 0)
+        hbox.pack_start(Gtk.Label(), True, True, 0)
+        self.pack_end(hbox, False, False, 30)
+
+    def update(self, img, text, systemClockFormat, sunrise, sunset):
+        size = 72000  # FIXME: (self.get_allocation().height / 300) * 72000
+        if img:
+            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(img, 500, 380)
+            pixbuf = pixbuf.new_subpixbuf(0, 0, 208, 208)
+            self.img.set_from_pixbuf(pixbuf)
+        self.text = text
+        self.time_label.set_markup(
+            "<span size='%i' color='dimgray'><b>%s</b></span>" % (size, text))
+        if systemClockFormat != self.systemClockFormat or \
+                sunrise != self.sunrise or sunset != self.sunset:
+            self.sunrise = sunrise
+            self.sunset = sunset
+            sunrise_markup = ""
+            sunset_markup = ""
+            if systemClockFormat == "12h":
+                sunrise_markup = sunrise_markup + "<span size ='large'>" +\
+                    time.strftime("%I:%M%p", sunrise) + "</span>"
+
+                sunset_markup = sunset_markup + "<span size ='large'>" +\
+                    time.strftime("%H:%M", sunset) + "</span>"
+            else:
+                sunrise_markup = sunrise_markup + "<span size ='large'>" +\
+                    time.strftime("%H:%M", sunrise) + "</span>"
+                sunset_markup = sunset_markup + "<span size ='large'>" +\
+                    time.strftime("%H:%M", sunset) + "</span>"
+            self.sunrise_time_label.set_markup(sunrise_markup)
+            self.sunset_time_label.set_markup(sunset_markup)
+        self.systemClockFormat = systemClockFormat
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 811bc19..5d8100f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,5 +1,8 @@
 data/gnome-clocks.desktop.in
+gnomeclocks/alarm.py
 gnomeclocks/app.py
 gnomeclocks/clocks.py
+gnomeclocks/stopwatch.py
 gnomeclocks/timer.py
 gnomeclocks/widgets.py
+gnomeclocks/world.py



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