From f71b628a22168033e080b8483ca0a17582932419 Mon Sep 17 00:00:00 2001
From: Aleksey Lim <alsroot@member.fsf.org>
Date: Sat, 5 Sep 2009 22:41:32 +0000
Subject: Journal list view: jumping back to first page when popping up a palette #1235

---
 src/jarabe/journal/listmodel.py |   57 +++++++++++++++++++++++++++++++++-----
 src/jarabe/journal/listview.py  |   44 ++++++++++--------------------
 src/jarabe/journal/model.py     |    3 ++
 3 files changed, 67 insertions(+), 37 deletions(-)

diff --git a/src/jarabe/journal/listmodel.py b/src/jarabe/journal/listmodel.py
index 917fbb1..ac8fccd 100644
--- a/src/jarabe/journal/listmodel.py
+++ b/src/jarabe/journal/listmodel.py
@@ -35,12 +35,18 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
     __gtype_name__ = 'JournalListModel'
 
     __gsignals__ = {
+        'setup':    (gobject.SIGNAL_RUN_FIRST,
+                     gobject.TYPE_NONE,
+                     ([])),
         'ready':    (gobject.SIGNAL_RUN_FIRST,
                      gobject.TYPE_NONE,
                      ([])),
         'progress': (gobject.SIGNAL_RUN_FIRST,
                      gobject.TYPE_NONE,
                      ([])),
+        'invalidated': (gobject.SIGNAL_RUN_FIRST,
+                        gobject.TYPE_NONE,
+                        ([])),
     }
 
     COLUMN_UID = 0
@@ -67,30 +73,65 @@ class ListModel(gtk.GenericTreeModel, gtk.TreeDragSource):
 
     _PAGE_SIZE = 10
 
-    def __init__(self, query):
+    def __init__(self):
         gobject.GObject.__init__(self)
 
+        self._query = None
         self._last_requested_index = None
         self._cached_row = None
-        self._result_set = model.find(query, ListModel._PAGE_SIZE)
+        self._result_set = None
         self._temp_drag_file_path = None
 
         # 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
 
-        self._result_set.ready.connect(self.__result_set_ready_cb)
+        model.updated.connect(self.__model_updated_cb)
+        model.created.connect(self.__model_created_cb)
+        model.deleted.connect(self.__model_deleted_cb)
+
+    def refresh(self, query):
+        self._query = query
+
+        old_len = None
+        if self._result_set is not None:
+            old_len = self._result_set.length
+            self._result_set.stop()
+
+        self._last_requested_index = None
+        self._cached_row = None
+
+        self.emit('setup')
+
+        def result_set_ready_cb(**kwargs):
+            if old_len is not None:
+                new_len = len(self)
+                for i in range(old_len, new_len):
+                    self.emit('row-inserted', (i, ), self.get_iter((i, )))
+                for i in reversed(range(new_len, old_len)):
+                    self.emit('row-deleted', (i, ))
+            self.emit('ready')
+
+        self._result_set = model.find(self._query, ListModel._PAGE_SIZE)
+        self._result_set.ready.connect(result_set_ready_cb)
         self._result_set.progress.connect(self.__result_set_progress_cb)
+        self._result_set.setup()
+
+    def __model_updated_cb(self, sender, **kwargs):
+        self._result_set.invalidate()
+        self._last_requested_index = None
+        self._cached_row = None
+        self.emit('invalidated')
+
+    def __model_created_cb(self, sender, **kwargs):
+        self.refresh(self._query)
 
-    def __result_set_ready_cb(self, **kwargs):
-        self.emit('ready')
+    def __model_deleted_cb(self, sender, **kwargs):
+        self.refresh(self._query)
 
     def __result_set_progress_cb(self, **kwargs):
         self.emit('progress')
 
-    def setup(self):
-        self._result_set.setup()
-
     def stop(self):
         self._result_set.stop()
 
diff --git a/src/jarabe/journal/listview.py b/src/jarabe/journal/listview.py
index 057b7c4..7d1e9b9 100644
--- a/src/jarabe/journal/listview.py
+++ b/src/jarabe/journal/listview.py
@@ -101,23 +101,9 @@ class BaseListView(gtk.Bin):
 
         # Auto-update stuff
         self._fully_obscured = True
-        self._dirty = False
         self._refresh_idle_handler = None
         self._update_dates_timer = None
 
-        model.created.connect(self.__model_created_cb)
-        model.updated.connect(self.__model_updated_cb)
-        model.deleted.connect(self.__model_deleted_cb)
-
-    def __model_created_cb(self, sender, **kwargs):
-        self._set_dirty()
-
-    def __model_updated_cb(self, sender, **kwargs):
-        self._set_dirty()
-
-    def __model_deleted_cb(self, sender, **kwargs):
-        self._set_dirty()
-
     def _add_columns(self):
         cell_favorite = CellRendererFavorite(self.tree_view)
         cell_favorite.connect('clicked', self.__favorite_clicked_cb)
@@ -278,16 +264,17 @@ class BaseListView(gtk.Bin):
 
     def refresh(self):
         logging.debug('ListView.refresh query %r', self._query)
-        self._stop_progress_bar()
-        self._start_progress_bar()
-
-        if self._model is not None:
-            self._model.stop()
 
-        self._model = ListModel(self._query)
+        self._model = ListModel()
+        self._model.connect('setup', self.__model_setup_cb)
         self._model.connect('ready', self.__model_ready_cb)
         self._model.connect('progress', self.__model_progress_cb)
-        self._model.setup()
+        self._model.connect('invalidated', self.__model_invalidated_cb)
+        self._model.refresh(self._query)
+
+    def __model_setup_cb(self, tree_model):
+        self._stop_progress_bar()
+        self._start_progress_bar()
 
     def __model_ready_cb(self, tree_model):
         self._stop_progress_bar()
@@ -320,6 +307,9 @@ class BaseListView(gtk.Bin):
                 self._progress_bar.pulse()
                 self._last_progress_bar_pulse = time.time()
 
+    def __model_invalidated_cb(self, tree_model):
+        self.tree_view.queue_draw()
+
     def _start_progress_bar(self):
         alignment = gtk.Alignment(xalign=0.5, yalign=0.5, xscale=0.5)
         self.remove(self.child)
@@ -408,18 +398,14 @@ class BaseListView(gtk.Bin):
                 next_iter = self._model.iter_next(self._model.get_iter(path))
                 path = self._model.get_path(next_iter)
 
-    def _set_dirty(self):
-        if self._fully_obscured:
-            self._dirty = True
-        else:
-            self.refresh()
-
     def set_is_visible(self, visible):
+        if visible != self._fully_obscured:
+            return
+
         logging.debug('canvas_visibility_notify_event_cb %r', visible)
+
         if visible:
             self._fully_obscured = False
-            if self._dirty:
-                self.refresh()
             if self._update_dates_timer is None:
                 logging.debug('Adding date updating timer')
                 self._update_dates_timer = \
diff --git a/src/jarabe/journal/model.py b/src/jarabe/journal/model.py
index 8ae78d8..76ac791 100644
--- a/src/jarabe/journal/model.py
+++ b/src/jarabe/journal/model.py
@@ -199,6 +199,9 @@ class BaseResultSet(object):
 
         return self._cache[self._position - self._offset]
 
+    def invalidate(self):
+        self._cache = _Cache()
+
 class DatastoreResultSet(BaseResultSet):
     """Encapsulates the result of a query on the datastore
     """
-- 
1.6.3.3

