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

View File

@ -90,7 +90,7 @@ from gramps.gen.config import config
from gramps.gen.errors import WindowActiveError
from .dialog import (ErrorDialog, WarningDialog, QuestionDialog2,
InfoDialog)
from . import widgets
from .widgets import Statusbar
from .undohistory import UndoHistory
from gramps.gen.utils.file import (media_path_full, get_unicode_path_from_env_var,
get_unicode_path_from_file_chooser)
@ -615,6 +615,7 @@ class ViewManager(CLIManager):
self.window = Gtk.Window()
self.window.set_icon_from_file(ICON)
self.window.set_has_resize_grip(True)
self.window.set_default_size(width, height)
vbox = Gtk.VBox()
@ -640,15 +641,13 @@ class ViewManager(CLIManager):
vbox.pack_start(self.menubar, False, True, 0)
vbox.pack_start(self.toolbar, False, True, 0)
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()
self.progress_monitor = ProgressMonitor(
GtkProgressDialog, ("", self.window))
self.uistate = DisplayState(
self.window, self.statusbar, self.progress, self.warnbtn,
self.uimanager, self.progress_monitor, self)
self.uistate = DisplayState(self.window, self.statusbar,
self.uimanager, self)
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
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):
"""
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:
return
self.uistate.set_busy_cursor(True)
self.pulse_progressbar(0)
self.uistate.pulse_progressbar(0)
self.uistate.progress.show()
self.uistate.push_message(self.dbstate, _("Making backup..."))
if include.get_active():
from gramps.plugins.export.exportpkg import PackageWriter
writer = PackageWriter(self.dbstate.db, filename,
User(error=ErrorDialog,
callback=self.pulse_progressbar))
callback=self.uistate.pulse_progressbar))
writer.export()
else:
from gramps.plugins.export.exportxml import XmlWriter
writer = XmlWriter(self.dbstate.db,
User(error=ErrorDialog,
callback=self.pulse_progressbar),
callback=self.uistate.pulse_progressbar),
strip_photos=0, compress=1)
writer.write(filename)
self.uistate.set_busy_cursor(False)
@ -1608,15 +1585,6 @@ class ViewManager(CLIManager):
self.uistate.push_message(self.dbstate, _("Backup aborted"))
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):
"""
Choose a backup folder. Make sure there is one highlighted in

View File

@ -1,7 +1,7 @@
#
# 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
# it under the terms of the GNU General Public License as published by
@ -20,8 +20,6 @@
# $Id$
__all__ = ["Statusbar"]
#-------------------------------------------------------------------------
#
# Standard python modules
@ -35,9 +33,14 @@ _LOG = logging.getLogger(".widgets.statusbar")
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
from gi.repository import GObject
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):
"""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),
}
A status bar
"""
def __init__(self):
GObject.GObject.__init__(self)
# initialize property values
self.__has_resize_grip = True
# 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}
Gtk.HBox.__init__(self)
self.set_spacing(4)
self.set_border_width(2)
##TODO GTK3: statusbar no longer has resize grip methods, depracate this part
## of Gramps Statusbar??
## 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'))
self.__progress = Gtk.ProgressBar()
self.__progress.set_size_request(100, -1)
self.__progress.hide()
def _get_next_id(self):
"""Get next unused statusbar id.
"""
id = 1
while id in self._bars:
id = id + 1
return id
self.__warnbtn = WarnButton()
# Public API
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)
self.__status = Gtk.Statusbar()
self.__status.show()
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.
"""
# HACK: add an extra space so grip doesn't overlap
return self._bars[bar_id].push(context_id, text + " ")
self.__filter = Gtk.Label()
self.__filter.set_alignment(1.0, 0.5)
self.__filter.show()
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)
self.pack_start(self.__warnbtn, False, True, 4)
self.pack_start(self.__progress, False, True, 4)
self.pack_start(self.__status, True, True, 4)
self.pack_end(self.__filter, False, True, 4)
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')
def get_warning_button(self):
"""Return the warning button widget."""
return self.__warnbtn
def main(args):
win = Gtk.Window()
win.set_title('Statusbar test window')
win.set_position(Gtk.WindowPosition.CENTER)
def cb(window, event):
Gtk.main_quit()
win.connect('delete-event', cb)
def get_progress_bar(self):
"""Return the progress bar widget."""
return self.__progress
vbox = Gtk.VBox()
win.add(vbox)
def get_context_id(self, context_description):
"""Return a new or existing context identifier."""
return self.__status.get_context_id(context_description)
statusbar = Statusbar()
vbox.pack_end(statusbar, False, True, 0)
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)
def push(self, context_id, text):
"""Push message onto a statusbar's stack."""
return self.__status.push(context_id, text)
last_statusbar = statusbar.insert(ralign=True)
statusbar.push(1, "The last statusbar",
last_statusbar)
win.show_all()
Gtk.main()
def pop(self, context_id):
"""Remove the top message from a statusbar's stack."""
self.__status.pop(context_id)
if __name__ == '__main__':
import sys
# fall back to root logger for testing
log = logging
sys.exit(main(sys.argv))
def remove(self, context_id, message_id):
"""Remove the message with the specified message_id."""
self.__status.remove(context_id, message_id)
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('')