From 00b1083e59eed27f99f2355fc5ec4fa5a38e6e42 Mon Sep 17 00:00:00 2001 From: DrFrasierCrane Date: Mon, 17 Dec 2007 19:41:55 +0100 Subject: [PATCH] Added "Add child" context menu option, more fixes on tree view manipulation... --- data/ui.xml | 2 ++ straw/FeedListView.py | 64 ++++++++++++++++++++++++++++++------------------- straw/FeedManager.py | 59 +++++++++++++++++++++++---------------------- straw/helpers.py | 1 + straw/model/__init__.py | 6 ++--- 5 files changed, 76 insertions(+), 56 deletions(-) diff --git a/data/ui.xml b/data/ui.xml index 8c58734..1dda723 100644 --- a/data/ui.xml +++ b/data/ui.xml @@ -3,6 +3,8 @@ + + diff --git a/straw/FeedListView.py b/straw/FeedListView.py index f5982ae..4768409 100644 --- a/straw/FeedListView.py +++ b/straw/FeedListView.py @@ -30,7 +30,7 @@ import pango import straw class Column: - pixbuf, name, foreground, unread, object = range(5) + pixbuf, name, foreground, unread, object, editable = range(6) _tmp_widget = gtk.Label() @@ -48,11 +48,9 @@ class TreeViewNode(object): #debug("obj %d changed: property.name = %s, self.path = %s, self.store[path].id = %s" % (obj.id, property.name, str(self.path), str(self.store[self.path][Column.object].node.id))) #debug("obj %d changed: property.name = %s, self.path = %s, self.store[path].id = %s" % (obj.id, property.name, str(self.path), str(self.store[self.path][Column.object].node.id))) if property.name == "unread-count": - #import time - #if self.unread_count == 794: - # time.sleep(2) debug("obj %d changed: property.name = %s, self.path = %s, self.store[path].id = %s" % (obj.id, property.name, str(self.path), str(self.store[self.path][Column.object].node.id))) debug("setting %d unread_count = %d, self.path = %s" % (obj.id, self.unread_count, str(self.path))) + self.store.set(self.iter, 3, self.node.unread_count) elif property.name == "status": if (self.node.status & straw.FS_UPDATING) > 0: @@ -166,7 +164,7 @@ class FeedListModel: self.tv_nodes[node.parent_id] = [TreeViewNode(child_node, self.store) for child_node in node.parent.children] def _prepare_store(self): - self.store = gtk.TreeStore(gtk.gdk.Pixbuf, str, str, str, gobject.TYPE_PYOBJECT) + self.store = gtk.TreeStore(gtk.gdk.Pixbuf, str, str, str, gobject.TYPE_PYOBJECT, bool) def _populate_tree(self, parent_id, parent_iter, done): if not self.tv_nodes.has_key(parent_id): @@ -186,12 +184,12 @@ class FeedListModel: if self.tv_nodes.has_key(node.id): self._populate_tree(node.id, current_parent, done) - def _create_row(self, node): + def _create_row(self, node, editable = False): return self.store.append(node.parent_iter, [node.pixbuf, node.title, 'black', node.unread_count, - node]) + node, editable]) def add_node(self, tv_node): if not self.tv_nodes.has_key(tv_node.node.parent_id): @@ -241,10 +239,16 @@ class FeedsView(MVP.WidgetView): # feed title renderer title_renderer = gtk.CellRendererText() + + title_renderer.connect("edited", self.on_node_edit_title_edited) + title_renderer.connect("editing-canceled", self.on_node_edit_title_canceled) + + #title_renderer.set_property('editable', True) column.pack_start(title_renderer, False) column.set_attributes(title_renderer, foreground=Column.foreground, - markup=Column.name) #, weight=Column.BOLD) + markup=Column.name, + editable=Column.editable) #, weight=Column.BOLD) self._widget.append_column(column) @@ -257,6 +261,8 @@ class FeedsView(MVP.WidgetView): uifactory = helpers.UIFactory('FeedListActions') action = uifactory.get_action('/feedlist_popup/refresh') action.connect('activate', self.on_menu_poll_selected_activate) + action = uifactory.get_action('/feedlist_popup/add_child') + action.connect('activate', self.on_menu_add_child_activate) action = uifactory.get_action('/feedlist_popup/mark_as_read') action.connect('activate', self.on_menu_mark_all_as_read_activate) action = uifactory.get_action('/feedlist_popup/stop_refresh') @@ -277,11 +283,8 @@ class FeedsView(MVP.WidgetView): def on_dragdata_received_cb(self, treeview, drag_context, x, y, selection, info, eventtime): model, iter_to_copy = treeview.get_selection().get_selected() - #print locals() temp = treeview.get_dest_row_at_pos(x, y) - #temp = treeview.get_drag_dest_row() - if temp != None: path, pos = temp else: @@ -292,11 +295,6 @@ class FeedsView(MVP.WidgetView): if self.check_row_path(model, iter_to_copy, target_iter): path = model.get_path(iter_to_copy) - #model.insert_before(None, None, model[path]) - #print model[path][Column.object].obj.title - #print "previous = %s" % str(path) - #print "target = %s" % str(path_of_target_iter) - #print path_of_target_iter[len(path_of_target_iter) - 1] from_path = path to_path = list(path_of_target_iter) @@ -325,19 +323,14 @@ class FeedsView(MVP.WidgetView): to_path.append(path_of_target_iter[len(path_of_target_iter) - 1] + 1) print "%s -> %s" % (str(from_path), str(to_path)) - #print model[0][Column.object].node.id + node = model[from_path][Column.object].node self.iter_copy(model, iter_to_copy, target_iter, pos) drag_context.finish(True, True, eventtime) FeedManager.move_node(node, to_path) - #print model[0][Column.object].node.id - #model.remove(iter_to_copy) - #treeview.expand_all() else: drag_context.finish(False, False, eventtime) - - print model[0][Column.object].node.id def check_row_path(self, model, iter_to_copy, target_iter): path_of_iter_to_copy = model.get_path(iter_to_copy) @@ -381,6 +374,8 @@ class FeedsView(MVP.WidgetView): path = treeview.get_path_at_pos(x, y) if path is None: return 1 + + self.node_at_popup = self.model.store[path[0]][Column.object] path, col, cellx, celly = path selection = treeview.get_selection() selection.unselect_all() @@ -389,6 +384,10 @@ class FeedsView(MVP.WidgetView): self.popup.popup(None, None, None, event.button, time) retval = 1 return retval + + def get_selected_tv_node(self): + selection = self._widget.get_selection() + (model, pathlist) = selection.get_selected_rows() def foreach_selected(self, func): selection = self._widget.get_selection() @@ -399,9 +398,18 @@ class FeedsView(MVP.WidgetView): object = model.get_value(treeiter, Column.object) func(object, model, treeiter) except TypeError, te: - ## XXX maybe object is a category logging.exception(te) return + + def on_menu_add_child_activate(self, *args): + category = Category() + category.parent = self.node_at_popup.node#FeedManager.get_model()[1] + self.new_child = TreeViewNode(category, self.model.store) + iter = self.model._create_row(self.new_child, editable = True) + path = self.model.store.get_path(iter) + column = self._widget.get_column(0) + self._widget.grab_focus() + self._widget.set_cursor_on_cell(path, focus_column = column, start_editing = True) def on_menu_poll_selected_activate(self, *args): config = Config.get_instance() @@ -430,7 +438,15 @@ class FeedsView(MVP.WidgetView): idx = feedlist.index(object.feed) del feedlist[idx] self.foreach_selected(remove) - return + + def on_node_edit_title_canceled(self, cellrenderer): + print "on_node_edit_title_canceled" + + def on_node_edit_title_edited(self, cellrenderertext, path, new_text): + self.new_child.node.name = new_text + FeedManager.save_category(self.new_child.node) + self.model.store.remove(self.new_child.iter) + self.new_child = None def on_display_properties_feed(self, *args): selection = self._widget.get_selection() diff --git a/straw/FeedManager.py b/straw/FeedManager.py index b7751e2..a98ecab 100644 --- a/straw/FeedManager.py +++ b/straw/FeedManager.py @@ -48,9 +48,9 @@ def update_all_feeds(observers, feeds = None): fm = _get_instance() return fm.update_all_feeds(observers, feeds) -def save_category(title, pid = None): +def save_category(category): fm = _get_instance() - return fm.save_category(title, parent_id = pid) + return fm.save_category(category) def save_feed(feed): fm = _get_instance() @@ -99,10 +99,21 @@ class FeedManager(GObject): self.dao = DAO(self.storage) self.nodes = self.dao.get_nodes() - #self._process_model() self._prepare_model() - - #print self.nodes[1].children + + def _prepare_model(self): + for node in self.nodes.values(): + self._setup_node_signals(node) + + if node.parent_id != None: + node.parent = self.nodes[node.parent_id] + node.parent.append_child(node) + else: + node.parent = None + + def _setup_node_signals(self, node): + node.connect("parent-changed", self.on_parent_changed) + node.connect("norder-changed", self.on_norder_changed) def import_opml(self, path, category): job = Job("opml-parse") @@ -122,11 +133,7 @@ class FeedManager(GObject): self.nodes[node.parent_id].add_child(node) def move_node(self, node, target_path): - #print node - #print new_parent - #print new_order - #print self.nodes[1].get_by_path(new_parent) - #print "move_node %d to %s [%s]" % (node.id, str(new_parent), new_parent[:-1]) + debug("fm:move_node %d to %s" % (node.id, str(target_path))) new_parent = self.nodes[1].get_by_path(target_path[:-1]) if not new_parent: @@ -136,9 +143,6 @@ class FeedManager(GObject): def save_all(self, save_list): for item in save_list: - item.connect("parent-changed", self.on_parent_changed) - item.connect("norder-changed", self.on_norder_changed) - if isinstance(item, Feed): item.parent_id = 1 @@ -177,6 +181,7 @@ class FeedManager(GObject): self.nodes[feed.id] = feed self._model_add_node(feed) + self._setup_node_signals(feed) self.emit("feed-added", feed) return result @@ -216,18 +221,27 @@ class FeedManager(GObject): self.dao.tx_commit() - ### CATEGORIES + # CATEGORIES def save_category(self, category): + debug("saving category %s with parent %s" % (category.name, str(category.parent_id))) + + if category.parent and not category.parent_id: + category.parent_id = category.parent.id + + self.dao.tx_begin() + self.dao.save(category) + self._model_add_node(category) + self.dao.save(category) + + self.dao.tx_commit() self.nodes[category.id] = category - self._model_add_node(category) + self._setup_node_signals(category) self.emit("category-added", category) - # ITEMS - def get_feed_items(self, id): feed = self.lookup_feed(id) feed.items = self.dao.get(Item, " WHERE feed_id = %d" % feed.id) @@ -268,17 +282,6 @@ class FeedManager(GObject): result = self.dao.get(Item, " WHERE feed_id = ? AND title = ?", (item.feed_id, item.title,)) return len(result) > 0 - def _prepare_model(self): - for node in self.nodes.values(): - node.connect("parent-changed", self.on_parent_changed) - node.connect("norder-changed", self.on_norder_changed) - - if node.parent_id != None: - node.parent = self.nodes[node.parent_id] - node.parent.append_child(node) - else: - node.parent = None - def on_item_is_read_changed(self, obj, is_read): self.dao.save(obj) diff --git a/straw/helpers.py b/straw/helpers.py index c346955..501566d 100644 --- a/straw/helpers.py +++ b/straw/helpers.py @@ -35,6 +35,7 @@ class UIFactory(object): actions = [ ("refresh", gtk.STOCK_REFRESH, _("_Refresh"), None, _("Update this feed"), None), + ("add_child", gtk.STOCK_ADD, _("Add child"), None, _("Update this feed"), None), ("mark_as_read", gtk.STOCK_CLEAR, _("_Mark As Read"), None, _("Mark all items in this feed as read"), None), ("stop_refresh", None, _("_Stop Refresh"), None, _("Stop updating this feed"), None), diff --git a/straw/model/__init__.py b/straw/model/__init__.py index da06345..31b53a5 100644 --- a/straw/model/__init__.py +++ b/straw/model/__init__.py @@ -142,13 +142,11 @@ class Node(gobject.GObject): self.parent.props.unread_count += self.unread_count def get_by_path(self, path): - #print "sss %d | %s | %s" % (self.id, str(path), str(len(self.children))) + print "sss %d | %s | %s" % (self.id, str(path), str(len(self.children))) if len(path) == 0: return self elif path[0] < len(self.children): - #print len(self.children) - #print self.children[path[0]].id - return self.children[path[0]].get_by_path(path[:-1]) + return self.children[path[0]].get_by_path(path[1:]) else: return None -- 2.11.4.GIT