Implement Gramps bottombar
svn: r16360
This commit is contained in:
parent
78cc4c3000
commit
e44dfa291e
@ -80,6 +80,7 @@ src/gen/plug/report/utils.py
|
||||
src/gen/proxy/private.py
|
||||
|
||||
# gui - GUI code
|
||||
src/gui/bottombar.py
|
||||
src/gui/columnorder.py
|
||||
src/gui/configure.py
|
||||
src/gui/dbloader.py
|
||||
@ -255,12 +256,16 @@ src/plugins/export/ExportXml.py
|
||||
src/plugins/gramplet/AgeOnDateGramplet.py
|
||||
src/plugins/gramplet/AgeStats.py
|
||||
src/plugins/gramplet/AttributesGramplet.py
|
||||
src/plugins/gramplet/bottombar.gpr.py
|
||||
src/plugins/gramplet/CalendarGramplet.py
|
||||
src/plugins/gramplet/DescendGramplet.py
|
||||
src/plugins/gramplet/FanChartGramplet.py
|
||||
src/plugins/gramplet/GivenNameGramplet.py
|
||||
src/plugins/gramplet/gramplet.gpr.py
|
||||
src/plugins/gramplet/PedigreeGramplet.py
|
||||
src/plugins/gramplet/PersonAttributes.py
|
||||
src/plugins/gramplet/PersonDetails.py
|
||||
src/plugins/gramplet/PersonResidence.py
|
||||
src/plugins/gramplet/QuickViewGramplet.py
|
||||
src/plugins/gramplet/RelativeGramplet.py
|
||||
src/plugins/gramplet/SessionLogGramplet.py
|
||||
|
@ -296,6 +296,7 @@ src/plugins/gramplet/DeepConnections.py
|
||||
src/plugins/gramplet/FaqGramplet.py
|
||||
src/plugins/gramplet/HeadlineNewsGramplet.py
|
||||
src/plugins/gramplet/NoteGramplet.py
|
||||
src/plugins/gramplet/PersonGallery.py
|
||||
src/plugins/gramplet/PluginManagerGramplet.py
|
||||
src/plugins/gramplet/PythonGramplet.py
|
||||
|
||||
|
@ -15,6 +15,7 @@ pkgdatadir = $(datadir)/@PACKAGE@/gui
|
||||
pkgdata_PYTHON = \
|
||||
__init__.py \
|
||||
basesidebar.py \
|
||||
bottombar.py \
|
||||
columnorder.py \
|
||||
configure.py \
|
||||
dbguielement.py \
|
||||
|
421
src/gui/bottombar.py
Normal file
421
src/gui/bottombar.py
Normal file
@ -0,0 +1,421 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# 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$
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Python modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
from gen.ggettext import gettext as _
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# GNOME modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import gtk
|
||||
import time
|
||||
import os
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Gramps modules
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
import ConfigParser
|
||||
import const
|
||||
from gui.widgets.grampletpane import (AVAILABLE_GRAMPLETS,
|
||||
GET_AVAILABLE_GRAMPLETS,
|
||||
get_gramplet_opts,
|
||||
get_gramplet_options_by_tname,
|
||||
get_gramplet_options_by_name,
|
||||
make_requested_gramplet)
|
||||
from ListModel import ListModel, NOSORT
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
NL = "\n"
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Bottombar class
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class Bottombar(object):
|
||||
"""
|
||||
A class which defines the graphical representation of the Gramps bottom bar.
|
||||
"""
|
||||
def __init__(self, dbstate, uistate, configfile, close_callback, defaults):
|
||||
|
||||
self.dbstate = dbstate
|
||||
self.uistate = uistate
|
||||
self.configfile = os.path.join(const.VERSION_DIR, "%s.ini" % configfile)
|
||||
self.close_callback = close_callback
|
||||
self.gramplet_map = {} # title->gramplet
|
||||
|
||||
self.top = gtk.HBox()
|
||||
self.notebook = gtk.Notebook()
|
||||
self.notebook.set_show_border(False)
|
||||
self.notebook.set_scrollable(True)
|
||||
self.notebook.connect('switch_page', self.__switch_page)
|
||||
|
||||
vbox = gtk.VBox()
|
||||
|
||||
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)
|
||||
vbox.pack_start(close_button, False)
|
||||
|
||||
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)
|
||||
vbox.pack_end(delete_button, False)
|
||||
|
||||
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)
|
||||
vbox.pack_end(add_button, False)
|
||||
|
||||
self.top.pack_start(self.notebook, True)
|
||||
self.top.pack_start(vbox, False)
|
||||
|
||||
vbox.show_all()
|
||||
self.notebook.show()
|
||||
|
||||
self.default_gramplets = defaults
|
||||
config_settings = self.load_gramplets()
|
||||
|
||||
for (name, opts) in config_settings[1]:
|
||||
all_opts = get_gramplet_opts(name, opts)
|
||||
gramplet = make_requested_gramplet(self, name, all_opts,
|
||||
self.dbstate, self.uistate)
|
||||
self.gramplet_map[all_opts["title"]] = gramplet
|
||||
|
||||
gramplets = [g for g in self.gramplet_map.itervalues()
|
||||
if g is not None]
|
||||
gramplets.sort(key=lambda x: x.page)
|
||||
for gramplet in gramplets:
|
||||
gramplet.scrolledwindow.set_size_request(-1, 200)
|
||||
self.notebook.append_page(gramplet.mainframe,
|
||||
gtk.Label(gramplet.title))
|
||||
self.notebook.set_tab_reorderable(gramplet.mainframe, True)
|
||||
|
||||
if config_settings[0][0]:
|
||||
self.top.show()
|
||||
self.notebook.set_current_page(config_settings[0][1])
|
||||
|
||||
def load_gramplets(self):
|
||||
"""
|
||||
Load the gramplets from the configuration file.
|
||||
"""
|
||||
retval = []
|
||||
visible = False
|
||||
default_page = 0
|
||||
filename = self.configfile
|
||||
if filename and os.path.exists(filename):
|
||||
cp = ConfigParser.ConfigParser()
|
||||
cp.read(filename)
|
||||
for sec in cp.sections():
|
||||
if sec == "Bar Options":
|
||||
if "visible" in cp.options(sec):
|
||||
visible = cp.get(sec, "visible") == "True"
|
||||
if "page" in cp.options(sec):
|
||||
default_page = int(cp.get(sec, "page"))
|
||||
else:
|
||||
data = {"title": sec}
|
||||
for opt in cp.options(sec):
|
||||
if opt.startswith("data["):
|
||||
temp = data.get("data", {})
|
||||
#temp.append(cp.get(sec, opt).strip())
|
||||
pos = int(opt[5:-1])
|
||||
temp[pos] = cp.get(sec, opt).strip()
|
||||
data["data"] = temp
|
||||
else:
|
||||
data[opt] = cp.get(sec, opt).strip()
|
||||
if "data" in data:
|
||||
data["data"] = [data["data"][key]
|
||||
for key in sorted(data["data"].keys())]
|
||||
if "name" not in data:
|
||||
data["name"] = "Unnamed Gramplet"
|
||||
data["tname"]= _("Unnamed Gramplet")
|
||||
retval.append((data["name"], data)) # name, opts
|
||||
else:
|
||||
# give defaults as currently known
|
||||
for name in self.default_gramplets:
|
||||
if name in AVAILABLE_GRAMPLETS():
|
||||
retval.append((name, GET_AVAILABLE_GRAMPLETS(name)))
|
||||
return ((visible, default_page), retval)
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Save the gramplet configuration.
|
||||
"""
|
||||
if len(self.gramplet_map) == 0:
|
||||
return # something is the matter
|
||||
filename = self.configfile
|
||||
try:
|
||||
fp = open(filename, "w")
|
||||
except:
|
||||
print "Failed writing '%s'; gramplets not saved" % filename
|
||||
return
|
||||
fp.write(";; Gramps bar configuration file" + NL)
|
||||
fp.write((";; Automatically created at %s" %
|
||||
time.strftime("%Y/%m/%d %H:%M:%S")) + NL + NL)
|
||||
fp.write("[Bar Options]" + NL)
|
||||
fp.write(("visible=%s" + NL) % self.top.get_property('visible'))
|
||||
fp.write(("page=%d" + NL) % self.notebook.get_current_page())
|
||||
fp.write(NL)
|
||||
|
||||
for page_num in range(self.notebook.get_n_pages()):
|
||||
title = get_title(self.notebook, page_num)
|
||||
gramplet = self.gramplet_map[title]
|
||||
|
||||
opts = get_gramplet_options_by_name(gramplet.name)
|
||||
if opts is not None:
|
||||
base_opts = opts.copy()
|
||||
for key in base_opts:
|
||||
if key in gramplet.__dict__:
|
||||
base_opts[key] = gramplet.__dict__[key]
|
||||
fp.write(("[%s]" + NL) % gramplet.title)
|
||||
for key in base_opts:
|
||||
if key == "content": continue
|
||||
elif key == "title": continue
|
||||
elif key == "row": 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":
|
||||
if not isinstance(base_opts["data"], (list, tuple)):
|
||||
fp.write(("data[0]=%s" + NL) % base_opts["data"])
|
||||
else:
|
||||
cnt = 0
|
||||
for item in base_opts["data"]:
|
||||
fp.write(("data[%d]=%s" + NL) % (cnt, item))
|
||||
cnt += 1
|
||||
else:
|
||||
fp.write(("%s=%s" + NL)% (key, base_opts[key]))
|
||||
fp.write(("page=%d" + NL) % page_num)
|
||||
fp.write(NL)
|
||||
|
||||
fp.close()
|
||||
|
||||
def set_active(self):
|
||||
"""
|
||||
Called with the view is set as active.
|
||||
"""
|
||||
page = self.notebook.get_current_page()
|
||||
title = get_title(self.notebook, page)
|
||||
if self.gramplet_map[title].pui:
|
||||
self.gramplet_map[title].pui.active = True
|
||||
if self.gramplet_map[title].pui.dirty:
|
||||
self.gramplet_map[title].pui.update()
|
||||
|
||||
def set_inactive(self):
|
||||
"""
|
||||
Called with the view is set as inactive.
|
||||
"""
|
||||
page = self.notebook.get_current_page()
|
||||
title = get_title(self.notebook, page)
|
||||
if self.gramplet_map[title].pui:
|
||||
if self.gramplet_map[title].state != "detached":
|
||||
self.gramplet_map[title].pui.active = False
|
||||
|
||||
def on_delete(self):
|
||||
"""
|
||||
Called when the view is closed.
|
||||
"""
|
||||
gramplets = (g for g in self.gramplet_map.itervalues()
|
||||
if g is not None)
|
||||
for gramplet in gramplets:
|
||||
# this is the only place where the gui runs user code directly
|
||||
if gramplet.pui:
|
||||
gramplet.pui.on_save()
|
||||
self.save()
|
||||
|
||||
def get_display(self):
|
||||
"""
|
||||
Return the top container widget for the GUI.
|
||||
"""
|
||||
return self.top
|
||||
|
||||
def show(self):
|
||||
"""
|
||||
Show the bottom bar.
|
||||
"""
|
||||
return self.top.show()
|
||||
|
||||
def hide(self):
|
||||
"""
|
||||
Hide the bottom bar.
|
||||
"""
|
||||
return self.top.hide()
|
||||
|
||||
def __close_clicked(self, button):
|
||||
"""
|
||||
Called when the sidebar is closed.
|
||||
"""
|
||||
self.close_callback()
|
||||
|
||||
def __add_clicked(self, button):
|
||||
"""
|
||||
Called when the add button is clicked.
|
||||
"""
|
||||
names = [GET_AVAILABLE_GRAMPLETS(key)["tname"] for key
|
||||
in AVAILABLE_GRAMPLETS()]
|
||||
skip = [gramplet.tname for gramplet in self.gramplet_map.values()]
|
||||
gramplet_list = [name for name in names if name not in skip]
|
||||
gramplet_list.sort()
|
||||
dialog = ChooseGrampletDialog(_("Select Gramplet"), gramplet_list)
|
||||
tname = dialog.run()
|
||||
if not tname:
|
||||
return
|
||||
|
||||
all_opts = get_gramplet_options_by_tname(tname)
|
||||
gramplet = make_requested_gramplet(self, all_opts["name"], all_opts,
|
||||
self.dbstate, self.uistate)
|
||||
if not gramplet:
|
||||
print "Problem creating ", tname
|
||||
return
|
||||
|
||||
title = all_opts["title"]
|
||||
self.gramplet_map[title] = gramplet
|
||||
gramplet.scrolledwindow.set_size_request(-1, gramplet.height)
|
||||
page_num = self.notebook.append_page(gramplet.mainframe,
|
||||
gtk.Label(title))
|
||||
self.notebook.set_tab_reorderable(gramplet.mainframe, True)
|
||||
self.notebook.set_current_page(page_num)
|
||||
|
||||
def __delete_clicked(self, button):
|
||||
"""
|
||||
Called when the delete button is clicked.
|
||||
"""
|
||||
page_num = self.notebook.get_current_page()
|
||||
title = get_title(self.notebook, page_num)
|
||||
del self.gramplet_map[title]
|
||||
self.notebook.remove_page(page_num)
|
||||
|
||||
def __switch_page(self, notebook, unused, new_page):
|
||||
"""
|
||||
Called when the user has switched to a new bottombar page.
|
||||
"""
|
||||
old_page = notebook.get_current_page()
|
||||
#print "switch from", old_page, "to", new_page
|
||||
if old_page >= 0:
|
||||
title = get_title(notebook, old_page)
|
||||
if self.gramplet_map[title].pui:
|
||||
if self.gramplet_map[title].state != "detached":
|
||||
self.gramplet_map[title].pui.active = False
|
||||
|
||||
title = get_title(notebook, new_page)
|
||||
if self.gramplet_map[title].pui:
|
||||
self.gramplet_map[title].pui.active = True
|
||||
if self.gramplet_map[title].pui.dirty:
|
||||
self.gramplet_map[title].pui.update()
|
||||
|
||||
def get_title(notebook, page_num):
|
||||
"""
|
||||
Reurn the title of a given page in a notebook.
|
||||
"""
|
||||
return notebook.get_tab_label_text(notebook.get_nth_page(page_num))
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Choose Gramplet Dialog
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
class ChooseGrampletDialog(object):
|
||||
"""
|
||||
A dialog to choose a gramplet
|
||||
"""
|
||||
def __init__(self, title, names):
|
||||
self.title = title
|
||||
self.names = names
|
||||
self.namelist = None
|
||||
self.namemodel = None
|
||||
self.top = self._create_dialog()
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Run the dialog and return the result.
|
||||
"""
|
||||
self._populate_model()
|
||||
response = self.top.run()
|
||||
result = None
|
||||
if response == gtk.RESPONSE_OK:
|
||||
store, iter_ = self.namemodel.get_selected()
|
||||
if iter_:
|
||||
result = store.get_value(iter_, 0)
|
||||
self.top.destroy()
|
||||
return result
|
||||
|
||||
def _populate_model(self):
|
||||
"""
|
||||
Populate the model.
|
||||
"""
|
||||
self.namemodel.clear()
|
||||
for name in self.names:
|
||||
self.namemodel.add([name])
|
||||
|
||||
def _create_dialog(self):
|
||||
"""
|
||||
Create a dialog box to organize tags.
|
||||
"""
|
||||
# pylint: disable-msg=E1101
|
||||
title = _("%(title)s - Gramps") % {'title': self.title}
|
||||
top = gtk.Dialog(title)
|
||||
top.set_default_size(400, 350)
|
||||
top.set_modal(True)
|
||||
top.set_has_separator(False)
|
||||
top.vbox.set_spacing(5)
|
||||
label = gtk.Label('<span size="larger" weight="bold">%s</span>'
|
||||
% self.title)
|
||||
label.set_use_markup(True)
|
||||
top.vbox.pack_start(label, 0, 0, 5)
|
||||
box = gtk.HBox()
|
||||
top.vbox.pack_start(box, 1, 1, 5)
|
||||
|
||||
name_titles = [(_('Name'), NOSORT, 200)]
|
||||
self.namelist = gtk.TreeView()
|
||||
self.namemodel = ListModel(self.namelist, name_titles)
|
||||
|
||||
slist = gtk.ScrolledWindow()
|
||||
slist.add_with_viewport(self.namelist)
|
||||
slist.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
box.pack_start(slist, 1, 1, 5)
|
||||
bbox = gtk.VButtonBox()
|
||||
bbox.set_layout(gtk.BUTTONBOX_START)
|
||||
bbox.set_spacing(6)
|
||||
top.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
top.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
|
||||
box.pack_start(bbox, 0, 0, 5)
|
||||
top.show_all()
|
||||
return top
|
||||
|
@ -50,6 +50,7 @@ import Errors
|
||||
from gui.dbguielement import DbGUIElement
|
||||
from gui.widgets.menutoolbuttonaction import MenuToolButtonAction
|
||||
from gui.sidebar import Sidebar
|
||||
from gui.bottombar import Bottombar
|
||||
from gui.widgets.grampletpane import GrampletPane
|
||||
from gui.configure import ConfigureDialog
|
||||
from config import config
|
||||
@ -116,6 +117,7 @@ class PageView(DbGUIElement):
|
||||
<menu action="ViewMenu">
|
||||
<placeholder name="Bars">
|
||||
<menuitem action="Sidebar"/>
|
||||
<menuitem action="Bottombar"/>
|
||||
</placeholder>
|
||||
</menu>
|
||||
</menubar>
|
||||
@ -150,6 +152,7 @@ class PageView(DbGUIElement):
|
||||
self.top = None
|
||||
self.gramplet_pane = None
|
||||
self.sidebar = None
|
||||
self.bottombar = None
|
||||
|
||||
DbGUIElement.__init__(self, dbstate.db)
|
||||
|
||||
@ -159,16 +162,22 @@ class PageView(DbGUIElement):
|
||||
Returns a gtk container widget.
|
||||
"""
|
||||
self.sidebar = Sidebar(self.sidebar_changed, self.sidebar_closed)
|
||||
defaults = self.get_default_gramplets()[1]
|
||||
self.bottombar = Bottombar(self.dbstate, self.uistate,
|
||||
self.ident + "_bottombar",
|
||||
self.bottombar_closed,
|
||||
defaults)
|
||||
hpane = gtk.HPaned()
|
||||
vpane = gtk.VPaned()
|
||||
hpane.pack1(vpane, resize=True, shrink=True)
|
||||
hpane.pack1(vpane, resize=True, shrink=False)
|
||||
hpane.pack2(self.sidebar.get_display(), resize=False, shrink=False)
|
||||
hpane.show()
|
||||
vpane.show()
|
||||
|
||||
widget = self.build_widget()
|
||||
widget.show_all()
|
||||
vpane.add1(widget)
|
||||
vpane.pack1(widget, resize=True, shrink=False)
|
||||
vpane.pack2(self.bottombar.get_display(), resize=False, shrink=False)
|
||||
initial_page = self._config.get('sidebar.page')
|
||||
|
||||
self.gramplet_pane = self.__create_gramplet_pane()
|
||||
@ -205,9 +214,11 @@ class PageView(DbGUIElement):
|
||||
"""
|
||||
Create a gramplet pane.
|
||||
"""
|
||||
defaults = self.get_default_gramplets()[0]
|
||||
gramplet_pane = GrampletPane(self.ident + "_sidebar",
|
||||
self, self.dbstate, self.uistate,
|
||||
column_count=1)
|
||||
column_count=1,
|
||||
default_gramplets=defaults)
|
||||
gramplet_pane.show_all()
|
||||
self.sidebar.add(_('Gramplets'), gramplet_pane, GRAMPLET_PAGE)
|
||||
return gramplet_pane
|
||||
@ -232,6 +243,17 @@ class PageView(DbGUIElement):
|
||||
self.sidebar_changed(None, False, None)
|
||||
self._config.set('sidebar.visible', active)
|
||||
|
||||
def __bottombar_toggled(self, action):
|
||||
"""
|
||||
Called when the bottombar is toggled.
|
||||
"""
|
||||
active = action.get_active()
|
||||
if active:
|
||||
self.bottombar.show()
|
||||
else:
|
||||
self.bottombar.hide()
|
||||
self._config.set('bottombar.visible', active)
|
||||
|
||||
def sidebar_changed(self, page_type, active, index):
|
||||
"""
|
||||
Called when the sidebar page is changed.
|
||||
@ -246,6 +268,23 @@ class PageView(DbGUIElement):
|
||||
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):
|
||||
"""
|
||||
Get the default gramplets for the Gramps sidebar and bottombar.
|
||||
Returns a 2-tuple. The first element is a tuple of sidebar gramplets
|
||||
and the second element is a tuple of bottombar gramplets.
|
||||
|
||||
Views should override this method to define default gramplets.
|
||||
"""
|
||||
return ((), ())
|
||||
|
||||
def key_press_handler(self, widget, event):
|
||||
"""
|
||||
A general keypress handler. Override if you want to handle
|
||||
@ -337,6 +376,7 @@ class PageView(DbGUIElement):
|
||||
then we rebuild the data.
|
||||
"""
|
||||
self.gramplet_pane.set_active()
|
||||
self.bottombar.set_active()
|
||||
self.active = True
|
||||
if self.dirty:
|
||||
self.uistate.set_busy_cursor(True)
|
||||
@ -348,6 +388,7 @@ class PageView(DbGUIElement):
|
||||
Marks page as being inactive (not currently displayed)
|
||||
"""
|
||||
self.gramplet_pane.set_inactive()
|
||||
self.bottombar.set_inactive()
|
||||
self.active = False
|
||||
|
||||
def build_tree(self):
|
||||
@ -443,6 +484,9 @@ class PageView(DbGUIElement):
|
||||
self._add_toggle_action('Sidebar', None, _('_Sidebar'),
|
||||
None, None, self.__sidebar_toggled,
|
||||
self._config.get('sidebar.visible'))
|
||||
self._add_toggle_action('Bottombar', None, _('_Bottombar'),
|
||||
None, None, self.__bottombar_toggled,
|
||||
self._config.get('bottombar.visible'))
|
||||
self._add_action("AddGramplet", gtk.STOCK_ADD, _("Add a gramplet"))
|
||||
self._add_action("RestoreGramplet", None, _("Restore a gramplet"))
|
||||
|
||||
@ -562,6 +606,7 @@ class PageView(DbGUIElement):
|
||||
that should be called when quiting the main application.
|
||||
"""
|
||||
self.gramplet_pane.on_delete()
|
||||
self.bottombar.on_delete()
|
||||
self._config.save()
|
||||
|
||||
def init_config(self):
|
||||
@ -584,8 +629,10 @@ class PageView(DbGUIElement):
|
||||
use_config_path=True)
|
||||
for section, value in self.CONFIGSETTINGS:
|
||||
self._config.register(section, value)
|
||||
self._config.register('sidebar.visible', True)
|
||||
self._config.register('sidebar.visible', False)
|
||||
self._config.register('sidebar.page', 0)
|
||||
self._config.register('bottombar.visible', False)
|
||||
self._config.register('bottombar.page', 0)
|
||||
self._config.init()
|
||||
self.config_connect()
|
||||
|
||||
|
@ -332,6 +332,7 @@ class GuiGramplet(object):
|
||||
self.detached_height = int(kwargs.get("detached_height", 300))
|
||||
self.detached_width = int(kwargs.get("detached_width", 400))
|
||||
self.row = int(kwargs.get("row", -1))
|
||||
self.page = int(kwargs.get("page", -1))
|
||||
self.state = kwargs.get("state", "maximized")
|
||||
self.data = kwargs.get("data", [])
|
||||
self.help_url = kwargs.get("help_url", WIKI_HELP_PAGE)
|
||||
@ -360,12 +361,16 @@ class GuiGramplet(object):
|
||||
self.titlelabel.get_children()[0].set_use_markup(True)
|
||||
self.titlelabel.connect("clicked", self.edit_title)
|
||||
self.titlelabel_entry = None
|
||||
self.titlelabel.hide()
|
||||
self.gvclose = self.xml.get_object('gvclose')
|
||||
self.gvclose.connect('clicked', self.close)
|
||||
self.gvclose.hide()
|
||||
self.gvstate = self.xml.get_object('gvstate')
|
||||
self.gvstate.connect('clicked', self.change_state)
|
||||
self.gvstate.hide()
|
||||
self.gvproperties = self.xml.get_object('gvproperties')
|
||||
self.gvproperties.connect('clicked', self.set_properties)
|
||||
self.gvproperties.hide()
|
||||
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,
|
||||
|
@ -9,6 +9,7 @@ pkgdata_PYTHON = \
|
||||
AgeOnDateGramplet.py \
|
||||
AgeStats.py \
|
||||
AttributesGramplet.py \
|
||||
bottombar.gpr.py \
|
||||
CalendarGramplet.py \
|
||||
DescendGramplet.py \
|
||||
FanChartGramplet.py \
|
||||
@ -16,6 +17,10 @@ pkgdata_PYTHON = \
|
||||
GivenNameGramplet.py \
|
||||
gramplet.gpr.py \
|
||||
PedigreeGramplet.py \
|
||||
PersonAttributes.py \
|
||||
PersonDetails.py \
|
||||
PersonGallery.py \
|
||||
PersonResidence.py \
|
||||
PluginManagerGramplet.py\
|
||||
QuickViewGramplet.py \
|
||||
RelativeGramplet.py \
|
||||
|
74
src/plugins/gramplet/PersonAttributes.py
Normal file
74
src/plugins/gramplet/PersonAttributes.py
Normal file
@ -0,0 +1,74 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# 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$
|
||||
#
|
||||
|
||||
from ListModel import ListModel, NOSORT
|
||||
from QuickReports import run_quick_report_by_name
|
||||
from gen.plug import Gramplet
|
||||
import gtk
|
||||
|
||||
class PersonAttributes(Gramplet):
|
||||
"""
|
||||
Displays the attributes of a person.
|
||||
"""
|
||||
def init(self):
|
||||
self.gui.WIDGET = self.build_gui()
|
||||
self.gui.get_container_widget().remove(self.gui.textview)
|
||||
self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET)
|
||||
self.gui.WIDGET.show()
|
||||
|
||||
def build_gui(self):
|
||||
"""
|
||||
Build the GUI interface.
|
||||
"""
|
||||
top = gtk.TreeView()
|
||||
titles = [(_('Key'), 1, 100),
|
||||
(_('Value'), 2, 100)]
|
||||
self.model = ListModel(top, titles, event_func=self.display_report)
|
||||
return top
|
||||
|
||||
def db_changed(self):
|
||||
self.dbstate.db.connect('person-update', self.update)
|
||||
self.update()
|
||||
|
||||
def active_changed(self, handle):
|
||||
self.update()
|
||||
|
||||
def main(self): # return false finishes
|
||||
active_handle = self.get_active('Person')
|
||||
active_person = self.dbstate.db.get_person_from_handle(active_handle)
|
||||
if not active_person:
|
||||
return
|
||||
|
||||
self.model.clear()
|
||||
for attr in active_person.get_attribute_list():
|
||||
self.model.add((attr.get_type(), attr.get_value()))
|
||||
|
||||
def display_report(self, treeview):
|
||||
"""
|
||||
Display the quick report for matching attribute key.
|
||||
"""
|
||||
model, iter_ = treeview.get_selection().get_selected()
|
||||
if iter_:
|
||||
key = model.get_value(iter_, 0)
|
||||
run_quick_report_by_name(self.dbstate,
|
||||
self.uistate,
|
||||
'attribute_match',
|
||||
key)
|
232
src/plugins/gramplet/PersonDetails.py
Normal file
232
src/plugins/gramplet/PersonDetails.py
Normal file
@ -0,0 +1,232 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# 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$
|
||||
#
|
||||
|
||||
from gen.lib import EventType, EventRoleType
|
||||
from gen.plug import Gramplet
|
||||
from gen.display.name import displayer as name_displayer
|
||||
from gen.ggettext import gettext as _
|
||||
import DateHandler
|
||||
import Utils
|
||||
import gtk
|
||||
import pango
|
||||
|
||||
class PersonDetails(Gramplet):
|
||||
"""
|
||||
Displays details for a person.
|
||||
"""
|
||||
def init(self):
|
||||
self.gui.WIDGET = self.build_gui()
|
||||
self.gui.get_container_widget().remove(self.gui.textview)
|
||||
self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET)
|
||||
self.gui.WIDGET.show()
|
||||
|
||||
def build_gui(self):
|
||||
"""
|
||||
Build the GUI interface.
|
||||
"""
|
||||
self.load_obj = None
|
||||
self.load_rect = None
|
||||
top = gtk.HBox()
|
||||
vbox = gtk.VBox()
|
||||
self.obj_photo = gtk.Image()
|
||||
self.name = gtk.Label()
|
||||
self.name.set_alignment(0, 0)
|
||||
self.name.modify_font(pango.FontDescription('sans bold 12'))
|
||||
vbox.pack_start(self.name, fill=True, expand=False, padding=10)
|
||||
table = gtk.Table(2, 2)
|
||||
self.father = self.make_row(table, 0, _('Father'))
|
||||
self.mother = self.make_row(table, 1, _('Mother'))
|
||||
vbox.pack_start(table, fill=True, expand=False, padding=5)
|
||||
table = gtk.Table(4, 2)
|
||||
self.birth = self.make_row(table, 0, _('Birth'))
|
||||
self.baptism = self.make_row(table, 1, _('Baptism'))
|
||||
self.death = self.make_row(table, 2, _('Death'))
|
||||
self.burial = self.make_row(table, 3, _('Burial'))
|
||||
vbox.pack_start(table, fill=True, expand=False, padding=5)
|
||||
table = gtk.Table(1, 2)
|
||||
self.occupation = self.make_row(table, 0, _('Occupation'))
|
||||
vbox.pack_start(table, fill=True, expand=False, padding=5)
|
||||
vbox.show_all()
|
||||
top.pack_start(self.obj_photo, fill=True, expand=False, padding=5)
|
||||
top.pack_start(vbox, fill=True, expand=True, padding=10)
|
||||
return top
|
||||
|
||||
def make_row(self, table, row, title):
|
||||
"""
|
||||
Make a row in a table.
|
||||
"""
|
||||
label = gtk.Label(title + ':')
|
||||
label.set_alignment(1, 0)
|
||||
widget = gtk.Label()
|
||||
widget.set_alignment(0, 0)
|
||||
table.attach(label, 0, 1, row, row + 1, xoptions=gtk.FILL, xpadding=10)
|
||||
table.attach(widget, 1, 2, row, row + 1)
|
||||
return (label, widget)
|
||||
|
||||
def db_changed(self):
|
||||
self.dbstate.db.connect('person-update', self.update)
|
||||
self.update()
|
||||
|
||||
def active_changed(self, handle):
|
||||
self.update()
|
||||
|
||||
def main(self): # return false finishes
|
||||
active_handle = self.get_active('Person')
|
||||
active_person = self.dbstate.db.get_person_from_handle(active_handle)
|
||||
if not active_person:
|
||||
return
|
||||
|
||||
self.load_person_image(active_person)
|
||||
self.name.set_text(name_displayer.display(active_person))
|
||||
self.display_parents(active_person)
|
||||
self.display_type(active_person, self.birth, EventType.BIRTH)
|
||||
self.display_type(active_person, self.baptism, EventType.BAPTISM)
|
||||
self.display_type(active_person, self.death, EventType.DEATH)
|
||||
self.display_type(active_person, self.burial, EventType.BURIAL)
|
||||
occupation_text = self.get_attribute(active_person, 'Occupation')
|
||||
self.occupation[1].set_text(occupation_text)
|
||||
|
||||
def display_parents(self, active_person):
|
||||
"""
|
||||
Display the parents of the active person.
|
||||
"""
|
||||
family_handle = active_person.get_main_parents_family_handle()
|
||||
if family_handle:
|
||||
family = self.dbstate.db.get_family_from_handle(family_handle)
|
||||
handle = family.get_father_handle()
|
||||
if handle:
|
||||
father = self.dbstate.db.get_person_from_handle(handle)
|
||||
self.father[1].set_text(name_displayer.display(father))
|
||||
else:
|
||||
self.father[1].set_text(_('Unknown'))
|
||||
handle = family.get_mother_handle()
|
||||
if handle:
|
||||
mother = self.dbstate.db.get_person_from_handle(handle)
|
||||
self.mother[1].set_text(name_displayer.display(mother))
|
||||
else:
|
||||
self.mother[1].set_text(_('Unknown'))
|
||||
else:
|
||||
self.father[1].set_text(_('Unknown'))
|
||||
self.mother[1].set_text(_('Unknown'))
|
||||
|
||||
def get_attribute(self, person, attr_key):
|
||||
"""
|
||||
Return an attribute with the given key.
|
||||
"""
|
||||
for attr in person.get_attribute_list():
|
||||
if attr.get_type() == attr_key:
|
||||
return attr.get_value()
|
||||
return _('Unknown')
|
||||
|
||||
def display_type(self, active_person, widget, event_type):
|
||||
"""
|
||||
Display an event type row.
|
||||
"""
|
||||
event = self.get_event(active_person, event_type)
|
||||
if event:
|
||||
widget[1].set_text(self.format_event(event))
|
||||
widget[0].show()
|
||||
widget[1].show()
|
||||
else:
|
||||
widget[1].set_text('')
|
||||
widget[0].hide()
|
||||
widget[1].hide()
|
||||
|
||||
def get_event(self, person, event_type):
|
||||
"""
|
||||
Return an event of the given type.
|
||||
"""
|
||||
for event_ref in person.get_event_ref_list():
|
||||
if int(event_ref.get_role()) == EventRoleType.PRIMARY:
|
||||
event = self.dbstate.db.get_event_from_handle(event_ref.ref)
|
||||
if int(event.get_type()) == event_type:
|
||||
return event
|
||||
return None
|
||||
|
||||
def format_event(self, event):
|
||||
"""
|
||||
Format the event for display.
|
||||
"""
|
||||
date = DateHandler.get_date(event)
|
||||
handle = event.get_place_handle()
|
||||
if handle:
|
||||
place = self.dbstate.db.get_place_from_handle(handle).get_title()
|
||||
retval = _('%s - %s.') % (date, place)
|
||||
else:
|
||||
retval = _('%s.') % date
|
||||
return retval
|
||||
|
||||
def load_person_image(self, person):
|
||||
"""
|
||||
Load the primary image if it exists.
|
||||
"""
|
||||
media_list = person.get_media_list()
|
||||
if media_list:
|
||||
photo = media_list[0]
|
||||
object_handle = photo.get_reference_handle()
|
||||
obj = self.dbstate.db.get_object_from_handle(object_handle)
|
||||
full_path = Utils.media_path_full(self.dbstate.db, obj.get_path())
|
||||
#reload if different media, or different rectangle
|
||||
if self.load_obj != full_path or \
|
||||
self.load_rect != photo.get_rectangle():
|
||||
mime_type = obj.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
self.load_photo(full_path, photo.get_rectangle())
|
||||
else:
|
||||
self.load_photo(None)
|
||||
else:
|
||||
self.load_photo(None)
|
||||
|
||||
def load_photo(self, path, rectangle=None):
|
||||
"""
|
||||
Load, scale and display the person's main photo from the path.
|
||||
"""
|
||||
self.load_obj = path
|
||||
self.load_rect = rectangle
|
||||
if path is None:
|
||||
self.obj_photo.hide()
|
||||
else:
|
||||
try:
|
||||
i = gtk.gdk.pixbuf_new_from_file(path)
|
||||
width = i.get_width()
|
||||
height = i.get_height()
|
||||
|
||||
if rectangle is not None:
|
||||
upper_x = min(rectangle[0], rectangle[2])/100.
|
||||
lower_x = max(rectangle[0], rectangle[2])/100.
|
||||
upper_y = min(rectangle[1], rectangle[3])/100.
|
||||
lower_y = max(rectangle[1], rectangle[3])/100.
|
||||
sub_x = int(upper_x * width)
|
||||
sub_y = int(upper_y * height)
|
||||
sub_width = int((lower_x - upper_x) * width)
|
||||
sub_height = int((lower_y - upper_y) * height)
|
||||
if sub_width > 0 and sub_height > 0:
|
||||
i = i.subpixbuf(sub_x, sub_y, sub_width, sub_height)
|
||||
|
||||
ratio = float(max(i.get_height(), i.get_width()))
|
||||
scale = float(190.0)/ratio
|
||||
x = int(scale*(i.get_width()))
|
||||
y = int(scale*(i.get_height()))
|
||||
i = i.scale_simple(x, y, gtk.gdk.INTERP_BILINEAR)
|
||||
self.obj_photo.set_from_pixbuf(i)
|
||||
self.obj_photo.show()
|
||||
except:
|
||||
self.obj_photo.hide()
|
125
src/plugins/gramplet/PersonGallery.py
Normal file
125
src/plugins/gramplet/PersonGallery.py
Normal file
@ -0,0 +1,125 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# 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$
|
||||
#
|
||||
|
||||
from gui.utils import open_file_with_default_application
|
||||
from gen.plug import Gramplet
|
||||
import Utils
|
||||
import gtk
|
||||
|
||||
class PersonGallery(Gramplet):
|
||||
"""
|
||||
Displays details for a person.
|
||||
"""
|
||||
def init(self):
|
||||
self.gui.WIDGET = self.build_gui()
|
||||
self.gui.get_container_widget().remove(self.gui.textview)
|
||||
self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET)
|
||||
self.gui.WIDGET.show()
|
||||
|
||||
def build_gui(self):
|
||||
"""
|
||||
Build the GUI interface.
|
||||
"""
|
||||
self.image_list = []
|
||||
self.top = gtk.HBox(False, 3)
|
||||
return self.top
|
||||
|
||||
def db_changed(self):
|
||||
self.dbstate.db.connect('person-update', self.update)
|
||||
self.update()
|
||||
|
||||
def active_changed(self, handle):
|
||||
self.update()
|
||||
|
||||
def main(self): # return false finishes
|
||||
active_handle = self.get_active('Person')
|
||||
active_person = self.dbstate.db.get_person_from_handle(active_handle)
|
||||
if not active_person:
|
||||
return
|
||||
|
||||
self.clear_images()
|
||||
self.load_person_images(active_person)
|
||||
|
||||
def clear_images(self):
|
||||
"""
|
||||
Remove all images from the Gramplet.
|
||||
"""
|
||||
for image in self.image_list:
|
||||
self.top.remove(image)
|
||||
self.image_list = []
|
||||
|
||||
def load_person_images(self, person):
|
||||
"""
|
||||
Load the primary image into the main form if it exists.
|
||||
"""
|
||||
media_list = person.get_media_list()
|
||||
for photo in media_list:
|
||||
object_handle = photo.get_reference_handle()
|
||||
obj = self.dbstate.db.get_object_from_handle(object_handle)
|
||||
full_path = Utils.media_path_full(self.dbstate.db, obj.get_path())
|
||||
mime_type = obj.get_mime_type()
|
||||
if mime_type and mime_type.startswith("image"):
|
||||
pb = self.get_pixbuf(full_path, photo.get_rectangle())
|
||||
eb = gtk.EventBox()
|
||||
eb.connect('button-press-event', self.display_image, full_path)
|
||||
image = gtk.Image()
|
||||
eb.add(image)
|
||||
self.image_list.append(eb)
|
||||
image.set_from_pixbuf(pb)
|
||||
eb.show_all()
|
||||
self.top.pack_start(eb, expand=False, fill=False)
|
||||
|
||||
def display_image(self, widget, event, path):
|
||||
"""
|
||||
Display the image with the default application.
|
||||
"""
|
||||
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
|
||||
open_file_with_default_application(path)
|
||||
|
||||
def get_pixbuf(self, path, rectangle=None):
|
||||
"""
|
||||
Load, scale and display the person's main photo from the path.
|
||||
"""
|
||||
try:
|
||||
i = gtk.gdk.pixbuf_new_from_file(path)
|
||||
width = i.get_width()
|
||||
height = i.get_height()
|
||||
|
||||
if rectangle is not None:
|
||||
upper_x = min(rectangle[0], rectangle[2])/100.
|
||||
lower_x = max(rectangle[0], rectangle[2])/100.
|
||||
upper_y = min(rectangle[1], rectangle[3])/100.
|
||||
lower_y = max(rectangle[1], rectangle[3])/100.
|
||||
sub_x = int(upper_x * width)
|
||||
sub_y = int(upper_y * height)
|
||||
sub_width = int((lower_x - upper_x) * width)
|
||||
sub_height = int((lower_y - upper_y) * height)
|
||||
if sub_width > 0 and sub_height > 0:
|
||||
i = i.subpixbuf(sub_x, sub_y, sub_width, sub_height)
|
||||
|
||||
ratio = float(max(i.get_height(), i.get_width()))
|
||||
scale = float(180.0)/ratio
|
||||
x = int(scale*(i.get_width()))
|
||||
y = int(scale*(i.get_height()))
|
||||
i = i.scale_simple(x, y, gtk.gdk.INTERP_BILINEAR)
|
||||
return i
|
||||
except:
|
||||
return None
|
92
src/plugins/gramplet/PersonResidence.py
Normal file
92
src/plugins/gramplet/PersonResidence.py
Normal file
@ -0,0 +1,92 @@
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# 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$
|
||||
#
|
||||
|
||||
from gen.lib import EventType, EventRoleType
|
||||
from gui.editors import EditEvent
|
||||
from ListModel import ListModel, NOSORT
|
||||
from gen.plug import Gramplet
|
||||
import DateHandler
|
||||
import gtk
|
||||
|
||||
class PersonResidence(Gramplet):
|
||||
"""
|
||||
Displays residence events for a person.
|
||||
"""
|
||||
def init(self):
|
||||
self.gui.WIDGET = self.build_gui()
|
||||
self.gui.get_container_widget().remove(self.gui.textview)
|
||||
self.gui.get_container_widget().add_with_viewport(self.gui.WIDGET)
|
||||
self.gui.WIDGET.show()
|
||||
|
||||
def build_gui(self):
|
||||
"""
|
||||
Build the GUI interface.
|
||||
"""
|
||||
top = gtk.TreeView()
|
||||
titles = [('', NOSORT, 50,),
|
||||
(_('Date'), 1, 200),
|
||||
(_('Place'), 2, 200)]
|
||||
self.model = ListModel(top, titles, event_func=self.edit_event)
|
||||
return top
|
||||
|
||||
def db_changed(self):
|
||||
self.dbstate.db.connect('person-update', self.update)
|
||||
self.update()
|
||||
|
||||
def active_changed(self, handle):
|
||||
self.update()
|
||||
|
||||
def main(self): # return false finishes
|
||||
active_handle = self.get_active('Person')
|
||||
active_person = self.dbstate.db.get_person_from_handle(active_handle)
|
||||
if not active_person:
|
||||
return
|
||||
|
||||
self.model.clear()
|
||||
for event_ref in active_person.get_event_ref_list():
|
||||
if int(event_ref.get_role()) == EventRoleType.PRIMARY:
|
||||
event = self.dbstate.db.get_event_from_handle(event_ref.ref)
|
||||
if int(event.get_type()) == EventType.RESIDENCE:
|
||||
self.add_residence(event)
|
||||
|
||||
def add_residence(self, event):
|
||||
"""
|
||||
Add a residence event to the model.
|
||||
"""
|
||||
date = DateHandler.get_date(event)
|
||||
place = ''
|
||||
handle = event.get_place_handle()
|
||||
if handle:
|
||||
place = self.dbstate.db.get_place_from_handle(handle).get_title()
|
||||
self.model.add((event.get_handle(), date, place))
|
||||
|
||||
def edit_event(self, treeview):
|
||||
"""
|
||||
Edit the selected event.
|
||||
"""
|
||||
model, iter_ = treeview.get_selection().get_selected()
|
||||
if iter_:
|
||||
handle = model.get_value(iter_, 0)
|
||||
try:
|
||||
event = self.dbstate.db.get_event_from_handle(handle)
|
||||
EditEvent(self.dbstate, self.uistate, [], event)
|
||||
except Errors.WindowActiveError:
|
||||
pass
|
78
src/plugins/gramplet/bottombar.gpr.py
Normal file
78
src/plugins/gramplet/bottombar.gpr.py
Normal file
@ -0,0 +1,78 @@
|
||||
#
|
||||
# Gramps - a GTK+/GNOME based genealogy program
|
||||
#
|
||||
# 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$
|
||||
|
||||
#------------------------------------------------------------------------
|
||||
#
|
||||
# Register Gramplet
|
||||
#
|
||||
#------------------------------------------------------------------------
|
||||
register(GRAMPLET,
|
||||
id="Person Details Gramplet",
|
||||
name=_("Person Details Gramplet"),
|
||||
description = _("Gramplet showing details of a person"),
|
||||
version="1.0.0",
|
||||
gramps_target_version="3.3",
|
||||
status = STABLE,
|
||||
fname="PersonDetails.py",
|
||||
height=200,
|
||||
gramplet = 'PersonDetails',
|
||||
gramplet_title=_("Details"),
|
||||
)
|
||||
|
||||
register(GRAMPLET,
|
||||
id="Person Gallery Gramplet",
|
||||
name=_("Person Gallery Gramplet"),
|
||||
description = _("Gramplet showing media objects for a person"),
|
||||
version="1.0.0",
|
||||
gramps_target_version="3.3",
|
||||
status = STABLE,
|
||||
fname="PersonGallery.py",
|
||||
height=200,
|
||||
gramplet = 'PersonGallery',
|
||||
gramplet_title=_("Gallery"),
|
||||
)
|
||||
|
||||
register(GRAMPLET,
|
||||
id="Person Residence Gramplet",
|
||||
name=_("Person Residence Gramplet"),
|
||||
description = _("Gramplet showing residence events for a person"),
|
||||
version="1.0.0",
|
||||
gramps_target_version="3.3",
|
||||
status = STABLE,
|
||||
fname="PersonResidence.py",
|
||||
height=200,
|
||||
gramplet = 'PersonResidence',
|
||||
gramplet_title=_("Residence"),
|
||||
)
|
||||
|
||||
register(GRAMPLET,
|
||||
id="Person Attributes Gramplet",
|
||||
name=_("Person Attributes Gramplet"),
|
||||
description = _("Gramplet showing the attributes of a person"),
|
||||
version="1.0.0",
|
||||
gramps_target_version="3.3",
|
||||
status = STABLE,
|
||||
fname="PersonAttributes.py",
|
||||
height=200,
|
||||
gramplet = 'PersonAttributes',
|
||||
gramplet_title=_("Attributes"),
|
||||
)
|
@ -440,3 +440,13 @@ class BasePersonView(ListView):
|
||||
person = self.dbstate.db.get_person_from_handle(person_handle)
|
||||
person.add_tag(tag_handle)
|
||||
self.dbstate.db.commit_person(person, transaction)
|
||||
|
||||
def get_default_gramplets(self):
|
||||
"""
|
||||
Define the default gramplets for the sidebar and bottombar.
|
||||
"""
|
||||
return (("Welcome Gramplet",),
|
||||
("Person Details Gramplet",
|
||||
"Person Gallery Gramplet",
|
||||
"Person Residence Gramplet",
|
||||
"Person Attributes Gramplet"))
|
||||
|
Loading…
Reference in New Issue
Block a user