[hamster-applet] fixed trailing space



commit 3c68355c5d60e3893b588d87b36d9f1a41e1da90
Author: Toms Bauģis <toms baugis gmail com>
Date:   Mon Jan 11 22:06:39 2010 +0000

    fixed trailing space

 hamster/KeyBinder.py                   |   20 ++--
 hamster/about.py                       |   10 +-
 hamster/applet.py                      |  108 +++++++-------
 hamster/charting.py                    |  178 +++++++++++-----------
 hamster/configuration.py               |   46 +++---
 hamster/db.py                          |  250 ++++++++++++++++----------------
 hamster/edit_activity.py               |   58 ++++----
 hamster/eds.py                         |    2 +-
 hamster/graphics.py                    |   61 ++++----
 hamster/hamster-applet.py              |   26 ++--
 hamster/hamsterdbus.py                 |   14 +-
 hamster/idle.py                        |    6 +-
 hamster/preferences.py                 |   98 ++++++------
 hamster/pytweener.py                   |  120 ++++++++--------
 hamster/reports.py                     |   68 +++++-----
 hamster/stats.py                       |   66 ++++----
 hamster/stats_overview.py              |   38 +++---
 hamster/stats_reports.py               |   22 ++--
 hamster/stats_stats.py                 |   82 +++++-----
 hamster/storage.py                     |   18 +-
 hamster/stuff.py                       |   58 ++++----
 hamster/widgets/__init__.py            |   16 +-
 hamster/widgets/activityentry.py       |   72 +++++-----
 hamster/widgets/dateinput.py           |   30 ++--
 hamster/widgets/dayline.py             |   80 +++++-----
 hamster/widgets/facttree.py            |   29 ++--
 hamster/widgets/reportchooserdialog.py |   14 +-
 hamster/widgets/tags.py                |  110 +++++++-------
 hamster/widgets/timeinput.py           |   64 ++++----
 hamster/widgets/timeline.py            |   78 +++++-----
 tests/charting_test.py                 |    4 +-
 tests/hamsterdbus_test.py              |   32 ++--
 tests/stuff_test.py                    |    4 +-
 33 files changed, 940 insertions(+), 942 deletions(-)
---
diff --git a/hamster/KeyBinder.py b/hamster/KeyBinder.py
index 9c8a730..6545d9d 100644
--- a/hamster/KeyBinder.py
+++ b/hamster/KeyBinder.py
@@ -26,19 +26,19 @@ from configuration import GconfStore, runtime
 class Keybinder(object):
     def __init__(self):
         self.config = GconfStore()
-        
+
         self.bound = False
         self.prevbinding = None
-        
+
         self.key_combination = self.config.get_keybinding()
         if self.key_combination is None:
             # This is for uninstalled cases, the real default is in the schema
             self.key_combination = "<Super>H"
-    
+
         runtime.dispatcher.add_handler("gconf_keybinding_changed", self.on_keybinding_changed)
-        
+
         self.bind()
-      
+
     def on_keybinding_changed(self, event, new_binding = None):
         self.prevbinding = self.key_combination
         self.key_combination = new_binding
@@ -46,14 +46,14 @@ class Keybinder(object):
 
     def on_keybinding_activated(self):
         runtime.dispatcher.dispatch('keybinding_activated')
-   
+
     def get_key_combination(self):
         return self.key_combination
-   
+
     def bind(self):
         if self.bound:
             self.unbind()
-         
+
         try:
             print 'Binding shortcut %s to popup hamster' % self.key_combination
             keybinder.tomboy_keybinder_bind(self.key_combination, self.on_keybinding_activated)
@@ -61,9 +61,9 @@ class Keybinder(object):
         except KeyError:
             # if the requested keybinding conflicts with an existing one, a KeyError will be thrown
             self.bound = False
-        
+
         #self.emit('changed', self.bound)  TODO - revert to previous hotkey
-               
+
     def unbind(self):
         try:
             print 'Unbinding shortcut %s to popup hamster' % self.prevbinding
diff --git a/hamster/about.py b/hamster/about.py
index 4eaff13..4609664 100644
--- a/hamster/about.py
+++ b/hamster/about.py
@@ -46,20 +46,20 @@ class About(object):
             "title": _("About Time Tracker"),
             "wrap-license": True
         }
-        
+
         about.set_authors(["Toms Bauģis <toms baugis gmail com>",
                            "Patryk Zawadzki <patrys pld-linux org>",
                            "PÄ?teris Caune <cuu508 gmail com>",
                            "Juanje Ojeda <jojeda emergya es>"])
         about.set_artists(["Kalle Persson <kalle kallepersson se>"])
-        
+
         about.set_translator_credits(_("translator-credits"))
-    
+
         for prop, val in infos.items():
             about.set_property(prop, val)
-    
+
         about.set_logo_icon_name("hamster-applet")
-        
+
         about.connect("response", lambda self, *args: self.destroy())
         about.show_all()
 
diff --git a/hamster/applet.py b/hamster/applet.py
index be44601..3688391 100755
--- a/hamster/applet.py
+++ b/hamster/applet.py
@@ -49,14 +49,14 @@ try:
     PYNOTIFY = True
 except:
     PYNOTIFY = False
-    
+
 class Notifier(object):
     def __init__(self, attach):
         self._icon = gtk.STOCK_DIALOG_QUESTION
         self._attach = attach
         # Title of reminder notification
         self.summary = _("Time Tracker")
-      
+
         if not pynotify.is_initted():
             pynotify.init('Hamster Applet')
 
@@ -67,9 +67,9 @@ class Notifier(object):
             #translators: this is edit activity action in the notifier bubble
             notify.add_action("edit", _("Edit"), edit_cb)
             #translators: this is switch activity action in the notifier bubble
-            notify.add_action("switch", _("Switch"), switch_cb)            
+            notify.add_action("switch", _("Switch"), switch_cb)
         notify.show()
-    
+
     def msg_low(self, message):
         notify = pynotify.Notification(self.summary, message, self._icon, self._attach)
         notify.set_urgency(pynotify.URGENCY_LOW)
@@ -81,7 +81,7 @@ class PanelButton(gtk.ToggleButton):
         gtk.ToggleButton.__init__(self)
         self.set_relief(gtk.RELIEF_NONE)
         self.set_border_width(0)
-        
+
         self.label = gtk.Label()
         self.label.set_justify(gtk.JUSTIFY_CENTER)
 
@@ -90,7 +90,7 @@ class PanelButton(gtk.ToggleButton):
         self.connect('button_press_event', self.on_button_press)
 
         self.add(self.label)
-        
+
         self.activity, self.duration = None, None
         self.prev_size = 0
 
@@ -100,7 +100,7 @@ class PanelButton(gtk.ToggleButton):
                 GtkWidget::focus-line-width=0
                 GtkWidget::focus-padding=0
             }
-                                     
+
             widget "*.hamster-applet-button" style "hamster-applet-button-style"
         """);
         gtk.Widget.set_name (self, "hamster-applet-button");
@@ -117,7 +117,7 @@ class PanelButton(gtk.ToggleButton):
         self.activity = activity
         self.duration = duration
         self.reformat_label()
-        
+
     def reformat_label(self):
         label = self.activity
         if self.duration:
@@ -125,7 +125,7 @@ class PanelButton(gtk.ToggleButton):
                 label = "%s\n%s" % (self.activity, self.duration)
             else:
                 label = "%s %s" % (self.activity, self.duration)
-        
+
         label = '<span gravity="south">%s</span>' % label
         self.label.set_markup("") #clear - seems to fix the warning
         self.label.set_markup(label)
@@ -139,7 +139,7 @@ class PanelButton(gtk.ToggleButton):
             return False
 
         popup_dir = self.get_parent().get_orient()
- 
+
         orient_vertical = popup_dir in [gnomeapplet.ORIENT_LEFT] or \
                           popup_dir in [gnomeapplet.ORIENT_RIGHT]
 
@@ -164,7 +164,7 @@ class PanelButton(gtk.ToggleButton):
             available_size = self.get_allocation().width
         else:
             available_size = self.get_allocation().height
-        
+
         return required_size <= available_size
 
     def on_label_style_set(self, widget, something):
@@ -175,7 +175,7 @@ class PanelButton(gtk.ToggleButton):
             return
 
         self.popup_dir = self.get_parent().get_orient()
-        
+
         orient_vertical = True
         new_size = allocation.width
         if self.popup_dir in [gnomeapplet.ORIENT_LEFT]:
@@ -186,7 +186,7 @@ class PanelButton(gtk.ToggleButton):
             new_angle = 0
             orient_vertical = False
             new_size = allocation.height
-        
+
         if new_angle != self.label.get_angle():
             self.label.set_angle(new_angle)
 
@@ -212,7 +212,7 @@ class HamsterApplet(object):
         self.open_fact_editors = []
 
         self.config = GconfStore()
-        
+
         self.button = PanelButton()
         self.button.connect('toggled', self.on_toggle)
         self.applet.add(self.button)
@@ -246,7 +246,7 @@ class HamsterApplet(object):
         self.treeview.connect("key-press-event", self.on_todays_keys)
         self.treeview.connect("edit-clicked", self._open_edit_activity)
         self.treeview.connect("row-activated", self.on_today_row_activated)
-        
+
         self.get_widget("today_box").add(self.treeview)
 
         # DBus Setup
@@ -261,7 +261,7 @@ class HamsterApplet(object):
 
         except dbus.DBusException, e:
             logging.error("Can't init dbus: %s" % e)
-    
+
         self.day_start = self.config.get_day_start()
 
         # Load today's data, activities and set label
@@ -292,9 +292,9 @@ class HamsterApplet(object):
 
         runtime.dispatcher.add_handler('gconf_notify_on_idle_changed', self.on_notify_on_idle_changed)
         self.notify_on_idle = self.config.get_notify_on_idle()
-        
+
         runtime.dispatcher.add_handler('gconf_on_day_start_changed', self.on_day_start_changed)
-        
+
         # init nagging timeout
         if PYNOTIFY:
             self.notify = Notifier(self.button)
@@ -304,10 +304,10 @@ class HamsterApplet(object):
 
     """UI functions"""
     def refresh_hamster(self):
-        """refresh hamster every x secs - load today, check last activity etc."""        
+        """refresh hamster every x secs - load today, check last activity etc."""
 
         #if we the day view is visible - update day's durations
-        if self.button.get_active(): 
+        if self.button.get_active():
             self.load_day()
 
         self.update_label()
@@ -325,12 +325,12 @@ class HamsterApplet(object):
         else:
             label = "%s" % _(u"No activity")
             self.button.set_text(label, None)
-            
+
 
     def check_user(self):
         if not self.notify_interval: #no interval means "never"
             return
-        
+
         now = dt.datetime.now()
         if self.last_activity:
             delta = now - self.last_activity['start_time']
@@ -349,7 +349,7 @@ class HamsterApplet(object):
         dialogs.edit.show(self.applet, activity_id = self.last_activity['id'])
 
     def switch_cb(self, n, action):
-        self.__show_toggle(None, not self.button.get_active())	
+        self.__show_toggle(None, not self.button.get_active())
 
 
     def load_day(self):
@@ -366,14 +366,14 @@ class HamsterApplet(object):
             self.last_activity = facts[-1]
         else:
             self.last_activity = None
-        
+
         if len(facts) > 10:
             self._gui.get_object("today_box").set_size_request(-1, 250)
             self._gui.get_object("today_box").set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
         else:
             self._gui.get_object("today_box").set_size_request(-1, -1)
             self._gui.get_object("today_box").set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_NEVER)
-            
+
         by_category = {}
         for fact in facts:
             duration = 24 * 60 * fact["delta"].days + fact["delta"].seconds / 60
@@ -381,13 +381,13 @@ class HamsterApplet(object):
                           by_category.setdefault(fact['category'], 0) + duration
             self.treeview.add_fact(fact)
 
-        
+
         if not facts:
             self._gui.get_object("today_box").hide()
             self._gui.get_object("fact_totals").set_text(_("No records today"))
         else:
             self._gui.get_object("today_box").show()
-            
+
             total_strings = []
             for category in by_category:
                 # listing of today's categories and time spent in them
@@ -395,27 +395,27 @@ class HamsterApplet(object):
                 total_strings.append(_("%(category)s: %(duration)s") % \
                         ({'category': category,
                           #duration in main drop-down per category in hours
-                          'duration': _("%sh") % duration 
+                          'duration': _("%sh") % duration
                           }))
 
             total_string = ", ".join(total_strings)
             self._gui.get_object("fact_totals").set_text(total_string)
-            
+
         self.set_last_activity()
 
     def set_last_activity(self):
         activity = self.last_activity
         #sets all the labels and everything as necessary
         self.get_widget("stop_tracking").set_sensitive(activity != None)
-        
-        
+
+
         if activity:
             self.get_widget("switch_activity").show()
             self.get_widget("start_tracking").hide()
-            
+
             delta = dt.datetime.now() - activity['start_time']
             duration = delta.seconds /  60
-            
+
             self.get_widget("last_activity_duration").set_text(stuff.format_duration(duration) or _("Just started"))
             self.get_widget("last_activity_name").set_text(activity['name'])
             if activity['category'] != _("Unsorted"):
@@ -443,21 +443,21 @@ class HamsterApplet(object):
         (cur, col) = self.treeview.get_cursor()
         runtime.storage.remove_fact(model[iter][0])
 
-        if next_row:        
+        if next_row:
             self.treeview.set_cursor(cur)
 
 
     def __update_fact(self):
         """dbus controller current fact updating"""
         last_activity_id = 0
-        
+
         if not self.last_activity:
             self.dbusController.TrackingStopped()
         else:
             last_activity_id = self.last_activity['id']
 
         self.dbusController.FactUpdated(last_activity_id)
-            
+
     def __show_toggle(self, event, is_active):
         """main window display and positioning"""
         self.button.set_active(is_active)
@@ -471,7 +471,7 @@ class HamsterApplet(object):
 
         label_geom = self.button.get_allocation()
         window_geom = self.window.get_allocation()
-        
+
         x, y = self.button.get_pos()
 
         self.popup_dir = self.applet.get_orient()
@@ -495,14 +495,14 @@ class HamsterApplet(object):
 
         self.new_name.set_text("");
         self.new_tags.set_text("");
-        gobject.idle_add(self._delayed_display)  
-        
+        gobject.idle_add(self._delayed_display)
+
     def _delayed_display(self):
         """show window only when gtk has become idle. otherwise we get
         mixed results. TODO - this looks like a hack though"""
         self.window.present()
         self.new_name.grab_focus()
-        
+
 
     """events"""
     def on_toggle(self, widget):
@@ -513,17 +513,17 @@ class HamsterApplet(object):
         if (event.keyval == gtk.keysyms.Delete):
             self.delete_selected()
             return True
-            
+
         return False
-    
+
     def _open_edit_activity(self, row, fact):
         """opens activity editor for selected row"""
         dialogs.edit.show(self.applet, fact_id = fact["id"])
-        
+
     def on_today_row_activated(self, tree, path, column):
         selection = tree.get_selection()
         (model, iter) = selection.get_selected()
-        
+
         fact = model[iter][6]
         if fact:
             activity = fact['name']
@@ -533,21 +533,21 @@ class HamsterApplet(object):
             tags = fact["tags"]
             if fact["description"]:
                 tags.append(fact["description"])
-                
+
             runtime.storage.add_fact(activity, ", ".join(tags))
             runtime.dispatcher.dispatch('panel_visible', False)
-        
-        
+
+
     def on_windows_keys(self, tree, event_key):
         if (event_key.keyval == gtk.keysyms.Escape
-          or (event_key.keyval == gtk.keysyms.w 
+          or (event_key.keyval == gtk.keysyms.w
               and event_key.state & gtk.gdk.CONTROL_MASK)):
             if self.new_name.popup.get_property("visible") == False \
                and self.new_tags.popup.get_property("visible") == False:
                 runtime.dispatcher.dispatch('panel_visible', False)
                 return True
         return False
-        
+
     """button events"""
     def on_overview(self, menu_item):
         runtime.dispatcher.dispatch('panel_visible', False)
@@ -566,13 +566,13 @@ class HamsterApplet(object):
         runtime.dispatcher.dispatch('panel_visible', False)
         dialogs.prefs.show(self.applet)
 
-    
+
     """signals"""
     def after_activity_update(self, widget, renames):
         self.new_name.refresh_activities()
         self.load_day()
         self.update_label()
-    
+
     def after_fact_update(self, event, date):
         self.load_day()
         self.update_label()
@@ -587,7 +587,7 @@ class HamsterApplet(object):
             self.refresh_hamster()
         elif self.timeout_enabled and self.last_activity and \
              self.last_activity['end_time'] is None:
-            
+
             runtime.storage.touch_fact(self.last_activity,
                                        end_time = self.dbusIdleListener.getIdleFrom())
 
@@ -599,7 +599,7 @@ class HamsterApplet(object):
     """global shortcuts"""
     def on_keybinding_activated(self, event, data):
         self.__show_toggle(None, not self.button.get_active())
-        
+
     def on_timeout_enabled_changed(self, event, enabled):
         self.timeout_enabled = enabled
 
@@ -629,6 +629,6 @@ class HamsterApplet(object):
 
     def show(self):
         self.window.show_all()
-        
+
     def get_widget(self, name):
         return self._gui.get_object(name)
diff --git a/hamster/charting.py b/hamster/charting.py
index 7522dbe..cdbf11a 100644
--- a/hamster/charting.py
+++ b/hamster/charting.py
@@ -75,16 +75,16 @@ def get_limits(set, stack_subfactors = True):
                 min_value = max(row, min_value)
 
     return min_value, max_value
-    
+
 
 class Bar(object):
     def __init__(self, value, size = 0):
         self.value = value
         self.size = size
-    
+
     def __repr__(self):
         return str((self.value, self.size))
-        
+
 
 class Chart(graphics.Area):
     """Chart constructor. Optional arguments:
@@ -146,34 +146,34 @@ class Chart(graphics.Area):
         self.keys = []
         self.data = None
         self.stack_keys = []
-        
+
         self.key_colors = {} # key:color dictionary. if key's missing will grab basecolor
         self.stack_key_colors = {} # key:color dictionary. if key's missing will grab basecolor
-        
+
 
         # use these to mark area where the "real" drawing is going on
         self.graph_x, self.graph_y = 0, 0
         self.graph_width, self.graph_height = None, None
-        
+
         self.mouse_bar = None
         if self.interactive:
             self.connect("mouse-over", self.on_mouse_over)
             self.connect("button-release", self.on_clicked)
-            
+
         self.bars_selected = []
-        
-    
+
+
     def on_mouse_over(self, area, region):
         if region:
             self.mouse_bar = int(region[0])
         else:
             self.mouse_bar = None
-            
+
         self.redraw_canvas()
-        
+
     def on_clicked(self, area, bar):
         self.emit("bar-clicked", self.mouse_bar)
-    
+
     def select_bar(self, index):
         pass
 
@@ -181,15 +181,15 @@ class Chart(graphics.Area):
         # returns color darkened by it's index
         # the approach reduces contrast by each step
         base_color = self.bar_base_color or (220, 220, 220)
-        
+
         base_hls = colorsys.rgb_to_hls(*base_color)
-        
+
         step = (base_hls[1] - 30) / 10 #will go from base down to 20 and max 22 steps
-        
+
         return colorsys.hls_to_rgb(base_hls[0],
                                    base_hls[1] - step * index,
                                    base_hls[2])
-        
+
 
     def draw_bar(self, x, y, w, h, color = None):
         """ draws a simple bar"""
@@ -219,15 +219,15 @@ class Chart(graphics.Area):
 
 
     def on_expose(self):
-        # fill whole area 
+        # fill whole area
         if self.background:
             self.fill_area(0, 0, self.width, self.height, self.background)
-        
+
 
     def _update_targets(self):
         # calculates new factors and then updates existing set
         max_value = float(self.max_value) or 1 # avoid division by zero
-        
+
         self.bars = size_list(self.bars, self.data)
 
         #need function to go recursive
@@ -244,7 +244,7 @@ class Chart(graphics.Area):
 
                     self.tweener.addTween(bars[i], size = bars[i].value / float(max_value))
             return bars
-    
+
         retarget(self.bars, self.data)
 
 
@@ -255,9 +255,9 @@ class Chart(graphics.Area):
             self.layout.set_text(label)
             label_w, label_h = self.layout.get_pixel_size()
             max_extent = max(label_w + 5, max_extent)
-        
+
         return max_extent
-    
+
     def draw(self):
         logging.error("OMG OMG, not implemented!!!")
 
@@ -269,7 +269,7 @@ class BarChart(Chart):
         if not self.data:
             return
 
-        context = self.context        
+        context = self.context
         context.set_line_width(1)
 
 
@@ -281,7 +281,7 @@ class BarChart(Chart):
                 grid_stride = int(self.max_value * self.grid_stride)
             else:
                 grid_stride = int(self.grid_stride)
-            
+
             scale_labels = [self.value_format % i
                   for i in range(grid_stride, int(self.max_value), grid_stride)]
             self.legend_width = legend_width = self.legend_width or self.longest_label(scale_labels)
@@ -320,7 +320,7 @@ class BarChart(Chart):
         bar_width = min(self.graph_width / float(len(self.keys)), self.max_bar_width)
         for i, key in enumerate(self.keys):
             exes[key] = (x + self.graph_x, round(bar_width - 1))
-            
+
             x = x + round(bar_width)
             bar_width = min(self.max_bar_width,
                             (self.graph_width - x) / float(max(1, len(self.keys) - i - 1)))
@@ -332,20 +332,20 @@ class BarChart(Chart):
             label_w, label_h = self.layout.get_pixel_size()
 
             intended_x = exes[key][0] + (exes[key][1] - label_w) / 2
-            
+
             if not prev_label_end or intended_x > prev_label_end:
                 self.context.move_to(intended_x, self.graph_height + 4)
                 context.show_layout(self.layout)
-            
+
                 prev_label_end = intended_x + label_w + 3
-                
+
 
             bar_start = 0
             base_color = self.bar_base_color or (220, 220, 220)
-            
+
             if self.stack_keys:
                 remaining_fractions, remaining_pixels = 1, max_bar_size
-                
+
                 for j, stack_bar in enumerate(bar):
                     if stack_bar.size > 0:
                         bar_size = round(remaining_pixels * (stack_bar.size / remaining_fractions))
@@ -353,7 +353,7 @@ class BarChart(Chart):
                         remaining_pixels -= bar_size
 
                         bar_start += bar_size
-                        
+
                         last_color = self.stack_key_colors.get(self.stack_keys[j]) or self.get_bar_color(j)
                         self.draw_bar(exes[key][0],
                                       self.graph_height - bar_start,
@@ -377,17 +377,17 @@ class BarChart(Chart):
                     total_value = sum(data[i])
                 else:
                     total_value = data[i]
-                
+
                 self.layout.set_width(-1)
                 self.layout.set_text(self.value_format % total_value)
                 label_w, label_h = self.layout.get_pixel_size()
-    
+
 
                 if bar_start > label_h + 2:
                     label_y = self.graph_y + self.graph_height - bar_start + 5
                 else:
                     label_y = self.graph_y + self.graph_height - bar_start - label_h + 5
-                
+
                 context.move_to(self.exes[key][0] + (self.exes[key][1] - label_w) / 2.0,
                                 label_y)
 
@@ -395,7 +395,7 @@ class BarChart(Chart):
                 if colorsys.rgb_to_hls(*graphics.Colors.rgb(last_color))[1] < 150:
                     self.set_color(graphics.Colors.almost_white)
                 else:
-                    self.set_color(graphics.Colors.aluminium[5])        
+                    self.set_color(graphics.Colors.aluminium[5])
 
                 context.show_layout(self.layout)
 
@@ -408,7 +408,7 @@ class BarChart(Chart):
                 grid_stride = int(self.max_value * self.grid_stride)
             else:
                 grid_stride = int(self.grid_stride)
-            
+
             context.set_line_width(1)
             for i in range(grid_stride, int(self.max_value), grid_stride):
                 y = round(max_bar_size * (i / self.max_value)) + 0.5
@@ -430,16 +430,16 @@ class BarChart(Chart):
         if self.show_stack_labels:
             #put series keys
             self.set_color(graphics.Colors.aluminium[5]);
-            
+
             y = self.graph_height
             label_y = None
 
-            # if labels are at end, then we need show them for the last bar! 
+            # if labels are at end, then we need show them for the last bar!
             if self.labels_at_end:
                 factors = self.bars[-1]
             else:
                 factors = self.bars[0]
-            
+
             if isinstance(factors, Bar):
                 factors = [factors]
 
@@ -449,28 +449,28 @@ class BarChart(Chart):
                 self.layout.set_alignment(pango.ALIGN_LEFT)
             else:
                 self.layout.set_alignment(pango.ALIGN_RIGHT)
-    
+
             for j in range(len(factors)):
                 factor = factors[j].size
                 bar_size = factor * max_bar_size
-                
+
                 if round(bar_size) > 0 and self.stack_keys:
                     label = "%s" % self.stack_keys[j]
 
-                    
+
                     self.layout.set_text(label)
                     label_w, label_h = self.layout.get_pixel_size()
-                    
+
                     y -= bar_size
                     intended_position = round(y + (bar_size - label_h) / 2)
-                    
+
                     if label_y:
                         label_y = min(intended_position, label_y - label_h)
                     else:
                         label_y = intended_position
-                    
+
                     if self.labels_at_end:
-                        label_x = self.graph_x + self.graph_width 
+                        label_x = self.graph_x + self.graph_width
                         line_x1 = self.graph_x + self.graph_width - 1
                         line_x2 = self.graph_x + self.graph_width - 6
                     else:
@@ -498,13 +498,13 @@ class HorizontalBarChart(Chart):
 
         context = self.context
         rowcount, keys = len(self.keys), self.keys
-        
+
         # push graph to the right, so it doesn't overlap
         legend_width = self.legend_width or self.longest_label(keys)
-        
+
         self.graph_x = legend_width
         self.graph_x += 8 #add another 8 pixes of padding
-        
+
         self.graph_width = self.width - self.graph_x
         self.graph_y, self.graph_height = 0, self.height
 
@@ -512,7 +512,7 @@ class HorizontalBarChart(Chart):
         if self.chart_background:
             self.fill_area(self.graph_x, self.graph_y, self.graph_width, self.graph_height, self.chart_background)
 
-    
+
         if not self.data:  # go home if we have nothing
             return
 
@@ -521,7 +521,7 @@ class HorizontalBarChart(Chart):
         bar_width = min(self.graph_height / float(len(self.keys)), self.max_bar_width)
         for i, key in enumerate(self.keys):
             positions[key] = (y + self.graph_y, round(bar_width - 1))
-            
+
             y = y + round(bar_width)
             bar_width = min(self.max_bar_width,
                             (self.graph_height - y) / float(max(1, len(self.keys) - i - 1)))
@@ -531,14 +531,14 @@ class HorizontalBarChart(Chart):
 
         self.layout.set_alignment(pango.ALIGN_RIGHT)
         self.layout.set_ellipsize(pango.ELLIPSIZE_END)
-        
 
-        
+
+
         context.set_line_width(1)
 
         # bars and labels
         self.layout.set_width(legend_width * pango.SCALE)
-        
+
 
         for i, label in enumerate(keys):
             if self.interactive:
@@ -551,8 +551,8 @@ class HorizontalBarChart(Chart):
             self.layout.set_width(legend_width * pango.SCALE)
             self.layout.set_text(label)
             label_w, label_h = self.layout.get_pixel_size()
-            
-            self.set_color(graphics.Colors.aluminium[5])        
+
+            self.set_color(graphics.Colors.aluminium[5])
             context.move_to(0, positions[label][0] + (positions[label][1] - label_h) / 2)
             context.show_layout(self.layout)
 
@@ -564,7 +564,7 @@ class HorizontalBarChart(Chart):
                 bar_start = 0
 
                 remaining_fractions, remaining_pixels = 1, max_bar_size
-                
+
                 for j, stack_bar in enumerate(self.bars[i]):
                     if stack_bar.size > 0:
                         bar_size = round(remaining_pixels * (stack_bar.size / remaining_fractions))
@@ -600,7 +600,7 @@ class HorizontalBarChart(Chart):
                 total_value = sum(self.data[i])
             else:
                 total_value = self.data[i]
-            
+
             self.layout.set_width(-1)
             self.layout.set_text(self.value_format % total_value)
             label_w, label_h = self.layout.get_pixel_size()
@@ -608,7 +608,7 @@ class HorizontalBarChart(Chart):
             vertical_padding = max((positions[label][1] - label_h) / 2.0, 1)
             if  bar_start - vertical_padding < label_w:
                 label_x = self.graph_x + bar_start + vertical_padding
-                self.set_color(graphics.Colors.aluminium[5])        
+                self.set_color(graphics.Colors.aluminium[5])
             else:
                 if i in self.bars_selected:
                     self.set_color(self.get_style().fg[gtk.STATE_SELECTED].to_string())
@@ -617,10 +617,10 @@ class HorizontalBarChart(Chart):
                     if colorsys.rgb_to_hls(*graphics.Colors.rgb(last_color))[1] < 150:
                         self.set_color(graphics.Colors.almost_white)
                     else:
-                        self.set_color(graphics.Colors.aluminium[5])        
-                    
+                        self.set_color(graphics.Colors.aluminium[5])
+
                 label_x = self.graph_x + bar_start - label_w - vertical_padding
-            
+
             context.move_to(label_x, positions[label][0] + (positions[label][1] - label_h) / 2.0)
             context.show_layout(self.layout)
 
@@ -635,39 +635,39 @@ class HorizontalDayChart(Chart):
     def __init__(self, *args, **kwargs):
         Chart.__init__(self, *args, **kwargs)
         self.start_time, self.end_time = None, None
-    
+
     def plot_day(self, keys, data, start_time = None, end_time = None):
         self.keys, self.data = keys, data
         self.start_time, self.end_time = start_time, end_time
         self.show()
         self.redraw_canvas()
-    
+
     def on_expose(self):
         context = self.context
-        
+
         Chart.on_expose(self)
         rowcount, keys = len(self.keys), self.keys
-        
+
         start_hour = 0
         if self.start_time:
             start_hour = self.start_time
-        end_hour = 24 * 60        
+        end_hour = 24 * 60
         if self.end_time:
             end_hour = self.end_time
-        
-        
+
+
         # push graph to the right, so it doesn't overlap
         legend_width = self.legend_width or self.longest_label(keys)
 
         self.graph_x = legend_width
         self.graph_x += 8 #add another 8 pixes of padding
-        
+
         self.graph_width = self.width - self.graph_x
-        
+
         #on the botttom leave some space for label
         self.layout.set_text("1234567890:")
         label_w, label_h = self.layout.get_pixel_size()
-        
+
         self.graph_y, self.graph_height = 0, self.height - label_h - 4
 
 
@@ -677,32 +677,32 @@ class HorizontalDayChart(Chart):
         if not self.data:  #if we have nothing, let's go home
             return
 
-        
+
         positions = {}
         y = 0
         bar_width = min(self.graph_height / float(len(self.keys)), self.max_bar_width)
         for i, key in enumerate(self.keys):
             positions[key] = (y + self.graph_y, round(bar_width - 1))
-            
+
             y = y + round(bar_width)
             bar_width = min(self.max_bar_width,
                             (self.graph_height - y) / float(max(1, len(self.keys) - i - 1)))
 
 
-        
+
         max_bar_size = self.graph_width - 15
 
         self.layout.set_alignment(pango.ALIGN_RIGHT)
         self.layout.set_ellipsize(pango.ELLIPSIZE_END)
-        
+
         # bars and labels
         self.layout.set_width(legend_width * pango.SCALE)
 
         factor = max_bar_size / float(end_hour - start_hour)
 
         for i, label in enumerate(keys):
-            self.set_color(graphics.Colors.aluminium[5])        
-            
+            self.set_color(graphics.Colors.aluminium[5])
+
             self.layout.set_text(label)
             label_w, label_h = self.layout.get_pixel_size()
 
@@ -713,11 +713,11 @@ class HorizontalDayChart(Chart):
 
             if isinstance(self.data[i], list) == False:
                 self.data[i] = [self.data[i]]
-            
+
             for row in self.data[i]:
                 bar_x = round((row[0]- start_hour) * factor)
                 bar_size = round((row[1] - start_hour) * factor - bar_x)
-                
+
                 self.draw_bar(round(self.graph_x + bar_x),
                               positions[label][0],
                               bar_size,
@@ -733,7 +733,7 @@ class HorizontalDayChart(Chart):
         last_position = positions[keys[-1]]
         for i in range(start_hour + 60, end_hour, pace):
             x = round((i - start_hour) * factor)
-            
+
             minutes = i % (24 * 60)
 
             self.layout.set_markup(dt.time(minutes / 60, minutes % 60).strftime("%H<small><sup>%M</sup></small>"))
@@ -744,13 +744,13 @@ class HorizontalDayChart(Chart):
             self.set_color(graphics.Colors.aluminium[4])
             context.show_layout(self.layout)
 
-            
+
             self.set_color((255, 255, 255))
             self.context.move_to(round(self.graph_x + x) + 0.5, self.graph_y)
             self.context.line_to(round(self.graph_x + x) + 0.5,
                                  last_position[0] + last_position[1])
 
-                
+
         context.stroke()
 
 
@@ -761,12 +761,12 @@ class BasicWindow:
         window.set_title("Hamster Charting")
         window.set_size_request(400, 300)
         window.connect("delete_event", lambda *args: gtk.main_quit())
-    
+
         self.stacked = BarChart(background = "#fafafa",
                                 bar_base_color = (220, 220, 220),
                                 legend_width = 20,
                                 show_stack_labels = True)
-        
+
         box = gtk.VBox()
         box.pack_start(self.stacked)
 
@@ -777,7 +777,7 @@ class BasicWindow:
 
         import random
         self.data = [[random.randint(0, 10) for j in range(len(self.stacks))] for i in range(len(self.series))]
-        
+
         color_buttons = gtk.HBox()
         color_buttons.set_spacing(4)
 
@@ -787,13 +787,13 @@ class BasicWindow:
             color_buttons.pack_start(button)
 
         box.pack_start(color_buttons, False)
-        
+
         window.add(box)
         window.show_all()
 
         self.plot()
-        
-        
+
+
     def plot(self):
         self.stacked.stack_key_colors = self.stack_colors
         self.stacked.plot(self.series, self.data, self.stacks)
diff --git a/hamster/configuration.py b/hamster/configuration.py
index b2d0618..2eb594e 100644
--- a/hamster/configuration.py
+++ b/hamster/configuration.py
@@ -44,7 +44,7 @@ class RuntimeStore(Singleton):
     data_dir = ""
     dispatcher = None
     storage = None
-    
+
 
     def __init__(self):
         gettext.install("hamster-applet", unicode = True)
@@ -61,7 +61,7 @@ class RuntimeStore(Singleton):
         # figure out the correct database file
         old_db_file = os.path.expanduser("~/.gnome2/hamster-applet/hamster.db")
         new_db_file = os.path.join(xdg_data_home, "hamster-applet", "hamster.db")
-        
+
         if os.path.exists(old_db_file):
             db_path, _ = os.path.split(os.path.realpath(new_db_file))
             if not os.path.exists(db_path):
@@ -73,7 +73,7 @@ class RuntimeStore(Singleton):
                 logging.info("Have two database %s and %s" % (new_db_file, old_db_file))
             else:
                 os.rename(old_db_file, new_db_file)
-        
+
         self.database_path = new_db_file
 
 
@@ -84,12 +84,12 @@ class RuntimeStore(Singleton):
                 if gio_file.query_info(gio.FILE_ATTRIBUTE_ETAG_VALUE).get_etag() == self.last_etag:
                     # ours
                     return
-                
+
                 logging.info("DB file has been modified externally. Calling all stations")
                 self.storage.dispatch_overwrite()
 
 
-        
+
         self.database_file = gio.File(self.database_path)
         self.db_monitor = self.database_file.monitor_file()
         self.db_monitor.connect("changed", on_db_file_change)
@@ -113,14 +113,14 @@ class OneWindow(object):
     def __init__(self, get_dialog_class):
         self.dialogs = {}
         self.get_dialog_class = get_dialog_class
-    
+
     def on_dialog_destroy(self, params):
         del self.dialogs[params]
         #self.dialogs[params] = None
 
     def show(self, parent = None, **kwargs):
         params = str(sorted(kwargs.items())) #this is not too safe but will work for most cases
-        
+
         if params in self.dialogs:
             self.dialogs[params].window.present()
         else:
@@ -129,12 +129,12 @@ class OneWindow(object):
                 dialog.window.set_transient_for(parent.get_toplevel())
             else:
                 dialog = self.get_dialog_class()(**kwargs)
-            
+
             # to make things simple, we hope that the target has defined self.window
             dialog.window.connect("destroy",
                                   lambda window, params: self.on_dialog_destroy(params),
                                   params)
-            
+
             self.dialogs[params] = dialog
 
 class Dialogs(Singleton):
@@ -166,31 +166,31 @@ class Dialogs(Singleton):
             return PreferencesEditor
         self.prefs = OneWindow(get_prefs_class)
 
-dialogs = Dialogs()    
+dialogs = Dialogs()
 
 class GconfStore(Singleton):
     """
-    Handles storing to and retrieving values from GConf 
+    Handles storing to and retrieving values from GConf
     """
 
     # GConf directory for deskbar in window mode and shared settings
     GCONF_DIR = "/apps/hamster-applet/general"
-    
+
     # GConf key for global keybinding
     GCONF_KEYBINDING = GCONF_DIR + "/keybinding"
     GCONF_ENABLE_TIMEOUT = GCONF_DIR + "/enable_timeout"
-    GCONF_STOP_ON_SHUTDOWN = GCONF_DIR + "/stop_on_shutdown"  
-    GCONF_NOTIFY_INTERVAL = GCONF_DIR + "/notify_interval" 
+    GCONF_STOP_ON_SHUTDOWN = GCONF_DIR + "/stop_on_shutdown"
+    GCONF_NOTIFY_INTERVAL = GCONF_DIR + "/notify_interval"
     GCONF_NOTIFY_ON_IDLE = GCONF_DIR + "/notify_on_idle"
     GCONF_DAY_START = GCONF_DIR + "/day_start"
 
     __instance = None
-        
+
     def __init__(self):
         super(GconfStore, self).__init__()
         self._client = gconf.client_get_default()
         self.__connect_notifications()
-        
+
     def __connect_notifications(self):
         self._client.add_dir(self.GCONF_DIR, gconf.CLIENT_PRELOAD_RECURSIVE)
         self._client.notify_add(self.GCONF_KEYBINDING, lambda x, y, z, a: runtime.dispatcher.dispatch("gconf_keybinding_changed", z.value.get_string()))
@@ -200,16 +200,16 @@ class GconfStore(Singleton):
         self._client.notify_add(self.GCONF_NOTIFY_ON_IDLE, lambda x, y, z, a: runtime.dispatcher.dispatch("gconf_notify_on_idle_changed", z.value.get_bool()))
         self._client.notify_add(self.GCONF_DAY_START, lambda x, y, z, a: runtime.dispatcher.dispatch("gconf_on_day_start_changed", z.value.get_int()))
 
-    
+
     def get_keybinding(self):
         return self._client.get_string(self.GCONF_KEYBINDING) or ""
-    
+
     def get_timeout_enabled(self):
         return self._client.get_bool(self.GCONF_ENABLE_TIMEOUT) or False
 
     def get_stop_on_shutdown(self):
         return self._client.get_bool(self.GCONF_STOP_ON_SHUTDOWN) or False
-        
+
     def get_notify_interval(self):
     	return self._client.get_int(self.GCONF_NOTIFY_INTERVAL) or 27
 
@@ -220,16 +220,16 @@ class GconfStore(Singleton):
         minutes = self._client.get_int(self.GCONF_DAY_START) or 5*60 + 30
         return dt.time(minutes / 60, minutes % 60)
 
-    #------------------------    
+    #------------------------
     def set_keybinding(self, binding):
         self._client.set_string(self.GCONF_KEYBINDING, binding)
-    
+
     def set_timeout_enabled(self, enabled):
         self._client.set_bool(self.GCONF_ENABLE_TIMEOUT, enabled)
-        
+
     def set_stop_on_shutdown(self, enabled):
         self._client.set_bool(self.GCONF_STOP_ON_SHUTDOWN, enabled)
-    
+
     def set_notify_interval(self, interval):
     	return self._client.set_int(self.GCONF_NOTIFY_INTERVAL, interval)
 
diff --git a/hamster/db.py b/hamster/db.py
index b686f28..d1edd83 100644
--- a/hamster/db.py
+++ b/hamster/db.py
@@ -85,36 +85,36 @@ class Storage(storage.Storage):
 
 
     __setup.complete = False
-    
+
     #tags, here we come!
     def __get_tags(self, autocomplete = None):
         query = "select * from tags"
         if autocomplete:
             query += " where autocomplete='true'"
-        
+
         query += " order by name"
         return self.fetchall(query)
-        
+
     def __get_tag_ids(self, tags):
         """look up tags by their name. create if not found"""
-        
+
         # filter descriptions out, just in case they have wandered in here
         tags = [tag.lower() for tag in tags if tag.startswith("!") == False and len(tag.split(" ")) < 3]
-        
+
         db_tags = self.fetchall("select * from tags where name in (%s)"
                                             % ",".join(["?"] * len(tags)), tags) # bit of magic here - using sqlites bind variables
-        
+
         changes = False
-        
+
         # check if any of tags needs ressurection
         set_complete = [str(tag["id"]) for tag in db_tags if tag["autocomplete"] == "false"]
         if set_complete:
             changes = True
             self.execute("update tags set autocomplete='true' where id in (%s)" % ", ".join(set_complete))
-        
-        
+
+
         found_tags = [tag["name"] for tag in db_tags]
-        
+
         add = set(tags) - set(found_tags)
         if add:
             statement = "insert into tags(name) values(?)"
@@ -131,7 +131,7 @@ class Storage(storage.Storage):
         #first we will create new ones
         tags, changes = self.__get_tag_ids(tags)
         tags = [tag["id"] for tag in tags]
-        
+
         #now we will find which ones are gone from the list
         query = """
                     SELECT b.id as id, count(a.fact_id) as occurences
@@ -149,7 +149,7 @@ class Storage(storage.Storage):
         if to_delete:
             self.execute("delete from tags where id in (%s)" % ", ".join(to_delete))
 
-        if to_uncomplete:        
+        if to_uncomplete:
             self.execute("update tags set autocomplete='false' where id in (%s)" % ", ".join(to_uncomplete))
 
 
@@ -160,10 +160,10 @@ class Storage(storage.Storage):
         # first check if we don't have an activity with same name before us
         activity = self.fetchone("select name from activities where id = ?", (id, ))
         existing_id = self.__get_activity_by_name(activity['name'], category_id)
-        
+
         if id == existing_id: # we are already there, go home
             return False
-        
+
         if existing_id: #ooh, we have something here!
             # first move all facts that belong to movable activity to the new one
             update = """
@@ -171,26 +171,26 @@ class Storage(storage.Storage):
                           SET activity_id = ?
                         WHERE activity_id = ?
             """
-            
+
             self.execute(update, (existing_id, id))
-            
+
             # and now get rid of our friend
             self.__remove_activity(id)
-        
-        else: #just moving        
+
+        else: #just moving
             query = "SELECT max(activity_order) + 1 FROM activities WHERE category_id = ?"
             max_order = self.fetchone(query, (category_id, ))[0] or 1
-            
+
             statement = """
-                       UPDATE activities 
+                       UPDATE activities
                           SET category_id = ?, activity_order = ?
                         WHERE id = ?
             """
-            
+
             self.execute(statement, (category_id, max_order, id))
-        
+
         return True
-    
+
     def __add_category(self, name):
         new_rec = self.fetchone("select max(id) +1, max(category_order) + 1  from categories")
 
@@ -210,50 +210,50 @@ class Storage(storage.Storage):
                            SET name = ?
                          WHERE id = ?
             """
-            self.execute(update, (name, id))        
-        
+            self.execute(update, (name, id))
+
     def __move_activity(self, source_id, target_order, insert_after = True):
         statement = "UPDATE activities SET activity_order = activity_order + 1"
-        
+
         if insert_after:
             statement += " WHERE activity_order > ?"
         else:
             statement += " WHERE activity_order >= ?"
 
         self.execute(statement, (target_order, ))
-        
+
         statement = "UPDATE activities SET activity_order = ? WHERE id = ?"
-        
+
         if insert_after:
             self.execute(statement, (target_order + 1, source_id))
         else:
             self.execute(statement, (target_order, source_id))
-            
-        
-        
+
+
+
     def __get_activity_by_name(self, name, category_id = None):
         """get most recent, preferably not deleted activity by it's name"""
-        
+
         if category_id:
             query = """
-                       SELECT id, deleted from activities 
+                       SELECT id, deleted from activities
                         WHERE lower(name) = lower(?)
                           AND category_id = ?
                      ORDER BY deleted, id desc
                         LIMIT 1
             """
-            
+
             res = self.fetchone(query, (name, category_id))
         else:
             query = """
-                       SELECT id, deleted from activities 
+                       SELECT id, deleted from activities
                         WHERE lower(name) = lower(?)
                      ORDER BY deleted, id desc
                         LIMIT 1
             """
 
             res = self.fetchone(query, (name, ))
-        
+
         if res:
             # if the activity was marked as deleted, ressurect on first call
             # and put in the unsorted category
@@ -264,13 +264,13 @@ class Storage(storage.Storage):
                              WHERE id = ?
                         """
                 self.execute(update, (res['id'], ))
-            
+
             return res['id']
-        
+
         return None
 
     def __get_category_by_name(self, name):
-        """returns category by it's name"""        
+        """returns category by it's name"""
 
         query = """
                    SELECT id from categories
@@ -278,12 +278,12 @@ class Storage(storage.Storage):
                  ORDER BY id desc
                     LIMIT 1
         """
-            
+
         res = self.fetchone(query, (name, ))
-        
+
         if res:
             return res['id']
-        
+
         return None
 
     def __get_fact(self, id):
@@ -309,11 +309,11 @@ class Storage(storage.Storage):
     def __group_tags(self, facts):
         """put the fact back together and move all the unique tags to an array"""
         if not facts: return facts  #be it None or whatever
-        
+
         grouped_facts = []
         for fact_id, fact_tags in itertools.groupby(facts, lambda f: f["id"]):
             fact_tags = list(fact_tags)
-            
+
             # first one is as good as the last one
             grouped_fact = fact_tags[0]
 
@@ -322,7 +322,7 @@ class Storage(storage.Storage):
             keys = ["id", "start_time", "end_time", "description", "name",
                     "activity_id", "category", "tag"]
             grouped_fact = dict([(key, grouped_fact[key]) for key in keys])
-            
+
             grouped_fact["tags"] = [ft["tag"] for ft in fact_tags if ft["tag"]]
             grouped_facts.append(grouped_fact)
         return grouped_facts
@@ -334,7 +334,7 @@ class Storage(storage.Storage):
         today = (dt.datetime.now() - dt.timedelta(hours = day_start.hour,
                                                   minutes = day_start.minute)).date()
         facts = self.__get_facts(today)
-        
+
         last_activity = None
         if facts and facts[-1]["end_time"] == None:
             last_activity = facts[-1]
@@ -375,14 +375,14 @@ class Storage(storage.Storage):
                                      start_time,
                                      start_time + dt.timedelta(seconds = 60 * 60 * 12)))
 
-        end_time = None        
+        end_time = None
 
         if fact:
             if fact["end_time"] and start_time > fact["start_time"]:
                 #we are in middle of a fact - truncate it to our start
                 self.execute("UPDATE facts SET end_time=? WHERE id=?",
                              (start_time, fact["id"]))
-                
+
                 # hamster is second-aware, but the edit dialog naturally is not
                 # so when an ongoing task is being edited, the seconds get truncated
                 # and the start time will be before previous task's end time.
@@ -393,7 +393,7 @@ class Storage(storage.Storage):
                 end_time = fact["start_time"]
 
         return end_time
-        
+
     def __solve_overlaps(self, start_time, end_time):
         """finds facts that happen in given interval and shifts them to
         make room for new fact"""
@@ -401,7 +401,7 @@ class Storage(storage.Storage):
         # this function is destructive - can't go with a wildcard
         if not end_time or not start_time:
             return
-        
+
         # activities that we are overlapping.
         # second OR clause is for elimination - |new fact--|---old-fact--|--new fact|
         query = """
@@ -411,19 +411,19 @@ class Storage(storage.Storage):
                 LEFT JOIN categories c on b.category_id = c.id
                     WHERE ((start_time < ? and end_time > ?)
                            OR (start_time < ? and end_time > ?))
-                           
+
                        OR ((start_time < ? and start_time > ?)
                            OR (end_time < ? and end_time > ?))
                  ORDER BY start_time
                 """
         conflicts = self.fetchall(query, (start_time, start_time, end_time, end_time,
                                           end_time, start_time, end_time, start_time))
-        
+
         for fact in conflicts:
             # split - truncate until beginning of new entry and create new activity for end
             if fact["start_time"] < start_time < fact["end_time"] and \
                fact["start_time"] < end_time < fact["end_time"]:
-                
+
                 logging.info("splitting %s" % fact["name"])
                 self.execute("""UPDATE facts
                                    SET end_time = ?
@@ -447,13 +447,13 @@ class Storage(storage.Storage):
                  start_time < fact["end_time"] < end_time:
                 logging.info("eliminating %s" % fact["name"])
                 self.__remove_fact(fact["id"])
-            
+
             # overlap start
             elif start_time < fact["start_time"] < end_time:
                 logging.info("Overlapping start of %s" % fact["name"])
                 self.execute("UPDATE facts SET start_time=? WHERE id=?",
                              (end_time, fact["id"]))
-            
+
             # overlap end
             elif start_time < fact["end_time"] < end_time:
                 logging.info("Overlapping end of %s" % fact["name"])
@@ -463,40 +463,40 @@ class Storage(storage.Storage):
 
     def __add_fact(self, activity_name, tags, start_time = None,
                      end_time = None, category_name = None, description = None):
-        
+
         activity = stuff.parse_activity_input(activity_name)
-        
+
         tags = [tag.strip() for tag in tags.split(",") if tag.strip()]  # split by comma
         descriptions = [tag for tag in tags if len(tag.split(" ")) > 2 or tag.startswith("!")]  #extract description
         tags = list(set(tags) - set(descriptions)) #remove any found descriptions from tag list
-        
+
         # TODO - untangle descriptions - allow just one place where to enter them
         activity.description = ", ".join(descriptions) # somebody will file bug on "why tags can't be seven words"
         tags = self.get_tag_ids(tags) #this will create any missing tags too
-        
+
         if category_name:
             activity.category_name = category_name
         if description:
             activity.description = description #override
-        
+
         start_time = activity.start_time or start_time or datetime.datetime.now()
-        
+
         if start_time > datetime.datetime.now():
             return None #no facts in future, please
-        
+
         start_time = start_time.replace(microsecond = 0)
         end_time = activity.end_time or end_time
         if end_time:
             end_time = end_time.replace(microsecond = 0)
 
-            
+
         # now check if maybe there is also a category
         category_id = None
         if activity.category_name:
             category_id = self.__get_category_by_name(activity.category_name)
             if not category_id:
                 category_id = self.__add_category(activity.category_name)
-        
+
         # try to find activity
         activity_id = self.__get_activity_by_name(activity.activity_name,
                                                   category_id)
@@ -506,7 +506,7 @@ class Storage(storage.Storage):
 
 
         # if we are working on +/- current day - check the last_activity
-        
+
         if (dt.datetime.now() - start_time <= dt.timedelta(days=1)):
             previous = self.__get_last_activity()
 
@@ -516,7 +516,7 @@ class Storage(storage.Storage):
                    and previous["tags"] == sorted([tag["name"] for tag in tags]) \
                    and previous["description"] == (description or ""):
                     return previous
-                
+
                 # otherwise, if not tags nor description is added (extra data
                 # see if maybe it is too short to qualify as an activity
                 if not previous["tags"] and not previous["description"] \
@@ -524,7 +524,7 @@ class Storage(storage.Storage):
                     self.__remove_fact(previous['id'])
                     start_time = previous['start_time']
                 else:
-                    # otherwise stop 
+                    # otherwise stop
                     update = """
                                UPDATE facts
                                   SET end_time = ?
@@ -548,12 +548,12 @@ class Storage(storage.Storage):
         self.execute(insert, (activity_id, start_time, end_time, activity.description))
 
         fact_id = self.fetchone("select max(id) as max_id from facts")['max_id']
-        
+
         #now link tags
         insert = ["insert into fact_tags(fact_id, tag_id) values(?, ?)"] * len(tags)
         params = [(fact_id, tag["id"]) for tag in tags]
         self.execute(insert, params)
-        
+
         return self.__get_fact(fact_id)
 
 
@@ -578,7 +578,7 @@ class Storage(storage.Storage):
         # we will be looking in activity names, descriptions, categories and tags
         # comma will be treated as OR
         # space will be treated as AND or possible join
-        
+
 
         # split by comma and then by space and remove all extra spaces
         or_bits = [[term.strip().lower().replace("'", "''") #striping removing case sensitivity and escaping quotes in term
@@ -590,10 +590,10 @@ class Storage(storage.Storage):
                        or lower(b.name) = '%(term)s'
                        or lower(c.name) = '%(term)s'
                        or lower(e.name) = '%(term)s' )""" % dict(term = term)
-        
+
         if or_bits:
             search_query = "1<>1 " # will be building OR chain, so start with a false
-            
+
             for and_bits in or_bits:
                 if len(and_bits) == 1:
                     and_query = all_fields(and_bits[0])
@@ -605,30 +605,30 @@ class Storage(storage.Storage):
                         and_query += "and (%s and %s) or %s" % (all_fields(bit1),
                                                                 all_fields(bit2),
                                                                 all_fields("%s %s" % (bit1, bit2)))
-                
+
                 search_query = "%s or (%s) " % (search_query, and_query)
-    
+
             query = "%s and (%s)" % (query, search_query)
-        
 
-        
+
+
         query += " ORDER BY a.start_time, e.name"
         end_date = end_date or date
 
         from configuration import GconfStore
         day_start = GconfStore().get_day_start()
-        
+
         split_time = day_start
         datetime_from = dt.datetime.combine(date, split_time)
         datetime_to = dt.datetime.combine(end_date, split_time) + dt.timedelta(days = 1)
-        
+
         facts = self.fetchall(query, (_("Unsorted"),
                                       datetime_from,
                                       datetime_to))
-        
+
         #first let's put all tags in an array
         facts = self.__group_tags(facts)
-        
+
         res = []
         for fact in facts:
             # heuristics to assign tasks to proper days
@@ -701,15 +701,15 @@ class Storage(storage.Storage):
                         WHERE category_id = ?
                           AND deleted is null
             """
-            
+
             # unsorted entries we sort by name - others by ID
             if category_id == -1:
                 query += "ORDER BY lower(a.name)"
             else:
                 query += "ORDER BY a.activity_order"
-                
+
             activities = self.fetchall(query, (category_id, ))
-            
+
         else:
             query = """
                        SELECT a.*, b.name as category
@@ -719,7 +719,7 @@ class Storage(storage.Storage):
                      ORDER BY lower(a.name)
             """
             activities = self.fetchall(query)
-            
+
         return activities
 
     def __get_autocomplete_activities(self):
@@ -734,17 +734,17 @@ class Storage(storage.Storage):
                  ORDER BY lower(a.name)
         """
         activities = self.fetchall(query)
-        
+
         return activities
 
     def __remove_activity(self, id):
         """ check if we have any facts with this activity and behave accordingly
             if there are facts - sets activity to deleted = True
             else, just remove it"""
-        
+
         query = "select count(*) as count from facts where activity_id = ?"
         bound_facts = self.fetchone(query, (id,))['count']
-        
+
         if bound_facts > 0:
             self.execute("UPDATE activities SET deleted = 1 WHERE id = ?", (id,))
         else:
@@ -752,13 +752,13 @@ class Storage(storage.Storage):
 
     def __remove_category(self, id):
         """move all activities to unsorted and remove category"""
-        
+
         update = "update activities set category_id = -1 where category_id = ?"
         self.execute(update, (id, ))
-        
+
         self.execute("delete from categories where id = ?", (id, ))
-        
-    
+
+
     def __swap_activities(self, id1, priority1, id2, priority2):
         """ swaps nearby activities """
         # TODO - 2 selects and 2 updates is wrong we could live without selects
@@ -771,7 +771,7 @@ class Storage(storage.Storage):
         activity_id = self.__get_activity_by_name(name, category_id)
         if activity_id:
             return activity_id
-        
+
         #now do the create bit
         category_id = category_id or -1
         new_rec = self.fetchone("select max(id) + 1 , max(activity_order) + 1  from activities")
@@ -841,57 +841,57 @@ class Storage(storage.Storage):
 
         con = self.__con or self.connection
         cur = self.__cur or con.cursor()
-        
+
         if isinstance(statement, list) == False: #we kind of think that we will get list of instructions
             statement = [statement]
             params = [params]
-            
+
         if isinstance(statement, list):
             for i in range(len(statement)):
                 logging.debug("%s %s" % (statement[i], params[i]))
-         
+
                 res = cur.execute(statement[i], params[i])
 
         if not self.__con:
             con.commit()
             cur.close()
             runtime.register_modification()
-        
-        
+
+
     def start_transaction(self):
         # will give some hints to execute not to close or commit anything
         self.__con = self.connection
         self.__cur = self.__con.cursor()
-    
+
     def end_transaction(self):
         self.__con.commit()
         self.__cur.close()
         self.__con = None
         from configuration import runtime
         runtime.register_modification()
-        
+
     def run_fixtures(self):
         self.start_transaction()
-        
+
         # defaults
         work_category = {"name": _("Work"),
                          "entries": [_("Reading news"),
                                      _("Checking stocks"),
                                      _("Super secret project X"),
                                      _("World domination")]}
-        
+
         nonwork_category = {"name": _("Day-to-day"),
                             "entries": [_("Lunch"),
                                         _("Watering flowers"),
                                         _("Doing handstands")]}
-        
+
         """upgrade DB to hamster version"""
         version = self.fetchone("SELECT version FROM version")["version"]
         current_version = 6
 
         if version < 2:
             """moving from fact_date, fact_time to start_time, end_time"""
-    
+
             self.execute("""
                                CREATE TABLE facts_new
                                             (id integer primary key,
@@ -899,7 +899,7 @@ class Storage(storage.Storage):
                                              start_time varchar2(12),
                                              end_time varchar2(12))
             """)
-    
+
             self.execute("""
                                INSERT INTO facts_new
                                            (id, activity_id, start_time)
@@ -921,7 +921,7 @@ class Storage(storage.Storage):
                                       ORDER BY start_time
             """)
             prev_fact = None
-    
+
             for fact in facts:
                 if prev_fact:
                     if prev_fact['start_date'] == fact['start_date']:
@@ -930,7 +930,7 @@ class Storage(storage.Storage):
                     else:
                         #otherwise that's the last entry of the day - remove it
                         self.execute("DELETE FROM facts WHERE id = ?", (prev_fact["id"],))
-                
+
                 prev_fact = fact
 
         #it was kind of silly not to have datetimes in first place
@@ -942,7 +942,7 @@ class Storage(storage.Storage):
                                              start_time timestamp,
                                              end_time timestamp)
             """)
-    
+
             self.execute("""
                                INSERT INTO facts_new
                                            (id, activity_id, start_time, end_time)
@@ -989,22 +989,22 @@ class Storage(storage.Storage):
                                       FROM activities
                                      WHERE deleted is null and work=1;
                """)['work_activities']
-            
+
             if work_activities > 0:
                 self.execute("""
                                INSERT INTO categories
                                            (id, name, category_order)
                                     VALUES (2, ?, 1);
                   """, (work_category["name"],))
-            
+
             # now add category field to activities, before starting the move
             self.execute("""   ALTER TABLE activities
                                 ADD COLUMN category_id integer;
                """)
-            
-            
+
+
             # starting the move
-            
+
             # first remove all deleted activities with no instances in facts
             self.execute("""
                                DELETE FROM activities
@@ -1012,25 +1012,25 @@ class Storage(storage.Storage):
                                        AND id not in(select activity_id from facts);
              """)
 
-            
+
             # moving work / non-work to appropriate categories
             # exploit false/true = 0/1 thing
             self.execute("""       UPDATE activities
                                       SET category_id = work + 1
                                     WHERE deleted is null
                """)
-            
-            #finally, set category to -1 where there is none            
+
+            #finally, set category to -1 where there is none
             self.execute("""       UPDATE activities
                                       SET category_id = -1
                                     WHERE category_id is null
                """)
-            
+
             # drop work column and forget value of deleted
             # previously deleted records are now unsorted ones
             # user will be able to mark them as deleted again, in which case
             # they won't appear in autocomplete, or in categories
-            # ressurection happens, when user enters the exact same name            
+            # ressurection happens, when user enters the exact same name
             self.execute("""
                                CREATE TABLE activities_new (id integer primary key,
                                                             name varchar2(500),
@@ -1038,7 +1038,7 @@ class Storage(storage.Storage):
                                                             deleted integer,
                                                             category_id integer);
             """)
-    
+
             self.execute("""
                                INSERT INTO activities_new
                                            (id, name, activity_order, category_id)
@@ -1048,7 +1048,7 @@ class Storage(storage.Storage):
 
             self.execute("DROP TABLE activities")
             self.execute("ALTER TABLE activities_new RENAME TO activities")
-        
+
         if version < 5:
             self.execute("ALTER TABLE facts add column description varchar2")
 
@@ -1067,21 +1067,21 @@ class Storage(storage.Storage):
             self.execute("CREATE INDEX idx_fact_tags_fact ON fact_tags(fact_id)")
             self.execute("CREATE INDEX idx_fact_tags_tag ON fact_tags(tag_id)")
 
-        # at the happy end, update version number 
+        # at the happy end, update version number
         if version < current_version:
             #lock down current version
-            self.execute("UPDATE version SET version = %d" % current_version) 
-        
+            self.execute("UPDATE version SET version = %d" % current_version)
+
         """we start with an empty database and then populate with default
            values. This way defaults can be localized!"""
-        
+
         category_count = self.fetchone("select count(*) from categories")[0]
-        
+
         if category_count == 0:
             work_cat_id = self.__add_category(work_category["name"])
             for entry in work_category["entries"]:
                 self.__add_activity(entry, work_cat_id)
-        
+
             nonwork_cat_id = self.__add_category(nonwork_category["name"])
             for entry in nonwork_category["entries"]:
                 self.__add_activity(entry, nonwork_cat_id)
diff --git a/hamster/edit_activity.py b/hamster/edit_activity.py
index ab3f799..bd361c7 100644
--- a/hamster/edit_activity.py
+++ b/hamster/edit_activity.py
@@ -36,31 +36,31 @@ class CustomFactController:
 
         self.parent, self.fact_id = parent, fact_id
         start_date, end_date = None, None
-        
+
         #TODO - should somehow hint that time is not welcome here
         self.new_name = widgets.ActivityEntry()
         self.get_widget("activity_box").add(self.new_name)
-        
+
         self.new_tags = widgets.TagsEntry()
         self.get_widget("tags_box").add(self.new_tags)
-        
+
         if fact_id:
             fact = runtime.storage.get_fact(fact_id)
 
             label = fact['name']
             if fact['category'] != _("Unsorted"):
                 label += "@%s" %  fact['category']
-                
+
             self.new_name.set_text(label)
-            
+
             if fact['description']:
                 fact['tags'].append(fact['description'])  #same edit field
             self.new_tags.set_text(", ".join(fact['tags']))
-            
-            
+
+
             start_date = fact["start_time"]
             end_date = fact["end_time"]
-            
+
             self.get_widget("save_button").set_label("gtk-save")
             self.window.set_title(_("Update activity"))
 
@@ -99,7 +99,7 @@ class CustomFactController:
 
         self.start_time = widgets.TimeInput(start_date)
         self.get_widget("start_time_placeholder").add(self.start_time)
-        
+
         self.end_time = widgets.TimeInput(end_date, start_date)
         self.get_widget("end_time_placeholder").add(self.end_time)
         self.set_end_date_label(end_date)
@@ -117,7 +117,7 @@ class CustomFactController:
         self.new_name.connect("changed", self.on_new_name_changed)
         self.end_time.connect("time-entered", self.on_end_time_entered)
         self._gui.connect_signals(self)
-        
+
         self.window.show_all()
 
     def update_time(self, start_time, end_time):
@@ -126,7 +126,7 @@ class CustomFactController:
         self.end_time.set_time(end_time)
         self.set_end_date_label(end_time)
 
-        
+
     def draw_preview(self, date, highlight = None):
         day_facts = runtime.storage.get_facts(date)
         self.dayline.draw(day_facts, highlight)
@@ -153,20 +153,20 @@ class CustomFactController:
             time, date = end_time, end_date
         else:
             time, date = start_time, start_date
-        
+
         if time and date:
             return dt.datetime.combine(date, time.time())
         else:
             return None
-    
+
     def on_save_button_clicked(self, button):
         activity = self.new_name.get_text().decode("utf-8")
-        
+
         if not activity:
             return False
 
         tags = self.new_tags.get_text().decode('utf8', 'replace')
-        
+
         start_time = self._get_datetime("start")
 
         if self.get_widget("in_progress").get_active():
@@ -182,17 +182,17 @@ class CustomFactController:
 
 
         # hide panel only on add - on update user will want to see changes
-        if not self.fact_id: 
+        if not self.fact_id:
             runtime.dispatcher.dispatch('panel_visible', False)
-        
+
         self.close_window()
-    
+
     def on_activity_list_key_pressed(self, entry, event):
         #treating tab as keydown to be able to cycle through available values
         if event.keyval == gtk.keysyms.Tab:
             event.keyval = gtk.keysyms.Down
         return False
-        
+
     def on_in_progress_toggled(self, check):
         sensitive = not check.get_active()
         self.end_time.set_sensitive(sensitive)
@@ -203,7 +203,7 @@ class CustomFactController:
 
     def on_cancel_clicked(self, button):
         self.close_window()
-        
+
     def on_new_name_changed(self, combo):
         self.validate_fields()
 
@@ -219,13 +219,13 @@ class CustomFactController:
         self.end_time.set_start_time(start_time)
         self.validate_fields()
         self.end_time.grab_focus()
-        
+
     def on_end_time_entered(self, widget):
         self.validate_fields()
-    
+
     def set_end_date_label(self, some_date):
         self.get_widget("end_date_label").set_text(some_date.strftime("%x"))
-    
+
     def validate_fields(self, widget = None):
         activity_text = self.new_name.get_text().decode('utf8', 'replace')
         start_time = self._get_datetime("start")
@@ -236,8 +236,8 @@ class CustomFactController:
             # make sure we are within 24 hours of start time
             end_time -= dt.timedelta(days=(end_time - start_time).days)
 
-    
-            self.draw_preview(start_time.date(), [start_time, end_time])    
+
+            self.draw_preview(start_time.date(), [start_time, end_time])
         else:
             self.draw_preview(dt.datetime.today().date(), [dt.datetime.now(),
                                                            dt.datetime.now()])
@@ -252,9 +252,9 @@ class CustomFactController:
 
     def on_window_key_pressed(self, tree, event_key):
         if (event_key.keyval == gtk.keysyms.Escape
-          or (event_key.keyval == gtk.keysyms.w 
+          or (event_key.keyval == gtk.keysyms.w
               and event_key.state & gtk.gdk.CONTROL_MASK)):
-            
+
             if self.start_date.popup.get_property("visible") or \
                self.start_time.popup.get_property("visible") or \
                self.end_time.popup.get_property("visible") or \
@@ -262,10 +262,10 @@ class CustomFactController:
                self.new_tags.popup.get_property("visible"):
                 return False
 
-            self.close_window()            
+            self.close_window()
 
     def on_close(self, widget, event):
-        self.close_window()        
+        self.close_window()
 
     def close_window(self):
         self.window.destroy()
diff --git a/hamster/eds.py b/hamster/eds.py
index 4a51abe..dc04015 100644
--- a/hamster/eds.py
+++ b/hamster/eds.py
@@ -31,7 +31,7 @@ except:
 def get_eds_tasks():
     if EDS_AVAILABLE == False:
         return []
-    
+
     try:
         sources = ecal.list_task_sources()
         tasks = []
diff --git a/hamster/graphics.py b/hamster/graphics.py
index 0186800..46bd545 100644
--- a/hamster/graphics.py
+++ b/hamster/graphics.py
@@ -44,7 +44,7 @@ class Colors(object):
                 color = [c / 255.0 for c in color]
 
         return color
-    
+
     @staticmethod
     def rgb(color):
         return [c * 255 for c in Colors.color(color)]
@@ -80,12 +80,12 @@ class Area(gtk.DrawingArea):
         self.context, self.layout = None, None
         self.width, self.height = None, None
         self.__prev_mouse_regions = None
-        
+
         self.tweener = pytweener.Tweener(0.4, pytweener.Easing.Cubic.easeInOut)
         self.framerate = 80
         self.last_frame_time = None
         self.__animating = False
-        
+
         self.mouse_drag = (None, None)
 
     def on_expose(self):
@@ -99,15 +99,15 @@ class Area(gtk.DrawingArea):
             self.__animating = True
             self.last_frame_time = dt.datetime.now()
             gobject.timeout_add(1000 / self.framerate, self.__interpolate)
-            
+
     """ animation bits """
     def __interpolate(self):
         self.__animating = self.tweener.hasTweens()
 
         if not self.window: #will wait until window comes
             return self.__animating
-        
-        
+
+
         time_since_start = (dt.datetime.now() - self.last_frame_time).microseconds / 1000000.0
         self.tweener.update(time_since_start)
 
@@ -122,10 +122,10 @@ class Area(gtk.DrawingArea):
         if easing: params["tweenType"] = easing    # if none will fallback to tweener default
         if callback: params["onCompleteFunction"] = callback
         self.tweener.addTween(object, **params)
-        
+
         if instant:
             self.redraw_canvas()
-    
+
 
     """ drawing on canvas bits """
     def draw_rect(self, x, y, w, h, corner_radius = 0):
@@ -139,7 +139,7 @@ class Area(gtk.DrawingArea):
         x2, y2 = x + w, y + h
 
         half_corner = corner_radius / 2
-        
+
         self.context.move_to(x + corner_radius, y);
         self.context.line_to(x2 - corner_radius, y);
         # top-right
@@ -170,7 +170,7 @@ class Area(gtk.DrawingArea):
         if color:
             self.set_color(color, opacity)
         self.context.rectangle(x, y, w, h)
-    
+
     def fill_area(self, x, y, w, h, color, opacity = 0):
         self.rectangle(x, y, w, h, color, opacity)
         self.context.fill()
@@ -179,7 +179,7 @@ class Area(gtk.DrawingArea):
         # sets text and returns width and height of the layout
         self.layout.set_text(text)
         return self.layout.get_pixel_size()
-        
+
     def set_color(self, color, opacity = None):
         color = Colors.color(color) #parse whatever we have there into a normalized triplet
 
@@ -212,7 +212,7 @@ class Area(gtk.DrawingArea):
         self.layout.set_font_description(default_font)
         alloc = self.get_allocation()  #x, y, width, height
         self.width, self.height = alloc.width, alloc.height
-        
+
         self.mouse_regions = [] #reset since these can move in each redraw
         self.on_expose()
 
@@ -225,7 +225,7 @@ class Area(gtk.DrawingArea):
             x = event.x
             y = event.y
             state = event.state
-        
+
         self.emit("mouse-move", (x, y), state)
 
         if not self.mouse_regions:
@@ -235,7 +235,7 @@ class Area(gtk.DrawingArea):
         for region in self.mouse_regions:
             if region[0] < x < region[2] and region[1] < y < region[3]:
                 mouse_regions.append(region[4])
-        
+
         if mouse_regions:
             area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
         else:
@@ -272,7 +272,7 @@ class Area(gtk.DrawingArea):
         x = event.x
         y = event.y
         state = event.state
-        
+
         drag_distance = 5
         if self.mouse_drag and (self.mouse_drag[0] - x) ** 2 + (self.mouse_drag[1] - y) ** 2 < drag_distance ** 2:
             #if the drag is less than the drag distance, then we have a click
@@ -281,7 +281,7 @@ class Area(gtk.DrawingArea):
 
         if not self.mouse_regions:
             return
-        
+
         mouse_regions = []
         for region in self.mouse_regions:
             if region[0] < x < region[2] and region[1] < y < region[3]:
@@ -299,31 +299,31 @@ class SampleArea(Area):
         self.rect_width, self.rect_height = 90, 90
 
         self.text_y = -100
-        
-        
+
+
     def on_expose(self):
         # on expose is called when we are ready to draw
-        
+
         # fill_area is just a shortcut function
         # feel free to use self.context. move_to, line_to and others
         self.font_size = 32
         self.layout.set_text("Hello, World!")
-        
+
         self.draw_rect(round(self.rect_x),
                        round(self.rect_y),
                        self.rect_width,
                        self.rect_height,
                        10)
-        
+
         self.set_color("#ff00ff")
         self.context.fill()
 
         self.context.move_to((self.width - self.layout.get_pixel_size()[0]) / 2,
                              self.text_y)
-        
+
         self.set_color("#333")
         self.context.show_layout(self.layout)
-        
+
 
 class BasicWindow:
     def __init__(self):
@@ -331,20 +331,20 @@ class BasicWindow:
         window.set_title("Graphics Module")
         window.set_size_request(300, 300)
         window.connect("delete_event", lambda *args: gtk.main_quit())
-    
+
         self.graphic = SampleArea()
-        
+
         box = gtk.VBox()
         box.pack_start(self.graphic)
-        
+
         button = gtk.Button("Hello")
         button.connect("clicked", self.on_go_clicked)
 
         box.add_with_properties(button, "expand", False)
-    
+
         window.add(box)
         window.show_all()
-        
+
         # drop the hello on init
         self.graphic.animate(self.graphic,
                             dict(text_y = 120),
@@ -354,13 +354,13 @@ class BasicWindow:
 
     def on_go_clicked(self, widget):
         import random
-        
+
         # set x and y to random position within the drawing area
         x = round(min(random.random() * self.graphic.width,
                       self.graphic.width - self.graphic.rect_width))
         y = round(min(random.random() * self.graphic.height,
                       self.graphic.height - self.graphic.rect_height))
-        
+
         # here we call the animate function with parameters we would like to change
         # the easing functions outside graphics module can be accessed via
         # graphics.Easing
@@ -373,4 +373,3 @@ class BasicWindow:
 if __name__ == "__main__":
    example = BasicWindow()
    gtk.main()
-    
\ No newline at end of file
diff --git a/hamster/hamster-applet.py b/hamster/hamster-applet.py
index d44231d..59194fb 100755
--- a/hamster/hamster-applet.py
+++ b/hamster/hamster-applet.py
@@ -32,7 +32,7 @@ def applet_factory(applet, iid):
     applet.connect("destroy", on_destroy)
     applet.set_applet_flags(gnomeapplet.EXPAND_MINOR)
 
-    from hamster.applet import HamsterApplet    
+    from hamster.applet import HamsterApplet
     hamster_applet = HamsterApplet(applet)
 
     applet.show_all()
@@ -43,13 +43,13 @@ def applet_factory(applet, iid):
 def on_destroy(event):
     from hamster.configuration import GconfStore, runtime
     config = GconfStore()
-    
+
     # handle config option to stop tracking on shutdown
     if config.get_stop_on_shutdown():
         last_activity = runtime.storage.get_last_activity()
         if last_activity and last_activity['end_time'] is None:
             runtime.storage.touch_fact(last_activity)
-        
+
     if gtk.main_level():
         gtk.main_quit()
 
@@ -69,7 +69,7 @@ if __name__ == "__main__":
                       dest="debug",
                       default=False,
                       help="set log level to debug")
-    
+
     #these two come from bonobo
     parser.add_option("--oaf-activate-iid")
     parser.add_option("--oaf-ior-fd")
@@ -96,22 +96,22 @@ if __name__ == "__main__":
             logging.info("Running from source folder, modifying PYTHONPATH")
             sys.path.insert(0, os.path.join(name, "hamster", "keybinder", ".libs"))
             sys.path.insert(0, name)
-        
+
         # Now the path is set, import our applet
         from hamster import defs
         from hamster.configuration import runtime, dialogs
-        
+
         # Setup i18n
-        locale_dir = os.path.abspath(os.path.join(defs.DATA_DIR, "locale"))        
+        locale_dir = os.path.abspath(os.path.join(defs.DATA_DIR, "locale"))
         for module in (gettext, locale):
             module.bindtextdomain('hamster-applet', locale_dir)
             module.textdomain('hamster-applet')
-        
+
             if hasattr(module, 'bind_textdomain_codeset'):
                 module.bind_textdomain_codeset('hamster-applet','UTF-8')
-        
+
         gtk.window_set_default_icon_name("hamster-applet")
-    
+
         if options.start_window or options.standalone:
             gobject.set_application_name("hamster-applet")
             if (options.start_window or "").startswith("over"):
@@ -127,16 +127,16 @@ if __name__ == "__main__":
 
             else: #default to main applet
                 gnome.init(defs.PACKAGE, defs.VERSION)
-        
+
                 app = gtk.Window(gtk.WINDOW_TOPLEVEL)
                 app.set_title(_(u"Time Tracker"))
-            
+
                 applet = gnomeapplet.Applet()
                 applet_factory(applet, None)
                 applet.reparent(app)
                 app.show_all()
 
-            gtk.main()    
+            gtk.main()
         else:
             gnomeapplet.bonobo_factory(
                 "OAFIID:Hamster_Applet_Factory",
diff --git a/hamster/hamsterdbus.py b/hamster/hamsterdbus.py
index eed86a8..26c8f29 100644
--- a/hamster/hamsterdbus.py
+++ b/hamster/hamsterdbus.py
@@ -48,7 +48,7 @@ class HamsterDbusController(dbus.service.Object):
 
     @staticmethod
     def to_dbus_fact(fact):
-        """Perform the conversion between fact database query and 
+        """Perform the conversion between fact database query and
         dbus supported data types
         """
         if not fact:
@@ -57,17 +57,17 @@ class HamsterDbusController(dbus.service.Object):
         fact = dict(fact)
         for key in fact.keys():
             fact[key] = fact[key] or 0
-            
+
             # make sure we return correct type where strings are expected
             if not fact[key] and key in ('name', 'category', 'description'):
                 fact[key] = ''
-                
+
             # convert times to gmtime
             if isinstance(fact[key], datetime.datetime):
                 fact[key] = timegm(fact[key].timetuple())
-                
+
         return fact
-    
+
 
     @dbus.service.method(HAMSTER_URI, out_signature='a{sv}')
     def GetCurrentFact(self):
@@ -169,10 +169,10 @@ class HamsterDbusController(dbus.service.Object):
         Parameters:
         s activity: Activity name with optional category and/or description
                     in the form 'activity_name[ category_name][,description]'
-                    Activity and matching category will be refered or created 
+                    Activity and matching category will be refered or created
                     on the fly.
         u start_time: Seconds since epoch (timestamp). Use 0 for 'now'
-        u end_time: Seconds since epoch (timestamp). 
+        u end_time: Seconds since epoch (timestamp).
                     Use 0 for 'in progress task'
         """
         #TODO: Assert start > end ?
diff --git a/hamster/idle.py b/hamster/idle.py
index 0808731..1fbeefd 100644
--- a/hamster/idle.py
+++ b/hamster/idle.py
@@ -84,7 +84,7 @@ class DbusIdleListener(object):
             idle_state = message.get_args_list()[0]
             if idle_state:
                 self.idle_from = dt.datetime.now()
-                
+
                 # from gnome screensaver 2.24 to 2.28 they have switched
                 # configuration keys and signal types.
                 # luckily we can determine key by signal type
@@ -121,9 +121,9 @@ class DbusIdleListener(object):
             # ActiveChanged and SessionIdle signals
             logging.debug("Screen Lock Requested")
             self.screen_locked = True
-        
+
         return
-    
+
 
     def getIdleFrom(self):
         if not self.idle_from:
diff --git a/hamster/preferences.py b/hamster/preferences.py
index 3fcca83..d234ba1 100755
--- a/hamster/preferences.py
+++ b/hamster/preferences.py
@@ -51,7 +51,7 @@ class CategoryStore(gtk.ListStore):
             self.append([category['id'],
                          category['name'],
                          category['category_order']])
-        
+
         self.unsorted_category = self.append([-1, _("Unsorted"), 999]) # all activities without category
 
 
@@ -63,12 +63,12 @@ class ActivityStore(gtk.ListStore):
     def load(self, category_id):
         """ Loads activity list from database, ordered by
             activity_order """
-            
+
         self.clear()
 
         if category_id is None:
             return
-        
+
         activity_list = runtime.storage.get_activities(category_id)
 
         for activity in activity_list:
@@ -90,8 +90,8 @@ class PreferencesEditor:
         ('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0),
         ('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_APP, 0),
         ]
-    
-    
+
+
     def __init__(self, parent = None):
         self.parent = parent
         self._gui = stuff.load_ui_file("preferences.ui")
@@ -169,10 +169,10 @@ class PreferencesEditor:
         #select first category
         selection = self.category_tree.get_selection()
         selection.select_path((0,))
-        
+
         self.prev_selected_activity = None
         self.prev_selected_category = None
-        
+
         # disable notification thing if pynotify is not available
         try:
             import pynotify
@@ -190,10 +190,10 @@ class PreferencesEditor:
         self.get_widget("notify_on_idle").set_active(self.config.get_notify_on_idle())
 
         self.day_start.set_time(self.config.get_day_start())
-        
+
         self.tags = [tag["name"] for tag in runtime.storage.get_tags(autocomplete=True)]
         self.get_widget("autocomplete_tags").set_text(", ".join(self.tags))
-            
+
 
     def on_autocomplete_tags_view_focus_out_event(self, view, event):
         buf = self.get_widget("autocomplete_tags")
@@ -202,10 +202,10 @@ class PreferencesEditor:
 
         if updated_tags == self.tags:
             return
-        
+
         runtime.storage.update_autocomplete_tags(updated_tags)
-        
-        
+
+
     def drag_data_get_data(self, treeview, context, selection, target_id,
                            etime):
         treeselection = treeview.get_selection()
@@ -220,7 +220,7 @@ class PreferencesEditor:
             if row[0] == id:
                 self.activity_tree.set_cursor((i, ))
             i += 1
-                
+
     def select_category(self, id):
         model = self.category_tree.get_model()
         i = 0
@@ -228,7 +228,7 @@ class PreferencesEditor:
             if row[0] == id:
                 self.category_tree.set_cursor((i, ))
             i += 1
-                
+
     def on_activity_list_drag_motion(self, treeview, drag_context, x, y, eventtime):
         self.prev_selected_activity = None
         try:
@@ -266,7 +266,7 @@ class PreferencesEditor:
         else:
             treeview.enable_model_drag_dest([drop_no], gtk.gdk.ACTION_MOVE)
 
-          
+
     def drag_data_received_data(self, treeview, context, x, y, selection,
                                 info, etime):
         model = treeview.get_model()
@@ -293,7 +293,7 @@ class PreferencesEditor:
         self.activity_store.load(self._get_selected_category())
 
         self.select_activity(int(data))
-        
+
         return
 
     def on_category_drop(self, treeview, context, x, y, selection,
@@ -301,12 +301,12 @@ class PreferencesEditor:
         model = self.category_tree.get_model()
         data = selection.data
         drop_info = treeview.get_dest_row_at_pos(x, y)
-        
+
         if drop_info:
             path, position = drop_info
             iter = model.get_iter(path)
             changed = runtime.storage.change_category(int(data), model[iter][0])
-            
+
             context.finish(changed, True, etime)
         else:
             context.finish(False, True, etime)
@@ -354,7 +354,7 @@ class PreferencesEditor:
     def activity_name_edited_cb(self, cell, path, new_text, model):
         id = model[path][0]
         category_id = model[path][2]
-        
+
         #look for dupes
         activities = runtime.storage.get_activities(category_id)
         for activity in activities:
@@ -363,15 +363,15 @@ class PreferencesEditor:
                     self.activity_store.remove(model.get_iter(path))
                 self.select_activity(activity['id'])
                 return False
-        
-        
+
+
         if id == -1: #new activity -> add
             model[path][0] = runtime.storage.add_activity(new_text.decode("utf-8"), category_id)
         else: #existing activity -> update
             runtime.storage.update_activity(id, new_text.decode("utf-8"), category_id)
         model[path][1] = new_text
         return True
-        
+
 
     def category_changed_cb(self, selection, model):
         """ enables and disables action buttons depending on selected item """
@@ -384,7 +384,7 @@ class PreferencesEditor:
 
             id = model[iter][0]
             self.activity_store.load(model[iter][0])
-        
+
         #start with nothing
         self.get_widget('activity_up').set_sensitive(False)
         self.get_widget('activity_down').set_sensitive(False)
@@ -401,12 +401,12 @@ class PreferencesEditor:
             return model[iter][0]
         else:
             return None
-        
+
 
     def activity_changed(self, selection, model):
         """ enables and disables action buttons depending on selected item """
         (model, iter) = selection.get_selected()
-        
+
         # treat any selected case
         unsorted_selected = self._get_selected_category() == -1
         self.get_widget('activity_up').set_sensitive(False)
@@ -414,7 +414,7 @@ class PreferencesEditor:
 
         self.get_widget('activity_edit').set_sensitive(iter != None)
         self.get_widget('activity_remove').set_sensitive(iter != None)
-        
+
         if iter != None and not unsorted_selected:
             first_item = model.get_path(iter) == (0,)
             self.get_widget('activity_up').set_sensitive(not first_item)
@@ -438,7 +438,7 @@ class PreferencesEditor:
         removable_id = model[iter][0]
         model.remove(iter)
         return removable_id
-        
+
     def unsorted_painter(self, column, cell, model, iter):
         cell_id = model.get_value(iter, 0)
         cell_text = model.get_value(iter, 1)
@@ -447,12 +447,12 @@ class PreferencesEditor:
             cell.set_property('markup', text)
         else:
             cell.set_property('text', cell_text)
-            
+
         return
 
     def on_activity_list_button_pressed(self, tree, event):
         self.activityCell.set_property("editable", False)
-        
+
 
     def on_activity_list_button_released(self, tree, event):
         if event.button == 1 and tree.get_path_at_pos(int(event.x), int(event.y)):
@@ -462,12 +462,12 @@ class PreferencesEditor:
             if self.prev_selected_activity == path:
                 self.activityCell.set_property("editable", True)
                 tree.set_cursor(path, focus_column = self.activityColumn, start_editing = True)
-    
+
             self.prev_selected_activity = path
-        
+
     def on_category_list_button_pressed(self, tree, event):
         self.activityCell.set_property("editable", False)
-        
+
     def on_category_list_button_released(self, tree, event):
         if event.button == 1 and tree.get_path_at_pos(int(event.x), int(event.y)):
             # Get treeview path.
@@ -479,10 +479,10 @@ class PreferencesEditor:
                 tree.set_cursor(path, focus_column = self.categoryColumn, start_editing = True)
             else:
                 self.categoryCell.set_property("editable", False)
-            
+
 
             self.prev_selected_category = path
-        
+
 
     def on_activity_remove_clicked(self, button):
         self.remove_current_activity()
@@ -494,7 +494,7 @@ class PreferencesEditor:
         (model, iter) = selection.get_selected()
         path = model.get_path(iter)[0]
         self.activity_tree.set_cursor(path, focus_column = self.activityColumn, start_editing = True)
-        
+
 
 
     """keyboard events"""
@@ -521,7 +521,7 @@ class PreferencesEditor:
 
     def on_category_remove_clicked(self, button):
         self.remove_current_category()
-        
+
     def on_category_edit_clicked(self, button):
         self.categoryCell.set_property("editable", True)
 
@@ -529,14 +529,14 @@ class PreferencesEditor:
         (model, iter) = selection.get_selected()
         path = model.get_path(iter)[0]
         self.category_tree.set_cursor(path, focus_column = self.categoryColumn, start_editing = True)
-        
-        
+
+
     def on_category_list_key_pressed(self, tree, event_key):
         key = event_key.keyval
-        
+
         if self._get_selected_category() == -1:
             return #ignoring unsorted category
-        
+
         selection = tree.get_selection()
         (model, iter) = selection.get_selected()
 
@@ -573,12 +573,12 @@ class PreferencesEditor:
                 self.categoryCell.set_property("editable", False)
                 return
 
-            self.close_window()     
+            self.close_window()
 
     """button events"""
     def on_category_add_clicked(self, button):
         """ appends row, jumps to it and allows user to input name """
-        
+
         new_category = self.category_store.insert_before(self.category_store.unsorted_category,
                                                          [-2, _(u"New category"), -1])
 
@@ -592,7 +592,7 @@ class PreferencesEditor:
     def on_activity_add_clicked(self, button):
         """ appends row, jumps to it and allows user to input name """
         category_id = self._get_selected_category()
-        
+
         new_activity = self.activity_store.append([-1, _(u"New activity"), category_id, -1])
 
         (model, iter) = self.selection.get_selected()
@@ -632,8 +632,8 @@ class PreferencesEditor:
         self.close_window()
 
     def on_close(self, widget, event):
-        self.close_window()        
-    
+        self.close_window()
+
     def close_window(self):
         if not self.parent:
             gtk.main_quit()
@@ -657,14 +657,14 @@ class PreferencesEditor:
         else:
             # notify interval slider value label
             label = _(u"Never")
-        
+
         return label
-    
+
     def on_notify_interval_value_changed(self, scale):
         value = int(scale.get_value())
         self.config.set_notify_interval(value)
         self.get_widget("notify_on_idle").set_sensitive(value <= 120)
-    
+
     def on_keybinding_changed(self, textbox):
         self.config.set_keybinding(textbox.get_text().decode('utf8', 'replace'))
 
@@ -677,4 +677,4 @@ class PreferencesEditor:
 
     def on_preferences_window_destroy(self, window):
         self.window = None
-        
+
diff --git a/hamster/pytweener.py b/hamster/pytweener.py
index 575dd31..c8c3876 100644
--- a/hamster/pytweener.py
+++ b/hamster/pytweener.py
@@ -17,28 +17,28 @@ class Tweener(object):
         self.currentTweens = {}
         self.defaultTweenType = tween or Easing.Cubic.easeInOut
         self.defaultDuration = default_duration or 1.0
- 
+
     def hasTweens(self):
         return len(self.currentTweens) > 0
- 
- 
+
+
     def addTween(self, obj, **kwargs):
         """ addTween( object, **kwargs) -> tweenObject or False
- 
+
             Example:
             tweener.addTween( myRocket, throttle=50, setThrust=400, tweenTime=5.0, tweenType=tweener.OUT_QUAD )
- 
+
             You must first specify an object, and at least one property or function with a corresponding
             change value. The tween will throw an error if you specify an attribute the object does
             not possess. Also the data types of the change and the initial value of the tweened item
             must match. If you specify a 'set' -type function, the tweener will attempt to get the
-            starting value by call the corresponding 'get' function on the object. If you specify a 
-            property, the tweener will read the current state as the starting value. You add both 
+            starting value by call the corresponding 'get' function on the object. If you specify a
+            property, the tweener will read the current state as the starting value. You add both
             functions and property changes to the same tween.
- 
+
             in addition to any properties you specify on the object, these keywords do additional
             setup of the tween.
- 
+
             tweenTime = the duration of the motion
             tweenType = one of the predefined tweening equations or your own function
             onComplete = specify a function to call on completion of the tween
@@ -48,37 +48,37 @@ class Tweener(object):
         if "tweenTime" in kwargs:
             t_time = kwargs.pop("tweenTime")
         else: t_time = self.defaultDuration
-        
+
         if "tweenType" in kwargs:
             t_type = kwargs.pop("tweenType")
         else: t_type = self.defaultTweenType
- 
+
         if "onComplete" in kwargs:
             t_completeFunc = kwargs.pop("onComplete")
         else: t_completeFunc = None
- 
+
         if "onUpdate" in kwargs:
             t_updateFunc = kwargs.pop("onUpdate")
         else: t_updateFunc = None
- 
+
         if "tweenDelay" in kwargs:
             t_delay = kwargs.pop("tweenDelay")
         else: t_delay = 0
- 
+
         tw = Tween( obj, t_time, t_type, t_completeFunc, t_updateFunc, t_delay, **kwargs )
-        if tw:    
+        if tw:
             tweenlist = self.currentTweens.setdefault(obj, [])
             tweenlist.append(tw)
         return tw
- 
+
     def removeTween(self, tweenObj):
         tweenObj.complete = True
- 
+
     def getTweensAffectingObject(self, obj):
         """Get a list of all tweens acting on the specified object
         Useful for manipulating tweens on the fly"""
         return self.currentTweens.get(obj, [])
- 
+
     def killTweensOf(self, obj):
         """Stop tweening an object, without completing the motion
         or firing the completeFunction"""
@@ -87,14 +87,14 @@ class Tweener(object):
         except:
             pass
 
- 
+
     def finish(self):
         #go to last frame for all tweens
         for obj in self.currentTweens:
             for t in self.currentTweens[obj]:
                 t.update(t.duration)
         self.currentTweens = {}
- 
+
     def update(self, timeSinceLastFrame):
         for obj in self.currentTweens.keys():
             # updating tweens from last to first and deleting while at it
@@ -103,25 +103,25 @@ class Tweener(object):
                 t.update(timeSinceLastFrame)
                 if t.complete:
                     del self.currentTweens[obj][i]
-                
+
                 if not self.currentTweens[obj]:
                     del self.currentTweens[obj]
- 
+
 class Tween(object):
     __slots__ = ['duration', 'delay', 'target', 'tween', 'tweenables', 'delta',
                  'target', 'ease', 'tweenables', 'delta', 'completeFunction',
                  'updateFunction', 'complete', 'paused']
-    
+
     def __init__(self, obj, duration, easing, on_complete, on_update, delay, **kwargs):
         """Tween object use Tweener.addTween( ... ) to create"""
         self.duration = duration
         self.delay = delay
         self.target = obj
         self.ease = easing
-        
+
         # list of (property, start_value, end_value)
         self.tweenables = [(k, self.target.__dict__[k], v) for k, v in kwargs.items()]
-        
+
         self.delta = 0
         self.completeFunction = on_complete
         self.updateFunction = on_update
@@ -135,20 +135,20 @@ class Tween(object):
             or tween.pause() which pauses indefinitely."""
         self.paused = True
         self.delay = numSeconds
- 
+
     def resume( self ):
         """Resume from pause"""
         if self.paused:
             self.paused=False
- 
+
     def update(self, ptime):
         """Update tween with the time since the last frame
            if there is an update callback, it is always called
            whether the tween is running or paused"""
-            
+
         if self.complete:
             return
-        
+
         if self.paused:
             if self.delay > 0:
                 self.delay = max( 0, self.delay - ptime )
@@ -158,20 +158,20 @@ class Tween(object):
                 if self.updateFunction:
                     self.updateFunction()
             return
- 
+
         self.delta = self.delta + ptime
         if self.delta > self.duration:
             self.delta = self.duration
 
-    
+
         for prop, start_value, end_value in self.tweenables:
             self.target.__dict__[prop] = self.ease(self.delta, start_value, end_value - start_value, self.duration)
-        
+
         if self.delta == self.duration:
             self.complete = True
             if self.completeFunction:
                 self.completeFunction()
- 
+
         if self.updateFunction:
             self.updateFunction()
 
@@ -181,7 +181,7 @@ There certainly is room for improvement, but wanted to keep the readability to s
 
 ================================================================================
  Easing Equations
- (c) 2003 Robert Penner, all rights reserved. 
+ (c) 2003 Robert Penner, all rights reserved.
  This work is subject to the terms in
  http://www.robertpenner.com/easing_terms_of_use.html.
 ================================================================================
@@ -231,7 +231,7 @@ class Easing(object):
         def easeInOut (t, b, c, d, s = 1.70158):
             t = t / (d * 0.5)
             s = s * 1.525
-            
+
             if t < 1:
                 return c * 0.5 * (t * t * ((s + 1) * t - s)) + b
 
@@ -266,7 +266,7 @@ class Easing(object):
             return Easing.Bounce.easeOut (t * 2 -d, 0, c, d) * .5 + c*.5 + b
 
 
-        
+
     class Circ(object):
         @staticmethod
         def easeIn (t, b, c, d):
@@ -283,7 +283,7 @@ class Easing(object):
             t = t / (d * 0.5)
             if t < 1:
                 return -c * 0.5 * (math.sqrt(1 - t * t) - 1) + b
-            
+
             t = t - 2
             return c*0.5 * (math.sqrt(1 - t * t) + 1) + b
 
@@ -304,7 +304,7 @@ class Easing(object):
             t = t / (d * 0.5)
             if t < 1:
                 return c * 0.5 * t * t * t + b
-            
+
             t = t - 2
             return c * 0.5 * (t * t * t + 2) + b
 
@@ -314,9 +314,9 @@ class Easing(object):
         def easeIn (t, b, c, d, a = 0, p = 0):
             if t==0: return b
 
-            t = t / d            
+            t = t / d
             if t == 1: return b+c
-            
+
             if not p: p = d * .3;
 
             if not a or a < abs(c):
@@ -324,18 +324,18 @@ class Easing(object):
                 s = p / 4
             else:
                 s = p / (2 * math.pi) * math.asin(c / a)
-            
-            t = t - 1            
+
+            t = t - 1
             return - (a * math.pow(2, 10 * t) * math.sin((t*d-s) * (2 * math.pi) / p)) + b
 
 
         @staticmethod
         def easeOut (t, b, c, d, a = 0, p = 0):
             if t == 0: return b
-            
+
             t = t / d
             if (t == 1): return b + c
-            
+
             if not p: p = d * .3;
 
             if not a or a < abs(c):
@@ -343,17 +343,17 @@ class Easing(object):
                 s = p / 4
             else:
                 s = p / (2 * math.pi) * math.asin(c / a)
-                
+
             return a * math.pow(2,-10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) + c + b
 
 
         @staticmethod
         def easeInOut (t, b, c, d, a = 0, p = 0):
             if t == 0: return b
-            
+
             t = t / (d * 0.5)
             if t == 2: return b + c
-            
+
             if not p: p = d * (.3 * 1.5)
 
             if not a or a < abs(c):
@@ -361,11 +361,11 @@ class Easing(object):
                 s = p / 4
             else:
                 s = p / (2 * math.pi) * math.asin(c / a)
-                
+
             if (t < 1):
                 t = t - 1
                 return -.5 * (a * math.pow(2, 10 * t) * math.sin((t * d - s) * (2 * math.pi) / p)) + b
-                
+
             t = t - 1
             return a * math.pow(2, -10 * t) * math.sin((t * d - s) * (2 * math.pi) / p) * .5 + c + b
 
@@ -393,10 +393,10 @@ class Easing(object):
                 return b+c
 
             t = t / (d * 0.5)
-            
+
             if t < 1:
                 return c * 0.5 * math.pow(2, 10 * (t - 1)) + b
-            
+
             return c * 0.5 * (-math.pow(2, -10 * (t - 1)) + 2) + b
 
 
@@ -434,7 +434,7 @@ class Easing(object):
             t = t / (d * 0.5)
             if t < 1:
                 return c * 0.5 * t * t + b
-            
+
             t = t - 1
             return -c * 0.5 * (t * (t - 2) - 1) + b
 
@@ -455,11 +455,11 @@ class Easing(object):
             t = t / (d * 0.5)
             if t < 1:
                 return c * 0.5 * t * t * t * t + b
-            
+
             t = t - 2
             return -c * 0.5 * (t * t * t * t - 2) + b
 
-    
+
     class Quint(object):
         @staticmethod
         def easeIn (t, b, c, d):
@@ -476,7 +476,7 @@ class Easing(object):
             t = t / (d * 0.5)
             if t < 1:
                 return c * 0.5 * t * t * t * t * t + b
-            
+
             t = t - 2
             return c * 0.5 * (t * t * t * t * t + 2) + b
 
@@ -506,10 +506,10 @@ class Easing(object):
         @staticmethod
         def easeInOut(t, b, c, d):
             t = t / (d * 0.5)
-            
+
             if t < 1:
                 return c * 0.5 * t * t * t * t * t + b
-            
+
             t = t - 2
             return c * 0.5 * (t * t * t * t * t + 2) + b
 
@@ -532,7 +532,7 @@ if __name__ == "__main__":
 
 
     total = dt.datetime.now()
-    
+
     t = dt.datetime.now()
     for i, o in enumerate(objects):
         tweener.addTween(o, a = i, b = i, c = i, tweenTime = 1.0)
@@ -545,7 +545,7 @@ if __name__ == "__main__":
     print "update", dt.datetime.now() - t
 
     t = dt.datetime.now()
-    
+
     for i in range(10):
         for i, o in enumerate(objects):
             tweener.killTweensOf(o)
@@ -553,5 +553,5 @@ if __name__ == "__main__":
     print "kill-add", dt.datetime.now() - t
 
     print "total", dt.datetime.now() - total
-    
+
 
diff --git a/hamster/reports.py b/hamster/reports.py
index cd740b1..58a900a 100644
--- a/hamster/reports.py
+++ b/hamster/reports.py
@@ -27,7 +27,7 @@ from hamster.i18n import C_
 
 def simple(facts, start_date, end_date, format, path):
     report_path = stuff.locale_from_utf8(path)
-    
+
     if format == "tsv":
         writer = TSVWriter(report_path)
     elif format == "xml":
@@ -45,52 +45,52 @@ class ReportWriter(object):
     def __init__(self, path, datetime_format = "%Y-%m-%d %H:%M:%S"):
         self.file = open(path, "w")
         self.datetime_format = datetime_format
-        
+
     def write_report(self, facts):
         try:
             for fact in facts:
                 fact["name"]= fact["name"].encode('utf-8')
                 fact["description"] = (fact["description"] or u"").encode('utf-8')
                 fact["category"] = (fact["category"] or _("Unsorted")).encode('utf-8')
-                
+
                 if self.datetime_format:
                     fact["start_time"] = fact["start_time"].strftime(self.datetime_format)
-                    
+
                     if fact["end_time"]:
                         fact["end_time"] = fact["end_time"].strftime(self.datetime_format)
                     else:
-                        fact["end_time"] = ""                
+                        fact["end_time"] = ""
                 fact["delta"] = fact["delta"].seconds / 60 + fact["delta"].days * 24 * 60
-    
+
                 self._write_fact(self.file, fact)
-    
+
             self._finish(self.file, facts)
         finally:
             self.file.close()
-    
+
     def _start(self, file, facts):
         raise NotImplementedError
-    
+
     def _write_fact(self, file, fact):
         raise NotImplementedError
-        
+
     def _finish(self, file, facts):
         raise NotImplementedError
-    
+
 class ICalWriter(ReportWriter):
     """a lame ical writer, could not be bothered with finding a library"""
     def __init__(self, path):
         ReportWriter.__init__(self, path, datetime_format = "%Y%m%dT%H%M%S")
         self.file.write("BEGIN:VCALENDAR\nVERSION:1.0\n")
 
-    
+
     def _write_fact(self, file, fact):
         #for now we will skip ongoing facts
         if not fact["end_time"]: return
 
         if fact["category"] == _("Unsorted"):
             fact["category"] = None
-            
+
         self.file.write("""BEGIN:VEVENT
 CATEGORIES:%(category)s
 DTSTART:%(start_time)s
@@ -99,7 +99,7 @@ SUMMARY:%(name)s
 DESCRIPTION:%(description)s
 END:VEVENT
 """ % fact)
-        
+
     def _finish(self, file, facts):
         self.file.write("END:VCALENDAR\n")
 
@@ -133,7 +133,7 @@ class XMLWriter(ReportWriter):
         ReportWriter.__init__(self, path)
         self.doc = Document()
         self.activity_list = self.doc.createElement("activities")
-    
+
     def _write_fact(self, file, fact):
         activity = self.doc.createElement("activity")
         activity.setAttribute("name", fact["name"])
@@ -143,9 +143,9 @@ class XMLWriter(ReportWriter):
         activity.setAttribute("category", fact["category"])
         activity.setAttribute("description", fact["description"])
         self.activity_list.appendChild(activity)
-        
+
     def _finish(self, file, facts):
-        self.doc.appendChild(self.activity_list)        
+        self.doc.appendChild(self.activity_list)
         file.write(self.doc.toxml())
 
 
@@ -162,7 +162,7 @@ class HTMLWriter(ReportWriter):
             self.title = _(u"Overview for %(start_B)s %(start_d)s â?? %(end_B)s %(end_d)s, %(end_Y)s") % dates_dict
         else:
             self.title = _(u"Overview for %(start_B)s %(start_d)s â?? %(end_d)s, %(end_Y)s") % dates_dict
-    
+
         if start_date == end_date:
             self.title = _(u"Overview for %(start_B)s %(start_d)s, %(start_Y)s") % dates_dict
 
@@ -170,7 +170,7 @@ class HTMLWriter(ReportWriter):
         self.even_row = True
 
         """TODO bring template to external file or write to PDF"""
-        
+
         self.file.write("""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
 <html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
@@ -184,7 +184,7 @@ class HTMLWriter(ReportWriter):
             font-size: 12px;
             padding: 12px;
             color: #303030;
-            
+
         }
         h1 {
             border-bottom: 2px solid #303030;
@@ -202,7 +202,7 @@ class HTMLWriter(ReportWriter):
             text-align: center;
             padding-bottom: 6px;
         }
-  
+
         .smallCell {
             text-align: center;
             width: 100px;
@@ -212,14 +212,14 @@ class HTMLWriter(ReportWriter):
         .largeCell {
             text-align: left;
             padding: 3px 3px 3px 5px;
-        }     
+        }
         .row0 {
                 background-color: #EAE8E3;
         }
 
         .row1 {
                 background-color: #ffffff;
-        }   
+        }
 
     </style>
 </head>
@@ -235,10 +235,10 @@ class HTMLWriter(ReportWriter):
         <th class="smallCell">""" + _("Duration") + """</th>
         <th class="largeCell">""" + _("Description") + """</th>
     </tr>""")
-    
+
     def _write_fact(self, report, fact):
         end_time = fact["end_time"]
-        
+
         # ongoing task in current day
         end_time_str = ""
         if end_time:
@@ -248,8 +248,8 @@ class HTMLWriter(ReportWriter):
         if fact["category"] != _("Unsorted"): #do not print "unsorted" in list
             category = fact["category"]
 
-        description = fact["description"] or ""            
-            
+        description = fact["description"] or ""
+
         # fact date column in HTML report
         report.write("""<tr class="row%d">
                             <td class="smallCell">%s</td>
@@ -267,23 +267,23 @@ class HTMLWriter(ReportWriter):
                                 # http://docs.python.org/library/time.html#time.strftime
                                 C_("html report","%b %d, %Y")),
                               fact["name"],
-                              category, 
+                              category,
                               fact["start_time"].strftime('%H:%M'),
                               end_time_str,
                               stuff.format_duration(fact["delta"]) or "",
                               description))
 
-        self.even_row = not self.even_row            
+        self.even_row = not self.even_row
 
 
         # save data for summary table
         if fact["delta"]:
             id_string = "<td class=\"smallCell\">%s</td><td class=\"largeCell\">%s</td>" % (fact["category"], fact["name"])
             self.sum_time[id_string] = self.sum_time.get(id_string, 0) + fact["delta"]
-    
+
     def _finish(self, report, facts):
         report.write("</table>")
-    
+
         # summary table
         report.write("\n<h2>%s</h2>\n" % _("Totals"))
         report.write("""<table>
@@ -297,11 +297,11 @@ class HTMLWriter(ReportWriter):
         for key in sorted(self.sum_time.keys()):
             report.write("    <tr class=\"row%d\">%s<td class=\"smallCell\">%s</td></tr>\n" % (int(even_row), key, stuff.format_duration(self.sum_time[key])))
             tot_time += self.sum_time[key]
-          
+
             even_row = not even_row
 
         report.write("    <tr><th colspan=\"2\" style=\"text-align:right;\">" + _("Total Time") + ":</th><th>%s</th></tr>\n" % (stuff.format_duration(tot_time)))
         report.write("</table>\n")
-    
+
         report.write("</body>\n</html>")
-    
+
diff --git a/hamster/stats.py b/hamster/stats.py
index ec65a1b..1e833b0 100644
--- a/hamster/stats.py
+++ b/hamster/stats.py
@@ -43,7 +43,7 @@ class StatsViewer(object):
         self.parent = parent# determine if app should shut down on close
         self._gui = stuff.load_ui_file("stats.ui")
         self.report_chooser = None
-        
+
         self.facts = None
 
         self.window = self.get_widget("tabs_window")
@@ -56,17 +56,17 @@ class StatsViewer(object):
 
         #set to monday
         self.start_date = self.view_date - dt.timedelta(self.view_date.weekday() + 1)
-        
+
         # look if we need to start on sunday or monday
         self.start_date = self.start_date + dt.timedelta(stuff.locale_first_weekday())
-        
+
         # see if we have not gotten carried away too much in all these calculations
         if (self.view_date - self.start_date) == dt.timedelta(7):
             self.start_date += dt.timedelta(7)
-        
+
         self.end_date = self.start_date + dt.timedelta(6)
 
-        
+
         self.overview = OverviewBox()
         self.get_widget("overview_tab").add(self.overview)
         self.fact_tree = self.overview.fact_tree # TODO - this is upside down, should maybe get the overview tab over here
@@ -74,7 +74,7 @@ class StatsViewer(object):
 
         self.reports = ReportsBox()
         self.get_widget("reports_tab").add(self.reports)
-        
+
         self.range_combo = gtk.combo_box_new_text()
         self.range_combo.append_text(_("Week"))
         self.range_combo.append_text(_("Month"))
@@ -84,9 +84,9 @@ class StatsViewer(object):
         self.range_combo.append_text("All")
         self.range_combo.set_active(0)
         self.range_combo.connect("changed", self.on_range_combo_changed)
-        
-        
-        
+
+
+
         self.get_widget("range_pick").add(self.range_combo)
 
 
@@ -113,10 +113,10 @@ class StatsViewer(object):
     def search(self):
         if self.start_date > self.end_date: # make sure the end is always after beginning
             self.start_date, self.end_date = self.end_date, self.start_date
-        
+
         self.start_date_input.set_date(self.start_date)
         self.end_date_input.set_date(self.end_date)
-        
+
         search_terms = self.get_widget("search").get_text().decode("utf8", "replace")
         self.facts = runtime.storage.get_facts(self.start_date, self.end_date, search_terms)
 
@@ -138,7 +138,7 @@ class StatsViewer(object):
         start_date, end_date = self.start_date, self.end_date
         dates_dict = stuff.dateDict(start_date, "start_")
         dates_dict.update(stuff.dateDict(end_date, "end_"))
-        
+
         if start_date == end_date:
             # date format for overview label when only single day is visible
             # Using python datetime formatting syntax. See:
@@ -187,21 +187,21 @@ class StatsViewer(object):
 
     def on_search_activate(self, widget):
         self.search()
-        
+
     def on_report_button_clicked(self, widget):
         def on_report_chosen(widget, format, path):
             self.report_chooser = None
             reports.simple(self.facts, self.start_date, self.end_date, format, path)
-    
+
             if format == ("html"):
                 webbrowser.open_new("file://%s" % path)
             else:
                 gtk.show_uri(gtk.gdk.Screen(),
                              "file://%s" % os.path.split(path)[0], 0L)
-    
+
         def on_report_chooser_closed(widget):
             self.report_chooser = None
-            
+
         if not self.report_chooser:
             self.report_chooser = widgets.ReportChooserDialog()
             self.report_chooser.connect("report-chosen", on_report_chosen)
@@ -218,7 +218,7 @@ class StatsViewer(object):
 
         self.get_widget("preset_range").hide()
         self.get_widget("range_box").hide()
-        
+
         if idx == 2: # date range
             self.get_widget("range_box").show()
         else:
@@ -227,16 +227,16 @@ class StatsViewer(object):
                 self.start_date = self.start_date + dt.timedelta(stuff.locale_first_weekday())
                 self.end_date = self.start_date + dt.timedelta(6)
                 self.get_widget("preset_range").show()
-    
+
             elif idx == 1: #month
                 self.start_date = self.view_date - dt.timedelta(self.view_date.day - 1) #set to beginning of month
                 first_weekday, days_in_month = calendar.monthrange(self.view_date.year, self.view_date.month)
                 self.end_date = self.start_date + dt.timedelta(days_in_month - 1)
                 self.get_widget("preset_range").show()
-    
-                
+
+
             self.search()
-        
+
     def on_start_date_entered(self, input):
         self.start_date = input.get_date().date()
         self.view_date = self.start_date
@@ -247,12 +247,12 @@ class StatsViewer(object):
         self.search()
 
     def _chosen_range(self):
-        return self.range_combo.get_active() 
+        return self.range_combo.get_active()
 
     def on_prev_clicked(self, button):
         if self._chosen_range() == 0:  # week
             self.start_date -= dt.timedelta(7)
-            self.end_date -= dt.timedelta(7)        
+            self.end_date -= dt.timedelta(7)
         elif self._chosen_range() == 1: # month
             self.end_date = self.start_date - dt.timedelta(1)
             first_weekday, days_in_month = calendar.monthrange(self.end_date.year, self.end_date.month)
@@ -264,12 +264,12 @@ class StatsViewer(object):
     def on_next_clicked(self, button):
         if self._chosen_range() == 0:  # week
             self.start_date += dt.timedelta(7)
-            self.end_date += dt.timedelta(7)        
+            self.end_date += dt.timedelta(7)
         elif self._chosen_range() == 1: # month
             self.start_date = self.end_date + dt.timedelta(1)
             first_weekday, days_in_month = calendar.monthrange(self.start_date.year, self.start_date.month)
             self.end_date = self.start_date + dt.timedelta(days_in_month - 1)
-    
+
         self.view_date = self.start_date
         self.search()
 
@@ -281,14 +281,14 @@ class StatsViewer(object):
             self.start_date = self.view_date - dt.timedelta(self.view_date.weekday() + 1)
             self.start_date = self.start_date + dt.timedelta(stuff.locale_first_weekday())
             self.end_date = self.start_date + dt.timedelta(6)
-        
+
         elif self._chosen_range() == 1: # month
             self.start_date = self.view_date - dt.timedelta(self.view_date.day - 1) #set to beginning of month
             first_weekday, days_in_month = calendar.monthrange(self.view_date.year, self.view_date.month)
             self.end_date = self.start_date + dt.timedelta(days_in_month - 1)
-        
+
         self.search()
-        
+
     def get_widget(self, name):
         """ skip one variable (huh) """
         return self._gui.get_object(name)
@@ -327,22 +327,22 @@ class StatsViewer(object):
     def on_close(self, widget, event):
         runtime.dispatcher.del_handler('activity_updated', self.after_activity_update)
         runtime.dispatcher.del_handler('day_updated', self.after_fact_update)
-        self.close_window()        
+        self.close_window()
 
     def on_window_key_pressed(self, tree, event_key):
       if (event_key.keyval == gtk.keysyms.Escape
-          or (event_key.keyval == gtk.keysyms.w 
+          or (event_key.keyval == gtk.keysyms.w
               and event_key.state & gtk.gdk.CONTROL_MASK)):
         self.close_window()
-    
-    
+
+
     def close_window(self):
         if not self.parent:
             gtk.main_quit()
         else:
             self.window.destroy()
             return False
-        
+
     def show(self):
         self.window.show()
 
diff --git a/hamster/stats_overview.py b/hamster/stats_overview.py
index 70af8bd..6da77c4 100644
--- a/hamster/stats_overview.py
+++ b/hamster/stats_overview.py
@@ -45,19 +45,19 @@ class OverviewBox(gtk.VBox):
     def __init__(self):
         gtk.VBox.__init__(self)
         self.set_border_width(6)
-        
+
         scroll = gtk.ScrolledWindow()
         scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
         scroll.set_shadow_type(gtk.SHADOW_IN)
-        
+
         self.start_date, self.end_date = None, None
         self.facts = []
-        
+
         self.fact_tree = widgets.FactTree()
         self.fact_tree.connect("row-activated", self.on_facts_row_activated)
         self.fact_tree.connect("key-press-event", self.on_facts_keys)
         self.fact_tree.connect("edit_clicked", lambda tree, fact: self.on_edit_clicked(fact))
-        
+
         scroll.add(self.fact_tree)
         self.add(scroll)
 
@@ -72,11 +72,11 @@ class OverviewBox(gtk.VBox):
     def fill_facts_tree(self):
         self.fact_tree.detach_model()
         self.fact_tree.clear()
-        
+
         #create list of all required dates
         dates = [(self.start_date + dt.timedelta(i), [])
                     for i in range((self.end_date - self.start_date).days  + 1)]
-        
+
         #update with facts for the day
         for date, facts in groupby(self.facts, lambda fact: fact["date"]):
             dates[dates.index((date, []))] = (date, list(facts))
@@ -143,7 +143,7 @@ class OverviewBox(gtk.VBox):
         selection = tree.get_selection()
         (model, iter) = selection.get_selected()
         custom_fact = dialogs.edit.show(self, fact_id = model[iter][0])
-        
+
     def on_facts_keys(self, tree, event):
         if (event.keyval == gtk.keysyms.Delete):
             self.delete_selected()
@@ -157,13 +157,13 @@ class OverviewBox(gtk.VBox):
         elif event.keyval == gtk.keysyms.v and event.state & gtk.gdk.CONTROL_MASK:
             self.check_clipboard()
             return True
-        
+
         return False
 
     def check_clipboard(self):
         clipboard = gtk.Clipboard()
         clipboard.request_text(self.on_clipboard_text)
-    
+
     def on_clipboard_text(self, clipboard, text, data):
         # first check that we have a date selected
         selection = self.fact_tree.get_selection()
@@ -177,23 +177,23 @@ class OverviewBox(gtk.VBox):
                                     int(selected_date[2]))
         if not selected_date:
             return
-        
+
         res = stuff.parse_activity_input(text)
 
         if res.start_time is None or res.end_time is None:
             return
-        
+
         start_time = res.start_time.replace(year = selected_date.year,
                                             month = selected_date.month,
                                             day = selected_date.day)
         end_time = res.end_time.replace(year = selected_date.year,
                                                month = selected_date.month,
                                                day = selected_date.day)
-    
+
         activity_name = res.activity_name
         if res.category_name:
             activity_name += "@%s" % res.category_name
-            
+
         if res.description:
             activity_name += ", %s" % res.description
 
@@ -202,10 +202,10 @@ class OverviewBox(gtk.VBox):
         # TODO - set cursor to the pasted entry when done
         # TODO - revisit parsing of selected date
         added_fact = runtime.storage.add_fact(activity_name, start_time, end_time)
-        
+
 
 if __name__ == "__main__":
-    gtk.window_set_default_icon_name("hamster-applet")    
+    gtk.window_set_default_icon_name("hamster-applet")
     window = gtk.Window()
     window.set_title("Hamster - reports")
     window.set_size_request(800, 600)
@@ -213,11 +213,11 @@ if __name__ == "__main__":
     window.add(overview)
     window.connect("delete_event", lambda *args: gtk.main_quit())
     window.show_all()
-    
-    start_date = dt.date.today() - dt.timedelta(days=30)    
+
+    start_date = dt.date.today() - dt.timedelta(days=30)
     end_date = dt.date.today()
     facts = runtime.storage.get_facts(start_date, end_date)
     overview.search(start_date, end_date, facts)
-    
 
-    gtk.main()    
+
+    gtk.main()
diff --git a/hamster/stats_reports.py b/hamster/stats_reports.py
index 1e166ca..3028d49 100644
--- a/hamster/stats_reports.py
+++ b/hamster/stats_reports.py
@@ -62,9 +62,9 @@ class ReportsBox(gtk.VBox):
         self.category_chart.connect("bar-clicked", self.on_category_clicked)
         self.selected_categories = []
         self.category_sums = None
-        
+
         self.get_widget("totals_by_category").add(self.category_chart);
-        
+
         self.activity_chart = charting.HorizontalBarChart(background = self.background,
                                                           max_bar_width = 20,
                                                           legend_width = x_offset,
@@ -89,7 +89,7 @@ class ReportsBox(gtk.VBox):
 
 
         self._gui.connect_signals(self)
-        
+
         self.config = GconfStore()
         runtime.dispatcher.add_handler('gconf_on_day_start_changed', self.on_day_start_changed)
 
@@ -132,7 +132,7 @@ class ReportsBox(gtk.VBox):
         self.category_sums, self.activity_sums, self.tag_sums = [], [], []
         self.selected_categories, self.selected_activities, self.selected_tags = [], [], []
         self.category_chart.bars_selected, self.activity_chart.bars_selected, self.tag_chart.bars_selected = [], [], []
-        
+
         self.start_date = start_date
         self.end_date = end_date
 
@@ -154,7 +154,7 @@ class ReportsBox(gtk.VBox):
 
         import copy
         facts = copy.deepcopy(self.facts)
-        
+
         for fact in facts:
             if self.selected_categories and fact["category"] not in self.selected_categories:
                 fact["delta"] = dt.timedelta()
@@ -207,7 +207,7 @@ class ReportsBox(gtk.VBox):
         for sum in tag_sums:
             tag_sums[sum] = tag_sums[sum] / 60 / 60.0
 
-        if tag_sums:        
+        if tag_sums:
             if self.tag_sums:
                 tag_sums = [(key, tag_sums[key]) for key in self.tag_sums[0]]
             else:
@@ -244,14 +244,14 @@ class ReportsBox(gtk.VBox):
 
     def on_day_start_changed(self, event, new_minutes):
         self.do_graph()
-    
+
     def on_statistics_button_clicked(self, button):
         dialogs.stats.show(self)
 
 
 
 if __name__ == "__main__":
-    gtk.window_set_default_icon_name("hamster-applet")    
+    gtk.window_set_default_icon_name("hamster-applet")
     window = gtk.Window()
     window.set_title("Hamster - reports")
     window.set_size_request(800, 600)
@@ -260,11 +260,11 @@ if __name__ == "__main__":
     window.connect("delete_event", lambda *args: gtk.main_quit())
     window.show_all()
 
-    start_date = dt.date.today() - dt.timedelta(days=30)    
+    start_date = dt.date.today() - dt.timedelta(days=30)
     end_date = dt.date.today()
     facts = runtime.storage.get_facts(start_date, end_date)
     reports.search(start_date, end_date, facts)
-    
 
-    gtk.main()    
+
+    gtk.main()
 
diff --git a/hamster/stats_stats.py b/hamster/stats_stats.py
index ddf80d3..26ee349 100644
--- a/hamster/stats_stats.py
+++ b/hamster/stats_stats.py
@@ -39,7 +39,7 @@ class TimelineBackground(widgets.TimeLine):
     def __init__(self):
         widgets.TimeLine.__init__(self)
         self.bar_color = (220, 220, 220)
-    
+
     def on_expose(self):
         self.fill_area(0, 0, self.width, self.height, (0.975, 0.975, 0.975))
         widgets.TimeLine.on_expose(self)
@@ -53,7 +53,7 @@ class StatsViewer(object):
 
         self.parent = parent# determine if app should shut down on close
 
-        
+
         self.background = (0.975, 0.975, 0.975)
         self.get_widget("explore_frame").modify_bg(gtk.STATE_NORMAL,
                       gtk.gdk.Color(*[int(b*65536.0) for b in self.background]))
@@ -75,21 +75,21 @@ class StatsViewer(object):
 
     def init_stats(self):
         self.stat_facts = runtime.storage.get_facts(dt.date(1970, 1, 1), dt.date.today())
-        
+
         if not self.stat_facts or self.stat_facts[-1]["start_time"].year == self.stat_facts[0]["start_time"].year:
             self.get_widget("explore_controls").hide()
         else:
             by_year = stuff.totals(self.stat_facts,
                                    lambda fact: fact["start_time"].year,
                                    lambda fact: 1)
-            
+
             year_box = self.get_widget("year_box")
             class YearButton(gtk.ToggleButton):
                 def __init__(self, label, year, on_clicked):
                     gtk.ToggleButton.__init__(self, label)
                     self.year = year
                     self.connect("clicked", on_clicked)
-            
+
             all_button = YearButton(C_("years", "All").encode("utf-8"),
                                     None,
                                     self.on_year_changed)
@@ -97,11 +97,11 @@ class StatsViewer(object):
             self.bubbling = True # TODO figure out how to properly work with togglebuttons as radiobuttons
             all_button.set_active(True)
             self.bubbling = False # TODO figure out how to properly work with togglebuttons as radiobuttons
-    
+
             years = sorted(by_year.keys())
             for year in years:
                 year_box.pack_start(YearButton(str(year), year, self.on_year_changed))
-    
+
             year_box.show_all()
 
         self.chart_category_totals = charting.HorizontalBarChart(value_format = "%.1f",
@@ -125,7 +125,7 @@ class StatsViewer(object):
                                                                 max_bar_width = 20,
                                                                 legend_width = 70)
         self.get_widget("explore_weekday_starts_ends").add(self.chart_weekday_starts_ends)
-        
+
         self.chart_category_starts_ends = charting.HorizontalDayChart(bars_beveled = False,
                                                                 animate = False,
                                                                 background = self.background,
@@ -141,11 +141,11 @@ class StatsViewer(object):
                 self.background = background
                 self.text = ""
                 self.fontsize = fontsize
-                
+
             def set_text(self, text):
                 self.text = text
                 self.redraw_canvas()
-                
+
             def on_expose(self):
                 if self.background:
                     self.fill_area(0, 0, self.width, self.height, self.background)
@@ -153,14 +153,14 @@ class StatsViewer(object):
                 default_font = pango.FontDescription(gtk.Style().font_desc.to_string())
                 default_font.set_size(self.fontsize * pango.SCALE)
                 self.layout.set_font_description(default_font)
-                
+
                 #self.context.set_source_rgb(0,0,0)
                 self.layout.set_markup(self.text)
 
                 self.layout.set_width((self.width) * pango.SCALE)
                 self.context.move_to(0,0)
                 self.set_color(charting.graphics.Colors.aluminium[5])
-                
+
                 self.context.show_layout(self.layout)
 
         self.explore_summary = CairoText(self.background)
@@ -202,21 +202,21 @@ A week of usage would be nice!"""))
         category_keys = sorted(categories.keys())
         categories = [categories[key] for key in category_keys]
         self.chart_category_totals.plot(category_keys, categories)
-        
+
         # Totals by weekday
         weekdays = stuff.totals(facts,
                                 lambda fact: (fact["start_time"].weekday(),
                                               fact["start_time"].strftime("%a")),
                                 lambda fact: fact['delta'].seconds / 60 / 60.0)
-        
-        weekday_keys = sorted(weekdays.keys(), key = lambda x: x[0]) #sort 
+
+        weekday_keys = sorted(weekdays.keys(), key = lambda x: x[0]) #sort
         weekdays = [weekdays[key] for key in weekday_keys] #get values in the order
         weekday_keys = [key[1] for key in weekday_keys] #now remove the weekday and keep just the abbreviated one
         self.chart_weekday_totals.plot(weekday_keys, weekdays)
 
 
         split_minutes = 5 * 60 + 30 #the mystical hamster midnight
-        
+
         # starts and ends by weekday
         by_weekday = {}
         for date, date_facts in groupby(facts, lambda fact: fact["start_time"].date()):
@@ -224,7 +224,7 @@ A week of usage would be nice!"""))
             weekday = (date_facts[0]["start_time"].weekday(),
                        date_facts[0]["start_time"].strftime("%a"))
             by_weekday.setdefault(weekday, [])
-            
+
             start_times, end_times = [], []
             for fact in date_facts:
                 start_time = fact["start_time"].time()
@@ -232,15 +232,15 @@ A week of usage would be nice!"""))
                 if fact["end_time"]:
                     end_time = fact["end_time"].time()
                     end_time = end_time.hour * 60 + end_time.minute
-                
+
                     if start_time < split_minutes:
                         start_time += 24 * 60
                     if end_time < start_time:
                         end_time += 24 * 60
-                    
+
                     start_times.append(start_time)
                     end_times.append(end_time)
-            if start_times and end_times:            
+            if start_times and end_times:
                 by_weekday[weekday].append((min(start_times), max(end_times)))
 
 
@@ -256,16 +256,16 @@ A week of usage would be nice!"""))
         weekdays = [by_weekday[key] for key in weekday_keys]
         weekday_keys = [key[1] for key in weekday_keys] # get rid of the weekday number as int
 
-        
+
         # starts and ends by category
         by_category = {}
         for date, date_facts in groupby(facts, lambda fact: fact["start_time"].date()):
             date_facts = sorted(list(date_facts), key = lambda x: x["category"])
-            
+
             for category, category_facts in groupby(date_facts, lambda x: x["category"]):
                 category_facts = list(category_facts)
                 by_category.setdefault(category, [])
-                
+
                 start_times, end_times = [], []
                 for fact in category_facts:
                     start_time = fact["start_time"]
@@ -273,7 +273,7 @@ A week of usage would be nice!"""))
                     if fact["end_time"]:
                         end_time = fact["end_time"].time()
                         end_time = end_time.hour * 60 + end_time.minute
-                        
+
                         if start_time < split_minutes:
                             start_time += 24 * 60
                         if end_time < start_time:
@@ -282,7 +282,7 @@ A week of usage would be nice!"""))
                         start_times.append(start_time)
                         end_times.append(end_time)
 
-                if start_times and end_times:            
+                if start_times and end_times:
                     by_category[category].append((min(start_times), max(end_times)))
 
         for cat in by_category:
@@ -307,7 +307,7 @@ A week of usage would be nice!"""))
         #now the factoids!
         summary = ""
 
-        # first record        
+        # first record
         if not year:
             # date format for the first record if the year has not been selected
             # Using python datetime formatting syntax. See:
@@ -321,12 +321,12 @@ A week of usage would be nice!"""))
 
         summary += _("First activity was recorded on %s.") % \
                                                      ("<b>%s</b>" % first_date)
-        
+
         # total time tracked
         total_delta = dt.timedelta(days=0)
         for fact in facts:
             total_delta += fact["delta"]
-        
+
         if total_delta.days > 1:
             human_years_str = ngettext("%(num)s year",
                                        "%(num)s years",
@@ -343,7 +343,7 @@ A week of usage would be nice!"""))
               "human_years": human_years_str,
               "working_days": ("<b>%d</b>" % (total_delta.days * 3)), # 8 should be pretty much an average working day
               "working_years": working_years_str }
-        
+
 
         # longest fact
         max_fact = None
@@ -356,10 +356,10 @@ A week of usage would be nice!"""))
             # Using python datetime formatting syntax. See:
             # http://docs.python.org/library/time.html#time.strftime
             C_("date of the longest activity", "%b %d, %Y"))
-        
+
         num_hours = max_fact["delta"].seconds / 60 / 60.0 + max_fact["delta"].days * 24
         hours = "<b>%.1f</b>" % (num_hours)
-        
+
         summary += "\n" + ngettext("Longest continuous work happened on \
 %(date)s and was %(hours)s hour.",
                                   "Longest continuous work happened on \
@@ -375,14 +375,14 @@ A week of usage would be nice!"""))
 
         early_start, early_end = dt.time(5,0), dt.time(9,0)
         late_start, late_end = dt.time(20,0), dt.time(5,0)
-        
-        
+
+
         fact_count = len(facts)
         def percent(condition):
             matches = [fact for fact in facts if condition(fact)]
             return round(len(matches) / float(fact_count) * 100)
-        
-        
+
+
         early_percent = percent(lambda fact: early_start < fact["start_time"].time() < early_end)
         late_percent = percent(lambda fact: fact["start_time"].time() > late_start or fact["start_time"].time() < late_end)
         short_percent = percent(lambda fact: fact["delta"] <= dt.timedelta(seconds = 60 * 15))
@@ -402,16 +402,16 @@ than 15 minutes you seem to be a busy bee." % ("<b>%d</b>" % short_percent))
         self.explore_summary.set_text(summary)
 
 
-        
+
     def on_year_changed(self, button):
         if self.bubbling: return
-        
+
         for child in button.parent.get_children():
             if child != button and child.get_active():
                 self.bubbling = True
                 child.set_active(False)
                 self.bubbling = False
-        
+
         self.stats(button.year)
 
 
@@ -430,8 +430,8 @@ than 15 minutes you seem to be a busy bee." % ("<b>%d</b>" % short_percent))
         else:
             self.window.destroy()
             return False
-        
+
 
 if __name__ == "__main__":
-    stats_viewer = StatsViewer() 
-    gtk.main()    
+    stats_viewer = StatsViewer()
+    gtk.main()
diff --git a/hamster/storage.py b/hamster/storage.py
index e4fe975..ebd0124 100644
--- a/hamster/storage.py
+++ b/hamster/storage.py
@@ -31,14 +31,14 @@ class Storage(object):
     def dispatch(self, event, data):
         self.parent.dispatch(event, data)
 
-    def dispatch_overwrite(self):        
+    def dispatch_overwrite(self):
         self.dispatch('new_tags_added', ())
         self.dispatch('day_updated', ())
         self.dispatch('activity_updated', ())
 
     def get_tags(self, autocomplete = None):
         return self.__get_tags(autocomplete)
-        
+
     def get_tag_ids(self, tags):
         tags, new_added = self.__get_tag_ids(tags)
         if new_added:
@@ -85,25 +85,25 @@ class Storage(object):
     def update_fact(self, fact_id, activity_name, tags, start_time, end_time):
         now = datetime.datetime.now()
         self.start_transaction()
-        
+
         fact = self.get_fact(fact_id)
         if fact:
             self.__remove_fact(fact_id)
-        
+
         result = self.__add_fact(activity_name, tags, start_time, end_time)
 
         self.end_transaction()
-        
+
         if result:
             self.dispatch('day_updated', result['start_time'])
         return result
 
     def get_activities(self, category_id = None):
         return self.__get_activities(category_id = category_id)
-    
+
     def get_autocomplete_activities(self):
         return self.__get_autocomplete_activities()
-    
+
     def get_last_activity(self):
         return self.__get_last_activity()
 
@@ -111,7 +111,7 @@ class Storage(object):
         result = self.__remove_activity(id)
         self.dispatch('activity_updated', ())
         return result
-    
+
     def remove_category(self, id):
         self.__remove_category(id)
         self.dispatch('activity_updated', ())
@@ -134,7 +134,7 @@ class Storage(object):
     def update_activity(self, id, name, category_id):
         self.__update_activity(id, name, category_id)
         self.dispatch('activity_updated', ())
-    
+
     def add_activity(self, name, category_id = -1):
         new_id = self.__add_activity(name, category_id)
         self.dispatch('activity_updated', ())
diff --git a/hamster/stuff.py b/hamster/stuff.py
index f2e1f22..b3d15cc 100644
--- a/hamster/stuff.py
+++ b/hamster/stuff.py
@@ -36,20 +36,20 @@ import os
 def format_duration(minutes, human = True):
     """formats duration in a human readable format.
     accepts either minutes or timedelta"""
-    
+
     if isinstance(minutes, dt.timedelta):
         minutes = duration_minutes(minutes)
-        
+
     if not minutes:
         if human:
             return ""
         else:
             return "00:00"
-    
+
     hours = minutes / 60
     minutes = minutes % 60
     formatted_duration = ""
-    
+
     if human:
         if minutes % 60 == 0:
             # duration in round hours
@@ -62,8 +62,8 @@ def format_duration(minutes, human = True):
             formatted_duration += _("%dh %dmin") % (hours, minutes % 60)
     else:
         formatted_duration += "%02d:%02d" % (hours, minutes)
-    
-    
+
+
     return formatted_duration
 
 def duration_minutes(duration):
@@ -75,11 +75,11 @@ def load_ui_file(name):
     from configuration import runtime
     ui = gtk.Builder()
     ui.add_from_file(os.path.join(runtime.data_dir, name))
-    return ui 
+    return ui
 
 def zero_hour(date):
     return dt.datetime.combine(date.date(), dt.time(0,0))
-    
+
 # it seems that python or something has bug of sorts, that breaks stuff for
 # japanese locale, so we have this locale from and to ut8 magic in some places
 # see bug 562298
@@ -111,14 +111,14 @@ def locale_first_weekday():
         first_weekday = int(beginning.strftime("%w"))
     except:
         logging.warn("WARNING - Failed to get first weekday from locale")
-        
+
     return first_weekday
-    
+
 class CategoryCell(gtk.CellRendererText):
     def __init__(self):
-        gtk.CellRendererText.__init__(self)        
+        gtk.CellRendererText.__init__(self)
         self.set_property('alignment', pango.ALIGN_RIGHT)
-        
+
         insensitive_color = gtk.Label().style.fg[gtk.STATE_INSENSITIVE]
         self.set_property('foreground-gdk', insensitive_color)
         self.set_property('scale', pango.SCALE_SMALL)
@@ -128,7 +128,7 @@ class CategoryCell(gtk.CellRendererText):
 insensitive_color = gtk.Label().style.fg[gtk.STATE_INSENSITIVE].to_string()
 def format_activity(name, category, description, pad_description = False):
     "returns pango markup for activity with category and description"
-    text = name    
+    text = name
     if category and category != _("Unsorted"):
         text += """ - <span color="%s" size="x-small">%s</span>""" % (insensitive_color, category)
 
@@ -138,9 +138,9 @@ def format_activity(name, category, description, pad_description = False):
             text += " " * 23
 
         text += """<span style="italic" size="small">%s</span>""" % description
-        
+
     return text
-    
+
 
 def totals(iter, keyfunc, sumfunc):
     """groups items by field described in keyfunc and counts totals using value
@@ -160,7 +160,7 @@ def totals(iter, keyfunc, sumfunc):
 def dateDict(date, prefix = ""):
     """converts date into dictionary, having prefix for all the keys"""
     res = {}
-    
+
     res[prefix+"a"] = date.strftime("%a")
     res[prefix+"A"] = date.strftime("%A")
     res[prefix+"b"] = date.strftime("%b")
@@ -182,7 +182,7 @@ def dateDict(date, prefix = ""):
     res[prefix+"y"] = date.strftime("%y")
     res[prefix+"Y"] = date.strftime("%Y")
     res[prefix+"Z"] = date.strftime("%Z")
-    
+
     for i, value in res.items():
         res[i] = locale_to_utf8(value)
 
@@ -191,7 +191,7 @@ def dateDict(date, prefix = ""):
 def escape_pango(text):
     if not text:
         return text
-    
+
     text = text.replace ("&", "&amp;")
     text = text.replace("<", "&lt;")
     text = text.replace(">", "&gt;")
@@ -200,14 +200,14 @@ def escape_pango(text):
 def figure_time(str_time):
     if not str_time or not str_time.strip():
         return None
-    
+
     # strip everything non-numeric and consider hours to be first number
     # and minutes - second number
     numbers = re.split("\D", str_time)
     numbers = filter(lambda x: x!="", numbers)
-    
+
     hours, minutes = None, None
-    
+
     if len(numbers) == 1 and len(numbers[0]) == 4:
         hours, minutes = int(numbers[0][:2]), int(numbers[0][2:])
     else:
@@ -215,7 +215,7 @@ def figure_time(str_time):
             hours = int(numbers[0])
         if len(numbers) >= 2:
             minutes = int(numbers[1])
-        
+
     if (hours is None or minutes is None) or hours > 24 or minutes > 60:
         return None #no can do
 
@@ -233,10 +233,10 @@ def parse_activity_input(text):
             self.end_time = None
             self.description = None
             self.tags = []
-            
-    
+
+
     res = InputParseResult()
-    
+
     input_parts = text.split(" ")
     if len(input_parts) > 1 and re.match('^-?\d', input_parts[0]): #look for time only if there is more
         potential_time = text.split(" ")[0]
@@ -245,20 +245,20 @@ def parse_activity_input(text):
             #if starts with minus, treat as minus delta minutes
             res.start_time = dt.datetime.now() + dt.timedelta(minutes =
                                                                 int(potential_time))
-    
+
         else:
             if potential_time.find("-") > 0:
                 potential_time, potential_end_time = potential_time.split("-", 2)
                 res.end_time = figure_time(potential_end_time)
-                
+
             res.start_time = figure_time(potential_time)
-        
+
         #remove parts that worked
         if res.start_time and potential_end_time and not res.end_time:
             res.start_time = None #scramble
         elif res.start_time:
             text = text[text.find(" ")+1:]
-    
+
     if text.find("@") > 0:
         text, res.category_name = text.split("@", 1)
         res.category_name = res.category_name.strip()
diff --git a/hamster/widgets/__init__.py b/hamster/widgets/__init__.py
index 0a82f24..63d7f55 100644
--- a/hamster/widgets/__init__.py
+++ b/hamster/widgets/__init__.py
@@ -40,26 +40,26 @@ from facttree import FactTree
 
 # handy wrappers
 def add_hint(entry, hint):
-    entry.hint = hint        
-    
+    entry.hint = hint
+
     def override_get_text(self):
         #override get text so it does not return true when hint is in!
         if self.real_get_text() == self.hint:
             return ""
         else:
             return self.real_get_text()
-        
+
     def _set_hint(self, widget, event):
         if self.get_text(): # do not mess with user entered text
-            return 
+            return
 
         self.modify_text(gtk.STATE_NORMAL, gtk.gdk.Color("gray"))
         hint_font = pango.FontDescription(gtk.Style().font_desc.to_string())
         hint_font.set_style(pango.STYLE_ITALIC)
         self.modify_font(hint_font)
-        
+
         self.set_text(self.hint)
-        
+
     def _set_normal(self, widget, event):
         self.modify_text(gtk.STATE_NORMAL, gtk.Style().fg[gtk.STATE_NORMAL])
         hint_font = pango.FontDescription(gtk.Style().font_desc.to_string())
@@ -67,7 +67,7 @@ def add_hint(entry, hint):
 
         if self.real_get_text() == self.hint:
             self.set_text("")
-            
+
     def _on_changed(self, widget):
         if self.real_get_text() == "" and self.is_focus() == False:
             self._set_hint(widget, None)
@@ -80,7 +80,7 @@ def add_hint(entry, hint):
     entry._on_changed = instancemethod(_on_changed, entry, gtk.Entry)
     entry.real_get_text = entry.get_text
     entry.get_text = instancemethod(override_get_text, entry, gtk.Entry)
-    
+
     entry.connect('focus-in-event', entry._set_normal)
     entry.connect('focus-out-event', entry._set_hint)
     entry.connect('changed', entry._on_changed)
diff --git a/hamster/widgets/activityentry.py b/hamster/widgets/activityentry.py
index c1a5ece..aceeb9e 100644
--- a/hamster/widgets/activityentry.py
+++ b/hamster/widgets/activityentry.py
@@ -38,9 +38,9 @@ class ActivityEntry(gtk.Entry):
         self.categories = None
         self.filter = None
         self.max_results = 10 # limit popup size to 10 results
-        
+
         self.popup = gtk.Window(type = gtk.WINDOW_POPUP)
-        
+
         box = gtk.ScrolledWindow()
         box.set_shadow_type(gtk.SHADOW_IN)
         box.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
@@ -53,11 +53,11 @@ class ActivityEntry(gtk.Entry):
         time_cell = gtk.CellRendererPixbuf()
         time_cell.set_property("icon-name", "appointment-new")
         time_cell.set_property("cell-background", bgcolor)
-        
+
         self.time_icon_column = gtk.TreeViewColumn("",
                                               time_cell)
         self.tree.append_column(self.time_icon_column)
-        
+
         time_cell = gtk.CellRendererText()
         time_cell.set_property("scale", 0.8)
         time_cell.set_property("cell-background", bgcolor)
@@ -73,7 +73,7 @@ class ActivityEntry(gtk.Entry):
                                                   text=1)
         self.activity_column.set_expand(True)
         self.tree.append_column(self.activity_column)
-        
+
         self.category_column = gtk.TreeViewColumn("Category",
                                                   stuff.CategoryCell(),
                                                   text=2)
@@ -85,7 +85,7 @@ class ActivityEntry(gtk.Entry):
 
         box.add(self.tree)
         self.popup.add(box)
-        
+
         self.connect("button-press-event", self._on_button_press_event)
         self.connect("key-press-event", self._on_key_press_event)
         self.connect("key-release-event", self._on_key_release_event)
@@ -106,7 +106,7 @@ class ActivityEntry(gtk.Entry):
             self.hide_popup()
             return
 
-        activity = stuff.parse_activity_input(self.filter)        
+        activity = stuff.parse_activity_input(self.filter)
         time = ''
         if activity.start_time:
             time = activity.start_time.strftime("%H:%M")
@@ -115,11 +115,11 @@ class ActivityEntry(gtk.Entry):
 
         self.time_icon_column.set_visible(activity.start_time != None and self.filter.find("@") == -1)
         self.time_column.set_visible(activity.start_time != None and self.filter.find("@") == -1)
-        
+
 
         self.category_column.set_visible(self.filter.find("@") == -1)
-        
-        
+
+
         #move popup under the widget
         alloc = self.get_allocation()
         x, y = self.get_parent_window().get_origin()
@@ -127,36 +127,36 @@ class ActivityEntry(gtk.Entry):
         self.popup.move(x + alloc.x,y + alloc.y + alloc.height)
 
         w = alloc.width
-        
+
         #TODO - this is clearly unreliable as we calculate tree row size based on our gtk entry
         self.tree.parent.set_size_request(w,(alloc.height-6) * min([result_count, self.max_results]))
         self.popup.resize(w, (alloc.height-6) * min([result_count, self.max_results]))
 
-        
+
         self.popup.show_all()
-        
+
     def complete_inline(self):
         model = self.tree.get_model()
         activity = stuff.parse_activity_input(self.filter)
         subject = self.get_text()
-        
+
         if not subject or model.iter_n_children(None) == 0:
             return
-        
+
         prefix_length = 0
-        
+
         labels = [row[0] for row in model]
         shortest = min([len(label) for label in labels])
         first = labels[0] #since we are looking for common prefix, we do not care which label we use for comparisons
-        
+
         for i in range(len(subject), shortest):
             letter_matching = all([label[i]==first[i] for label in labels])
-                
+
             if not letter_matching:
                 break
-            
+
             prefix_length +=1
-        
+
         if prefix_length:
             prefix = first[len(subject):len(subject)+prefix_length]
             self.set_text("%s%s" % (self.filter, prefix))
@@ -172,29 +172,29 @@ class ActivityEntry(gtk.Entry):
             cursor = self.get_selection_bounds()[0]
         else:
             cursor = self.get_position()
-            
+
         if self.activities and self.categories and self.filter == self.get_text().decode('utf8', 'replace')[:cursor]:
             return #same thing, no need to repopulate
 
         self.activities = self.activities or runtime.storage.get_autocomplete_activities()
         self.categories = self.categories or runtime.storage.get_category_list()
 
-        
+
         self.filter = self.get_text().decode('utf8', 'replace')[:cursor]
-        
+
         input_activity = stuff.parse_activity_input(self.filter)
-        
+
         time = ''
         if input_activity.start_time:
             time = input_activity.start_time.strftime("%H:%M")
             if input_activity.end_time:
                 time += "-%s" % input_activity.end_time.strftime("%H:%M")
-        
-        
+
+
         store = self.tree.get_model()
         if not store:
             store = gtk.ListStore(str, str, str, str)
-            self.tree.set_model(store)            
+            self.tree.set_model(store)
         store.clear()
 
         if self.filter.find("@") > 0:
@@ -213,18 +213,18 @@ class ActivityEntry(gtk.Entry):
 
                     if time: #as we also support deltas, for the time we will grab anything up to first space
                         fillable = "%s %s" % (self.filter.split(" ", 1)[0], fillable)
-        
+
                     store.append([fillable, activity['name'], activity['category'], time])
 
     def after_activity_update(self, widget, event):
         self.refresh_activities()
-        
+
     def _on_focus_out_event(self, widget, event):
         self.hide_popup()
 
     def _on_text_changed(self, widget):
         self.news = True
-        
+
 
     def _on_button_press_event(self, button, event):
         self.populate_suggestions()
@@ -250,22 +250,22 @@ class ActivityEntry(gtk.Entry):
         else:
             self.populate_suggestions()
             self.show_popup()
-            
+
             if event.keyval not in (gtk.keysyms.Delete, gtk.keysyms.BackSpace):
                 self.complete_inline()
 
-        
+
 
 
     def _on_key_press_event(self, entry, event):
 
         if event.keyval in (gtk.keysyms.Up, gtk.keysyms.Down):
             cursor = self.tree.get_cursor()
-    
+
             if not cursor or not cursor[0]:
                 self.tree.set_cursor(0)
                 return True
-            
+
             i = cursor[0][0]
 
             if event.keyval == gtk.keysyms.Up:
@@ -275,13 +275,13 @@ class ActivityEntry(gtk.Entry):
 
             # keep it in the sane borders
             i = min(max(i, 0), len(self.tree.get_model()) - 1)
-            
+
             self.tree.set_cursor(i)
             self.tree.scroll_to_cell(i, use_align = True, row_align = 0.4)
             return True
         else:
             return False
-        
+
     def _on_tree_button_press_event(self, tree, event):
         model, iter = tree.get_selection().get_selected()
         value = model.get_value(iter, 0)
diff --git a/hamster/widgets/dateinput.py b/hamster/widgets/dateinput.py
index 46ea201..362674b 100644
--- a/hamster/widgets/dateinput.py
+++ b/hamster/widgets/dateinput.py
@@ -33,7 +33,7 @@ class DateInput(gtk.Entry):
 
     def __init__(self, date = None):
         gtk.Entry.__init__(self)
-        
+
         self.set_width_chars(12) #12 is enough for 12-oct-2009, which is verbose
         self.date = date
         if date:
@@ -86,21 +86,21 @@ class DateInput(gtk.Entry):
 
     def _on_text_changed(self, widget):
         self.news = True
-        
+
     def __on_day_selected_double_click(self, calendar):
         self.prev_cal_day = None
         self._on_day_selected(calendar) #forward
-        
+
     def _on_cal_button_press_event(self, calendar, event):
         self.prev_cal_day = calendar.get_date()[2]
 
     def _on_day_selected(self, calendar):
         if self.popup.get_property("visible") == False:
             return
-        
+
         if self.prev_cal_day == calendar.get_date()[2]:
             return
-        
+
         cal_date = calendar.get_date()
 
         self.date = dt.date(cal_date[0], cal_date[1] + 1, cal_date[2])
@@ -110,23 +110,23 @@ class DateInput(gtk.Entry):
         if self.news:
             self.emit("date-entered")
             self.news = False
-        
-    
+
+
     def show_popup(self):
         window = self.get_parent_window()
         x, y= window.get_origin()
 
         alloc = self.get_allocation()
-        
+
         date = self._figure_date(self.get_text())
         if date:
-            self.prev_cal_day = date.day #avoid 
+            self.prev_cal_day = date.day #avoid
             self.date_calendar.select_month(date.month-1, date.year)
             self.date_calendar.select_day(date.day)
-        
+
         self.popup.move(x + alloc.x,y + alloc.y + alloc.height)
         self.popup.show_all()
-    
+
     def _on_focus_in_event(self, entry, event):
         self.show_popup()
 
@@ -139,7 +139,7 @@ class DateInput(gtk.Entry):
         if self.news:
             self.emit("date-entered")
             self.news = False
-    
+
     def _on_key_press_event(self, entry, event):
         if self.popup.get_property("visible"):
             cal_date = self.date_calendar.get_date()
@@ -165,13 +165,13 @@ class DateInput(gtk.Entry):
         else:
             self.popup.hide()
             return False
-        
+
         if enter_pressed:
             self.prev_cal_day = "borken"
         else:
             #prev_cal_day is our only way of checking that date is right
-            self.prev_cal_day = date.day 
-        
+            self.prev_cal_day = date.day
+
         self.date_calendar.select_month(date.month, date.year)
         self.date_calendar.select_day(date.day)
         return True
diff --git a/hamster/widgets/dayline.py b/hamster/widgets/dayline.py
index 1d73219..03acf4c 100644
--- a/hamster/widgets/dayline.py
+++ b/hamster/widgets/dayline.py
@@ -32,8 +32,8 @@ class DayLine(graphics.Area):
     def get_value_at_pos(self, x):
         """returns mapped value at the coordinates x,y"""
         return x / float(self.width / self.view_minutes)
-    
-    
+
+
     #normal stuff
     def __init__(self):
         graphics.Area.__init__(self)
@@ -55,7 +55,7 @@ class DayLine(graphics.Area):
 
         self.range_start = None
         self.range_start_int = None #same date just expressed as integer so we can interpolate it  (a temporar hack)
-        
+
         self.in_motion = False
         self.days = []
 
@@ -70,11 +70,11 @@ class DayLine(graphics.Area):
         self.facts = day_facts
         if self.facts:
             self.days.append(self.facts[0]["start_time"].date())
-        
+
         start_time = highlight[0] - dt.timedelta(minutes = highlight[0].minute) - dt.timedelta(hours = 10)
-        
+
         start_time_int = int(time.mktime(start_time.timetuple()))
-        
+
         if self.range_start:
             self.range_start = start_time
             self.scroll_to_range_start()
@@ -84,16 +84,16 @@ class DayLine(graphics.Area):
 
 
         self.highlight = highlight
-        
+
         self.show()
-        
+
         self.redraw_canvas()
 
 
     def on_button_release(self, area, event):
         if not self.drag_start:
             return
-        
+
         self.drag_start, self.move_type = None, None
 
         if event.state & gtk.gdk.BUTTON1_MASK:
@@ -109,13 +109,13 @@ class DayLine(graphics.Area):
 
         if self.on_time_changed:
             self.on_time_changed(start_time, end_time)
-    
+
     def get_time(self, pixels):
         minutes = self.get_value_at_pos(x = pixels)
-        return dt.datetime.fromtimestamp(self.range_start_int) + dt.timedelta(minutes = minutes) 
-    
+        return dt.datetime.fromtimestamp(self.range_start_int) + dt.timedelta(minutes = minutes)
+
+
 
-        
     def draw_cursor(self, area, event):
         if event.is_hint:
             x, y, state = event.window.get_pointer()
@@ -125,10 +125,10 @@ class DayLine(graphics.Area):
             state = event.state
 
         mouse_down = state & gtk.gdk.BUTTON1_MASK
-        
+
         highlight_start = self.highlight_start + self.graph_x
         highlight_end = self.highlight_end + self.graph_x
-            
+
         if highlight_start != None:
             start_drag = 10 > (highlight_start - x) > -1
 
@@ -157,7 +157,7 @@ class DayLine(graphics.Area):
                     self.move_type = "scale_drag"
                     self.drag_start_time = dt.datetime.fromtimestamp(self.range_start_int)
 
-            
+
             if mouse_down and self.drag_start:
                 start, end = 0, 0
                 if self.move_type and self.move_type != "scale_drag":
@@ -172,9 +172,9 @@ class DayLine(graphics.Area):
                     elif self.move_type == "move":
                         width = self.highlight_end - self.highlight_start
                         start = x - self.drag_start + self.graph_x
-                        
+
                         end = start + width
-    
+
                     if end - start > 1:
                         self.highlight = (self.get_time(start), self.get_time(end))
                         self.redraw_canvas()
@@ -193,8 +193,8 @@ class DayLine(graphics.Area):
                 area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR))
             else:
                 area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW))
-                
-        
+
+
     def _minutes_from_start(self, date):
             delta = (date - dt.datetime.fromtimestamp(self.range_start_int))
             return delta.days * 24 * 60 + delta.seconds / 60
@@ -204,7 +204,7 @@ class DayLine(graphics.Area):
         self.animate(self, {"range_start_int": int(time.mktime(self.range_start.timetuple())),
                             "tweenType": graphics.Easing.Expo.easeOut,
                             "tweenTime": 0.4})
-        
+
     def on_expose(self):
         # check if maybe we are approaching day boundaries and should ask for
         # more data!
@@ -223,13 +223,13 @@ class DayLine(graphics.Area):
 
         context = self.context
         #TODO - use system colors and fonts
- 
+
         context.set_line_width(1)
 
         #we will buffer 4 hours to both sides so partial labels also appear
-        range_end = now + dt.timedelta(hours = 12 + 2 * 4)        
+        range_end = now + dt.timedelta(hours = 12 + 2 * 4)
         self.graph_x = -self.width / 3 #so x moves one third out of screen
-        
+
         pixels_in_minute = self.width / self.view_minutes
 
         minutes = self._minutes_from_start(range_end)
@@ -239,17 +239,17 @@ class DayLine(graphics.Area):
         graph_height = self.height - 10
         graph_y2 = graph_y + graph_height
 
-        
+
         # graph area
         self.fill_area(0, graph_y - 1, self.width, graph_height, (1,1,1))
 
         context.save()
         context.translate(self.graph_x, self.graph_y)
-    
+
         #bars
         for fact in self.facts:
             start_minutes = self._minutes_from_start(fact["start_time"])
-            
+
             if fact["end_time"]:
                 end_minutes = self._minutes_from_start(fact["end_time"])
             else:
@@ -257,7 +257,7 @@ class DayLine(graphics.Area):
                     end_minutes = self._minutes_from_start(dt.datetime.now())
                 else:
                     end_minutes = start_minutes
-            
+
             if end_minutes * pixels_in_minute > 0 and \
                 start_minutes * pixels_in_minute + self.graph_x < self.width:
                     context.set_source_rgba(0.86, 0.86, 0.86, 0.5)
@@ -276,14 +276,14 @@ class DayLine(graphics.Area):
                     self.context.line_to(round(end_minutes * pixels_in_minute) + 0.5, graph_y2)
                     context.stroke()
 
-        
-        
+
+
         #time scale
         context.set_source_rgb(0, 0, 0)
         self.layout.set_width(-1)
         for i in range(minutes):
             label_time = (now + dt.timedelta(minutes=i))
-            
+
             if label_time.minute == 0:
                 context.set_source_rgb(0.8, 0.8, 0.8)
                 self.context.move_to(round(i * pixels_in_minute) + 0.5, graph_y2 - 15)
@@ -294,9 +294,9 @@ class DayLine(graphics.Area):
                 self.context.move_to(round(i * pixels_in_minute) + 0.5, graph_y2 - 5)
                 self.context.line_to(round(i * pixels_in_minute) + 0.5, graph_y2)
                 context.stroke()
-                
-                
-                
+
+
+
             if label_time.minute == 0 and label_time.hour % 2 == 0:
                 if label_time.hour == 0:
                     context.set_source_rgb(0.8, 0.8, 0.8)
@@ -309,12 +309,12 @@ class DayLine(graphics.Area):
                 context.set_source_rgb(0.4, 0.4, 0.4)
                 self.layout.set_markup(label_minutes)
                 label_w, label_h = self.layout.get_pixel_size()
-                
-                context.move_to(round(i * pixels_in_minute) + 2, graph_y2 - label_h - 8)                
+
+                context.move_to(round(i * pixels_in_minute) + 2, graph_y2 - label_h - 8)
 
                 context.show_layout(self.layout)
         context.stroke()
-        
+
         #highlight rectangle
         if self.highlight:
             self.highlight_start = round(self._minutes_from_start(self.highlight[0]) * pixels_in_minute)
@@ -338,17 +338,17 @@ class DayLine(graphics.Area):
             self.context.line_to(self.highlight_end + 0.5, graph_y + graph_height)
             context.stroke()
 
-        context.restore()            
+        context.restore()
 
         #and now put a frame around the whole thing
         context.set_source_rgb(0.7, 0.7, 0.7)
         context.rectangle(0, graph_y-0.5, self.width - 0.5, graph_height)
         context.stroke()
-        
+
         if self.move_type == "move" and (self.highlight_start + self.graph_x <= 0 or self.highlight_end + self.graph_x >= self.width):
             if self.highlight_start + self.graph_x <= 0:
                 self.range_start = self.range_start - dt.timedelta(minutes=30)
             if self.highlight_end + self.graph_x >= self.width:
                 self.range_start = self.range_start + dt.timedelta(minutes=30)
-            
+
             self.scroll_to_range_start()
diff --git a/hamster/widgets/facttree.py b/hamster/widgets/facttree.py
index d395717..7521384 100644
--- a/hamster/widgets/facttree.py
+++ b/hamster/widgets/facttree.py
@@ -28,13 +28,13 @@ import pango
 
 def parent_painter(column, cell, model, iter):
     cell_text = model.get_value(iter, 1)
-    
+
     if model.get_value(iter, 6) is None:
         if model.get_path(iter) == (0,):
             text = '<span weight="heavy">%s</span>' % cell_text
         else:
             text = '<span weight="heavy" rise="-20000">%s</span>' % cell_text
-            
+
         cell.set_property('markup', text)
 
     else:
@@ -45,7 +45,7 @@ def parent_painter(column, cell, model, iter):
         markup = stuff.format_activity(activity_name,
                                        category,
                                        description,
-                                       pad_description = True)            
+                                       pad_description = True)
         cell.set_property('markup', markup)
 
 def duration_painter(column, cell, model, iter):
@@ -76,10 +76,10 @@ class FactTree(gtk.TreeView):
         "edit-clicked": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, )),
         "double-click": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, ))
     }
-    
+
     def __init__(self):
         gtk.TreeView.__init__(self)
-        
+
         self.set_headers_visible(False)
         self.set_show_expanders(False)
 
@@ -101,7 +101,7 @@ class FactTree(gtk.TreeView):
         tagColumn = gtk.TreeViewColumn("", tag_cell, data=6)
         tagColumn.set_expand(True)
         self.append_column(tagColumn)
-        
+
 
         # duration
         timeColumn = gtk.TreeViewColumn()
@@ -121,10 +121,10 @@ class FactTree(gtk.TreeView):
         self.connect("key-press-event", self._on_key_pressed)
 
         self.show()
-    
+
     def clear(self):
         self.store_model.clear()
-        
+
     def add_fact(self, fact, parent = None):
         duration = stuff.duration_minutes(fact["delta"]) / 60
 
@@ -144,7 +144,7 @@ class FactTree(gtk.TreeView):
 
     def add_group(self, group_label, facts):
         total = sum([stuff.duration_minutes(fact["delta"]) for fact in facts])
-        
+
         # adds group of facts with the given label
         group_row = self.store_model.append(None,
                                     [-1,
@@ -154,7 +154,7 @@ class FactTree(gtk.TreeView):
                                      "",
                                      "",
                                      None])
-        
+
         for fact in facts:
             self.add_fact(fact, group_row)
 
@@ -166,7 +166,7 @@ class FactTree(gtk.TreeView):
     def attach_model(self):
         self.set_model(self.store_model)
         self.expand_all()
-        
+
     def get_selected_fact(self):
         selection = self.get_selection()
         (model, iter) = selection.get_selected()
@@ -177,11 +177,11 @@ class FactTree(gtk.TreeView):
         # a hackish solution to make edit icon keyboard accessible
         pointer = event.window.get_pointer() # x, y, flags
         path = self.get_path_at_pos(pointer[0], pointer[1]) #column, innerx, innery
-        
+
         if path and path[1] == self.edit_column:
             self.emit("edit-clicked", self.get_selected_fact())
             return True
-        
+
         return False
 
     def _on_row_activated(self, tree, path, column):
@@ -197,6 +197,5 @@ class FactTree(gtk.TreeView):
               and event.state & gtk.gdk.CONTROL_MASK):
             self.emit("edit-clicked", self.get_selected_fact())
             return True
-            
+
         return False
-            
\ No newline at end of file
diff --git a/hamster/widgets/reportchooserdialog.py b/hamster/widgets/reportchooserdialog.py
index 8becd86..e61cea7 100644
--- a/hamster/widgets/reportchooserdialog.py
+++ b/hamster/widgets/reportchooserdialog.py
@@ -33,7 +33,7 @@ class ReportChooserDialog(gtk.Dialog):
     }
     def __init__(self):
         gtk.Dialog.__init__(self)
-        
+
 
         self.dialog = gtk.FileChooserDialog(title = _("Save report - Time Tracker"),
                                             parent = None,
@@ -81,7 +81,7 @@ class ReportChooserDialog(gtk.Dialog):
         filter.set_name("All files")
         filter.add_pattern("*")
         self.dialog.add_filter(filter)
-        
+
 
     def show(self, start_date, end_date):
         #set suggested name to something readable, replace backslashes with dots
@@ -89,15 +89,15 @@ class ReportChooserDialog(gtk.Dialog):
         filename = "Time track %s - %s." % (start_date.strftime("%x").replace("/", "."),
                                            end_date.strftime("%x").replace("/", "."))
         self.dialog.set_current_name(filename)
-        
+
         response = self.dialog.run()
-        
+
         if response != gtk.RESPONSE_OK:
             self.emit("report-chooser-closed")
             self.dialog.destroy()
         else:
             self.on_save_button_clicked()
-        
+
 
     def present(self):
         self.dialog.present()
@@ -109,13 +109,13 @@ class ReportChooserDialog(gtk.Dialog):
         if self.dialog.get_filter() in self.filters:
             format = self.filters[self.dialog.get_filter()]
         path = self.dialog.get_filename()
-        
+
         # append correct extension if it is missing
         # TODO - proper way would be to change extension on filter change
         # only pointer in web is http://www.mail-archive.com/pygtk daa com au/msg08740.html
         if path.endswith(".%s" % format) == False:
             path = "%s.%s" % (path.rstrip("."), format)
-        
+
         categories = []
 
         # format, path, start_date, end_date
diff --git a/hamster/widgets/tags.py b/hamster/widgets/tags.py
index 0320249..945b393 100644
--- a/hamster/widgets/tags.py
+++ b/hamster/widgets/tags.py
@@ -35,20 +35,20 @@ class TagsEntry(gtk.Entry):
         self.tags = None
         self.filter = None # currently applied filter string
         self.filter_tags = [] #filtered tags
-        
+
         self.popup = gtk.Window(type = gtk.WINDOW_POPUP)
         self.scroll_box = gtk.ScrolledWindow()
         self.scroll_box.set_shadow_type(gtk.SHADOW_IN)
         self.scroll_box.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
         viewport = gtk.Viewport()
         viewport.set_shadow_type(gtk.SHADOW_NONE)
-        
+
         self.tag_box = TagBox()
         self.tag_box.connect("tag-selected", self.on_tag_selected)
         self.tag_box.connect("tag-unselected", self.on_tag_unselected)
         self.tag_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(65536.0,65536.0,65536.0))
 
-        
+
         viewport.add(self.tag_box)
         self.scroll_box.add(viewport)
         self.popup.add(self.scroll_box)
@@ -72,7 +72,7 @@ class TagsEntry(gtk.Entry):
     def on_tag_selected(self, tag_box, tag):
         tags = self.get_tags()
         tags.append(tag)
-        
+
         self.tag_box.selected_tags = tags
 
         self.set_text(", ".join(tags))
@@ -82,13 +82,13 @@ class TagsEntry(gtk.Entry):
         tags = self.get_tags()
         while tag in tags: #it could be that dear user is mocking us and entering same tag over and over again
             tags.remove(tag)
-            
+
         self.tag_box.selected_tags = tags
 
         self.set_text(", ".join(tags))
         self.set_position(len(self.get_text()))
-        
-        
+
+
     def hide_popup(self):
         self.popup.hide()
 
@@ -96,7 +96,7 @@ class TagsEntry(gtk.Entry):
         if not self.filter_tags:
             self.popup.hide()
             return
-        
+
         alloc = self.get_allocation()
         x, y = self.get_parent_window().get_origin()
 
@@ -105,14 +105,14 @@ class TagsEntry(gtk.Entry):
         w = alloc.width
 
         height = self.tag_box.count_height(w)
-        
+
         self.scroll_box.set_size_request(w, height)
         self.popup.resize(w, height)
         self.popup.show_all()
 
-        
+
     def complete_inline(self):
-        return         
+        return
 
     def refresh_activities(self):
         # scratch activities and categories so that they get repopulated on demand
@@ -123,17 +123,17 @@ class TagsEntry(gtk.Entry):
         self.tags = self.tags or [tag["name"] for tag in runtime.storage.get_tags(autocomplete = True)]
 
         cursor_tag = self.get_cursor_tag()
-            
+
         self.filter = cursor_tag
 
         entered_tags = self.get_tags()
         self.tag_box.selected_tags = entered_tags
-        
+
         self.filter_tags = [tag for tag in self.tags if (tag or "").lower().startswith((self.filter or "").lower())]
-        
+
         self.tag_box.draw(self.filter_tags)
-        
-        
+
+
 
     def _on_focus_out_event(self, widget, event):
         self.hide_popup()
@@ -159,11 +159,11 @@ class TagsEntry(gtk.Entry):
         else:
             self.populate_suggestions()
             self.show_popup()
-            
+
             if event.keyval not in (gtk.keysyms.Delete, gtk.keysyms.BackSpace):
                 self.complete_inline()
 
-    
+
     def get_cursor_tag(self):
         #returns the tag on which the cursor is on right now
         if self.get_selection_bounds():
@@ -185,7 +185,7 @@ class TagsEntry(gtk.Entry):
             cursor = self.get_selection_bounds()[0]
         else:
             cursor = self.get_position()
-        
+
         self.set_text(", ".join(tags))
         self.set_position(cursor + len(new_tag)-len(old_tag)) # put the cursor back
 
@@ -216,7 +216,7 @@ class TagBox(graphics.Area):
         self.tags = []
         self.selected_tags = []
         graphics.Area.__init__(self)
-        
+
         self.font_size = 10 #override default font size
 
         if self.interactive:
@@ -228,9 +228,9 @@ class TagBox(graphics.Area):
             self.hover_tag = regions[0]
         else:
             self.hover_tag = None
-        
+
         self.redraw_canvas()
-    
+
     def on_tag_click(self, widget, regions):
         tag = regions[0]
         if tag in self.selected_tags:
@@ -241,11 +241,11 @@ class TagBox(graphics.Area):
             self.emit("tag-selected", tag)
 
         self.redraw_canvas()
-        
+
     def draw(self, tags):
         """Draw chart with given data"""
         self.tags = tags
-        self.show()        
+        self.show()
         self.redraw_canvas()
 
     def tag_size(self, label):
@@ -275,10 +275,10 @@ class TagBox(graphics.Area):
             if cur_x + w >= width - 5:  #if we do not fit, we wrap
                 cur_x = 5
                 cur_y += h + 6
-            
+
             cur_x += w + 8 #some padding too, please
         return cur_y + h + 6
-    
+
     def on_expose(self):
         cur_x, cur_y = 4, 4
         for tag in self.tags:
@@ -286,21 +286,21 @@ class TagBox(graphics.Area):
             if cur_x + w >= self.width - 5:  #if we do not fit, we wrap
                 cur_x = 5
                 cur_y += h + 6
-            
+
             if tag in self.selected_tags:
                 color = (242, 229, 97)
             elif tag == self.hover_tag:
                 color = (252, 248, 204)
             else:
                 color = (241, 234, 170)
-        
+
             Tag(self.context,
                 self.layout,
                 True,
                 tag,
                 color,
-                gtk.gdk.Rectangle(cur_x, cur_y, self.width - cur_x, self.height - cur_y))    
-            
+                gtk.gdk.Rectangle(cur_x, cur_y, self.width - cur_x, self.height - cur_y))
+
             if self.interactive:
                 self.register_mouse_region(cur_x, cur_y, cur_x + w, cur_y + h, tag)
 
@@ -311,33 +311,33 @@ class TagBox(graphics.Area):
 # wish he could write tutorials
 class TagCellRenderer(gtk.GenericCellRenderer):
     __gproperties__ = {
-        "data": (gobject.TYPE_PYOBJECT, "Data", "Data", gobject.PARAM_READWRITE), 
+        "data": (gobject.TYPE_PYOBJECT, "Data", "Data", gobject.PARAM_READWRITE),
     }
-   
+
     def __init__(self):
         gtk.GenericCellRenderer.__init__(self)
         self.height = 0
         self.width = None
         self.data = None
-        
+
         self._font = pango.FontDescription(gtk.Style().font_desc.to_string())
         self._font_size = 10
         self.layout = None
-    
+
     def font_size(self):
         return self._font_size
 
     def set_font_size(self, val):
         self._font_size = val
         self._font.set_size(pango.SCALE * self._font_size)
-        
-    
+
+
     def do_set_property (self, pspec, value):
         setattr (self, pspec.name, value)
-        
+
     def do_get_property (self, pspec):
         return getattr (self, pspec.name)
-                
+
 
     def tag_size(self, label):
         text_w, text_h = self.set_text(label)
@@ -355,7 +355,7 @@ class TagCellRenderer(gtk.GenericCellRenderer):
         if not self.data: return
 
         self.width = cell_area.width
-        
+
         context = window.cairo_create()
 
         if isinstance(self.data, dict):
@@ -366,25 +366,25 @@ class TagCellRenderer(gtk.GenericCellRenderer):
         x, y, width, h = cell_area
 
         context.translate(x, y)
-        
+
         if not self.layout:
             self.layout = context.create_layout()
         self.layout.set_font_description(self._font)
-        
+
         cur_x, cur_y = 4, 2
         for tag in tags:
             w, h = self.tag_size(tag)
             if cur_x + w >= self.width - 5:  #if we do not fit, we wrap
                 cur_x = 5
                 cur_y += h + 6
-            
+
             Tag(context,
                 self.layout,
                 True,
                 tag,
                 None,
-                gtk.gdk.Rectangle(cur_x, cur_y, self.width - cur_x, self.height - cur_y))    
-            
+                gtk.gdk.Rectangle(cur_x, cur_y, self.width - cur_x, self.height - cur_y))
+
 
             cur_x += w + 6 #some padding too, please
 
@@ -420,20 +420,20 @@ class TagCellRenderer(gtk.GenericCellRenderer):
                 if cur_x + w >= self.width - 5:  #if we do not fit, we wrap
                     cur_x = 5
                     cur_y += h + 6
-                
+
                 cur_x += w + 6 #some padding too, please
 
             cur_y += h + 3
-    
+
             self.height = cur_y # TODO - this should actually trigger whole tree redraw if heights do not match
-        
+
         return (0, 0, min_width, self.height)
-    
+
 
 class Tag(object):
     def __init__(self, context, layout, render_now = False, label = None, color = None, rect = None):
         self.font_size = 10
-        
+
         if not context:
             render_now = False
         else:
@@ -441,10 +441,10 @@ class Tag(object):
             self.layout = layout
 
         self.x, self.y, self.width, self.height = rect.x, rect.y, rect.width, rect.height
-        
+
         if not render_now:
             return
-        
+
         self.label = label
         self.color = color or (241, 234, 170)
 
@@ -484,9 +484,9 @@ class Tag(object):
         if x - round(x) != 0.5: x += 0.5
         if y - round(y) != 0.5: y += 0.5
 
-        w, h = self.tag_size(label)            
+        w, h = self.tag_size(label)
         corner = h / 3
-        
+
         self.context.move_to(x, y + corner)
         self.context.line_to(x + corner, y)
         self.context.line_to(x + w, y)
@@ -494,7 +494,7 @@ class Tag(object):
         self.context.line_to(x + corner, y + h)
         self.context.line_to(x, y + h - corner)
         self.context.line_to(x, y + corner)
-        
+
         self.set_color(color)
         self.context.fill_preserve()
         self.set_color((180, 180, 180))
@@ -510,7 +510,7 @@ class Tag(object):
 
         #self.layout.set_width((self.width) * pango.SCALE)
         self.context.move_to(x + 12,y)
-        
+
         self.set_color((30, 30, 30))
         self.context.show_layout(self.layout)
 
diff --git a/hamster/widgets/timeinput.py b/hamster/widgets/timeinput.py
index 7dbffed..f45168d 100644
--- a/hamster/widgets/timeinput.py
+++ b/hamster/widgets/timeinput.py
@@ -78,21 +78,21 @@ class TimeInput(gtk.Entry):
     def set_time(self, time):
         self.time = time
         self.set_text(self._format_time(time))
-        
+
     def _on_text_changed(self, widget):
         self.news = True
-        
+
     def figure_time(self, str_time):
         if not str_time:
             return self.time
-        
+
         # strip everything non-numeric and consider hours to be first number
         # and minutes - second number
         numbers = re.split("\D", str_time)
         numbers = filter(lambda x: x!="", numbers)
-        
+
         hours, minutes = None, None
-        
+
         if len(numbers) == 1 and len(numbers[0]) == 4:
             hours, minutes = int(numbers[0][:2]), int(numbers[0][2:])
         else:
@@ -100,10 +100,10 @@ class TimeInput(gtk.Entry):
                 hours = int(numbers[0])
             if len(numbers) >= 2:
                 minutes = int(numbers[1])
-            
+
         if (hours is None or minutes is None) or hours > 24 or minutes > 60:
             return self.time #no can do
-    
+
         return dt.datetime.now().replace(hour = hours, minute = minutes,
                                          second = 0, microsecond = 0)
 
@@ -111,15 +111,15 @@ class TimeInput(gtk.Entry):
     def _select_time(self, time_text):
         #convert forth and back so we have text formated as we want
         time = self.figure_time(time_text)
-        time_text = self._format_time(time) 
-        
+        time_text = self._format_time(time)
+
         self.set_text(time_text)
         self.set_position(len(time_text))
         self.popup.hide()
         if self.news:
             self.emit("time-entered")
             self.news = False
-    
+
     def get_time(self):
         self.time = self.figure_time(self.get_text())
         self.set_text(self._format_time(self.time))
@@ -128,10 +128,10 @@ class TimeInput(gtk.Entry):
     def _format_time(self, time):
         if time is None:
             return None
-        
+
         #return time.strftime("%I:%M%p").lstrip("0").lower()
         return time.strftime("%H:%M").lower()
-    
+
 
     def _on_focus_in_event(self, entry, event):
         self.show_popup()
@@ -144,41 +144,41 @@ class TimeInput(gtk.Entry):
         if self.news:
             self.emit("time-entered")
             self.news = False
-        
+
 
     def show_popup(self):
         focus_time = self.figure_time(self.get_text())
-        
+
         hours = gtk.ListStore(gobject.TYPE_STRING)
-        
+
         # populate times
         i_time = self.start_time or dt.datetime(1900, 1, 1, 0, 0)
-        
+
         if focus_time and focus_time < i_time:
             focus_time += dt.timedelta(days = 1)
-        
+
         if self.start_time:
             end_time = i_time + dt.timedelta(hours = 12)
             i_time += dt.timedelta(minutes = 15)
         else:
             end_time = i_time + dt.timedelta(hours = 24)
-        
+
         i, focus_row = 0, None
-        
+
         while i_time < end_time:
             row_text = self._format_time(i_time)
             if self.start_time:
                 delta = (i_time - self.start_time).seconds / 60
                 delta_text = format_duration(delta)
-                
+
                 row_text += " (%s)" % delta_text
 
             hours.append([row_text])
-            
+
             if focus_time and i_time <= focus_time <= i_time + \
                                                      dt.timedelta(minutes = 30):
                 focus_row = i
-            
+
             if self.start_time:
                 i_time += dt.timedelta(minutes = 15)
             else:
@@ -186,13 +186,13 @@ class TimeInput(gtk.Entry):
 
             i += 1
 
-        self.time_tree.set_model(hours)        
+        self.time_tree.set_model(hours)
 
         #focus on row
         if focus_row != None:
             self.time_tree.set_cursor(focus_row)
             self.time_tree.scroll_to_cell(focus_row, use_align = True, row_align = 0.4)
-        
+
         #move popup under the widget
         alloc = self.get_allocation()
         w = alloc.width
@@ -206,19 +206,19 @@ class TimeInput(gtk.Entry):
         self.popup.move(x + alloc.x,y + alloc.y + alloc.height)
         self.popup.show_all()
 
-    
+
     def _on_time_tree_button_press_event(self, tree, event):
         model, iter = tree.get_selection().get_selected()
         time = model.get_value(iter, 0)
         self._select_time(time)
-        
-        
+
+
     def _on_key_press_event(self, entry, event):
         cursor = self.time_tree.get_cursor()
 
         if not cursor or not cursor[0]:
             return
-        
+
         i = cursor[0][0]
 
         if event.keyval == gtk.keysyms.Up:
@@ -227,7 +227,7 @@ class TimeInput(gtk.Entry):
             i+=1
         elif (event.keyval == gtk.keysyms.Return or
               event.keyval == gtk.keysyms.KP_Enter):
-            
+
             if self.popup.get_property("visible"):
                 self._select_time(self.time_tree.get_model()[i][0])
             else:
@@ -238,13 +238,13 @@ class TimeInput(gtk.Entry):
             #any kind of other input
             self.popup.hide()
             return False
-        
+
         # keep it in the sane borders
         i = min(max(i, 0), len(self.time_tree.get_model()) - 1)
-        
+
         self.time_tree.set_cursor(i)
         self.time_tree.scroll_to_cell(i, use_align = True, row_align = 0.4)
         return True
 
 
-    
+
diff --git a/hamster/widgets/timeline.py b/hamster/widgets/timeline.py
index 982358c..cab33af 100644
--- a/hamster/widgets/timeline.py
+++ b/hamster/widgets/timeline.py
@@ -35,24 +35,24 @@ MONTH = dt.timedelta(30)
 
 class TimeLine(graphics.Area):
     """this widget is kind of half finished"""
-    
+
     def __init__(self):
         graphics.Area.__init__(self)
         self.start_time, self.end_time = None, None
         self.facts = []
         self.day_start = GconfStore().get_day_start()
         self.first_weekday = stuff.locale_first_weekday()
-        
+
         self.minor_tick = None
-        
+
         self.tick_totals = []
-        
+
         self.bar_color = "#ccc"
 
-        
+
     def draw(self, facts, start_date, end_date):
         self.facts = facts
-        
+
         if start_date > end_date:
             start_date, end_date = end_date, start_date
 
@@ -65,7 +65,7 @@ class TimeLine(graphics.Area):
             if facts:
                 fact_start_time = facts[0]["start_time"]
                 fact_end_time = facts[-1]["start_time"] + facts[-1]["delta"]
-    
+
             self.start_time = min([start_time, fact_start_time])
             self.end_time = max([end_time, fact_end_time])
 
@@ -77,14 +77,14 @@ class TimeLine(graphics.Area):
             if facts:
                 fact_start_time = dt.datetime.combine(facts[0]["date"], dt.time())
                 fact_end_time = dt.datetime.combine(facts[-1]["date"], dt.time())
-    
+
             self.start_time = min([start_time, fact_start_time])
             self.end_time = max([end_time, fact_end_time])
 
 
 
         days = (self.end_time - self.start_time).days
-        
+
 
         # determine fraction and do addittional start time move
         if days > 125: # about 4 month -> show per month
@@ -108,7 +108,7 @@ class TimeLine(graphics.Area):
             self.minor_tick = dt.timedelta(seconds = 60 * 60)
 
         self.count_hours()
-        
+
         self.redraw_canvas()
 
 
@@ -119,7 +119,7 @@ class TimeLine(graphics.Area):
         graph_x = 2
         graph_width = self.width - graph_x - 2
 
-        
+
         total_minutes = stuff.duration_minutes(self.end_time - self.start_time)
         bar_width = float(graph_width) / len(self.tick_totals)
 
@@ -131,16 +131,16 @@ class TimeLine(graphics.Area):
             major_step = dt.timedelta(seconds = 60 * 60)
         else:
             major_step = dt.timedelta(days=1)
-        
+
         x = graph_x
         major_tick_step = graph_width / (total_minutes / float(stuff.duration_minutes(major_step)))
         current_time = self.start_time
-        
+
 
         def first_weekday(date):
             return (date.weekday() + 1 - self.first_weekday) % 7 == 0
 
-        
+
         # calculate position of each bar
         # essentially we care more about the exact 1px gap between bars than about the bar width
         # so after each iteration, we adjust the bar width
@@ -148,7 +148,7 @@ class TimeLine(graphics.Area):
         exes = {}
         adapted_bar_width = bar_width
         for i, (current_time, total) in enumerate(self.tick_totals):
-            
+
             # move the x bit further when ticks kick in
             if (major_step < DAY and current_time.time() == dt.time(0,0)) \
                or (self.minor_tick == DAY and first_weekday(current_time)) \
@@ -159,7 +159,7 @@ class TimeLine(graphics.Area):
             exes[current_time] = (x, round(adapted_bar_width)) #saving those as getting pixel precision is not an exact science
             x = round(x + adapted_bar_width)
             adapted_bar_width = (self.width - x) / float(max(len(self.tick_totals) - i - 1, 1))
-        
+
 
 
 
@@ -168,7 +168,7 @@ class TimeLine(graphics.Area):
             self.set_color(color)
             self.context.line_to(round(x) + 0.5, self.height)
             self.context.stroke()
-            
+
         def somewhere_in_middle(time, color):
             # draws line somewhere in middle of the minor tick
             left_index = exes.keys()[bisect(exes.keys(), time) - 1]
@@ -176,17 +176,17 @@ class TimeLine(graphics.Area):
             adjustment = stuff.duration_minutes(time - left_index) / float(stuff.duration_minutes(self.minor_tick))
             x, width = exes[left_index]
             line(x + round(width * adjustment) - 1, color)
-        
-        
+
+
         # mark tick lines
         current_time = self.start_time
         while current_time < self.end_time:
             current_time += major_step
             x += major_tick_step
-            
+
             if current_time >= self.end_time: # TODO - fix the loop so we do not have to break
                 break
-            
+
             if major_step < DAY:  # about the same day
                 if current_time.time() == dt.time(0,0): # midnight
                     line(exes[current_time][0] - 2, "#bbb")
@@ -194,15 +194,15 @@ class TimeLine(graphics.Area):
                 if self.minor_tick == DAY:  # week change
                     if first_weekday(current_time):
                         line(exes[current_time][0] - 2, "#bbb")
-    
+
                 if self.minor_tick <= WEEK:  # month change
                     if current_time.day == 1:
                         if current_time in exes:
                             line(exes[current_time][0] - 2, "#bbb")
                         else: #if we are somewhere in middle then it gets a bit more complicated
                             somewhere_in_middle(current_time, "#bbb")
-        
-                # year change    
+
+                # year change
                 if current_time.timetuple().tm_yday == 1: # year change
                     if current_time in exes:
                         line(exes[current_time][0] - 2, "#f00")
@@ -210,7 +210,7 @@ class TimeLine(graphics.Area):
                         somewhere_in_middle(current_time, "#f00")
 
 
-        # the bars        
+        # the bars
         for i, (current_time, total) in enumerate(self.tick_totals):
             bar_size = max(round(self.height * total * 0.9), 1)
             x, bar_width = exes[current_time]
@@ -232,7 +232,7 @@ class TimeLine(graphics.Area):
                 step_format = "%b %d"
             else:
                 step_format = "%a"
-        else:        
+        else:
             step_format = "%H<small><sup>%M</sup></small>"
 
 
@@ -241,22 +241,22 @@ class TimeLine(graphics.Area):
             if (self.end_time - self.start_time) > dt.timedelta(10) \
                and self.minor_tick == DAY and first_weekday(current_time) == False:
                 continue
-            
+
             x, bar_width = exes[current_time]
 
             self.set_color("#666")
             self.layout.set_width(int((self.width - x) * pango.SCALE))
             self.layout.set_markup(current_time.strftime(step_format))
             w, h = self.layout.get_pixel_size()
-            
+
             self.context.move_to(x + 2, self.height - h - 2)
             self.context.show_layout(self.layout)
 
-        
+
     def count_hours(self):
         #go through facts and make array of time used by our fraction
         fractions = []
-        
+
         current_time = self.start_time
 
         minor_tick = self.minor_tick
@@ -264,20 +264,20 @@ class TimeLine(graphics.Area):
             # if minor tick is month, the starting date will have been
             # already adjusted to the first
             # now we have to make sure to move month by month
-            if self.minor_tick >= dt.timedelta(days=28): 
+            if self.minor_tick >= dt.timedelta(days=28):
                 minor_tick = dt.timedelta(calendar.monthrange(current_time.year, current_time.month)[1]) # days in month
-            
+
             fractions.append(current_time)
             current_time += minor_tick
-        
+
         hours = [0] * len(fractions)
-        
+
         tick_minutes = float(stuff.duration_minutes(self.minor_tick))
-        
+
         for fact in self.facts:
             if self.minor_tick < dt.timedelta(1):
                 end_time = fact["start_time"] + fact["delta"] # the thing about ongoing task - it has no end time
-                
+
                 # find in which fraction the fact starts and
                 # add duration up to the border of tick to that fraction
                 # then move cursor to the start of next fraction
@@ -285,16 +285,16 @@ class TimeLine(graphics.Area):
                 step_time = fractions[first_index]
                 first_end = min(end_time, step_time + self.minor_tick)
                 first_tick = stuff.duration_minutes(first_end - fact["start_time"]) / tick_minutes
-                
+
                 hours[first_index] += first_tick
                 step_time = step_time + self.minor_tick
-    
+
                 # now go through ticks until we reach end of the time
                 while step_time < end_time:
                     index = bisect(fractions, step_time) - 1
                     interval = min([1, stuff.duration_minutes(end_time - step_time) / tick_minutes])
                     hours[index] += interval
-                    
+
                     step_time += self.minor_tick
             else:
                 hour_index = bisect(fractions, dt.datetime.combine(fact["date"], dt.time())) - 1
diff --git a/tests/charting_test.py b/tests/charting_test.py
index bf369b9..b6f64ed 100644
--- a/tests/charting_test.py
+++ b/tests/charting_test.py
@@ -24,12 +24,12 @@ class TestIteratorFunctions(unittest.TestCase):
         # target is reached
         integrator = graphics.Integrator(0)
         integrator.target(10)
-        
+
         while integrator.update():
             pass
         self.assertEquals(round(integrator.value, 0), 10)
 
-    
+
 class TestSizeListFunctions(unittest.TestCase):
     def test_values_stay(self):
         # on shrinkage, values are kept
diff --git a/tests/hamsterdbus_test.py b/tests/hamsterdbus_test.py
index ed30d3a..70879c2 100644
--- a/tests/hamsterdbus_test.py
+++ b/tests/hamsterdbus_test.py
@@ -10,7 +10,7 @@ from hamster.hamsterdbus import HAMSTER_PATH, HAMSTER_URI
 
 def rndstr(length=10):
     result = ''
-    for i in range(1,10): 
+    for i in range(1,10):
         result += choice(letters)
 
     return result
@@ -39,19 +39,19 @@ class TestTracking(unittest.TestCase):
         activity = fact['name'] + '@' + fact['category'] + ',' + \
                 fact['description']
         fact_id = self.addfact(activity, fact['start_time'], fact['end_time'])
-        self.failUnless(type(fact_id) == dbus.Int32 and fact_id != 0, 
+        self.failUnless(type(fact_id) == dbus.Int32 and fact_id != 0,
             'expected non-zero dbus.Int32 as return value')
 
         dbfact = self.getfactbyid(fact_id)
-        self.assertEqual(fact['name'], dbfact['name'], 
+        self.assertEqual(fact['name'], dbfact['name'],
                 'expected same activity name')
-        self.assertEqual(fact['category'], dbfact['category'], 
+        self.assertEqual(fact['category'], dbfact['category'],
                 'expected same category name')
-        self.assertEqual(fact['description'], dbfact['description'], 
+        self.assertEqual(fact['description'], dbfact['description'],
                 'expected same description name')
-        self.assertEqual(fact['start_time'], dbfact['start_time'], 
+        self.assertEqual(fact['start_time'], dbfact['start_time'],
                 'expected same start_time')
-        self.assertEqual(fact['end_time'], dbfact['end_time'], 
+        self.assertEqual(fact['end_time'], dbfact['end_time'],
                 'expected same end_time')
 
         facts = self.getfacts(dbfact['start_time'], dbfact['end_time'])
@@ -82,19 +82,19 @@ class TestTracking(unittest.TestCase):
         activity = fact['name'] + '@' + fact['category'] + ',' + \
                 fact['description']
         fact_id = self.addfact(activity, fact['start_time'], 0)
-        self.failUnless(type(fact_id) == dbus.Int32 and fact_id != 0, 
+        self.failUnless(type(fact_id) == dbus.Int32 and fact_id != 0,
             'expected non-zero dbus.Int32 as return value')
 
         current = self.getcurrentfact()
-        self.assertEqual(fact['name'], current['name'], 
+        self.assertEqual(fact['name'], current['name'],
                 'expected same activity name')
-        self.assertEqual(fact['category'], current['category'], 
+        self.assertEqual(fact['category'], current['category'],
                 'expected same category name')
-        self.assertEqual(fact['description'], current['description'], 
+        self.assertEqual(fact['description'], current['description'],
                 'expected same description name')
-        self.assertEqual(fact['start_time'], current['start_time'], 
+        self.assertEqual(fact['start_time'], current['start_time'],
                 'expected same start_time')
-        self.assertEqual(0, current['end_time'], 
+        self.assertEqual(0, current['end_time'],
                 'expected same end_time')
 
         self.stoptracking()
@@ -140,9 +140,9 @@ class TestTracking(unittest.TestCase):
 
     def __rndfactgenerator(self, name=None, category=None, description=None,
             start_time=None, end_time=None):
-        fact = {'name':name or rndstr(), 'category':category or rndstr(), 
-                'description':description or rndstr(), 
-                'start_time':start_time or timegm(dt.datetime.now().timetuple()), 
+        fact = {'name':name or rndstr(), 'category':category or rndstr(),
+                'description':description or rndstr(),
+                'start_time':start_time or timegm(dt.datetime.now().timetuple()),
                 'end_time':end_time or timegm((dt.datetime.now() + \
                         dt.timedelta(hours=1)).timetuple())}
         return fact
diff --git a/tests/stuff_test.py b/tests/stuff_test.py
index da4e8b7..dd690b4 100644
--- a/tests/stuff_test.py
+++ b/tests/stuff_test.py
@@ -20,7 +20,7 @@ class TestActivityInputParsing(unittest.TestCase):
         self.assertEquals(activity.activity_name, "with start time")
         self.assertEquals(activity.start_time.strftime("%H:%M"), "12:35")
 
-        #rest must be empty        
+        #rest must be empty
         assert activity.category_name is None \
                and activity.end_time is None and activity.category_name is None\
                and activity.description is None
@@ -32,7 +32,7 @@ class TestActivityInputParsing(unittest.TestCase):
         self.assertEquals(activity.start_time.strftime("%H:%M"), "12:35")
         self.assertEquals(activity.end_time.strftime("%H:%M"), "14:25")
 
-        #rest must be empty        
+        #rest must be empty
         assert activity.category_name is None \
                and activity.category_name is None\
                and activity.description is None



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