GEPS 014: Plugin registration and management

Also views are now plugins belonging to view category


svn: r13528
This commit is contained in:
Benny Malengier
2009-11-08 16:41:49 +00:00
parent eea7ba35c7
commit 19522ec975
51 changed files with 588 additions and 354 deletions

View File

@@ -0,0 +1,35 @@
# This is the src/plugins/quickview level Makefile for Gramps
# We could use GNU make's ':=' syntax for nice wildcard use,
# but that is not necessarily portable.
# If not using GNU make, then list all .py files individually
pkgdatadir = $(datadir)/@PACKAGE@/plugins/view
pkgdata_PYTHON = \
eventview.py \
familyview.py \
geoview.py \
geoview.gpr.py \
grampletview.py \
htmlrenderer \
mediaview.py \
noteview.py \
pedigreeview.py \
personview.py \
placeview.py \
relview.py \
repoview.py \
sourceview.py \
view.gpr.py
pkgpyexecdir = @pkgpyexecdir@/plugins/view
pkgpythondir = @pkgpythondir@/plugins/view
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo
GRAMPS_PY_MODPATH = "../../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));

View File

@@ -0,0 +1,255 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2007 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
#
# 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$
"""
Provide the event view.
"""
#-------------------------------------------------------------------------
#
# Standard python modules
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import logging
_LOG = logging.getLogger(".plugins.eventview")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import gen.lib
from gui.views.listview import ListView
from gui.views.treemodels import EventModel
import Utils
import Errors
import Bookmarks
import config
from DdTargets import DdTargets
from Editors import EditEvent, DelEventQuery
from Filters.SideBar import EventSidebarFilter
from gen.plug import CATEGORY_QR_EVENT
#-------------------------------------------------------------------------
#
# EventView
#
#-------------------------------------------------------------------------
class EventView(ListView):
"""
EventView class, derived from the ListView
"""
COLUMN_NAMES = [
_('Description'),
_('ID'),
_('Type'),
_('Date'),
_('Place'),
_('Last Changed'),
_('Main Participants'),
]
ADD_MSG = _("Add a new event")
EDIT_MSG = _("Edit the selected event")
DEL_MSG = _("Delete the selected event")
FILTER_TYPE = "Event"
QR_CATEGORY = CATEGORY_QR_EVENT
def __init__(self, dbstate, uistate):
"""
Create the Event View
"""
signal_map = {
'event-add' : self.row_add,
'event-update' : self.row_update,
'event-delete' : self.row_delete,
'event-rebuild' : self.object_build,
}
ListView.__init__(
self, _('Events'), dbstate, uistate,
EventView.COLUMN_NAMES, len(EventView.COLUMN_NAMES),
EventModel,
signal_map, dbstate.db.get_event_bookmarks(),
Bookmarks.EventBookmarks,
multiple=True,
filter_class=EventSidebarFilter)
self.func_list = {
'<CONTROL>J' : self.jump,
'<CONTROL>BackSpace' : self.key_delete,
}
config.connect("interface.filter",
self.filter_toggle)
def column_ord_setfunc(self, clist):
self.dbstate.db.set_event_column_order(clist)
def get_bookmarks(self):
"""
Return the bookmark object
"""
return self.dbstate.db.get_event_bookmarks()
def drag_info(self):
"""
Indicate that the drag type is an EVENT
"""
return DdTargets.EVENT
def column_order(self):
"""
returns a tuple indicating the column order
"""
return self.dbstate.db.get_event_column_order()
def get_stock(self):
"""
Use the gramps-event stock icon
"""
return 'gramps-event'
def ui_definition(self):
"""
Defines the UI string for UIManager
"""
return '''<ui>
<menubar name="MenuBar">
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
<menu action="FileMenu">
<placeholder name="LocalExport">
<menuitem action="ExportTab"/>
</placeholder>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</placeholder>
<menuitem action="ColumnEdit"/>
<menuitem action="FilterEdit"/>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonEdit">
<toolitem action="Add"/>
<toolitem action="Edit"/>
<toolitem action="Remove"/>
</placeholder>
</toolbar>
<popup name="Popup">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
<separator/>
<menu name="QuickReport" action="QuickReport">
<menuitem action="Dummy"/>
</menu>
</popup>
</ui>'''
def define_actions(self):
ListView.define_actions(self)
self._add_action('FilterEdit', None, _('Event Filter Editor'),
callback=self.filter_editor,)
self._add_action('ColumnEdit', gtk.STOCK_PROPERTIES,
_('_Column Editor'), callback=self._column_editor,)
self._add_action('QuickReport', None,
_("Quick View"), None, None, None)
self._add_action('Dummy', None,
' ', None, None, self.dummy_report)
def get_handle_from_gramps_id(self, gid):
obj = self.dbstate.db.get_event_from_gramps_id(gid)
if obj:
return obj.get_handle()
else:
return None
def _column_editor(self, obj):
"""
returns a tuple indicating the column order
"""
import ColumnOrder
ColumnOrder.ColumnOrder(
_('Select Event Columns'),
self.uistate,
self.dbstate.db.get_event_column_order(),
EventView.COLUMN_NAMES,
self.set_column_order)
def add(self, obj):
try:
EditEvent(self.dbstate, self.uistate, [], gen.lib.Event())
except Errors.WindowActiveError:
pass
def remove(self, obj):
self.remove_selected_objects()
def remove_object_from_handle(self, handle):
person_list = [
item[1] for item in
self.dbstate.db.find_backlink_handles(handle,['Person']) ]
family_list = [
item[1] for item in
self.dbstate.db.find_backlink_handles(handle,['Family']) ]
object = self.dbstate.db.get_event_from_handle(handle)
query = DelEventQuery(self.dbstate, self.uistate, object,
person_list, family_list)
is_used = len(person_list) + len(family_list) > 0
return (query, is_used, object)
def edit(self, obj):
for handle in self.selected_handles():
event = self.dbstate.db.get_event_from_handle(handle)
try:
EditEvent(self.dbstate, self.uistate, [], event)
except Errors.WindowActiveError:
pass
def dummy_report(self, obj):
""" For the xml UI definition of popup to work, the submenu
Quick Report must have an entry in the xml
As this submenu will be dynamically built, we offer a dummy action
"""
pass

View File

@@ -0,0 +1,230 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
#
# 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$
"""
Family View.
"""
#-------------------------------------------------------------------------
#
# Standard python modules
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import logging
_LOG = logging.getLogger(".plugins.eventview")
#-------------------------------------------------------------------------
#
# GNOME/GTK+ modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import gen.lib
from gui.views.listview import ListView
from gui.views.treemodels import FamilyModel
import Bookmarks
import Errors
import config
from Filters.SideBar import FamilySidebarFilter
from gen.plug import CATEGORY_QR_FAMILY
#-------------------------------------------------------------------------
#
# FamilyView
#
#-------------------------------------------------------------------------
class FamilyView(ListView):
COLUMN_NAMES = [
_('ID'),
_('Father'),
_('Mother'),
_('Relationship'),
_('Marriage Date'),
_('Last Changed'),
]
ADD_MSG = _("Add a new family")
EDIT_MSG = _("Edit the selected family")
DEL_MSG = _("Delete the selected family")
FILTER_TYPE = "Family"
QR_CATEGORY = CATEGORY_QR_FAMILY
def __init__(self, dbstate, uistate):
signal_map = {
'family-add' : self.row_add,
'family-update' : self.row_update,
'family-delete' : self.row_delete,
'family-rebuild' : self.object_build,
}
ListView.__init__(
self, _('Families'), dbstate, uistate,
FamilyView.COLUMN_NAMES, len(FamilyView.COLUMN_NAMES),
FamilyModel,
signal_map, dbstate.db.get_family_bookmarks(),
Bookmarks.FamilyBookmarks, filter_class=FamilySidebarFilter)
self.func_list = {
'<CONTROL>J' : self.jump,
'<CONTROL>BackSpace' : self.key_delete,
}
config.connect("interface.filter",
self.filter_toggle)
def column_ord_setfunc(self, clist):
self.dbstate.db.set_family_list_column_order(clist)
def column_order(self):
return self.dbstate.db.get_family_list_column_order()
def _column_editor(self, obj):
import ColumnOrder
ColumnOrder.ColumnOrder(
_('Select Family Columns'),
self.uistate,
self.dbstate.db.get_family_list_column_order(),
FamilyView.COLUMN_NAMES,
self.set_column_order)
def get_stock(self):
return 'gramps-family'
def ui_definition(self):
return '''<ui>
<menubar name="MenuBar">
<menu action="FileMenu">
<placeholder name="LocalExport">
<menuitem action="ExportTab"/>
</placeholder>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</placeholder>
<menuitem action="ColumnEdit"/>
<menuitem action="FilterEdit"/>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonEdit">
<toolitem action="Add"/>
<toolitem action="Edit"/>
<toolitem action="Remove"/>
</placeholder>
</toolbar>
<popup name="Popup">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
<separator/>
<menu name="QuickReport" action="QuickReport">
<menuitem action="Dummy"/>
</menu>
</popup>
</ui>'''
def define_actions(self):
"""Add the Forward action group to handle the Forward button."""
ListView.define_actions(self)
self._add_action('ColumnEdit', gtk.STOCK_PROPERTIES,
_('_Column Editor...'), callback=self._column_editor)
self._add_action('FilterEdit', None, _('Family Filter Editor'),
callback=self.filter_editor,)
self.all_action = gtk.ActionGroup(self.title + "/FamilyAll")
self.all_action.add_actions([
('QuickReport', None, _("Quick View"), None, None, None),
('Dummy', None, ' ', None, None, self.dummy_report),
])
self._add_action_group(self.all_action)
def get_bookmarks(self):
return self.dbstate.db.get_family_bookmarks()
def add_bookmark(self, obj):
mlist = self.selected_handles()
if mlist:
self.bookmarks.add(mlist[0])
else:
from QuestionDialog import WarningDialog
WarningDialog(
_("Could Not Set a Bookmark"),
_("A bookmark could not be set because "
"no one was selected."))
def add(self, obj):
from Editors import EditFamily
family = gen.lib.Family()
try:
EditFamily(self.dbstate, self.uistate, [], family)
except Errors.WindowActiveError:
pass
def remove(self, obj):
from QuestionDialog import QuestionDialog2
from Utils import data_recover_msg
msg = _('Deleting item will remove it from the database.')
msg = msg + '\n' + data_recover_msg
q = QuestionDialog2(_('Delete %s?') % _('family'), msg,
_('_Delete Item'), _('Cancel'))
if q.run():
self.uistate.set_busy_cursor(1)
import gen.utils
for handle in self.selected_handles():
gen.utils.remove_family_relationships(self.dbstate.db, handle)
self.build_tree()
self.uistate.set_busy_cursor(0)
def edit(self, obj):
for handle in self.selected_handles():
from Editors import EditFamily
family = self.dbstate.db.get_family_from_handle(handle)
try:
EditFamily(self.dbstate, self.uistate, [], family)
except Errors.WindowActiveError:
pass
def dummy_report(self, obj):
""" For the xml UI definition of popup to work, the submenu
Quick Report must have an entry in the xml
As this submenu will be dynamically built, we offer a dummy action
"""
pass

View File

@@ -0,0 +1,69 @@
# encoding:utf-8
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2009 Benny Malengier
#
# 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$
#------------------------------------------------------------------------
#
# Geoview and HtmlView
#
#------------------------------------------------------------------------
TOOLKIT = NOWEB
try:
import webkit
TOOLKIT = WEBKIT
except:
try:
import gtkmozembed
TOOLKIT = MOZILLA
except:
pass
#no interfaces present, we do not register these plugins
if not (TOOLKIT == NOWEB):
register(VIEW,
id = 'geoview',
name = _("Geographic View"),
description = _("The view showing events on an interactive internet map "
"(internet connection needed"),
version = '1.0',
status = STABLE,
fname = 'geoview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_GEO,
viewclass = 'GeoView',
)
register(VIEW,
id = 'htmlview',
name = _("Html View"),
description = _("A view allowing to see html pages embedded in GRAMPS"),
version = '1.0',
status = UNSTABLE,
fname = 'htmlrenderer.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_MISC,
viewclass = 'HtmlView',
)

1855
src/plugins/view/geoview.py Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,652 @@
# -*- python -*-
# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2007-2009 Serge Noiraud
# Copyright (C) 2008 Benny Malengier
#
# 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: GeoView.py 12995 2009-08-13 21:59:59Z noirauds $
"""
Html Renderer
Can use the Webkit or Gecko ( Mozilla ) library
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import os
import locale
import urlparse
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Gramps Modules
#
#-------------------------------------------------------------------------
from gui.views.pageview import PageView
import Utils
import config
from const import TEMP_DIR
#-------------------------------------------------------------------------
#
# Functions
#
#-------------------------------------------------------------------------
def get_identity():
if Utils.lin():
platform = "X11"
elif Utils.win():
platform = "Windows"
elif Utils.mac():
platform = "Macintosh"
else:
platform = "Unknown"
(lang_country, modifier ) = locale.getlocale()
lang = lang_country.replace('_','-')
#lang += ", " + lang_country.split('_')[0]
return "Mozilla/5.0 (%s; U; %s) Gramps/3.2" % ( platform, lang)
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
# I think we should set the two following variable in const.py
# They are used only with gtkmozembed.
MOZEMBED_PATH = TEMP_DIR
MOZEMBED_SUBPATH = Utils.get_empty_tempdir('mozembed_gramps')
GEOVIEW_SUBPATH = Utils.get_empty_tempdir('geoview')
NOWEB = 0
WEBKIT = 1
MOZILLA = 2
KITNAME = [ "None", "WebKit", "Mozilla" ]
URL_SEP = '/'
#-------------------------------------------------------------------------
#
# What Web interfaces ?
#
# We use firstly webkit if it is present. If not, we use gtkmozembed.
# If no web interface is present, we don't register GeoView in the gui.
#-------------------------------------------------------------------------
TOOLKIT = NOWEB
try:
import webkit
TOOLKIT = WEBKIT
except:
try:
import gtkmozembed
TOOLKIT = MOZILLA
except:
pass
#no interfaces present, raise Error so that options for GeoView do not show
if TOOLKIT == NOWEB :
raise ImportError, 'No GTK html plugin found'
#-------------------------------------------------------------------------
#
# Renderer
#
#-------------------------------------------------------------------------
#class Renderer(object):
class Renderer():
"""
Renderer renders the webpage. Several backend implementations are
possible
"""
def __init__(self):
self.window = None
def get_window(self):
"""
Returns a container class with the widget that contains browser
window
"""
return self.window
def get_uri(self):
"""
Get the current url
"""
raise NotImplementedError
def show_all(self):
"""
show all in the main window.
"""
self.window.show_all()
def open(self, url):
"""
open the webpage at url
"""
raise NotImplementedError
def refresh(self):
"""
We need to reload the page.
"""
raise NotImplementedError
def go_back(self):
"""
Go to the previous page.
"""
self.window.go_back()
def can_go_back(self):
"""
is the browser able to go backward ?
"""
return self.window.can_go_back()
def go_forward(self):
"""
Go to the next page.
"""
self.window.go_forward()
def can_go_forward(self):
"""
is the browser able to go forward ?
"""
return self.window.can_go_forward()
def get_title(self):
"""
We need to get the html title page.
"""
raise NotImplementedError
def execute_script(self, url):
"""
execute javascript in the current html page
"""
raise NotImplementedError
def page_loaded(self, *args):
"""
The page is completely loaded.
"""
raise NotImplementedError
def set_button_sensitivity(self):
"""
We must set the back and forward button in the HtmlView class.
"""
raise NotImplementedError
#-------------------------------------------------------------------------
#
# Renderer with WebKit
#
#-------------------------------------------------------------------------
class RendererWebkit(Renderer):
"""
Implementation of Renderer with Webkit
"""
def __init__(self):
Renderer.__init__(self)
self.window = webkit.WebView()
try:
self.window.set_custom_encoding('utf-8') # needs webkit 1.1.10
except: # pylint: disable-msg=W0702
pass
settings = self.window.get_settings()
try:
proxy = os.environ['http_proxy']
# webkit use libsoup instead of libcurl.
#if proxy:
# settings.set_property("use-proxy", True)
except: # pylint: disable-msg=W0702
pass
#settings.set_property("ident-string", get_identity())
# do we need it ? Yes if webkit avoid to use local files for security
## The following available starting from WebKitGTK+ 1.1.13
#settings.set_property("enable-universal-access-from-file-uris", True)
self.browser = WEBKIT
self.title = None
self.frame = self.window.get_main_frame()
self.frame.connect("load-done", self.page_loaded)
self.frame.connect("title-changed", self.get_title)
self.fct = None
def page_loaded(self, *args):
"""
We just loaded one page in the browser.
Set the button sensitivity
"""
self.set_button_sensitivity()
def set_button_sensitivity(self):
"""
We must set the back and forward button in the HtmlView class.
"""
self.fct()
def open(self, url):
"""
We need to load the page in the browser.
"""
self.window.open(url)
def refresh(self):
"""
We need to reload the page in the browser.
"""
self.window.reload()
def get_title(self, *args):
"""
We need to get the html title page.
"""
self.title = self.frame.get_title()
def execute_script(self, url):
"""
We need to execute a javascript function into the browser
"""
self.window.execute_script(url)
def get_uri(self):
"""
What is the uri loaded in the browser ?
"""
return self.window.get_main_frame().get_uri()
#-------------------------------------------------------------------------
#
# The Mozilla or Gecko Renderer class
#
#-------------------------------------------------------------------------
class RendererMozilla(Renderer):
"""
Implementation of Renderer with gtkmozembed
"""
def __init__(self):
Renderer.__init__(self)
if hasattr(gtkmozembed, 'set_profile_path'):
set_profile_path = gtkmozembed.set_profile_path
else:
set_profile_path = gtkmozembed.gtk_moz_embed_set_profile_path
set_profile_path(MOZEMBED_PATH, MOZEMBED_SUBPATH)
self.__set_mozembed_proxy()
self.window = gtkmozembed.MozEmbed()
self.browser = MOZILLA
self.title = None
self.handler = self.window.connect("net-stop", self.page_loaded)
self.window.connect("title", self.get_title)
self.fct = None
def page_loaded(self, *args):
"""
We just loaded one page in the browser.
Set the button sensitivity
"""
self.set_button_sensitivity()
def set_button_sensitivity(self):
"""
We must set the back and forward button in the HtmlView class.
"""
self.fct()
def open(self, url):
"""
We need to load the page in the browser.
"""
self.window.load_url(url)
def get_title(self, *args):
"""
We need to get the html title page.
"""
self.title = self.window.get_title()
def execute_script(self, url):
"""
We need to execute a javascript function into the browser
"""
self.window.load_url(url)
def get_uri(self):
"""
What is the uri loaded in the browser ?
"""
return self.window.get_location()
def refresh(self):
"""
We need to reload the page in the browser.
"""
self.window.reload(0)
def __set_mozembed_proxy(self):
"""
Try to see if we have some proxy environment variable.
http_proxy in our case.
The standard format is : http://[user:password@]proxy:port/
"""
try:
proxy = os.environ['http_proxy']
if proxy:
host_port = None
prefs = open(os.path.join(MOZEMBED_SUBPATH,
"prefs.js"),
"w+")
parts = urlparse.urlparse(proxy)
if not parts[0] or parts[0] == 'http':
host_port = parts[1]
hport = host_port.split(':')
host = hport[0].strip()
if host:
try:
port = int(hport[1])
except:
user = host
uprox = hport[1].split('@')
password = uprox[0]
host = uprox[1]
port = int(hport[2])
if port and host:
port = str(port)
prefs.write('user_pref("network.proxy')
prefs.write('.type", 1);\r\n')
prefs.write('user_pref("network.proxy')
prefs.write('.http", "'+host+'");\r\n')
prefs.write('user_pref("network.proxy')
prefs.write('.http_port", '+port+');\r\n')
prefs.write('user_pref("network.proxy')
prefs.write('.no_proxies_on",')
prefs.write(' "127.0.0.1,localhost,localhost')
prefs.write('.localdomain");\r\n')
prefs.write('user_pref("network.proxy')
prefs.write('.share_proxy_settings", true);\r\n')
prefs.write('user_pref("network.http')
prefs.write('.proxy.pipelining", true);\r\n')
prefs.write('user_pref("network.http')
prefs.write('.proxy.keep-alive", true);\r\n')
prefs.write('user_pref("network.http')
prefs.write('.proxy.version", 1.1);\r\n')
prefs.write('user_pref("network.http')
prefs.write('.sendRefererHeader, 0);\r\n')
prefs.write('user_pref("general.useragent')
prefs.write('.extra.firefox, "Mozilla/5.0");\r\n')
prefs.write('user_pref("general.useragent')
prefs.write('.locale, "fr");\r\n')
prefs.close()
except:
try: # trying to remove pref.js in case of proxy change.
os.remove(os.path.join(MOZEMBED_SUBPATH, "prefs.js"))
except:
pass
#-------------------------------------------------------------------------
#
# HtmlView
#
#-------------------------------------------------------------------------
class HtmlView(PageView):
"""
HtmlView is a view showing a top widget with controls, and a bottom part
with an embedded webbrowser showing a given URL
"""
def __init__(self, dbstate, uistate, title=_('HtmlView')):
PageView.__init__(self, title, dbstate, uistate)
self.dbstate = dbstate
self.back_action = None
self.forward_action = None
self.renderer = None
self.urlfield = ""
self.htmlfile = ""
self.table = ""
self.browser = NOWEB
self.bootstrap_handler = None
self.box = None
def build_widget(self):
"""
Builds the interface and returns a gtk.Container type that
contains the interface. This containter will be inserted into
a gtk.Notebook page.
"""
self.box = gtk.VBox(False, 4)
#top widget at the top
self.box.pack_start(self.top_widget(), False, False, 0 )
#web page under it in a scrolled window
self.table = gtk.Table(1, 1, False)
frame = gtk.ScrolledWindow(None, None)
frame.set_shadow_type(gtk.SHADOW_NONE)
frame.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
frame.add_with_viewport(self.table)
self.bootstrap_handler = self.box.connect("size-request",
self.init_parent_signals_for_map)
self.table.get_parent().set_shadow_type(gtk.SHADOW_NONE)
self.table.set_row_spacings(1)
self.table.set_col_spacings(0)
if (TOOLKIT == WEBKIT) :
# We use webkit
self.renderer = RendererWebkit()
elif (TOOLKIT == MOZILLA) :
# We use gtkmozembed
self.renderer = RendererMozilla()
self.table.add(self.renderer.get_window())
self.box.pack_start(frame, True, True, 0)
# this is used to activate the back and forward button
# from the renderer class.
self.renderer.fct = self.set_button_sensitivity
self.renderer.show_all()
#load a welcome html page
urlhelp = self._create_start_page()
self.open(urlhelp)
return self.box
def top_widget(self):
"""
The default class gives a widget where user can type an url
"""
hbox = gtk.HBox(False, 4)
self.urlfield = gtk.Entry()
self.urlfield.set_text(config.get("htmlview.start-url"))
self.urlfield.connect('activate', self._on_activate)
hbox.pack_start(self.urlfield, True, True, 4)
button = gtk.Button(stock=gtk.STOCK_APPLY)
button.connect('clicked', self._on_activate)
hbox.pack_start(button, False, False, 4)
return hbox
def set_button_sensitivity(self):
"""
Set the backward and forward button in accordance to the browser.
"""
self.forward_action.set_sensitive(self.renderer.can_go_forward())
self.back_action.set_sensitive(self.renderer.can_go_back())
def open(self, url):
"""
open an url
"""
self.renderer.open(url)
def go_back(self, button):
"""
Go to the previous loaded url.
"""
self.renderer.go_back()
self.set_button_sensitivity()
self.external_uri()
def go_forward(self, button):
"""
Go to the next loaded url.
"""
self.renderer.go_forward()
self.set_button_sensitivity()
self.external_uri()
def refresh(self, button):
"""
Force to reload the page.
"""
self.renderer.refresh()
def external_uri(self):
"""
used to resize or not resize depending on external or local file.
"""
uri = self.renderer.get_uri()
def _on_activate(self, nobject):
"""
Here when we activate the url button.
"""
url = self.urlfield.get_text()
if url.find('://') == -1:
url = 'http://'+ url
self.open(url)
def build_tree(self):
"""
Rebuilds the current display. Called from ViewManager
"""
pass #htmlview is build on click and startup
def get_stock(self):
"""
Returns the name of the stock icon to use for the display.
This assumes that this icon has already been registered with
GNOME as a stock icon.
"""
return 'gramps-geo'
def ui_definition(self):
"""
Specifies the UIManager XML code that defines the menus and buttons
associated with the interface.
"""
return '''<ui>
<toolbar name="ToolBar">
<placeholder name="CommonNavigation">
<toolitem action="Back"/>
<toolitem action="Forward"/>
<toolitem action="Refresh"/>
</placeholder>
</toolbar>
</ui>'''
def define_actions(self):
"""
Required define_actions function for PageView. Builds the action
group information required.
"""
HtmlView._define_actions_fw_bw(self)
def _define_actions_fw_bw(self):
"""
prepare the forward and backward buttons.
add the Backward action to handle the Backward button
accel doesn't work in webkit and gtkmozembed !
we must do that ...
"""
self.back_action = gtk.ActionGroup(self.title + '/Back')
self.back_action.add_actions([
('Back', gtk.STOCK_GO_BACK, _("_Back"),
"<ALT>Left", _("Go to the previous page in the history"),
self.go_back)
])
self._add_action_group(self.back_action)
# add the Forward action to handle the Forward button
self.forward_action = gtk.ActionGroup(self.title + '/Forward')
self.forward_action.add_actions([
('Forward', gtk.STOCK_GO_FORWARD, _("_Forward"),
"<ALT>Right", _("Go to the next page in the history"),
self.go_forward)
])
self._add_action_group(self.forward_action)
# add the Refresh action to handle the Refresh button
self._add_action('Refresh', gtk.STOCK_REFRESH, _("_Refresh"),
callback=self.refresh,
accel="<Ctl>R",
tip=_("Stop and reload the page."))
def init_parent_signals_for_map(self, widget, event):
"""
Required to properly bootstrap the signal handlers.
This handler is connected by build_widget.
After the outside ViewManager has placed this widget we are
able to access the parent container.
"""
pass
def get_renderer(self):
"""
return the renderer : Webkit, Mozilla or None
"""
#return self.browser
return KITNAME[self.browser]
def _create_start_page(self):
"""
This command creates a default start page, and returns the URL of
this page.
"""
tmpdir = GEOVIEW_SUBPATH
data = """
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" \
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>%(title)s</title>
</head>
<body >
<H4>%(content)s</H4>
</body>
</html>
""" % { 'height' : 600,
'title' : _('Start page for the Html View'),
'content': _('Type a webpage address at the top, and hit'
' the execute button to load a webpage in this'
' page\n<br>\n'
'For example: <b>http://gramps-project.org</p>')
}
filename = os.path.join(tmpdir, 'startpage.html')
ufd = file(filename, "w+")
ufd.write(data)
ufd.close()
return urlparse.urlunsplit(('file', '',
URL_SEP.join(filename.split(os.sep)),
'', ''))

View File

@@ -0,0 +1,401 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
#
# 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$
"""
Media View.
"""
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import urlparse
import os
import cPickle as pickle
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
from gui.utils import open_file_with_default_application
from gui.views.listview import ListView
from gui.views.treemodels import MediaModel
import ThumbNails
import const
import config
import Utils
import Bookmarks
import Mime
import gen.lib
from Editors import EditMedia, DeleteMediaQuery
import Errors
from Filters.SideBar import MediaSidebarFilter
from DdTargets import DdTargets
#-------------------------------------------------------------------------
#
# MediaView
#
#-------------------------------------------------------------------------
class MediaView(ListView):
"""
Provide the Media View interface on the GRAMPS main window. This allows
people to manage all media items in their database. This is very similar
to the other list based views, with the exception that it also has a
thumbnail image at the top of the view that must be updated when the
selection changes or when the selected media object changes.
"""
COLUMN_NAMES = [
_('Title'),
_('ID'),
_('Type'),
_('Path'),
_('Last Changed'),
_('Date'),
]
ADD_MSG = _("Add a new media object")
EDIT_MSG = _("Edit the selected media object")
DEL_MSG = _("Delete the selected media object")
FILTER_TYPE = 'MediaObject'
_DND_TYPE = DdTargets.URI_LIST
def __init__(self, dbstate, uistate):
signal_map = {
'media-add' : self.row_add,
'media-update' : self.row_update,
'media-delete' : self.row_delete,
'media-rebuild' : self.object_build,
}
ListView.__init__(
self, _('Media'), dbstate, uistate,
MediaView.COLUMN_NAMES, len(MediaView.COLUMN_NAMES),
MediaModel,
signal_map, dbstate.db.get_media_bookmarks(),
Bookmarks.MediaBookmarks, filter_class=MediaSidebarFilter,
multiple=True)
self.func_list = {
'<CONTROL>J' : self.jump,
'<CONTROL>BackSpace' : self.key_delete,
}
config.connect("interface.filter",
self.filter_toggle)
def column_ord_setfunc(self, clist):
self.dbstate.db.set_media_column_order(clist)
def _set_dnd(self):
"""
Set up drag-n-drop. The source and destination are set by calling .target()
on the _DND_TYPE. Obviously, this means that there must be a _DND_TYPE
variable defined that points to an entry in DdTargets.
"""
dnd_types = [ self._DND_TYPE.target() ]
self.list.drag_dest_set(gtk.DEST_DEFAULT_ALL, dnd_types,
gtk.gdk.ACTION_COPY)
self.list.drag_source_set(gtk.gdk.BUTTON1_MASK,
[self._DND_TYPE.target()],
gtk.gdk.ACTION_COPY)
self.list.connect('drag_data_get', self.drag_data_get)
self.list.connect('drag_data_received', self.drag_data_received)
def drag_data_get(self, widget, context, sel_data, info, time):
"""
Provide the drag_data_get function, which passes a tuple consisting of:
1) Drag type defined by the .drag_type field specified by the value
assigned to _DND_TYPE
2) The id value of this object, used for the purpose of determining
the source of the object. If the source of the object is the same
as the object, we are doing a reorder instead of a normal drag
and drop
3) Pickled data. The pickled version of the selected object
4) Source row. Used for a reorder to determine the original position
of the object
"""
selected_ids = self.selected_handles()
if selected_ids:
data = (self.drag_info().drag_type, id(self), selected_ids[0], 0)
sel_data.set(sel_data.target, 8, pickle.dumps(data))
def drag_info(self):
"""
Return the type of DND targetst that this view will accept. For Media
View, we will accept media objects.
"""
return DdTargets.MEDIAOBJ
def find_index(self, obj):
"""
returns the index of the object within the associated data
"""
return self.model.indexlist[obj]
def drag_data_received(self, widget, context, x, y, sel_data, info, time):
"""
Handle the standard gtk interface for drag_data_received.
If the selection data is define, extract the value from sel_data.data,
and decide if this is a move or a reorder.
"""
if sel_data and sel_data.data:
cleaned_string = sel_data.data.replace('\0', ' ')
cleaned_string = cleaned_string.replace("\r", " ").strip()
data_list = Utils.fix_encoding(cleaned_string).split('\n')
for d in [item.strip() for item in data_list]:
protocol, site, mfile, j, k, l = urlparse.urlparse(d)
if protocol == "file":
name = Utils.fix_encoding(mfile)
mime = Mime.get_type(name)
if not Mime.is_valid_type(mime):
return
photo = gen.lib.MediaObject()
photo.set_path(name)
photo.set_mime_type(mime)
basename = os.path.basename(name)
(root, ext) = os.path.splitext(basename)
photo.set_description(root)
trans = self.dbstate.db.transaction_begin()
self.dbstate.db.add_object(photo, trans)
self.dbstate.db.transaction_commit(trans,
_("Drag Media Object"))
widget.emit_stop_by_name('drag_data_received')
def get_bookmarks(self):
"""
Return the booksmarks associated with this view
"""
return self.dbstate.db.get_media_bookmarks()
def define_actions(self):
"""
Defines the UIManager actions specific to Media View. We need to make
sure that the common List View actions are defined as well, so we
call the parent function.
"""
ListView.define_actions(self)
self._add_action('ColumnEdit', gtk.STOCK_PROPERTIES,
_('_Column Editor'), callback=self._column_editor)
self._add_action('FilterEdit', None, _('Media Filter Editor'),
callback=self.filter_editor)
self._add_action('OpenMedia', 'gramps-viewmedia', _('View'),
tip=_("View in the default viewer"),
callback=self.view_media)
def view_media(self, obj):
"""
Launch external viewers for the selected objects.
"""
for handle in self.selected_handles():
ref_obj = self.dbstate.db.get_object_from_handle(handle)
mpath = Utils.media_path_full(self.dbstate.db, ref_obj.get_path())
open_file_with_default_application(mpath)
def _column_editor(self, obj):
"""
Start the column editor dialog
"""
import ColumnOrder
ColumnOrder.ColumnOrder(
_('Select Media Columns'),
self.uistate,
self.dbstate.db.get_media_column_order(),
MediaView.COLUMN_NAMES,
self.set_column_order)
def column_order(self):
"""
Get the column order from the database
"""
return self.dbstate.db.get_media_column_order()
def get_stock(self):
"""
Return the icon for this view
"""
return 'gramps-media'
def build_widget(self):
"""
Builds the View from GTK components
"""
base = ListView.build_widget(self)
vbox = gtk.VBox()
vbox.set_border_width(0)
vbox.set_spacing(4)
self.image = gtk.Image()
self.image.set_size_request(int(const.THUMBSCALE),
int(const.THUMBSCALE))
ebox = gtk.EventBox()
ebox.add(self.image)
ebox.connect('button-press-event', self.button_press_event)
ebox.set_tooltip_text(
_('Double click image to view in an external viewer'))
vbox.pack_start(ebox, False)
vbox.pack_start(base, True)
self.selection.connect('changed', self.row_change)
self._set_dnd()
return vbox
def button_press_event(self, obj, event):
"""
Event handler that catches a double click, and and launches a viewer for
the selected object.
"""
if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
self.view_media(obj)
def row_update(self, obj):
"""
Update the data in the row. we override this because the Media View adds
additional functionality to the normal List View. The Media View may
have to update the thumbnail image. So, we call the parent task to
handle the normal operation, then call row_change to make sure that
the thumbnail is updated properly if needed.
"""
ListView.row_update(self, obj)
if self.active:
self.row_change(obj)
def row_change(self, obj):
"""
Update the thumbnail on a row change. If nothing is selected, clear
the thumbnail image.
"""
handle = self.first_selected()
if not handle:
self.image.clear()
else:
obj = self.dbstate.db.get_object_from_handle(handle)
pix = ThumbNails.get_thumbnail_image(
Utils.media_path_full(self.dbstate.db, obj.get_path()))
self.image.set_from_pixbuf(pix)
def ui_definition(self):
"""
Return the UIManager XML description of the menus
"""
return '''<ui>
<menubar name="MenuBar">
<menu action="FileMenu">
<placeholder name="LocalExport">
<menuitem action="ExportTab"/>
</placeholder>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</placeholder>
<menuitem action="ColumnEdit"/>
<menuitem action="FilterEdit"/>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonEdit">
<toolitem action="Add"/>
<toolitem action="Edit"/>
<toolitem action="Remove"/>
</placeholder>
<separator/>
<toolitem action="OpenMedia"/>
</toolbar>
<popup name="Popup">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="OpenMedia"/>
<menuitem action="Remove"/>
</popup>
</ui>'''
def add(self, obj):
"""Add a new media object to the media list"""
try:
EditMedia(self.dbstate, self.uistate, [], gen.lib.MediaObject())
except Errors.WindowActiveError:
pass
def remove(self, obj):
self.remove_selected_objects()
def remove_object_from_handle(self, handle):
"""
Remove the selected objects from the database after getting
user verification.
"""
the_lists = Utils.get_media_referents(handle, self.dbstate.db)
object = self.dbstate.db.get_object_from_handle(handle)
query = DeleteMediaQuery(self.dbstate, self.uistate, handle, the_lists)
is_used = any(the_lists)
return (query, is_used, object)
def edit(self, obj):
"""
Edit the selected objects in the EditMedia dialog
"""
for handle in self.selected_handles():
object = self.dbstate.db.get_object_from_handle(handle)
try:
EditMedia(self.dbstate, self.uistate, [], object)
except Errors.WindowActiveError:
pass
def get_handle_from_gramps_id(self, gid):
"""
returns the handle of the specified object
"""
obj = self.dbstate.db.get_object_from_gramps_id(gid)
if obj:
return obj.get_handle()
else:
return None

View File

@@ -0,0 +1,218 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
#
# 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$
"""
Note View.
"""
#-------------------------------------------------------------------------
#
# python modules
#
#-------------------------------------------------------------------------
from gettext import gettext as _
import logging
_LOG = logging.getLogger(".plugins.noteview")
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
from gui.views.listview import ListView
from gui.views.treemodels import NoteModel
import Utils
import Errors
import Bookmarks
import config
import ColumnOrder
from gen.lib import Note
from DdTargets import DdTargets
from Filters.SideBar import NoteSidebarFilter
from Editors import EditNote, DeleteNoteQuery
#-------------------------------------------------------------------------
#
# NoteView
#
#-------------------------------------------------------------------------
class NoteView(ListView):
COLUMN_NAMES = [
_('Preview'),
_('ID'),
_('Type'),
_('Marker'),
]
ADD_MSG = _("Add a new note")
EDIT_MSG = _("Edit the selected note")
DEL_MSG = _("Delete the selected note")
FILTER_TYPE = "Note"
def __init__(self, dbstate, uistate):
signal_map = {
'note-add' : self.row_add,
'note-update' : self.row_update,
'note-delete' : self.row_delete,
'note-rebuild' : self.object_build,
}
self.func_list = {
'<CONTROL>J' : self.jump,
'<CONTROL>BackSpace' : self.key_delete,
}
ListView.__init__(
self, _('Notes'), dbstate, uistate, NoteView.COLUMN_NAMES,
len(NoteView.COLUMN_NAMES), NoteModel, signal_map,
dbstate.db.get_note_bookmarks(),
Bookmarks.NoteBookmarks,
filter_class=NoteSidebarFilter,
multiple=True)
config.connect("interface.filter",
self.filter_toggle)
def column_ord_setfunc(self, clist):
self.dbstate.db.set_note_column_order(clist)
def get_bookmarks(self):
"""
Return the bookmark object
"""
return self.dbstate.db.get_note_bookmarks()
def drag_info(self):
"""
Indicate that the drag type is an EVENT
"""
return DdTargets.NOTE_LINK
def column_order(self):
"""
returns a tuple indicating the column order
"""
return self.dbstate.db.get_note_column_order()
def get_stock(self):
"""
Use the gramps-event stock icon
"""
return 'gramps-notes'
def ui_definition(self):
"""
Defines the UI string for UIManager
"""
return '''<ui>
<menubar name="MenuBar">
<menu action="FileMenu">
<placeholder name="LocalExport">
<menuitem action="ExportTab"/>
</placeholder>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</placeholder>
<menuitem action="ColumnEdit"/>
<menuitem action="FilterEdit"/>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonEdit">
<toolitem action="Add"/>
<toolitem action="Edit"/>
<toolitem action="Remove"/>
</placeholder>
</toolbar>
<popup name="Popup">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</popup>
</ui>'''
def define_actions(self):
ListView.define_actions(self)
self._add_action('ColumnEdit', gtk.STOCK_PROPERTIES,
_('_Column Editor'), callback=self._column_editor)
self._add_action('FilterEdit', None, _('Note Filter Editor'),
callback=self.filter_editor,)
def get_handle_from_gramps_id(self, gid):
obj = self.dbstate.db.get_note_from_gramps_id(gid)
if obj:
return obj.get_handle()
else:
return None
def _column_editor(self, obj):
"""
returns a tuple indicating the column order
"""
ColumnOrder.ColumnOrder(
_('Select Note Columns'),
self.uistate,
self.dbstate.db.get_note_column_order(),
NoteView.COLUMN_NAMES,
self.set_column_order)
def add(self, obj):
try:
EditNote(self.dbstate, self.uistate, [], Note())
except Errors.WindowActiveError:
pass
def remove(self, obj):
self.remove_selected_objects()
def remove_object_from_handle(self, handle):
the_lists = Utils.get_note_referents(handle, self.dbstate.db)
object = self.dbstate.db.get_note_from_handle(handle)
query = DeleteNoteQuery(self.dbstate, self.uistate, object, the_lists)
is_used = any(the_lists)
return (query, is_used, object)
def edit(self, obj):
for handle in self.selected_handles():
note = self.dbstate.db.get_note_from_handle(handle)
try:
EditNote(self.dbstate, self.uistate, [], note)
except Errors.WindowActiveError:
pass

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,464 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2009 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$
"""
Provide the person view.
"""
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# set up logging
#
#-------------------------------------------------------------------------
import logging
_LOG = logging.getLogger(".gui.personview")
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import gen.lib
from gui.views.pageview import NAVIGATION_PERSON
from gui.views.listview import ListView
from gui.views.treemodels import PeopleModel
import Utils
from BasicUtils import name_displayer
from QuestionDialog import ErrorDialog, QuestionDialog
import Errors
import Bookmarks
import config
from DdTargets import DdTargets
from Editors import EditPerson
from Filters.SideBar import PersonSidebarFilter
from gen.plug import CATEGORY_QR_PERSON
#-------------------------------------------------------------------------
#
# internationalization
#
#-------------------------------------------------------------------------
from TransUtils import sgettext as _
#-------------------------------------------------------------------------
#
# PersonView
#
#-------------------------------------------------------------------------
class PersonView(ListView):
"""
PersonView class, derived from the ListView
"""
COLUMN_NAMES = [
_('Name'),
_('ID'),
_('Gender'),
_('Birth Date'),
_('Birth Place'),
_('Death Date'),
_('Death Place'),
_('Spouse'),
_('Last Changed'),
]
ADD_MSG = _("Add a new person")
EDIT_MSG = _("Edit the selected person")
DEL_MSG = _("Delete the selected person")
FILTER_TYPE = "Person"
QR_CATEGORY = CATEGORY_QR_PERSON
def __init__(self, dbstate, uistate):
"""
Create the Person View
"""
signal_map = {
'person-add' : self.row_add,
'person-update' : self.row_update,
'person-delete' : self.row_delete,
'person-rebuild' : self.object_build,
}
ListView.__init__(
self, _('People'), dbstate, uistate,
PersonView.COLUMN_NAMES, len(PersonView.COLUMN_NAMES),
PeopleModel,
signal_map, dbstate.db.get_bookmarks(),
Bookmarks.Bookmarks,
multiple=True,
filter_class=PersonSidebarFilter,
markup=True)
self.func_list = {
'<CONTROL>J' : self.jump,
'<CONTROL>BackSpace' : self.key_delete,
}
config.connect("interface.filter", self.filter_toggle)
def column_ord_setfunc(self, clist):
self.dbstate.db.set_person_column_order(clist)
def navigation_type(self):
return NAVIGATION_PERSON
def get_bookmarks(self):
"""
Return the bookmark object
"""
return self.dbstate.db.get_bookmarks()
def drag_info(self):
"""
Specify the drag type for a single selection
"""
return DdTargets.PERSON_LINK
def drag_list_info(self):
"""
Specify the drag type for a multiple selected rows
"""
return DdTargets.PERSON_LINK_LIST
def column_order(self):
"""
returns a tuple indicating the column order
"""
return self.dbstate.db.get_person_column_order()
def exact_search(self):
"""
Returns a tuple indicating columns requiring an exact search
"""
return (2,) # Gender ('female' contains the string 'male')
def get_stock(self):
"""
Use the gramps-person stock icon
"""
return 'gramps-person'
def ui_definition(self):
"""
Defines the UI string for UIManager
"""
return '''<ui>
<menubar name="MenuBar">
<menu action="FileMenu">
<placeholder name="LocalExport">
<menuitem action="ExportTab"/>
</placeholder>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
<menu action="GoMenu">
<placeholder name="CommonGo">
<menuitem action="Back"/>
<menuitem action="Forward"/>
<separator/>
<menuitem action="HomePerson"/>
<separator/>
</placeholder>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</placeholder>
<menuitem action="SetActive"/>
<menuitem action="ColumnEdit"/>
<menuitem action="FilterEdit"/>
<placeholder name="Merge">
<menuitem action="CmpMerge"/>
<menuitem action="FastMerge"/>
</placeholder>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonNavigation">
<toolitem action="Back"/>
<toolitem action="Forward"/>
<toolitem action="HomePerson"/>
</placeholder>
<placeholder name="CommonEdit">
<toolitem action="Add"/>
<toolitem action="Edit"/>
<toolitem action="Remove"/>
</placeholder>
</toolbar>
<popup name="Popup">
<menuitem action="Back"/>
<menuitem action="Forward"/>
<menuitem action="HomePerson"/>
<separator/>
<menuitem action="OpenAllNodes"/>
<menuitem action="CloseAllNodes"/>
<separator/>
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
<separator/>
<menu name="QuickReport" action="QuickReport">
<menuitem action="Dummy"/>
</menu>
</popup>
</ui>'''
def get_handle_from_gramps_id(self, gid):
obj = self.dbstate.db.get_person_from_gramps_id(gid)
if obj:
return obj.get_handle()
else:
return None
def _column_editor(self, obj):
"""
returns a tuple indicating the column order
"""
import ColumnOrder
ColumnOrder.ColumnOrder(
_('Select Person Columns'),
self.uistate,
self.dbstate.db.get_person_column_order(),
PersonView.COLUMN_NAMES,
self.set_column_order)
def add(self, obj):
person = gen.lib.Person()
# attempt to get the current surname
(model, pathlist) = self.selection.get_selected_rows()
name = u""
if len(pathlist) == 1:
path = pathlist[0]
if len(path) == 1:
name = model.on_get_iter(path)
else:
node = model.on_get_iter(path)
name = model.on_iter_parent(node)
try:
person.get_primary_name().set_surname(name)
EditPerson(self.dbstate, self.uistate, [], person)
except Errors.WindowActiveError:
pass
def edit(self, obj):
for handle in self.selected_handles():
person = self.dbstate.db.get_person_from_handle(handle)
try:
EditPerson(self.dbstate, self.uistate, [], person)
except Errors.WindowActiveError:
pass
def remove(self, obj):
for sel in self.selected_handles():
person = self.dbstate.db.get_person_from_handle(sel)
self.active_person = person
name = name_displayer.display(person)
msg = _('Deleting the person will remove the person '
'from the database.')
msg = "%s %s" % (msg, Utils.data_recover_msg)
QuestionDialog(_('Delete %s?') % name,
msg,
_('_Delete Person'),
self.delete_person_response)
def delete_person_response(self):
"""
Deletes the person from the database.
"""
# set the busy cursor, so the user knows that we are working
self.uistate.set_busy_cursor(True)
# create the transaction
trans = self.dbstate.db.transaction_begin()
# create name to save
person = self.active_person
active_name = _("Delete Person (%s)") % name_displayer.display(person)
# delete the person from the database
gen.utils.delete_person_from_database(self.dbstate.db, person, trans)
# remove the person from the list
self.remove_from_person_list(person)
# commit the transaction
self.dbstate.db.transaction_commit(trans, active_name)
# select the previously active person, turn off the busy cursor
self.uistate.phistory.back()
self.uistate.set_busy_cursor(False)
def remove_from_person_list(self, person):
"""Remove the selected person from the list. A person object is
expected, not an ID"""
path = self.model.on_get_path(person.get_handle())
(col, row) = path
if row > 0:
self.selection.select_path((col, row-1))
elif row == 0 and self.model.on_get_iter(path):
self.selection.select_path(path)
def dummy_report(self, obj):
""" For the xml UI definition of popup to work, the submenu
Quick Report must have an entry in the xml
As this submenu will be dynamically built, we offer a dummy action
"""
pass
def define_actions(self):
"""
Required define_actions function for PageView. Builds the action
group information required. We extend beyond the normal here,
since we want to have more than one action group for the PersonView.
Most PageViews really won't care about this.
Special action groups for Forward and Back are created to allow the
handling of navigation buttons. Forward and Back allow the user to
advance or retreat throughout the history, and we want to have these
be able to toggle these when you are at the end of the history or
at the beginning of the history.
"""
ListView.define_actions(self)
self.all_action = gtk.ActionGroup(self.title + "/PersonAll")
self.edit_action = gtk.ActionGroup(self.title + "/PersonEdit")
self.all_action.add_actions([
('FilterEdit', None, _('Person Filter Editor'), None, None,
self.filter_editor),
('OpenAllNodes', None, _("Expand all Nodes"), None, None,
self.open_all_nodes),
('Edit', gtk.STOCK_EDIT, _("action|_Edit..."), "<control>Return",
_("Edit the selected person"), self.edit),
('CloseAllNodes', None, _("Collapse all Nodes"), None, None,
self.close_all_nodes),
('QuickReport', None, _("Quick View"), None, None, None),
('Dummy', None, ' ', None, None, self.dummy_report),
])
self.edit_action.add_actions(
[
('Add', gtk.STOCK_ADD, _("_Add..."), "<control>Insert",
_("Add a new person"), self.add),
('Remove', gtk.STOCK_REMOVE, _("_Remove"), "<control>Delete",
_("Remove the Selected Person"), self.remove),
('ColumnEdit', gtk.STOCK_PROPERTIES, _('_Column Editor...'), None,
None, self._column_editor),
('CmpMerge', None, _('Compare and _Merge...'), None, None,
self.cmp_merge),
('FastMerge', None, _('_Fast Merge...'), None, None,
self.fast_merge),
('ExportTab', None, _('Export View...'), None, None, self.export),
])
self._add_action_group(self.edit_action)
self._add_action_group(self.all_action)
def enable_action_group(self, obj):
ListView.enable_action_group(self, obj)
self.all_action.set_visible(True)
self.edit_action.set_visible(False)
self.edit_action.set_sensitive(not self.dbstate.db.readonly)
def disable_action_group(self):
ListView.disable_action_group(self)
self.all_action.set_visible(False)
self.edit_action.set_visible(False)
def open_all_nodes(self, obj):
self.uistate.status_text(_("Updating display..."))
self.uistate.set_busy_cursor(True)
self.list.expand_all()
self.uistate.set_busy_cursor(False)
self.uistate.modify_statusbar(self.dbstate)
def close_all_nodes(self, obj):
self.list.collapse_all()
def cmp_merge(self, obj):
mlist = self.get_selected_objects()
if len(mlist) != 2:
ErrorDialog(
_("Cannot merge people"),
_("Exactly two people must be selected to perform a merge. "
"A second person can be selected by holding down the "
"control key while clicking on the desired person."))
else:
import Merge
person1 = self.db.get_person_from_handle(mlist[0])
person2 = self.db.get_person_from_handle(mlist[1])
if person1 and person2:
Merge.PersonCompare(self.dbstate, self.uistate, person1,
person2, self.build_tree)
else:
ErrorDialog(
_("Cannot merge people"),
_("Exactly two people must be selected to perform a "
"merge. A second person can be selected by holding "
"down the control key while clicking on the desired "
"person."))
def fast_merge(self, obj):
mlist = self.get_selected_objects()
if len(mlist) != 2:
ErrorDialog(
_("Cannot merge people"),
_("Exactly two people must be selected to perform a merge. "
"A second person can be selected by holding down the "
"control key while clicking on the desired person."))
else:
import Merge
person1 = self.db.get_person_from_handle(mlist[0])
person2 = self.db.get_person_from_handle(mlist[1])
if person1 and person2:
Merge.MergePeopleUI(self.dbstate, self.uistate, person1,
person2, self.build_tree)
else:
ErrorDialog(
_("Cannot merge people"),
_("Exactly two people must be selected to perform a merge. "
"A second person can be selected by holding down the "
"control key while clicking on the desired person."))

View File

@@ -0,0 +1,382 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
#
# 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$
"""
Place View
"""
#-------------------------------------------------------------------------
#
# Global modules
#
#-------------------------------------------------------------------------
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import gen.lib
from gui.views.listview import ListView
from gui.views.treemodels import PlaceModel
from gui.utils import add_menuitem
import Errors
import Bookmarks
import config
from QuestionDialog import ErrorDialog
from gui.pluginmanager import GuiPluginManager
from DdTargets import DdTargets
from Editors import EditPlace, DeletePlaceQuery
from Filters.SideBar import PlaceSidebarFilter
#-------------------------------------------------------------------------
#
# internationalization
#
#-------------------------------------------------------------------------
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# PlaceView
#
#-------------------------------------------------------------------------
class PlaceView(ListView):
COLUMN_NAMES = [
_('Place Name'),
_('ID'),
_('Church Parish'),
_('ZIP/Postal Code'),
_('City'),
_('County'),
_('State'),
_('Country'),
_('Latitude'),
_('Longitude'),
_('Last Changed'),
_('Street'),
]
ADD_MSG = _("Add a new place")
EDIT_MSG = _("Edit the selected place")
DEL_MSG = _("Delete the selected place")
FILTER_TYPE = "Place"
def __init__(self, dbstate, uistate):
signal_map = {
'place-add' : self.row_add,
'place-update' : self.row_update,
'place-delete' : self.row_delete,
'place-rebuild' : self.object_build,
}
self.func_list = {
'<CONTROL>J' : self.jump,
'<CONTROL>BackSpace' : self.key_delete,
}
self.mapservice = config.get('interface.mapservice')
self.mapservicedata = {}
ListView.__init__(
self, _('Places'), dbstate, uistate, PlaceView.COLUMN_NAMES,
len(PlaceView.COLUMN_NAMES),
PlaceModel, signal_map,
dbstate.db.get_place_bookmarks(),
Bookmarks.PlaceBookmarks,
multiple=True,
filter_class=PlaceSidebarFilter)
config.connect("interface.filter",
self.filter_toggle)
def column_ord_setfunc(self, clist):
self.dbstate.db.set_place_column_order(clist)
def get_bookmarks(self):
return self.dbstate.db.get_place_bookmarks()
def define_actions(self):
ListView.define_actions(self)
self._add_action('ColumnEdit', gtk.STOCK_PROPERTIES,
_('_Column Editor'), callback=self._column_editor)
self._add_action('FastMerge', None, _('_Merge...'),
callback=self.fast_merge)
self._add_toolmenu_action('MapsList', _('Loading...'),
_("Attempt to see selected locations with a Map "
"Service (OpenstreetMap, Google Maps, ...)"),
self.gotomap,
_('Select a Map Service'))
self._add_action('GotoMap', gtk.STOCK_JUMP_TO,
_('_Look up with Map Service'),
callback=self.gotomap,
tip=_("Attempt to see this location with a Map "
"Service (OpenstreetMap, Google Maps, ...)"))
self._add_action('FilterEdit', None, _('Place Filter Editor'),
callback=self.filter_editor)
def change_page(self):
"""
Called by viewmanager at end of realization when arriving on the page
At this point the Toolbar is created. We need to:
1. get the menutoolbutton
2. add all possible map services in the drop down menu
3. add the actions that correspond to clicking in this drop down menu
4. set icon and label of the menutoolbutton now that it is realized
5. store label so it can be changed when selection changes
"""
ListView.change_page(self)
#menutoolbutton actions are stored in PageView class,
# obtain the widgets where we need to add to menu
actionservices = self.action_toolmenu['MapsList']
widgets = actionservices.get_proxies()
mmenu = self.__create_maps_menu_actions()
if not self.mapservicedata:
return
self.mapslistlabel = []
if not self.mapservice in self.mapservicedata:
#stored val no longer exists, use the first key instead
self.set_mapservice(self.mapservicedata.keys()[0])
#store all gtk labels to be able to update label on selection change
for widget in widgets :
if isinstance(widget, gtk.MenuToolButton):
widget.set_menu(mmenu)
if gtk.pygtk_version >= (2, 12, 0):
widget.set_arrow_tooltip_text(actionservices.arrowtooltip)
lbl = gtk.Label(self.mapservice_label())
lbl.show()
self.mapslistlabel.append(lbl)
widget.set_label_widget(self.mapslistlabel[-1])
widget.set_stock_id(gtk.STOCK_JUMP_TO)
if self.drag_info():
self.list.enable_model_drag_source(gtk.gdk.BUTTON1_MASK,
[('text/plain', 0, 0), self.drag_info().target()],
gtk.gdk.ACTION_COPY)
def __create_maps_menu_actions(self):
"""
Function creating a menu and actions that are used as dropdown menu
from the menutoolbutton
"""
menu = gtk.Menu()
#select the map services to show
self.mapservicedata = {}
servlist = GuiPluginManager.get_instance().get_reg_mapservices()
for i, pdata in zip(range(len(servlist)), servlist):
key = pdata.id.replace(' ', '-')
add_menuitem(menu, pdata.name, None,
make_callback(self.set_mapservice, key))
self.mapservicedata[key] = pdata
return menu
def set_mapservice(self, mapkey):
"""
change the service that runs on click of the menutoolbutton
used as callback menu on menu clicks
"""
self.mapservice = mapkey
for label in self.mapslistlabel:
label.set_label(self.mapservice_label())
label.show()
config.set('interface.mapservice', mapkey)
config.save()
def mapservice_label(self):
"""
return the current label for the menutoolbutton
"""
return self.mapservicedata[self.mapservice].name
def gotomap(self, obj):
"""
Run the map service
"""
#First test if any map service is available
if not len(self.mapservicedata):
msg = _("No map service is available.")
msg2 = _("Check your installation.")
ErrorDialog(msg, msg2)
return
place_handles = self.selected_handles()
try:
place_handle = self.selected_handles()[0]
except IndexError:
msg = _("No place selected.")
msg2 = _("You need to select a place to be able to view it"
" on a map. Some Map Services might support multiple"
" selections.")
ErrorDialog(msg, msg2)
return
#TODO: support for descriptions in some cases. For now, pass None
#TODO: Later this might be 'Birth of William' ....
places = [(x, None) for x in place_handles]
#run the mapservice:
pmgr = GuiPluginManager.get_instance()
serv = self.mapservicedata[self.mapservice]
mod = pmgr.load_plugin(serv)
if mod:
servfunc = eval('mod.' + serv.mapservice)
servfunc()(self.dbstate.db, places)
else:
print 'Failed to load map plugin, see Plugin Status'
def drag_info(self):
return DdTargets.PLACE_LINK
def _column_editor(self, obj):
import ColumnOrder
ColumnOrder.ColumnOrder(
_('Select Place Columns'),
self.uistate,
self.dbstate.db.get_place_column_order(),
PlaceView.COLUMN_NAMES,
self.set_column_order)
def column_order(self):
return self.dbstate.db.get_place_column_order()
def get_stock(self):
return 'gramps-place'
def ui_definition(self):
return '''<ui>
<menubar name="MenuBar">
<menu action="FileMenu">
<placeholder name="LocalExport">
<menuitem action="ExportTab"/>
</placeholder>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</placeholder>
<menuitem action="ColumnEdit"/>
<menuitem action="FilterEdit"/>
<placeholder name="Merge">
<menuitem action="FastMerge"/>
</placeholder>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonEdit">
<toolitem action="Add"/>
<toolitem action="Edit"/>
<toolitem action="Remove"/>
<separator/>
<toolitem action="MapsList"/>
</placeholder>
</toolbar>
<popup name="Popup">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
<menuitem action="GotoMap"/>
</popup>
</ui>'''
def add(self, obj):
try:
EditPlace(self.dbstate, self.uistate, [], gen.lib.Place())
except Errors.WindowActiveError:
pass
def remove(self, obj):
self.remove_selected_objects()
def remove_object_from_handle(self, handle):
person_list = [
item[1] for item in
self.dbstate.db.find_backlink_handles(handle,['Person'])]
family_list = [
item[1] for item in
self.dbstate.db.find_backlink_handles(handle,['Family'])]
event_list = [
item[1] for item in
self.dbstate.db.find_backlink_handles(handle,['Event'])]
object = self.dbstate.db.get_place_from_handle(handle)
query = DeletePlaceQuery(self.dbstate, self.uistate, object,
person_list, family_list, event_list)
is_used = len(person_list) + len(family_list) + len(event_list) > 0
return (query, is_used, object)
def edit(self, obj):
for handle in self.selected_handles():
place = self.dbstate.db.get_place_from_handle(handle)
try:
EditPlace(self.dbstate, self.uistate, [], place)
except Errors.WindowActiveError:
pass
def fast_merge(self, obj):
mlist = self.selected_handles()
if len(mlist) != 2:
msg = _("Cannot merge places.")
msg2 = _("Exactly two places must be selected to perform a merge. "
"A second place can be selected by holding down the "
"control key while clicking on the desired place.")
ErrorDialog(msg, msg2)
else:
import Merge
Merge.MergePlaces(self.dbstate, self.uistate, mlist[0], mlist[1])
def get_handle_from_gramps_id(self, gid):
obj = self.dbstate.db.get_place_from_gramps_id(gid)
if obj:
return obj.get_handle()
else:
return None
def make_callback(func, val):
return lambda x: func(val)

1622
src/plugins/view/relview.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,227 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
#
# 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$
"""
Repository View
"""
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import gen.lib
from gui.views.listview import ListView
from gui.views.treemodels import RepositoryModel
import Utils
import Bookmarks
import Errors
import config
from Editors import EditRepository, DelRepositoryQuery
from DdTargets import DdTargets
from Filters.SideBar import RepoSidebarFilter
from gen.plug import CATEGORY_QR_REPOSITORY
#-------------------------------------------------------------------------
#
# internationalization
#
#-------------------------------------------------------------------------
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# RepositoryView
#
#-------------------------------------------------------------------------
class RepositoryView(ListView):
COLUMN_NAMES = [
_('Name'),
_('ID'),
_('Type'),
_('Home URL'),
_('Street'),
_('ZIP/Postal Code'),
_('City'),
_('County'),
_('State'),
_('Country'),
_('Email'),
_('Search URL'),
_('Last Changed'),
]
ADD_MSG = _("Add a new repository")
EDIT_MSG = _("Edit the selected repository")
DEL_MSG = _("Delete the selected repository")
FILTER_TYPE = "Repository"
QR_CATEGORY = CATEGORY_QR_REPOSITORY
def __init__(self, dbstate, uistate):
signal_map = {
'repository-add' : self.row_add,
'repository-update' : self.row_update,
'repository-delete' : self.row_delete,
'repository-rebuild' : self.object_build,
}
self.func_list = {
'<CONTROL>J' : self.jump,
'<CONTROL>BackSpace' : self.key_delete,
}
ListView.__init__(
self, _('Repositories'), dbstate, uistate,
RepositoryView.COLUMN_NAMES, len(RepositoryView.COLUMN_NAMES),
RepositoryModel, signal_map,
dbstate.db.get_repo_bookmarks(),
Bookmarks.RepoBookmarks, multiple=True,
filter_class=RepoSidebarFilter)
config.connect("interface.filter",
self.filter_toggle)
def column_ord_setfunc(self, clist):
self.dbstate.db.set_repository_column_order(clist)
def get_bookmarks(self):
return self.dbstate.db.get_repo_bookmarks()
def drag_info(self):
return DdTargets.REPO_LINK
def define_actions(self):
ListView.define_actions(self)
self._add_action('ColumnEdit', gtk.STOCK_PROPERTIES,
_('_Column Editor'), callback=self._column_editor)
self._add_action('FilterEdit', None, _('Repository Filter Editor'),
callback=self.filter_editor,)
self._add_action('QuickReport', None,
_("Quick View"), None, None, None)
self._add_action('Dummy', None,
' ', None, None, self.dummy_report)
def _column_editor(self, obj):
import ColumnOrder
ColumnOrder.ColumnOrder(
_('Select Repository Columns'),
self.uistate,
self.dbstate.db.get_repository_column_order(),
RepositoryView.COLUMN_NAMES,
self.set_column_order)
def column_order(self):
return self.dbstate.db.get_repository_column_order()
def get_stock(self):
return 'gramps-repository'
def ui_definition(self):
return '''<ui>
<menubar name="MenuBar">
<menu action="FileMenu">
<placeholder name="LocalExport">
<menuitem action="ExportTab"/>
</placeholder>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</placeholder>
<menuitem action="ColumnEdit"/>
<menuitem action="FilterEdit"/>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonEdit">
<toolitem action="Add"/>
<toolitem action="Edit"/>
<toolitem action="Remove"/>
</placeholder>
</toolbar>
<popup name="Popup">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
<separator/>
<menu name="QuickReport" action="QuickReport">
<menuitem action="Dummy"/>
</menu>
</popup>
</ui>'''
def add(self, obj):
EditRepository(self.dbstate, self.uistate, [], gen.lib.Repository())
def remove(self, obj):
self.remove_selected_objects()
def remove_object_from_handle(self, handle):
source_list = [
item[1] for item in
self.dbstate.db.find_backlink_handles(handle, ['Source'])]
object = self.dbstate.db.get_repository_from_handle(handle)
query = DelRepositoryQuery(self.dbstate, self.uistate, object,
source_list)
is_used = len(source_list) > 0
return (query, is_used, object)
def edit(self, obj):
for handle in self.selected_handles():
repos = self.dbstate.db.get_repository_from_handle(handle)
try:
EditRepository(self.dbstate, self.uistate, [], repos)
except Errors.WindowActiveError:
pass
def get_handle_from_gramps_id(self, gid):
obj = self.dbstate.db.get_repository_from_gramps_id(gid)
if obj:
return obj.get_handle()
else:
return None
def dummy_report(self, obj):
""" For the xml UI definition of popup to work, the submenu
Quick Report must have an entry in the xml
As this submenu will be dynamically built, we offer a dummy action
"""
pass

View File

@@ -0,0 +1,219 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
#
# 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$
"""
Source View
"""
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import gen.lib
import config
from gui.views.listview import ListView
from gui.views.treemodels import SourceModel
import Utils
import Bookmarks
import Errors
from DdTargets import DdTargets
from QuestionDialog import ErrorDialog
from Editors import EditSource, DelSrcQuery
from Filters.SideBar import SourceSidebarFilter
#-------------------------------------------------------------------------
#
# internationalization
#
#-------------------------------------------------------------------------
from gettext import gettext as _
#-------------------------------------------------------------------------
#
# SourceView
#
#-------------------------------------------------------------------------
class SourceView(ListView):
COLUMN_NAMES = [
_('Title'),
_('ID'),
_('Author'),
_('Abbreviation'),
_('Publication Information'),
_('Last Changed'),
]
ADD_MSG = _("Add a new source")
EDIT_MSG = _("Edit the selected source")
DEL_MSG = _("Delete the selected source")
FILTER_TYPE = "Source"
def __init__(self, dbstate, uistate):
signal_map = {
'source-add' : self.row_add,
'source-update' : self.row_update,
'source-delete' : self.row_delete,
'source-rebuild' : self.object_build,
}
self.func_list = {
'<CONTROL>J' : self.jump,
'<CONTROL>BackSpace' : self.key_delete,
}
ListView.__init__(
self, _('Sources'), dbstate, uistate,
SourceView.COLUMN_NAMES, len(SourceView.COLUMN_NAMES),
SourceModel, signal_map,
dbstate.db.get_source_bookmarks(),
Bookmarks.SourceBookmarks, multiple=True,
filter_class=SourceSidebarFilter)
config.connect("interface.filter",
self.filter_toggle)
def column_ord_setfunc(self, clist):
self.dbstate.db.set_source_column_order(clist)
def get_bookmarks(self):
return self.dbstate.db.get_source_bookmarks()
def drag_info(self):
return DdTargets.SOURCE_LINK
def define_actions(self):
ListView.define_actions(self)
self._add_action('ColumnEdit', gtk.STOCK_PROPERTIES,
_('_Column Editor'), callback=self._column_editor)
self._add_action('FastMerge', None, _('_Merge'),
callback=self.fast_merge)
self._add_action('FilterEdit', None, _('Source Filter Editor'),
callback=self.filter_editor,)
def _column_editor(self, obj):
import ColumnOrder
ColumnOrder.ColumnOrder(
_('Select Source Columns'),
self.uistate,
self.dbstate.db.get_source_column_order(),
SourceView.COLUMN_NAMES,
self.set_column_order)
def column_order(self):
return self.dbstate.db.get_source_column_order()
def get_stock(self):
return 'gramps-source'
def ui_definition(self):
return '''<ui>
<menubar name="MenuBar">
<menu action="FileMenu">
<placeholder name="LocalExport">
<menuitem action="ExportTab"/>
</placeholder>
</menu>
<menu action="BookMenu">
<placeholder name="AddEditBook">
<menuitem action="AddBook"/>
<menuitem action="EditBook"/>
</placeholder>
</menu>
<menu action="EditMenu">
<placeholder name="CommonEdit">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</placeholder>
<menuitem action="ColumnEdit"/>
<menuitem action="FilterEdit"/>
<placeholder name="Merge">
<menuitem action="FastMerge"/>
</placeholder>
</menu>
</menubar>
<toolbar name="ToolBar">
<placeholder name="CommonEdit">
<toolitem action="Add"/>
<toolitem action="Edit"/>
<toolitem action="Remove"/>
</placeholder>
</toolbar>
<popup name="Popup">
<menuitem action="Add"/>
<menuitem action="Edit"/>
<menuitem action="Remove"/>
</popup>
</ui>'''
def add(self, obj):
EditSource(self.dbstate, self.uistate, [], gen.lib.Source())
def remove(self, obj):
self.remove_selected_objects()
def remove_object_from_handle(self, handle):
the_lists = Utils.get_source_referents(handle, self.dbstate.db)
object = self.dbstate.db.get_source_from_handle(handle)
query = DelSrcQuery(self.dbstate, self.uistate, object, the_lists)
is_used = any(the_lists)
return (query, is_used, object)
def edit(self, obj):
for handle in self.selected_handles():
source = self.dbstate.db.get_source_from_handle(handle)
try:
EditSource(self.dbstate, self.uistate, [], source)
except Errors.WindowActiveError:
pass
def fast_merge(self, obj):
mlist = self.selected_handles()
if len(mlist) != 2:
msg = _("Cannot merge sources.")
msg2 = _("Exactly two sources must be selected to perform a merge. "
"A second source can be selected by holding down the "
"control key while clicking on the desired source.")
ErrorDialog(msg, msg2)
else:
import Merge
Merge.MergeSources(self.dbstate, self.uistate, mlist[0], mlist[1])
def get_handle_from_gramps_id(self, gid):
obj = self.dbstate.db.get_source_from_gramps_id(gid)
if obj:
return obj.get_handle()
else:
return None

View File

@@ -0,0 +1,171 @@
# encoding:utf-8
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2009 Benny Malengier
#
# 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$
#------------------------------------------------------------------------
#
# default views of GRAMPS
#
#------------------------------------------------------------------------
register(VIEW,
id = 'eventview',
name = _("Event View"),
description = _("The view showing all the events"),
version = '1.0',
status = STABLE,
fname = 'eventview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_EVENT,
viewclass = 'EventView',
)
register(VIEW,
id = 'familyview',
name = _("Family View"),
description = _("The view showing all families"),
version = '1.0',
status = STABLE,
fname = 'familyview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_FAMILY,
viewclass = 'FamilyView',
)
register(VIEW,
id = 'grampletview',
name = _("Gramplet View"),
description = _("The view allowing to see Gramplets"),
version = '1.0',
status = STABLE,
fname = 'grampletview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_MISC,
viewclass = 'GrampletView',
)
register(VIEW,
id = 'mediaview',
name = _("Media View"),
description = _("The view showing all the media objects"),
version = '1.0',
status = STABLE,
fname = 'mediaview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_MEDIA,
viewclass = 'MediaView',
)
register(VIEW,
id = 'noteview',
name = _("Note View"),
description = _("The view showing all the notes"),
version = '1.0',
status = STABLE,
fname = 'noteview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_NOTE,
viewclass = 'NoteView',
)
register(VIEW,
id = 'relview',
name = _("Relationship View"),
description = _("The view showing all relationships of the selected person"),
version = '1.0',
status = STABLE,
fname = 'relview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_REL,
viewclass = 'RelationshipView',
)
register(VIEW,
id = 'pedigreeview',
name = _("Pedigree View"),
description = _("The view showing an ancestor pedigree of the selected person"),
version = '1.0',
status = STABLE,
fname = 'pedigreeview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_REL,
viewclass = 'PedigreeView',
)
register(VIEW,
id = 'personview',
name = _("Person View"),
description = _("The view showing all people in the family tree"),
version = '1.0',
status = STABLE,
fname = 'personview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_PERSON,
viewclass = 'PersonView',
)
register(VIEW,
id = 'placeview',
name = _("Place View"),
description = _("The view showing all the places of the family tree"),
version = '1.0',
status = STABLE,
fname = 'placeview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_PLACE,
viewclass = 'PlaceView',
)
register(VIEW,
id = 'repoview',
name = _("Repository View"),
description = _("The view showing all the repositories"),
version = '1.0',
status = STABLE,
fname = 'repoview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_REPO,
viewclass = 'RepositoryView',
)
register(VIEW,
id = 'sourceview',
name = _("Source View"),
description = _("The view showing all the sources"),
version = '1.0',
status = STABLE,
fname = 'sourceview.py',
authors = [u"The GRAMPS project"],
authors_email = ["http://gramps-project.org"],
category = VIEW_SOURCE,
viewclass = 'SourceView',
)