Introduce workspaces with a shared filter/gramplet sidebar

svn: r16160
This commit is contained in:
Nick Hall 2010-11-08 15:50:51 +00:00
parent 69d9528be0
commit 56e7869137
26 changed files with 590 additions and 273 deletions

View File

@ -516,7 +516,7 @@ class DisplayState(gen.utils.Callback):
def show_filter_results(self, dbstate, matched, total):
#nav_type = self.viewmanager.active_page.navigation_type()
#text = ((_("%(nav_type)s View") % {"nav_type": _(nav_type)}) +
text = (self.viewmanager.active_page.title +
text = (self.viewmanager.active_page.get_title() +
(": %d/%d" % (matched, total)))
self.status.pop(1, self.last_bar)
self.status.push(1, text, self.last_bar)

View File

@ -65,20 +65,6 @@ class SidebarFilter(DbGUIElement):
self._tag_rebuild()
def _init_interface(self):
self.table.attach(widgets.MarkupLabel(_('<b>Filter</b>')),
0, 2, 0, 1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=0)
btn = gtk.Button()
img = gtk.image_new_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
box = gtk.HBox()
btn.set_image(img)
btn.set_relief(gtk.RELIEF_NONE)
btn.set_alignment(1.0, 0.5)
box.pack_start(gtk.Label(''), expand=True, fill=True)
box.pack_end(btn, fill=False, expand=False)
box.show_all()
self.table.attach(box, 2, 4, 0, 1, yoptions=0)
btn.connect('clicked', self.btn_clicked)
self.create_widget()
self.apply_btn.connect('clicked', self.clicked)
@ -105,10 +91,6 @@ class SidebarFilter(DbGUIElement):
self.table.attach(hbox, 2, 4, self.position, self.position+1,
xoptions=gtk.FILL, yoptions=0)
def btn_clicked(self, obj):
config.set('interface.filter', False)
config.save()
def get_widget(self):
return self.table

View File

@ -48,6 +48,7 @@ class SearchBar(object):
self.dbstate = dbstate
self.uistate = uistate
self.apply_text = ''
self.visible = False
self.filterbar = gtk.HBox()
self.filter_text = gtk.Entry()
@ -167,6 +168,11 @@ class SearchBar(object):
def show(self):
self.filterbar.show()
self.visible = True
def hide(self):
self.filterbar.hide()
self.visible = False
def is_visible(self):
return self.visible

171
src/gui/navigator.py Normal file
View File

@ -0,0 +1,171 @@
#
# 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
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from gen.plug import (START, END)
#-------------------------------------------------------------------------
#
# Navigator class
#
#-------------------------------------------------------------------------
class Navigator(object):
"""
A class which defines the graphical representation of the Gramps navigator.
"""
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('')
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_end(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, order):
"""
Add a page to the sidebar for a plugin.
"""
self.pages.append((title, sidebar))
index = self.notebook.append_page(sidebar.get_top(), gtk.Label(title))
menu_item = gtk.MenuItem(title)
if order == START:
self.menu.prepend(menu_item)
self.notebook.set_current_page(index)
else:
self.menu.append(menu_item)
menu_item.connect('activate', self.cb_menu_activate, index)
menu_item.show()
def view_changed(self, cat_num, view_num):
"""
Called when a Gramps view is changed.
"""
for page in self.pages:
page[1].view_changed(cat_num, view_num)
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.
"""
pass
#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/Navigator').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)

View File

@ -19,10 +19,13 @@
#
# $Id$
"""
A module that provides pluggable sidebars. These provide an interface to
manage pages in the main Gramps window.
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
#-------------------------------------------------------------------------
#
# GNOME modules
@ -35,7 +38,7 @@ import gtk
# Gramps modules
#
#-------------------------------------------------------------------------
from gen.plug import (START, END)
import config
#-------------------------------------------------------------------------
#
@ -46,9 +49,9 @@ class Sidebar(object):
"""
A class which defines the graphical representation of the Gramps sidebar.
"""
def __init__(self, viewmanager):
def __init__(self, callback):
self.viewmanager = viewmanager
self.callback = callback
self.pages = []
self.top = gtk.VBox()
@ -59,7 +62,7 @@ class Sidebar(object):
select_button = gtk.ToggleButton()
select_button.set_relief(gtk.RELIEF_NONE)
select_hbox = gtk.HBox()
self.title_label = gtk.Label('')
self.title_label = gtk.Label()
arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_NONE)
select_hbox.pack_start(self.title_label, False)
select_hbox.pack_end(arrow, False)
@ -71,51 +74,66 @@ class Sidebar(object):
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)
close_button.connect('clicked', self.__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.menu.connect('deactivate', self.__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.notebook.connect('switch_page', self.__switch_page)
self.top.pack_start(self.notebook, True)
self.top.show_all()
def get_top(self):
def get_display(self):
"""
Return the top container widget for the GUI.
"""
return self.top
def get_page_type(self):
"""
Return the type of the active page.
"""
return self.pages[self.notebook.get_current_page()][1]
def add(self, title, sidebar, order):
def add(self, title, container, page_type):
"""
Add a page to the sidebar for a plugin.
Add a page to the sidebar.
"""
self.pages.append((title, sidebar))
index = self.notebook.append_page(sidebar.get_top(), gtk.Label(title))
menu_item = gtk.MenuItem(title)
if order == START:
self.menu.prepend(menu_item)
self.notebook.set_current_page(index)
else:
self.menu.append(menu_item)
menu_item.connect('activate', self.cb_menu_activate, index)
self.pages.append([title, page_type, menu_item])
index = self.notebook.append_page(container, gtk.Label(title))
menu_item.connect('activate', self.__menu_activate, index)
menu_item.show()
self.menu.append(menu_item)
self.notebook.set_current_page(index)
def view_changed(self, cat_num, view_num):
def remove(self, page_type):
"""
Called when a Gramps view is changed.
Replace a page in the sidebar.
"""
for page in self.pages:
page[1].view_changed(cat_num, view_num)
position = self.__get_page(page_type)
if position is not None:
self.notebook.remove_page(position)
self.menu.remove(self.pages[position][2])
self.pages = self.pages[:position] + self.pages[position+1:]
def __get_page(self, page_type):
"""
Return the page number of the page with the given type.
"""
for page_num, page in enumerate(self.pages):
if page[1] == page_type:
return page_num
return None
def __menu_button_pressed(self, button, event):
"""
@ -125,46 +143,43 @@ class Sidebar(object):
button.grab_focus()
button.set_active(True)
self.menu.popup(None, None, cb_menu_position, event.button,
self.menu.popup(None, None, self.__menu_position, event.button,
event.time, button)
def cb_menu_activate(self, menu, index):
def __menu_position(self, menu, button):
"""
Determine the position of the popup menu.
"""
x, y = button.window.get_origin()
x += button.allocation.x
y += button.allocation.y + button.allocation.height
return (x, y, False)
def __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):
def __menu_deactivate(self, menu, button):
"""
Called when the user has switched to a new sidebar plugin page.
Called when the popup menu disappears.
"""
button.set_active(False)
def __switch_page(self, notebook, unused, index):
"""
Called when the user has switched to a new sidebar page.
"""
if self.pages:
self.title_label.set_text(self.pages[index][0])
self.title_label.set_markup('<b>%s</b>' % self.pages[index][0])
active = self.top.get_property('visible')
self.callback(self.pages[index][1], active)
def cb_close_clicked(self, button):
def __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)
config.set('interface.filter', False)
config.save()

View File

@ -89,7 +89,8 @@ 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
from workspace import Workspace
from gui.navigator import Navigator
from gui.views.tags import Tags
from gen.utils.configmanager import safe_eval
@ -130,9 +131,9 @@ UIDEFAULT = '''<ui>
</menu>
<menu action="ViewMenu">
<menuitem action="ConfigView"/>
<menuitem action="Sidebar"/>
<menuitem action="Navigator"/>
<menuitem action="Toolbar"/>
<menuitem action="Filter"/>
<menuitem action="Sidebar"/>
<menuitem action="Fullscreen"/>
<separator/>
<placeholder name="ViewsInCategory"/>
@ -278,9 +279,9 @@ class ViewManager(CLIManager):
self.views = None
self.current_views = [] # The current view in each category
self.show_sidebar = config.get('interface.view')
self.show_navigator = config.get('interface.view')
self.show_toolbar = config.get('interface.toolbar-on')
self.show_filter = config.get('interface.filter')
self.show_sidebar = config.get('interface.filter')
self.fullscreen = config.get('interface.fullscreen')
self.__build_main_window()
@ -515,8 +516,8 @@ class ViewManager(CLIManager):
hpane = gtk.HPaned()
self.ebox = gtk.EventBox()
self.sidebar = Sidebar(self)
self.ebox.add(self.sidebar.get_top())
self.navigator = Navigator(self)
self.ebox.add(self.navigator.get_top())
hpane.add1(self.ebox)
hpane.show_all()
@ -547,8 +548,8 @@ class ViewManager(CLIManager):
self.tags = Tags(self.uistate, self.dbstate)
self.filter_menu = self.uimanager.get_widget(
'/MenuBar/ViewMenu/Filter/')
self.sidebar_menu = self.uimanager.get_widget(
'/MenuBar/ViewMenu/Sidebar/')
# handle OPEN button, insert it into the toolbar. Unfortunately,
# UIManager has no built in support for and Open Recent button
@ -563,7 +564,7 @@ class ViewManager(CLIManager):
self.db_loader = DbLoader(self.dbstate, self.uistate)
self.__setup_sidebar()
self.__setup_navigator()
if self.show_toolbar:
self.toolbar.show()
@ -591,7 +592,7 @@ class ViewManager(CLIManager):
sidebar_class = getattr(module, pdata.sidebarclass)
sidebar_page = sidebar_class(self.dbstate, self.uistate)
self.sidebar.add(pdata.menu_label, sidebar_page, pdata.order)
self.navigator.add(pdata.menu_label, sidebar_page, pdata.order)
def __setup_statusbar(self):
"""
@ -615,12 +616,12 @@ class ViewManager(CLIManager):
hbox2.show()
return hbox2
def __setup_sidebar(self):
def __setup_navigator(self):
"""
If we have enabled te sidebar, show it, and turn off the tabs. If
disabled, hide the sidebar and turn on the tabs.
"""
if self.show_sidebar:
if self.show_navigator:
self.ebox.show()
else:
self.ebox.hide()
@ -733,12 +734,12 @@ class ViewManager(CLIManager):
]
self._file_toggle_action_list = [
('Sidebar', None, _('_Sidebar'), None, None, self.sidebar_toggle,
self.show_sidebar ),
('Navigator', None, _('_Navigator'), None, None,
self.navigator_toggle, self.show_navigator ),
('Toolbar', None, _('_Toolbar'), None, None, self.toolbar_toggle,
self.show_toolbar ),
('Filter', None, _('_Filter Sidebar'), None, None,
filter_toggle, self.show_filter),
('Sidebar', None, _('_Sidebar'), None, None,
sidebar_toggle, self.show_sidebar),
('Fullscreen', None, _('F_ull Screen'), "F11", None,
self.fullscreen_toggle, self.fullscreen),
]
@ -814,10 +815,8 @@ class ViewManager(CLIManager):
self.__rebuild_report_and_tool_menus)
self.fileactions.set_sensitive(True)
self.uistate.widget.set_sensitive(True)
config.connect("interface.statusbar",
self.__statusbar_key_update)
config.connect("interface.filter",
self.__filter_signal)
config.connect("interface.statusbar", self.__statusbar_key_update)
config.connect("interface.filter", self.__sidebar_signal)
def __statusbar_key_update(self, client, cnxn_id, entry, data):
"""
@ -825,12 +824,12 @@ class ViewManager(CLIManager):
"""
self.uistate.modify_statusbar(self.dbstate)
def __filter_signal(self, client, cnxn_id, entry, data):
def __sidebar_signal(self, client, cnxn_id, entry, data):
"""
Callback function for statusbar key update
Callback function for sidebar key update
"""
if self.filter_menu.get_active() != config.get('interface.filter'):
self.filter_menu.set_active(config.get('interface.filter'))
if self.sidebar_menu.get_active() != config.get('interface.filter'):
self.sidebar_menu.set_active(config.get('interface.filter'))
def post_init_interface(self, show_manager=True):
"""
@ -995,7 +994,7 @@ class ViewManager(CLIManager):
except Errors.WindowActiveError:
pass
def sidebar_toggle(self, obj):
def navigator_toggle(self, obj):
"""
Set the sidebar based on the value of the toggle button. Save the
results in the configuration settings
@ -1003,11 +1002,11 @@ class ViewManager(CLIManager):
if obj.get_active():
self.ebox.show()
config.set('interface.view', True)
self.show_sidebar = True
self.show_navigator = True
else:
self.ebox.hide()
config.set('interface.view', False)
self.show_sidebar = False
self.show_navigator = False
config.save()
def toolbar_toggle(self, obj):
@ -1084,8 +1083,9 @@ class ViewManager(CLIManager):
"""
Create a new page and set it as the current page.
"""
wspace = Workspace(self.uistate, self.dbstate)
try:
page = page_def(self.dbstate, self.uistate)
page = page_def(self.dbstate, self.uistate, wspace)
except:
import traceback
LOG.warn("View '%s' failed to load." % pdata.id)
@ -1109,7 +1109,9 @@ class ViewManager(CLIManager):
return
page_display.show_all()
page.post()
self.pages.append(page)
wspace.add_view(page)
self.pages.append(wspace)
# create icon/label for workspace notebook
hbox = gtk.HBox()
@ -1118,8 +1120,7 @@ class ViewManager(CLIManager):
hbox.pack_start(image, False)
hbox.add(gtk.Label(pdata.name))
hbox.show_all()
page_num = self.notebook.append_page(page_display,
hbox)
page_num = self.notebook.append_page(wspace.get_display(), hbox)
def view_changed(self, notebook, page, page_num):
"""
@ -1142,7 +1143,7 @@ class ViewManager(CLIManager):
config.set('preferences.last-views', last_views)
config.save()
self.sidebar.view_changed(cat_num, view_num)
self.navigator.view_changed(cat_num, view_num)
self.__change_page(page_num)
def __change_page(self, page_num):
@ -1663,7 +1664,7 @@ def display_about_box(obj):
about.run()
about.destroy()
def filter_toggle(obj):
def sidebar_toggle(obj):
"""
Save the filter state to the config settings on change
"""

View File

@ -175,11 +175,7 @@ class ListView(NavigationView):
self.selection.connect('changed', self.row_changed)
self.setup_filter()
if self.filter_class:
return self.build_filter_container(self.vbox, self.filter_class)
else:
return self.vbox
return self.vbox
def define_actions(self):
"""
@ -252,7 +248,7 @@ class ListView(NavigationView):
def build_tree(self, force_sidebar=False):
if self.active:
cput0 = time.clock()
if config.get('interface.filter') or force_sidebar:
if not self.search_bar.is_visible():
filter_info = (True, self.generic_filter, False)
else:
value = self.search_bar.get_value()
@ -308,50 +304,11 @@ class ListView(NavigationView):
"""
return ()
####################################################################
# Filter
####################################################################
def build_filter_container(self, box, filter_class):
self.filter_sidebar = filter_class(self.dbstate, self.uistate,
self.filter_clicked)
self.filter_pane = self.filter_sidebar.get_widget()
hpaned = gtk.HBox()
hpaned.pack_start(self.vbox, True, True)
hpaned.pack_end(self.filter_pane, False, False)
self.filter_toggle(None, None, None, None)
return hpaned
def filter_toggle(self, client, cnxn_id, entry, data):
"""
Callback on change interface.filter, inheriting methods connect to
change in ini file
"""
if config.get('interface.filter'):
self.search_bar.hide()
self.filter_pane.show()
else:
self.search_bar.show()
self.filter_pane.hide()
def post(self):
if self.filter_class:
if config.get('interface.filter'):
self.search_bar.hide()
self.filter_pane.show()
else:
self.search_bar.show()
self.filter_pane.hide()
def get_viewtype_stock(self):
"""Type of view in category, default listview is a flat list
"""
return 'gramps-tree-list'
def filter_clicked(self):
self.generic_filter = self.filter_sidebar.get_filter()
self.build_tree()
def filter_editor(self, obj):
try:
FilterEditor(self.FILTER_TYPE , const.CUSTOM_FILTERS,
@ -588,7 +545,7 @@ class ListView(NavigationView):
self.sort_order = order
handle = self.first_selected()
if config.get('interface.filter'):
if not self.search_bar.is_visible():
filter_info = (True, self.generic_filter, False)
else:
value = self.search_bar.get_value()

274
src/gui/workspace.py Normal file
View File

@ -0,0 +1,274 @@
#
# 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$
"""
Workspace
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
#-------------------------------------------------------------------------
#
# GNOME modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from gui.sidebar import Sidebar
from gui.widgets.grampletpane import GrampletPane
from gui.views.listview import ListView
import config
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
GRAMPLET_PAGE = 0
FILTER_PAGE = 1
#-------------------------------------------------------------------------
#
# Workspace class
#
#-------------------------------------------------------------------------
class Workspace(object):
"""
A Workspace contains panes to contain a view and associated objects such as
a filter and gramplet pane.
"""
def __init__(self, uistate, dbstate):
self.uistate = uistate
self.dbstate = dbstate
self.active = False
self.view = None
self.sidebar = Sidebar(self.sidebar_changed)
self.hpane = gtk.HPaned()
self.vpane = gtk.VPaned()
self.gramplet_pane = self.__create_gramplet_pane()
self.gramplet_pane.show_all()
self.hpane.pack1(self.vpane, resize=True, shrink=True)
self.hpane.pack2(self.sidebar.get_display(), resize=False, shrink=False)
self.hpane.show()
self.vpane.show()
if config.get('interface.filter'):
self.sidebar.get_display().show()
else:
self.sidebar.get_display().hide()
self.define_actions()
def get_display(self):
"""
Return the top container widget for the GUI.
"""
return self.hpane
def add_view(self, view):
"""
Add a view to the workspace.
"""
self.view = view
self.vpane.add1(view.get_display())
if isinstance(view, ListView):
self.add_filter(view.filter_class)
def add_aux(self, aux):
"""
Add an auxilliary object to the workspace.
"""
self.aux = aux
self.vpane.add2(aux.get_display())
def add_filter(self, filter_class):
"""
Add a filter to the workspace sidebar.
"""
self.filter_sidebar = filter_class(self.dbstate, self.uistate,
self.__filter_clicked)
top = self.filter_sidebar.get_widget()
top.show_all()
self.sidebar.add(_('Filter'), top, FILTER_PAGE)
def remove_filter(self,):
"""
Remove the filter from the workspace sidebar.
"""
self.filter_sidebar = None
self.sidebar.remove(FILTER_PAGE)
def __create_gramplet_pane(self):
"""
Create a gramplet pane.
"""
self.uidef = '''<ui>
<popup name="Popup">
<menuitem action="AddGramplet"/>
<menuitem action="RestoreGramplet"/>
</popup>
</ui>'''
eb = gtk.EventBox()
eb.connect('button-press-event', self._gramplet_button_press)
gramplet_pane = GrampletPane("grampletsidebar",
self, self.dbstate, self.uistate,
column_count=1)
eb.add(gramplet_pane)
eb.show()
self.sidebar.add(_('Gramplets'), eb, GRAMPLET_PAGE)
return gramplet_pane
def _gramplet_button_press(self, obj, event):
"""
Called to display the context menu in the gramplet pane.
"""
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
menu = self.uistate.uimanager.get_widget('/Popup')
if menu:
menu.popup(None, None, None, event.button, event.time)
return True
def __filter_clicked(self):
"""
Called when the filter 'Find' button is clicked.
"""
self.view.generic_filter = self.filter_sidebar.get_filter()
self.view.build_tree()
def __sidebar_toggled(self, action):
"""
Called when the sidebar is toggled.
"""
active = action.get_active()
if active:
self.sidebar.get_display().show()
self.sidebar_changed(self.sidebar.get_page_type(), True)
else:
self.sidebar.get_display().hide()
self.sidebar_changed(None, False)
config.set('interface.filter', active)
config.save()
def sidebar_changed(self, page_type, active):
"""
Called when the sidebar page is changed.
"""
if isinstance(self.view, ListView):
if active and page_type == FILTER_PAGE:
self.view.search_bar.hide()
else:
self.view.search_bar.show()
def get_title(self):
"""
Return the title of the view.
"""
if self.view:
return self.view.title
return ''
def define_actions(self):
"""
Defines the UIManager actions.
"""
self.action_group = gtk.ActionGroup('Workspace')
self.action_group.add_toggle_actions([
('Sidebar', None, _('_Sidebar'),
None, None, self.__sidebar_toggled, config.get('interface.filter'))
])
self.action_group.add_actions([
("AddGramplet", None, _("Add a gramplet")),
("RestoreGramplet", None, _("Restore a gramplet")
)])
def set_active(self):
"""
Called when the view is set as active.
"""
self.active = True
self.view.set_active()
self.gramplet_pane.set_active()
def set_inactive(self):
"""
Called when the view is set as inactive.
"""
self.active = False
self.view.set_inactive()
self.gramplet_pane.set_inactive()
def get_actions(self):
"""
Return the actions that should be used for the view.
"""
action_list = self.view.get_actions()
action_list.append(self.action_group)
return action_list
def ui_definition(self):
"""
Returns the XML UI definition for the UIManager.
"""
return self.view.ui_definition()
def additional_ui_definitions(self):
"""
Return any additional interfaces for the UIManager that the view
needs to define.
"""
defs = self.view.additional_ui_definitions()
defs.append(self.uidef)
return defs
def change_page(self):
"""
Called when the view changes.
"""
self.view.change_page()
def on_delete(self):
"""
Method called on shutdown.
"""
self.view.on_delete()
self.gramplet_pane.on_delete()
def can_configure(self):
"""
Returns True if the view has a configure window.
"""
return self.view.can_configure()
def configure(self):
"""
Open the configure dialog for the view.
"""
self.view.configure()

View File

@ -141,7 +141,6 @@ class BasePersonView(ListView):
'<CONTROL>BackSpace' : self.key_delete,
})
config.connect("interface.filter", self.filter_toggle)
uistate.connect('nameformat-changed', self.build_tree)
def navigation_type(self):

View File

@ -147,9 +147,6 @@ class PlaceBaseView(ListView):
'<CONTROL>BackSpace' : self.key_delete,
})
config.connect("interface.filter",
self.filter_toggle)
def navigation_type(self):
return 'Place'

View File

@ -100,7 +100,7 @@ class EventView(ListView):
FILTER_TYPE = "Event"
QR_CATEGORY = CATEGORY_QR_EVENT
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
"""
Create the Event View
"""
@ -126,7 +126,6 @@ class EventView(ListView):
'<CONTROL>BackSpace' : self.key_delete,
})
config.connect("interface.filter", self.filter_toggle)
uistate.connect('nameformat-changed', self.build_tree)
def navigation_type(self):

View File

@ -97,7 +97,7 @@ class FamilyView(ListView):
FILTER_TYPE = "Family"
QR_CATEGORY = CATEGORY_QR_FAMILY
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
signal_map = {
'family-add' : self.row_add,
@ -121,7 +121,6 @@ class FamilyView(ListView):
'<CONTROL>BackSpace' : self.key_delete,
})
config.connect("interface.filter", self.filter_toggle)
uistate.connect('nameformat-changed', self.build_tree)
def navigation_type(self):

View File

@ -566,7 +566,7 @@ class FanChartView(NavigationView):
"""
The Gramplet code that realizes the FanChartWidget.
"""
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
NavigationView.__init__(self, _('Fan Chart'),
dbstate, uistate,
dbstate.db.get_bookmarks(),

View File

@ -158,7 +158,6 @@ _UI_DEF = '''\
<separator/>
<menuitem action="AddPlaceMenu"/>
<menuitem action="LinkPlaceMenu"/>
<menuitem action="FilterEdit"/>
</menu>
</menubar>
<toolbar name="ToolBar">
@ -344,8 +343,9 @@ class GeoView(HtmlView):
('preferences.webkit', True),
)
def __init__(self, dbstate, uistate):
HtmlView.__init__(self, dbstate, uistate, title=_("GeoView"))
def __init__(self, dbstate, uistate, wspace):
HtmlView.__init__(self, dbstate, uistate, wspace, title=_("GeoView"))
self.wspace = wspace
self.dbstate = dbstate
self.uistate = uistate
self.dbstate.connect('database-changed', self._new_database)
@ -704,9 +704,9 @@ class GeoView(HtmlView):
self.box1.pack_start(self.title, False, False, padding=2)
self.box1.show_all()
if self.displaytype == "places":
self.build_filters_container(self.filter, PlaceSidebarFilter)
self.wspace.add_filter(PlaceSidebarFilter)
elif self.displaytype == "event":
self.build_filters_container(self.filter, EventSidebarFilter)
self.wspace.add_filter(EventSidebarFilter)
return self.box1
def _entry_key_event(self, widget, event):
@ -1235,9 +1235,6 @@ class GeoView(HtmlView):
self._add_action('EventMapsMenu', 'geo-show-event', _('_Event'),
callback=self._event_places,
tip=_("Attempt to view places connected to all events."))
self._add_toggle_action('FilterEdit', None, _('_Filter Sidebar'),
callback=self.filter_toggle_action)
config.connect('interface.filter', self.filter_toggle)
####################################################################
# BOOKMARKS
@ -1481,7 +1478,6 @@ class GeoView(HtmlView):
self._savezoomandposition(500) # every 500 millisecondes
self.endinit = True
self.uistate.clear_filter_results()
self.filter_toggle(None, None, None, None)
self._set_provider_icon()
self._geo_places()
@ -1491,7 +1487,6 @@ class GeoView(HtmlView):
"""
if not self.uistate.get_active('Person'):
return
self.filter_toggle(None, None, None, None)
self._geo_places()
def _all_places(self, hanle=None): # pylint: disable-msg=W0613
@ -1499,7 +1494,8 @@ class GeoView(HtmlView):
Specifies the place for the home person to display with mapstraction.
"""
self.displaytype = "places"
self.build_filters_container(self.filter, PlaceSidebarFilter)
self.wspace.remove_filter()
self.wspace.add_filter(PlaceSidebarFilter)
self._geo_places()
def _person_places(self, handle=None): # pylint: disable-msg=W0613
@ -1507,7 +1503,7 @@ class GeoView(HtmlView):
Specifies the person places.
"""
self.displaytype = "person"
self.no_filter()
self.wspace.remove_filter()
if not self.uistate.get_active('Person'):
return
self._geo_places()
@ -1517,7 +1513,7 @@ class GeoView(HtmlView):
Specifies the family places to display with mapstraction.
"""
self.displaytype = "family"
self.no_filter()
self.wspace.remove_filter()
if not self.uistate.get_active('Person'):
return
self._geo_places()
@ -1527,7 +1523,8 @@ class GeoView(HtmlView):
Specifies all event places to display with mapstraction.
"""
self.displaytype = "event"
self.build_filters_container(self.filter, EventSidebarFilter)
self.wspace.remove_filter()
self.wspace.add_filter(EventSidebarFilter)
self._geo_places()
def _new_database(self, database):
@ -2576,74 +2573,6 @@ class GeoView(HtmlView):
except Errors.WindowActiveError: # pylint: disable-msg=W0704
pass # pylint: disable-msg=W0702
####################################################################
# Filters
####################################################################
def build_filters_container(self, box, filter_class):
"""
Used to create the filters on Geoview.
Depending on the events view or places, view we must generate the
good filter.
We need to remove the old filter if it exists then add the new one.
"""
try:
self.vbox.destroy()
except: # pylint: disable-msg=W0704
pass # pylint: disable-msg=W0702
map(self.hpaned.remove, self.hpaned.get_children())
self.vbox = gtk.VBox()
self.hpaned.pack_start(self.vbox, True, True)
self.filter_sidebar = filter_class(self.dbstate, self.uistate,
self.filter_clicked)
self.filter_pane = self.filter_sidebar.get_widget()
self.hpaned.pack_end(self.filter_pane, False, False)
box.show_all()
self.filter_toggle(None, None, None, None)
def no_filter(self):
"""
We don't need a filter for the current view.
"""
try:
self.filter_pane.hide()
except: # pylint: disable-msg=W0704
pass # pylint: disable-msg=W0702
def filter_toggle(self, client, cnxn_id, entry, data):
# pylint: disable-msg=W0613
"""
We must show or hide the filter depending on the filter toggle button.
"""
if not self.endinit:
return
if self.displaytype == "places" or self.displaytype == "event":
if config.get('interface.filter'):
self.filter.show()
else:
self.filter.hide()
def filter_toggle_action(self, obj):
"""
Depending on the filter toggle button action, we must show or hile
the filter then save the state in the config file.
"""
if self.displaytype == "places" or self.displaytype == "event":
if obj.get_active():
self.filter.show()
active = True
else:
self.filter.hide()
active = False
config.set('interface.filter', active)
def filter_clicked(self):
"""
We have clicked on the Find button into the filter box.
"""
self.generic_filter = self.filter_sidebar.get_filter()
self.build_tree()
def build_tree(self):
"""
Builds the new view depending on the filter.

View File

@ -45,7 +45,7 @@ class GrampletView(PageView):
GrampletView interface
"""
def __init__(self, dbstate, uistate):
def __init__(self, dbstate, uistate, wspace):
"""
Create a GrampletView, with the current dbstate and uistate
"""

View File

@ -441,7 +441,7 @@ class HtmlView(PageView):
with an embedded webbrowser showing a given URL
"""
def __init__(self, dbstate, uistate, title=_('HtmlView')):
def __init__(self, dbstate, uistate, wspace, title=_('HtmlView')):
PageView.__init__(self, title, dbstate, uistate)
self.dbstate = dbstate
self.back_action = None

View File

@ -113,7 +113,7 @@ class MediaView(ListView):
_DND_TYPE = DdTargets.URI_LIST
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
signal_map = {
'media-add' : self.row_add,
@ -137,9 +137,6 @@ class MediaView(ListView):
'<CONTROL>BackSpace' : self.key_delete,
})
config.connect("interface.filter",
self.filter_toggle)
def navigation_type(self):
return 'Media'

View File

@ -92,7 +92,7 @@ class NoteView(ListView):
FILTER_TYPE = "Note"
QR_CATEGORY = CATEGORY_QR_NOTE
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
signal_map = {
'note-add' : self.row_add,
@ -115,9 +115,6 @@ class NoteView(ListView):
'<CONTROL>BackSpace' : self.key_delete,
})
config.connect("interface.filter",
self.filter_toggle)
def navigation_type(self):
return 'Note'

View File

@ -667,7 +667,7 @@ class PedigreeView(NavigationView):
('interface.pedview-show-unknown-people', True),
)
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
NavigationView.__init__(self, _('Pedigree'), dbstate, uistate,
dbstate.db.get_bookmarks(),
Bookmarks.PersonBookmarks,

View File

@ -53,7 +53,7 @@ class PersonListView(BasePersonView):
"""
A hierarchical view of the top three levels of places.
"""
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
BasePersonView.__init__(self, dbstate, uistate,
_('Person View'), PersonListModel,
nav_group=nav_group)

View File

@ -55,7 +55,7 @@ class PersonTreeView(BasePersonView):
"""
A hierarchical view of the top three levels of places.
"""
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
BasePersonView.__init__(self, dbstate, uistate,
_('People Tree View'), PersonTreeModel,
nav_group=nav_group)

View File

@ -47,7 +47,7 @@ class PlaceListView(PlaceBaseView):
"""
Flat place view. (Original code in PlaceBaseView).
"""
def __init__(self, dbstate, uistate):
def __init__(self, dbstate, uistate, wspace):
PlaceBaseView.__init__(self, dbstate, uistate,
_('Place View'), PlaceListModel,
nav_group=0)

View File

@ -93,7 +93,7 @@ class PlaceTreeView(PlaceBaseView):
100, 150, 150, 100, 150])
)
def __init__(self, dbstate, uistate):
def __init__(self, dbstate, uistate, wspace):
PlaceBaseView.__init__(self, dbstate, uistate,
_('Place Tree View'), PlaceTreeModel,
nav_group=0, markup=PlaceBaseView.MARKUP_COLS)

View File

@ -129,7 +129,7 @@ class RelationshipView(NavigationView):
('preferences.releditbtn', True),
)
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
NavigationView.__init__(self, _('Relationships'),
dbstate, uistate,
dbstate.db.get_bookmarks(),

View File

@ -109,7 +109,7 @@ class RepositoryView(ListView):
FILTER_TYPE = "Repository"
QR_CATEGORY = CATEGORY_QR_REPOSITORY
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
signal_map = {
'repository-add' : self.row_add,
@ -132,9 +132,6 @@ class RepositoryView(ListView):
'<CONTROL>BackSpace' : self.key_delete,
})
config.connect("interface.filter",
self.filter_toggle)
def navigation_type(self):
return 'Repository'

View File

@ -93,7 +93,7 @@ class SourceView(ListView):
FILTER_TYPE = "Source"
QR_CATEGORY = CATEGORY_QR_SOURCE
def __init__(self, dbstate, uistate, nav_group=0):
def __init__(self, dbstate, uistate, wspace, nav_group=0):
signal_map = {
'source-add' : self.row_add,
@ -116,9 +116,6 @@ class SourceView(ListView):
'<CONTROL>BackSpace' : self.key_delete,
})
config.connect("interface.filter",
self.filter_toggle)
def navigation_type(self):
return 'Source'