GEPS 019: Improved sidebar which allows sidebar plugins
svn: r15029
This commit is contained in:
@ -140,6 +140,7 @@ src/plugins/lib/Makefile
|
|||||||
src/plugins/mapservices/Makefile
|
src/plugins/mapservices/Makefile
|
||||||
src/plugins/quickview/Makefile
|
src/plugins/quickview/Makefile
|
||||||
src/plugins/rel/Makefile
|
src/plugins/rel/Makefile
|
||||||
|
src/plugins/sidebar/Makefile
|
||||||
src/plugins/textreport/Makefile
|
src/plugins/textreport/Makefile
|
||||||
src/plugins/tool/Makefile
|
src/plugins/tool/Makefile
|
||||||
src/plugins/view/Makefile
|
src/plugins/view/Makefile
|
||||||
|
@ -288,6 +288,11 @@ class BasePluginManager(object):
|
|||||||
"""
|
"""
|
||||||
return self.__pgr.gramplet_plugins()
|
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):
|
def get_external_opt_dict(self):
|
||||||
""" Return the dictionary of external options. """
|
""" Return the dictionary of external options. """
|
||||||
return self.__external_opt_dict
|
return self.__external_opt_dict
|
||||||
|
@ -68,8 +68,9 @@ MAPSERVICE = 7
|
|||||||
VIEW = 8
|
VIEW = 8
|
||||||
RELCALC = 9
|
RELCALC = 9
|
||||||
GRAMPLET = 10
|
GRAMPLET = 10
|
||||||
PTYPE = [ REPORT , QUICKREPORT, TOOL, IMPORT,
|
SIDEBAR = 11
|
||||||
EXPORT, DOCGEN, GENERAL, MAPSERVICE, VIEW, RELCALC, GRAMPLET]
|
PTYPE = [REPORT , QUICKREPORT, TOOL, IMPORT, EXPORT, DOCGEN, GENERAL,
|
||||||
|
MAPSERVICE, VIEW, RELCALC, GRAMPLET, SIDEBAR]
|
||||||
PTYPE_STR = {
|
PTYPE_STR = {
|
||||||
REPORT: _('Report') ,
|
REPORT: _('Report') ,
|
||||||
QUICKREPORT: _('Quickreport'),
|
QUICKREPORT: _('Quickreport'),
|
||||||
@ -82,6 +83,7 @@ PTYPE_STR = {
|
|||||||
VIEW: _('Gramps View'),
|
VIEW: _('Gramps View'),
|
||||||
RELCALC: _('Relationships'),
|
RELCALC: _('Relationships'),
|
||||||
GRAMPLET: _('Gramplet'),
|
GRAMPLET: _('Gramplet'),
|
||||||
|
SIDEBAR: _('Sidebar'),
|
||||||
}
|
}
|
||||||
|
|
||||||
#possible report categories
|
#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
|
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
|
prepended. Only set START if you want a view to be the first in the
|
||||||
order of views
|
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):
|
def __init__(self):
|
||||||
@ -364,6 +374,10 @@ class PluginData(object):
|
|||||||
#VIEW attr
|
#VIEW attr
|
||||||
self._viewclass = None
|
self._viewclass = None
|
||||||
self._order = END
|
self._order = END
|
||||||
|
self._stock_icon = None
|
||||||
|
#SIDEBAR attr
|
||||||
|
self._sidebarclass = None
|
||||||
|
self._menu_label = ''
|
||||||
|
|
||||||
def _set_id(self, id):
|
def _set_id(self, id):
|
||||||
self._id = id
|
self._id = id
|
||||||
@ -811,9 +825,37 @@ class PluginData(object):
|
|||||||
def _get_order(self):
|
def _get_order(self):
|
||||||
return self._order
|
return self._order
|
||||||
|
|
||||||
viewclass = property(_get_viewclass, _set_viewclass)
|
def _set_stock_icon(self, stock_icon):
|
||||||
order = property(_get_order, _set_order)
|
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():
|
def newplugin():
|
||||||
"""
|
"""
|
||||||
@ -865,6 +907,7 @@ def make_environment(**kwargs):
|
|||||||
'VIEW': VIEW,
|
'VIEW': VIEW,
|
||||||
'RELCALC': RELCALC,
|
'RELCALC': RELCALC,
|
||||||
'GRAMPLET': GRAMPLET,
|
'GRAMPLET': GRAMPLET,
|
||||||
|
'SIDEBAR': SIDEBAR,
|
||||||
'CATEGORY_TEXT': CATEGORY_TEXT,
|
'CATEGORY_TEXT': CATEGORY_TEXT,
|
||||||
'CATEGORY_DRAW': CATEGORY_DRAW,
|
'CATEGORY_DRAW': CATEGORY_DRAW,
|
||||||
'CATEGORY_CODE': CATEGORY_CODE,
|
'CATEGORY_CODE': CATEGORY_CODE,
|
||||||
@ -1107,6 +1150,11 @@ class PluginRegister(object):
|
|||||||
"""
|
"""
|
||||||
return self.type_plugins(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):
|
def filter_load_on_reg(self):
|
||||||
"""Return a list of PluginData that have load_on_reg == True
|
"""Return a list of PluginData that have load_on_reg == True
|
||||||
"""
|
"""
|
||||||
|
@ -21,6 +21,7 @@ pkgdata_PYTHON = \
|
|||||||
filtereditor.py \
|
filtereditor.py \
|
||||||
grampsgui.py \
|
grampsgui.py \
|
||||||
pluginmanager.py \
|
pluginmanager.py \
|
||||||
|
sidebar.py \
|
||||||
utils.py \
|
utils.py \
|
||||||
viewmanager.py
|
viewmanager.py
|
||||||
|
|
||||||
|
@ -62,8 +62,7 @@ from QuestionDialog import ErrorDialog
|
|||||||
import config
|
import config
|
||||||
import Utils
|
import Utils
|
||||||
from constfunc import win
|
from constfunc import win
|
||||||
from gui.pluginmanager import GuiPluginManager, base_reg_stock_icons
|
from gui.pluginmanager import base_reg_stock_icons
|
||||||
from gen.plug import (START, END)
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -71,7 +70,6 @@ from gen.plug import (START, END)
|
|||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def register_stock_icons ():
|
def register_stock_icons ():
|
||||||
"""
|
"""
|
||||||
Add the gramps names for its icons (eg gramps-person) to the GTK icon
|
Add the gramps names for its icons (eg gramps-person) to the GTK icon
|
||||||
@ -186,53 +184,6 @@ def _display_welcome_message():
|
|||||||
# config.set('behavior.betawarn', True)
|
# config.set('behavior.betawarn', True)
|
||||||
config.set('behavior.betawarn', config.get('behavior.betawarn'))
|
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
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Main Gramps class
|
# Main Gramps class
|
||||||
@ -256,11 +207,7 @@ class Gramps(object):
|
|||||||
|
|
||||||
dbstate = DbState.DbState()
|
dbstate = DbState.DbState()
|
||||||
self.vm = ViewManager(dbstate, config.get("interface.view-categories"))
|
self.vm = ViewManager(dbstate, config.get("interface.view-categories"))
|
||||||
|
self.vm.init_interface()
|
||||||
#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)
|
|
||||||
|
|
||||||
#act based on the given arguments
|
#act based on the given arguments
|
||||||
ah = ArgHandler(dbstate, argparser, self.vm, self.argerrorfunc,
|
ah = ArgHandler(dbstate, argparser, self.vm, self.argerrorfunc,
|
||||||
@ -290,7 +237,6 @@ class Gramps(object):
|
|||||||
""" Show basic errors in argument handling in GUI fashion"""
|
""" Show basic errors in argument handling in GUI fashion"""
|
||||||
ErrorDialog(_("Error parsing arguments"), string)
|
ErrorDialog(_("Error parsing arguments"), string)
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Main startup functions
|
# Main startup functions
|
||||||
|
@ -289,6 +289,12 @@ class GuiPluginManager(gen.utils.Callback):
|
|||||||
return [plg for plg in self.basemgr.get_reg_gramplets()
|
return [plg for plg in self.basemgr.get_reg_gramplets()
|
||||||
if plg.id not in self.__hidden_plugins]
|
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):
|
def get_reg_importers(self):
|
||||||
""" Return list of registered importers
|
""" Return list of registered importers
|
||||||
"""
|
"""
|
||||||
|
173
src/gui/sidebar.py
Normal file
173
src/gui/sidebar.py
Normal file
@ -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)
|
@ -4,6 +4,7 @@
|
|||||||
# Copyright (C) 2005-2007 Donald N. Allingham
|
# Copyright (C) 2005-2007 Donald N. Allingham
|
||||||
# Copyright (C) 2008 Brian G. Matherly
|
# Copyright (C) 2008 Brian G. Matherly
|
||||||
# Copyright (C) 2009 Benny Malengier
|
# Copyright (C) 2009 Benny Malengier
|
||||||
|
# Copyright (C) 2010 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
|
||||||
@ -61,6 +62,7 @@ from PluginUtils import Tool, PluginWindows, \
|
|||||||
ReportPluginDialog, ToolPluginDialog, gui_tool
|
ReportPluginDialog, ToolPluginDialog, gui_tool
|
||||||
from gen.plug import REPORT
|
from gen.plug import REPORT
|
||||||
from gui.pluginmanager import GuiPluginManager
|
from gui.pluginmanager import GuiPluginManager
|
||||||
|
from gen.plug import (START, END)
|
||||||
import Relationship
|
import Relationship
|
||||||
import ReportBase
|
import ReportBase
|
||||||
import DisplayState
|
import DisplayState
|
||||||
@ -78,6 +80,7 @@ from gui.configure import GrampsPreferences
|
|||||||
from gen.db.backup import backup
|
from gen.db.backup import backup
|
||||||
from gen.db.exceptions import DbException
|
from gen.db.exceptions import DbException
|
||||||
from GrampsAboutDialog import GrampsAboutDialog
|
from GrampsAboutDialog import GrampsAboutDialog
|
||||||
|
from gui.sidebar import Sidebar
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
@ -183,20 +186,6 @@ UIDEFAULT = '''<ui>
|
|||||||
</ui>
|
</ui>
|
||||||
'''
|
'''
|
||||||
|
|
||||||
UICATEGORY = '''<ui>
|
|
||||||
<menubar name="MenuBar">
|
|
||||||
<menu action="ViewMenu">
|
|
||||||
<placeholder name="ViewsInCategory">%s
|
|
||||||
</placeholder>
|
|
||||||
</menu>
|
|
||||||
</menubar>
|
|
||||||
<toolbar name="ToolBar">
|
|
||||||
<placeholder name="ViewsInCategory">%s
|
|
||||||
</placeholder>
|
|
||||||
</toolbar>
|
|
||||||
</ui>
|
|
||||||
'''
|
|
||||||
|
|
||||||
WIKI_HELP_PAGE_FAQ = '%s_-_FAQ' % const.URL_MANUAL_PAGE
|
WIKI_HELP_PAGE_FAQ = '%s_-_FAQ' % const.URL_MANUAL_PAGE
|
||||||
WIKI_HELP_PAGE_KEY = '%s_-_Keybindings' % const.URL_MANUAL_PAGE
|
WIKI_HELP_PAGE_KEY = '%s_-_Keybindings' % const.URL_MANUAL_PAGE
|
||||||
WIKI_HELP_PAGE_MAN = '%s' % 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
|
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
|
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):
|
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
|
working, and a fixed view_category_order, which is the order in which
|
||||||
the view categories are accessible in the sidebar.
|
the view categories are accessible in the sidebar.
|
||||||
"""
|
"""
|
||||||
@ -248,12 +238,8 @@ class ViewManager(CLIManager):
|
|||||||
self.view_category_order = view_category_order
|
self.view_category_order = view_category_order
|
||||||
#set pluginmanager to GUI one
|
#set pluginmanager to GUI one
|
||||||
self._pmgr = GuiPluginManager.get_instance()
|
self._pmgr = GuiPluginManager.get_instance()
|
||||||
self.page_is_changing = False
|
|
||||||
self.active_page = None
|
self.active_page = None
|
||||||
self.views = []
|
|
||||||
self.pages = []
|
self.pages = []
|
||||||
self.button_handlers = []
|
|
||||||
self.buttons = []
|
|
||||||
self.merge_ids = []
|
self.merge_ids = []
|
||||||
self.toolactions = None
|
self.toolactions = None
|
||||||
self.tool_menu_ui_id = None
|
self.tool_menu_ui_id = None
|
||||||
@ -294,12 +280,13 @@ class ViewManager(CLIManager):
|
|||||||
|
|
||||||
vbox = gtk.VBox()
|
vbox = gtk.VBox()
|
||||||
self.window.add(vbox)
|
self.window.add(vbox)
|
||||||
hbox = gtk.HBox()
|
hpane = gtk.HPaned()
|
||||||
self.ebox = gtk.EventBox()
|
self.ebox = gtk.EventBox()
|
||||||
self.bbox = gtk.VBox()
|
|
||||||
self.ebox.add(self.bbox)
|
self.sidebar = Sidebar(self)
|
||||||
hbox.pack_start(self.ebox, False)
|
self.ebox.add(self.sidebar.get_top())
|
||||||
hbox.show_all()
|
hpane.add1(self.ebox)
|
||||||
|
hpane.show_all()
|
||||||
|
|
||||||
self.notebook = gtk.Notebook()
|
self.notebook = gtk.Notebook()
|
||||||
self.notebook.set_scrollable(True)
|
self.notebook.set_scrollable(True)
|
||||||
@ -309,12 +296,12 @@ class ViewManager(CLIManager):
|
|||||||
self.__init_lists()
|
self.__init_lists()
|
||||||
self.__build_ui_manager()
|
self.__build_ui_manager()
|
||||||
|
|
||||||
hbox.pack_start(self.notebook, True)
|
hpane.add2(self.notebook)
|
||||||
self.menubar = self.uimanager.get_widget('/MenuBar')
|
self.menubar = self.uimanager.get_widget('/MenuBar')
|
||||||
self.toolbar = self.uimanager.get_widget('/ToolBar')
|
self.toolbar = self.uimanager.get_widget('/ToolBar')
|
||||||
vbox.pack_start(self.menubar, False)
|
vbox.pack_start(self.menubar, False)
|
||||||
vbox.pack_start(self.toolbar, False)
|
vbox.pack_start(self.toolbar, False)
|
||||||
vbox.add(hbox)
|
vbox.add(hpane)
|
||||||
vbox.pack_end(self.__setup_statusbar(), False)
|
vbox.pack_end(self.__setup_statusbar(), False)
|
||||||
vbox.show()
|
vbox.show()
|
||||||
|
|
||||||
@ -358,6 +345,21 @@ class ViewManager(CLIManager):
|
|||||||
# But we need to realize it here to have gtk.gdk.window handy
|
# But we need to realize it here to have gtk.gdk.window handy
|
||||||
self.window.realize()
|
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):
|
def __setup_statusbar(self):
|
||||||
"""
|
"""
|
||||||
Create the statusbar that sits at the bottom of the window
|
Create the statusbar that sits at the bottom of the window
|
||||||
@ -387,10 +389,8 @@ class ViewManager(CLIManager):
|
|||||||
"""
|
"""
|
||||||
if self.show_sidebar:
|
if self.show_sidebar:
|
||||||
self.ebox.show()
|
self.ebox.show()
|
||||||
self.notebook.set_show_tabs(False)
|
|
||||||
else:
|
else:
|
||||||
self.ebox.hide()
|
self.ebox.hide()
|
||||||
self.notebook.set_show_tabs(True)
|
|
||||||
|
|
||||||
def __build_open_button(self):
|
def __build_open_button(self):
|
||||||
"""
|
"""
|
||||||
@ -406,10 +406,17 @@ class ViewManager(CLIManager):
|
|||||||
|
|
||||||
def __connect_signals(self):
|
def __connect_signals(self):
|
||||||
"""
|
"""
|
||||||
connects the signals needed
|
Connects the signals needed
|
||||||
"""
|
"""
|
||||||
self.window.connect('delete-event', self.quit)
|
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):
|
def __init_lists(self):
|
||||||
"""
|
"""
|
||||||
@ -547,11 +554,9 @@ class ViewManager(CLIManager):
|
|||||||
new_page = 0
|
new_page = 0
|
||||||
else:
|
else:
|
||||||
new_page = current_page + 1
|
new_page = current_page + 1
|
||||||
if self.show_sidebar:
|
self.sidebar.handlers_block()
|
||||||
#cause a click signal
|
self.notebook.set_current_page(new_page)
|
||||||
self.buttons[new_page].set_active(True)
|
self.sidebar.handlers_unblock()
|
||||||
else:
|
|
||||||
self.notebook.set_current_page(new_page)
|
|
||||||
|
|
||||||
def __prev_view(self, action):
|
def __prev_view(self, action):
|
||||||
"""
|
"""
|
||||||
@ -564,19 +569,16 @@ class ViewManager(CLIManager):
|
|||||||
new_page = len(self.pages)-1
|
new_page = len(self.pages)-1
|
||||||
else:
|
else:
|
||||||
new_page = current_page - 1
|
new_page = current_page - 1
|
||||||
if self.show_sidebar:
|
self.sidebar.handlers_block()
|
||||||
#cause a click signal
|
self.notebook.set_current_page(new_page)
|
||||||
self.buttons[new_page].set_active(True)
|
self.sidebar.handlers_unblock()
|
||||||
else:
|
|
||||||
self.notebook.set_current_page(new_page)
|
|
||||||
|
|
||||||
def init_interface(self, vieworder):
|
def init_interface(self):
|
||||||
"""
|
"""
|
||||||
Initialize the interface, creating the pages as given in vieworder
|
Initialize the interface, creating the pages as given in vieworder
|
||||||
"""
|
"""
|
||||||
self.views = vieworder
|
|
||||||
self.__init_lists()
|
self.__init_lists()
|
||||||
self.__create_pages()
|
self.__load_sidebar_plugins()
|
||||||
|
|
||||||
if not self.file_loaded:
|
if not self.file_loaded:
|
||||||
self.actiongroup.set_visible(False)
|
self.actiongroup.set_visible(False)
|
||||||
@ -787,12 +789,10 @@ class ViewManager(CLIManager):
|
|||||||
"""
|
"""
|
||||||
if obj.get_active():
|
if obj.get_active():
|
||||||
self.ebox.show()
|
self.ebox.show()
|
||||||
self.notebook.set_show_tabs(False)
|
|
||||||
config.set('interface.view', True)
|
config.set('interface.view', True)
|
||||||
self.show_sidebar = True
|
self.show_sidebar = True
|
||||||
else:
|
else:
|
||||||
self.ebox.hide()
|
self.ebox.hide()
|
||||||
self.notebook.set_show_tabs(True)
|
|
||||||
config.set('interface.view', False)
|
config.set('interface.view', False)
|
||||||
self.show_sidebar = False
|
self.show_sidebar = False
|
||||||
config.save()
|
config.save()
|
||||||
@ -823,267 +823,71 @@ class ViewManager(CLIManager):
|
|||||||
config.set('interface.fullscreen', False)
|
config.set('interface.fullscreen', False)
|
||||||
config.save()
|
config.save()
|
||||||
|
|
||||||
def view_toggle(self, radioaction, current, category_page):
|
def create_page(self, pdata, page_def):
|
||||||
"""
|
try:
|
||||||
Go to the views in category_page, with in category: view_page
|
page = page_def(self.dbstate, self.uistate)
|
||||||
The view has id id_page
|
except:
|
||||||
This is the only method that can call change of views in a category
|
import traceback
|
||||||
"""
|
LOG.warn("View '%s' failed to load." % pdata.id)
|
||||||
self.__vb_handlers_block()
|
traceback.print_exc()
|
||||||
if self.notebook.get_current_page() != category_page:
|
return
|
||||||
raise Error, 'Error changing view, category is not active'
|
# Category is (string, trans):
|
||||||
cat_notebook = self.notebook_cat[category_page]
|
page.set_category(pdata.category)
|
||||||
view_page = radioaction.get_current_value()
|
page.set_ident(page.get_category() + '_' + pdata.id)
|
||||||
if self.notebook_cat[category_page].get_current_page() != view_page:
|
page_title = page.get_title()
|
||||||
self.notebook_cat[category_page].set_current_page(view_page)
|
page_category = page.get_category()
|
||||||
self.__change_view(category_page, view_page)
|
page_translated_category = page.get_translated_category()
|
||||||
self.__vb_handlers_unblock()
|
page_stock = page.get_stock()
|
||||||
|
|
||||||
def __switch_page_on_dnd(self, widget, context, xpos, ypos, time, page_no):
|
page.define_actions()
|
||||||
"""
|
try:
|
||||||
Switches the page based on drag and drop
|
page_display = page.get_display()
|
||||||
"""
|
except:
|
||||||
self.__vb_handlers_block()
|
import traceback
|
||||||
if self.notebook.get_current_page() != page_no:
|
print "ERROR: '%s' failed to create view" % pdata.name
|
||||||
self.notebook.set_current_page(page_no)
|
traceback.print_exc()
|
||||||
self.__vb_handlers_unblock()
|
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()
|
||||||
|
|
||||||
|
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):
|
def __delete_pages(self):
|
||||||
"""
|
"""
|
||||||
Calls on_delete() for each view
|
Calls on_delete() for each view
|
||||||
"""
|
"""
|
||||||
for pages in self.pages:
|
for page in self.pages:
|
||||||
for page in pages:
|
page.on_delete()
|
||||||
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<menuitem action="%s"/>' % pageid
|
|
||||||
uitoolitems += '\n<toolitem action="%s"/>' % pageid
|
|
||||||
# id, stock, button text, UI, tooltip, page
|
|
||||||
if nrpage < 9:
|
|
||||||
modifier = "<CONTROL>%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)
|
|
||||||
|
|
||||||
def __disconnect_previous_page(self):
|
def __disconnect_previous_page(self):
|
||||||
"""
|
"""
|
||||||
@ -1098,11 +902,8 @@ class ViewManager(CLIManager):
|
|||||||
for grp in groups:
|
for grp in groups:
|
||||||
if grp in self.uimanager.get_action_groups():
|
if grp in self.uimanager.get_action_groups():
|
||||||
self.uimanager.remove_action_group(grp)
|
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
|
Inserts the action groups associated with the current page
|
||||||
into the UIManager
|
into the UIManager
|
||||||
@ -1117,90 +918,12 @@ class ViewManager(CLIManager):
|
|||||||
mergeid = self.uimanager.add_ui_from_string(uidef)
|
mergeid = self.uimanager.add_ui_from_string(uidef)
|
||||||
self.merge_ids.append(mergeid)
|
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')
|
configaction = self.actiongroup.get_action('ConfigView')
|
||||||
if self.active_page.can_configure():
|
if self.active_page.can_configure():
|
||||||
configaction.set_sensitive(True)
|
configaction.set_sensitive(True)
|
||||||
else:
|
else:
|
||||||
configaction.set_sensitive(False)
|
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):
|
def import_data(self, obj):
|
||||||
"""
|
"""
|
||||||
Imports a file
|
Imports a file
|
||||||
@ -1267,7 +990,6 @@ class ViewManager(CLIManager):
|
|||||||
self.uistate.window.set_title(msg)
|
self.uistate.window.set_title(msg)
|
||||||
self.actiongroup.set_sensitive(True)
|
self.actiongroup.set_sensitive(True)
|
||||||
|
|
||||||
self.change_category(None, None)
|
|
||||||
self.actiongroup.set_visible(True)
|
self.actiongroup.set_visible(True)
|
||||||
self.readonlygroup.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
|
Makes a callback for a report/tool menu item
|
||||||
"""
|
"""
|
||||||
return lambda x: run_plugin(pdata, dbstate, uistate)
|
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
|
||||||
|
22
src/plugins/sidebar/Makefile.am
Normal file
22
src/plugins/sidebar/Makefile.am
Normal file
@ -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));
|
301
src/plugins/sidebar/categorysidebar.py
Normal file
301
src/plugins/sidebar/categorysidebar.py
Normal file
@ -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 = '''<ui>
|
||||||
|
<menubar name="MenuBar">
|
||||||
|
<menu action="ViewMenu">
|
||||||
|
<placeholder name="ViewsInCategory">%s
|
||||||
|
</placeholder>
|
||||||
|
</menu>
|
||||||
|
</menubar>
|
||||||
|
<toolbar name="ToolBar">
|
||||||
|
<placeholder name="ViewsInCategory">%s
|
||||||
|
</placeholder>
|
||||||
|
</toolbar>
|
||||||
|
</ui>
|
||||||
|
'''
|
||||||
|
|
||||||
|
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<menuitem action="%s"/>' % pageid
|
||||||
|
uitoolitems += '\n<toolitem action="%s"/>' % pageid
|
||||||
|
# id, stock, button text, UI, tooltip, page
|
||||||
|
if view_num < 9:
|
||||||
|
modifier = "<CONTROL>%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()
|
40
src/plugins/sidebar/sidebar.gpr.py
Normal file
40
src/plugins/sidebar/sidebar.gpr.py
Normal file
@ -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'
|
||||||
|
)
|
@ -10,4 +10,5 @@ register(VIEW,
|
|||||||
authors = [u"Douglas S. Blank"],
|
authors = [u"Douglas S. Blank"],
|
||||||
authors_email = ["doug.blank@gmail.com"],
|
authors_email = ["doug.blank@gmail.com"],
|
||||||
viewclass = 'FanChartView',
|
viewclass = 'FanChartView',
|
||||||
|
stock_icon = 'gramps-fanchart',
|
||||||
)
|
)
|
||||||
|
@ -10,4 +10,5 @@ register(VIEW,
|
|||||||
authors_email = [""],
|
authors_email = [""],
|
||||||
category = ("Places", _("Places")),
|
category = ("Places", _("Places")),
|
||||||
viewclass = 'PlaceTreeView',
|
viewclass = 'PlaceTreeView',
|
||||||
|
stock_icon = 'gramps-tree-group',
|
||||||
)
|
)
|
||||||
|
@ -130,6 +130,7 @@ authors_email = ["http://gramps-project.org"],
|
|||||||
category = ("Ancestry", _("Ancestry")),
|
category = ("Ancestry", _("Ancestry")),
|
||||||
viewclass = 'PedigreeView',
|
viewclass = 'PedigreeView',
|
||||||
order = START,
|
order = START,
|
||||||
|
stock_icon = 'gramps-pedigree',
|
||||||
)
|
)
|
||||||
|
|
||||||
register(VIEW,
|
register(VIEW,
|
||||||
@ -145,6 +146,7 @@ authors_email = ["http://gramps-project.org"],
|
|||||||
category = ("People", _("People")),
|
category = ("People", _("People")),
|
||||||
viewclass = 'PersonTreeView',
|
viewclass = 'PersonTreeView',
|
||||||
order = START,
|
order = START,
|
||||||
|
stock_icon = 'gramps-tree-group',
|
||||||
)
|
)
|
||||||
|
|
||||||
register(VIEW,
|
register(VIEW,
|
||||||
@ -161,7 +163,9 @@ authors_email = ["http://gramps-project.org"],
|
|||||||
category = ("People", _("People")),
|
category = ("People", _("People")),
|
||||||
viewclass = 'PersonListView',
|
viewclass = 'PersonListView',
|
||||||
order = START,
|
order = START,
|
||||||
|
stock_icon = 'gramps-tree-list',
|
||||||
)
|
)
|
||||||
|
|
||||||
register(VIEW,
|
register(VIEW,
|
||||||
id = 'placelistview',
|
id = 'placelistview',
|
||||||
name = _("Place View"),
|
name = _("Place View"),
|
||||||
@ -175,6 +179,7 @@ authors_email = ["http://gramps-project.org"],
|
|||||||
category = ("Places", _("Places")),
|
category = ("Places", _("Places")),
|
||||||
viewclass = 'PlaceListView',
|
viewclass = 'PlaceListView',
|
||||||
order = START,
|
order = START,
|
||||||
|
stock_icon = 'gramps-tree-list',
|
||||||
)
|
)
|
||||||
|
|
||||||
register(VIEW,
|
register(VIEW,
|
||||||
|
Reference in New Issue
Block a user