[tor-commits] [arm/master] Replace list->treestore caching from conn panel with wrappers.

atagar at torproject.org atagar at torproject.org
Thu Aug 11 15:27:57 UTC 2011


commit 5d05a442373b252ed21f2cad237d1ed37786390c
Author: Kamran Riaz Khan <krkhan at inspirated.com>
Date:   Sun Jul 24 05:25:10 2011 +0500

    Replace list->treestore caching from conn panel with wrappers.
    
    The old method of refreshing treestore entries every three seconds via
    the CLI counterpart is replaced by the list wrapper (developed for
    config panel, part of gtkTools).
    
    The list wrapper patches the conn panel so that each time the CLI
    panel updates entryLines, the relevant treestore structures are updated
    automatically. This way, the treestores are only updated when arm
    backend is updated.
---
 src/gui/configPanel.py           |   18 ++---
 src/gui/connections/connPanel.py |  145 ++++++++++++-------------------------
 src/util/gtkTools.py             |   46 +++++++-----
 3 files changed, 82 insertions(+), 127 deletions(-)

diff --git a/src/gui/configPanel.py b/src/gui/configPanel.py
index a8d7f02..433d612 100644
--- a/src/gui/configPanel.py
+++ b/src/gui/configPanel.py
@@ -14,7 +14,7 @@ from util import connections, gtkTools, sysTools, torTools, uiTools
 from TorCtl import TorCtl
 
 class ConfContents(gtkTools.ListWrapper):
-  def _create_row_from_entry(self, entry):
+  def _create_row_from_value(self, entry):
     option = entry.get(Field.OPTION)
     value = entry.get(Field.VALUE)
     summary = entry.get(Field.SUMMARY)
@@ -30,25 +30,23 @@ class ConfigPanel(object, CliConfigPanel):
     self.builder = builder
 
     listStore = self.builder.get_object('liststore_config')
-    self._confImportantContents = ConfContents(self.confImportantContents, listStore)
-
-    self.confImportantContents += self.confImportantContents[-5:]
+    self._wrappedConfImportantContents = ConfContents(self.confImportantContents, listStore)
 
   @property
   def confImportantContents(self):
-    if hasattr(self, '_confImportantContents'):
-      return self._confImportantContents.container
+    if hasattr(self, '_wrappedConfImportantContents'):
+      return self._wrappedConfImportantContents.container
     else:
       return []
 
   @confImportantContents.setter
   def confImportantContents(self, value):
-    if hasattr(self, '_confImportantContents'):
-      self._confImportantContents.empty()
+    if hasattr(self, '_wrappedConfImportantContents'):
+      self._wrappedConfImportantContents.empty()
       for entry in value:
-        self._confImportantContents.append(entry)
+        self._wrappedConfImportantContents.append(entry)
     else:
-      self._confImportantContents = ConfContents(value)
+      self._wrappedConfImportantContents = ConfContents(value)
 
   def pack_widgets(self):
     treeView = self.builder.get_object('treeview_config')
diff --git a/src/gui/connections/connPanel.py b/src/gui/connections/connPanel.py
index 55669f9..9476059 100644
--- a/src/gui/connections/connPanel.py
+++ b/src/gui/connections/connPanel.py
@@ -11,43 +11,51 @@ from collections import deque
 import gobject
 import gtk
 
-from cli.connections import (circEntry as cliCircEntry, connEntry as cliConnEntry)
+from cli.connections import (circEntry as cliCircEntry, connEntry as cliConnEntry, entries)
 from cli.connections.connPanel import ConnectionPanel as CliConnectionPanel
 from gui.connections import circEntry, connEntry
-from util import connections, sysTools, uiTools, torTools
+from util import connections, gtkTools, sysTools, uiTools, torTools
 from TorCtl import TorCtl
 
-class GuiConverter:
+def convert_to_gui(cliInstance):
   cliToGuiMap = [ (cliCircEntry.CircHeaderLine, circEntry.CircHeaderLine),
                   (cliCircEntry.CircLine, circEntry.CircLine),
                   (cliConnEntry.ConnectionLine, connEntry.ConnectionLine)]
 
-  def __init__(self):
-    self._cache = {}
+  line = None
 
-  def __call__(self, cliInstance):
-    cacheKey = self._calculate_cache_key(cliInstance)
+  for (cliClass, guiClass) in cliToGuiMap:
+    if isinstance(cliInstance, cliClass):
+      line = guiClass(cliInstance)
+      break
 
-    if self._cache.has_key(cacheKey):
-      return self._cache[cacheKey]
+  return line
 
-    line = None
+class EntryLines(gtkTools.TreeWrapper):
+  def __init__(self, container, model=None, listingType=None):
+    gtkTools.TreeWrapper.__init__(self, container, model)
 
-    for (cliClass, guiClass) in GuiConverter.cliToGuiMap:
-      if isinstance(cliInstance, cliClass):
-        line = guiClass(cliInstance)
-        self._cache[cacheKey] = line
-        break
+    self._listingType = listingType if listingType else entries.ListingType.IP_ADDRESS
 
-    return line
+  def _model_append(self, cliLine):
+    if not self.model:
+      return
 
-  def _calculate_cache_key(self, entryLine):
-    local = (entryLine.local.ipAddr, entryLine.local.port)
-    foreign = (entryLine.foreign.ipAddr, entryLine.foreign.port)
+    row = self._create_row_from_value(cliLine)
+    line = convert_to_gui(cliLine)
 
-    return (entryLine.__class__, local, foreign)
+    if isinstance(line, circEntry.CircHeaderLine):
+      self.headerIter = self.model.append(None, row)
+    elif isinstance(line, circEntry.CircLine):
+      self.model.append(self.headerIter, row)
+    else:
+      self.model.append(None, row)
 
-convert_to_gui = GuiConverter()
+  def _create_row_from_value(self, cliLine):
+    line = convert_to_gui(cliLine)
+    row = line.get_listing_row(self._listingType)
+
+    return row
 
 class ConnectionPanel(CliConnectionPanel):
   def __init__(self, builder):
@@ -60,84 +68,25 @@ class ConnectionPanel(CliConnectionPanel):
     torCmdName = sysTools.getProcessName(torPid, 'tor')
     connections.getResolver(torCmdName, torPid, 'tor')
 
-    gobject.idle_add(self._fill_entries)
-    gobject.timeout_add(3000, self._timeout_fill_entries)
+    treeStore = self.builder.get_object('treestore_conn')
+    self._wrappedEntryLines = EntryLines(self._entryLines, treeStore)
+
+  @property
+  def _entryLines(self):
+    if hasattr(self, '_wrappedEntryLines'):
+      return self._wrappedEntryLines.container
+    else:
+      return []
+
+  @_entryLines.setter
+  def _entryLines(self, value):
+    if hasattr(self, '_wrappedEntryLines'):
+      self._wrappedEntryLines.empty()
+      for entry in value:
+        self._wrappedEntryLines.append(entry)
+    else:
+      self._wrappedEntryLines = EntryLines(value)
 
   def pack_widgets(self):
     self.start()
 
-  def _timeout_fill_entries(self):
-    self._fill_entries()
-
-    return True
-
-  def _fill_entries(self):
-    self.valsLock.acquire()
-
-    label = self.builder.get_object('label_conn_top')
-    label.set_text(self._title)
-
-    treeStore = self.builder.get_object('treestore_conn')
-
-    # first pass checks whether we have enough entries cached to not update the treeview
-    index = 0
-    for cliLine in self._entryLines:
-      line = convert_to_gui(cliLine)
-
-      treeIter = self._treestore_get_iter(line)
-
-      if treeIter:
-        if not isinstance(line, circEntry.CircLine):
-          timeLabel = "%d s" % (time.time() - line.cliLine.startTime)
-          treeStore.set_value(treeIter, 2, timeLabel)
-      else:
-        break
-
-      index = index + 1
-
-    if index == len(self._entryLines):
-      self.valsLock.release()
-      return True
-
-    # one of the entries was not found in cache, clear and repopulate the treeStore
-    treeStore.clear()
-    headerIter = None
-
-    for cliLine in self._entryLines:
-      line = convert_to_gui(cliLine)
-
-      if isinstance(line, connEntry.ConnectionLine) and line.cliLine.isUnresolvedApp():
-        self._resolveApps()
-
-      row = line.get_listing_row(self._listingType)
-
-      if isinstance(line, circEntry.CircHeaderLine):
-        currentIter = treeStore.append(None, row)
-        headerIter = currentIter
-      elif isinstance(line, circEntry.CircLine):
-        currentIter = treeStore.append(headerIter, row)
-      else:
-        currentIter = treeStore.append(None, row)
-
-    self.valsLock.release()
-
-  def _treestore_get_iter(self, line):
-    def match_func(model, treeIter, data):
-      column, key = data
-      value = model.get_value(treeIter, column)
-      return value == key
-
-    def search(model, treeIter, func, data):
-      while treeIter:
-        if func(model, treeIter, data):
-          return treeIter
-        result = search(model, model.iter_children(treeIter), func, data)
-        if result: return result
-        treeIter = model.iter_next(treeIter)
-      return None
-
-    treeStore = self.builder.get_object('treestore_conn')
-    matchIter = search(treeStore, treeStore.iter_children(None), match_func, (5, line))
-
-    return matchIter
-
diff --git a/src/util/gtkTools.py b/src/util/gtkTools.py
index b60a829..c1b14dd 100644
--- a/src/util/gtkTools.py
+++ b/src/util/gtkTools.py
@@ -25,16 +25,16 @@ class ListWrapper(object):
     self.container = []
     self.model = model
 
-    for entry in container:
-      self.append(entry)
+    for value in container:
+      self.append(value)
 
-  def append(self, entry):
-    self.container.append(entry)
-    gobject.idle_add(self.__model_append, entry)
+  def append(self, value):
+    self.container.append(value)
+    gobject.idle_add(self._model_append, value)
 
   def empty(self):
     self.container = []
-    gobject.idle_add(self.__model_clear)
+    gobject.idle_add(self._model_clear)
 
   def __str__(self):
     return str(self.container)
@@ -46,49 +46,57 @@ class ListWrapper(object):
     return len(self.container)
 
   def __iadd__(self, other):
-    for entry in other:
-      self.append(entry)
+    for value in other:
+      self.append(value)
 
   def __delitem__(self, key):
     del self.container[key]
 
-    gobject.idle_add(self.__model_del, key)
+    gobject.idle_add(self._model_del, key)
 
   def __getitem__(self, key):
     return self.container[key]
 
-  def __setitem__(self, key, entry):
-    self.container[key] = entry
+  def __setitem__(self, key, value):
+    self.container[key] = value
 
-    gobject.idle_add(self.__model_set, key, entry)
+    gobject.idle_add(self._model_set, key, value)
 
-  def __model_append(self, entry):
+  def _model_append(self, value):
     if not self.model:
       return
 
-    row = self._create_row_from_entry(entry)
+    row = self._create_row_from_value(value)
     self.model.append(row)
 
-  def __model_clear(self):
+  def _model_clear(self):
     if not self.model:
       return
 
     self.model.clear()
 
-  def __model_del(self, key):
+  def _model_del(self, key):
     if not self.model:
       return
 
     treeIter = self.model.get_iter(key)
     self.model.remove(treeIter)
 
-  def __model_set(self, key, entry):
+  def _model_set(self, key, value):
     if not self.model:
       return
 
-    row = self._create_row_from_entry(entry)
+    row = self._create_row_from_value(value)
     self.model[key] = row
 
-  def _create_row_from_entry(self, entry):
+  def _create_row_from_value(self, value):
     raise NotImplementedError("Subclass must implement abstract method")
 
+class TreeWrapper(ListWrapper):
+  def _model_append(self, value):
+    if not self.model:
+      return
+
+    row = self._create_row_from_value(value)
+    self.model.append(None, row)
+





More information about the tor-commits mailing list