[hamster-applet] so now it is possible to add tags and do nothing with it.



commit 2539c42cbfcf7ff99565d879feadc7a82324aeb5
Author: Toms Bauģis <toms baugis gmail com>
Date:   Tue Nov 24 10:43:57 2009 +0000

    so now it is possible to add tags and do nothing with it.
    let's see if somebody buys into that!

 data/applet.ui        |  228 ++++++++++++++++++++++++++++++++-----------------
 data/hamster.ui       |   19 ++++-
 hamster/applet.py     |   80 ++++++++++++-----
 hamster/db.py         |   72 +++++++++++++--
 hamster/standalone.py |   58 +++++++++----
 hamster/storage.py    |   14 +++-
 6 files changed, 339 insertions(+), 132 deletions(-)
---
diff --git a/data/applet.ui b/data/applet.ui
index 9598c12..bb056c4 100644
--- a/data/applet.ui
+++ b/data/applet.ui
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <interface>
-  <!-- interface-requires gtk+ 2.12 -->
+  <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy toplevel-contextual -->
   <object class="GtkWindow" id="hamster-window">
     <property name="can_focus">True</property>
@@ -32,62 +32,27 @@
                 <property name="orientation">vertical</property>
                 <property name="spacing">6</property>
                 <child>
-                  <object class="GtkHBox" id="hbox1">
+                  <object class="GtkVBox" id="vbox2">
                     <property name="visible">True</property>
-                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                    <property name="spacing">6</property>
+                    <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkAlignment" id="alignment3">
+                      <object class="GtkHBox" id="current_activity_box">
                         <property name="visible">True</property>
-                        <property name="yalign">0</property>
-                        <property name="yscale">0</property>
-                        <property name="top_padding">4</property>
-                        <property name="right_padding">6</property>
                         <child>
-                          <object class="GtkLabel" id="label2">
+                          <object class="GtkVBox" id="vbox6">
                             <property name="visible">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="label" translatable="yes">_Activity:</property>
-                            <property name="use_underline">True</property>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkVBox" id="vbox3">
-                        <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkAlignment" id="activity_name_box">
-                            <property name="width_request">400</property>
-                            <property name="visible">True</property>
-                            <property name="yscale">0</property>
-                            <child>
-                              <placeholder/>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkAlignment" id="more_info_label">
-                            <property name="xalign">0</property>
-                            <property name="left_padding">6</property>
+                            <property name="orientation">vertical</property>
                             <child>
-                              <object class="GtkHBox" id="hbox3">
+                              <object class="GtkHBox" id="hbox1">
                                 <property name="visible">True</property>
-                                <property name="spacing">4</property>
                                 <child>
-                                  <object class="GtkLabel" id="input_description">
+                                  <object class="GtkLabel" id="last_activity_name">
                                     <property name="visible">True</property>
                                     <property name="xalign">0</property>
-                                    <property name="yalign">0.50999999046325684</property>
-                                    <property name="label" translatable="yes">&lt;span size="small" &gt;Type in an activity and hit Enter to start tracking!&lt;/span&gt;</property>
-                                    <property name="use_markup">True</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                      <attribute name="size" value="15000"/>
+                                    </attributes>
                                   </object>
                                   <packing>
                                     <property name="expand">False</property>
@@ -95,67 +60,174 @@
                                   </packing>
                                 </child>
                                 <child>
-                                  <object class="GtkAlignment" id="alignment6">
+                                  <object class="GtkLabel" id="last_activity_category">
                                     <property name="visible">True</property>
                                     <property name="xalign">0</property>
-                                    <property name="xscale">0</property>
-                                    <child>
-                                      <object class="GtkButton" id="more_info_button">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">True</property>
-                                        <property name="relief">none</property>
-                                        <signal name="clicked" handler="on_more_info_button_clicked"/>
-                                        <child>
-                                          <object class="GtkLabel" id="label3">
-                                            <property name="visible">True</property>
-                                            <property name="label" translatable="yes">&lt;span size="small" color="blue" underline="single"&gt;Tell me more&lt;/span&gt;</property>
-                                            <property name="use_markup">True</property>
-                                          </object>
-                                        </child>
-                                      </object>
-                                    </child>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                      <attribute name="size" value="15000"/>
+                                    </attributes>
                                   </object>
                                   <packing>
                                     <property name="position">1</property>
                                   </packing>
                                 </child>
                               </object>
+                              <packing>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="last_activity_duration">
+                                <property name="visible">True</property>
+                                <property name="xalign">0</property>
+                                <attributes>
+                                  <attribute name="weight" value="bold"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkLabel" id="last_activity_description">
+                                <property name="visible">True</property>
+                                <property name="no_show_all">True</property>
+                                <property name="xalign">0</property>
+                                <property name="wrap">True</property>
+                                <attributes>
+                                  <attribute name="size" value="8000"/>
+                                </attributes>
+                              </object>
+                              <packing>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkAlignment" id="alignment5">
+                            <property name="visible">True</property>
+                            <property name="yalign">0</property>
+                            <property name="yscale">0</property>
+                            <child>
+                              <object class="GtkHButtonBox" id="hbuttonbox1">
+                                <property name="visible">True</property>
+                                <property name="spacing">4</property>
+                                <child>
+                                  <object class="GtkButton" id="stop_tracking">
+                                    <property name="label" translatable="yes">Stop tracking</property>
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <signal name="clicked" handler="on_stop_tracking_clicked"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                              </object>
                             </child>
                           </object>
                           <packing>
+                            <property name="expand">False</property>
                             <property name="position">1</property>
                           </packing>
                         </child>
                       </object>
                       <packing>
-                        <property name="position">1</property>
+                        <property name="expand">False</property>
+                        <property name="position">0</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkAlignment" id="alignment4">
+                      <object class="GtkAlignment" id="new_entry_box">
                         <property name="visible">True</property>
-                        <property name="yalign">0</property>
-                        <property name="yscale">0</property>
+                        <property name="no_show_all">True</property>
+                        <property name="top_padding">12</property>
                         <child>
-                          <object class="GtkButton" id="stop_tracking">
-                            <property name="label" translatable="yes">_Stop Tracking</property>
+                          <object class="GtkHBox" id="bleh1">
                             <property name="visible">True</property>
-                            <property name="can_focus">True</property>
-                            <property name="receives_default">True</property>
-                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
-                            <property name="use_underline">True</property>
-                            <signal name="clicked" handler="on_stop_tracking"/>
+                            <property name="spacing">4</property>
+                            <child>
+                              <object class="GtkAlignment" id="new_name_box">
+                                <property name="width_request">300</property>
+                                <property name="visible">True</property>
+                                <child>
+                                  <placeholder/>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkAlignment" id="new_tags_box">
+                                <property name="width_request">300</property>
+                                <property name="visible">True</property>
+                                <child>
+                                  <placeholder/>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkHButtonBox" id="hbuttonbox2">
+                                <property name="visible">True</property>
+                                <child>
+                                  <object class="GtkButton" id="switch_activity">
+                                    <property name="label" translatable="yes">Switch</property>
+                                    <property name="width_request">80</property>
+                                    <property name="visible">True</property>
+                                    <property name="sensitive">False</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <signal name="clicked" handler="on_switch_activity_clicked"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">0</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <object class="GtkButton" id="start_tracking">
+                                    <property name="label" translatable="yes">Start Tracking</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="receives_default">True</property>
+                                    <signal name="clicked" handler="on_switch_activity_clicked"/>
+                                  </object>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
                           </object>
                         </child>
                       </object>
                       <packing>
-                        <property name="position">2</property>
+                        <property name="expand">False</property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="expand">False</property>
                     <property name="position">0</property>
                   </packing>
                 </child>
diff --git a/data/hamster.ui b/data/hamster.ui
index abff98d..e831299 100644
--- a/data/hamster.ui
+++ b/data/hamster.ui
@@ -103,11 +103,12 @@
                         <property name="visible">True</property>
                         <property name="spacing">4</property>
                         <child>
-                          <object class="GtkButton" id="button2">
+                          <object class="GtkButton" id="stop_tracking">
                             <property name="label" translatable="yes">Stop tracking</property>
                             <property name="visible">True</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">True</property>
+                            <signal name="clicked" handler="on_stop_tracking_clicked"/>
                           </object>
                           <packing>
                             <property name="expand">False</property>
@@ -167,13 +168,14 @@
                       <object class="GtkHButtonBox" id="hbuttonbox2">
                         <property name="visible">True</property>
                         <child>
-                          <object class="GtkButton" id="button1">
+                          <object class="GtkButton" id="switch_activity">
                             <property name="label" translatable="yes">Switch</property>
                             <property name="width_request">80</property>
                             <property name="visible">True</property>
                             <property name="sensitive">False</property>
                             <property name="can_focus">True</property>
                             <property name="receives_default">True</property>
+                            <signal name="clicked" handler="on_switch_activity_clicked"/>
                           </object>
                           <packing>
                             <property name="expand">False</property>
@@ -181,6 +183,19 @@
                             <property name="position">0</property>
                           </packing>
                         </child>
+                        <child>
+                          <object class="GtkButton" id="start_tracking">
+                            <property name="label" translatable="yes">Start Tracking</property>
+                            <property name="can_focus">True</property>
+                            <property name="receives_default">True</property>
+                            <signal name="clicked" handler="on_switch_activity_clicked"/>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">False</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
diff --git a/hamster/applet.py b/hamster/applet.py
index 6a04309..3ec6b48 100755
--- a/hamster/applet.py
+++ b/hamster/applet.py
@@ -126,8 +126,8 @@ class PanelButton(gtk.ToggleButton):
             else:
                 label = "%s %s" % (self.activity, self.duration)
         
-        label = stuff.escape_pango(label)
-        label = '<span gravity=\"south\">' + label + '</span>'
+        label = '<span gravity="south">%s</span>' % stuff.escape_pango(label)
+        self.label.set_markup("") #clear - seems to fix the warning
         self.label.set_markup(label)
 
     def get_pos(self):
@@ -231,9 +231,13 @@ class HamsterApplet(object):
 
         self.new_name = widgets.ActivityEntry()
         widgets.add_hint(self.new_name, _("Time and Name"))
-        self._gui.get_object("activity_name_box").add(self.new_name)
-        self.new_name.connect("value-entered", self.on_activity_entered)
-        
+        self.get_widget("new_name_box").add(self.new_name)
+        self.new_name.connect("changed", self.on_activity_text_changed)
+
+        self.new_tags = widgets.TagsEntry()
+        self.new_tags.set_entries([tag["name"] for tag in runtime.storage.get_tags(autocomplete = True)])
+        widgets.add_hint(self.new_tags, _("Tags or Description"))
+        self.get_widget("new_tags_box").add(self.new_tags)
         
         # init today's tree
         self.setup_activity_tree()
@@ -337,25 +341,40 @@ class HamsterApplet(object):
                                stuff.format_duration(duration, False))
             self.button.set_text(self.last_activity['name'],
                                  stuff.format_duration(duration, False))
-            
-            self._gui.get_object('stop_tracking').set_sensitive(1);
-
-            label = self.last_activity['name']
-            if self.last_activity['category'] != _("Unsorted"):
-                label += "@%s" %  self.last_activity['category']
-            self.new_name.set_text(label)
-
-            self.new_name.select_region(0, -1)
-            self._gui.get_object("more_info_label").hide()
         else:
             label = "%s" % _(u"No activity")
             self.button.set_text(label, None)
-            self._gui.get_object('stop_tracking').set_sensitive(0);
+            
+        self.set_last_activity()
 
-            self.new_name.set_text('')
-            self._gui.get_object("more_info_label").show()
         
+    def set_last_activity(self):
+        activity = runtime.storage.get_last_activity()
+        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"):
+                self.get_widget("last_activity_category") \
+                    .set_text(" - %s" % activity['category'])
+
+            self.get_widget("last_activity_description").set_text(activity['description'])
+        else:
+            self.get_widget("switch_activity").hide()
+            self.get_widget("start_tracking").show()
+
+            self.get_widget("last_activity_name").set_text(_("No activity"))
+            self.get_widget("last_activity_duration").set_text("")
+            self.get_widget("last_activity_category").set_text("")
+         
     def check_user(self):
         if not self.notify_interval: #no interval means "never"
             return
@@ -588,12 +607,6 @@ class HamsterApplet(object):
         return False
         
     """button events"""
-    def on_stop_tracking(self, button):
-        runtime.storage.touch_fact(self.last_activity)
-        self.last_activity = None
-        self.update_label()
-        runtime.dispatcher.dispatch('panel_visible', False)
-
     def on_overview(self, menu_item):
         runtime.dispatcher.dispatch('panel_visible', False)
         stats_viewer = StatsViewer(self)
@@ -690,3 +703,22 @@ Now, start tracking!
         message_dialog.set_markup(more_info)
         message_dialog.show()
 
+    def on_activity_text_changed(self, widget):
+        self.get_widget("switch_activity").set_sensitive(widget.get_text() != "")
+
+    def on_switch_activity_clicked(self, widget):
+        runtime.storage.add_fact(self.new_name.get_text().encode("utf-8"), self.new_tags.get_text())
+        self.new_name.set_text("")
+        self.new_tags.set_text("")
+        runtime.dispatcher.dispatch('panel_visible', False)
+
+    def on_stop_tracking_clicked(self, widget):
+        runtime.storage.touch_fact(runtime.storage.get_last_activity())
+        self.last_activity = None
+        runtime.dispatcher.dispatch('panel_visible', False)
+
+    def show(self):
+        self.window.show_all()
+        
+    def get_widget(self, name):
+        return self._gui.get_object(name)
diff --git a/hamster/db.py b/hamster/db.py
index 8b068fb..833a312 100644
--- a/hamster/db.py
+++ b/hamster/db.py
@@ -81,6 +81,37 @@ 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'"
+        
+        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 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
+        
+        found_tags = [tag["name"] for tag in db_tags]
+        
+        add = set(tags) - set(found_tags)
+        if add:
+            statement = "insert into tags(name) values(?)"
+
+            self.execute([statement] * len(add), [(tag,) for tag in add])
+
+            return self.__get_tag_ids(list(add)) # all done, recurse
+        else:
+            return db_tags
+
+        print db_tags
 
     def __get_category_list(self):
         return self.fetchall("SELECT * FROM categories ORDER BY category_order")
@@ -315,7 +346,7 @@ class Storage(storage.Storage):
         make room for new fact"""
 
         # this function is destructive - can't go with a wildcard
-        if not end_time or not start_time: #this function is destructive
+        if not end_time or not start_time:
             return
         
         # activities that we are overlapping.
@@ -345,11 +376,17 @@ class Storage(storage.Storage):
                                    SET end_time = ?
                                  WHERE id = ?""", (start_time, fact["id"]))
                 fact_name = fact["name"]
-                self.__add_fact(fact["name"],
-                                end_time,
-                                fact["end_time"],
-                                fact["category"],
-                                fact["description"])
+                new_fact = self.__add_fact(fact["name"],
+                                           "", # will create tags in the next step
+                                           end_time,
+                                           fact["end_time"],
+                                           fact["category"],
+                                           fact["description"])
+                tag_update = """INSERT INTO fact_tags(fact_id, tag_id)
+                                     SELECT ?, tag_id
+                                       FROM fact_tags
+                                      WHERE fact_id = ?"""
+                self.execute(tag_update, (new_fact["id"], fact["id"])) #clone tags
 
             #eliminate
             elif fact["end_time"] and \
@@ -371,14 +408,24 @@ class Storage(storage.Storage):
                              (start_time, fact["id"]))
 
 
-    def __add_fact(self, activity_name, start_time = None,
+    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
+            print "over ride %s" % description
+            activity.description = description #override
         
         start_time = activity.start_time or start_time or datetime.datetime.now()
         
@@ -412,12 +459,12 @@ class Storage(storage.Storage):
 
             if last_activity and last_activity['start_time'] < start_time:
                 #if this is the same, ongoing activity, then there is no need to create another one
-                if not activity.description \
+                if not tags and not activity.description \
                    and last_activity['activity_id'] == activity_id:
                     return last_activity
                 
                 #if duration is less than a minute - it must have been a mistake
-                if not activity.description \
+                if not tags and not activity.description \
                    and not last_activity["description"] \
                    and 60 >= (start_time - last_activity['start_time']).seconds >= 0:
                     self.__remove_fact(last_activity['id'])
@@ -448,6 +495,11 @@ class Storage(storage.Storage):
 
         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)
 
 
diff --git a/hamster/standalone.py b/hamster/standalone.py
index 65b0b41..a4a29e6 100755
--- a/hamster/standalone.py
+++ b/hamster/standalone.py
@@ -46,13 +46,12 @@ class MainWindow(object):
         self.new_name = widgets.ActivityEntry()
         widgets.add_hint(self.new_name, _("Time and Name"))
         self.get_widget("new_name_box").add(self.new_name)
+        self.new_name.connect("changed", self.on_activity_text_changed)
+
+
 
         self.new_tags = widgets.TagsEntry()
-        
-        self.new_tags.set_entries(["peh", "poh", "and so on", "etc", "true magic",
-                                   "and so we go", "on and on", "until you drop",
-                                   "somewhere", "and forget", "what we", "were",
-                                   "actually doing"])
+        self.new_tags.set_entries([tag["name"] for tag in runtime.storage.get_tags(autocomplete = True)])
         
         widgets.add_hint(self.new_tags, _("Tags or Description"))
         self.get_widget("new_tags_box").add(self.new_tags)
@@ -66,9 +65,13 @@ class MainWindow(object):
         
         self.tag_box = widgets.TagBox()
         self.get_widget("tag_box").add(self.tag_box)
+
+        runtime.dispatcher.add_handler('activity_updated', self.after_activity_update)
+        runtime.dispatcher.add_handler('day_updated', self.after_fact_update)
         
         self._gui.connect_signals(self)
         
+        
 
     def magic(self, button, uri):
         print uri, button
@@ -76,24 +79,31 @@ class MainWindow(object):
 
     def set_last_activity(self):
         activity = runtime.storage.get_last_activity()
+        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))
+            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"):
                 self.get_widget("last_activity_category") \
                     .set_text(" - %s" % activity['category'])
-                self.get_widget("last_activity_category").show()
-            else:
-                self.get_widget("last_activity_category").hide()
 
-            if activity['description']:
-                self.get_widget("last_activity_description").set_text(activity['description'])
-                self.get_widget("last_activity_description").show()
-            else:
-                self.get_widget("last_activity_description").hide()
+            self.get_widget("last_activity_description").set_text(activity['description'])
+        else:
+            self.get_widget("switch_activity").hide()
+            self.get_widget("start_tracking").show()
+
+            self.get_widget("last_activity_name").set_text(_("No activity"))
+            self.get_widget("last_activity_duration").set_text("")
+            self.get_widget("last_activity_category").set_text("")
+            
 
     def load_today(self):
         todays_facts = runtime.storage.get_facts(dt.date.today())
@@ -147,10 +157,26 @@ class MainWindow(object):
 
 
 
-        
+    def on_activity_text_changed(self, widget):
+        self.get_widget("switch_activity").set_sensitive(widget.get_text() != "")
 
     def on_switch_activity_clicked(self, widget):
-        self.get_widget("new_entry_box").show()
+        runtime.storage.add_fact(self.new_name.get_text().encode("utf-8"), self.new_tags.get_text())
+        self.new_name.set_text("")
+        self.new_tags.set_text("")
+
+    def on_stop_tracking_clicked(self, widget):
+        runtime.storage.touch_fact(runtime.storage.get_last_activity())
+
+    def after_activity_update(self, widget, stuff):
+        print "activity updated"
+        self.set_last_activity()
+        self.load_today()
+
+    def after_fact_update(self, widget, stuff):
+        print "fact updated"
+        self.set_last_activity()
+        self.load_today()
 
     def show(self):
         self.window.show_all()
diff --git a/hamster/storage.py b/hamster/storage.py
index edb0297..9071dc0 100644
--- a/hamster/storage.py
+++ b/hamster/storage.py
@@ -30,12 +30,22 @@ class Storage(object):
 
     def dispatch(self, event, data):
         self.parent.dispatch(event, data)
+        
+
+    def get_tags(self, autocomplete = None):
+        return self.__get_tags(autocomplete)
+        
+    def get_tag_ids(self, tags):
+        self.__get_tag_ids(tags)        
+
 
     def get_fact(self, id):
         return self.__get_fact(id)
 
-    def add_fact(self, activity_name, start_time = None,  end_time = None):
-        result = self.__add_fact(activity_name, start_time, end_time)
+    def add_fact(self, activity_name, tags, start_time = None, end_time = None,
+                                      category_name = None, description = None):
+
+        result = self.__add_fact(activity_name, tags, start_time, end_time, category_name, description)
         if result:
             self.dispatch('day_updated', result['start_time'])
         return result



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