Simplify status bar and fix justification of filter status

svn: r22872
This commit is contained in:
Nick Hall 2013-08-15 22:08:23 +00:00
parent 2d8b44db89
commit c56996b635
3 changed files with 74 additions and 249 deletions

View File

@ -69,6 +69,7 @@ from gramps.gen.relationship import get_relationship_calculator
from .glade import Glade from .glade import Glade
from gramps.gen.utils.db import navigation_label from gramps.gen.utils.db import navigation_label
from gramps.gen.constfunc import UNITYPE, cuni from gramps.gen.constfunc import UNITYPE, cuni
from .widgets.progressdialog import ProgressMonitor, GtkProgressDialog
DISABLED = -1 DISABLED = -1
@ -389,30 +390,28 @@ class DisplayState(Callback):
BUSY_CURSOR = Gdk.Cursor.new(Gdk.CursorType.WATCH) BUSY_CURSOR = Gdk.Cursor.new(Gdk.CursorType.WATCH)
def __init__(self, window, status, progress, warnbtn, uimanager, def __init__(self, window, status, uimanager, viewmanager=None):
progress_monitor, viewmanager=None):
self.busy = False self.busy = False
self.cursor = None self.cursor = None
self.viewmanager = viewmanager self.viewmanager = viewmanager
self.uimanager = uimanager self.uimanager = uimanager
self.progress_monitor = progress_monitor self.progress_monitor = ProgressMonitor(GtkProgressDialog, ("", window))
self.window = window self.window = window
Callback.__init__(self) Callback.__init__(self)
self.status = status self.status = status
self.status_id = status.get_context_id('GRAMPS') self.status_id = status.get_context_id('GRAMPS')
self.progress = progress self.progress = status.get_progress_bar()
self.history_lookup = {} self.history_lookup = {}
self.gwm = GrampsWindowManager(uimanager) self.gwm = GrampsWindowManager(uimanager)
self.widget = None self.widget = None
self.disprel_old = '' self.disprel_old = ''
self.disprel_defpers = None self.disprel_defpers = None
self.disprel_active = None self.disprel_active = None
self.warnbtn = warnbtn
self.last_bar = self.status.insert(min_width=35, ralign=True)
self.set_relationship_class() self.set_relationship_class()
formatter = logging.Formatter('%(levelname)s %(name)s: %(message)s') formatter = logging.Formatter('%(levelname)s %(name)s: %(message)s')
warnbtn = status.get_warning_button()
self.rhandler = WarnHandler(capacity=400, button=warnbtn) self.rhandler = WarnHandler(capacity=400, button=warnbtn)
self.rhandler.setFormatter(formatter) self.rhandler.setFormatter(formatter)
self.rhandler.setLevel(logging.WARNING) self.rhandler.setLevel(logging.WARNING)
@ -560,12 +559,10 @@ class DisplayState(Callback):
#text = ((_("%(nav_type)s View") % {"nav_type": _(nav_type)}) + #text = ((_("%(nav_type)s View") % {"nav_type": _(nav_type)}) +
text = (self.viewmanager.active_page.get_title() + text = (self.viewmanager.active_page.get_title() +
(": %d/%d" % (matched, total))) (": %d/%d" % (matched, total)))
self.status.pop(1, self.last_bar) self.status.set_filter(text)
self.status.push(1, text, self.last_bar)
def clear_filter_results(self): def clear_filter_results(self):
self.status.pop(1, self.last_bar) self.status.clear_filter()
self.status.push(1, '', self.last_bar)
def modify_statusbar(self, dbstate, active=None): def modify_statusbar(self, dbstate, active=None):
view = self.viewmanager.active_page view = self.viewmanager.active_page
@ -593,9 +590,12 @@ class DisplayState(Callback):
self.status.push(self.status_id, name) self.status.push(self.status_id, name)
process_pending_events() process_pending_events()
def pulse_progressbar(self, value): def pulse_progressbar(self, value, text=None):
self.progress.set_fraction(min(value/100.0, 1.0)) self.progress.set_fraction(min(value/100.0, 1.0))
self.progress.set_text("%d%%" % value) if text:
self.progress.set_text("%s: %d%%" % (text, value))
else:
self.progress.set_text("%d%%" % value)
process_pending_events() process_pending_events()
def status_text(self, text): def status_text(self, text):

View File

@ -90,7 +90,7 @@ from gramps.gen.config import config
from gramps.gen.errors import WindowActiveError from gramps.gen.errors import WindowActiveError
from .dialog import (ErrorDialog, WarningDialog, QuestionDialog2, from .dialog import (ErrorDialog, WarningDialog, QuestionDialog2,
InfoDialog) InfoDialog)
from . import widgets from .widgets import Statusbar
from .undohistory import UndoHistory from .undohistory import UndoHistory
from gramps.gen.utils.file import (media_path_full, get_unicode_path_from_env_var, from gramps.gen.utils.file import (media_path_full, get_unicode_path_from_env_var,
get_unicode_path_from_file_chooser) get_unicode_path_from_file_chooser)
@ -615,6 +615,7 @@ class ViewManager(CLIManager):
self.window = Gtk.Window() self.window = Gtk.Window()
self.window.set_icon_from_file(ICON) self.window.set_icon_from_file(ICON)
self.window.set_has_resize_grip(True)
self.window.set_default_size(width, height) self.window.set_default_size(width, height)
vbox = Gtk.VBox() vbox = Gtk.VBox()
@ -640,15 +641,13 @@ class ViewManager(CLIManager):
vbox.pack_start(self.menubar, False, True, 0) vbox.pack_start(self.menubar, False, True, 0)
vbox.pack_start(self.toolbar, False, True, 0) vbox.pack_start(self.toolbar, False, True, 0)
vbox.add(hpane) vbox.add(hpane)
vbox.pack_end(self.__setup_statusbar(), False, True, 0) self.statusbar = Statusbar()
self.statusbar.show()
vbox.pack_end(self.statusbar, False, True, 0)
vbox.show() vbox.show()
self.progress_monitor = ProgressMonitor( self.uistate = DisplayState(self.window, self.statusbar,
GtkProgressDialog, ("", self.window)) self.uimanager, self)
self.uistate = DisplayState(
self.window, self.statusbar, self.progress, self.warnbtn,
self.uimanager, self.progress_monitor, self)
self.dbstate.connect('database-changed', self.uistate.db_changed) self.dbstate.connect('database-changed', self.uistate.db_changed)
@ -685,28 +684,6 @@ class ViewManager(CLIManager):
# But we need to realize it here to have Gdk.window handy # But we need to realize it here to have Gdk.window handy
self.window.realize() self.window.realize()
def __setup_statusbar(self):
"""
Create the statusbar that sits at the bottom of the window
"""
self.progress = Gtk.ProgressBar()
self.progress.set_size_request(100, -1)
self.progress.hide()
self.statusbar = widgets.Statusbar()
self.statusbar.show()
self.warnbtn = widgets.WarnButton()
hbox2 = Gtk.HBox()
hbox2.set_spacing(4)
hbox2.set_border_width(2)
hbox2.pack_start(self.progress, False, True, 0)
hbox2.pack_start(self.warnbtn, False, True, 0)
hbox2.pack_end(self.statusbar, True, True, 0)
hbox2.show()
return hbox2
def __setup_navigator(self): def __setup_navigator(self):
""" """
If we have enabled te sidebar, show it, and turn off the tabs. If If we have enabled te sidebar, show it, and turn off the tabs. If
@ -1583,20 +1560,20 @@ class ViewManager(CLIManager):
if not yes_no: if not yes_no:
return return
self.uistate.set_busy_cursor(True) self.uistate.set_busy_cursor(True)
self.pulse_progressbar(0) self.uistate.pulse_progressbar(0)
self.uistate.progress.show() self.uistate.progress.show()
self.uistate.push_message(self.dbstate, _("Making backup...")) self.uistate.push_message(self.dbstate, _("Making backup..."))
if include.get_active(): if include.get_active():
from gramps.plugins.export.exportpkg import PackageWriter from gramps.plugins.export.exportpkg import PackageWriter
writer = PackageWriter(self.dbstate.db, filename, writer = PackageWriter(self.dbstate.db, filename,
User(error=ErrorDialog, User(error=ErrorDialog,
callback=self.pulse_progressbar)) callback=self.uistate.pulse_progressbar))
writer.export() writer.export()
else: else:
from gramps.plugins.export.exportxml import XmlWriter from gramps.plugins.export.exportxml import XmlWriter
writer = XmlWriter(self.dbstate.db, writer = XmlWriter(self.dbstate.db,
User(error=ErrorDialog, User(error=ErrorDialog,
callback=self.pulse_progressbar), callback=self.uistate.pulse_progressbar),
strip_photos=0, compress=1) strip_photos=0, compress=1)
writer.write(filename) writer.write(filename)
self.uistate.set_busy_cursor(False) self.uistate.set_busy_cursor(False)
@ -1608,15 +1585,6 @@ class ViewManager(CLIManager):
self.uistate.push_message(self.dbstate, _("Backup aborted")) self.uistate.push_message(self.dbstate, _("Backup aborted"))
window.destroy() window.destroy()
def pulse_progressbar(self, value, text=None):
self.progress.set_fraction(min(value/100.0, 1.0))
if text:
self.progress.set_text("%s: %d%%" % (text, value))
else:
self.progress.set_text("%d%%" % value)
while Gtk.events_pending():
Gtk.main_iteration()
def select_backup_path(self, widget, path_entry): def select_backup_path(self, widget, path_entry):
""" """
Choose a backup folder. Make sure there is one highlighted in Choose a backup folder. Make sure there is one highlighted in

View File

@ -1,7 +1,7 @@
# #
# Gramps - a GTK+/GNOME based genealogy program # Gramps - a GTK+/GNOME based genealogy program
# #
# Copyright (C) 2007-2008 Zsolt Foldvari # Copyright (C) 2013 Nick Hall
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -20,8 +20,6 @@
# $Id$ # $Id$
__all__ = ["Statusbar"]
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Standard python modules # Standard python modules
@ -35,9 +33,14 @@ _LOG = logging.getLogger(".widgets.statusbar")
# GTK/Gnome modules # GTK/Gnome modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from gi.repository import GObject
from gi.repository import Gtk from gi.repository import Gtk
from gi.repository import Pango
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from . import WarnButton
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -45,206 +48,60 @@ from gi.repository import Pango
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class Statusbar(Gtk.HBox): 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' A status bar
"""
##__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): def __init__(self):
GObject.GObject.__init__(self) Gtk.HBox.__init__(self)
# initialize property values self.set_spacing(4)
self.__has_resize_grip = True self.set_border_width(2)
# create the main statusbar with id #0
main_bar = Gtk.Statusbar()
main_bar.show()
self.pack_start(main_bar, True, True, 0)
self._bars = {0: main_bar}
##TODO GTK3: statusbar no longer has resize grip methods, depracate this part self.__progress = Gtk.ProgressBar()
## of Gramps Statusbar?? self.__progress.set_size_request(100, -1)
## self._set_resize_grip() self.__progress.hide()
##
## # 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 _get_next_id(self): self.__warnbtn = WarnButton()
"""Get next unused statusbar id.
"""
id = 1
while id in self._bars:
id = id + 1
return id
# Public API self.__status = Gtk.Statusbar()
self.__status.show()
def insert(self, index=-1, min_width=None, ralign=False):
"""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.show()
self.pack_start(new_bar, True, True, 0)
self.reorder_child(new_bar, index)
##TODO GTK3: statusbar no longer has resize grip methods, depracate this part
## of Gramps Statusbar??
## self._set_resize_grip()
if ralign:
frame = new_bar.get_children()[0]
obj = frame.get_children()[0]
# obj is HBox
obj = obj.get_children()[0]
##TODO GTK3: Check if following give expected alignment in statusbar
obj.valign = Gtk.Align(value=Gtk.Align.CENTER)
obj.halign = Gtk.Align(value=Gtk.Align.END)
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):
"""Return 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): self.__filter = Gtk.Label()
"""Push message onto a statusbar's stack. self.__filter.set_alignment(1.0, 0.5)
self.__filter.show()
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.
"""
# HACK: add an extra space so grip doesn't overlap
return self._bars[bar_id].push(context_id, text + " ")
def pop(self, context_id, bar_id=0): self.pack_start(self.__warnbtn, False, True, 4)
"""Remove the top message from a statusbar's stack. self.pack_start(self.__progress, False, True, 4)
self.pack_start(self.__status, True, True, 4)
The target statusbar is identified by bar_id created when statusbar self.pack_end(self.__filter, False, True, 4)
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): def get_warning_button(self):
"""Remove the message with the specified message_id. """Return the warning button widget."""
return self.__warnbtn
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')
def main(args): def get_progress_bar(self):
win = Gtk.Window() """Return the progress bar widget."""
win.set_title('Statusbar test window') return self.__progress
win.set_position(Gtk.WindowPosition.CENTER)
def cb(window, event):
Gtk.main_quit()
win.connect('delete-event', cb)
vbox = Gtk.VBox() def get_context_id(self, context_description):
win.add(vbox) """Return a new or existing context identifier."""
return self.__status.get_context_id(context_description)
statusbar = Statusbar() def push(self, context_id, text):
vbox.pack_end(statusbar, False, True, 0) """Push message onto a statusbar's stack."""
return self.__status.push(context_id, text)
statusbar.push(1, "My statusbar")
my_statusbar = statusbar.insert()
statusbar.push(1, "Testing width", my_statusbar)
yet_another_statusbar = statusbar.insert()
statusbar.push(1, "A short one", yet_another_statusbar)
last_statusbar = statusbar.insert(ralign=True) def pop(self, context_id):
statusbar.push(1, "The last statusbar", """Remove the top message from a statusbar's stack."""
last_statusbar) self.__status.pop(context_id)
win.show_all()
Gtk.main()
if __name__ == '__main__': def remove(self, context_id, message_id):
import sys """Remove the message with the specified message_id."""
# fall back to root logger for testing self.__status.remove(context_id, message_id)
log = logging
sys.exit(main(sys.argv)) def set_filter(self, text):
"""Set the filter status text."""
self.__filter.set_text(text)
def clear_filter(self):
"""Clear the filter status text."""
self.__filter.set_text('')