Skip to content
Browse files

refactored functions related to activity editing - don't drink

and code, kids!

svn path=/trunk/; revision=105
  • Loading branch information...
1 parent 7ffd896 commit 5673bbc655b86b6b282412afd47697c5366ba674 Toms Baugis committed
Showing with 167 additions and 186 deletions.
  1. +108 −134 hamster/activities.py
  2. +47 −46 hamster/db.py
  3. +12 −6 hamster/storage.py
View
242 hamster/activities.py
@@ -18,16 +18,7 @@ def get_prev(selection, model):
else:
return None
-def ordered_list(row, columns):
- #FIXME - i know there was some cool short way to map directly
- res = []
- for column in columns:
- res.append(row[column])
- return res
-
class CategoryStore(gtk.ListStore):
- columns = ['id', 'name', 'category_order']
-
def __init__(self):
#id, name, color_code, order
gtk.ListStore.__init__(self, int, str, int)
@@ -39,20 +30,14 @@ def load(self):
category_list = storage.get_category_list()
for category in category_list:
- self.append(ordered_list(category, self.columns)) #performing the magic, so we don't risk with database field order change
+ self.append([category['id'],
+ category['name'],
+ category['category_order']])
self.append([-1, "Unsorted", 999]) # all activities without category
- def value(self, path, column):
- return self[path][self.columns.index(column)]
-
- def update(self, path, column, new_value):
- self[path][self.columns.index(column)] = new_value
-
class ActivityStore(gtk.ListStore):
- columns = ['id', 'name', 'category_id', 'activity_order']
-
def __init__(self):
#id, name, category_id, order
gtk.ListStore.__init__(self, int, str, int, int)
@@ -69,13 +54,10 @@ def load(self, category_id):
activity_list = storage.get_activities(category_id)
for activity in activity_list:
- self.append(ordered_list(activity, self.columns)) #performing the magic, so we don't risk with database field order change
-
- def value(self, path, column):
- return self[path][self.columns.index(column)]
-
- def update(self, path, column, new_value):
- self[path][self.columns.index(column)] = new_value
+ self.append([activity['id'],
+ activity['name'],
+ activity['category_id'],
+ activity['activity_order']])
class ActivitiesEditor:
TARGETS = [
@@ -88,34 +70,71 @@ def __init__(self):
self.wTree = gtk.glade.XML(os.path.join(SHARED_DATA_DIR, "activities.glade"))
self.window = self.get_widget('activities_window')
- # create and fill store with activities
- self.store = ActivityStore()
- #self.store.load() #get data from DB
-
+ # create and fill activity tree
+ self.activity_tree = self.get_widget('activity_list')
+ self.activity_store = ActivityStore()
+
+ nameColumn = gtk.TreeViewColumn(_(u'Name'))
+ nameColumn.set_expand(True)
+ nameCell = gtk.CellRendererText()
+ nameCell.set_property('editable', True)
+ nameCell.connect('edited', self.activity_name_edited_cb, self.activity_store)
+ nameColumn.pack_start(nameCell, True)
+ nameColumn.set_attributes(nameCell, text = 1)
+ nameColumn.set_sort_column_id(1)
+ self.activity_tree.append_column(nameColumn)
+
+ self.activity_tree.set_model(self.activity_store)
+
+ self.selection = self.activity_tree.get_selection()
+ self.selection.connect('changed', self.activity_changed, self.activity_store)
+
+
+ # create and fill category tree
+ self.category_tree = self.get_widget('category_list')
self.category_store = CategoryStore()
+
+ nameColumn = gtk.TreeViewColumn(_(u'Category'))
+ nameColumn.set_expand(True)
+ nameCell = gtk.CellRendererText()
+ nameCell.set_property('editable', True)
+ nameCell.connect('edited', self.category_edited_cb, self.category_store)
+
+ nameColumn.pack_start(nameCell, True)
+ nameColumn.set_attributes(nameCell, text = 1)
+ nameColumn.set_sort_column_id(1)
+ self.category_tree.append_column(nameColumn)
+
self.category_store.load()
+ self.category_tree.set_model(self.category_store)
+
+ selection = self.category_tree.get_selection()
+ selection.connect('changed', self.category_changed_cb, self.category_store)
- self.configure_tree()
- self.configure_categories()
self.wTree.signal_autoconnect(self)
# Allow enable drag and drop of rows including row move
- self.treeview.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,
+ self.activity_tree.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,
self.TARGETS,
gtk.gdk.ACTION_DEFAULT|
gtk.gdk.ACTION_MOVE)
- self.treeview.enable_model_drag_dest(self.TARGETS,
- gtk.gdk.ACTION_DEFAULT)
+ self.activity_tree.enable_model_drag_dest(self.TARGETS,
+ gtk.gdk.ACTION_DEFAULT)
self.category_tree.enable_model_drag_dest(self.TARGETS,
- gtk.gdk.ACTION_DEFAULT)
+ gtk.gdk.ACTION_DEFAULT)
- self.treeview.connect("drag_data_get", self.drag_data_get_data)
- self.treeview.connect("drag_data_received",
- self.drag_data_received_data)
+ self.activity_tree.connect("drag_data_get", self.drag_data_get_data)
+ self.activity_tree.connect("drag_data_received",
+ self.drag_data_received_data)
self.category_tree.connect("drag_data_received",
- self.on_category_drop)
+ self.on_category_drop)
+
+ #select first category
+ selection = self.category_tree.get_selection()
+ selection.select_path((0,))
+
def drag_data_get_data(self, treeview, context, selection, target_id,
etime):
@@ -125,14 +144,11 @@ def drag_data_get_data(self, treeview, context, selection, target_id,
selection.set(selection.target, 0, str(data))
def select_activity(self, id):
- model = self.treeview.get_model()
-
- id_column = self.store.columns.index('id')
-
+ model = self.activity_tree.get_model()
i = 0
for row in model:
- if row[id_column] == id:
- self.treeview.set_cursor((i, ))
+ if row[0] == id:
+ self.activity_tree.set_cursor((i, ))
i += 1
@@ -162,7 +178,7 @@ def drag_data_received_data(self, treeview, context, x, y, selection,
context.finish(True, True, etime)
- self.store.load(self._get_selected_category())
+ self.activity_store.load(self._get_selected_category())
self.select_activity(int(data))
@@ -196,73 +212,37 @@ def get_widget(self, name):
def get_store(self):
"""returns store, so we can add some watchers in case if anything changes"""
- return self.store
+ return self.activity_store
def show(self):
- self.selection_changed_cb(self.treeview.get_selection(), self.store)
self.window.show_all()
- def configure_categories(self):
- """ Fills store with activities, and connects it to tree """
-
- self.category_tree = treeview = self.get_widget('category_list')
-
- nameColumn = gtk.TreeViewColumn(_(u'Category'))
- nameColumn.set_expand(True)
- nameCell = gtk.CellRendererText()
- nameCell.set_property('editable', True)
- nameCell.connect('edited', self.category_edited_cb, self.category_store)
-
- nameColumn.pack_start(nameCell, True)
- nameColumn.set_attributes(nameCell, text = self.store.columns.index('name'))
- nameColumn.set_sort_column_id(1)
- treeview.append_column(nameColumn)
-
- treeview.set_model(self.category_store)
-
- selection = treeview.get_selection()
- selection.connect('changed', self.category_changed_cb, self.category_store)
-
-
- def configure_tree(self):
- """ Fills store with activities, and connects it to tree """
-
- self.treeview = treeview = self.get_widget('activity_list')
-
- nameColumn = gtk.TreeViewColumn(_(u'Name'))
- nameColumn.set_expand(True)
- nameCell = gtk.CellRendererText()
- nameCell.set_property('editable', True)
- nameCell.connect('edited', self.name_edited_cb, self.store)
- nameColumn.pack_start(nameCell, True)
- nameColumn.set_attributes(nameCell, text = self.store.columns.index('name'))
- nameColumn.set_sort_column_id(1)
- treeview.append_column(nameColumn)
-
- treeview.set_model(self.store)
-
-
- self.selection = treeview.get_selection()
- self.selection.connect('changed', self.selection_changed_cb, self.store)
-
def update_activity(self, tree_row):
print "Update activity: ", tree_row[3]
#map to dictionary, for easier updates
- row_data = {'name': tree_row[1],
- 'category_id': tree_row[2],
- 'id': tree_row[0]}
-
- # update id (necessary for new records)
- tree_row[0] = storage.update_activity(row_data)
+ name = tree_row[1]
+ category_id = tree_row[2]
+ id = tree_row[0]
+
+ if id == -1:
+ tree_row[0] = storage.insert_activity(name, category_id)
+ else:
+ storage.update_activity(id, name, category_id)
# callbacks
def category_edited_cb(self, cell, path, new_text, model):
- model.update(path, 'name', new_text)
- id = storage.update_category_name(model[path][0], model[path][1])
- model.update(path, 'id', id)
- return True
+ model[path][1] = new_text
+ id = model[path][0]
+ name = model[path][1]
+
+ if id == -2:
+ id = storage.insert_category(name)
+ model[path][0] = id
+ elif id > -1: #ignore unsorted category (id = -1)
+ storage.update_category(id, name)
- def name_edited_cb(self, cell, path, new_text, model):
+
+ def activity_name_edited_cb(self, cell, path, new_text, model):
model.update(path, 'name', new_text)
self.update_activity(model[path])
return True
@@ -270,12 +250,19 @@ def name_edited_cb(self, cell, path, new_text, model):
def category_changed_cb(self, selection, model):
""" enables and disables action buttons depending on selected item """
(model, iter) = selection.get_selected()
-
+ id = 0
if iter == None:
- self.store.clear()
+ self.activity_store.clear()
else:
- print model[iter][0]
- self.store.load(model[iter][0])
+ id = model[iter][0]
+ self.activity_store.load(model[iter][0])
+
+ #do not allow to remove the unsorted category
+ self.get_widget('remove_category').set_sensitive(id != -1)
+
+ self.get_widget('promote_activity').set_sensitive(False)
+ self.get_widget('demote_activity').set_sensitive(False)
+ self.get_widget('remove_activity').set_sensitive(False)
return True
@@ -289,30 +276,23 @@ def _get_selected_category(self):
return None
- def selection_changed_cb(self, selection, model):
+ def activity_changed(self, selection, model):
""" enables and disables action buttons depending on selected item """
(model, iter) = selection.get_selected()
- if iter == None:
- self.get_widget('remove_activity').set_sensitive(False)
- self.get_widget('promote_activity').set_sensitive(False)
- self.get_widget('demote_activity').set_sensitive(False)
- else:
- self.get_widget('remove_activity').set_sensitive(True)
+ # treat any selected case
+ self.get_widget('remove_activity').set_sensitive(iter != None)
+ unsorted_selected = self._get_selected_category() == -1
+ self.get_widget('promote_activity').set_sensitive(False)
+ self.get_widget('demote_activity').set_sensitive(False)
+ if iter != None and not unsorted_selected:
first_item = model.get_path(iter) == (0,)
self.get_widget('promote_activity').set_sensitive(not first_item)
last_item = model.iter_next(iter) == None
self.get_widget('demote_activity').set_sensitive(not last_item)
- # override enabled buttons for unsorted category
- if self._get_selected_category() == -1:
- self.get_widget('promote_activity').set_sensitive(False)
- self.get_widget('demote_activity').set_sensitive(False)
-
- return True
-
def _del_selected_row(self, tree):
selection = tree.get_selection()
(model, iter) = selection.get_selected()
@@ -322,7 +302,7 @@ def _del_selected_row(self, tree):
if next_row:
selection.select_iter(next_row)
else:
- path = self.store.get_path(iter)[0] - 1
+ path = model.get_path(iter)[0] - 1
if path > 0:
selection.select_path(path)
@@ -345,7 +325,6 @@ def on_add_category_clicked(self, button):
focus_column = self.category_tree.get_column(0),
focus_cell = None,
start_editing = True)
- return
def on_remove_category_clicked(self, button):
removable_id = self._del_selected_row(self.category_tree)
@@ -357,18 +336,17 @@ def on_add_activity_clicked(self, button):
""" appends row, jumps to it and allows user to input name """
category_id = self._get_selected_category()
- new_activity = self.store.append([-1, _(u"New activity"), category_id, -1])
+ new_activity = self.activity_store.append([-1, _(u"New activity"), category_id, -1])
(model, iter) = self.selection.get_selected()
- self.treeview.set_cursor_on_cell(model.get_string_from_iter(new_activity),
- focus_column = self.treeview.get_column(0),
+ self.activity_tree.set_cursor_on_cell(model.get_string_from_iter(new_activity),
+ focus_column = self.activity_tree.get_column(0),
focus_cell = None,
start_editing = True)
- return
def on_remove_activity_clicked(self, button):
- removable_id = self._del_selected_row(self.treeview)
+ removable_id = self._del_selected_row(self.activity_tree)
storage.remove_activity(removable_id)
def on_promote_activity_clicked(self, button):
@@ -379,25 +357,21 @@ def on_promote_activity_clicked(self, button):
storage.swap_activities(model[iter][0], model[prev_iter][0])
model.move_before(iter, prev_iter)
- self.selection_changed_cb(self.selection, model)
+ self.activity_changed(self.selection, model)
dispatcher.dispatch('activity_updated', ())
- return
def on_demote_activity_clicked(self, button):
(model, iter) = self.selection.get_selected()
next_iter = model.iter_next(iter)
storage.swap_activities(model[iter][0], model[next_iter][0])
- self.store.move_after(iter, next_iter)
+ self.activity_store.move_after(iter, next_iter)
- self.selection_changed_cb(self.selection, model)
+ self.activity_changed(self.selection, model)
dispatcher.dispatch('activity_updated', ())
- return
if __name__ == '__main__':
controller = ActivitiesController()
controller.show()
gtk.main()
-
-
View
93 hamster/db.py
@@ -26,28 +26,27 @@ def __change_category(self, id, category_id):
self.execute(statement, (category_id, max_order, id))
- def __update_category_name(self, id, new_name):
- if id == -2: # -1 means, we have a new entry!
- new_rec = self.fetchone("select max(id) +1 , max(category_order) + 1 from categories")
- new_id, new_order = 0, 0
- if new_rec: # handle case when we have no activities at all
- new_id, new_order = new_rec[0], new_rec[1]
+ def __insert_category(self, name):
+ new_rec = self.fetchone("select max(id) +1 , max(category_order) + 1 from categories")
+ id, order = 0, 0
+ if new_rec: # handle case when we have no activities at all
+ id, order = new_rec[0], new_rec[1]
- query = """
- INSERT INTO categories (id, name, category_order)
- VALUES (?, ?, ?)
- """
- self.execute(query, (new_id, new_name, new_order))
- id = new_id
- elif id > -1: # Update, and ignore unsorted, if that was somehow triggered
+ query = """
+ INSERT INTO categories (id, name, category_order)
+ VALUES (?, ?, ?)
+ """
+ self.execute(query, (id, name, order))
+ return id
+
+ def __update_category(self, id, name):
+ if id > -1: # Update, and ignore unsorted, if that was somehow triggered
update = """
UPDATE categories
SET name = ?
WHERE id = ?
"""
- self.execute(update, (new_name, id))
-
- return 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"
@@ -71,12 +70,18 @@ def __move_activity(self, source_id, target_order, insert_after = True):
def __get_activity_by_name(self, name):
"""get most recent, preferably not deleted activity by it's name"""
query = """
- SELECT * from activities
+ SELECT id from activities
WHERE lower(name) = lower(?)
ORDER BY deleted, id desc
LIMIT 1
"""
- return self.fetchone(query, (name,))
+
+ res = self.fetchone(query, (name,))
+
+ if res:
+ return res['id']
+
+ return None
def __get_fact(self, id):
query = """SELECT a.id AS id,
@@ -130,17 +135,16 @@ def __add_fact(self, activity_name, fact_time = None):
start_time = fact_time or datetime.datetime.now()
# try to lookup activity by it's name in db. active ones have priority
- activity = self.__get_activity_by_name(activity_name)
+ activity_id = self.__get_activity_by_name(activity_name)
- if not activity:
- activity = {'id': -1, 'order': -1, 'category_id': -1, 'name': activity_name}
- activity['id'] = self.update_activity(activity)
+ if not activity_id:
+ activity_id = self.insert_activity(activity_name)
# avoid dupes and facts shorter than minute
prev_activity = self.__get_last_activity()
if prev_activity and prev_activity['start_time'].date() == start_time.date():
- if prev_activity['id'] == activity['id']:
+ if prev_activity['id'] == activity_id:
return
# if the time since previous task is about minute
@@ -168,7 +172,7 @@ def __add_fact(self, activity_name, fact_time = None):
(activity_id, start_time, end_time)
VALUES (?, ?, ?)
"""
- self.execute(insert, (activity['id'], start_time, start_time))
+ self.execute(insert, (activity_id, start_time, start_time))
fact_id = self.fetchone("select max(id) as max_id from facts")['max_id']
@@ -255,30 +259,27 @@ def __swap_activities(self, id1, id2):
self.execute("update activities set activity_order = ? where id = ?", (priority1, id2) )
self.execute("update activities set activity_order = ? where id = ?", (priority2, id1) )
- def __update_activity(self, activity):
-
- if activity['id'] == -1: # -1 means, we have a new entry!
- new_rec = self.fetchone("select max(id) +1 , max(activity_order) + 1 from activities")
- new_id, new_order = 0, 0
- if new_rec: # handle case when we have no activities at all
- new_id, new_order = new_rec[0], new_rec[1]
+ def __insert_activity(self, name, category_id = -1):
+ new_rec = self.fetchone("select max(id) + 1 , max(activity_order) + 1 from activities")
+ new_id, new_order = 0, 0
+ if new_rec: # handle case when we have no activities at all
+ new_id, new_order = new_rec[0], new_rec[1]
- query = """
- INSERT INTO activities (id, name, category_id, activity_order)
- VALUES (?, ?, ?, ?)
- """
- self.execute(query, (new_id, activity['name'], activity['category_id'], new_order))
- activity['id'] = new_id
- else: # Update
- query = """
- UPDATE activities
- SET name = ?,
- category_id = ?
- WHERE id = ?
- """
- self.execute(query, (activity['name'], activity['category_id'], activity['id']))
+ query = """
+ INSERT INTO activities (id, name, category_id, activity_order)
+ VALUES (?, ?, ?, ?)
+ """
+ self.execute(query, (new_id, name, category_id, new_order))
+ return new_id
- return activity['id']
+ def __update_activity(self, id, name, category_id):
+ query = """
+ UPDATE activities
+ SET name = ?,
+ category_id = ?
+ WHERE id = ?
+ """
+ self.execute(query, (name, category_id, id))
""" Here be dragons (lame connection/cursor wrappers) """
def get_connection(self):
View
18 hamster/storage.py
@@ -58,14 +58,20 @@ def change_category(self, id, category_id):
def swap_activities(self, id1, id2):
return self.__swap_activities(id1, id2)
- def update_activity(self, activity):
- result = self.__update_activity(activity)
+ def update_activity(self, id, name, category_id):
+ self.__update_activity(id, name, category_id)
self.dispatch('activity_updated', ())
- return result
+
+ def insert_activity(self, name, category_id = -1):
+ new_id = self.__insert_activity(name, category_id)
+ self.dispatch('activity_updated', ())
+ return new_id
+
+ def update_category(self, id, name):
+ self.__update_category(id, name)
- def update_category_name(self, id, new_name):
- res = self.__update_category_name(id, new_name)
- return res
+ def insert_category(self, name):
+ return self.__insert_category(name)
def get_category_list(self):

0 comments on commit 5673bbc

Please sign in to comment.
Something went wrong with that request. Please try again.