[meld] Add new statusbar class supporting per-view information areas



commit 48c3e1d164d6b75a13e7dc38f2a53fb7a612682e
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Tue Oct 9 07:37:10 2012 +1000

    Add new statusbar class supporting per-view information areas
    
    The new MeldStatusBar subclasses gtk.Statusbar, mucking with internal
    packing and the like to provide better behaviour for Meld. The
    progressbar has been changed to use pulse mode exclusively (we never
    used anything else) and progress text is now shown in the progress bar.
    The space on the right of the statusbar is now an 'information area'
    that individual pages fill themselves.
    
    data/ui/meldapp.ui: Remove old Statusbars, and create our custom one
    meld/dirdiff.py: Adapt to new API
    meld/filediff.py: Adapt to new API
    meld/ui/statusbar.py: New file for MeldStatusBar class
    meld/ui/gladesupport.py: Support UIBuilder construction
    meld/meldapp.py: Absorb some on_idle logic into the new status bar
    meld/melddoc.py: Remove the 'status-changed' signal and provide a
                     harness for individual page status areas

 data/ui/meldapp.ui      |   34 +------------------
 meld/dirdiff.py         |   16 ++++++++-
 meld/filediff.py        |   14 +++++++-
 meld/melddoc.py         |    4 ++
 meld/meldwindow.py      |   65 +++++++++---------------------------
 meld/ui/gladesupport.py |    1 +
 meld/ui/statusbar.py    |   83 +++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 134 insertions(+), 83 deletions(-)
---
diff --git a/data/ui/meldapp.ui b/data/ui/meldapp.ui
index e6968cb..e22856e 100644
--- a/data/ui/meldapp.ui
+++ b/data/ui/meldapp.ui
@@ -29,42 +29,12 @@
           </packing>
         </child>
         <child>
-          <object class="GtkHBox" id="status_box">
+          <object class="MeldStatusBar" id="statusbar">
             <property name="visible">True</property>
-            <child>
-              <object class="GtkProgressBar" id="task_progress">
-                <property name="visible">True</property>
-                <property name="pulse_step">0.109999999404</property>
-                <property name="text" translatable="yes"/>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkStatusbar" id="task_status">
-                <property name="visible">True</property>
-                <property name="has_resize_grip">False</property>
-              </object>
-              <packing>
-                <property name="position">1</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkStatusbar" id="doc_status">
-                <property name="width_request">175</property>
-                <property name="visible">True</property>
-              </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">False</property>
-                <property name="position">2</property>
-              </packing>
-            </child>
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="fill">False</property>
+            <property name="fill">True</property>
             <property name="position">0</property>
             <property name="pack_type">GTK_PACK_END</property>
           </packing>
diff --git a/meld/dirdiff.py b/meld/dirdiff.py
index 0386a26..6802622 100644
--- a/meld/dirdiff.py
+++ b/meld/dirdiff.py
@@ -281,6 +281,14 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
         self.on_treeview_focus_out_event(None, None)
         self.treeview_focussed = None
 
+        lastchanged_label = gtk.Label()
+        lastchanged_label.set_size_request(100, -1)
+        lastchanged_label.show()
+        permissions_label = gtk.Label()
+        permissions_label.set_size_request(100, -1)
+        permissions_label.show()
+        self.status_info_labels = [lastchanged_label, permissions_label]
+
         for i in range(3):
             self.treeview[i].get_selection().set_mode(gtk.SELECTION_MULTIPLE)
             column = gtk.TreeViewColumn()
@@ -845,9 +853,13 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
                 stat = os.stat(fname)
             # TypeError for if fname is None
             except (OSError, TypeError):
-                self.emit("status-changed", "")
+                self.status_info_labels[0].set_text("")
+                self.status_info_labels[1].set_markup("")
             else:
-                self.emit("status-changed", "%s : %s" % (rwx(stat.st_mode), nice(time.time() - stat.st_mtime) ) )
+                mode_text = "<tt>%s</tt>" % rwx(stat.st_mode)
+                last_changed_text = str(nice(time.time() - stat.st_mtime))
+                self.status_info_labels[0].set_text(last_changed_text)
+                self.status_info_labels[1].set_markup(mode_text)
 
     def on_treeview_key_press_event(self, view, event):
         pane = self.treeview.index(view)
diff --git a/meld/filediff.py b/meld/filediff.py
index 0db8536..2b1398f 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -231,6 +231,14 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
         self.undosequence.connect("checkpointed", self.on_undo_checkpointed)
         self.connect("next-conflict-changed", self.on_next_conflict_changed)
 
+        overwrite_label = gtk.Label()
+        overwrite_label.set_size_request(50, -1)
+        overwrite_label.show()
+        cursor_label = gtk.Label()
+        cursor_label.set_size_request(150, -1)
+        cursor_label.show()
+        self.status_info_labels = [overwrite_label, cursor_label]
+
     def get_keymask(self):
         return self._keymask
     def set_keymask(self, value):
@@ -333,7 +341,11 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
         insert_overwrite = self._insert_overwrite_text[self.textview_overwrite]
         line_column = self._line_column_text % (line + 1, offset + 1)
         status = "%s : %s" % (insert_overwrite, line_column)
-        self.emit("status-changed", status)
+        # FIXME: Think this status-changed is wrong...
+        # self.emit("status-changed", status)
+
+        self.status_info_labels[0].set_text(insert_overwrite)
+        self.status_info_labels[1].set_text(line_column)
 
         if line != self.cursor.line or force:
             chunk, prev, next = self.linediffer.locate_chunk(pane, line)
diff --git a/meld/melddoc.py b/meld/melddoc.py
index 55fe965..28961b6 100644
--- a/meld/melddoc.py
+++ b/meld/melddoc.py
@@ -56,6 +56,10 @@ class MeldDoc(gobject.GObject):
         self.num_panes = 0
         self.label_text = _("untitled")
         self.tooltip_text = _("untitled")
+        self.status_info_labels = []
+
+    def get_info_widgets(self):
+        return self.status_info_labels
 
     def save(self):
         pass
diff --git a/meld/meldwindow.py b/meld/meldwindow.py
index 97d4014..26f1d21 100644
--- a/meld/meldwindow.py
+++ b/meld/meldwindow.py
@@ -92,28 +92,6 @@ class NewDocDialog(gnomeglade.Component):
 
 ################################################################################
 #
-# MeldStatusBar
-#
-################################################################################
-
-class MeldStatusBar(object):
-
-    def __init__(self, task_progress, task_status, doc_status):
-        self.task_progress = task_progress
-        self.task_status = task_status
-        self.doc_status = doc_status
-
-    def set_task_status(self, status):
-        self.task_status.pop(1)
-        self.task_status.push(1, status)
-
-    def set_doc_status(self, status):
-        self.doc_status.pop(1)
-        self.doc_status.push(1, status)
-
-
-################################################################################
-#
 # MeldApp
 #
 ################################################################################
@@ -205,9 +183,7 @@ class MeldWindow(gnomeglade.Component):
 
         self.appvbox.pack_start(self.menubar, expand=False)
         self.appvbox.pack_start(self.toolbar, expand=False)
-        # TODO: should possibly use something other than doc_status
-        self._menu_context = self.doc_status.get_context_id("Tooltips")
-        self.statusbar = MeldStatusBar(self.task_progress, self.task_status, self.doc_status)
+        self._menu_context = self.statusbar.get_context_id("Tooltips")
         self.widget.drag_dest_set(
             gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP,
             [ ('text/uri-list', 0, 0) ],
@@ -216,7 +192,7 @@ class MeldWindow(gnomeglade.Component):
                             self.on_widget_drag_data_received)
         self.toolbar.set_style(app.prefs.get_toolbar_style())
         self.toolbar.props.visible = app.prefs.toolbar_visible
-        self.status_box.props.visible = app.prefs.statusbar_visible
+        self.statusbar.props.visible = app.prefs.statusbar_visible
         app.prefs.notify_add(self.on_preference_changed)
         self.idle_hooked = 0
         self.scheduler = task.LifoScheduler()
@@ -268,41 +244,35 @@ class MeldWindow(gnomeglade.Component):
             widget.disconnect(cid)
 
     def _on_action_item_select_enter(self, item, tooltip):
-        self.statusbar.doc_status.push(self._menu_context, tooltip)
+        self.statusbar.push(self._menu_context, tooltip)
 
     def _on_action_item_deselect_leave(self, item):
-        self.statusbar.doc_status.pop(self._menu_context)
+        self.statusbar.pop(self._menu_context)
 
     def on_idle(self):
         ret = self.scheduler.iteration()
-        if ret:
-            if type(ret) in (type(""), type(u"")):
-                self.statusbar.set_task_status(ret)
-            elif type(ret) == type(0.0):
-                self.statusbar.task_progress.set_fraction(ret)
-            else:
-                self.statusbar.task_progress.pulse()
-        else:
-            self.statusbar.task_progress.set_fraction(0)
-        if self.scheduler.tasks_pending():
-            self.actiongroup.get_action("Stop").set_sensitive(True)
-            return 1
-        else:
+        if ret and isinstance(ret, basestring):
+            self.statusbar.set_task_status(ret)
+
+        pending = self.scheduler.tasks_pending()
+        if not pending:
+            self.statusbar.stop_pulse()
             self.statusbar.set_task_status("")
-            self.idle_hooked = 0
+            self.idle_hooked = None
             self.actiongroup.get_action("Stop").set_sensitive(False)
-            return 0
+        return pending
 
     def on_scheduler_runnable(self, sched):
         if not self.idle_hooked:
-            self.idle_hooked = 1
-            gobject.idle_add( self.on_idle )
+            self.statusbar.start_pulse()
+            self.actiongroup.get_action("Stop").set_sensitive(True)
+            self.idle_hooked = gobject.idle_add(self.on_idle)
 
     def on_preference_changed(self, key, value):
         if key == "toolbar_style":
             self.toolbar.set_style(app.prefs.get_toolbar_style())
         elif key == "statusbar_visible":
-            self.status_box.props.visible = app.prefs.statusbar_visible
+            self.statusbar.props.visible = app.prefs.statusbar_visible
         elif key == "toolbar_visible":
             self.toolbar.props.visible = app.prefs.toolbar_visible
 
@@ -348,7 +318,7 @@ class MeldWindow(gnomeglade.Component):
 
         nbl = self.notebook.get_tab_label( newdoc.widget )
         self.widget.set_title(nbl.get_label_text() + " - Meld")
-        self.statusbar.set_doc_status("")
+        self.statusbar.set_info_box(newdoc.get_info_widgets())
         self.diff_handler = newdoc.connect("next-diff-changed",
                                            self.on_next_diff_changed)
         newdoc.on_container_switch_in_event(self.ui)
@@ -623,7 +593,6 @@ class MeldWindow(gnomeglade.Component):
         page.connect("label-changed", self.on_notebook_label_changed)
         page.connect("file-changed", self.on_file_changed)
         page.connect("create-diff", lambda obj,arg: self.append_diff(arg) )
-        page.connect("status-changed", lambda junk,arg: self.statusbar.set_doc_status(arg) )
 
         # Allow reordering of tabs
         self.notebook.set_tab_reorderable(page.widget, True);
diff --git a/meld/ui/gladesupport.py b/meld/ui/gladesupport.py
index 4afbf6d..f542307 100644
--- a/meld/ui/gladesupport.py
+++ b/meld/ui/gladesupport.py
@@ -1,6 +1,7 @@
 
 import historyentry
 import msgarea
+import statusbar
 import meld.linkmap
 import meld.diffmap
 import meld.util.sourceviewer
diff --git a/meld/ui/statusbar.py b/meld/ui/statusbar.py
new file mode 100644
index 0000000..8dd5713
--- /dev/null
+++ b/meld/ui/statusbar.py
@@ -0,0 +1,83 @@
+### Copyright (C) 2012 Kai Willadsen <kai willadsen gmail com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import gobject
+import gtk
+import pango
+
+class MeldStatusBar(gtk.Statusbar):
+    __gtype_name__ = "MeldStatusBar"
+
+    def __init__(self):
+        gtk.Statusbar.__init__(self)
+        self.props.spacing = 6
+
+        if hasattr(self, "get_message_area"):
+            # FIXME: added in 2.20, but not in the corresponding pygtk. Use this if available
+            hbox = self.get_message_area()
+        else:
+            frame = self.get_children()[0]
+            self.set_child_packing(frame, False, False, 0, gtk.PACK_START)
+            hbox = frame.get_child()
+        hbox.props.spacing = 6
+
+        label = hbox.get_children()[0]
+        label.props.ellipsize = pango.ELLIPSIZE_NONE
+        hbox.remove(label)
+
+        self.progress = gtk.ProgressBar()
+        self.progress.props.pulse_step = 0.02
+        self.progress.props.ellipsize = pango.ELLIPSIZE_END
+        self.progress.set_size_request(200, -1)
+        progress_font = self.progress.get_style().font_desc
+        progress_font.set_size(progress_font.get_size() - 2 * pango.SCALE)
+        self.progress.modify_font(progress_font)
+        hbox.pack_start(self.progress, expand=False)
+        self.progress.show()
+        hbox.pack_start(label)
+
+        alignment = gtk.Alignment(xalign=1.0)
+        self.info_box = gtk.HBox(False, 6)
+        self.info_box.show()
+        alignment.add(self.info_box)
+        self.pack_start(alignment, expand=True)
+        alignment.show()
+
+        self.timeout_source = None
+
+    def start_pulse(self):
+        self.progress.show()
+        if self.timeout_source is None:
+            def pulse():
+                self.progress.pulse()
+                return True
+            self.timeout_source = gobject.timeout_add(50, pulse)
+
+    def stop_pulse(self):
+        if self.timeout_source is not None:
+            gobject.source_remove(self.timeout_source)
+            self.timeout_source = None
+        self.progress.set_fraction(0)
+        self.progress.hide()
+
+    def set_task_status(self, status):
+        self.progress.set_text(status)
+
+    def set_info_box(self, widgets):
+        for child in self.info_box.get_children():
+            self.info_box.remove(child)
+        for widget in widgets:
+            self.info_box.pack_end(widget)



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