Commit 48c3e1d1 authored by Kai Willadsen's avatar Kai Willadsen

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
parent e8af9866
......@@ -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>
......
......@@ -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)
......
......@@ -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)
......
......@@ -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
......
......@@ -90,28 +90,6 @@ class NewDocDialog(gnomeglade.Component):
self.widget.destroy()
################################################################################
#
# 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);
......
import historyentry
import msgarea
import statusbar
import meld.linkmap
import meld.diffmap
import meld.util.sourceviewer
### 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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment