diff --git a/configure.in b/configure.in
index 95cbd96cc..bbdc06a4d 100644
--- a/configure.in
+++ b/configure.in
@@ -140,6 +140,7 @@ src/plugins/lib/Makefile
src/plugins/mapservices/Makefile
src/plugins/quickview/Makefile
src/plugins/rel/Makefile
+src/plugins/sidebar/Makefile
src/plugins/textreport/Makefile
src/plugins/tool/Makefile
src/plugins/view/Makefile
diff --git a/src/gen/plug/_manager.py b/src/gen/plug/_manager.py
index 7bd2174b1..bb92aa3b4 100644
--- a/src/gen/plug/_manager.py
+++ b/src/gen/plug/_manager.py
@@ -288,6 +288,11 @@ class BasePluginManager(object):
"""
return self.__pgr.gramplet_plugins()
+ def get_reg_sidebars(self):
+ """ Return list of registered sidebars.
+ """
+ return self.__pgr.sidebar_plugins()
+
def get_external_opt_dict(self):
""" Return the dictionary of external options. """
return self.__external_opt_dict
diff --git a/src/gen/plug/_pluginreg.py b/src/gen/plug/_pluginreg.py
index 31487ac15..2be679a12 100644
--- a/src/gen/plug/_pluginreg.py
+++ b/src/gen/plug/_pluginreg.py
@@ -68,8 +68,9 @@ MAPSERVICE = 7
VIEW = 8
RELCALC = 9
GRAMPLET = 10
-PTYPE = [ REPORT , QUICKREPORT, TOOL, IMPORT,
- EXPORT, DOCGEN, GENERAL, MAPSERVICE, VIEW, RELCALC, GRAMPLET]
+SIDEBAR = 11
+PTYPE = [REPORT , QUICKREPORT, TOOL, IMPORT, EXPORT, DOCGEN, GENERAL,
+ MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR]
PTYPE_STR = {
REPORT: _('Report') ,
QUICKREPORT: _('Quickreport'),
@@ -82,6 +83,7 @@ PTYPE_STR = {
VIEW: _('Gramps View'),
RELCALC: _('Relationships'),
GRAMPLET: _('Gramplet'),
+ SIDEBAR: _('Sidebar'),
}
#possible report categories
@@ -301,6 +303,14 @@ class PluginData(object):
the view is appended to the list of views. If START, then the view is
prepended. Only set START if you want a view to be the first in the
order of views
+ .. attribute:: stock_icon
+ The icon in the toolbar or sidebar used to select the view
+
+ Attributes for SIDEBAR plugins
+ .. attribute:: sidebarclass
+ The class that defines the sidebar.
+ .. attribute:: menu_label
+ A label to use on the seltion menu.
"""
def __init__(self):
@@ -364,6 +374,10 @@ class PluginData(object):
#VIEW attr
self._viewclass = None
self._order = END
+ self._stock_icon = None
+ #SIDEBAR attr
+ self._sidebarclass = None
+ self._menu_label = ''
def _set_id(self, id):
self._id = id
@@ -811,10 +825,38 @@ class PluginData(object):
def _get_order(self):
return self._order
- viewclass = property(_get_viewclass, _set_viewclass)
- order = property(_get_order, _set_order)
-
+ def _set_stock_icon(self, stock_icon):
+ if not self._ptype == VIEW:
+ raise ValueError, 'stock_icon may only be set for VIEW plugins'
+ self._stock_icon = stock_icon
+ def _get_stock_icon(self):
+ return self._stock_icon
+
+ viewclass = property(_get_viewclass, _set_viewclass)
+ order = property(_get_order, _set_order)
+ stock_icon = property(_get_stock_icon, _set_stock_icon)
+
+ #SIDEBAR attributes
+ def _set_sidebarclass(self, sidebarclass):
+ if not self._ptype == SIDEBAR:
+ raise ValueError, 'sidebarclass may only be set for SIDEBAR plugins'
+ self._sidebarclass = sidebarclass
+
+ def _get_sidebarclass(self):
+ return self._sidebarclass
+
+ def _set_menu_label(self, menu_label):
+ if not self._ptype == SIDEBAR:
+ raise ValueError, 'menu_label may only be set for SIDEBAR plugins'
+ self._menu_label = menu_label
+
+ def _get_menu_label(self):
+ return self._menu_label
+
+ sidebarclass = property(_get_sidebarclass, _set_sidebarclass)
+ menu_label = property(_get_menu_label, _set_menu_label)
+
def newplugin():
"""
Function to create a new plugindata object, add it to list of
@@ -865,6 +907,7 @@ def make_environment(**kwargs):
'VIEW': VIEW,
'RELCALC': RELCALC,
'GRAMPLET': GRAMPLET,
+ 'SIDEBAR': SIDEBAR,
'CATEGORY_TEXT': CATEGORY_TEXT,
'CATEGORY_DRAW': CATEGORY_DRAW,
'CATEGORY_CODE': CATEGORY_CODE,
@@ -1106,6 +1149,11 @@ class PluginRegister(object):
"""Return a list of PluginData that are of type GRAMPLET
"""
return self.type_plugins(GRAMPLET)
+
+ def sidebar_plugins(self):
+ """Return a list of PluginData that are of type SIDEBAR
+ """
+ return self.type_plugins(SIDEBAR)
def filter_load_on_reg(self):
"""Return a list of PluginData that have load_on_reg == True
diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am
index 764bf1ff1..0f30dad49 100644
--- a/src/gui/Makefile.am
+++ b/src/gui/Makefile.am
@@ -21,6 +21,7 @@ pkgdata_PYTHON = \
filtereditor.py \
grampsgui.py \
pluginmanager.py \
+ sidebar.py \
utils.py \
viewmanager.py
diff --git a/src/gui/grampsgui.py b/src/gui/grampsgui.py
index 3eda845ac..8d466187e 100644
--- a/src/gui/grampsgui.py
+++ b/src/gui/grampsgui.py
@@ -62,8 +62,7 @@ from QuestionDialog import ErrorDialog
import config
import Utils
from constfunc import win
-from gui.pluginmanager import GuiPluginManager, base_reg_stock_icons
-from gen.plug import (START, END)
+from gui.pluginmanager import base_reg_stock_icons
#-------------------------------------------------------------------------
#
@@ -71,7 +70,6 @@ from gen.plug import (START, END)
#
#-------------------------------------------------------------------------
-
def register_stock_icons ():
"""
Add the gramps names for its icons (eg gramps-person) to the GTK icon
@@ -185,53 +183,6 @@ def _display_welcome_message():
config.set('behavior.autoload', False)
# config.set('behavior.betawarn', True)
config.set('behavior.betawarn', config.get('behavior.betawarn'))
-
-def construct_view_order():
- """
- Query the views and determine what views to show and in which order
-
- :Returns: a list of lists containing tuples (view_id, viewclass)
- """
- pmgr = GuiPluginManager.get_instance()
- view_list = pmgr.get_reg_views()
- viewstoshow = {}
- for pdata in view_list:
- mod = pmgr.load_plugin(pdata)
- if not mod or not hasattr(mod, pdata.viewclass):
- #import of plugin failed
- ErrorDialog(
- _('Failed Loading View'),
- _('The view %(name)s did not load. See Help Menu, Plugin Manager'
- ' for more info.\nUse http://bugs.gramps-project.org to'
- ' submit bugs of official views, contact the view '
- 'author (%(firstauthoremail)s) otherwise. ') % {
- 'name': pdata.name,
- 'firstauthoremail': pdata.authors_email[0] if
- pdata.authors_email else '...'})
- continue
- viewclass = getattr(mod, pdata.viewclass)
- # pdata.category is (string, trans-string):
- if pdata.category[0] in viewstoshow:
- if pdata.order == START:
- viewstoshow[pdata.category[0]].insert(0, ((pdata, viewclass)))
- else:
- viewstoshow[pdata.category[0]].append((pdata, viewclass))
- else:
- viewstoshow[pdata.category[0]] = [(pdata, viewclass)]
-
- resultorder = []
- # First, get those in order defined, if exists:
- for item in config.get("interface.view-categories"):
- if item in viewstoshow:
- resultorder.append(viewstoshow[item])
- # Next, get the rest in some order:
- viewstoshow_names = viewstoshow.keys()
- viewstoshow_names.sort()
- for item in viewstoshow_names:
- if viewstoshow[item] in resultorder:
- continue
- resultorder.append(viewstoshow[item])
- return resultorder
#-------------------------------------------------------------------------
#
@@ -256,11 +207,7 @@ class Gramps(object):
dbstate = DbState.DbState()
self.vm = ViewManager(dbstate, config.get("interface.view-categories"))
-
- #now we determine which views are present, which to show, and we
- #instruct the viewmanager to show them
- vieworder = construct_view_order()
- self.vm.init_interface(vieworder)
+ self.vm.init_interface()
#act based on the given arguments
ah = ArgHandler(dbstate, argparser, self.vm, self.argerrorfunc,
@@ -289,7 +236,6 @@ class Gramps(object):
def argerrorfunc(self, string):
""" Show basic errors in argument handling in GUI fashion"""
ErrorDialog(_("Error parsing arguments"), string)
-
#-------------------------------------------------------------------------
#
diff --git a/src/gui/pluginmanager.py b/src/gui/pluginmanager.py
index 2cb8ee9e1..abfdefcb7 100644
--- a/src/gui/pluginmanager.py
+++ b/src/gui/pluginmanager.py
@@ -289,6 +289,12 @@ class GuiPluginManager(gen.utils.Callback):
return [plg for plg in self.basemgr.get_reg_gramplets()
if plg.id not in self.__hidden_plugins]
+ def get_reg_sidebars(self):
+ """ Return list of non hidden registered sidebars
+ """
+ return [plg for plg in self.basemgr.get_reg_sidebars()
+ if plg.id not in self.__hidden_plugins]
+
def get_reg_importers(self):
""" Return list of registered importers
"""
diff --git a/src/gui/sidebar.py b/src/gui/sidebar.py
new file mode 100644
index 000000000..df712c5ff
--- /dev/null
+++ b/src/gui/sidebar.py
@@ -0,0 +1,173 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2010 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
+# 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
+#
+# $Id$
+
+"""
+A module that provides pluggable sidebars. These provide an interface to
+manage pages in the main Gramps window.
+"""
+#-------------------------------------------------------------------------
+#
+# GNOME modules
+#
+#-------------------------------------------------------------------------
+import gtk
+
+#-------------------------------------------------------------------------
+#
+# Sidebar class
+#
+#-------------------------------------------------------------------------
+class Sidebar(object):
+ """
+ A class which defines the graphical representation of the Gramps sidebar.
+ """
+ def __init__(self, viewmanager):
+
+ self.viewmanager = viewmanager
+ self.pages = []
+ self.top = gtk.VBox()
+
+ frame = gtk.Frame()
+ hbox = gtk.HBox()
+ frame.add(hbox)
+
+ select_button = gtk.ToggleButton()
+ select_button.set_relief(gtk.RELIEF_NONE)
+ select_hbox = gtk.HBox()
+ self.title_label = gtk.Label('Category')
+ arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_NONE)
+ select_hbox.pack_start(self.title_label, False)
+ select_hbox.pack_end(arrow, False)
+ select_button.add(select_hbox)
+
+ select_button.connect('button_press_event', self.__menu_button_pressed)
+
+ close_button = gtk.Button()
+ img = gtk.image_new_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
+ close_button.set_image(img)
+ close_button.set_relief(gtk.RELIEF_NONE)
+ close_button.connect('clicked', self.cb_close_clicked)
+ hbox.pack_start(select_button, False)
+ hbox.pack_end(close_button, False)
+
+ self.top.pack_start(frame, False)
+
+ self.menu = gtk.Menu()
+ self.menu.show()
+ self.menu.connect('deactivate', cb_menu_deactivate, select_button)
+
+ self.notebook = gtk.Notebook()
+ self.notebook.show()
+ self.notebook.set_show_tabs(False)
+ self.notebook.set_show_border(False)
+ self.notebook.connect('switch_page', self.cb_switch_page)
+ self.top.pack_start(self.notebook, True)
+
+ def get_top(self):
+ """
+ Return the top container widget for the GUI.
+ """
+ return self.top
+
+ def add(self, title, sidebar):
+ """
+ Add a page to the sidebar for a plugin.
+ """
+ index = self.notebook.append_page(sidebar.get_top(), gtk.Label(title))
+ self.pages.append((title, sidebar))
+
+ menu_item = gtk.MenuItem(title)
+ menu_item.connect('activate', self.cb_menu_activate, index)
+ menu_item.show()
+ self.menu.append(menu_item)
+
+ def view_changed(self, page_num):
+ """
+ Called when a Gramps view is changed.
+ """
+ for page in self.pages:
+ page[1].view_changed(page_num)
+
+ def handlers_block(self):
+ """
+ Block signals to the buttons to prevent spurious events.
+ """
+ for page in self.pages:
+ page[1].handlers_block()
+
+ def handlers_unblock(self):
+ """
+ Unblock signals to the buttons.
+ """
+ for page in self.pages:
+ page[1].handlers_unblock()
+
+ def __menu_button_pressed(self, button, event):
+ """
+ Called when the button to select a sidebar page is pressed.
+ """
+ if event.button == 1 and event.type == gtk.gdk.BUTTON_PRESS:
+ button.grab_focus()
+ button.set_active(True)
+
+ self.menu.popup(None, None, cb_menu_position, event.button,
+ event.time, button)
+
+ def cb_menu_activate(self, menu, index):
+ """
+ Called when an item in the popup menu is selected.
+ """
+ self.notebook.set_current_page(index)
+
+ def cb_switch_page(self, notebook, unused, index):
+ """
+ Called when the user has switched to a new sidebar plugin page.
+ """
+ if self.pages:
+ self.title_label.set_text(self.pages[index][0])
+
+ def cb_close_clicked(self, button):
+ """
+ Called when the sidebar is closed.
+ """
+ uimanager = self.viewmanager.uimanager
+ uimanager.get_action('/MenuBar/ViewMenu/Sidebar').activate()
+
+#-------------------------------------------------------------------------
+#
+# Functions
+#
+#-------------------------------------------------------------------------
+def cb_menu_position(menu, button):
+ """
+ Determine the position of the popup menu.
+ """
+ x_pos, y_pos = button.window.get_origin()
+ x_pos += button.allocation.x
+ y_pos += button.allocation.y + button.allocation.height
+
+ return (x_pos, y_pos, False)
+
+def cb_menu_deactivate(menu, button):
+ """
+ Called when the popup menu disappears.
+ """
+ button.set_active(False)
diff --git a/src/gui/viewmanager.py b/src/gui/viewmanager.py
index e7d8c1625..2cd339017 100644
--- a/src/gui/viewmanager.py
+++ b/src/gui/viewmanager.py
@@ -4,6 +4,7 @@
# Copyright (C) 2005-2007 Donald N. Allingham
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2009 Benny Malengier
+# Copyright (C) 2010 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
@@ -61,6 +62,7 @@ from PluginUtils import Tool, PluginWindows, \
ReportPluginDialog, ToolPluginDialog, gui_tool
from gen.plug import REPORT
from gui.pluginmanager import GuiPluginManager
+from gen.plug import (START, END)
import Relationship
import ReportBase
import DisplayState
@@ -78,6 +80,7 @@ from gui.configure import GrampsPreferences
from gen.db.backup import backup
from gen.db.exceptions import DbException
from GrampsAboutDialog import GrampsAboutDialog
+from gui.sidebar import Sidebar
#-------------------------------------------------------------------------
#
@@ -183,20 +186,6 @@ UIDEFAULT = '''
'''
-UICATEGORY = '''
-
-
-
-
- %s
-
-
-
-'''
-
WIKI_HELP_PAGE_FAQ = '%s_-_FAQ' % const.URL_MANUAL_PAGE
WIKI_HELP_PAGE_KEY = '%s_-_Keybindings' % const.URL_MANUAL_PAGE
WIKI_HELP_PAGE_MAN = '%s' % const.URL_MANUAL_PAGE
@@ -234,13 +223,14 @@ class ViewManager(CLIManager):
The View Manager does not have to know the number of views, the type of
views, or any other details about the views. It simply provides the
- method of containing each view, and switching between the views.
+ method of containing each view, and has methods for creating, deleting and
+ switching between the views.
"""
def __init__(self, dbstate, view_category_order):
"""
- The viewmanager is initialiste with a dbstate on which GRAMPS is
+ The viewmanager is initialised with a dbstate on which GRAMPS is
working, and a fixed view_category_order, which is the order in which
the view categories are accessible in the sidebar.
"""
@@ -248,12 +238,8 @@ class ViewManager(CLIManager):
self.view_category_order = view_category_order
#set pluginmanager to GUI one
self._pmgr = GuiPluginManager.get_instance()
- self.page_is_changing = False
self.active_page = None
- self.views = []
self.pages = []
- self.button_handlers = []
- self.buttons = []
self.merge_ids = []
self.toolactions = None
self.tool_menu_ui_id = None
@@ -294,12 +280,13 @@ class ViewManager(CLIManager):
vbox = gtk.VBox()
self.window.add(vbox)
- hbox = gtk.HBox()
+ hpane = gtk.HPaned()
self.ebox = gtk.EventBox()
- self.bbox = gtk.VBox()
- self.ebox.add(self.bbox)
- hbox.pack_start(self.ebox, False)
- hbox.show_all()
+
+ self.sidebar = Sidebar(self)
+ self.ebox.add(self.sidebar.get_top())
+ hpane.add1(self.ebox)
+ hpane.show_all()
self.notebook = gtk.Notebook()
self.notebook.set_scrollable(True)
@@ -309,12 +296,12 @@ class ViewManager(CLIManager):
self.__init_lists()
self.__build_ui_manager()
- hbox.pack_start(self.notebook, True)
+ hpane.add2(self.notebook)
self.menubar = self.uimanager.get_widget('/MenuBar')
self.toolbar = self.uimanager.get_widget('/ToolBar')
vbox.pack_start(self.menubar, False)
vbox.pack_start(self.toolbar, False)
- vbox.add(hbox)
+ vbox.add(hpane)
vbox.pack_end(self.__setup_statusbar(), False)
vbox.show()
@@ -358,6 +345,21 @@ class ViewManager(CLIManager):
# But we need to realize it here to have gtk.gdk.window handy
self.window.realize()
+ def __load_sidebar_plugins(self):
+ """
+ Load the sidebar plugins.
+ """
+ for pdata in self._pmgr.get_reg_sidebars():
+ module = self._pmgr.load_plugin(pdata)
+ if not module:
+ print "Error loading sidebar '%s': skipping content" \
+ % pdata.name
+ continue
+
+ sidebar_class = getattr(module, pdata.sidebarclass)
+ sidebar_page = sidebar_class(self.dbstate, self.uistate)
+ self.sidebar.add(pdata.menu_label, sidebar_page)
+
def __setup_statusbar(self):
"""
Create the statusbar that sits at the bottom of the window
@@ -387,10 +389,8 @@ class ViewManager(CLIManager):
"""
if self.show_sidebar:
self.ebox.show()
- self.notebook.set_show_tabs(False)
else:
self.ebox.hide()
- self.notebook.set_show_tabs(True)
def __build_open_button(self):
"""
@@ -406,10 +406,17 @@ class ViewManager(CLIManager):
def __connect_signals(self):
"""
- connects the signals needed
+ Connects the signals needed
"""
self.window.connect('delete-event', self.quit)
- self.notebook.connect('switch-page', self.change_category)
+ self.notebook.connect('switch-page', self.view_changed)
+
+ def view_changed(self, notebook, page, page_num):
+ """
+ Called when the notebook page is changed.
+ """
+ self.sidebar.view_changed(page_num)
+ self.__change_page(page_num)
def __init_lists(self):
"""
@@ -547,11 +554,9 @@ class ViewManager(CLIManager):
new_page = 0
else:
new_page = current_page + 1
- if self.show_sidebar:
- #cause a click signal
- self.buttons[new_page].set_active(True)
- else:
- self.notebook.set_current_page(new_page)
+ self.sidebar.handlers_block()
+ self.notebook.set_current_page(new_page)
+ self.sidebar.handlers_unblock()
def __prev_view(self, action):
"""
@@ -564,19 +569,16 @@ class ViewManager(CLIManager):
new_page = len(self.pages)-1
else:
new_page = current_page - 1
- if self.show_sidebar:
- #cause a click signal
- self.buttons[new_page].set_active(True)
- else:
- self.notebook.set_current_page(new_page)
+ self.sidebar.handlers_block()
+ self.notebook.set_current_page(new_page)
+ self.sidebar.handlers_unblock()
- def init_interface(self, vieworder):
+ def init_interface(self):
"""
Initialize the interface, creating the pages as given in vieworder
"""
- self.views = vieworder
self.__init_lists()
- self.__create_pages()
+ self.__load_sidebar_plugins()
if not self.file_loaded:
self.actiongroup.set_visible(False)
@@ -787,12 +789,10 @@ class ViewManager(CLIManager):
"""
if obj.get_active():
self.ebox.show()
- self.notebook.set_show_tabs(False)
config.set('interface.view', True)
self.show_sidebar = True
else:
self.ebox.hide()
- self.notebook.set_show_tabs(True)
config.set('interface.view', False)
self.show_sidebar = False
config.save()
@@ -823,267 +823,71 @@ class ViewManager(CLIManager):
config.set('interface.fullscreen', False)
config.save()
- def view_toggle(self, radioaction, current, category_page):
- """
- Go to the views in category_page, with in category: view_page
- The view has id id_page
- This is the only method that can call change of views in a category
- """
- self.__vb_handlers_block()
- if self.notebook.get_current_page() != category_page:
- raise Error, 'Error changing view, category is not active'
- cat_notebook = self.notebook_cat[category_page]
- view_page = radioaction.get_current_value()
- if self.notebook_cat[category_page].get_current_page() != view_page:
- self.notebook_cat[category_page].set_current_page(view_page)
- self.__change_view(category_page, view_page)
- self.__vb_handlers_unblock()
+ def create_page(self, pdata, page_def):
+ try:
+ page = page_def(self.dbstate, self.uistate)
+ except:
+ import traceback
+ LOG.warn("View '%s' failed to load." % pdata.id)
+ traceback.print_exc()
+ return
+ # Category is (string, trans):
+ page.set_category(pdata.category)
+ page.set_ident(page.get_category() + '_' + pdata.id)
+ page_title = page.get_title()
+ page_category = page.get_category()
+ page_translated_category = page.get_translated_category()
+ page_stock = page.get_stock()
+
+ page.define_actions()
+ try:
+ page_display = page.get_display()
+ except:
+ import traceback
+ print "ERROR: '%s' failed to create view" % pdata.name
+ traceback.print_exc()
+ return
+ page_display.show_all()
+ page.post()
+ self.pages.append(page)
+
+ # create icon/label for workspace notebook
+ hbox = gtk.HBox()
+ image = gtk.Image()
+ image.set_from_stock(page_stock, gtk.ICON_SIZE_MENU)
+ hbox.pack_start(image, False)
+ hbox.add(gtk.Label(pdata.name))
+ hbox.show_all()
- def __switch_page_on_dnd(self, widget, context, xpos, ypos, time, page_no):
- """
- Switches the page based on drag and drop
- """
- self.__vb_handlers_block()
- if self.notebook.get_current_page() != page_no:
- self.notebook.set_current_page(page_no)
- self.__vb_handlers_unblock()
+ page_num = self.notebook.append_page(page_display, hbox)
+ return page_num
+
+ def goto_page(self, page_num):
+ self.sidebar.handlers_block()
+ self.notebook.set_current_page(page_num)
+ self.sidebar.handlers_unblock()
+
+ self.__change_page(page_num)
+
+ def __change_page(self, page_num):
+ self.__disconnect_previous_page()
+
+ self.active_page = self.pages[page_num]
+ self.active_page.set_active()
+ self.__connect_active_page(page_num)
+
+ self.uimanager.ensure_update()
+ while gtk.events_pending():
+ gtk.main_iteration()
+
+ self.active_page.change_page()
def __delete_pages(self):
"""
Calls on_delete() for each view
"""
- for pages in self.pages:
- for page in pages:
- page.on_delete()
-
- def __create_pages(self):
- """
- Create the Views
- """
- self.pages = []
- self.ui_category = {}
- self.view_toggle_actions = {}
- self.cat_view_group = None
-
- use_text = config.get('interface.sidebar-text')
- #obtain which views should be the active ones
- current_cat, current_cat_view, default_cat_views = \
- self.__views_to_show(config.get('preferences.use-last-view'))
-
- for indexcat, cat_views in enumerate(self.views):
- #for every category, we create a button in the sidebar and a main
- #workspace in which to show the view
- nr_views = len(cat_views)
- uimenuitems = ''
- uitoolitems = ''
- self.view_toggle_actions[indexcat] = []
- self.pages.append([])
- nrpage = 0
- for pdata, page_def in cat_views:
- try:
- page = page_def(self.dbstate, self.uistate)
- except:
- import traceback
- LOG.warn("View '%s' failed to load." % pdata.id)
- traceback.print_exc()
- continue
- # Category is (string, trans):
- page.set_category(pdata.category)
- page.set_ident(page.get_category() + '_' + pdata.id)
- page_title = page.get_title()
- page_category = page.get_category()
- page_translated_category = page.get_translated_category()
- page_stock = page.get_stock()
-
- if nrpage == 0:
- #the first page of this category, used to obtain
- #category workspace notebook
- notebook = gtk.Notebook()
- notebook.set_scrollable(False)
- notebook.set_show_tabs(False)
- notebook.show()
- self.notebook_cat.append(notebook)
- # create icon/label for workspace notebook
- hbox = gtk.HBox()
- image = gtk.Image()
- image.set_from_stock(page_stock, gtk.ICON_SIZE_MENU)
- hbox.pack_start(image, False)
- hbox.add(gtk.Label(page_translated_category))
- hbox.show_all()
- page_cat = self.notebook.append_page(notebook, hbox)
- # Enable view switching during DnD
- hbox.drag_dest_set(0, [], 0)
- hbox.connect('drag_motion', self.__switch_page_on_dnd,
- page_cat)
-
- # create the button and add it to the sidebar
- button = self.__make_sidebar_button(use_text, indexcat,
- page_translated_category,
- page_stock)
-
- self.bbox.pack_start(button, False)
- self.buttons.append(button)
-
- # Enable view switching during DnD
- button.drag_dest_set(0, [], 0)
- button.connect('drag_motion', self.__switch_page_on_dnd,
- page_cat)
-
- # create view page and add to category notebook
- page.define_actions()
- try:
- page_display = page.get_display()
- except:
- import traceback
- print "ERROR: '%s' failed to create view" % pdata.name
- traceback.print_exc()
- continue
- page_display.show_all()
- page.post()
- page_no = self.notebook_cat[-1].append_page(page_display,
- gtk.Label(page_title))
- self.pages[-1].append(page)
- pageid = (pdata.id + '_%i' % nrpage)
- uimenuitems += '\n' % pageid
- uitoolitems += '\n' % pageid
- # id, stock, button text, UI, tooltip, page
- if nrpage < 9:
- modifier = "%d" % ((nrpage % 9) + 1)
- else:
- modifier = ""
- self.view_toggle_actions[indexcat].append((pageid,
- page.get_viewtype_stock(),
- pdata.name, modifier, page_title, nrpage))
-
- nrpage += 1
- if nr_views > 1:
- #allow for switching views in a category
- self.ui_category[indexcat] = UICATEGORY % (uimenuitems,
- uitoolitems)
- #set view cat to last used in this category
- self.notebook_cat[-1].set_current_page(default_cat_views[indexcat])
-
- if self.views:
- self.active_page = self.pages[current_cat][current_cat_view]
- self.buttons[current_cat].set_active(True)
- self.active_page.set_active()
- self.notebook.set_current_page(current_cat)
- self.notebook_cat[current_cat].set_current_page(current_cat_view)
- else:
- #not one single view loaded
- WarningDialog(
- _("No views loaded"),
- _("No view plugins are loaded. Go to Help->Plugin "
- "Manager, and make sure some plugins of type 'View' are "
- "enabled. Then restart Gramps"))
-
-
- def __views_to_show(self, use_last = True):
- """
- Determine based on preference setting which views should be shown
- """
- current_cat = 0
- current_cat_view = 0
- default_cat_views = [0] * len(self.views)
- if use_last:
- current_page_id = config.get('preferences.last-view')
- default_page_ids = config.get('preferences.last-views')
- found = False
- for indexcat, cat_views in enumerate(self.views):
- cat_view = 0
- for pdata, page_def in cat_views:
- if not found:
- if pdata.id == current_page_id:
- current_cat = indexcat
- current_cat_view = cat_view
- default_cat_views[indexcat] = cat_view
- found = True
- break
- if pdata.id in default_page_ids:
- default_cat_views[indexcat] = cat_view
- cat_view += 1
- if not found:
- current_cat = 0
- current_cat_view = 0
- return current_cat, current_cat_view, default_cat_views
-
- def __make_sidebar_button(self, use_text, index, page_title, page_stock):
- """
- Create the sidebar button. The page_title is the text associated with
- the button.
- """
-
- # create the button
- button = gtk.ToggleButton()
- button.set_relief(gtk.RELIEF_NONE)
- button.set_alignment(0, 0.5)
-
- # add the tooltip
- button.set_tooltip_text(page_title)
- #self.tips.set_tip(button, page_title)
-
- # connect the signal, along with the index as user data
- handler_id = button.connect('clicked', self.__vb_clicked, index)
- self.button_handlers.append(handler_id)
- button.show()
-
- # add the image. If we are using text, use the BUTTON (larger) size.
- # otherwise, use the smaller size
- hbox = gtk.HBox()
- hbox.show()
- image = gtk.Image()
- if use_text:
- image.set_from_stock(page_stock, gtk.ICON_SIZE_BUTTON)
- else:
- image.set_from_stock(page_stock, gtk.ICON_SIZE_DND)
- image.show()
- hbox.pack_start(image, False, False)
- hbox.set_spacing(4)
-
- # add text if requested
- if use_text:
- label = gtk.Label(page_title)
- label.show()
- hbox.pack_start(label, False, True)
-
- button.add(hbox)
- return button
-
- def __vb_clicked(self, button, index):
- """
- Called when the button causes a page change
- """
- if config.get('interface.view'):
- self.__vb_handlers_block()
- self.notebook.set_current_page(index)
-
- # If the click is on the same view we're in,
- # restore the button state to active
- if not button.get_active():
- button.set_active(True)
- self.__vb_handlers_unblock()
-
- def __vb_handlers_block(self):
- """
- Block signals to the buttons to prevent spurious events
- """
- for idx in range(len(self.buttons)):
- self.buttons[idx].handler_block(self.button_handlers[idx])
-
- def __vb_handlers_unblock(self):
- """
- Unblock signals to the buttons
- """
- for idx in range(len(self.buttons)):
- self.buttons[idx].handler_unblock(self.button_handlers[idx])
-
- def __set_active_button(self, num):
- """
- Set the corresponding button active, while setting the others
- inactive
- """
- for idx in range(len(self.buttons)):
- self.buttons[idx].set_active(idx==num)
+ for page in self.pages:
+ page.on_delete()
def __disconnect_previous_page(self):
"""
@@ -1098,11 +902,8 @@ class ViewManager(CLIManager):
for grp in groups:
if grp in self.uimanager.get_action_groups():
self.uimanager.remove_action_group(grp)
- if self.cat_view_group:
- if self.cat_view_group in self.uimanager.get_action_groups():
- self.uimanager.remove_action_group(self.cat_view_group)
- def __connect_active_page(self, category_page, view_page):
+ def __connect_active_page(self, page_num):
"""
Inserts the action groups associated with the current page
into the UIManager
@@ -1117,90 +918,12 @@ class ViewManager(CLIManager):
mergeid = self.uimanager.add_ui_from_string(uidef)
self.merge_ids.append(mergeid)
- if category_page in self.ui_category:
- #add entries for the different views in the category
- self.cat_view_group = gtk.ActionGroup('categoryviews')
- self.cat_view_group.add_radio_actions(
- self.view_toggle_actions[category_page], value=view_page,
- on_change=self.view_toggle, user_data=category_page)
- self.cat_view_group.set_sensitive(True)
- self.uimanager.insert_action_group(self.cat_view_group, 1)
- mergeid = self.uimanager.add_ui_from_string(self.ui_category[
- category_page])
- self.merge_ids.append(mergeid)
-
configaction = self.actiongroup.get_action('ConfigView')
if self.active_page.can_configure():
configaction.set_sensitive(True)
else:
configaction.set_sensitive(False)
- def change_category(self, obj, page, num=-1):
- """
- Wrapper for the __do_change_category, to prevent entering into the
- routine while already in it.
- """
- if not self.page_is_changing:
- self.page_is_changing = True
- self.__do_change_category(num)
- self.page_is_changing = False
-
- def __do_change_category(self, num):
- """
- Change the category to the new category
- """
- if num == -1:
- num = self.notebook.get_current_page()
-
- # set button of current page active
- self.__set_active_button(num)
- # now do view specific change
- self.__change_view(num)
-
- def __change_view(self, category_page, view_page=-1):
- """
- Change a view in a category.
-
- :Param category_page: the category number the view is in
- :Type category_page: integer >= 0
-
- :Param view_page: the view page number to switch to. If -1 is passed
- the currently already active view in the category is switched to.
- Use this when a category changes.
- :Type view_page: integer >=0 to switch to a specific page, or -1 to
- switch to the active view in the category
- """
- if self.notebook_cat:
- if view_page == -1:
- #just show active one
- view_page = self.notebook_cat[category_page].get_current_page()
- if self.dbstate.open:
- self.__disconnect_previous_page()
- if len(self.pages) > 0:
- self.active_page = self.pages[category_page][view_page]
- self.active_page.set_active()
- newcurpageid = self.views[category_page][view_page][0].id
- config.set('preferences.last-view', newcurpageid)
- olddefaults = config.get('preferences.last-views')
- if len(olddefaults) != len(self.pages):
- #number views changed, we cannot trust the old
- olddefaults = [''] * len(self.pages)
- olddefaults[category_page] = newcurpageid
- config.set('preferences.last-views', olddefaults)
- config.save()
-
- self.__connect_active_page(category_page, view_page)
-
- self.uimanager.ensure_update()
-
- while gtk.events_pending():
- gtk.main_iteration()
-
- self.active_page.change_page()
- else:
- #no views loaded
- pass
-
def import_data(self, obj):
"""
Imports a file
@@ -1267,7 +990,6 @@ class ViewManager(CLIManager):
self.uistate.window.set_title(msg)
self.actiongroup.set_sensitive(True)
- self.change_category(None, None)
self.actiongroup.set_visible(True)
self.readonlygroup.set_visible(True)
@@ -1597,3 +1319,79 @@ def make_plugin_callback(pdata, dbstate, uistate):
Makes a callback for a report/tool menu item
"""
return lambda x: run_plugin(pdata, dbstate, uistate)
+
+def get_available_views():
+ """
+ Query the views and determine what views to show and in which order
+
+ :Returns: a list of lists containing tuples (view_id, viewclass)
+ """
+ pmgr = GuiPluginManager.get_instance()
+ view_list = pmgr.get_reg_views()
+ viewstoshow = {}
+ for pdata in view_list:
+ mod = pmgr.load_plugin(pdata)
+ if not mod or not hasattr(mod, pdata.viewclass):
+ #import of plugin failed
+ ErrorDialog(
+ _('Failed Loading View'),
+ _('The view %(name)s did not load. See Help Menu, Plugin Manager'
+ ' for more info.\nUse http://bugs.gramps-project.org to'
+ ' submit bugs of official views, contact the view '
+ 'author (%(firstauthoremail)s) otherwise. ') % {
+ 'name': pdata.name,
+ 'firstauthoremail': pdata.authors_email[0] if
+ pdata.authors_email else '...'})
+ continue
+ viewclass = getattr(mod, pdata.viewclass)
+ # pdata.category is (string, trans-string):
+ if pdata.category[0] in viewstoshow:
+ if pdata.order == START:
+ viewstoshow[pdata.category[0]].insert(0, ((pdata, viewclass)))
+ else:
+ viewstoshow[pdata.category[0]].append((pdata, viewclass))
+ else:
+ viewstoshow[pdata.category[0]] = [(pdata, viewclass)]
+
+ resultorder = []
+ # First, get those in order defined, if exists:
+ for item in config.get("interface.view-categories"):
+ if item in viewstoshow:
+ resultorder.append(viewstoshow[item])
+ # Next, get the rest in some order:
+ viewstoshow_names = viewstoshow.keys()
+ viewstoshow_names.sort()
+ for item in viewstoshow_names:
+ if viewstoshow[item] in resultorder:
+ continue
+ resultorder.append(viewstoshow[item])
+ return resultorder
+
+def views_to_show(views, use_last=True):
+ """
+ Determine based on preference setting which views should be shown
+ """
+ current_cat = 0
+ current_cat_view = 0
+ default_cat_views = [0] * len(views)
+ if use_last:
+ current_page_id = config.get('preferences.last-view')
+ default_page_ids = config.get('preferences.last-views')
+ found = False
+ for indexcat, cat_views in enumerate(views):
+ cat_view = 0
+ for pdata, page_def in cat_views:
+ if not found:
+ if pdata.id == current_page_id:
+ current_cat = indexcat
+ current_cat_view = cat_view
+ default_cat_views[indexcat] = cat_view
+ found = True
+ break
+ if pdata.id in default_page_ids:
+ default_cat_views[indexcat] = cat_view
+ cat_view += 1
+ if not found:
+ current_cat = 0
+ current_cat_view = 0
+ return current_cat, current_cat_view, default_cat_views
diff --git a/src/plugins/sidebar/Makefile.am b/src/plugins/sidebar/Makefile.am
new file mode 100644
index 000000000..049ffca29
--- /dev/null
+++ b/src/plugins/sidebar/Makefile.am
@@ -0,0 +1,22 @@
+# This is the src/plugins/sidebar level Makefile for Gramps
+# We could use GNU make's ':=' syntax for nice wildcard use,
+# but that is not necessarily portable.
+# If not using GNU make, then list all .py files individually
+
+pkgdatadir = $(datadir)/@PACKAGE@/plugins/sidebar
+
+pkgdata_PYTHON = \
+ categorysidebar.py\
+ sidebar.gpr.py
+
+pkgpyexecdir = @pkgpyexecdir@/plugins/sidebar
+pkgpythondir = @pkgpythondir@/plugins/sidebar
+
+# Clean up all the byte-compiled files
+MOSTLYCLEANFILES = *pyc *pyo
+
+GRAMPS_PY_MODPATH = "../../"
+
+pycheck:
+ (export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
+ pychecker $(pkgdata_PYTHON));
diff --git a/src/plugins/sidebar/categorysidebar.py b/src/plugins/sidebar/categorysidebar.py
new file mode 100644
index 000000000..949e722fa
--- /dev/null
+++ b/src/plugins/sidebar/categorysidebar.py
@@ -0,0 +1,301 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2005-2007 Donald N. Allingham
+# Copyright (C) 2008 Brian G. Matherly
+# Copyright (C) 2009 Benny Malengier
+# Copyright (C) 2010 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
+# 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
+#
+# $Id$
+
+#-------------------------------------------------------------------------
+#
+# GNOME modules
+#
+#-------------------------------------------------------------------------
+import gtk
+
+#-------------------------------------------------------------------------
+#
+# GRAMPS modules
+#
+#-------------------------------------------------------------------------
+import config
+from gui.viewmanager import get_available_views, views_to_show
+
+#-------------------------------------------------------------------------
+#
+# Constants
+#
+#-------------------------------------------------------------------------
+UICATEGORY = '''
+
+
+
+
+ %s
+
+
+
+'''
+
+CATEGORY_ICON = {
+ 'Gramplets': 'gramps-gramplet',
+ 'People': 'gramps-person',
+ 'Relationships': 'gramps-relation',
+ 'Families': 'gramps-family',
+ 'Events': 'gramps-event',
+ 'Ancestry': 'gramps-pedigree',
+ 'Places': 'gramps-place',
+ 'Geography': 'gramps-geo',
+ 'Sources': 'gramps-source',
+ 'Repositories': 'gramps-repository',
+ 'Media': 'gramps-media',
+ 'Notes': 'gramps-notes'}
+
+#-------------------------------------------------------------------------
+#
+# CategorySidebar class
+#
+#-------------------------------------------------------------------------
+class CategorySidebar(object):
+ """
+ A sidebar displaying a column of toggle buttons that allows the user to
+ change the current view.
+ """
+ def __init__(self, dbstate, uistate):
+
+ self.viewmanager = uistate.viewmanager
+
+ self.buttons = []
+ self.button_handlers = []
+
+ self.vbox = gtk.VBox()
+
+ self.pages = {}
+ self.page_defs = {}
+
+ self.ui_category = {}
+ self.view_toggle_actions = {}
+ self.cat_view_group = None
+ self.merge_ids = []
+
+ self.views = get_available_views()
+ defaults = views_to_show(self.views,
+ config.get('preferences.use-last-view'))
+ self.current_views = defaults[2]
+
+ use_text = config.get('interface.sidebar-text')
+ for cat_num, cat_views in enumerate(self.views):
+ uimenuitems = ''
+ uitoolitems = ''
+ self.view_toggle_actions[cat_num] = []
+ for view_num, page in enumerate(cat_views):
+
+ if view_num == 0:
+ category = page[0].category[1]
+ cat_icon = CATEGORY_ICON.get(page[0].category[0])
+ if cat_icon is None:
+ cat_icon = 'gramps-view'
+
+ # create the button and add it to the sidebar
+ button = self.__make_sidebar_button(use_text, cat_num,
+ category, cat_icon)
+ self.vbox.pack_start(button, False)
+
+ # Enable view switching during DnD
+ button.drag_dest_set(0, [], 0)
+ button.connect('drag_motion', self.cb_switch_page_on_dnd,
+ cat_num)
+ self.vbox.show_all()
+
+ self.page_defs[(cat_num, view_num)] = page
+
+ pageid = (page[0].id + '_%i' % view_num)
+ uimenuitems += '\n' % pageid
+ uitoolitems += '\n' % pageid
+ # id, stock, button text, UI, tooltip, page
+ if view_num < 9:
+ modifier = "%d" % ((view_num % 9) + 1)
+ else:
+ modifier = ""
+
+ stock_icon = page[0].stock_icon
+ if stock_icon is None:
+ stock_icon = cat_icon
+ self.view_toggle_actions[cat_num].append((pageid,
+ stock_icon,
+ page[0].name, modifier, page[0].name, view_num))
+
+ if len(cat_views) > 1:
+ #allow for switching views in a category
+ self.ui_category[cat_num] = UICATEGORY % (uimenuitems,
+ uitoolitems)
+ # Open the default view
+ self.__category_clicked(self.buttons[defaults[0]], defaults[0])
+
+ def get_top(self):
+ """
+ Return the top container widget for the GUI.
+ """
+ return self.vbox
+
+ def view_changed(self, page_num):
+ """
+ Called when the active view is changed.
+ """
+ cat_num = view_num = None
+ for key in self.pages:
+ if self.pages[key] == page_num:
+ cat_num, view_num = key
+ break
+
+ # Save last view in configuration
+ view_id = self.views[cat_num][view_num][0].id
+ config.set('preferences.last-view', view_id)
+ last_views = config.get('preferences.last-views')
+ last_views[cat_num] = view_id
+ config.set('preferences.last-views', last_views)
+ config.save()
+
+ # Add buttons to the toolbar for the different view in the category
+ uimanager = self.viewmanager.uimanager
+ if self.cat_view_group:
+ if self.cat_view_group in uimanager.get_action_groups():
+ uimanager.remove_action_group(self.cat_view_group)
+
+ map(uimanager.remove_ui, self.merge_ids)
+
+ if cat_num in self.ui_category:
+ self.cat_view_group = gtk.ActionGroup('categoryviews')
+ self.cat_view_group.add_radio_actions(
+ self.view_toggle_actions[cat_num], value=view_num,
+ on_change=self.cb_view_clicked, user_data=cat_num)
+ self.cat_view_group.set_sensitive(True)
+ uimanager.insert_action_group(self.cat_view_group, 1)
+ mergeid = uimanager.add_ui_from_string(self.ui_category[cat_num])
+ self.merge_ids.append(mergeid)
+
+ # Set new button as selected
+ self.handlers_block()
+ for index, button in enumerate(self.buttons):
+ if index == cat_num:
+ button.set_active(True)
+ else:
+ button.set_active(False)
+ self.handlers_unblock()
+
+ def handlers_block(self):
+ """
+ Block signals to the buttons to prevent spurious events.
+ """
+ for idx in range(len(self.buttons)):
+ self.buttons[idx].handler_block(self.button_handlers[idx])
+
+ def handlers_unblock(self):
+ """
+ Unblock signals to the buttons.
+ """
+ for idx in range(len(self.buttons)):
+ self.buttons[idx].handler_unblock(self.button_handlers[idx])
+
+ def cb_view_clicked(self, radioaction, current, cat_num):
+ """
+ Called when a button causes a view change.
+ """
+ view_num = radioaction.get_current_value()
+ self.__goto_page(cat_num, view_num)
+
+ def __category_clicked(self, button, cat_num):
+ """
+ Called when a button causes a category change.
+ """
+ view_num = self.current_views[cat_num]
+ self.__goto_page(cat_num, view_num)
+
+ # If the click is on the same view we're in,
+ # restore the button state to active
+ if not button.get_active():
+ button.set_active(True)
+
+ def __goto_page(self, cat_num, view_num):
+ """
+ Create the page if it doesn't exist and make it the current page.
+ """
+ self.current_views[cat_num] = view_num
+
+ page_num = self.pages.get((cat_num, view_num))
+ if page_num is None:
+ page = self.page_defs[(cat_num, view_num)]
+ page_num = self.viewmanager.create_page(page[0], page[1])
+ self.pages[(cat_num, view_num)] = page_num
+
+ self.current_views[cat_num] = view_num
+ self.viewmanager.goto_page(page_num)
+
+ def __make_sidebar_button(self, use_text, index, page_title, page_stock):
+ """
+ Create the sidebar button. The page_title is the text associated with
+ the button.
+ """
+ # create the button
+ button = gtk.ToggleButton()
+ button.set_relief(gtk.RELIEF_NONE)
+ button.set_alignment(0, 0.5)
+ self.buttons.append(button)
+
+ # add the tooltip
+ button.set_tooltip_text(page_title)
+
+ # connect the signal, along with the index as user data
+ handler_id = button.connect('clicked', self.__category_clicked, index)
+ self.button_handlers.append(handler_id)
+ button.show()
+
+ # add the image. If we are using text, use the BUTTON (larger) size.
+ # otherwise, use the smaller size
+ hbox = gtk.HBox()
+ hbox.show()
+ image = gtk.Image()
+ if use_text:
+ image.set_from_stock(page_stock, gtk.ICON_SIZE_BUTTON)
+ else:
+ image.set_from_stock(page_stock, gtk.ICON_SIZE_DND)
+ image.show()
+ hbox.pack_start(image, False, False)
+ hbox.set_spacing(4)
+
+ # add text if requested
+ if use_text:
+ label = gtk.Label(page_title)
+ label.show()
+ hbox.pack_start(label, False, True)
+
+ button.add(hbox)
+ return button
+
+ def cb_switch_page_on_dnd(self, widget, context, xpos, ypos, time, page_no):
+ """
+ Switches the page based on drag and drop.
+ """
+ self.handlers_block()
+ if self.viewmanager.notebook.get_current_page() != page_no:
+ self.viewmanager.notebook.set_current_page(page_no)
+ self.handlers_unblock()
diff --git a/src/plugins/sidebar/sidebar.gpr.py b/src/plugins/sidebar/sidebar.gpr.py
new file mode 100644
index 000000000..60c2eb480
--- /dev/null
+++ b/src/plugins/sidebar/sidebar.gpr.py
@@ -0,0 +1,40 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2010 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
+# 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
+#
+# $Id$
+
+#------------------------------------------------------------------------
+#
+# Register default sidebars
+#
+#------------------------------------------------------------------------
+
+register(SIDEBAR,
+id = 'categorysidebar',
+name = _("Category Sidebar"),
+description = _("A sidebar to allow the selection of view categories"),
+version = '1.0',
+gramps_target_version = '3.3',
+status = STABLE,
+fname = 'categorysidebar.py',
+authors = [u"Nick Hall"],
+authors_email = ["nick__hall@hotmail.com"],
+sidebarclass = 'CategorySidebar',
+menu_label = 'Category'
+)
diff --git a/src/plugins/view/fanchartview.gpr.py b/src/plugins/view/fanchartview.gpr.py
index 2ad2ab887..fe5e7a936 100644
--- a/src/plugins/view/fanchartview.gpr.py
+++ b/src/plugins/view/fanchartview.gpr.py
@@ -10,4 +10,5 @@ register(VIEW,
authors = [u"Douglas S. Blank"],
authors_email = ["doug.blank@gmail.com"],
viewclass = 'FanChartView',
+ stock_icon = 'gramps-fanchart',
)
diff --git a/src/plugins/view/placetreeview.gpr.py b/src/plugins/view/placetreeview.gpr.py
index 6bab25367..f845a3aa4 100644
--- a/src/plugins/view/placetreeview.gpr.py
+++ b/src/plugins/view/placetreeview.gpr.py
@@ -10,4 +10,5 @@ register(VIEW,
authors_email = [""],
category = ("Places", _("Places")),
viewclass = 'PlaceTreeView',
+ stock_icon = 'gramps-tree-group',
)
diff --git a/src/plugins/view/view.gpr.py b/src/plugins/view/view.gpr.py
index eaba02441..9c1945d33 100644
--- a/src/plugins/view/view.gpr.py
+++ b/src/plugins/view/view.gpr.py
@@ -130,6 +130,7 @@ authors_email = ["http://gramps-project.org"],
category = ("Ancestry", _("Ancestry")),
viewclass = 'PedigreeView',
order = START,
+stock_icon = 'gramps-pedigree',
)
register(VIEW,
@@ -145,6 +146,7 @@ authors_email = ["http://gramps-project.org"],
category = ("People", _("People")),
viewclass = 'PersonTreeView',
order = START,
+stock_icon = 'gramps-tree-group',
)
register(VIEW,
@@ -161,7 +163,9 @@ authors_email = ["http://gramps-project.org"],
category = ("People", _("People")),
viewclass = 'PersonListView',
order = START,
+stock_icon = 'gramps-tree-list',
)
+
register(VIEW,
id = 'placelistview',
name = _("Place View"),
@@ -175,6 +179,7 @@ authors_email = ["http://gramps-project.org"],
category = ("Places", _("Places")),
viewclass = 'PlaceListView',
order = START,
+stock_icon = 'gramps-tree-list',
)
register(VIEW,