[Dextrose] [PATCH 1/5][dx3][sugar] multi-selection listmodel

Martin Abente martin.abente.lahaye at gmail.com
Tue Jun 7 17:46:22 EDT 2011


Implements the selection logic by adding a "_selection" set
to the ListModel class. This set stores the uid of the entries
(from the the current result_set) that are marked as selected
from the view.

Adds the new column to the treemodel and the changes to the
on_get_value method to feed every row with the selection
information.

Fires a "select" signal to communicate the current status of
the selection and in some cases to force the view redraw.

Uses a "_query_set_cache" set to store the uid from all
the entries that belong to the current result_set. This cache
is necessary to maintain a decent performance while doing common
selection operations.

Signed-off-by: Martin Abente <martin.abente.lahaye at gmail.com>
---
 src/jarabe/journal/listmodel.py |   56 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 56 insertions(+), 0 deletions(-)

diff --git a/src/jarabe/journal/listmodel.py b/src/jarabe/journal/listmodel.py
index 3902eba..e2061fb 100644
--- a/src/jarabe/journal/listmodel.py
+++ b/src/jarabe/journal/listmodel.py
@@ -40,6 +40,7 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
     __gsignals__ = {
         'ready': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
         'progress': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
+        'select': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([bool, bool]))
     }
 
     COLUMN_UID = 0
@@ -54,6 +55,7 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
     COLUMN_BUDDY_1 = 9
     COLUMN_BUDDY_2 = 10
     COLUMN_BUDDY_3 = 11
+    COLUMN_SELECT = 12
 
     _COLUMN_TYPES = {
         COLUMN_UID: str,
@@ -68,6 +70,7 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
         COLUMN_BUDDY_1: object,
         COLUMN_BUDDY_3: object,
         COLUMN_BUDDY_2: object,
+        COLUMN_SELECT: bool
     }
 
     _PAGE_SIZE = 10
@@ -80,6 +83,10 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
         self._result_set = model.find(query, ListModel._PAGE_SIZE)
         self._temp_drag_file_path = None
 
+        # Multi-selection stuff
+        self._selection = set()
+        self._query_set_cache = set()
+
         # HACK: The view will tell us that it is resizing so the model can
         # avoid hitting D-Bus and disk.
         self.view_is_resizing = False
@@ -93,6 +100,16 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
     def __result_set_progress_cb(self, **kwargs):
         self.emit('progress')
 
+    def _get_query_set(self):
+        if self._query_set_cache:
+            return self._query_set_cache
+        query_set = set()
+        def collect(model, path, iter):
+            query_set.add(model[path][ListModel.COLUMN_UID])
+        self.foreach(collect)
+        self._query_set_cache = query_set
+        return query_set
+
     def setup(self):
         self._result_set.setup()
 
@@ -102,6 +119,37 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
     def get_metadata(self, path):
         return model.get(self[path][ListModel.COLUMN_UID])
 
+    def get_selection(self):
+        return self._selection.copy()
+
+    def add_selection(self, selection):
+        if type(selection) is set:
+            query_set = self._get_query_set()
+            selection = selection.intersection(query_set)
+            self._selection = self._selection.union(selection)
+        self._emit_select()
+
+    def set_selection_all(self):
+        query_set = self._get_query_set()
+        self._selection = self._selection.union(query_set)
+        self._emit_select(refresh_view=True)
+
+    def set_selection_none(self):
+        self._selection = set()
+        self._emit_select(refresh_view=True)
+
+    def toggle_selection(self, path):
+        uid = self[path][ListModel.COLUMN_UID]
+        if uid in self._selection:
+           self._selection.discard(uid)
+        else:
+            self._selection.add(uid)
+        self._emit_select()
+
+    def _emit_select(self, refresh_view=False):
+        status = not (not self._selection)
+        self.emit('select', status, refresh_view)
+
     def on_get_n_columns(self):
         return len(ListModel._COLUMN_TYPES)
 
@@ -119,6 +167,11 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
             return None
 
         if index == self._last_requested_index:
+            # HACK: avoid redrawing the whole view just for one row
+            selected = (self._cached_row[ListModel.COLUMN_UID] \
+                       in self._selection)
+            self._cached_row[ListModel.COLUMN_SELECT] = selected
+
             return self._cached_row[column]
 
         if index >= self._result_set.length:
@@ -199,6 +252,9 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
 
             self._cached_row.append(None)
 
+        selected = (metadata['uid'] in self._selection)
+        self._cached_row.append(selected)
+
         return self._cached_row[column]
 
     def on_iter_nth_child(self, iterator, n):
-- 
1.7.4.4



More information about the Dextrose mailing list