[gnome-clocks] Refine the new alarm dialog



commit 75aac183fc5cce853ef20d72ff01ec5072e46c4f
Author: Eslam Mostafa <cseslam gmail com>
Date:   Sun Aug 5 13:44:18 2012 +0200

    Refine the new alarm dialog
    
    Signed-off-by: Seif Lotfy <seif lotfy com>

 src/alarm.py          |  140 ++++++++++++++++++-----
 src/alarms_handler.py |   39 ------
 src/clocks.py         |   39 ++++--
 src/gnome_clocks.py   |    9 +-
 src/gnome_clocks.py~  |  308 -------------------------------------------------
 src/storage.py        |    6 +
 src/widgets.py        |  212 ++++++++++++++++++++--------------
 7 files changed, 273 insertions(+), 480 deletions(-)
---
diff --git a/src/alarm.py b/src/alarm.py
index c6d3985..a940a2e 100644
--- a/src/alarm.py
+++ b/src/alarm.py
@@ -1,20 +1,102 @@
-import datetime, vobject, time
+import datetime, vobject, time, os
+
+class ICSHandler():
+    def __init__(self):
+        self.ics_file = 'alarms.ics'
+        
+    def add_vevent(self, vobj):        
+        with open(self.ics_file, 'r+') as ics:        
+            content = ics.read()        
+            ics.seek(0)
+            vcal = vobject.readOne(content)                  
+            vcal.add(vobj)        
+            ics.write(vcal.serialize())                  
+                
+    def load_vevents(self):                
+        alarms = [] 
+        if os.path.exists(self.ics_file):
+            with open(self.ics_file, 'r') as ics:                            
+                vcal = vobject.readOne(ics.read())          
+                for item in vcal.components():            
+                    alarms.append(item)                                
+        else:
+            self.generate_ics_file()
+        return alarms
+        
+    def generate_ics_file(self):
+        vcal = vobject.iCalendar()
+        ics = open('alarms.ics', 'w')      
+        ics.write(vcal.serialize())
+        ics.close()  
+        
+        
+    def delete_alarm(self, alarm_uid):
+        with open('alarms.ics', 'r+') as ics:
+            data = vobject.readOne(ics.read())
+        for alarm in vcal.vevent_list:
+            if alarm.uid.value == alarm_uid:
+                #delete event
+                break
+      
+    def edit_alarm(self, alarm_uid, new_name=None, new_hour=None, new_mins=None, new_p=None, new_repeat=None):
+        with open(self.ics_file, 'r+') as ics:
+            vcal = vobject.readOne(ics.read())
+        for event in vcal.vevent_list:
+            if event.uid.value == alarm_uid:
+                if new_name:
+                    del event.summary
+                    event.add('summary').value = new_name
 
 class AlarmItem:
-    def __init__(self, name, time, repeat, h, m, p):
-        self.name = name
-        self.time = time
+    def __init__(self, name=None, repeat=None, h=None, m=None, p=None):
+        self.name = name        
         self.repeat = repeat
+        self.vevent = None
+        self.uid = None
         self.h = h
         self.m = m
         self.p = p
+            
+    def new_from_vevent(self, vevent):        
+        self.name = vevent.summary.value        
+        self.time = vevent.dtstart.value
+        self.h = int(self.time.strftime("%H"))
+        self.m = int(self.time.strftime("%M"))
+        self.p = self.time.strftime("%p")
+        self.uid = vevent.uid.value        
 
-    def set_alarm_time(self, time):
-        self.time = time 
+    def set_alarm_time(self, h, m, p):
+        self.h = h
+        self.m = m
+        self.p = p
         
-    def get_alarm_time(self):
+    def get_alarm_time(self):        
+        time = {}
+        time['h'] = self.h 
+        time['m'] = self.m        
+        time['p'] = self.p
         return self.time
         
+    def get_time_12h_as_string(self):
+        if self.p == 'AM' or self.p == 'PM':        
+            if self.h == 12 or self.h == 0:
+                h = 12
+            else:
+                h = self.h - 12
+        else:
+            h = self.h
+        return "%2i:%2i %s" % (h, self.m, self.p)
+        
+                    
+    def get_time_24h_as_string(self):
+        if self.p == 'AM' or self.p == 'PM':        
+            h = self.h + 12
+            if h == 24:
+                h = 12
+        else:
+            h = self.h
+        return "%2i:%2i" % (h, self.m)
+        
     def set_alarm_name(self, name):
         self.name = name
     
@@ -26,28 +108,26 @@ class AlarmItem:
 
     def get_alarm_repeat(self):
         return self.repeat
+        
+    def get_uid(self):
+        return self.vevent.uid.value
     
-    def get_vobject(self):                
-        alarm = vobject.newFromBehavior('vevent')            
-        alarm.add('summary').value = self.name                        
-        if self.p == 'AM':
-            print self.h
-            if self.h == 12:
-                self.h = 0
-            h_end = self.h+1
-            m_end = self.m
-        elif self.p == 'PM':
-            self.h += 12
-            h_end = self.h+1
-            m_end = self.m
-            if self.h == 24:
-                self.h = 23
-                h_end = 23
-                m_end = 59
+    def get_vevent(self):                
+        self.vevent = vevent = vobject.newFromBehavior('vevent')                    
+        vevent.add('summary').value = self.name               
+        h = self.h
+        m = self.m
+        if self.p == "PM":
+            h = self.h + 12
+            if h == 24:
+                h = 12
+        elif self.p == "AM":
+            if h == 12:
+                h = 0        
+        vevent.add('dtstart').value = datetime.datetime.combine(datetime.date.today(), datetime.time(h, m))                      
+        vevent.add('dtend').value = datetime.datetime.combine(datetime.date.today(), datetime.time(h, 59))
+        if len(self.repeat) == 0:
+            vevent.add('rrule').value = 'FREQ=DAILY;'
         else:
-            h_end = self.h
-            m_end = 59
-        alarm.add('dtstart').value = datetime.datetime.combine(datetime.date.today(), datetime.time(self.h, self.m))                      
-        alarm.add('dtend').value = datetime.datetime.combine(datetime.date.today(), datetime.time(h_end, m_end))
-        alarm.add('rrule').value = 'FREQ=WEEKLY;BYDAY=%s' % ','.join(self.repeat)        
-        return alarm        
+            vevent.add('rrule').value = 'FREQ=WEEKLY;BYDAY=%s' % ','.join(self.repeat)        
+        return vevent
diff --git a/src/clocks.py b/src/clocks.py
index 2d469aa..9a05e22 100644
--- a/src/clocks.py
+++ b/src/clocks.py
@@ -22,13 +22,12 @@ from gi.repository import Gtk, GObject, Gio, Gdk, Gst, Notify, cairo
 from gi.repository.GdkPixbuf import Pixbuf
 
 from widgets import NewWorldClockDialog, DigitalClock, NewAlarmDialog, AlarmWidget, WorldEmpty
-from alarms_handler import AlarmsHandler
 from storage import worldclockstorage
 
 from datetime import datetime, timedelta
 from pytz import timezone
 from timer import TimerWelcomeScreen, TimerScreen, Spinner
-from alarm import AlarmItem
+from alarm import AlarmItem, ICSHandler
 import pytz, time, os
 
 
@@ -205,22 +204,36 @@ class Alarm (Clock):
         self.alarms = []
         self.load_alarms()
         self.show_all()
+    
+    def get_system_clock_format(self):
+        settings = Gio.Settings.new('org.gnome.desktop.interface')
+        systemClockFormat = settings.get_string('clock-format')
+        return systemClockFormat
         
     def load_alarms(self):
-        ah = AlarmsHandler()
-        alarms = ah.load_alarms()        
-        for alarm in alarms:         
-            name = alarm.summary.value        
-            time = alarm.dtstart.value                                  
-            d = AlarmWidget(time)                        
-            view_iter = self.liststore.append([d.drawing.pixbuf, "<b>" + name + "</b>", d])
-            d.set_iter(self.liststore, view_iter)          
+        handler = ICSHandler()
+        vevents = handler.load_vevents()        
+        if vevents:
+            for vevent in vevents:         
+                alarm = AlarmItem()
+                alarm.new_from_vevent(vevent)                        
+                scf = self.get_system_clock_format()
+                if scf == "12h":
+                    d = AlarmWidget(alarm.get_time_12h_as_string())                        
+                else:
+                    d = AlarmWidget(alarm.get_time_24h_as_string())                        
+                view_iter = self.liststore.append([d.drawing.pixbuf, "<b>" + alarm.get_alarm_name() + "</b>", d])
+                d.set_iter(self.liststore, view_iter)          
         self.show_all()
       
     def add_alarm(self, alarm):
-        ah = AlarmsHandler()
-        ah.add_alarm(alarm.get_vobject())
-        d = AlarmWidget(datetime.utcfromtimestamp(alarm.time))
+        handler = ICSHandler()
+        handler.add_vevent(alarm.get_vevent())        
+        scf = self.get_system_clock_format()
+        if scf == "12h":
+            d = AlarmWidget(alarm.get_time_12h_as_string())
+        else:
+            d = AlarmWidget(alarm.get_time_24h_as_string())                               
         view_iter = self.liststore.append([d.drawing.pixbuf, "<b>" + alarm.get_alarm_name() + "</b>", d])
         d.set_iter(self.liststore, view_iter)
         self.show_all()
diff --git a/src/gnome_clocks.py b/src/gnome_clocks.py
index 68a0213..bb36d13 100755
--- a/src/gnome_clocks.py
+++ b/src/gnome_clocks.py
@@ -27,15 +27,14 @@ import sys
 
 class Window (Gtk.ApplicationWindow):
     def __init__ (self, app):
-        Gtk.ApplicationWindow.__init__ (self, title="Clocks", application=app)
+        Gtk.ApplicationWindow.__init__ (self, title="Clocks", application=app, hide_titlebar_when_maximized=True)
 
         self.set_wmclass("Clocks", "Clocks")
 
         css_provider = Gtk.CssProvider()
-        css_provider.load_from_path("gtk-style.css")
-        self.set_hide_titlebar_when_maximized (True)
-        #self.maximize ()
-        self.set_icon_from_file ('data/preferences-system-time.png')
+        css_provider.load_from_path("../gtk-style.css")
+        #self.set_hide_titlebar_when_maximized (True)        
+        self.set_icon_from_file ('../data/preferences-system-time.png')
         context = Gtk.StyleContext()
         context.add_provider_for_screen (Gdk.Screen.get_default (),
                                          css_provider,
diff --git a/src/storage.py b/src/storage.py
index 1da6dac..aa1cd0e 100644
--- a/src/storage.py
+++ b/src/storage.py
@@ -69,5 +69,11 @@ class WorldClockStorage ():
         except Exception, e:
           print "--", e
           return []
+          
+    def delete_all_clocks(self):
+        f = open(DATA_PATH, "w")
+        f.write("")
+        f.close()
 
 worldclockstorage = WorldClockStorage ()
+worldclockstorage.delete_all_clocks()
diff --git a/src/widgets.py b/src/widgets.py
index 6614bbd..ab73c31 100644
--- a/src/widgets.py
+++ b/src/widgets.py
@@ -139,9 +139,9 @@ class DigitalClock ():
     def get_image(self):
         local_time = self.get_local_time ()
         if local_time.tm_hour > 7 and local_time.tm_hour < 19:
-            return "data/cities/day.png"
+            return "../data/cities/day.png"
         else:
-            return "data/cities/night.png"
+            return "../data/cities/night.png"
 
     def get_is_day(self):
         local_time = self.get_local_time ()
@@ -172,36 +172,6 @@ class DigitalClock ():
         
     def get_standalone_widget (self):
         return self.standalone
-
-class AlarmWidget():
-    def __init__(self, t_given):                          
-        self.drawing = DigitalClockDrawing ()        
-        clockformat = self.get_system_clock_format()
-        if clockformat == '12h':
-            t = t_given.strftime("%I:%M %p")        
-        else:
-            t = t_given.strftime("%H:%M")        
-        isDay = self.get_is_day(t)
-        if isDay == True:
-            img = "data/cities/day.png"
-        else:
-            img = "data/cities/night.png"
-        self.drawing.render(t, img, isDay)
-    
-    def get_system_clock_format(self):
-        settings = Gio.Settings.new('org.gnome.desktop.interface')
-        systemClockFormat = settings.get_string('clock-format')
-        return systemClockFormat
-        
-    def get_is_day(self, t):
-        if t[6:8] == 'AM':
-            return True
-        else:
-            return False
-        
-    def set_iter (self, list_store, view_iter):
-        self.view_iter = view_iter
-        self.list_store = list_store
       
 class DigitalClockStandalone (Gtk.VBox):
     def __init__ (self, location):
@@ -346,6 +316,33 @@ class DigitalClockDrawing (Gtk.DrawingArea):
         self.pixbuf = pixbuf
         return self.pixbuf
 
+class AlarmWidget():
+    def __init__(self, time_given):                              
+        self.drawing = DigitalClockDrawing ()        
+        clockformat = self.get_system_clock_format()            
+        t = time_given
+        isDay = self.get_is_day(t)
+        if isDay == True:
+            img = "../data/cities/day.png"
+        else:
+            img = "../data/cities/night.png"
+        self.drawing.render(t, img, isDay)
+    
+    def get_system_clock_format(self):
+        settings = Gio.Settings.new('org.gnome.desktop.interface')
+        systemClockFormat = settings.get_string('clock-format')
+        return systemClockFormat
+        
+    def get_is_day(self, t):
+        if t[6:8] == 'AM':
+            return True
+        else:
+            return False
+        
+    def set_iter (self, list_store, view_iter):
+        self.view_iter = view_iter
+        self.list_store = list_store
+
 class NewAlarmDialog (Gtk.Dialog):
     
     __gsignals__ = {'add-alarm': (GObject.SignalFlags.RUN_LAST,
@@ -368,10 +365,7 @@ class NewAlarmDialog (Gtk.Dialog):
         table1.set_col_spacings(9)
         content_area = self.get_content_area ()        
         content_area.pack_start(table1, True, True, 0)
-        cancel = self.add_button("Cancel", 0)
-        self.save = save = self.add_button("Save", 1)
-        save.get_style_context().add_class('raised')        
-        save.set_sensitive(False)
+        self.add_buttons("Cancel", 0, "Save", 1)        
         self.connect("response", self.on_response)
         table1.set_border_width (5)
         
@@ -385,21 +379,13 @@ class NewAlarmDialog (Gtk.Dialog):
         points.set_alignment(0.5, 0.5)
 
         if cf == "12h":
-            houradjust = Gtk.Adjustment(h, 0, 12, 1, 1, 0)
+            if p == "PM":
+                h = h-12            
+            self.hourselect = hourselect = AlarmDialogSpin(h, 1, 12)
         else:
-            houradjust = Gtk.Adjustment(h, 0, 23, 1, 1, 0)
-        self.hourselect = hourselect = Gtk.SpinButton()
-        hourselect.connect('value-changed', self._on_hours_changed)
-        hourselect.set_adjustment(houradjust)        
-        hourbox = Gtk.Box(True, 0)
-        hourbox.pack_start (hourselect, False, True, 0)
+            self.hourselect = hourselect = AlarmDialogSpin(h, 0, 23)                 
+        self.minuteselect = minuteselect = AlarmDialogSpin(m, 0, 59)
         
-        minuteadjust = Gtk.Adjustment(m, 0, 59, 1, 1, 0)
-        self.minuteselect = minuteselect = Gtk.SpinButton()
-        minuteselect.connect('value-changed', self._on_minutes_changed)
-        minuteselect.set_adjustment(minuteadjust)
-        minutebox = Gtk.Box(True, 0)        
-        minutebox.pack_start (minuteselect, False, True, 0)
         
         
         if cf == "12h":
@@ -412,15 +398,15 @@ class NewAlarmDialog (Gtk.Dialog):
                 ampm.set_active(1)    
             
             table1.attach (time_label, 0, 1, 0, 1)
-            table1.attach (hourbox, 1, 2, 0, 1)
+            table1.attach (hourselect, 1, 2, 0, 1)
             table1.attach (points, 2, 3, 0, 1)
-            table1.attach (minutebox, 3, 4, 0, 1)  
+            table1.attach (minuteselect, 3, 4, 0, 1)  
             table1.attach (ampm, 4, 5, 0, 1)  
         else:
             table1.attach (time_label, 0, 1, 0, 1)
-            table1.attach (hourbox, 1, 2, 0, 1)
+            table1.attach (hourselect, 1, 2, 0, 1)
             table1.attach (points, 2, 3, 0, 1)
-            table1.attach (minutebox, 3, 4, 0, 1)              
+            table1.attach (minuteselect, 3, 4, 0, 1)              
             
         name = Gtk.Label ("Name")
         name.set_alignment(1.0, 0.5)
@@ -483,88 +469,125 @@ class NewAlarmDialog (Gtk.Dialog):
         if id == 0:
             self.destroy ()
         if id == 1:
-            name = self.entry.get_text()  #Perfect
-            time = self.hourselect.get_value_as_int() * 60 * 60 + self.minuteselect.get_value_as_int() * 60            
+            name = self.entry.get_text()  #Perfect            
             repeat = self.repeat_days
+            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'
+                    p = "AM"
                 else:
-                    p = 'PM'
-                new_alarm = AlarmItem(name, time, repeat, self.hourselect.get_value_as_int(), self.minuteselect.get_value_as_int(), p)            
+                    p = "PM"
             else:
-                new_alarm = AlarmItem(name, time, repeat, self.hourselect.get_value_as_int(), self.minuteselect.get_value_as_int(), None)            
+                p = None
+            new_alarm = AlarmItem(name, repeat, h, m, p)              
             self.emit('add-alarm', new_alarm)
             self.destroy ()
         else:
             pass
-            
-    def _on_hours_changed(self, btn):
-        self.check_save_button_status()
-        
-    def _on_minutes_changed(self, btn):
-        self.check_save_button_status()
-        
-    def check_save_button_status(self):
-        if len(self.repeat_days) != 0:              
-            self.save.set_sensitive(True)
-        else:
-            self.save.set_sensitive(False)
+                
                     
     def on_d1_clicked(self, btn):        
         if btn.get_active() == True:
             self.repeat_days.append('MO')
         if btn.get_active() == False:
             self.repeat_days.remove('MO')
-        self.check_save_button_status()
-                  
+                      
     def on_d2_clicked(self, btn):    
         if btn.get_active() == True:
             self.repeat_days.append('TU')
         else:
-            self.repeat_days.remove('TU')
-        self.check_save_button_status()
+            self.repeat_days.remove('TU')        
     
     def on_d3_clicked(self, btn):        
         if btn.get_active() == True:
             self.repeat_days.append('WE')
         else:
             self.repeat_days.remove('WE')
-        self.check_save_button_status()
     
     def on_d4_clicked(self, btn):
         if btn.get_active() == True:
             self.repeat_days.append('TH')
         else:
             self.repeat_days.remove('TH')
-        self.check_save_button_status()
     
     def on_d5_clicked(self, btn):        
         if btn.get_active() == True:
             self.repeat_days.append('FR')
         else:
             self.repeat_days.remove('FR')
-        self.check_save_button_status()
     
     def on_d6_clicked(self, btn):        
         if btn.get_active() == True:
             self.repeat_days.append('SA')
         else:
             self.repeat_days.remove('SA')
-        self.check_save_button_status()
     
     def on_d7_clicked(self, btn):        
         if btn.get_active() == True:
             self.repeat_days.append('SU')
         else:
             self.repeat_days.remove('SU')
-        self.check_save_button_status()
-
-class ClocksHome(Gtk.Box):
-    def __init__(self):
-        Gt.Box.__init__(self)
-        self.set_orientation(Gtk.Orientation.VERTICAL)
+            
+class AlarmDialogSpin(Gtk.Box):
+    def __init__(self, value, min_num, max_num):
+        Gtk.Box.__init__(self)
+        self.get_style_context().add_class('linked')
+        self.max_num = max_num
+        self.min_num = min_num
+        #
+        group = Gtk.SizeGroup()        
+        group.set_mode(Gtk.SizeGroupMode.VERTICAL)        
+        self.entry = entry = Gtk.Entry()
+        entry.set_size_request(-1, -1)
+        self.entry.set_text(str(value))
+        self.entry.set_max_length(2)
+        self.entry.set_alignment(1)
+        height = self.entry.get_allocated_height()
+        
+        group.add_widget(entry)
+        #
+        m_gicon = Gio.ThemedIcon.new_with_default_fallbacks("list-remove-symbolic")
+        m_img = Gtk.Image.new_from_gicon(m_gicon, Gtk.IconSize.MENU)
+        minus = Gtk.Button()
+      #  minus.set_size_request(-1, 10)
+        minus.set_image(m_img)
+        minus.connect("clicked", self._on_click_minus)
+        group.add_widget(minus)
+        #
+        p_gicon = Gio.ThemedIcon.new_with_default_fallbacks("list-add-symbolic")
+        p_img = Gtk.Image.new_from_gicon(p_gicon, Gtk.IconSize.MENU)
+        plus = Gtk.Button()        
+        #plus.set_size_request(-1, 10)
+        plus.set_image(p_img)
+        plus.connect("clicked", self._on_click_plus)
+        group.add_widget(plus)
+        #
+        self.pack_start(entry, False, False, 0)
+        self.pack_start(minus, False, False, 0)
+        self.pack_start(plus, False, False, 0)
+        self.show_all()
+        
+    def get_value_as_int(self):
+        text = self.entry.get_text()
+        return int(text)
+        
+    def _on_click_minus(self, btn):
+        value = self.get_value_as_int()
+        if value == self.min_num:
+            new_value = self.max_num
+        else:
+            new_value = value - 1
+        self.entry.set_text(str(new_value))
+        
+    def _on_click_plus(self, btn):
+        value = self.get_value_as_int()
+        if value == self.max_num:
+            new_value = self.min_num
+        else:
+            new_value = value + 1
+        self.entry.set_text(str(new_value))
         
 class WorldEmpty(Gtk.Box):
     def __init__(self):
@@ -584,3 +607,22 @@ class WorldEmpty(Gtk.Box):
 
     def unselect_all(self):
         pass
+
+class AlarmsEmpty(Gtk.Box):
+    def __init__(self):
+        Gtk.Box.__init__(self)
+        self.set_orientation(Gtk.Orientation.VERTICAL)
+        gicon = Gio.ThemedIcon.new_with_default_fallbacks("document-open-recent-symbolic")
+        image = Gtk.Image.new_from_gicon(gicon, Gtk.IconSize.DIALOG)
+        image.set_sensitive (False)
+        text = Gtk.Label("")
+        text.set_markup("<span color='darkgrey'>Select <b>New</b> to add a world clock</span>")
+        self.pack_start(Gtk.Label(""), True, True, 0)
+        self.pack_start(image, False, False, 6)
+        self.pack_start(text, False, False, 6)
+        self.pack_start(Gtk.Label(""), True, True, 0)
+        self.button = Gtk.ToggleButton()
+        self.show_all()
+
+    def unselect_all(self):
+        pass



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