[meld] Rework VC and DirDiff TreeViews to take text attributes from the store



commit e80379d338a5af4ab3525c46d45806e268dc4bca
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Wed Sep 8 07:26:17 2010 +1000

    Rework VC and DirDiff TreeViews to take text attributes from the store
    
    The existing code used string substitution into markup to format
    cells in the TreeViews. While this worked, the approach was messy to
    theme. With this commit, we instead store pango, etc. attributes in
    the TreeStore and set column properties appropriately.
    
    While this should make themeing improvements easier, there are no
    themeing changes in this commit.

 meld/dirdiff.py |   23 ++++++++-----
 meld/tree.py    |   98 ++++++++++++++++++++++++++++++++----------------------
 meld/vcview.py  |   26 +++++++++-----
 3 files changed, 89 insertions(+), 58 deletions(-)
---
diff --git a/meld/dirdiff.py b/meld/dirdiff.py
index 556315e..d744cf4 100644
--- a/meld/dirdiff.py
+++ b/meld/dirdiff.py
@@ -165,8 +165,7 @@ COL_EMBLEM, COL_END = tree.COL_END, tree.COL_END + 1
 ################################################################################
 class DirDiffTreeStore(tree.DiffTreeStore):
     def __init__(self, ntree):
-        types = [str] * COL_END * ntree
-        tree.DiffTreeStore.__init__(self, ntree, types)
+        tree.DiffTreeStore.__init__(self, ntree, [str])
 
 
 class CanonicalListing(object):
@@ -286,7 +285,12 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
             column.pack_start(renicon, expand=0)
             column.pack_start(rentext, expand=1)
             col_index = self.model.column_index
-            column.set_attributes(rentext, markup=col_index(tree.COL_TEXT,i))
+            column.set_attributes(rentext, text=col_index(tree.COL_TEXT,i),
+                                  foreground=col_index(tree.COL_FG, i),
+                                  background=col_index(tree.COL_BG, i),
+                                  style=col_index(tree.COL_STYLE, i),
+                                  weight=col_index(tree.COL_WEIGHT, i),
+                                  strikethrough=col_index(tree.COL_STRIKE, i))
             column.set_attributes(renicon,
                                   icon_name=col_index(tree.COL_ICON, i),
                                   emblem_name=col_index(COL_EMBLEM, i),
@@ -1025,26 +1029,27 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
                 isdir = os.path.isdir( files[j] )
                 # TODO: Differentiate the DodgySame case
                 if all_same == Same or all_same == DodgySame:
-                    self.model.set_state(it, j,  tree.STATE_NORMAL, isdir)
+                    self.model.set_path_state(it, j, tree.STATE_NORMAL, isdir)
                     different = 0
                 elif all_same == SameFiltered:
-                    self.model.set_state(it, j,  tree.STATE_NOCHANGE, isdir)
+                    self.model.set_path_state(it, j, tree.STATE_NOCHANGE, isdir)
                     different = 0
                 # TODO: Differentiate the SameFiltered and DodgySame cases
                 elif all_present_same in (Same, SameFiltered, DodgySame):
-                    self.model.set_state(it, j,  tree.STATE_NEW, isdir)
+                    self.model.set_path_state(it, j, tree.STATE_NEW, isdir)
                 elif all_same == FileError or all_present_same == FileError:
-                    self.model.set_state(it, j,  tree.STATE_ERROR, isdir)
+                    self.model.set_path_state(it, j, tree.STATE_ERROR, isdir)
                 # Different and DodgyDifferent
                 else:
-                    self.model.set_state(it, j,  tree.STATE_MODIFIED, isdir)
+                    self.model.set_path_state(it, j, tree.STATE_MODIFIED, isdir)
                 self.model.set_value(it,
                     self.model.column_index(COL_EMBLEM, j),
                     j == newest_index and "emblem-meld-newer-file" or None)
                 one_isdir[j] = isdir
         for j in range(self.model.ntree):
             if not mod_times[j]:
-                self.model.set_state(it, j, tree.STATE_MISSING, True in one_isdir)
+                self.model.set_path_state(it, j, tree.STATE_MISSING,
+                                          True in one_isdir)
         return different
 
     def popup_in_pane(self, pane, event):
diff --git a/meld/tree.py b/meld/tree.py
index df29187..4906236 100644
--- a/meld/tree.py
+++ b/meld/tree.py
@@ -17,8 +17,13 @@
 import os
 import gobject
 import gtk
+import pango
+
+COL_PATH, COL_STATE, COL_TEXT, COL_ICON, COL_TINT, COL_FG, COL_BG, COL_STYLE, \
+    COL_WEIGHT, COL_STRIKE, COL_END = range(11)
+
+COL_TYPES = (str, str, str, str, str, str, str, pango.Style, pango.Weight, bool)
 
-COL_PATH, COL_STATE, COL_TEXT, COL_ICON, COL_TINT, COL_END = range(6)
 
 from meld.vc._vc import \
     STATE_IGNORED, STATE_NONE, STATE_NORMAL, STATE_NOCHANGE, \
@@ -30,25 +35,31 @@ from meld.vc._vc import \
 class DiffTreeStore(gtk.TreeStore):
 
     def __init__(self, ntree, types):
-        gtk.TreeStore.__init__(self, *types)
+        full_types = []
+        for col_type in (COL_TYPES + tuple(types)):
+            full_types.extend([col_type] * ntree)
+        gtk.TreeStore.__init__(self, *full_types)
         self.ntree = ntree
         self._setup_default_styles()
 
     def _setup_default_styles(self):
-        self.textstyle = [
-            '<span foreground="#888888">%s</span>', # STATE_IGNORED
-            '<span foreground="#888888">%s</span>', # STATE_NONE
-            '%s', # STATE_NORMAL
-            '<span style="italic">%s</span>', # STATE_NOCHANGE
-            '<span foreground="#ff0000" background="yellow" weight="bold">%s</span>', # STATE_ERROR
-            '<span foreground="#999999" style="italic">%s</span>', # STATE_EMPTY
-            '<span foreground="#008800" weight="bold">%s</span>', # STATE_NEW
-            '<span foreground="#880000" weight="bold">%s</span>', # STATE_MODIFIED
-            '<span foreground="#ff0000" background="#ffeeee" weight="bold">%s</span>', # STATE_CONFLICT
-            '<span foreground="#880000" strikethrough="true" weight="bold">%s</span>', # STATE_REMOVED
-            '<span foreground="#888888" strikethrough="true">%s</span>' # STATE_MISSING
+        roman, italic = pango.STYLE_NORMAL, pango.STYLE_ITALIC
+        normal, bold = pango.WEIGHT_NORMAL, pango.WEIGHT_BOLD
+
+        self.text_attributes = [
+            # foreground, background, style, weight, strikethrough
+            ("#888888", None,      roman,     normal, None), # STATE_IGNORED
+            ("#888888", None,      roman,     normal, None), # STATE_NONE
+            (None,      None,      roman,     normal, None), # STATE_NORMAL
+            (None,      None,      italic,    normal, None), # STATE_NOCHANGE
+            ("#ff0000", "yellow",  roman,     bold,   None), # STATE_ERROR
+            ("#999999", None,      italic,    normal, None), # STATE_EMPTY
+            ("#008800", None,      roman,     bold,   None), # STATE_NEW
+            ("#880000", None,      roman,     bold,   None), # STATE_MODIFIED
+            ("#ff0000", "#ffeeee", roman,     bold,   None), # STATE_CONFLICT
+            ("#880000", None,      roman,     bold,   True), # STATE_REMOVED
+            ("#888888", None,      roman,     normal, True), # STATE_MISSING
         ]
-        assert len(self.textstyle) == STATE_MAX
 
         self.pixstyle = [
             ("text-x-generic", "folder"), # IGNORED
@@ -78,51 +89,58 @@ class DiffTreeStore(gtk.TreeStore):
             ("#ffffff", "#ffffff"), # MISSING
         ]
 
-        assert len(self.pixstyle) == len(self.icon_tints) == STATE_MAX
+        assert len(self.pixstyle) == len(self.icon_tints) == len(self.text_attributes) == STATE_MAX
+
+    def value_paths(self, it):
+        return [self.value_path(it, i) for i in range(self.ntree)]
+
+    def value_path(self, it, pane):
+        return self.get_value(it, self.column_index(COL_PATH, pane))
+
+    def column_index(self, col, pane):
+        return self.ntree * col + pane
 
     def add_entries(self, parent, names):
         child = self.append(parent)
-        for i,f in enumerate(names):
-            self.set_value( child, self.column_index(COL_PATH,i), f)
+        for pane, path in enumerate(names):
+            self.set_value(child, self.column_index(COL_PATH, pane), path)
         return child
 
     def add_empty(self, parent, text="empty folder"):
-        child = self.append(parent)
-        for i in range(self.ntree):
-            self.set_value(child, self.column_index(COL_PATH, i), None)
-            self.set_value(child, self.column_index(COL_STATE, i), str(STATE_EMPTY))
-            self.set_value(child, self.column_index(COL_ICON, i), self.pixstyle[STATE_EMPTY][0])
-            self.set_value(child, self.column_index(COL_TEXT, i), self.textstyle[STATE_EMPTY] % gobject.markup_escape_text(text))
-        return child
+        it = self.append(parent)
+        for pane in range(self.ntree):
+            self.set_value(it, self.column_index(COL_PATH, pane), None)
+            self.set_state(it, pane, STATE_EMPTY, text)
 
     def add_error(self, parent, msg, pane):
-        err = self.append(parent)
+        it = self.append(parent)
         for i in range(self.ntree):
-            self.set_value(err, self.column_index(COL_STATE, i), str(STATE_ERROR))
-        self.set_value(err, self.column_index(COL_ICON, pane), self.pixstyle[STATE_ERROR][0] )
-        self.set_value(err, self.column_index(COL_TINT, pane),
-                       self.icon_tints[STATE_ERROR][0])
-        self.set_value(err, self.column_index(COL_TEXT, pane), self.textstyle[STATE_ERROR] % gobject.markup_escape_text(msg))
+            self.set_value(it, self.column_index(COL_STATE, i),
+                           str(STATE_ERROR))
+        self.set_state(it, pane, STATE_ERROR, msg)
 
-    def value_paths(self, it):
-        return [self.value_path(it, i) for i in range(self.ntree)]
-    def value_path(self, it, pane):
-        return self.get_value(it, self.column_index(COL_PATH, pane))
-    def column_index(self, col, pane):
-        return self.ntree * col + pane
-
-    def set_state(self, it, pane, state, isdir=0):
+    def set_path_state(self, it, pane, state, isdir=0):
         fullname = self.get_value(it, self.column_index(COL_PATH,pane))
         name = gobject.markup_escape_text(os.path.basename(fullname))
+        self.set_state(it, pane, state, name, isdir)
+
+    def set_state(self, it, pane, state, label, isdir=0):
         STATE = self.column_index(COL_STATE, pane)
         TEXT  = self.column_index(COL_TEXT,  pane)
         ICON  = self.column_index(COL_ICON,  pane)
         TINT  = self.column_index(COL_TINT,  pane)
         self.set_value(it, STATE, str(state))
-        self.set_value(it, TEXT,  self.textstyle[state] % name)
+        self.set_value(it, TEXT, gobject.markup_escape_text(label))
         self.set_value(it, ICON,  self.pixstyle[state][isdir])
         self.set_value(it, TINT,  self.icon_tints[state][isdir])
 
+        state_attr = self.text_attributes[state]
+        self.set_value(it, self.column_index(COL_FG, pane), state_attr[0])
+        self.set_value(it, self.column_index(COL_BG, pane), state_attr[1])
+        self.set_value(it, self.column_index(COL_STYLE, pane), state_attr[2])
+        self.set_value(it, self.column_index(COL_WEIGHT, pane), state_attr[3])
+        self.set_value(it, self.column_index(COL_STRIKE, pane), state_attr[4])
+
     def get_state(self, it, pane):
         STATE = self.column_index(COL_STATE, pane)
         return int(self.get_value(it, STATE))
diff --git a/meld/vcview.py b/meld/vcview.py
index 3e8da6f..7cf57e1 100644
--- a/meld/vcview.py
+++ b/meld/vcview.py
@@ -17,10 +17,12 @@
 
 import tempfile
 import shutil
-import gtk
 import os
 from gettext import gettext as _
 
+import gtk
+import pango
+
 import tree
 import misc
 from ui import gnomeglade
@@ -80,10 +82,9 @@ COL_LOCATION, COL_STATUS, COL_REVISION, COL_TAG, COL_OPTIONS, COL_END = range(tr
 
 class VcTreeStore(tree.DiffTreeStore):
     def __init__(self):
-        ntree = 1
-        types = [str] * COL_END * ntree
-        tree.DiffTreeStore.__init__(self, ntree, types)
-        self.textstyle[tree.STATE_MISSING] = '<span foreground="#000088" strikethrough="true" weight="bold">%s</span>'
+        tree.DiffTreeStore.__init__(self, 1, [str] * 5)
+        self.text_attributes[tree.STATE_MISSING] = \
+                ("#000088", None, pango.STYLE_NORMAL, pango.WEIGHT_BOLD, True)
 
 ################################################################################
 # filters
@@ -172,7 +173,14 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
         column.set_attributes(renicon,
                               icon_name=col_index(tree.COL_ICON, 0),
                               icon_tint=col_index(tree.COL_TINT, 0))
-        column.set_attributes(rentext, markup=col_index(tree.COL_TEXT, 0))
+        column.set_attributes(rentext,
+                    text=col_index(tree.COL_TEXT, 0),
+                    foreground=col_index(tree.COL_FG, 0),
+                    background=col_index(tree.COL_BG, 0),
+                    style=col_index(tree.COL_STYLE, 0),
+                    weight=col_index(tree.COL_WEIGHT, 0),
+                    strikethrough=col_index(tree.COL_STRIKE, 0))
+
         self.treeview.append_column(column)
 
         def addCol(name, num):
@@ -303,7 +311,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
         it = self.model.add_entries( None, [location] )
         self.treeview.grab_focus()
         self.treeview.get_selection().select_iter(it)
-        self.model.set_state(it, 0, tree.STATE_NORMAL, isdir=1)
+        self.model.set_path_state(it, 0, tree.STATE_NORMAL, isdir=1)
         self.recompute_label()
         self.scheduler.remove_all_tasks()
 
@@ -620,7 +628,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
             if it:
                 newiter = self.model.insert_after( None, it)
                 self.model.set_value(newiter, self.model.column_index( tree.COL_PATH, 0), where)
-                self.model.set_state(newiter, 0, tree.STATE_NORMAL, isdir=1)
+                self.model.set_path_state(newiter, 0, tree.STATE_NORMAL, True)
                 self.model.remove(it)
                 self.scheduler.add_task( self._search_recursively_iter(newiter).next )
         else: # XXX fixme
@@ -628,7 +636,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
 
     def _update_item_state(self, it, vcentry, location):
         e = vcentry
-        self.model.set_state( it, 0, e.state, e.isdir )
+        self.model.set_path_state(it, 0, e.state, e.isdir)
         def setcol(col, val):
             self.model.set_value(it, self.model.column_index(col, 0), val)
         setcol(COL_LOCATION, location)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]