diff --git a/ChangeLog b/ChangeLog index 7e4baf2be..999f33519 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2007-04-01 Zsolt Foldvari + * src/GrampsWidgets.py: Statusbar widget added. + * src/ViewManager.py: use custom Statusbar. + 2007-03-31 Brian Matherly * src/BaseDoc.py: * src/docgen/AbiWord2Doc.py: diff --git a/src/GrampsWidgets.py b/src/GrampsWidgets.py index 8f9070860..fb71573b9 100644 --- a/src/GrampsWidgets.py +++ b/src/GrampsWidgets.py @@ -46,6 +46,7 @@ log = logging.getLogger(".GrampsWidget") #------------------------------------------------------------------------- import gobject import gtk +import gtk.glade import pango #------------------------------------------------------------------------- @@ -684,6 +685,178 @@ class PlaceEntry: self.tooltips.set_tip(self.share, _('Select an existing place')) self.tooltips.set_tip(self.add_del, _('Add a new place')) +class Statusbar(gtk.HBox): + """Custom Statusbar with flexible number of "bars". + + Statusbar can have any number of fields included, each identified + by it's own bar id. It has by default one field with id = 0. This + defult field is used when no bar id is given in the relevant (push, pop, + etc.) methods, thus Statusbar behaves as a single gtk.Statusbar. + + To add a new field use the "insert" method. Using the received bar id + one can push, pop and remove messages to/from this newly inserted field. + + """ + __gtype_name__ = 'Statusbar' + + ##__gsignals__ = { + ##'text-popped': , + ##'text-pushed': , + ##} + + __gproperties__ = { + 'has-resize-grip': (gobject.TYPE_BOOLEAN, + 'Resize grip', + 'Whether resize grip is visible', + True, + gobject.PARAM_READWRITE), + } + + def __init__(self, min_width=300): + gtk.HBox.__init__(self) + + # initialize property values + self.__has_resize_grip = True + + # create the main statusbar with id #0 + main_bar = gtk.Statusbar() + main_bar.set_size_request(min_width, -1) + main_bar.show() + self.pack_start(main_bar) + self._bars = {0: main_bar} + self._set_resize_grip() + + # Virtual methods + + def do_get_property(self, prop): + '''Return the gproperty's value. + ''' + if prop.name == 'has-resize-grip': + return self.__has_resize_grip + else: + raise AttributeError, 'unknown property %s' % prop.name + + def do_set_property(self, prop, value): + '''Set the property of writable properties. + ''' + if prop.name == 'has-resize-grip': + self.__has_resize_grip = value + self._set_resize_grip() + else: + raise AttributeError, 'unknown or read only property %s' % prop.name + + # Private + + def _set_resize_grip(self): + """Set the resize grip for the statusbar. + + Resize grip is disabled for all statusbars except the last one, + which is set according to the "has-resize-grip" propery. + + """ + for bar in self.get_children(): + bar.set_has_resize_grip(False) + + bar.set_has_resize_grip(self.get_property('has-resize-grip')) + + def _set_packing(self): + """Set packing style of the statusbars. + + All bars are packed with "expand"=False, "fill"=False parameters, + except the last one, which is packed with "expand"=True, "fill"=True. + + """ + for bar in self.get_children(): + self.set_child_packing(bar, False, False, 0, gtk.PACK_START) + + self.set_child_packing(bar, True, True, 0, gtk.PACK_START) + + def _get_next_id(self): + """Get next unused statusbar id. + """ + id = 1 + while id in self._bars.keys(): + id = id + 1 + + return id + + # Public API + + def insert(self, index=-1, min_width=300): + """Insert a new statusbar. + + Create a new statusbar and insert it at the given index. Index starts + from '0'. If index is negative the new statusbar is appended. + The new bar_id is returned. + + """ + new_bar = gtk.Statusbar() + new_bar.set_size_request(min_width, -1) + new_bar.show() + self.pack_start(new_bar) + self.reorder_child(new_bar, index) + self._set_resize_grip() + self._set_packing() + + new_bar_id = self._get_next_id() + self._bars[new_bar_id] = new_bar + + return new_bar_id + + def get_context_id(self, context_description, bar_id=0): + """Returns a new or existing context identifier. + + The target statusbar is identified by bar_id created when statusbar + was added. + Existence of the bar_id is not checked as giving a wrong id is + programming fault. + + """ + return self._bars[bar_id].get_context_id(context_description) + + def push(self, context_id, text, bar_id=0): + """Push message onto a statusbar's stack. + + The target statusbar is identified by bar_id created when statusbar + was added. + Existence of the bar_id is not checked as giving a wrong id is + programming fault. + + """ + return self._bars[bar_id].push(context_id, text) + + def pop(self, context_id, bar_id=0): + """Remove the top message from a statusbar's stack. + + The target statusbar is identified by bar_id created when statusbar + was added. + Existence of the bar_id is not checked as giving a wrong id is + programming fault. + + """ + self._bars[bar_id].pop(context_id) + + def remove(self, context_id, message_id, bar_id=0): + """Remove the message with the specified message_id. + + Remove the message with the specified message_id and context_id + from the statusbar's stack, which is identified by bar_id. + Existence of the bar_id is not checked as giving a wrong id is + programming fault. + + """ + self._bars[bar_id].remove(context_id, message_id) + + def set_has_resize_grip(self, setting): + """Mirror gtk.Statusbar functionaliy. + """ + self.set_property('has-resize-grip', setting) + + def get_has_resize_grip(self): + """Mirror gtk.Statusbar functionaliy. + """ + return self.get_property('has-resize-grip') + #============================================================================ # # MaskedEntry and ValidatableMaskedEntry copied and merged from the Kiwi @@ -2368,6 +2541,24 @@ def main(args): widget2.connect('validate', on_validate) widget2.mandatory = True vbox.pack_start(widget2, fill=False) + + # == Statusbar testing ==================================================== + statusbar = Statusbar() + vbox.pack_end(statusbar, False) + + statusbar.push(1, "Testing status bar") + + my_statusbar = statusbar.insert(min_width=200) + statusbar.push(1, "This is my statusbar...", my_statusbar) + + yet_another_statusbar = statusbar.insert(1, 100) + statusbar.push(1, "A short one", yet_another_statusbar) + + last_statusbar = statusbar.insert() + statusbar.push(1, "I'm the last statusbar always taking " + "the remaining space", last_statusbar) + + # ========================================================================= win.show_all() gtk.main() diff --git a/src/ViewManager.py b/src/ViewManager.py index cf7e47fd2..59ead4134 100644 --- a/src/ViewManager.py +++ b/src/ViewManager.py @@ -219,7 +219,7 @@ class ViewManager: self.window.set_icon_from_file(const.icon) self.window.set_default_size(width, height) - self.statusbar = gtk.Statusbar() + self.statusbar = GrampsWidgets.Statusbar() self.RelClass = relationship_class