Sidebar tidy-up and bug fixes

svn: r16319
This commit is contained in:
Nick Hall
2010-12-28 17:04:41 +00:00
parent a5ab94721f
commit 6f7ce7726f
26 changed files with 388 additions and 572 deletions

View File

@@ -50,6 +50,7 @@ import pango
# GRAMPS
#
#----------------------------------------------------------------
from gui.views.pageview import PageView, FILTER_PAGE
from gui.views.navigationview import NavigationView
from gui.columnorder import ColumnOrder
import config
@@ -91,10 +92,10 @@ class ListView(NavigationView):
FILTER_TYPE = None # Set in inheriting class
QR_CATEGORY = -1
def __init__(self, title, dbstate, uistate, columns, handle_col,
def __init__(self, title, pdata, dbstate, uistate, columns, handle_col,
make_model, signal_map, get_bookmarks, bm_type, nav_group,
multiple=False, filter_class=None, markup=None):
NavigationView.__init__(self, title, dbstate, uistate,
NavigationView.__init__(self, title, pdata, dbstate, uistate,
get_bookmarks, bm_type, nav_group)
#default is listviews keep themself in sync with database
self._dirty_on_change_inactive = False
@@ -861,6 +862,16 @@ class ListView(NavigationView):
self.edit_action.set_visible(True)
self.edit_action.set_sensitive(not self.dbstate.db.readonly)
def sidebar_changed(self, page_type, active, index):
"""
Called when the sidebar page is changed.
"""
PageView.sidebar_changed(self, page_type, active, index)
if active and page_type == FILTER_PAGE:
self.search_bar.hide()
else:
self.search_bar.show()
def on_delete(self):
"""
Save the column widths when the view is shutdown.
@@ -877,7 +888,7 @@ class ListView(NavigationView):
index += 1
newsize.append(size)
self._config.set('columns.size', newsize)
self._config.save()
PageView.on_delete(self)
####################################################################
# Export data

View File

@@ -78,8 +78,8 @@ class NavigationView(PageView):
should derive from this class.
"""
def __init__(self, title, state, uistate, bookmarks, bm_type, nav_group):
PageView.__init__(self, title, state, uistate)
def __init__(self, title, pdata, state, uistate, bookmarks, bm_type, nav_group):
PageView.__init__(self, title, pdata, state, uistate)
self.bookmarks = bm_type(self.dbstate, self.uistate, bookmarks,
self.goto_handle)
@@ -107,6 +107,7 @@ class NavigationView(PageView):
"""
Define menu actions.
"""
PageView.define_actions(self)
self.bookmark_actions()
self.navigation_actions()

View File

@@ -49,8 +49,19 @@ from gen.ggettext import gettext as _
import Errors
from gui.dbguielement import DbGUIElement
from gui.widgets.menutoolbuttonaction import MenuToolButtonAction
from gui.sidebar import Sidebar
from gui.widgets.grampletpane import GrampletPane
from gui.configure import ConfigureDialog
from config import config
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
GRAMPLET_PAGE = 0
FILTER_PAGE = 1
#------------------------------------------------------------------------------
#
# PageView
@@ -88,8 +99,9 @@ class PageView(DbGUIElement):
CONFIGSETTINGS = []
def __init__(self, title, dbstate, uistate):
def __init__(self, title, pdata, dbstate, uistate):
self.title = title
self.pdata = pdata
self.dbstate = dbstate
self.uistate = uistate
self.action_list = []
@@ -99,15 +111,29 @@ class PageView(DbGUIElement):
self.action_group = None
self.additional_action_groups = []
self.additional_uis = []
self.widget = None
self.ui_def = '<ui></ui>'
self.ui_def = '''<ui>
<menubar name="MenuBar">
<menu action="ViewMenu">
<placeholder name="Bars">
<menuitem action="Sidebar"/>
</placeholder>
</menu>
</menubar>
<popup name="GrampletPopup">
<menuitem action="AddGramplet"/>
<menuitem action="RestoreGramplet"/>
</popup>
</ui>'''
self.dirty = True
self.active = False
self._dirty_on_change_inactive = True
self.func_list = {}
self.category = "Miscellaneous"
self.ident = None
self.translated_category = _("Miscellaneous")
if isinstance(self.pdata.category, tuple):
self.category, self.translated_category = self.pdata.category
else:
raise AttributeError("View category must be (name, translated-name)")
self.ident = self.category + '_' + self.pdata.id
self.dbstate.connect('no-database', self.disable_action_group)
self.dbstate.connect('database-changed', self.enable_action_group)
@@ -118,10 +144,108 @@ class PageView(DbGUIElement):
self.handle_col = 0
self._config = None
self.__configure_content = None
self.init_config()
self.filter_class = None
self.top = None
self.gramplet_pane = None
self.sidebar = None
DbGUIElement.__init__(self, dbstate.db)
def build_interface(self):
"""
Builds the container widget for the interface.
Returns a gtk container widget.
"""
self.sidebar = Sidebar(self.sidebar_changed, self.sidebar_closed)
hpane = gtk.HPaned()
vpane = gtk.VPaned()
hpane.pack1(vpane, resize=True, shrink=True)
hpane.pack2(self.sidebar.get_display(), resize=False, shrink=False)
hpane.show()
vpane.show()
widget = self.build_widget()
widget.show_all()
vpane.add1(widget)
initial_page = self._config.get('sidebar.page')
self.gramplet_pane = self.__create_gramplet_pane()
if self.filter_class:
self.add_filter(self.filter_class)
self.sidebar.set_current_page(initial_page)
if self._config.get('sidebar.visible'):
self.sidebar.show()
else:
self.sidebar.hide()
return hpane
def add_filter(self, filter_class):
"""
Add a filter to the workspace sidebar.
"""
self.filter_sidebar = filter_class(self.dbstate, self.uistate,
self.__filter_clicked)
top = self.filter_sidebar.get_widget()
top.show_all()
self.sidebar.add(_('Filter'), top, FILTER_PAGE)
def remove_filter(self):
"""
Remove the filter from the workspace sidebar.
"""
self.filter_sidebar = None
self.sidebar.remove(FILTER_PAGE)
def __create_gramplet_pane(self):
"""
Create a gramplet pane.
"""
gramplet_pane = GrampletPane(self.ident + "_sidebar",
self, self.dbstate, self.uistate,
column_count=1)
gramplet_pane.show_all()
self.sidebar.add(_('Gramplets'), gramplet_pane, GRAMPLET_PAGE)
return gramplet_pane
def __filter_clicked(self):
"""
Called when the filter 'Find' button is clicked.
"""
self.generic_filter = self.filter_sidebar.get_filter()
self.build_tree()
def __sidebar_toggled(self, action):
"""
Called when the sidebar is toggled.
"""
active = action.get_active()
if active:
self.sidebar.show()
self.sidebar_changed(self.sidebar.get_page_type(), True, None)
else:
self.sidebar.hide()
self.sidebar_changed(None, False, None)
self._config.set('sidebar.visible', active)
def sidebar_changed(self, page_type, active, index):
"""
Called when the sidebar page is changed.
"""
if index is not None:
self._config.set('sidebar.page', index)
def sidebar_closed(self):
"""
Called when the sidebar close button is clicked.
"""
uimanager = self.uistate.uimanager
uimanager.get_action('/MenuBar/ViewMenu/Bars/Sidebar').activate()
def key_press_handler(self, widget, event):
"""
A general keypress handler. Override if you want to handle
@@ -212,6 +336,7 @@ class PageView(DbGUIElement):
Called with the PageView is set as active. If the page is "dirty",
then we rebuild the data.
"""
self.gramplet_pane.set_active()
self.active = True
if self.dirty:
self.uistate.set_busy_cursor(True)
@@ -222,6 +347,7 @@ class PageView(DbGUIElement):
"""
Marks page as being inactive (not currently displayed)
"""
self.gramplet_pane.set_inactive()
self.active = False
def build_tree(self):
@@ -279,20 +405,6 @@ class PageView(DbGUIElement):
"""
return self.title
def set_category(self, category):
"""
Set the category of the view. This is used to define the text for the
button, and for the tab label.
category - a tuple of the form (category, translated-category)
"""
if isinstance(category, tuple):
self.category = category[0]
self.translated_category = category[1]
else:
raise AttributeError("View category must be (name, translated-name)")
def get_category(self):
"""
Return the category name of the view. This is used to define
@@ -307,25 +419,18 @@ class PageView(DbGUIElement):
"""
return self.translated_category
def set_ident(self, ident):
"""
Set the id of the view. This is an unique ident
"""
self.ident = ident
self.init_config()
def get_display(self):
"""
Builds the graphical display, returning the top level widget.
"""
if not self.widget:
self.widget = self.build_widget()
return self.widget
if not self.top:
self.top = self.build_interface()
return self.top
def build_widget(self):
"""
Builds the container widget for the interface. Must be overridden by the
the base class. Returns a gtk container widget.
Builds the container widget for the main view pane. Must be overridden
by the the base class. Returns a gtk container widget.
"""
raise NotImplementedError
@@ -334,10 +439,12 @@ class PageView(DbGUIElement):
Defines the UIManager actions. Called by the ViewManager to set up the
View. The user typically defines self.action_list and
self.action_toggle_list in this function.
Derived classes must override this function.
"""
raise NotImplementedError
self._add_toggle_action('Sidebar', None, _('_Sidebar'),
None, None, self.__sidebar_toggled,
self._config.get('sidebar.visible'))
self._add_action("AddGramplet", gtk.STOCK_ADD, _("Add a gramplet"))
self._add_action("RestoreGramplet", None, _("Restore a gramplet"))
def __build_action_group(self):
"""
@@ -454,7 +561,8 @@ class PageView(DbGUIElement):
Method called on shutdown. Data views should put code here
that should be called when quiting the main application.
"""
pass
self.gramplet_pane.on_delete()
self._config.save()
def init_config(self):
"""
@@ -512,3 +620,56 @@ class PageView(DbGUIElement):
:return: list of functions
"""
raise NotImplementedError
def __get_configure_funcs(self):
"""
Return a combined list of configuration functions for all of the panes
in the view.
:return: list of functions
"""
retval = []
if self.can_configure():
other = self._get_configure_page_funcs()
if callable(other):
retval += other()
else:
retval += other
if self.gramplet_pane is not None:
func = self.gramplet_pane._get_configure_page_funcs()
retval += func()
return retval
def configure(self):
"""
Open the configure dialog for the workspace.
"""
title = _("Configure %(cat)s - %(view)s") % \
{'cat': self.get_translated_category(),
'view': self.get_title()}
try:
ViewConfigureDialog(self.uistate, self.dbstate,
self.__get_configure_funcs(),
self, self._config, dialogtitle=title,
ident=_("%(cat)s - %(view)s") %
{'cat': self.get_translated_category(),
'view': self.get_title()})
except Errors.WindowActiveError:
return
class ViewConfigureDialog(ConfigureDialog):
"""
All workspaces can have their own configuration dialog
"""
def __init__(self, uistate, dbstate, configure_page_funcs, configobj,
configmanager,
dialogtitle=_("Preferences"), on_close=None, ident=''):
self.ident = ident
ConfigureDialog.__init__(self, uistate, dbstate, configure_page_funcs,
configobj, configmanager,
dialogtitle=dialogtitle, on_close=on_close)
def build_menu_names(self, obj):
return (_('Configure %s View') % self.ident, None)