commit 5d05a442373b252ed21f2cad237d1ed37786390c
Author: Kamran Riaz Khan <krkhan(a)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)
+