Add extra GrampsBar functionality.

svn: r16502
This commit is contained in:
Nick Hall
2011-01-30 03:02:38 +00:00
parent 9b24451db1
commit 116d26e69f
19 changed files with 881 additions and 554 deletions

View File

@ -172,7 +172,7 @@ class Gramplet(object):
""" """
Sets the tooltip for this gramplet. Sets the tooltip for this gramplet.
""" """
self.gui.tooltip = tip self.gui.set_tooltip(tip)
def get_text(self): def get_text(self):
""" """
@ -229,8 +229,6 @@ class Gramplet(object):
Set the textview to wrap or not. Set the textview to wrap or not.
""" """
import gtk import gtk
self.gui.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
# gtk.WRAP_NONE, gtk.WRAP_CHAR, gtk.WRAP_WORD or gtk.WRAP_WORD_CHAR. # gtk.WRAP_NONE, gtk.WRAP_CHAR, gtk.WRAP_WORD or gtk.WRAP_WORD_CHAR.
if value in [True, 1]: if value in [True, 1]:
self.gui.textview.set_wrap_mode(gtk.WRAP_WORD) self.gui.textview.set_wrap_mode(gtk.WRAP_WORD)
@ -275,7 +273,7 @@ class Gramplet(object):
""" """
import gobject import gobject
if ((not self.active or if ((not self.active or
self.gui.state in ["closed", "minimized"] or self.gui.gstate in ["closed", "minimized"] or
not self.dbstate.open) and not self.dbstate.open) and
not self.gui.force_update): not self.gui.force_update):
self.dirty = True self.dirty = True

View File

@ -1,7 +1,8 @@
# #
# Gramps - a GTK+/GNOME based genealogy program # Gramps - a GTK+/GNOME based genealogy program
# #
# Copyright (C) 2011 Nick Hall # Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2011 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
@ -19,12 +20,17 @@
# #
# $Id$ # $Id$
"""
Module that implements the sidebar and bottombar fuctionality.
"""
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Python modules # Python modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from gen.ggettext import gettext as _ from gen.ggettext import gettext as _
import time
import os
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -32,8 +38,15 @@ from gen.ggettext import gettext as _
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import gtk import gtk
import time gtk.rc_parse_string("""
import os style "tab-button-style" {
GtkWidget::focus-padding = 0
GtkWidget::focus-line-width = 0
xthickness = 0
ythickness = 0
}
widget "*.tab-button" style "tab-button-style"
""")
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -42,20 +55,23 @@ import os
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import ConfigParser import ConfigParser
import const import const
import ManagedWindow
import GrampsDisplay
from gui.widgets.grampletpane import (AVAILABLE_GRAMPLETS, from gui.widgets.grampletpane import (AVAILABLE_GRAMPLETS,
GET_AVAILABLE_GRAMPLETS, GET_AVAILABLE_GRAMPLETS,
get_gramplet_opts, get_gramplet_opts,
get_gramplet_options_by_tname,
get_gramplet_options_by_name, get_gramplet_options_by_name,
make_requested_gramplet) make_requested_gramplet,
GuiGramplet)
from gui.widgets.undoablebuffer import UndoableBuffer
from ListModel import ListModel, NOSORT from ListModel import ListModel, NOSORT
from QuestionDialog import ErrorDialog
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Constants # Constants
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
WIKI_HELP_PAGE = const.URL_MANUAL_PAGE + '_-_Gramplets'
NL = "\n" NL = "\n"
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -63,74 +79,41 @@ NL = "\n"
# GrampsBar class # GrampsBar class
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class GrampsBar(object): class GrampsBar(gtk.Notebook):
""" """
A class which defines the graphical representation of the Gramps bar. A class which defines the graphical representation of the GrampsBar.
""" """
def __init__(self, dbstate, uistate, configfile, close_callback, defaults): def __init__(self, dbstate, uistate, pageview, configfile, defaults):
gtk.Notebook.__init__(self)
self.dbstate = dbstate self.dbstate = dbstate
self.uistate = uistate self.uistate = uistate
self.pageview = pageview
self.configfile = os.path.join(const.VERSION_DIR, "%s.ini" % configfile) self.configfile = os.path.join(const.VERSION_DIR, "%s.ini" % configfile)
self.close_callback = close_callback self.detached_gramplets = []
self.gramplet_map = {} # title->gramplet
self.filter_page = 0
self.notebook = gtk.Notebook() self.set_group_id(1)
self.notebook.set_show_border(False) self.set_show_border(False)
self.notebook.set_scrollable(True) self.set_scrollable(True)
self.notebook.connect('switch_page', self.__switch_page) self.connect('switch-page', self.__switch_page)
self.connect('page-added', self.__page_added)
self.connect('create-window', self.__create_window)
self.connect('button-press-event', self.__button_press)
self.top = self._build_interface(self.notebook) config_settings, opts_list = self.__load(defaults)
self.default_gramplets = defaults
config_settings, opts_list = self.load_gramplets()
opts_list.sort(key=lambda opt: opt["page"]) opts_list.sort(key=lambda opt: opt["page"])
for opts in opts_list: for opts in opts_list:
name = opts["name"] all_opts = get_gramplet_opts(opts["name"], opts)
all_opts = get_gramplet_opts(name, opts) gramplet = make_requested_gramplet(TabGramplet, self, all_opts,
all_opts["layout"] = "tabs"
gramplet = make_requested_gramplet(self, name, all_opts,
self.dbstate, self.uistate) self.dbstate, self.uistate)
self.gramplet_map[all_opts["title"]] = gramplet
self.__add_tab(gramplet) self.__add_tab(gramplet)
if config_settings[0]: if config_settings[0]:
self.top.show() self.show()
self.notebook.set_current_page(config_settings[1]) self.set_current_page(config_settings[1])
def _build_interface(self, notebook): def __load(self, defaults):
"""
Build the user interface. Must be implemented in adervied class.
"""
raise NotImplementedError
def _make_buttons(self):
"""
Make the buttons.
"""
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.__close_clicked)
delete_button = gtk.Button()
img = gtk.image_new_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU)
delete_button.set_image(img)
delete_button.set_relief(gtk.RELIEF_NONE)
delete_button.connect('clicked', self.__delete_clicked)
add_button = gtk.Button()
img = gtk.image_new_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_MENU)
add_button.set_image(img)
add_button.set_relief(gtk.RELIEF_NONE)
add_button.connect('clicked', self.__add_clicked)
return (close_button, delete_button, add_button)
def load_gramplets(self):
""" """
Load the gramplets from the configuration file. Load the gramplets from the configuration file.
""" """
@ -163,40 +146,41 @@ class GrampsBar(object):
for key in sorted(data["data"].keys())] for key in sorted(data["data"].keys())]
if "name" not in data: if "name" not in data:
data["name"] = "Unnamed Gramplet" data["name"] = "Unnamed Gramplet"
data["tname"]= _("Unnamed Gramplet") data["tname"] = _("Unnamed Gramplet")
retval.append(data) retval.append(data)
else: else:
# give defaults as currently known # give defaults as currently known
for name in self.default_gramplets: for name in defaults:
if name in AVAILABLE_GRAMPLETS(): if name in AVAILABLE_GRAMPLETS():
retval.append(GET_AVAILABLE_GRAMPLETS(name)) retval.append(GET_AVAILABLE_GRAMPLETS(name))
return ((visible, default_page), retval) return ((visible, default_page), retval)
def save(self): def __save(self):
""" """
Save the gramplet configuration. Save the gramplet configuration.
""" """
if len(self.gramplet_map) == 0: if self.get_n_pages() == 0:
return # something is the matter return # something is the matter
filename = self.configfile filename = self.configfile
try: try:
fp = open(filename, "w") fp = open(filename, "w")
except: except IOError:
print "Failed writing '%s'; gramplets not saved" % filename print "Failed writing '%s'; gramplets not saved" % filename
return return
fp.write(";; Gramps bar configuration file" + NL) fp.write(";; Gramps bar configuration file" + NL)
fp.write((";; Automatically created at %s" % fp.write((";; Automatically created at %s" %
time.strftime("%Y/%m/%d %H:%M:%S")) + NL + NL) time.strftime("%Y/%m/%d %H:%M:%S")) + NL + NL)
fp.write("[Bar Options]" + NL) fp.write("[Bar Options]" + NL)
fp.write(("visible=%s" + NL) % self.top.get_property('visible')) fp.write(("visible=%s" + NL) % self.get_property('visible'))
fp.write(("page=%d" + NL) % self.notebook.get_current_page()) fp.write(("page=%d" + NL) % self.get_current_page())
fp.write(NL) fp.write(NL)
for page_num in range(self.notebook.get_n_pages()): gramplet_list = [self.get_nth_page(page_num)
title = get_title(self.notebook, page_num) for page_num in range(self.get_n_pages())]
gramplet = self.gramplet_map[title] gramplet_list.extend(self.detached_gramplets)
if gramplet is None: continue # filter tab
opts = get_gramplet_options_by_name(gramplet.name) for page_num, gramplet in enumerate(gramplet_list):
opts = get_gramplet_options_by_name(gramplet.gname)
if opts is not None: if opts is not None:
base_opts = opts.copy() base_opts = opts.copy()
for key in base_opts: for key in base_opts:
@ -204,13 +188,9 @@ class GrampsBar(object):
base_opts[key] = gramplet.__dict__[key] base_opts[key] = gramplet.__dict__[key]
fp.write(("[%s]" + NL) % gramplet.title) fp.write(("[%s]" + NL) % gramplet.title)
for key in base_opts: for key in base_opts:
if key == "content": continue if key in ["content", "title", "row", "column", "page",
elif key == "title": continue "version", "gramps"]: # don't save
elif key == "row": continue continue
elif key == "column": continue
elif key == "page": continue
elif key == "version": continue # code, don't save
elif key == "gramps": continue # code, don't save
elif key == "data": elif key == "data":
if not isinstance(base_opts["data"], (list, tuple)): if not isinstance(base_opts["data"], (list, tuple)):
fp.write(("data[0]=%s" + NL) % base_opts["data"]) fp.write(("data[0]=%s" + NL) % base_opts["data"])
@ -230,226 +210,286 @@ class GrampsBar(object):
""" """
Called with the view is set as active. Called with the view is set as active.
""" """
page = self.notebook.get_current_page() gramplet = self.get_nth_page(self.get_current_page())
title = get_title(self.notebook, page) if gramplet and gramplet.pui:
if title is not None and self.gramplet_map[title] \ gramplet.pui.active = True
and self.gramplet_map[title].pui: if gramplet.pui.dirty:
self.gramplet_map[title].pui.active = True gramplet.pui.update()
if self.gramplet_map[title].pui.dirty:
self.gramplet_map[title].pui.update()
def set_inactive(self): def set_inactive(self):
""" """
Called with the view is set as inactive. Called with the view is set as inactive.
""" """
page = self.notebook.get_current_page() gramplet = self.get_nth_page(self.get_current_page())
title = get_title(self.notebook, page) if gramplet and gramplet.pui:
if title is not None and self.gramplet_map[title] \ if gramplet.gstate != "detached":
and self.gramplet_map[title].pui: gramplet.pui.active = False
if self.gramplet_map[title].state != "detached":
self.gramplet_map[title].pui.active = False
def on_delete(self): def on_delete(self):
""" """
Called when the view is closed. Called when the view is closed.
""" """
gramplets = (g for g in self.gramplet_map.itervalues() for page_num in range(self.get_n_pages()):
if g is not None) gramplet = self.get_nth_page(page_num)
for gramplet in gramplets:
# this is the only place where the gui runs user code directly # this is the only place where the gui runs user code directly
if gramplet.pui: if gramplet.pui:
gramplet.pui.on_save() gramplet.pui.on_save()
self.save() self.__save()
def get_display(self): def add_gramplet(self, gname):
""" """
Return the top container widget for the GUI. Add a gramplet by name.
""" """
return self.top if self.has_gramplet(gname):
return
all_opts = get_gramplet_options_by_name(gname)
gramplet = make_requested_gramplet(TabGramplet, self, all_opts,
self.dbstate, self.uistate)
if not gramplet:
print "Problem creating ", gname
return
def show(self): page_num = self.__add_tab(gramplet)
""" self.set_current_page(page_num)
Show the bottom bar.
"""
return self.top.show()
def hide(self): def remove_gramplet(self, gname):
""" """
Hide the bottom bar. Remove a gramplet by name.
""" """
return self.top.hide() for page_num in range(self.get_n_pages()):
gramplet = self.get_nth_page(page_num)
def is_visible(self): if gramplet.gname == gname:
""" self.remove_page(page_num)
Return True if the bar is visible, else return False.
"""
return self.top.get_property('visible')
def add_filter(self, filter):
"""
Add a filter.
"""
self.gramplet_map[_('Filter')] = None
self.notebook.prepend_page(filter, gtk.Label(_('Filter')))
self.notebook.set_tab_reorderable(filter, True)
self.notebook.set_current_page(0)
def remove_filter(self):
"""
Remove the filter.
"""
for page_num in range(self.notebook.get_n_pages()):
title = get_title(self.notebook, page_num)
if title == _('Filter'):
self.notebook.remove_page(page_num)
del self.gramplet_map[_('Filter')]
return return
def __close_clicked(self, button): def has_gramplet(self, gname):
""" """
Called when the sidebar is closed. Return True if the GrampsBar contains the gramplet, else False.
""" """
self.close_callback() return True if gname in self.all_gramplets() else False
def __add_clicked(self, button): def all_gramplets(self):
"""
Return a list of names of all the gramplets in the GrampsBar.
"""
return [gramplet.gname for gramplet in self.get_children() +
self.detached_gramplets]
def __add_clicked(self):
""" """
Called when the add button is clicked. Called when the add button is clicked.
""" """
names = [GET_AVAILABLE_GRAMPLETS(key)["tname"] for key skip = self.all_gramplets()
in AVAILABLE_GRAMPLETS()] names = [name for name in AVAILABLE_GRAMPLETS() if name not in skip]
skip = [gramplet.tname for gramplet in self.gramplet_map.values() gramplet_list = [(GET_AVAILABLE_GRAMPLETS(name)["tname"], name)
if gramplet is not None] for name in names]
gramplet_list = [name for name in names if name not in skip]
gramplet_list.sort() gramplet_list.sort()
dialog = ChooseGrampletDialog(_("Select Gramplet"), gramplet_list) dialog = ChooseGrampletDialog(_("Select Gramplet"), gramplet_list)
tname = dialog.run() name = dialog.run()
if not tname: if name:
return self.add_gramplet(name)
all_opts = get_gramplet_options_by_tname(tname)
all_opts["layout"] = "tabs"
gramplet = make_requested_gramplet(self, all_opts["name"], all_opts,
self.dbstate, self.uistate)
if not gramplet:
print "Problem creating ", tname
return
self.gramplet_map[gramplet.title] = gramplet
page_num = self.__add_tab(gramplet)
self.notebook.set_current_page(page_num)
def __add_tab(self, gramplet): def __add_tab(self, gramplet):
""" """
Add a tab to the notebook for the given gramplet. Add a tab to the notebook for the given gramplet.
""" """
gramplet.scrolledwindow.set_size_request(-1, gramplet.height) gramplet.set_size_request(gramplet.width, gramplet.height)
label = gtk.Label(gramplet.title) page_num = self.append_page(gramplet)
label.set_tooltip_text(gramplet.tname)
page_num = self.notebook.append_page(gramplet.mainframe, label)
self.notebook.set_tab_reorderable(gramplet.mainframe, True)
return page_num return page_num
def __delete_clicked(self, button): def __create_tab_label(self, gramplet):
"""
Create a tab label consisting of a label and a close button.
"""
hbox = gtk.HBox(False, 4)
label = gtk.Label(gramplet.title)
label.set_tooltip_text(gramplet.tname)
closebtn = gtk.Button()
image = gtk.Image()
image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
closebtn.connect("clicked", self.__delete_clicked, gramplet)
closebtn.set_image(image)
closebtn.set_relief(gtk.RELIEF_NONE)
# The next three lines adjust the close button to the correct size.
closebtn.set_name('tab-button')
size = gtk.icon_size_lookup_for_settings(closebtn.get_settings(),
gtk.ICON_SIZE_MENU)
closebtn.set_size_request(size[0] + 2, size[1] + 2)
hbox.pack_start(label, True, True)
hbox.pack_end(closebtn, False, False)
hbox.show_all()
return hbox
def __delete_clicked(self, button, gramplet):
""" """
Called when the delete button is clicked. Called when the delete button is clicked.
""" """
page_num = self.notebook.get_current_page() page_num = self.page_num(gramplet)
title = get_title(self.notebook, page_num) self.remove_page(page_num)
if self.gramplet_map[title] is None:
ErrorDialog(
_("Cannot remove tab"),
_("The filter tab cannot be removed"))
else:
del self.gramplet_map[title]
self.notebook.remove_page(page_num)
def __switch_page(self, notebook, unused, new_page): def __switch_page(self, notebook, unused, new_page):
""" """
Called when the user has switched to a new bottombar page. Called when the user has switched to a new GrampsBar page.
""" """
old_page = notebook.get_current_page() old_page = notebook.get_current_page()
#print "switch from", old_page, "to", new_page
if old_page >= 0: if old_page >= 0:
title = get_title(notebook, old_page) gramplet = self.get_nth_page(old_page)
if self.gramplet_map[title] and self.gramplet_map[title].pui: if gramplet and gramplet.pui:
if self.gramplet_map[title].state != "detached": if gramplet.gstate != "detached":
self.gramplet_map[title].pui.active = False gramplet.pui.active = False
title = get_title(notebook, new_page) gramplet = self.get_nth_page(new_page)
if self.gramplet_map[title] and self.gramplet_map[title].pui: if gramplet and gramplet.pui:
self.gramplet_map[title].pui.active = True gramplet.pui.active = True
if self.gramplet_map[title].pui.dirty: if gramplet.pui.dirty:
self.gramplet_map[title].pui.update() gramplet.pui.update()
def get_title(notebook, page_num): def __page_added(self, notebook, unused, new_page):
"""
Reurn the title of a given page in a notebook.
"""
page = notebook.get_nth_page(page_num)
if page is None:
return None
else:
return notebook.get_tab_label_text(page)
#-------------------------------------------------------------------------
#
# HBar class
#
#-------------------------------------------------------------------------
class HBar(GrampsBar):
"""
A class which defines the representation of a horizontal Gramps bar.
"""
def _build_interface(self, notebook):
""" """
Build the horizontal user interface. Called when a new page is added to the GrampsBar.
""" """
top = gtk.HBox() gramplet = self.get_nth_page(new_page)
vbox = gtk.VBox() label = self.__create_tab_label(gramplet)
self.set_tab_label(gramplet, label)
self.set_tab_reorderable(gramplet, True)
self.set_tab_detachable(gramplet, True)
if gramplet in self.detached_gramplets:
self.detached_gramplets.remove(gramplet)
self.reorder_child(gramplet, gramplet.page)
close_button, delete_button, add_button = self._make_buttons() def __create_window(self, grampsbar, gramplet, x_pos, y_pos):
"""
Called when the user has switched to a new GrampsBar page.
"""
gramplet.page = self.page_num(gramplet)
self.detached_gramplets.append(gramplet)
win = DetachedWindow(grampsbar, gramplet, x_pos, y_pos)
return win.get_notebook()
vbox.pack_start(close_button, False) def __button_press(self, widget, event):
vbox.pack_end(delete_button, False) """
vbox.pack_end(add_button, False) Called when a button is pressed in the tabs section of the GrampsBar.
"""
top.pack_start(notebook, True) if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
top.pack_start(vbox, False) # TODO: We will probably want a context menu here.
self.__add_clicked()
notebook.show()
vbox.show_all()
return top
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# VBar class # TabGramplet class
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class VBar(GrampsBar): class TabGramplet(gtk.ScrolledWindow, GuiGramplet):
""" """
A class which defines the representation of a vertical Gramps bar. Class that handles the plugin interfaces for the GrampletBar.
""" """
def _build_interface(self, notebook): def __init__(self, pane, dbstate, uistate, title, **kwargs):
""" """
Build the vertical user interface. Internal constructor for GUI portion of a gramplet.
""" """
top = gtk.VBox() gtk.ScrolledWindow.__init__(self)
hbox = gtk.HBox() GuiGramplet.__init__(self, pane, dbstate, uistate, title, **kwargs)
close_button, delete_button, add_button = self._make_buttons() self.scrolledwindow = self
self.textview = gtk.TextView()
self.buffer = UndoableBuffer()
self.text_length = 0
self.textview.set_buffer(self.buffer)
self.textview.connect("key-press-event", self.on_key_press_event)
self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.add(self.textview)
self.show_all()
hbox.pack_start(add_button, False) def get_container_widget(self):
hbox.pack_start(delete_button, False) """
hbox.pack_end(close_button, False) Return the top level container widget.
"""
top.pack_start(hbox, False) return self
top.pack_start(notebook, True)
notebook.show()
hbox.show_all()
return top #-------------------------------------------------------------------------
#
# DetachedWindow class
#
#-------------------------------------------------------------------------
class DetachedWindow(ManagedWindow.ManagedWindow):
"""
Class for showing a detached gramplet.
"""
def __init__(self, grampsbar, gramplet, x_pos, y_pos):
"""
Construct the window.
"""
self.title = gramplet.title + " " + _("Gramplet")
self.grampsbar = grampsbar
self.gramplet = gramplet
ManagedWindow.ManagedWindow.__init__(self, gramplet.uistate, [],
self.title)
self.set_window(gtk.Dialog("", gramplet.uistate.window,
gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)),
None,
self.title)
self.window.move(x_pos, y_pos)
self.window.set_size_request(gramplet.detached_width,
gramplet.detached_height)
self.window.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP)
self.window.connect('response', self.handle_response)
self.notebook = gtk.Notebook()
self.notebook.set_show_tabs(False)
self.notebook.set_show_border(False)
self.notebook.show()
self.window.vbox.add(self.notebook)
self.show()
def handle_response(self, object, response):
"""
Callback for taking care of button clicks.
"""
if response in [gtk.RESPONSE_CLOSE, gtk.STOCK_CLOSE]:
self.close()
elif response == gtk.RESPONSE_HELP:
# translated name:
if self.gramplet.help_url:
if self.gramplet.help_url.startswith("http://"):
GrampsDisplay.url(self.gramplet.help_url)
else:
GrampsDisplay.help(self.gramplet.help_url)
else:
GrampsDisplay.help(WIKI_HELP_PAGE,
self.gramplet.tname.replace(" ", "_"))
def get_notebook(self):
"""
Return the notebook.
"""
return self.notebook
def build_menu_names(self, obj):
"""
Part of the GRAMPS window interface.
"""
return (self.title, 'Gramplet')
def get_title(self):
"""
Returns the window title.
"""
return self.title
def close(self, *args):
"""
Dock the detached gramplet back in the GrampsBar from where it came.
"""
size = self.window.get_size()
self.gramplet.detached_width = size[0]
self.gramplet.detached_height = size[1]
self.gramplet.reparent(self.grampsbar)
ManagedWindow.ManagedWindow.close(self, *args)
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -477,7 +517,7 @@ class ChooseGrampletDialog(object):
if response == gtk.RESPONSE_OK: if response == gtk.RESPONSE_OK:
store, iter_ = self.namemodel.get_selected() store, iter_ = self.namemodel.get_selected()
if iter_: if iter_:
result = store.get_value(iter_, 0) result = store.get_value(iter_, 1)
self.top.destroy() self.top.destroy()
return result return result
@ -487,7 +527,7 @@ class ChooseGrampletDialog(object):
""" """
self.namemodel.clear() self.namemodel.clear()
for name in self.names: for name in self.names:
self.namemodel.add([name]) self.namemodel.add(name)
def _create_dialog(self): def _create_dialog(self):
""" """
@ -507,7 +547,8 @@ class ChooseGrampletDialog(object):
box = gtk.HBox() box = gtk.HBox()
top.vbox.pack_start(box, 1, 1, 5) top.vbox.pack_start(box, 1, 1, 5)
name_titles = [(_('Name'), NOSORT, 200)] name_titles = [(_('Name'), NOSORT, 200),
('', NOSORT, 200)]
self.namelist = gtk.TreeView() self.namelist = gtk.TreeView()
self.namemodel = ListModel(self.namelist, name_titles) self.namemodel = ListModel(self.namelist, name_titles)
@ -523,4 +564,3 @@ class ChooseGrampletDialog(object):
box.pack_start(bbox, 0, 0, 5) box.pack_start(bbox, 0, 0, 5)
top.show_all() top.show_all()
return top return top

View File

@ -49,7 +49,7 @@ from gen.ggettext import gettext as _
import Errors import Errors
from gui.dbguielement import DbGUIElement from gui.dbguielement import DbGUIElement
from gui.widgets.menutoolbuttonaction import MenuToolButtonAction from gui.widgets.menutoolbuttonaction import MenuToolButtonAction
from gui.grampsbar import HBar, VBar from gui.grampsbar import GrampsBar
from gui.configure import ConfigureDialog from gui.configure import ConfigureDialog
from config import config from config import config
@ -147,56 +147,28 @@ class PageView(DbGUIElement):
Returns a gtk container widget. Returns a gtk container widget.
""" """
defaults = self.get_default_gramplets() defaults = self.get_default_gramplets()
self.sidebar = VBar(self.dbstate, self.uistate, self.sidebar = GrampsBar(self.dbstate, self.uistate, self,
self.ident + "_sidebar", self.ident + "_sidebar",
self.sidebar_closed,
defaults[0]) defaults[0])
self.bottombar = HBar(self.dbstate, self.uistate, self.bottombar = GrampsBar(self.dbstate, self.uistate, self,
self.ident + "_bottombar", self.ident + "_bottombar",
self.bottombar_closed,
defaults[1]) defaults[1])
hpane = gtk.HPaned() hpane = gtk.HPaned()
vpane = gtk.VPaned() vpane = gtk.VPaned()
hpane.pack1(vpane, resize=True, shrink=False) hpane.pack1(vpane, resize=True, shrink=False)
hpane.pack2(self.sidebar.get_display(), resize=False, shrink=True) hpane.pack2(self.sidebar, resize=False, shrink=True)
hpane.show() hpane.show()
vpane.show() vpane.show()
widget = self.build_widget() widget = self.build_widget()
widget.show_all() widget.show_all()
vpane.pack1(widget, resize=True, shrink=False) vpane.pack1(widget, resize=True, shrink=False)
vpane.pack2(self.bottombar.get_display(), resize=False, shrink=True) vpane.pack2(self.bottombar, resize=False, shrink=True)
if self.filter_class: self.sidebar_toggled(self.sidebar.get_property('visible'))
self.add_filter(self.filter_class)
self.sidebar_toggled(self.sidebar.is_visible())
return hpane return hpane
def add_filter(self, filter_class):
"""
Add a filter to the sidebar.
"""
self.filter_tab = filter_class(self.dbstate, self.uistate,
self.__filter_clicked)
top = self.filter_tab.get_widget()
top.show_all()
self.sidebar.add_filter(top)
def remove_filter(self):
"""
Remove the filter from the sidebar.
"""
self.filter_tab = None
self.sidebar.remove_filter()
def __filter_clicked(self):
"""
Called when the filter 'Find' button is clicked.
"""
self.generic_filter = self.filter_tab.get_filter()
self.build_tree()
def __sidebar_toggled(self, action): def __sidebar_toggled(self, action):
""" """
Called when the sidebar is toggled. Called when the sidebar is toggled.
@ -225,20 +197,6 @@ class PageView(DbGUIElement):
""" """
pass pass
def sidebar_closed(self):
"""
Called when the sidebar close button is clicked.
"""
uimanager = self.uistate.uimanager
uimanager.get_action('/MenuBar/ViewMenu/Bars/Sidebar').activate()
def bottombar_closed(self):
"""
Called when the bottombar close button is clicked.
"""
uimanager = self.uistate.uimanager
uimanager.get_action('/MenuBar/ViewMenu/Bars/Bottombar').activate()
def get_default_gramplets(self): def get_default_gramplets(self):
""" """
Get the default gramplets for the Gramps sidebar and bottombar. Get the default gramplets for the Gramps sidebar and bottombar.
@ -446,9 +404,11 @@ class PageView(DbGUIElement):
self.action_toggle_list in this function. self.action_toggle_list in this function.
""" """
self._add_toggle_action('Sidebar', None, _('_Sidebar'), self._add_toggle_action('Sidebar', None, _('_Sidebar'),
None, None, self.__sidebar_toggled, self.sidebar.is_visible()) None, None, self.__sidebar_toggled,
self.sidebar.get_property('visible'))
self._add_toggle_action('Bottombar', None, _('_Bottombar'), self._add_toggle_action('Bottombar', None, _('_Bottombar'),
None, None, self.__bottombar_toggled, self.bottombar.is_visible()) None, None, self.__bottombar_toggled,
self.bottombar.get_property('visible'))
def __build_action_group(self): def __build_action_group(self):
""" """

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program # Gramps - a GTK+/GNOME based genealogy program
# #
# Copyright (C) 2000-2007 Donald N. Allingham # Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2011 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
@ -31,9 +32,7 @@ GrampletView interface.
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
import gtk import gtk
import pango import pango
import traceback
import time import time
import types
import os import os
from gen.ggettext import gettext as _ from gen.ggettext import gettext as _
@ -147,27 +146,20 @@ def get_gramplet_options_by_tname(name):
print ("Unknown gramplet name: '%s'" % name) print ("Unknown gramplet name: '%s'" % name)
return None return None
def make_requested_gramplet(pane, name, opts, dbstate, uistate): def make_requested_gramplet(gui_class, pane, opts, dbstate, uistate):
""" """
Make a GUI gramplet given its name. Make a GUI gramplet given its name.
""" """
name = opts["name"]
if name in AVAILABLE_GRAMPLETS(): if name in AVAILABLE_GRAMPLETS():
gui = GuiGramplet(pane, dbstate, uistate, **opts) gui = gui_class(pane, dbstate, uistate, **opts)
if opts.get("content", None): if opts.get("content", None):
pdata = PLUGMAN.get_plugin(opts["name"]) pdata = PLUGMAN.get_plugin(name)
module = PLUGMAN.load_plugin(pdata) module = PLUGMAN.load_plugin(pdata)
if module: if module:
getattr(module, opts["content"])(gui) getattr(module, opts["content"])(gui)
else: else:
print "Error loading gramplet '%s': skipping content" \ print "Error loading gramplet '%s': skipping content" % name
% opts["name"]
# now that we have user code, set the tooltips
msg = gui.tooltip
if opts.get("layout", "grid") == "grid" and msg is None:
msg = _("Drag Properties Button to move and click it for setup")
if msg:
gui.scrolledwindow.set_tooltip_text(msg)
gui.tooltips_text = msg
return gui return gui
return None return None
@ -205,11 +197,12 @@ class GrampletWindow(ManagedWindow.ManagedWindow):
self.gramplet = gramplet self.gramplet = gramplet
self.gramplet.detached_window = self self.gramplet.detached_window = self
# Keep track of what state it was in: # Keep track of what state it was in:
self.docked_state = gramplet.state self.docked_state = gramplet.gstate
# Now detach it # Now detach it
self.gramplet.set_state("detached") self.gramplet.set_state("detached")
ManagedWindow.ManagedWindow.__init__(self, gramplet.uistate, [], self.title) ManagedWindow.ManagedWindow.__init__(self, gramplet.uistate, [],
self.set_window(gtk.Dialog("",gramplet.uistate.window, self.title)
self.set_window(gtk.Dialog("", gramplet.uistate.window,
gtk.DIALOG_DESTROY_WITH_PARENT, gtk.DIALOG_DESTROY_WITH_PARENT,
(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)), (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)),
None, self.title) None, self.title)
@ -279,7 +272,7 @@ class GrampletWindow(ManagedWindow.ManagedWindow):
if gramplet.row > self.gramplet.row: if gramplet.row > self.gramplet.row:
pane.columns[col].remove(gframe) pane.columns[col].remove(gframe)
stack.append(gframe) stack.append(gframe)
expand = self.gramplet.state == "maximized" and self.gramplet.expand expand = self.gramplet.gstate == "maximized" and self.gramplet.expand
column = pane.columns[col] column = pane.columns[col]
parent = self.gramplet.pane.get_column_frame(self.gramplet.column) parent = self.gramplet.pane.get_column_frame(self.gramplet.column)
self.gramplet.mainframe.reparent(parent) self.gramplet.mainframe.reparent(parent)
@ -287,13 +280,13 @@ class GrampletWindow(ManagedWindow.ManagedWindow):
self.gramplet.pui.active = self.gramplet.pane.pageview.active self.gramplet.pui.active = self.gramplet.pane.pageview.active
for gframe in stack: for gframe in stack:
gramplet = pane.frame_map[str(gframe)] gramplet = pane.frame_map[str(gframe)]
expand = gramplet.state == "maximized" and gramplet.expand expand = gramplet.gstate == "maximized" and gramplet.expand
pane.columns[col].pack_start(gframe, expand=expand) pane.columns[col].pack_start(gframe, expand=expand)
# Now make sure they all have the correct expand: # Now make sure they all have the correct expand:
for gframe in pane.columns[col]: for gframe in pane.columns[col]:
gramplet = pane.frame_map[str(gframe)] gramplet = pane.frame_map[str(gframe)]
expand, fill, padding, pack = column.query_child_packing(gramplet.mainframe) expand, fill, padding, pack = column.query_child_packing(gramplet.mainframe)
expand = gramplet.state == "maximized" and gramplet.expand expand = gramplet.gstate == "maximized" and gramplet.expand
column.set_child_packing(gramplet.mainframe, expand, fill, padding, pack) column.set_child_packing(gramplet.mainframe, expand, fill, padding, pack)
self.gramplet.gvclose.show() self.gramplet.gvclose.show()
self.gramplet.gvstate.show() self.gramplet.gvstate.show()
@ -304,89 +297,52 @@ class GrampletWindow(ManagedWindow.ManagedWindow):
class GuiGramplet(object): class GuiGramplet(object):
""" """
Class that handles the plugin interfaces for the GrampletView. Class that handles the GUI representation of a Gramplet.
""" """
TARGET_TYPE_FRAME = 80
LOCAL_DRAG_TYPE = 'GRAMPLET'
LOCAL_DRAG_TARGET = (LOCAL_DRAG_TYPE, 0, TARGET_TYPE_FRAME)
def __init__(self, pane, dbstate, uistate, title, **kwargs): def __init__(self, pane, dbstate, uistate, title, **kwargs):
""" """
Internal constructor for GUI portion of a gramplet. Internal constructor for GUI portion of a gramplet.
""" """
self.pane = pane self.pane = pane
self.view = pane.pageview
self.dbstate = dbstate self.dbstate = dbstate
self.uistate = uistate self.uistate = uistate
self.title = title self.title = title
self.detached_window = None self.detached_window = None
self.force_update = False self.force_update = False
self._tags = [] self._tags = []
self.link_cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
self.standard_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM)
########## Set defaults ########## Set defaults
self.name = kwargs.get("name", "Unnamed Gramplet") self.gname = kwargs.get("name", "Unnamed Gramplet")
self.tname = kwargs.get("tname", "Unnamed Gramplet") self.tname = kwargs.get("tname", "Unnamed Gramplet")
self.version = kwargs.get("version", "0.0.0") self.version = kwargs.get("version", "0.0.0")
self.gramps = kwargs.get("gramps", "0.0.0") self.gramps = kwargs.get("gramps", "0.0.0")
self.expand = logical_true(kwargs.get("expand", False)) self.expand = logical_true(kwargs.get("expand", False))
self.height = int(kwargs.get("height", 200)) self.height = int(kwargs.get("height", 200))
self.width = int(kwargs.get("width", 375))
self.column = int(kwargs.get("column", -1)) self.column = int(kwargs.get("column", -1))
self.detached_height = int(kwargs.get("detached_height", 300)) self.detached_height = int(kwargs.get("detached_height", 300))
self.detached_width = int(kwargs.get("detached_width", 400)) self.detached_width = int(kwargs.get("detached_width", 400))
self.row = int(kwargs.get("row", -1)) self.row = int(kwargs.get("row", -1))
self.page = int(kwargs.get("page", -1)) self.page = int(kwargs.get("page", -1))
self.state = kwargs.get("state", "maximized") self.gstate = kwargs.get("state", "maximized")
self.data = kwargs.get("data", []) self.data = kwargs.get("data", [])
self.help_url = kwargs.get("help_url", WIKI_HELP_PAGE) self.help_url = kwargs.get("help_url", WIKI_HELP_PAGE)
########## ##########
self.use_markup = False self.use_markup = False
self.pui = None # user code self.pui = None # user code
self.tooltip = None # text
self.tooltips = None # gtk tooltip widget
self.tooltips_text = None self.tooltips_text = None
self.link_cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
self.standard_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM)
self.scrolledwindow = None
self.textview = None
self.buffer = None
def set_tooltip(self, tip):
self.tooltips_text = tip
self.scrolledwindow.set_tooltip_text(tip)
self.xml = Glade()
self.gvwin = self.xml.toplevel
self.mainframe = self.xml.get_object('gvgramplet')
self.gvwin.remove(self.mainframe)
self.textview = self.xml.get_object('gvtextview')
self.buffer = UndoableBuffer()
self.text_length = 0
self.textview.set_buffer(self.buffer)
self.textview.connect("key-press-event", self.on_key_press_event)
#self.buffer = self.textview.get_buffer()
self.scrolledwindow = self.xml.get_object('gvscrolledwindow')
self.vboxtop = self.xml.get_object('vboxtop')
self.titlelabel = self.xml.get_object('gvtitle')
self.titlelabel.get_children()[0].set_text("<b><i>%s</i></b>" % self.title)
self.titlelabel.get_children()[0].set_use_markup(True)
self.titlelabel.connect("clicked", self.edit_title)
self.titlelabel_entry = None
self.gvclose = self.xml.get_object('gvclose')
self.gvclose.connect('clicked', self.close)
self.gvstate = self.xml.get_object('gvstate')
self.gvstate.connect('clicked', self.change_state)
self.gvproperties = self.xml.get_object('gvproperties')
self.gvproperties.connect('clicked', self.set_properties)
self.xml.get_object('gvcloseimage').set_from_stock(gtk.STOCK_CLOSE,
gtk.ICON_SIZE_MENU)
self.xml.get_object('gvstateimage').set_from_stock(gtk.STOCK_REMOVE,
gtk.ICON_SIZE_MENU)
self.xml.get_object('gvpropertiesimage').set_from_stock(gtk.STOCK_PROPERTIES,
gtk.ICON_SIZE_MENU)
# source:
drag = self.gvproperties
drag.drag_source_set(gtk.gdk.BUTTON1_MASK,
[GuiGramplet.LOCAL_DRAG_TARGET],
gtk.gdk.ACTION_COPY)
if kwargs.get("layout", "grid") == "tabs":
self.titlelabel.hide()
self.gvclose.hide()
self.gvstate.hide()
self.gvproperties.hide()
def undo(self): def undo(self):
self.buffer.undo() self.buffer.undo()
self.text_length = self.len_text(self.get_text()) self.text_length = self.len_text(self.get_text())
@ -413,117 +369,6 @@ class GuiGramplet(object):
return False return False
def edit_title(self, widget):
"""
Edit the the title in the GUI.
"""
parent = widget.get_parent()
widget.hide()
if self.titlelabel_entry is None:
self.titlelabel_entry = gtk.Entry()
parent = widget.get_parent()
parent.pack_end(self.titlelabel_entry)
self.titlelabel_entry.connect("focus-out-event", self.edit_title_done)
self.titlelabel_entry.connect("activate", self.edit_title_done)
self.titlelabel_entry.connect("key-press-event", self.edit_title_keypress)
self.titlelabel_entry.set_text(widget.get_children()[0].get_text())
self.titlelabel_entry.show()
self.titlelabel_entry.grab_focus()
return True
def edit_title_keypress(self, widget, event):
"""
Edit the title, handle escape.
"""
if event.type == gtk.gdk.KEY_PRESS:
if event.keyval == gtk.keysyms.Escape:
self.titlelabel.show()
widget.hide()
def edit_title_done(self, widget, event=None):
"""
Edit title in GUI, finishing callback.
"""
result = self.set_title(widget.get_text())
if result: # if ok to set title to that
self.titlelabel.show()
widget.hide()
return False # Return False for gtk requirement
def close(self, *obj):
"""
Remove (delete) the gramplet from view.
"""
if self.state == "detached":
return
self.state = "closed"
self.pane.closed_gramplets.append(self)
self.mainframe.get_parent().remove(self.mainframe)
def detach(self):
"""
Detach the gramplet from the GrampletView, and open in own window.
"""
# hide buttons:
#self.set_state("detached")
self.pane.detached_gramplets.append(self)
# make a window, and attach it there
self.detached_window = GrampletWindow(self)
def set_state(self, state):
"""
Set the state of a gramplet.
"""
oldstate = self.state
self.state = state
if state == "minimized":
self.scrolledwindow.hide()
self.xml.get_object('gvstateimage').set_from_stock(gtk.STOCK_ADD,
gtk.ICON_SIZE_MENU)
column = self.mainframe.get_parent() # column
expand,fill,padding,pack = column.query_child_packing(self.mainframe)
column.set_child_packing(self.mainframe,False,fill,padding,pack)
else:
self.scrolledwindow.show()
self.xml.get_object('gvstateimage').set_from_stock(gtk.STOCK_REMOVE,
gtk.ICON_SIZE_MENU)
column = self.mainframe.get_parent() # column
expand,fill,padding,pack = column.query_child_packing(self.mainframe)
column.set_child_packing(self.mainframe,
self.expand,
fill,
padding,
pack)
if self.pui and self.pui.dirty:
self.pui.update()
def change_state(self, obj):
"""
Change the state of a gramplet.
"""
if self.state == "detached":
pass # don't change if detached
else:
if self.state == "maximized":
self.set_state("minimized")
else:
self.set_state("maximized")
def set_properties(self, obj):
"""
Set the properties of a gramplet.
"""
if self.state == "detached":
pass
else:
self.detach()
return
self.expand = not self.expand
if self.state == "maximized":
column = self.mainframe.get_parent() # column
expand,fill,padding,pack = column.query_child_packing(self.mainframe)
column.set_child_packing(self.mainframe,self.expand,fill,padding,pack)
def append_text(self, text, scroll_to="end"): def append_text(self, text, scroll_to="end"):
enditer = self.buffer.get_end_iter() enditer = self.buffer.get_end_iter()
start = self.buffer.create_mark(None, enditer, True) start = self.buffer.create_mark(None, enditer, True)
@ -619,31 +464,31 @@ class GuiGramplet(object):
self.append_text(retval) self.append_text(retval)
for items in markup_pos["TT"]: for items in markup_pos["TT"]:
if len(items) == 3: if len(items) == 3:
(a,attributes,b) = items (a, attributes, b) = items
start = self.buffer.get_iter_at_offset(a + offset) start = self.buffer.get_iter_at_offset(a + offset)
stop = self.buffer.get_iter_at_offset(b + offset) stop = self.buffer.get_iter_at_offset(b + offset)
self.buffer.apply_tag_by_name("fixed", start, stop) self.buffer.apply_tag_by_name("fixed", start, stop)
for items in markup_pos["B"]: for items in markup_pos["B"]:
if len(items) == 3: if len(items) == 3:
(a,attributes,b) = items (a, attributes, b) = items
start = self.buffer.get_iter_at_offset(a + offset) start = self.buffer.get_iter_at_offset(a + offset)
stop = self.buffer.get_iter_at_offset(b + offset) stop = self.buffer.get_iter_at_offset(b + offset)
self.buffer.apply_tag_by_name("bold", start, stop) self.buffer.apply_tag_by_name("bold", start, stop)
for items in markup_pos["I"]: for items in markup_pos["I"]:
if len(items) == 3: if len(items) == 3:
(a,attributes,b) = items (a, attributes, b) = items
start = self.buffer.get_iter_at_offset(a + offset) start = self.buffer.get_iter_at_offset(a + offset)
stop = self.buffer.get_iter_at_offset(b + offset) stop = self.buffer.get_iter_at_offset(b + offset)
self.buffer.apply_tag_by_name("italic", start, stop) self.buffer.apply_tag_by_name("italic", start, stop)
for items in markup_pos["U"]: for items in markup_pos["U"]:
if len(items) == 3: if len(items) == 3:
(a,attributes,b) = items (a, attributes, b) = items
start = self.buffer.get_iter_at_offset(a + offset) start = self.buffer.get_iter_at_offset(a + offset)
stop = self.buffer.get_iter_at_offset(b + offset) stop = self.buffer.get_iter_at_offset(b + offset)
self.buffer.apply_tag_by_name("underline", start, stop) self.buffer.apply_tag_by_name("underline", start, stop)
for items in markup_pos["A"]: for items in markup_pos["A"]:
if len(items) == 3: if len(items) == 3:
(a,attributes,b) = items (a, attributes, b) = items
start = self.buffer.get_iter_at_offset(a + offset) start = self.buffer.get_iter_at_offset(a + offset)
stop = self.buffer.get_iter_at_offset(b + offset) stop = self.buffer.get_iter_at_offset(b + offset)
if "href" in attributes: if "href" in attributes:
@ -664,9 +509,10 @@ class GuiGramplet(object):
if self.use_markup == value: return if self.use_markup == value: return
self.use_markup = value self.use_markup = value
if value: if value:
self.buffer.create_tag("bold",weight=pango.WEIGHT_HEAVY) self.buffer.create_tag("bold", weight=pango.WEIGHT_HEAVY)
self.buffer.create_tag("italic",style=pango.STYLE_ITALIC) self.buffer.create_tag("italic", style=pango.STYLE_ITALIC)
self.buffer.create_tag("underline",underline=pango.UNDERLINE_SINGLE) self.buffer.create_tag("underline",
underline=pango.UNDERLINE_SINGLE)
self.buffer.create_tag("fixed", font="monospace") self.buffer.create_tag("fixed", font="monospace")
else: else:
tag_table = self.buffer.get_tag_table() tag_table = self.buffer.get_tag_table()
@ -678,15 +524,8 @@ class GuiGramplet(object):
self.append_text(text, scroll_to) self.append_text(text, scroll_to)
self.buffer.reset() self.buffer.reset()
def get_source_widget(self):
"""
Hack to allow us to send this object to the drop_widget
method as a context.
"""
return self.gvproperties
def get_container_widget(self): def get_container_widget(self):
return self.scrolledwindow raise NotImplementedError
def make_gui_options(self): def make_gui_options(self):
if not self.pui: return if not self.pui: return
@ -746,6 +585,7 @@ class GuiGramplet(object):
return False # handle event further, if necessary return False # handle event further, if necessary
def on_button_press(self, view, event): def on_button_press(self, view, event):
# pylint: disable-msg=W0212
buffer_location = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, buffer_location = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
int(event.x), int(event.x),
int(event.y)) int(event.y))
@ -764,7 +604,7 @@ class GuiGramplet(object):
return True # handled event return True # handled event
except Errors.WindowActiveError: except Errors.WindowActiveError:
pass pass
elif event.type == gtk.gdk.BUTTON_PRESS: # single click elif event.type == gtk.gdk.BUTTON_PRESS: # single
self.uistate.set_active(handle, 'Person') self.uistate.set_active(handle, 'Person')
return True # handled event return True # handled event
elif event.button == 3: # right mouse elif event.button == 3: # right mouse
@ -848,13 +688,195 @@ class GuiGramplet(object):
return True return True
return False # did not handle event return False # did not handle event
class GridGramplet(GuiGramplet):
"""
Class that handles the plugin interfaces for the GrampletView.
"""
TARGET_TYPE_FRAME = 80
LOCAL_DRAG_TYPE = 'GRAMPLET'
LOCAL_DRAG_TARGET = (LOCAL_DRAG_TYPE, 0, TARGET_TYPE_FRAME)
def __init__(self, pane, dbstate, uistate, title, **kwargs):
"""
Internal constructor for GUI portion of a gramplet.
"""
GuiGramplet.__init__(self, pane, dbstate, uistate, title,
**kwargs)
self.xml = Glade()
self.gvwin = self.xml.toplevel
self.mainframe = self.xml.get_object('gvgramplet')
self.gvwin.remove(self.mainframe)
self.textview = self.xml.get_object('gvtextview')
self.buffer = UndoableBuffer()
self.text_length = 0
self.textview.set_buffer(self.buffer)
self.textview.connect("key-press-event", self.on_key_press_event)
#self.buffer = self.textview.get_buffer()
self.scrolledwindow = self.xml.get_object('gvscrolledwindow')
self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
self.vboxtop = self.xml.get_object('vboxtop')
self.titlelabel = self.xml.get_object('gvtitle')
self.titlelabel.get_children()[0].set_text("<b><i>%s</i></b>" %
self.title)
self.titlelabel.get_children()[0].set_use_markup(True)
self.titlelabel.connect("clicked", self.edit_title)
self.titlelabel_entry = None
self.gvclose = self.xml.get_object('gvclose')
self.gvclose.connect('clicked', self.close)
self.gvstate = self.xml.get_object('gvstate')
self.gvstate.connect('clicked', self.change_state)
self.gvproperties = self.xml.get_object('gvproperties')
self.gvproperties.connect('clicked', self.set_properties)
self.xml.get_object('gvcloseimage').set_from_stock(gtk.STOCK_CLOSE,
gtk.ICON_SIZE_MENU)
self.xml.get_object('gvstateimage').set_from_stock(gtk.STOCK_REMOVE,
gtk.ICON_SIZE_MENU)
self.xml.get_object('gvpropertiesimage').set_from_stock(gtk.STOCK_PROPERTIES,
gtk.ICON_SIZE_MENU)
# source:
drag = self.gvproperties
drag.drag_source_set(gtk.gdk.BUTTON1_MASK,
[GridGramplet.LOCAL_DRAG_TARGET],
gtk.gdk.ACTION_COPY)
# default tooltip
msg = _("Drag Properties Button to move and click it for setup")
if not self.tooltips_text:
self.set_tooltip(msg)
def edit_title(self, widget):
"""
Edit the the title in the GUI.
"""
parent = widget.get_parent()
widget.hide()
if self.titlelabel_entry is None:
self.titlelabel_entry = gtk.Entry()
parent = widget.get_parent()
parent.pack_end(self.titlelabel_entry)
self.titlelabel_entry.connect("focus-out-event",
self.edit_title_done)
self.titlelabel_entry.connect("activate", self.edit_title_done)
self.titlelabel_entry.connect("key-press-event",
self.edit_title_keypress)
self.titlelabel_entry.set_text(widget.get_children()[0].get_text())
self.titlelabel_entry.show()
self.titlelabel_entry.grab_focus()
return True
def edit_title_keypress(self, widget, event):
"""
Edit the title, handle escape.
"""
if event.type == gtk.gdk.KEY_PRESS:
if event.keyval == gtk.keysyms.Escape:
self.titlelabel.show()
widget.hide()
def edit_title_done(self, widget, event=None):
"""
Edit title in GUI, finishing callback.
"""
result = self.set_title(widget.get_text())
if result: # if ok to set title to that
self.titlelabel.show()
widget.hide()
return False # Return False for gtk requirement
def close(self, *obj):
"""
Remove (delete) the gramplet from view.
"""
if self.gstate == "detached":
return
self.gstate = "closed"
self.pane.closed_gramplets.append(self)
self.mainframe.get_parent().remove(self.mainframe)
def detach(self):
"""
Detach the gramplet from the GrampletView, and open in own window.
"""
# hide buttons:
#self.set_state("detached")
self.pane.detached_gramplets.append(self)
# make a window, and attach it there
self.detached_window = GrampletWindow(self)
def set_state(self, state):
"""
Set the state of a gramplet.
"""
oldstate = self.gstate
self.gstate = state
if state == "minimized":
self.scrolledwindow.hide()
self.xml.get_object('gvstateimage').set_from_stock(gtk.STOCK_ADD,
gtk.ICON_SIZE_MENU)
column = self.mainframe.get_parent() # column
expand, fill, padding, pack = column.query_child_packing(self.mainframe)
column.set_child_packing(self.mainframe, False, fill, padding, pack)
else:
self.scrolledwindow.show()
self.xml.get_object('gvstateimage').set_from_stock(gtk.STOCK_REMOVE,
gtk.ICON_SIZE_MENU)
column = self.mainframe.get_parent() # column
expand, fill, padding, pack = column.query_child_packing(self.mainframe)
column.set_child_packing(self.mainframe,
self.expand,
fill,
padding,
pack)
if self.pui and self.pui.dirty:
self.pui.update()
def change_state(self, obj):
"""
Change the state of a gramplet.
"""
if self.gstate == "detached":
pass # don't change if detached
else:
if self.gstate == "maximized":
self.set_state("minimized")
else:
self.set_state("maximized")
def set_properties(self, obj):
"""
Set the properties of a gramplet.
"""
if self.gstate == "detached":
pass
else:
self.detach()
return
self.expand = not self.expand
if self.gstate == "maximized":
column = self.mainframe.get_parent() # column
expand, fill, padding, pack = column.query_child_packing(self.mainframe)
column.set_child_packing(self.mainframe, self.expand, fill,
padding, pack)
def get_source_widget(self):
"""
Hack to allow us to send this object to the drop_widget
method as a context.
"""
return self.gvproperties
def get_container_widget(self):
return self.scrolledwindow
def get_title(self): def get_title(self):
return self.title return self.title
def set_height(self, height): def set_height(self, height):
self.height = height self.height = height
self.scrolledwindow.set_size_request(-1, self.height) self.scrolledwindow.set_size_request(-1, self.height)
self.set_state(self.state) self.set_state(self.gstate)
def get_height(self): def get_height(self):
return self.height return self.height
@ -877,7 +899,7 @@ class GuiGramplet(object):
def set_expand(self, value): def set_expand(self, value):
self.expand = value self.expand = value
self.scrolledwindow.set_size_request(-1, self.height) self.scrolledwindow.set_size_request(-1, self.height)
self.set_state(self.state) self.set_state(self.gstate)
def set_title(self, new_title): def set_title(self, new_title):
# can't do it if already titled that way # can't do it if already titled that way
@ -889,7 +911,8 @@ class GuiGramplet(object):
self.detached_window.window.set_title("%s %s - Gramps" % self.detached_window.window.set_title("%s %s - Gramps" %
(new_title, _("Gramplet"))) (new_title, _("Gramplet")))
self.pane.gramplet_map[self.title] = self self.pane.gramplet_map[self.title] = self
self.titlelabel.get_children()[0].set_text("<b><i>%s</i></b>" % self.title) self.titlelabel.get_children()[0].set_text("<b><i>%s</i></b>" %
self.title)
self.titlelabel.get_children()[0].set_use_markup(True) self.titlelabel.get_children()[0].set_use_markup(True)
return True return True
@ -931,7 +954,7 @@ class GrampletPane(gtk.ScrolledWindow):
self.columns = [] self.columns = []
for i in range(self.column_count): for i in range(self.column_count):
self.columns.append(gtk.VBox()) self.columns.append(gtk.VBox())
self.hbox.pack_start(self.columns[-1],expand=True) self.hbox.pack_start(self.columns[-1], expand=True)
# Load the gramplets # Load the gramplets
self.gramplet_map = {} # title->gramplet self.gramplet_map = {} # title->gramplet
self.frame_map = {} # frame->gramplet self.frame_map = {} # frame->gramplet
@ -957,8 +980,8 @@ class GrampletPane(gtk.ScrolledWindow):
self.gramplet_map[all_opts["title"]] = None # save closed name self.gramplet_map[all_opts["title"]] = None # save closed name
self.closed_opts.append(all_opts) self.closed_opts.append(all_opts)
continue continue
g = make_requested_gramplet(self, name, all_opts, g = make_requested_gramplet(GridGramplet, self, all_opts,
self.dbstate, self.uistate) self.dbstate, self.uistate)
if g: if g:
self.gramplet_map[all_opts["title"]] = g self.gramplet_map[all_opts["title"]] = g
self.frame_map[str(g.mainframe)] = g self.frame_map[str(g.mainframe)] = g
@ -973,7 +996,7 @@ class GrampletPane(gtk.ScrolledWindow):
""" """
super(GrampletPane, self).show_all() super(GrampletPane, self).show_all()
for gramplet in self.gramplet_map.values(): for gramplet in self.gramplet_map.values():
if gramplet.state == "minimized": if gramplet.gstate == "minimized":
gramplet.set_state("minimized") gramplet.set_state("minimized")
def set_state_all(self): def set_state_all(self):
@ -982,8 +1005,8 @@ class GrampletPane(gtk.ScrolledWindow):
parts of a collapsed gramplet on sidebars. parts of a collapsed gramplet on sidebars.
""" """
for gramplet in self.gramplet_map.values(): for gramplet in self.gramplet_map.values():
if gramplet.state in ["minimized", "maximized"]: if gramplet.gstate in ["minimized", "maximized"]:
gramplet.set_state(gramplet.state) gramplet.set_state(gramplet.gstate)
def get_column_frame(self, column_num): def get_column_frame(self, column_num):
if column_num < len(self.columns): if column_num < len(self.columns):
@ -998,7 +1021,7 @@ class GrampletPane(gtk.ScrolledWindow):
gramplets = (g for g in self.gramplet_map.itervalues() gramplets = (g for g in self.gramplet_map.itervalues()
if g is not None) if g is not None)
for gramplet in gramplets: for gramplet in gramplets:
if (gramplet.state == "detached" or gramplet.state == "closed"): if (gramplet.gstate == "detached" or gramplet.gstate == "closed"):
continue continue
column = gramplet.mainframe.get_parent() column = gramplet.mainframe.get_parent()
if column: if column:
@ -1025,21 +1048,23 @@ class GrampletPane(gtk.ScrolledWindow):
gramplet.column = pos gramplet.column = pos
gramplet.row = rows[gramplet.column] gramplet.row = rows[gramplet.column]
rows[gramplet.column] += 1 rows[gramplet.column] += 1
if recolumn and (gramplet.state == "detached" or gramplet.state == "closed"): if recolumn and (gramplet.gstate == "detached" or
gramplet.gstate == "closed"):
continue continue
if gramplet.state == "minimized": if gramplet.gstate == "minimized":
self.columns[pos].pack_start(gramplet.mainframe, expand=False) self.columns[pos].pack_start(gramplet.mainframe, expand=False)
else: else:
self.columns[pos].pack_start(gramplet.mainframe, expand=gramplet.expand) self.columns[pos].pack_start(gramplet.mainframe,
expand=gramplet.expand)
# set height on gramplet.scrolledwindow here: # set height on gramplet.scrolledwindow here:
gramplet.scrolledwindow.set_size_request(-1, gramplet.height) gramplet.scrolledwindow.set_size_request(-1, gramplet.height)
# Can't minimize here, because GRAMPS calls show_all later: # Can't minimize here, because GRAMPS calls show_all later:
#if gramplet.state == "minimized": # starts max, change to min it #if gramplet.gstate == "minimized": # starts max, change to min it
# gramplet.set_state("minimized") # minimize it # gramplet.set_state("minimized") # minimize it
# set minimized is called in page subclass hack (above) # set minimized is called in page subclass hack (above)
if gramplet.state == "detached": if gramplet.gstate == "detached":
gramplet.detach() gramplet.detach()
elif gramplet.state == "closed": elif gramplet.gstate == "closed":
gramplet.close() gramplet.close()
def load_gramplets(self): def load_gramplets(self):
@ -1068,10 +1093,11 @@ class GrampletPane(gtk.ScrolledWindow):
else: else:
data[opt] = cp.get(sec, opt).strip() data[opt] = cp.get(sec, opt).strip()
if "data" in data: if "data" in data:
data["data"] = [data["data"][key] for key in sorted(data["data"].keys())] data["data"] = [data["data"][key]
for key in sorted(data["data"].keys())]
if "name" not in data: if "name" not in data:
data["name"] = "Unnamed Gramplet" data["name"] = "Unnamed Gramplet"
data["tname"]= _("Unnamed Gramplet") data["tname"] = _("Unnamed Gramplet")
retval.append((data["name"], data)) # name, opts retval.append((data["name"], data)) # name, opts
else: else:
# give defaults as currently known # give defaults as currently known
@ -1086,11 +1112,12 @@ class GrampletPane(gtk.ScrolledWindow):
filename = self.configfile filename = self.configfile
try: try:
fp = open(filename, "w") fp = open(filename, "w")
except: except IOError:
print "Failed writing '%s'; gramplets not saved" % filename print "Failed writing '%s'; gramplets not saved" % filename
return return
fp.write(";; Gramps gramplets file" + NL) fp.write(";; Gramps gramplets file" + NL)
fp.write((";; Automatically created at %s" % time.strftime("%Y/%m/%d %H:%M:%S")) + NL + NL) fp.write((";; Automatically created at %s" %
time.strftime("%Y/%m/%d %H:%M:%S")) + NL + NL)
fp.write("[Gramplet View Options]" + NL) fp.write("[Gramplet View Options]" + NL)
fp.write(("column_count=%d" + NL) % self.column_count) fp.write(("column_count=%d" + NL) % self.column_count)
fp.write(("pane_position=%d" + NL) % self.pane_position) fp.write(("pane_position=%d" + NL) % self.pane_position)
@ -1101,7 +1128,7 @@ class GrampletPane(gtk.ScrolledWindow):
row = 0 row = 0
for gframe in self.columns[col]: for gframe in self.columns[col]:
gramplet = self.frame_map[str(gframe)] gramplet = self.frame_map[str(gframe)]
opts = get_gramplet_options_by_name(gramplet.name) opts = get_gramplet_options_by_name(gramplet.gname)
if opts is not None: if opts is not None:
base_opts = opts.copy() base_opts = opts.copy()
for key in base_opts: for key in base_opts:
@ -1117,7 +1144,8 @@ class GrampletPane(gtk.ScrolledWindow):
elif key == "gramps": continue # code, don't save elif key == "gramps": continue # code, don't save
elif key == "data": elif key == "data":
if not isinstance(base_opts["data"], (list, tuple)): if not isinstance(base_opts["data"], (list, tuple)):
fp.write(("data[0]=%s" + NL) % base_opts["data"]) fp.write(("data[0]=%s" + NL) %
base_opts["data"])
else: else:
cnt = 0 cnt = 0
for item in base_opts["data"]: for item in base_opts["data"]:
@ -1130,7 +1158,7 @@ class GrampletPane(gtk.ScrolledWindow):
fp.write(NL) fp.write(NL)
row += 1 row += 1
for gramplet in self.detached_gramplets: for gramplet in self.detached_gramplets:
opts = get_gramplet_options_by_name(gramplet.name) opts = get_gramplet_options_by_name(gramplet.gname)
if opts is not None: if opts is not None:
base_opts = opts.copy() base_opts = opts.copy()
for key in base_opts: for key in base_opts:
@ -1188,13 +1216,13 @@ class GrampletPane(gtk.ScrolledWindow):
maingramplet.column = col maingramplet.column = col
maingramplet.row = current_row maingramplet.row = current_row
current_row += 1 current_row += 1
expand = maingramplet.state == "maximized" and maingramplet.expand expand = maingramplet.gstate == "maximized" and maingramplet.expand
self.columns[col].pack_start(mainframe, expand=expand) self.columns[col].pack_start(mainframe, expand=expand)
for gframe in stack: for gframe in stack:
gramplet = self.frame_map[str(gframe)] gramplet = self.frame_map[str(gframe)]
gramplet.row = current_row gramplet.row = current_row
current_row += 1 current_row += 1
expand = gramplet.state == "maximized" and gramplet.expand expand = gramplet.gstate == "maximized" and gramplet.expand
self.columns[col].pack_start(gframe, expand=expand) self.columns[col].pack_start(gframe, expand=expand)
return True return True
@ -1212,7 +1240,7 @@ class GrampletPane(gtk.ScrolledWindow):
for i in range(self.column_count): for i in range(self.column_count):
self.columns.append(gtk.VBox()) self.columns.append(gtk.VBox())
self.columns[-1].show() self.columns[-1].show()
self.hbox.pack_start(self.columns[-1],expand=True) self.hbox.pack_start(self.columns[-1], expand=True)
# place the gramplets back in the new columns # place the gramplets back in the new columns
self.place_gramplets(recolumn=True) self.place_gramplets(recolumn=True)
self.show() self.show()
@ -1222,7 +1250,7 @@ class GrampletPane(gtk.ScrolledWindow):
############### First kind: from current session ############### First kind: from current session
for gramplet in self.closed_gramplets: for gramplet in self.closed_gramplets:
if gramplet.title == name: if gramplet.title == name:
#gramplet.state = "maximized" #gramplet.gstate = "maximized"
self.closed_gramplets.remove(gramplet) self.closed_gramplets.remove(gramplet)
if self._popup_xy is not None: if self._popup_xy is not None:
self.drop_widget(self, gramplet, self.drop_widget(self, gramplet,
@ -1235,8 +1263,8 @@ class GrampletPane(gtk.ScrolledWindow):
for opts in self.closed_opts: for opts in self.closed_opts:
if opts["title"] == name: if opts["title"] == name:
self.closed_opts.remove(opts) self.closed_opts.remove(opts)
g = make_requested_gramplet(self, opts["name"], opts, g = make_requested_gramplet(GridGramplet, self, opts,
self.dbstate, self.uistate) self.dbstate, self.uistate)
if g: if g:
self.gramplet_map[opts["title"]] = g self.gramplet_map[opts["title"]] = g
self.frame_map[str(g.mainframe)] = g self.frame_map[str(g.mainframe)] = g
@ -1244,12 +1272,13 @@ class GrampletPane(gtk.ScrolledWindow):
print "Can't make gramplet of type '%s'." % name print "Can't make gramplet of type '%s'." % name
if g: if g:
gramplet = g gramplet = g
gramplet.state = "maximized" gramplet.gstate = "maximized"
if gramplet.column >= 0 and gramplet.column < len(self.columns): if gramplet.column >= 0 and gramplet.column < len(self.columns):
pos = gramplet.column pos = gramplet.column
else: else:
pos = 0 pos = 0
self.columns[pos].pack_start(gramplet.mainframe, expand=gramplet.expand) self.columns[pos].pack_start(gramplet.mainframe,
expand=gramplet.expand)
# set height on gramplet.scrolledwindow here: # set height on gramplet.scrolledwindow here:
gramplet.scrolledwindow.set_size_request(-1, gramplet.height) gramplet.scrolledwindow.set_size_request(-1, gramplet.height)
## now drop it in right place ## now drop it in right place
@ -1276,8 +1305,8 @@ class GrampletPane(gtk.ScrolledWindow):
cnt += 1 cnt += 1
all_opts["title"] = unique all_opts["title"] = unique
if all_opts["title"] not in self.gramplet_map: if all_opts["title"] not in self.gramplet_map:
g = make_requested_gramplet(self, name, all_opts, g = make_requested_gramplet(GridGramplet, self, all_opts,
self.dbstate, self.uistate) self.dbstate, self.uistate)
if g: if g:
self.gramplet_map[all_opts["title"]] = g self.gramplet_map[all_opts["title"]] = g
self.frame_map[str(g.mainframe)] = g self.frame_map[str(g.mainframe)] = g
@ -1286,7 +1315,8 @@ class GrampletPane(gtk.ScrolledWindow):
pos = gramplet.column pos = gramplet.column
else: else:
pos = 0 pos = 0
self.columns[pos].pack_start(gramplet.mainframe, expand=gramplet.expand) self.columns[pos].pack_start(gramplet.mainframe,
expand=gramplet.expand)
# set height on gramplet.scrolledwindow here: # set height on gramplet.scrolledwindow here:
gramplet.scrolledwindow.set_size_request(-1, gramplet.height) gramplet.scrolledwindow.set_size_request(-1, gramplet.height)
## now drop it in right place ## now drop it in right place
@ -1337,7 +1367,7 @@ class GrampletPane(gtk.ScrolledWindow):
def set_inactive(self): def set_inactive(self):
for title in self.gramplet_map: for title in self.gramplet_map:
if self.gramplet_map[title].pui: if self.gramplet_map[title].pui:
if self.gramplet_map[title].state != "detached": if self.gramplet_map[title].gstate != "detached":
self.gramplet_map[title].pui.active = False self.gramplet_map[title].pui.active = False
def set_active(self): def set_active(self):
@ -1345,7 +1375,7 @@ class GrampletPane(gtk.ScrolledWindow):
if self.gramplet_map[title].pui: if self.gramplet_map[title].pui:
self.gramplet_map[title].pui.active = True self.gramplet_map[title].pui.active = True
if self.gramplet_map[title].pui.dirty: if self.gramplet_map[title].pui.dirty:
if self.gramplet_map[title].state == "maximized": if self.gramplet_map[title].gstate == "maximized":
self.gramplet_map[title].pui.update() self.gramplet_map[title].pui.update()
def on_delete(self): def on_delete(self):
@ -1375,7 +1405,7 @@ class GrampletPane(gtk.ScrolledWindow):
return [self.config_panel] + \ return [self.config_panel] + \
[self.build_panel(gramplet) for gramplet in [self.build_panel(gramplet) for gramplet in
sorted(self.gramplet_map.values(), key=lambda g: g.title) sorted(self.gramplet_map.values(), key=lambda g: g.title)
if gramplet.state != "closed"] if gramplet.gstate != "closed"]
return generate_pages return generate_pages
def get_columns(self): def get_columns(self):
@ -1405,8 +1435,8 @@ class GrampletPane(gtk.ScrolledWindow):
def build_panel(self, gramplet): def build_panel(self, gramplet):
# BEGIN WORKAROUND: # BEGIN WORKAROUND:
# This is necessary because gtk doesn't redisplay these widgets correctly # This is necessary because gtk doesn't redisplay these widgets
# so we replace them with new ones # correctly so we replace them with new ones
if gramplet.pui: if gramplet.pui:
gramplet.pui.save_options() gramplet.pui.save_options()
gramplet.pui.update_options = {} gramplet.pui.update_options = {}
@ -1418,9 +1448,11 @@ class GrampletPane(gtk.ScrolledWindow):
self._config.register("%s.height" % gramplet.title, self._config.register("%s.height" % gramplet.title,
int, gramplet.get_height, gramplet.set_height) int, gramplet.get_height, gramplet.set_height)
self._config.register("%s.detached_height" % gramplet.title, self._config.register("%s.detached_height" % gramplet.title,
int, gramplet.get_detached_height, gramplet.set_detached_height) int, gramplet.get_detached_height,
gramplet.set_detached_height)
self._config.register("%s.detached_width" % gramplet.title, self._config.register("%s.detached_width" % gramplet.title,
int, gramplet.get_detached_width, gramplet.set_detached_width) int, gramplet.get_detached_width,
gramplet.set_detached_width)
self._config.register("%s.expand" % gramplet.title, self._config.register("%s.expand" % gramplet.title,
bool, gramplet.get_expand, gramplet.set_expand) bool, gramplet.get_expand, gramplet.set_expand)
def gramplet_panel(configdialog): def gramplet_panel(configdialog):

View File

@ -0,0 +1,146 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2010 Doug Blank <doug.blank@gmail.com>
# Copyright (C) 2011 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$
#
#-------------------------------------------------------------------------
#
# Gramps modules
#
#-------------------------------------------------------------------------
from gen.plug import Gramplet
from Filters.SideBar import (PersonSidebarFilter, FamilySidebarFilter,
EventSidebarFilter, SourceSidebarFilter,
PlaceSidebarFilter, MediaSidebarFilter,
RepoSidebarFilter, NoteSidebarFilter)
#-------------------------------------------------------------------------
#
# Filter class
#
#-------------------------------------------------------------------------
class Filter(Gramplet):
"""
The base class for all filter gramplets.
"""
FILTER_CLASS = None
def init(self):
self.filter = self.FILTER_CLASS(self.dbstate, self.uistate,
self.__filter_clicked)
self.widget = self.filter.get_widget()
self.gui.get_container_widget().remove(self.gui.textview)
self.gui.get_container_widget().add_with_viewport(self.widget)
self.widget.show_all()
def __filter_clicked(self):
"""
Called when the filter apply button is clicked.
"""
self.gui.view.generic_filter = self.filter.get_filter()
self.gui.view.build_tree()
#-------------------------------------------------------------------------
#
# PersonFilter class
#
#-------------------------------------------------------------------------
class PersonFilter(Filter):
"""
A gramplet providing a Person Filter.
"""
FILTER_CLASS = PersonSidebarFilter
#-------------------------------------------------------------------------
#
# FamilyFilter class
#
#-------------------------------------------------------------------------
class FamilyFilter(Filter):
"""
A gramplet providing a Family Filter.
"""
FILTER_CLASS = FamilySidebarFilter
#-------------------------------------------------------------------------
#
# EventFilter class
#
#-------------------------------------------------------------------------
class EventFilter(Filter):
"""
A gramplet providing a Event Filter.
"""
FILTER_CLASS = EventSidebarFilter
#-------------------------------------------------------------------------
#
# SourceFilter class
#
#-------------------------------------------------------------------------
class SourceFilter(Filter):
"""
A gramplet providing a Source Filter.
"""
FILTER_CLASS = SourceSidebarFilter
#-------------------------------------------------------------------------
#
# PlaceFilter class
#
#-------------------------------------------------------------------------
class PlaceFilter(Filter):
"""
A gramplet providing a Place Filter.
"""
FILTER_CLASS = PlaceSidebarFilter
#-------------------------------------------------------------------------
#
# MediaFilter class
#
#-------------------------------------------------------------------------
class MediaFilter(Filter):
"""
A gramplet providing a Media Filter.
"""
FILTER_CLASS = MediaSidebarFilter
#-------------------------------------------------------------------------
#
# RepositoryFilter class
#
#-------------------------------------------------------------------------
class RepositoryFilter(Filter):
"""
A gramplet providing a Repository Filter.
"""
FILTER_CLASS = RepoSidebarFilter
#-------------------------------------------------------------------------
#
# NoteFilter class
#
#-------------------------------------------------------------------------
class NoteFilter(Filter):
"""
A gramplet providing a Note Filter.
"""
FILTER_CLASS = NoteSidebarFilter

View File

@ -41,7 +41,7 @@ class PersonAttributes(Gramplet):
""" """
tip = _('Double-click on a row to view a quick report showing ' tip = _('Double-click on a row to view a quick report showing '
'all people with the selected attribute.') 'all people with the selected attribute.')
self.gui.tooltip = tip self.set_tooltip(tip)
top = gtk.TreeView() top = gtk.TreeView()
titles = [(_('Key'), 1, 100), titles = [(_('Key'), 1, 100),
(_('Value'), 2, 100)] (_('Value'), 2, 100)]

View File

@ -42,7 +42,6 @@ class PersonDetails(Gramplet):
""" """
Build the GUI interface. Build the GUI interface.
""" """
self.gui.tooltip = ''
self.load_obj = None self.load_obj = None
self.load_rect = None self.load_rect = None
self.top = gtk.HBox() self.top = gtk.HBox()

View File

@ -39,7 +39,7 @@ class PersonGallery(Gramplet):
""" """
tip = _('Double-click on a picture to view it in the default image ' tip = _('Double-click on a picture to view it in the default image '
'viewer application.') 'viewer application.')
self.gui.tooltip = tip self.set_tooltip(tip)
self.image_list = [] self.image_list = []
self.top = gtk.HBox(False, 3) self.top = gtk.HBox(False, 3)
return self.top return self.top

View File

@ -42,7 +42,7 @@ class PersonResidence(Gramplet):
Build the GUI interface. Build the GUI interface.
""" """
tip = _('Double-click on a row to edit the selected event.') tip = _('Double-click on a row to edit the selected event.')
self.gui.tooltip = tip self.set_tooltip(tip)
top = gtk.TreeView() top = gtk.TreeView()
titles = [('', NOSORT, 50,), titles = [('', NOSORT, 50,),
(_('Date'), 1, 200), (_('Date'), 1, 200),

View File

@ -76,3 +76,107 @@ register(GRAMPLET,
gramplet = 'PersonAttributes', gramplet = 'PersonAttributes',
gramplet_title=_("Attributes"), gramplet_title=_("Attributes"),
) )
register(GRAMPLET,
id="Person Filter Gramplet",
name=_("Person Filter Gramplet"),
description = _("Gramplet providing a person filter"),
version="1.0.0",
gramps_target_version="3.3",
status = STABLE,
fname="Filter.py",
height=200,
gramplet = 'PersonFilter',
gramplet_title=_("Filter"),
)
register(GRAMPLET,
id="Family Filter Gramplet",
name=_("Family Filter Gramplet"),
description = _("Gramplet providing a family filter"),
version="1.0.0",
gramps_target_version="3.3",
status = STABLE,
fname="Filter.py",
height=200,
gramplet = 'FamilyFilter',
gramplet_title=_("Filter"),
)
register(GRAMPLET,
id="Event Filter Gramplet",
name=_("Event Filter Gramplet"),
description = _("Gramplet providing an event filter"),
version="1.0.0",
gramps_target_version="3.3",
status = STABLE,
fname="Filter.py",
height=200,
gramplet = 'EventFilter',
gramplet_title=_("Filter"),
)
register(GRAMPLET,
id="Source Filter Gramplet",
name=_("Source Filter Gramplet"),
description = _("Gramplet providing a source filter"),
version="1.0.0",
gramps_target_version="3.3",
status = STABLE,
fname="Filter.py",
height=200,
gramplet = 'SourceFilter',
gramplet_title=_("Filter"),
)
register(GRAMPLET,
id="Place Filter Gramplet",
name=_("Place Filter Gramplet"),
description = _("Gramplet providing a place filter"),
version="1.0.0",
gramps_target_version="3.3",
status = STABLE,
fname="Filter.py",
height=200,
gramplet = 'PlaceFilter',
gramplet_title=_("Filter"),
)
register(GRAMPLET,
id="Media Filter Gramplet",
name=_("Media Filter Gramplet"),
description = _("Gramplet providing a media filter"),
version="1.0.0",
gramps_target_version="3.3",
status = STABLE,
fname="Filter.py",
height=200,
gramplet = 'MediaFilter',
gramplet_title=_("Filter"),
)
register(GRAMPLET,
id="Repository Filter Gramplet",
name=_("Repository Filter Gramplet"),
description = _("Gramplet providing a repository filter"),
version="1.0.0",
gramps_target_version="3.3",
status = STABLE,
fname="Filter.py",
height=200,
gramplet = 'RepositoryFilter',
gramplet_title=_("Filter"),
)
register(GRAMPLET,
id="Note Filter Gramplet",
name=_("Note Filter Gramplet"),
description = _("Gramplet providing a note filter"),
version="1.0.0",
gramps_target_version="3.3",
status = STABLE,
fname="Filter.py",
height=200,
gramplet = 'NoteFilter',
gramplet_title=_("Filter"),
)

View File

@ -445,7 +445,7 @@ class BasePersonView(ListView):
""" """
Define the default gramplets for the sidebar and bottombar. Define the default gramplets for the sidebar and bottombar.
""" """
return (("Welcome Gramplet",), return (("Person Filter Gramplet",),
("Person Details Gramplet", ("Person Details Gramplet",
"Person Gallery Gramplet", "Person Gallery Gramplet",
"Person Residence Gramplet", "Person Residence Gramplet",

View File

@ -420,5 +420,12 @@ class PlaceBaseView(ListView):
else: else:
return None return None
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
"""
return (("Place Filter Gramplet",),
())
def make_callback(func, val): def make_callback(func, val):
return lambda x: func(val) return lambda x: func(val)

View File

@ -284,3 +284,9 @@ class EventView(ListView):
""" """
pass pass
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
"""
return (("Event Filter Gramplet",),
())

View File

@ -338,3 +338,10 @@ class FamilyView(ListView):
family = self.dbstate.db.get_family_from_handle(family_handle) family = self.dbstate.db.get_family_from_handle(family_handle)
family.add_tag(tag_handle) family.add_tag(tag_handle)
self.dbstate.db.commit_family(family, transaction) self.dbstate.db.commit_family(family, transaction)
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
"""
return (("Family Filter Gramplet",),
())

View File

@ -77,7 +77,6 @@ from PlaceUtils import conv_lat_lon
from gui.views.navigationview import NavigationView from gui.views.navigationview import NavigationView
from gui.editors import EditPlace from gui.editors import EditPlace
from gui.selectors.selectplace import SelectPlace from gui.selectors.selectplace import SelectPlace
from Filters.SideBar import PlaceSidebarFilter, EventSidebarFilter
import Bookmarks import Bookmarks
from Utils import navigation_label from Utils import navigation_label
@ -424,7 +423,8 @@ class GeoView(HtmlView):
) )
self.side = None self.side = None
self.bottom = None self.bottom = None
self.add_filter(PlaceSidebarFilter) self.sidebar.remove_gramplet('Event Filter Gramplet')
self.sidebar.add_gramplet('Place Filter Gramplet')
return HtmlView.build_widget(self) return HtmlView.build_widget(self)
def can_configure(self): def can_configure(self):
@ -889,7 +889,7 @@ class GeoView(HtmlView):
self.width = (widget.parent.parent.get_allocation().width - self.width = (widget.parent.parent.get_allocation().width -
widget.parent.parent.get_child2().get_allocation().width - 30) widget.parent.parent.get_child2().get_allocation().width - 30)
if not self.sidebar.is_visible(): if not self.sidebar.get_property('visible'):
if self.side is not None: if self.side is not None:
self.width = widget.parent.parent.get_allocation().width - 24 self.width = widget.parent.parent.get_allocation().width - 24
else: else:
@ -899,7 +899,7 @@ class GeoView(HtmlView):
else: else:
_LOG.debug("Sidebar : map width=%d" % self.width) _LOG.debug("Sidebar : map width=%d" % self.width)
if not self.bottombar.is_visible(): if not self.bottombar.get_property('visible'):
if self.bottom is not None: if self.bottom is not None:
self.height = (widget.parent.get_allocation().height self.height = (widget.parent.get_allocation().height
- self.header_size - 24) - self.header_size - 24)
@ -1223,9 +1223,9 @@ class GeoView(HtmlView):
Specifies the place for the home person to display with mapstraction. Specifies the place for the home person to display with mapstraction.
""" """
self.displaytype = "places" self.displaytype = "places"
self.remove_filter() self.sidebar.remove_gramplet('Event Filter Gramplet')
self.add_filter(PlaceSidebarFilter) self.sidebar.add_gramplet('Place Filter Gramplet')
self.widget.parent.parent.get_child2().show() #self.widget.parent.parent.get_child2().show()
self._geo_places() self._geo_places()
def _person_places(self, handle=None): # pylint: disable-msg=W0613 def _person_places(self, handle=None): # pylint: disable-msg=W0613
@ -1235,7 +1235,7 @@ class GeoView(HtmlView):
self.displaytype = "person" self.displaytype = "person"
if not self.uistate.get_active('Person'): if not self.uistate.get_active('Person'):
return return
self.widget.parent.parent.get_child2().hide() #self.widget.parent.parent.get_child2().hide()
self._geo_places() self._geo_places()
def _family_places(self, hanle=None): # pylint: disable-msg=W0613 def _family_places(self, hanle=None): # pylint: disable-msg=W0613
@ -1245,7 +1245,7 @@ class GeoView(HtmlView):
self.displaytype = "family" self.displaytype = "family"
if not self.uistate.get_active('Person'): if not self.uistate.get_active('Person'):
return return
self.widget.parent.parent.get_child2().hide() #self.widget.parent.parent.get_child2().hide()
self._geo_places() self._geo_places()
def _event_places(self, hanle=None): # pylint: disable-msg=W0613 def _event_places(self, hanle=None): # pylint: disable-msg=W0613
@ -1253,9 +1253,9 @@ class GeoView(HtmlView):
Specifies all event places to display with mapstraction. Specifies all event places to display with mapstraction.
""" """
self.displaytype = "event" self.displaytype = "event"
self.remove_filter() self.sidebar.remove_gramplet('Place Filter Gramplet')
self.add_filter(EventSidebarFilter) self.sidebar.add_gramplet('Event Filter Gramplet')
self.widget.parent.parent.get_child2().show() #self.widget.parent.parent.get_child2().show()
self._geo_places() self._geo_places()
def _new_database(self, database): def _new_database(self, database):

View File

@ -488,3 +488,10 @@ class MediaView(ListView):
media = self.dbstate.db.get_object_from_handle(media_handle) media = self.dbstate.db.get_object_from_handle(media_handle)
media.add_tag(tag_handle) media.add_tag(tag_handle)
self.dbstate.db.commit_media_object(media, transaction) self.dbstate.db.commit_media_object(media, transaction)
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
"""
return (("Media Filter Gramplet",),
())

View File

@ -293,3 +293,10 @@ class NoteView(ListView):
note = self.dbstate.db.get_note_from_handle(note_handle) note = self.dbstate.db.get_note_from_handle(note_handle)
note.add_tag(tag_handle) note.add_tag(tag_handle)
self.dbstate.db.commit_note(note, transaction) self.dbstate.db.commit_note(note, transaction)
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
"""
return (("Note Filter Gramplet",),
())

View File

@ -268,3 +268,10 @@ class RepositoryView(ListView):
As this submenu will be dynamically built, we offer a dummy action As this submenu will be dynamically built, we offer a dummy action
""" """
pass pass
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
"""
return (("Repository Filter Gramplet",),
())

View File

@ -245,3 +245,10 @@ class SourceView(ListView):
return obj.get_handle() return obj.get_handle()
else: else:
return None return None
def get_default_gramplets(self):
"""
Define the default gramplets for the sidebar and bottombar.
"""
return (("Source Filter Gramplet",),
())