[hamster-applet] what you say? an actual search? in hamster?! i don't believe my ears!



commit 5d0b8729fa2489e64fe0f5e4d6908568af8767a6
Author: Toms Bauģis <toms baugis gmail com>
Date:   Tue Dec 22 23:37:20 2009 +0000

    what you say? an actual search? in hamster?! i don't believe my ears!

 data/stats.ui      |    5 +++--
 hamster/db.py      |   43 ++++++++++++++++++++++++++++++++++---------
 hamster/stats.py   |   10 +++++++---
 hamster/storage.py |    4 ++--
 4 files changed, 46 insertions(+), 16 deletions(-)
---
diff --git a/data/stats.ui b/data/stats.ui
index a47aa4c..a27f458 100644
--- a/data/stats.ui
+++ b/data/stats.ui
@@ -243,20 +243,21 @@
                     <property name="left_padding">6</property>
                     <property name="right_padding">6</property>
                     <child>
-                      <object class="GtkEntry" id="entry1">
+                      <object class="GtkEntry" id="search">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="invisible_char">&#x2022;</property>
                         <property name="secondary_icon_stock">gtk-find</property>
                         <property name="primary_icon_sensitive">True</property>
                         <property name="secondary_icon_sensitive">True</property>
+                        <signal name="activate" handler="on_search_activate"/>
                       </object>
                     </child>
                   </object>
                 </child>
               </object>
               <packing>
-                <property name="expand">False</property>
+                <property name="expand">True</property>
               </packing>
             </child>
           </object>
diff --git a/hamster/db.py b/hamster/db.py
index 09f36de..114845e 100644
--- a/hamster/db.py
+++ b/hamster/db.py
@@ -317,7 +317,7 @@ class Storage(storage.Storage):
             # we need dict so we can modify it (sqlite.Row is read only)
             # in python 2.5, sqlite does not have keys() yet, so we hardcode them (yay!)
             keys = ["id", "start_time", "end_time", "description", "name",
-                    "activity_id", "category", "category_id", "tags"]
+                    "category", "tags"]
             grouped_fact = dict([(key, grouped_fact[key]) for key in keys])
             
             grouped_fact["tags"] = [ft["tags"] for ft in fact_tags if ft["tags"]]
@@ -572,14 +572,14 @@ class Storage(storage.Storage):
         return self.__get_fact(fact_id)
 
 
-    def __get_facts(self, date, end_date = None, category_id = None):
+    def __get_facts(self, date, end_date = None, search_terms = ""):
         query = """
                    SELECT a.id AS id,
                           a.start_time AS start_time,
                           a.end_time AS end_time,
                           a.description as description,
-                          b.name AS name, b.id as activity_id,
-                          coalesce(c.name, ?) as category, coalesce(c.id, -1) as category_id,
+                          b.name AS name,
+                          coalesce(c.name, ?) as category,
                           e.name as tags
                      FROM facts a
                 LEFT JOIN activities b ON a.activity_id = b.id
@@ -588,12 +588,35 @@ class Storage(storage.Storage):
                 LEFT JOIN tags e ON e.id = d.tag_id
                     WHERE (a.end_time >= ? OR a.end_time IS NULL) AND a.start_time <= ?
         """
+
+        # let's see what we can do with search terms
+        # 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
+                          for term in terms.strip().split(" ") if term.strip()]
+                          for terms in search_terms.split(",") if terms.strip()]
+        
+        if or_bits:
+            search_query = "1<>1 "
+            
+            for and_bits in or_bits:
+                and_query = "1=1 "
+                for and_bit in and_bits:
+                    and_query += """and (lower(a.description) like '%%%(term)s%%'
+                                     or lower(b.name) = '%(term)s'
+                                     or lower(c.name) = '%(term)s'
+                                     or lower(e.name) = '%(term)s' )""" % dict(term = and_bit)
+                
+                search_query = "%s or (%s) " % (search_query, and_query)
+    
+            query = "%s and (%s)" % (query, search_query)
         
-        if category_id and isinstance(category_id, int):
-            query += " and b.category_id = %d" % category_id
-        elif category_id and isinstance(category_id, list):
-            query += " and b.category_id IN (%s)" % (",".join([str(id) for id in category_id]))
 
+        
         query += " ORDER BY a.start_time"
         end_date = end_date or date
 
@@ -604,7 +627,9 @@ class Storage(storage.Storage):
         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))
+        facts = self.fetchall(query, (_("Unsorted"),
+                                      datetime_from,
+                                      datetime_to))
         
         #first let's put all tags in an array
         facts = self.__group_tags(facts)
diff --git a/hamster/stats.py b/hamster/stats.py
index 1496e0b..39b834c 100644
--- a/hamster/stats.py
+++ b/hamster/stats.py
@@ -128,14 +128,18 @@ class StatsViewer(object):
         self.start_date_input.set_date(self.start_date)
         self.end_date_input.set_date(self.end_date)
         
-        facts = runtime.storage.get_facts(self.start_date, self.end_date)
+        search_terms = self.get_widget("search").get_text().decode("utf8", "replace")
+        facts = runtime.storage.get_facts(self.start_date, self.end_date, search_terms)
+
         self.get_widget("report_button").set_sensitive(len(facts) > 0)
 
         self.timeline.draw(facts, self.start_date, self.end_date)
         
         self.overview.search(self.start_date, self.end_date, facts)
         self.reports.search(self.start_date, self.end_date, facts)
-        
+
+    def on_search_activate(self, widget):
+        self.search()
         
     def on_report_button_clicked(self, widget):
         self.reports.on_report_button_clicked(widget) #forward for now
@@ -226,7 +230,7 @@ class StatsViewer(object):
         elif pagenum == 1:
             self.get_widget('remove').set_sensitive(False)
             self.get_widget('edit').set_sensitive(False)
-            self.reports.do_graph()
+            self.reports.do_graph(self.facts)
 
 
     def on_add_clicked(self, button):
diff --git a/hamster/storage.py b/hamster/storage.py
index 366cdf4..a6f3fea 100644
--- a/hamster/storage.py
+++ b/hamster/storage.py
@@ -63,8 +63,8 @@ class Storage(object):
         self.dispatch('day_updated', fact['start_time'])
         return result
 
-    def get_facts(self, date, end_date = None, category_id = None):
-        return self.__get_facts(date, end_date, category_id)
+    def get_facts(self, date, end_date = None, search_terms = ""):
+        return self.__get_facts(date, end_date, search_terms)
 
     def get_popular_categories(self):
         return self.__get_popular_categories()



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