Merged trunk r18398 through r18497 into geps023.

Conflicts resolved in:
    NarrativeWeb.py


svn: r18498
This commit is contained in:
Tim G L Lyons 2011-11-24 18:15:53 +00:00
commit 6cb761b010
32 changed files with 8402 additions and 8293 deletions

2722
po/cs.po

File diff suppressed because it is too large Load Diff

431
po/de.po

File diff suppressed because it is too large Load Diff

4615
po/fr.po

File diff suppressed because it is too large Load Diff

7038
po/sv.po

File diff suppressed because it is too large Load Diff

View File

@ -164,6 +164,7 @@ class SearchBar(object):
self.filter_button.set_sensitive(False)
self.uistate.status_text(_('Updating display...'))
self.on_apply_callback()
self.filter_text.grab_focus()
self.uistate.modify_statusbar(self.dbstate)
def show(self):

View File

@ -88,14 +88,14 @@ def _convert_str_to_match_type(str_val, type_val):
if str_val.isdigit():
return int(str_val)
else:
print "%s is not an integer number" % str_val
print "'%s' is not an integer number" % str_val
return 0
elif ret_type == float:
try:
return float(str_val)
except ValueError:
print "%s is not a decimal number" % str_val
print "'%s' is not a decimal number" % str_val
return 0.0
elif ret_type == bool:
@ -104,13 +104,13 @@ def _convert_str_to_match_type(str_val, type_val):
elif str_val == str(False):
return False
else:
print "%s is not a boolean-- try 'True' or 'False'" % str_val
print "'%s' is not a boolean-- try 'True' or 'False'" % str_val
return False
elif ret_type == list:
ret_val = []
if not ( str_val.startswith("[") and str_val.endswith("]") ):
print "%s is not a list-- try: [%s]" % (str_val, str_val)
print "'%s' is not a list-- try: [%s]" % (str_val, str_val)
return ret_val
entry = ""
@ -526,7 +526,7 @@ class CommandLineReport(object):
else:
#there was a show option given, but the option is invalid
print ("option %s not valid. Use 'show=all' to see all valid "
print ("option '%s' not valid. Use 'show=all' to see all valid "
"options." % self.show)
#------------------------------------------------------------------------

View File

@ -39,7 +39,8 @@ Declare constants used by database modules
__all__ = (
('DBPAGE', 'DBMODE', 'DBCACHE', 'DBLOCKS', 'DBOBJECTS', 'DBUNDO',
'DBEXT', 'DBMODE_R', 'DBMODE_W', 'DBUNDOFN', 'DBLOCKFN',
'DBRECOVFN', 'DBLOGNAME', 'DBFLAGS_O', 'DBFLAGS_R', 'DBFLAGS_D',
'DBRECOVFN','BDBVERSFN', 'DBLOGNAME', 'DBFLAGS_O', 'DBFLAGS_R',
'DBFLAGS_D',
) +
('PERSON_KEY', 'FAMILY_KEY', 'SOURCE_KEY', 'CITATION_KEY',
@ -54,9 +55,10 @@ DBEXT = ".db" # File extension to be used for database files
DBUNDOFN = "undo.db" # File name of 'undo' database
DBLOCKFN = "lock" # File name of lock file
DBRECOVFN = "need_recover" # File name of recovery file
BDBVERSFN = "bdbversion.txt"# File name of Berkeley DB version file
DBLOGNAME = ".Db" # Name of logger
DBMODE_R = "r" # Read-only access
DBMODE_W = "w" # Full Reaw/Write access
DBMODE_W = "w" # Full Read/Write access
DBPAGE = 16384 # Size of the pages used to hold items in the database
DBMODE = 0666 # Unix mode for database creation
DBCACHE = 0x4000000 # Size of the shared memory buffer pool

View File

@ -79,6 +79,30 @@ class DbVersionError(Exception):
"Gramps.\nPlease upgrade to the corresponding version or use "
"XML for porting data between different database versions.")
class BsddbDowngradeError(Exception):
"""
Error used to report that the Berkeley database used to create the family
tree is of a version that is too new to be supported by the current version.
"""
def __init__(self, env_version, bdb_version):
Exception.__init__(self)
self.env_version = str(env_version)
self.bdb_version = str(bdb_version)
def __str__(self):
return _('Gramps stores its data in a Berkeley Database. '
'The family tree you try to load was created with version '
'%(env_version)s of the Berkeley DB. However, the Gramps '
'version in use right now employs version %(bdb_version)s '
'of the Berkeley DB. So you are trying to load data created '
'in a newer format into an older program; this is bound to '
'fail. The right approach in this case is to use XML export '
'and import. So try to open the family tree on that computer '
'with that software that created the family tree, export it '
'to XML and load that XML into the version of Gramps you '
'intend to use.') % {'env_version': self.env_version,
'bdb_version': self.bdb_version}
class DbEnvironmentError(Exception):
"""
Error used to report that the database 'environment' could not be opened.

View File

@ -57,9 +57,9 @@ else:
from gen.lib import (GenderStats, Person, Family, Event, Place, Source,
Citation, MediaObject, Repository, Note, Tag)
from gen.db import (DbBsddbRead, DbWriteBase, BSDDBTxn,
DbTxn, BsddbBaseCursor, DbVersionError, DbEnvironmentError,
DbUpgradeRequiredError, find_surname, find_surname_name,
DbUndoBSDDB as DbUndo)
DbTxn, BsddbBaseCursor, BsddbDowngradeError, DbVersionError,
DbEnvironmentError, DbUpgradeRequiredError, find_surname,
find_surname_name, DbUndoBSDDB as DbUndo)
from gen.db.dbconst import *
from gen.utils.callback import Callback
from gen.updatecallback import UpdateCallback
@ -231,6 +231,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.secondary_connected = False
self.has_changed = False
self.brief_name = None
self.update_env_version = False
def catch_db_error(func):
"""
@ -356,6 +357,27 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
with BSDDBTxn(self.env, self.metadata) as txn:
txn.put('mediapath', path)
def __check_bdb_version(self, name):
"""Older version of Berkeley DB can't read data created by a newer
version."""
bdb_version = db.version()
env_version = (0, 0, 0)
versionpath = os.path.join(self.path, BDBVERSFN)
try:
with open(versionpath, "r") as version_file:
env_version = version_file.read().strip()
env_version = tuple(map(int, env_version[1:-1].split(', ')))
except:
# Just assume that the Berkeley DB version is OK.
pass
if (env_version[0] > bdb_version[0]) or \
(env_version[0] == bdb_version[0] and
env_version[1] > bdb_version[1]):
clear_lock_file(name)
raise BsddbDowngradeError(env_version, bdb_version)
elif env_version != bdb_version and not self.readonly:
self.update_env_version = True
@catch_db_error
def version_supported(self):
dbversion = self.metadata.get('version', default=0)
@ -408,6 +430,8 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.path = self.full_name
self.brief_name = os.path.basename(name)
self.__check_bdb_version(name)
# Set up database environment
self.env = db.DBEnv()
self.env.set_cachesize(0, DBCACHE)
@ -1120,6 +1144,15 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback):
self.undo_history_callback = None
self.undodb = None
if self.update_env_version:
versionpath = os.path.join(self.path, BDBVERSFN)
try:
with open(versionpath, "w") as version_file:
version_file.write(str(db.version()))
except:
# Storing the version of Berkeley Db is not really vital.
pass
try:
clear_lock_file(self.get_save_path())
except IOError:

View File

@ -47,9 +47,12 @@ def get_description(mime_type):
progid = _get_prog_id(extension)
if progid:
hcr = ConnectRegistry(None, HKEY_CLASSES_ROOT)
desc = QueryValue(hcr, progid)
CloseKey(hcr)
try:
hcr = ConnectRegistry(None, HKEY_CLASSES_ROOT)
desc = QueryValue(hcr, progid)
CloseKey(hcr)
except WindowsError:
pass
if not desc:
desc = _("unknown")

File diff suppressed because it is too large Load Diff

View File

@ -351,14 +351,14 @@ def run():
try:
build_user_paths()
except OSError, msg:
error += [(_("Configuration error"), str(msg))]
error += [(_("Configuration error:"), str(msg))]
return error
except msg:
LOG.error("Error reading configuration.", exc_info=True)
return [(_("Error reading configuration"), str(msg))]
if not mime_type_is_defined(const.APP_GRAMPS):
error += [(_("Configuration error"),
error += [(_("Configuration error:"),
_("A definition for the MIME-type %s could not "
"be found \n\n Possibly the installation of Gramps "
"was incomplete. Make sure the MIME-types "
@ -425,7 +425,12 @@ def run():
from guiQML.grampsqml import startqml
startqml(error, argpars)
else:
from gui.grampsgui import startgtkloop
try:
from gui.grampsgui import startgtkloop
# no DISPLAY is a RuntimeError in an older pygtk (e.g. F14's 2.17)
except RuntimeError, msg:
error += [(_("Configuration error:"), str(msg))]
return error
startgtkloop(error, argpars)
else:
#CLI use of GRAMPS

View File

@ -309,6 +309,9 @@ class DbLoader(CLIDbLoader):
self.dbstate.db.set_save_path(filename)
else:
self.dbstate.no_database()
except gen.db.exceptions.BsddbDowngradeError, msg:
self.dbstate.no_database()
self._errordialog( _("Cannot open database"), str(msg))
except gen.db.exceptions.DbVersionError, msg:
self.dbstate.no_database()
self._errordialog( _("Cannot open database"), str(msg))

View File

@ -3,6 +3,7 @@
#
# Copyright (C) 2000-2006 Donald N. Allingham
# 2009 Gary Burton
# 2011 Michiel D. Nauta
#
# 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
@ -82,6 +83,11 @@ class EditEventRef(EditReference):
self.primtab = RefTab(self.dbstate, self.uistate, self.track,
_('_General'), tblref)
def _post_init(self):
date = self.top.get_object('eer_date_entry')
if not date.get_text_length():
date.grab_focus();
def _init_event(self):
if not self.db.readonly:
self.commit_event = self.db.commit_personal_event

View File

@ -3,6 +3,7 @@
#
# Copyright (C) 2000-2006 Donald N. Allingham
# 2009 Gary Burton
# 2011 Michiel D. Nauta / MathieuMD
#
# 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
@ -80,6 +81,14 @@ class EditSourceRef(EditReference):
self.primtab = RefTab(self.dbstate, self.uistate, self.track,
_('General'), tblref)
def _post_init(self):
title = self.top.get_object('title')
volume = self.top.get_object('volume')
if not title.get_text_length():
title.grab_focus();
elif not volume.get_text_length():
volume.grab_focus();
def _connect_signals(self):
self.define_ok_button(self.top.get_object('ok'),self.ok_clicked)
self.define_cancel_button(self.top.get_object('cancel'))

View File

@ -3,6 +3,7 @@
#
# Copyright (C) 2005-2007 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
# Copyright (C) 2011 Paul Franklin
#
# 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
@ -38,7 +39,6 @@ log = logging.getLogger(".")
#
#-------------------------------------------------------------------------
import const
import Utils
from gen.display.name import displayer as name_displayer
import Errors
from gen.plug._options import (Options, OptionHandler, OptionList,
@ -86,6 +86,11 @@ class Tool(object):
self.options = options_class
self.options.load_previous_values()
if hasattr(options_class, 'options_dict'):
old_opts = options_class.saved_options_dict
for key in options_class.options_dict:
if options_class.options_dict[key] != old_opts[key]:
self.options.options_dict[key] = old_opts[key]
def run_tool(self):
pass
@ -181,10 +186,12 @@ class CommandLineTool(object):
self.options_help[key] = self.option_class.options_help[key]
def parse_option_str(self):
from cli.plug import _convert_str_to_match_type
for opt in self.options_str_dict:
if opt in self.options_dict:
converter = Utils.get_type_converter(self.options_dict[opt])
self.options_dict[opt] = converter(self.options_str_dict[opt])
self.options_dict[opt] = \
_convert_str_to_match_type(self.options_str_dict[opt],
self.options_dict[opt])
self.option_class.handler.options_dict[opt] = self.options_dict[opt]
else:
print "Ignoring unknown option: %s" % opt
@ -254,6 +261,7 @@ def cli_tool(dbstate, name, category, tool_class, options_class, options_str_dic
clt = CommandLineTool(dbstate.db, name, category,
options_class, options_str_dict)
clt.option_class.saved_options_dict = clt.options_dict
# Exit here if show option was given
if clt.show:

View File

@ -30,7 +30,7 @@
plg = newplugin()
plg.id = 'ancestor_chart,BKI'
plg.name = _("Ancestor Tree")
plg.description = _("Produces a graphical ancestral tree")
plg.description = _("Produces a graphical ancestral tree (Book report)")
plg.version = '1.0'
plg.gramps_target_version = '3.4'
plg.status = STABLE
@ -90,7 +90,7 @@ plg.report_modes = [REPORT_MODE_GUI, REPORT_MODE_BKI, REPORT_MODE_CLI]
plg = newplugin()
plg.id = 'descend_chart,BKI'
plg.name = _("Descendant Tree")
plg.description = _("Produces a graphical descendant tree")
plg.description = _("Produces a graphical descendant tree (Book report)")
plg.version = '1.0'
plg.gramps_target_version = '3.4'
plg.status = STABLE
@ -128,7 +128,7 @@ plg.report_modes = [REPORT_MODE_GUI, REPORT_MODE_CLI]
plg = newplugin()
plg.id = 'family_descend_chart,BKI'
plg.name = _("Family Descendant Tree")
plg.description = _("Produces a graphical descendant tree around a family")
plg.description = _("Produces a graphical descendant tree around a family (Book report)")
plg.version = '1.0'
plg.status = STABLE
plg.fname = 'DescendTree.py'

View File

@ -38,7 +38,7 @@ plg.fname = 'ExportCsv.py'
plg.ptype = EXPORT
plg.export_function = 'exportData'
plg.export_options = 'CSVWriterOptionBox'
plg.export_options_title = ('CSV spreadsheet options')
plg.export_options_title = _('CSV spreadsheet options')
plg.extension = "csv"
#------------------------------------------------------------------------
@ -59,7 +59,7 @@ plg.fname = 'ExportFtree.py'
plg.ptype = EXPORT
plg.export_function = 'writeData'
plg.export_options = 'WriterOptionBox'
plg.export_options_title = ('Web Family Tree export options')
plg.export_options_title = _('Web Family Tree export options')
plg.extension = "wft"
#------------------------------------------------------------------------
@ -81,7 +81,7 @@ plg.fname = 'ExportGedcom.py'
plg.ptype = EXPORT
plg.export_function = 'export_data'
plg.export_options = 'WriterOptionBox'
plg.export_options_title = ('GEDCOM export options')
plg.export_options_title = _('GEDCOM export options')
plg.extension = "ged"
#------------------------------------------------------------------------
@ -102,7 +102,7 @@ plg.fname = 'ExportGeneWeb.py'
plg.ptype = EXPORT
plg.export_function = 'exportData'
plg.export_options = 'WriterOptionBox'
plg.export_options_title = ('GeneWeb export options')
plg.export_options_title = _('GeneWeb export options')
plg.extension = "gw"
#------------------------------------------------------------------------
@ -124,7 +124,7 @@ plg.fname = 'ExportPkg.py'
plg.ptype = EXPORT
plg.export_function = 'writeData'
plg.export_options = 'WriterOptionBox'
plg.export_options_title = ('Gramps package export options')
plg.export_options_title = _('Gramps package export options')
plg.extension = "gpkg"
#------------------------------------------------------------------------
@ -147,7 +147,7 @@ plg.fname = 'ExportXml.py'
plg.ptype = EXPORT
plg.export_function = 'export_data'
plg.export_options = 'WriterOptionBox'
plg.export_options_title = ('Gramps XML export options')
plg.export_options_title = _('Gramps XML export options')
plg.extension = "gramps"
#------------------------------------------------------------------------
@ -168,7 +168,7 @@ plg.fname = 'ExportVCalendar.py'
plg.ptype = EXPORT
plg.export_function = 'exportData'
plg.export_options = 'WriterOptionBox'
plg.export_options_title = ('vCalendar export options')
plg.export_options_title = _('vCalendar export options')
plg.extension = "vcs"
#------------------------------------------------------------------------
@ -189,5 +189,5 @@ plg.fname = 'ExportVCard.py'
plg.ptype = EXPORT
plg.export_function = 'exportData'
plg.export_options = 'WriterOptionBox'
plg.export_options_title = ('vCard export options')
plg.export_options_title = _('vCard export options')
plg.extension = "vcf"

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
#!/usr/bin/python
#!/usr/bin/env python
#
# Gramps - a GTK+/GNOME based genealogy program
@ -62,7 +62,7 @@ from gen.plug import Gramplet
from libmetadata import MetadataView, format_datetime
from gui.widgets import ValidatableMaskedEntry
from Errors import ValidationError
from QuestionDialog import WarningDialog, QuestionDialog, OptionDialog
from QuestionDialog import QuestionDialog, OptionDialog
from gen.lib import Date
@ -93,7 +93,6 @@ else:
#------------------------------------------------
# support functions
#------------------------------------------------
def _parse_datetime(value):
"""
Parse date and time and return a datetime object.
@ -163,8 +162,8 @@ _DATAMAP = {
"Exif.GPSInfo.GPSAltitudeRef" : "AltitudeRef",
"Exif.GPSInfo.GPSAltitude" : "Altitude",
"Exif.Photo.DateTimeDigitized" : "Digitized" }
_DATAMAP = dict((key, val) for key, val in _DATAMAP.items() )
_DATAMAP.update( (val, key) for key, val in _DATAMAP.items() )
_DATAMAP = dict( (key, val) for key, val in _DATAMAP.items())
_DATAMAP.update( (val, key) for key, val in _DATAMAP.items())
# define tooltips for all data entry fields
_TOOLTIPS = {
@ -202,7 +201,8 @@ _TOOLTIPS = {
# GPS Altitude (in meters)
"Altitude" : _("This is the measurement of Above or Below Sea Level. It is measured in meters."
"Example: 200.558, -200.558") }
_TOOLTIPS = dict( (key, tooltip) for key, tooltip in _TOOLTIPS.items() )
_TOOLTIPS = dict(
(key, tooltip) for key, tooltip in _TOOLTIPS.items())
# define tooltips for all buttons
# common buttons for all images
@ -230,7 +230,7 @@ _BUTTONTIPS = {
# Delete/ Erase/ Wipe Exif metadata button
"Delete" : _("WARNING: This will completely erase all Exif metadata "
"from this image! Are you sure that you want to do this?") }
"from this image! Are you sure that you want to do this?")}
# ------------------------------------------------------------------------
#
@ -292,25 +292,25 @@ class EditExifMetadata(Gramplet):
main_vbox.pack_start(messagearea, expand =False, fill =True, padding =0)
# Separator line before the buttons
main_vbox.pack_start(gtk.HSeparator(), expand =False, fill =True, padding =5)
main_vbox.pack_start(gtk.HSeparator(), expand =False, fill =False, padding =0)
# Thumbnail, ImageType, and Convert buttons
new_hbox = gtk.HBox(False, 0)
main_vbox.pack_start(new_hbox, expand =False, fill =True, padding =5)
main_vbox.pack_start(new_hbox, expand =False, fill =False, padding =0)
new_hbox.show()
# Thumbnail button
event_box = gtk.EventBox()
new_hbox.pack_start(event_box, expand =False, fill =True, padding =5)
new_hbox.pack_start(event_box, expand =False, fill =False, padding =0)
event_box.show()
button = self.__create_button(
"Thumbnail", _("Thumbnail"), [self.thumbnail_view])
"Thumbnail", _("Thumbnail"), [self.thumbnail_view], )
event_box.add(button)
# Image Types
event_box = gtk.EventBox()
new_hbox.pack_start(event_box, expand =False, fill =True, padding =5)
new_hbox.pack_start(event_box, expand =False, fill =False, padding =0)
event_box.show()
combo_box = gtk.combo_box_new_text()
@ -323,7 +323,7 @@ class EditExifMetadata(Gramplet):
# Convert button
event_box = gtk.EventBox()
new_hbox.pack_start(event_box, expand =False, fill =True, padding =5)
new_hbox.pack_start(event_box, expand =False, fill =False, padding =0)
event_box.show()
button = self.__create_button(
@ -335,7 +335,7 @@ class EditExifMetadata(Gramplet):
# Help, Edit, and Delete buttons
new_hbox = gtk.HBox(False, 0)
main_vbox.pack_start(new_hbox, expand =False, fill =True, padding =5)
main_vbox.pack_start(new_hbox, expand =False, fill =False, padding =0)
new_hbox.show()
for (widget, text, callback, icon, is_sensitive) in [
@ -343,9 +343,13 @@ class EditExifMetadata(Gramplet):
("Edit", False, [self.display_edit], gtk.STOCK_EDIT, False),
("Delete", False, [self._wipe_dialog], gtk.STOCK_DELETE, False) ]:
event_box = gtk.EventBox()
new_hbox.pack_start(event_box, expand =False, fill =False, padding =0)
event_box.show()
button = self.__create_button(
widget, text, callback, icon, is_sensitive)
new_hbox.pack_start(button, expand =False, fill =True, padding =5)
event_box.add(button)
# add viewing model
self.view = MetadataView()
@ -362,15 +366,8 @@ class EditExifMetadata(Gramplet):
return main_vbox
def db_changed(self):
"""
if media changes, then update addon...
"""
self.dbstate.db.connect('media-add', self.update)
self.dbstate.db.connect('media-delete', self.update)
self.dbstate.db.connect('media-edit', self.update)
self.dbstate.db.connect('media-rebuild', self.update)
self.connect_signal("Media", self.update)
self.dbstate.db.connect('media-update', self.update)
self.connect_signal('Media', self.update)
self.update()
def active_changed(self, handle):
@ -927,92 +924,91 @@ class EditExifMetadata(Gramplet):
"""
creates the editing area fields.
"""
tip = _("Click the close button when you are finished modifying this "
"image's Exif metadata.")
self.edtarea = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.edtarea.tooltip = tip
self.edtarea.set_title( self.orig_image.get_description() )
self.edtarea.set_default_size(525, 560)
self.edtarea.set_border_width(10)
self.edtarea.connect("destroy", lambda w: self.edtarea.destroy() )
main_scr_width = self.uistate.screen_width()
# on a screen of 1024 x 768, width = 614, height will always remain at 600 for netbooks
# with a screen height of 600 maximum...
width_ = int(main_scr_width * 0.60)
edtarea = gtk.Window(gtk.WINDOW_TOPLEVEL)
edtarea.tooltip = tip
edtarea.set_title( self.orig_image.get_description())
edtarea.set_size_request((width_ + 45), 550)
edtarea.set_border_width(10)
width_ -= 10 # width = 604
edtarea.connect("destroy", lambda w: edtarea.destroy())
# create a new scrolled window.
scrollwindow = gtk.ScrolledWindow()
scrollwindow.set_size_request(width_, 600)
scrollwindow.set_border_width(10)
width_ -= 10 # width = 594
# will show scrollbars only when necessary
scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.edtarea.add(scrollwindow)
edtarea.add(scrollwindow)
scrollwindow.show()
vbox = self.__build_edit_gui()
vbox = self.__build_edit_gui(width_)
scrollwindow.add_with_viewport(vbox)
self.edtarea.show()
vbox.show_all()
edtarea.show()
# display all fields and button tooltips...
# need to add Save and Close over here...
_BUTTONTIPS.update( (key, tip) for key, tip in {
# need to add Save, Clear, and Close over here...
_BUTTONTIPS.update(
(key, tip) for key, tip in {
# Add the Save button...
"Save" : _("Saves a copy of the data fields into the image's Exif metadata."),
# Add the Save button...
"Save" : _("Saves a copy of the data fields into the image's Exif metadata."),
# Add the Close button...
"Close" : _("Closes this popup Edit window.\n"
"WARNING: This action will NOT Save any changes/ modification made to this "
"image's Exif metadata."),
# Re- display the data fields button...
"Copy" : _("Re -display the data fields that were cleared from the Edit Area."),
# Clear button...
"Clear" : _("This button will clear all of the data fields shown here."),
# Add the Clear button...
"Clear" : _("This button will clear all of the data fields shown here."),
# Re- display the data fields button...
"Copy" : _("Re -display the data fields that were cleared from the Edit Area.") }.items() )
# Add the Close button...
"Close" : _("Closes this popup Edit window.\n"
"WARNING: This action will NOT Save any changes/ modification made to this "
"image's Exif metadata.") }.items() )
# True, True -- all data fields and button tooltips will be displayed...
self._setup_widget_tips(fields =True, buttons = True)
# display all data fields and their values...
self.edit_area(_get_exif_keypairs(self.plugin_image) )
self.edit_area(_get_exif_keypairs(self.plugin_image))
def __build_edit_gui(self):
def __build_edit_gui(self, width_):
"""
will build the edit screen ...
creates the content for the edit window...
"""
main_vbox = gtk.VBox()
main_vbox.set_border_width(10)
main_vbox.set_size_request(480, 460)
width_ -= 10 # width = 584
# Notification Area for the Edit Area...
label = self.__create_label("EditMessage", False, width =440, height = 25)
main_vbox.pack_start(label, expand = False, fill =True, padding =5)
# 520 is the normal height of this vertical box...
main_vbox.set_size_request(width_, 500)
# Notification Area for the Edit Area window...
label = self.__create_label("EditMessage", False, width =(width_ - 62), height =25)
main_vbox.pack_start(label, expand = False, fill =True, padding =0)
# Media Title Frame...
width_ -= 10 # 574 on a screen width of 1024
title_frame = gtk.Frame(_("Media Object Title"))
title_frame.set_size_request(470, 60)
title_frame.set_size_request(width_, 60) # width = 574
main_vbox.pack_start(title_frame, expand =False, fill =True, padding =10)
title_frame.show()
new_hbox = gtk.HBox(False, 0)
title_frame.add(new_hbox)
new_hbox.show()
event_box = self.__create_event_entry("MediaTitle", 440, 40, 100, "Entry", [] )
new_hbox.pack_start(event_box, expand =False, fill =True, padding =10)
# create the data fields...
# ***Description, Artist, and Copyright
gen_frame = gtk.Frame(_("General Data"))
gen_frame.set_size_request(470, 155)
main_vbox.pack_start(gen_frame, expand =False, fill =True, padding =10)
gen_frame.show()
new_vbox = gtk.VBox(False, 0)
gen_frame.add(new_vbox)
title_frame.add(new_vbox)
new_vbox.show()
for widget, text in [
("Description", _("Description :") ),
("Artist", _("Artist :") ),
("Copyright", _("Copyright :") ) ]:
("MediaTitle", _("media Title: ")) ]:
new_hbox = gtk.HBox(False, 0)
new_vbox.pack_start(new_hbox, expand =False, fill =False, padding =5)
@ -1021,17 +1017,42 @@ class EditExifMetadata(Gramplet):
label = self.__create_label(False, text, width =90, height =25)
new_hbox.pack_start(label, expand =False, fill =False, padding =0)
event_box = self.__create_event_entry(widget, 360, 30, 100, "Entry", [] )
event_box = self.__create_event_entry(widget, 464, 30, 100, "Entry", [])
new_hbox.pack_start(event_box, expand =False, fill =False, padding =0)
# create the data fields...
# ***Description, Artist, and Copyright
gen_frame = gtk.Frame(_("General Data"))
gen_frame.set_size_request(width_, 155) # width = 574
main_vbox.pack_start(gen_frame, expand =False, fill =True, padding =10)
gen_frame.show()
new_vbox = gtk.VBox(False, 0)
gen_frame.add(new_vbox)
new_vbox.show()
for widget, text in [
("Description", _("Description: ")),
("Artist", _("Artist: ")),
("Copyright", _("Copyright: ")) ]:
new_hbox = gtk.HBox(False, 0)
new_vbox.pack_start(new_hbox, expand =False, fill =False, padding =5)
new_hbox.show()
label = self.__create_label(False, text, width =90, height =25)
new_hbox.pack_start(label, expand =False, fill =False, padding =0)
event_box = self.__create_event_entry(widget, 464, 30, 100, "Entry", [])
new_hbox.pack_start(event_box, expand =False, fill =False, padding =0)
# iso format: Year, Month, Day spinners...
datetime_frame = gtk.Frame(_("Date/ Time"))
datetime_frame.set_size_request(470, 90)
datetime_frame.set_size_request(width_, 90) # width = 574
main_vbox.pack_start(datetime_frame, expand =False, fill =False, padding =0)
datetime_frame.show()
new_vbox = gtk.VBox(False, 0)
new_vbox.set_border_width(5)
datetime_frame.add(new_vbox)
new_vbox.show()
@ -1040,25 +1061,26 @@ class EditExifMetadata(Gramplet):
new_hbox.show()
for widget, text in [
("Original", _("Original Date/ Time :") ),
("Modified", _("Last Changed :") ) ]:
("Original", _("Original: ")),
("Modified", _("Modified: ")) ]:
vbox2 = gtk.VBox(False, 0)
new_hbox.pack_start(vbox2, expand =False, fill =False, padding =5)
vbox2.show()
label = self.__create_label(widget, text, width =150, height =25)
label = self.__create_label(widget, text, width =90, height =25)
vbox2.pack_start(label, expand =False, fill =False, padding =0)
label.show()
event_box = self.__create_event_entry(widget, 215, 30, 0, "Validate", [self.validate_datetime] )
# each box width = 157
event_box = self.__create_event_entry(widget, 272, 30, 0, "Validate", [self.validate_datetime])
vbox2.pack_start(event_box, expand =False, fill =False, padding =0)
self.dates[widget] = None
# GPS coordinates...
latlong_frame = gtk.Frame(_("Latitude/ Longitude/ Altitude GPS coordinates"))
latlong_frame.set_size_request(470, 80)
latlong_frame.set_size_request(width_, 80) # width = 574
main_vbox.pack_start(latlong_frame, expand =False, fill =False, padding =0)
latlong_frame.show()
@ -1083,7 +1105,7 @@ class EditExifMetadata(Gramplet):
vbox2.pack_start(label, expand =False, fill =False, padding =0)
label.show()
event_box = self.__create_event_entry(widget, 141, 30, 0, "Validate", [self.validate_coordinate])
event_box = self.__create_event_entry(widget, 178, 30, 0, "Validate", [self.validate_coordinate])
vbox2.pack_start(event_box, expand =False, fill =False, padding =0)
# Help, Save, Clear, Copy, and Close buttons...
@ -1093,21 +1115,19 @@ class EditExifMetadata(Gramplet):
for (widget, text, callback, icon, is_sensitive) in [
("Help", False, [self.__help_page], gtk.STOCK_HELP, True),
("Save", False, [self.save_metadata,
self.update], gtk.STOCK_SAVE, True),
("Save", False, [self.save_metadata, self.update], gtk.STOCK_SAVE, True),
("Clear", False, [self.clear_metadata], gtk.STOCK_CLEAR, True),
("Copy", False, [self.__display_exif_tags], gtk.STOCK_COPY, True),
("Close", False, [lambda w: self.edtarea.destroy()], gtk.STOCK_CLOSE, True) ]:
event_box = gtk.EventBox()
event_box.set_size_request(81, 30)
new_hbox.pack_start(event_box, expand =False, fill =True, padding =5)
event_box.set_size_request(112, 30)
new_hbox.pack_start(event_box, expand =False, fill =True, padding =1)
event_box.show()
event_box.add( self.__create_button(
widget, text, callback, icon, is_sensitive) )
main_vbox.show_all()
event_box.add(self.__create_button(
widget, text, callback, icon, is_sensitive)
)
return main_vbox
def set_datetime(self, widget, field):
@ -1149,7 +1169,6 @@ class EditExifMetadata(Gramplet):
"""
QuestionDialog(_("Edit Image Exif Metadata"), _("WARNING! You are about to completely "
"delete the Exif metadata from this image?"), gtk.STOCK_DELETE, self.strip_metadata)
self.update()
def clear_metadata(self, object):

View File

@ -6,6 +6,7 @@
# Copyright (C) 2009-2010 Gary Burton
# Contribution 2009 by Bob Ham <rah@bash.sh>
# Copyright (C) 2010 Jakim Friant
# Copyright (C) 2011 Paul Franklin
#
# 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
@ -112,7 +113,7 @@ class FamilyLinesOptions(MenuReportOptions):
person_list = PersonListOption(_('People of interest'))
person_list.set_help(_('People of interest are used as a starting '
'point when determining "family lines".'))
'point when determining "family lines".'))
add_option('gidlist', person_list)
followpar = BooleanOption(
@ -124,7 +125,7 @@ class FamilyLinesOptions(MenuReportOptions):
followchild = BooleanOption(_('Follow children to determine '
'"family lines"'), True)
followchild.set_help(_('Children will be considered when '
'determining "family lines".'))
'determining "family lines".'))
add_option('followchild', followchild)
remove_extra_people = BooleanOption(
@ -156,54 +157,56 @@ class FamilyLinesOptions(MenuReportOptions):
add_option('colorfemales', color_females)
color_unknown = ColorOption(_('Unknown'), '#e0e0e0')
color_unknown.set_help(
_('The colour to use when the gender is unknown.'))
color_unknown.set_help(_('The colour to use '
'when the gender is unknown.'))
add_option('colorunknown', color_unknown)
color_family = ColorOption(_('Families'), '#ffffe0')
color_family.set_help(_('The colour to use to display families.'))
add_option('colorfamilies', color_family)
self.limit_parents = BooleanOption(_('Limit the number of parents'),
self.limit_parents = BooleanOption(_('Limit the number of ancestors'),
False)
self.limit_parents.set_help(
_('The maximum number of ancestors to include.'))
self.limit_parents.set_help(_('Whether to '
'limit the number of ancestors.'))
add_option('limitparents', self.limit_parents)
self.limit_parents.connect('value-changed', self.limit_changed)
self.max_parents = NumberOption('', 50, 10, 9999)
self.max_parents.set_help(
_('The maximum number of ancestors to include.'))
self.max_parents.set_help(_('The maximum number '
'of ancestors to include.'))
add_option('maxparents', self.max_parents)
self.limit_children = BooleanOption(_('Limit the number of children'),
self.limit_children = BooleanOption(_('Limit the number '
'of descendants'),
False)
self.limit_children.set_help(
_('The maximum number of children to include.'))
self.limit_children.set_help(_('Whether to '
'limit the number of descendants.'))
add_option('limitchildren', self.limit_children)
self.limit_children.connect('value-changed', self.limit_changed)
self.max_children = NumberOption('', 50, 10, 9999)
self.max_children.set_help(
_('The maximum number of children to include.'))
self.max_children.set_help(_('The maximum number '
'of descendants to include.'))
add_option('maxchildren', self.max_children)
# --------------------
add_option = partial(menu.add_option, _('Images'))
# --------------------
self.include_images = BooleanOption(
_('Include thumbnail images of people'), True)
self.include_images.set_help(
_('The maximum number of children to include.'))
self.include_images = BooleanOption(_('Include '
'thumbnail images of people'),
True)
self.include_images.set_help(_('Whether to '
'include thumbnail images of people.'))
add_option('incimages', self.include_images)
self.include_images.connect('value-changed', self.images_changed)
self.image_location = EnumeratedListOption(_('Thumbnail location'), 0)
self.image_location.add_item(0, _('Above the name'))
self.image_location.add_item(1, _('Beside the name'))
self.image_location.set_help(
_('Where the thumbnail image should appear relative to the name'))
self.image_location.set_help(_('Where the thumbnail image '
'should appear relative to the name'))
add_option('imageonside', self.image_location)
# ---------------------
@ -214,8 +217,8 @@ class FamilyLinesOptions(MenuReportOptions):
for i in range(len(_COLORS)):
color.add_item(_COLORS[i]["value"], _COLORS[i]["name"])
color.set_help(_("Males will be shown with blue, females "
"with red, unless otherwise set above for filled."
" If the sex of an individual "
"with red, unless otherwise set above for filled. "
"If the sex of an individual "
"is unknown it will be shown with gray."))
add_option("color", color)
@ -250,7 +253,7 @@ class FamilyLinesOptions(MenuReportOptions):
include_private = BooleanOption(_('Include private records'), False)
include_private.set_help(_('Whether to include names, dates, and '
'families that are marked as private.'))
'families that are marked as private.'))
add_option('incprivate', include_private)
self.limit_changed()

View File

@ -587,8 +587,8 @@ class GeneWebParser(object):
title = self.create_event(
gen.lib.EventType.NOB_TITLE, ttitle, tstart, tplace)
# TODO: Geneweb has a start date and an end date, and therefore
# supprts stuff like: FROM about 1955 TO between 1998 and 1999
# gramps only supports one single date ore range.
# supports stuff like: FROM about 1955 TO between 1998 and 1999
# gramps only supports one single date or range.
if tname and tname != "*":
n = gen.lib.Note()
n.set(tname)

View File

@ -364,6 +364,29 @@
<date name="1. Weihnachtsfeiertag" type="religious" value="*/12/25" />
<date name="2. Weihnachtsfeiertag" type="religious" value="*/12/26" />
</country>
<country _name="Japan">
<date name="元日" value="*/1/1" />
<date name="成人の日" value="*/2/mon/jan" />
<date name="建国記念の日" value="*/2/11" />
<date name="春分の日" value="*/3/20" />
<date name="春分の日" value="*/3/21" />
<date name="昭和の日" value="*/4/29" />
<date name="憲法記念日" value="*/5/3" />
<date name="みどりの日" value="*/5/4" />
<date name="こどもの日" value="*/5/5" />
<date name="海の日" value="*/3/mon/jul" />
<date name="敬老の日" value="*/3/mon/sep" />
<date name="秋分の日" value="*/9/22" />
<date name="秋分の日" value="*/9/23" />
<date name="体育の日" value="*/2/mon/oct" />
<date name="文化の日" value="*/11/3" />
<date name="勤労感謝の日" value="*/11/23" />
<date name="天皇誕生日" value="*/12/23" />
<date name="皇太子明仁親王の結婚" value="1959/4/10" />
<date name="昭和天皇の大喪の礼" value="1989/2/24" />
<date name="天皇(明仁)即位記念" value="1990/11/12" />
<date name="皇太子徳仁親王の結婚" value="1993/6/9" />
</country>
<country _name="Sweden - Holidays">
<date name="Nyårsdagen" value="*/1/1" type="religious" />
<date name="Trettondagen" value="*/1/6" type="religious" />
@ -394,19 +417,16 @@
<date name="April Fool's Day" value="*/4/1" type="secular" />
<date name="Arbor Day" value="*/-1/fri/apr" type="secular" />
<date name="Earth Day" value="*/4/22" type="secular" />
<date name="Easter" type="religious" value="> easter(y)" />
<date name="Ash Wednesday" type="religious" value="> easter(y)" offset="-46" />
<date name="Mardi Gras" type="religious" value="> easter(y)" offset="-47" />
<date name="Easter" value="> easter(y)" type="religious" />
<date name="Ash Wednesday" value="> easter(y)" type="religious" offset="-46" />
<date name="Mardi Gras" value="> easter(y)" type="religious" offset="-47" />
<date name="Daylight Saving begins" value="> dst(y)[0]" type="informational" />
<date name="Income Taxes due" value="*/4/15" type="national"
if="date.weekday().__cmp__(4)-1" />
<date name="Income Taxes due" value="*/4/16" type="national"
if="date.weekday() == 0" />
<date name="Income Taxes due" value="*/4/17" type="national"
if="date.weekday() == 0" />
<date name="Income Taxes due" value="*/4/15" type="national" if="date.weekday().__cmp__(4)-1" />
<date name="Income Taxes due" value="*/4/16" type="national" if="date.weekday() == 0" />
<date name="Income Taxes due" value="*/4/17" type="national" if="date.weekday() == 0" />
<date name="Daylight Saving ends" value="> dst(y)[1]" type="informational" />
<date name="Inauguration Day" value="*/1/20" if="(y - 1980) % 4 == 1" type="national" />
<date name="Passover" type="religious" value="> passover(y)" />
<date name="Inauguration Day" value="*/1/20" type="national" if="(y - 1980) % 4 == 1" />
<date name="Passover" value="> passover(y)" type="religious" />
<date name="Assistants' Day" value="*/-1/sat/apr" offset="-3" type="secular" />
<date name="Cinco de Mayo" value="*/5/5" type="secular" />
<date name="Armed Forces Day" value="*/3/sat/may" type="secular" />
@ -417,20 +437,20 @@
<date name="Independence Day" value="*/7/4" type="national" />
<date name="Parents' Day" value="*/4/sun/jul" type="secular" />
<date name="Labor Day" value="*/1/mon/sep" type="national" />
<date name="Grandparents' Day" value="*/1/mon/sep" offset="6" type="secular" />
<date name="Grandparents' Day" value="*/1/mon/sep" type="secular" offset="6" />
<date name="Columbus Day" value="*/2/mon/oct" type="secular" />
<date name="Ramadan begins" value="2006/09/24" type="religious" />
<date name="Ramadan begins" value="2007/09/13" type="religious" />
<date name="Ramadan begins" value="2008/09/2" type="religious" />
<date name="Ramadan begins" value="2009/08/22" type="religious" />
<date name="Yom Kippur" type="religious" value="> passover(y)" offset="172" />
<date name="Yom Kippur" value="> passover(y)" type="religious" offset="172" />
<date name="United Nations Day" value="*/10/24" type="secular" />
<date name="Halloween" value="*/10/31" type="secular" />
<date name="Election Day" value="*/11/2" offset="tue" type="secular" />
<date name="Election Day" value="*/11/2" type="secular" offset="tue" />
<date name="Veterans Day" value="*/11/11" type="national" />
<date name="Thanksgiving" value="*/4/thu/nov" type="national" />
<date name="Hanukkah begins" type="religious" value="> hanuka(y)" />
<date name="Christmas" value="*/12/25" type="national" />
<date name="Hanukkah begins" value="> hanuka(y)" type="religious" />
<date name="Christmas" value="*/12/25" type="religious" />
<date name="Kwanzaa begins" value="*/12/26" type="religious" />
</country>
<country _name="Jewish Holidays">

View File

@ -5558,7 +5558,10 @@ class GedcomParser(UpdateCallback):
"""
if not state.location:
state.location = gen.lib.Location()
self.__parse_note(line, state.event, state.level+1)
if state.event:
self.__parse_note(line, state.event, state.level+1)
else:
self.__not_recognized(line, state.level)
def __optional_note(self, line, state):
"""

View File

@ -122,19 +122,17 @@ class OdfBackend(DocBackend):
if tagtype not in self.SUPPORTED_MARKUP:
return None
if ( tagtype == DocBackend.FONTCOLOR ):
return ('<text:span text:style-name=\"FontColor__%s__\">' %
self.ESCAPE_FUNC()(value),
return ('<text:span text:style-name=\"FontColor__%s__\">' % value,
'</text:span>')
elif ( tagtype == DocBackend.FONTFACE ):
return ('<text:span text:style-name=\"FontFace__%s__\">' %
self.ESCAPE_FUNC()(value),
return ('<text:span text:style-name=\"FontFace__%s__\">' %
self.ESCAPE_FUNC()(value),
'</text:span>')
elif ( tagtype == DocBackend.FONTSIZE ):
return ('<text:span text:style-name=\"FontSize__%d__\">' % value,
return ('<text:span text:style-name=\"FontSize__%d__\">' % value,
'</text:span>')
else: #elif ( tagtype == DocBackend.HIGHLIGHT ):
return ('<text:span text:style-name=\"FontHighlight__%s__\">' %
self.ESCAPE_FUNC()(value),
return ('<text:span text:style-name=\"FontHighlight__%s__\">' % value,
'</text:span>')
def format_link(self, value):

View File

@ -160,10 +160,10 @@ class osmGpsMap():
def build_widget(self):
self.vbox = gtk.VBox(False, 0)
cache_path = os.path.join(const.HOME_DIR, 'maps')
cache_path = config.get('geography.path')
if not os.path.isdir(cache_path):
try:
os.mkdir(cache_path, 0750)
os.makedirs(cache_path, 0755) # create dir like mkdir -p
except:
ErrorDialog(_("Can't create tiles cache directory %s") %
cache_path )
@ -178,10 +178,10 @@ class osmGpsMap():
self.osm.image_remove_all()
self.vbox.remove(self.osm)
self.osm.destroy()
tiles_path=os.path.join(GEOGRAPHY_PATH, constants.tiles_path[map_type])
tiles_path=os.path.join(config.get('geography.path'), constants.tiles_path[map_type])
if not os.path.isdir(tiles_path):
try:
os.mkdir(tiles_path, 0750)
os.makedirs(tiles_path, 0755) # create dir like mkdir -p
except:
ErrorDialog(_("Can't create tiles cache directory for '%s'.") %
constants.map_title[map_type])

View File

@ -4,7 +4,7 @@
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
# Copyright (C) 2011 PaulFranklin
# Copyright (C) 2011 Paul Franklin
#
# 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
@ -81,6 +81,7 @@ WIKI_HELP_SEC = _('manual|Verify_the_Data...')
_person_cache = {}
_family_cache = {}
_event_cache = {}
_today = gen.lib.date.Today().get_sort_value()
def find_event(db, handle):
if handle in _event_cache:
@ -359,6 +360,7 @@ class Verify(tool.Tool, ManagedWindow, UpdateCallback):
BirthAfterDeath(self.db,person),
BaptAfterBury(self.db,person),
OldAge(self.db,person, oldage,estimate_age),
OldAgeButNoDeath(self.db,person, oldage,estimate_age),
UnknownGender(self.db,person),
MultipleParents(self.db,person),
MarriedOften(self.db,person,wedder),
@ -736,7 +738,7 @@ class VerifyOptions(tool.ToolOptions):
"Number of years"),
'oldunm' : ("=num","Maximum age for an unmarried person"
"Number of years"),
'estimate_age' : ("=0/1","Whether to estimate missing dates",
'estimate_age' : ("=0/1","Whether to estimate missing or inexact dates",
["Do not estimate","Estimate dates"],
True),
'invdate' : ("=0/1","Whether to check for invalid dates"
@ -1539,3 +1541,26 @@ class MarriedRelation(FamilyRule):
def get_message(self):
return _("Marriage date but not married")
class OldAgeButNoDeath(PersonRule):
ID = 32
SEVERITY = Rule.WARNING
def __init__(self,db,person, old_age,est):
PersonRule.__init__(self,db,person)
self.old_age = old_age
self.est = est
def _get_params(self):
return (self.old_age,self.est)
def broken(self):
birth_date = get_birth_date(self.db,self.obj,self.est)
dead = get_death_date(self.db,self.obj,True) # if no death use burial
if dead or not birth_date:
return 0
age = ( _today - birth_date ) / 365
return ( age > self.old_age )
def get_message(self):
return _("Old age but no death")

View File

@ -221,7 +221,7 @@
</child>
<child>
<object class="GtkCheckButton" id="estimate_age">
<property name="label" translatable="yes">_Estimate missing dates</property>
<property name="label" translatable="yes">_Estimate missing or inexact dates</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>

View File

@ -48,7 +48,7 @@ if not (TOOLKIT == NOWEB):
register(VIEW,
id = 'htmlview',
name = _("Html View"),
description = _("A view allowing to see html pages embedded in Gramps"),
description = _("A view showing html pages embedded in Gramps"),
version = '1.0',
gramps_target_version = '3.4',
status = STABLE,

View File

@ -60,7 +60,7 @@ order = START,
register(VIEW,
id = 'grampletview',
name = _("Gramplet View"),
description = _("The view allowing to see Gramplets"),
description = _("The view showing Gramplets"),
version = '1.0',
gramps_target_version = '3.4',
status = STABLE,

View File

@ -95,17 +95,12 @@ import gen.mime
from gen.display.name import displayer as _nd
from DateHandler import displayer as _dd
from gen.proxy import PrivateProxyDb, LivingProxyDb
from libhtmlconst import _CHARACTER_SETS, _CC, _COPY_OPTIONS
from libhtmlconst import _CHARACTER_SETS, _CC, _COPY_OPTIONS, openstreet_jsc, google_jsc
# import for Place Map Pages...
from libhtmlconst import openstreet_jsc, google_jsc
# import HTML Class from
# src/plugins/lib/libhtml.py
# import HTML Class from src/plugins/lib/libhtml.py
from libhtml import Html
# import styled notes from
# src/plugins/lib/libhtmlbackend.py
# import styled notes from src/plugins/lib/libhtmlbackend.py
from libhtmlbackend import HtmlBackend, process_spaces
from libgedcom import make_gedcom_date
@ -344,7 +339,7 @@ class BasePage(object):
self.noid = report.options['nogid']
self.linkhome = report.options['linkhome']
self.create_media = report.options['gallery']
self.inc_thumbnails = report.options['inc_thumbnails']
self.create_thumbs_only = report.options['create_thumbs_only']
self.inc_families = report.options['inc_families']
self.inc_events = report.options['inc_events']
@ -653,8 +648,6 @@ class BasePage(object):
@param: place_lat_long -- for use in Family Map Pages
"""
placetitle = place.get_title()
latitude, longitude = "", ""
latitude = place.get_latitude()
longitude = place.get_longitude()
@ -1249,12 +1242,13 @@ class BasePage(object):
inc_repos = True
if (not self.report.inc_repository or
not len(self.report.database.get_repository_handles()) ):
inc_repos = False
inc_repos = False
# include thumbnails preview page or not?
inc_thumbnails = True
if (not self.create_media or not self.report.inc_thumbnails):
inc_thumbnails = False
# create media pages...
if self.create_media:
_create_media_link = True
if self.create_thumbs_only:
_create_media_link = False
# determine which menu items will be available?
navs = [
@ -1265,8 +1259,8 @@ class BasePage(object):
('families', _("Families"), self.report.inc_families),
('places', _("Places"), True),
('events', _("Events"), self.report.inc_events),
('media', _("Media"), self.create_media),
('thumbnails', _("Thumbnails"), inc_thumbnails),
('media', _("Media"), _create_media_link),
('thumbnails', _("Thumbnails"), True),
('sources', _("Sources"), True),
('repositories', _("Repositories"), inc_repos),
("addressbook", _("Address Book"), self.report.inc_addressbook),
@ -1982,7 +1976,7 @@ class BasePage(object):
spouse = db.get_person_from_handle(spouse_handle)
rtype = str(family.get_relationship())
# display family relationship status...
# display family relationship status, and add spouse to FamilyMapPages
if spouse:
if self.familymappages:
self._get_event_place(spouse, ppl_handle_list, place_lat_long)
@ -2093,9 +2087,12 @@ class BasePage(object):
with Html("div", class_ = "thumbnail") as thumbnail:
# begin hyperlink
hyper = Html("a", href = url, title = name) + (
Html("img", src = img_url, alt = name)
)
if not self.create_thumbs_only:
hyper = Html("a", href = url, title = name) + (
Html("img", src = img_url, alt = name)
)
else:
hyper = Html("img", src =img_url, alt =name)
thumbnail += hyper
if usedescr:
@ -2114,20 +2111,24 @@ class BasePage(object):
@param: usedescr - add description to hyperlink
"""
url = self.report.build_url_fname(handle, "img", up)
name = html_escape(name)
# begin thumbnail division
with Html("div", class_ = "thumbnail") as thumbnail:
document_url = self.report.build_url_image("document.png", "images", up)
# begin hyperlink
hyper = Html("a", href = url, title = html_escape(name))
thumbnail += hyper
url = self.report.build_url_image("document.png", "images", up)
hyper += Html("img", src = url, alt = html_escape(name), title = html_escape(name))
if not self.create_thumbs_only:
document_link = Html("a", href =url, title = name) + (
Html("img", src =document_url, alt =name)
)
else:
document_link = Html("img", src =document_url, alt =name)
if usedescr:
hyper += Html('br')
hyper += Html("span", html_escape(name), inline = True)
document_link += Html('br') + (
Html("span", name, inline =True)
)
thumbnail += document_link
# return thumbnail division to its callers
return thumbnail
@ -2441,10 +2442,10 @@ class IndividualListPage(BasePage):
if not first_family:
tcell += ", "
use_link = check_person_database(partner_handle, ppl_handle_list)
if use_link:
if use_link:
url = self.report.build_url_fname_html(partner_handle, "ppl")
tcell += self.person_link(url, partner, _NAME_STYLE_DEFAULT,
gid = partner.gramps_id)
gid = partner.get_gramps_id())
else:
tcell += self.get_name(partner)
first_family = False
@ -2861,7 +2862,8 @@ class FamilyPage(BasePage):
use_link = check_person_database(partner_handle, ppl_handle_list)
if use_link:
url = self.report.build_url_fname_html(partner_handle, 'ppl', up =self.up)
partner_link = self.person_link(url, partner, _NAME_STYLE_DEFAULT, gid = partner.get_gramps_id())
partner_link = self.person_link(url, partner, _NAME_STYLE_DEFAULT,
gid = partner.get_gramps_id())
else:
partner_link = self.get_name(partner)
@ -4307,6 +4309,7 @@ class ThumbnailPreviewPage(BasePage):
def __init__(self, report, title, cb_progress):
BasePage.__init__(self, report, title)
db = report.database
self.create_thumbs_only = report.options['create_thumbs_only']
sort = Sort.Sort(db)
self.photo_keys = sorted(self.report.photo_list, key =sort.by_media_title_key)
@ -4316,8 +4319,13 @@ class ThumbnailPreviewPage(BasePage):
media_list = []
for phandle in self.photo_keys:
photo = db.get_object_from_handle(phandle)
if (photo and photo.get_mime_type().startswith("image/")):
media_list.append( (photo.get_description(), phandle, photo) )
if photo:
if photo.get_mime_type().startswith("image"):
media_list.append((photo.get_description(), phandle, photo))
if self.create_thumbs_only:
copy_thumbnail(self.report, phandle, photo)
if not media_list:
return
media_list.sort()
@ -4452,19 +4460,27 @@ class ThumbnailPreviewPage(BasePage):
"""
return Html("a", index, title =html_escape(name), href ="#%d" % index)
def thumb_hyper_image(self, img_src, subdir, fname, name):
def thumb_hyper_image(self, thumbnailUrl, subdir, fname, name):
"""
eplaces media_link() because it doesn't work for this instance
"""
name = html_escape(name)
url = "/".join(self.report.build_subdirs(subdir, fname) + [fname]) + self.ext
with Html("div", class_ ="thumbnail") as section:
thumb = Html("a", title =name, href =url) + (
Html("img", alt =name, src =img_src)
)
section += thumb
with Html("div", class_ ="content", id ="ThumbnailPreview") as section:
with Html("div", class_="snapshot") as snapshot:
section += snapshot
with Html("div", class_ ="thumbnail") as thumbnail:
snapshot += thumbnail
if not self.create_thumbs_only:
thumbnail_link = Html("a", href =url, title =name) + (
Html("img", src =thumbnailUrl, alt =name)
)
else:
thumbnail_link = Html("img", src =thumbnailUrl, alt =name)
thumbnail += thumbnail_link
return section
class DownloadPage(BasePage):
@ -4857,6 +4873,30 @@ class IndividualPage(BasePage):
# sort place_lat_long based on latitude and longitude order...
place_lat_long.sort()
# create the array, if there are more than one set of coordinates to be displayed?
if number_markers > 1:
if self.googleopts == "FamilyLinks":
tracelife = """
var tracelife = ["""
# place titles Array for place maps...
titleArray = """
var titleArray = ["""
for index in xrange(0, (number_markers - 1)):
dataline = place_lat_long[index]
latitude, longitude, placetitle = dataline[0], dataline[1], dataline[2]
tracelife += """
new google.maps.LatLng(%s, %s),""" % (latitude, longitude)
titleArray += """'%s',""" % placetitle
dataline = place_lat_long[-1]
latitude, longitude, placetitle = dataline[0], dataline[1], dataline[2]
tracelife += """
new google.maps.LatLng(%s, %s) ];""" % (latitude, longitude)
titleArray += """
'%s' ];""" % placetitle
of = self.report.create_file(person.get_handle(), "maps")
self.up = True
familymappage, head, body = self.write_header(_("Family Map"))
@ -4880,18 +4920,19 @@ class IndividualPage(BasePage):
src ="http://www.openlayers.org/api/OpenLayers.js", inline =True)
# begin inline javascript code
# because jsc is a string, it does NOT have to properly indented
# because jsc is a docstring, it does NOT have to properly indented
with Html("script", type ="text/javascript", indent =False) as jsc:
# Google Maps add their javascript inside of the head element...
if self.mapservice == "Google":
head += jsc
# if the number of places is only 1, then use code from imported javascript?
if number_markers == 1:
data = place_lat_long[0]
jsc += google_jsc % (data[0], data[1])
dataline = place_lat_long[0]
latitude, longitude = dataline[0], dataline[1]
jsc += google_jsc % (latitude, longitude)
# Google Maps add their javascript inside of the head element...
else:
if self.googleopts == "FamilyLinks":
jsc += """
@ -4906,72 +4947,90 @@ class IndividualPage(BasePage):
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var lifeHistory = [""" % (midX_, midY_, zoomlevel)
for index in xrange(0, (number_markers - 1)):
latitude, longitude = place_lat_long[index][0], place_lat_long[index][1]
jsc += """ new google.maps.LatLng(%s, %s),""" % (latitude, longitude)
latitude, longitude = place_lat_long[-1][0], place_lat_long[-1][1]
jsc += """ new google.maps.LatLng(%s, %s) ];
var flightPath = new google.maps.Polyline({
path: lifeHistory,
path: %s,
strokeColor: "#FF0000",
strokeOpacity: 1.0,
strokeWeight: 2
});
flightPath.setMap(map);
}""" % (latitude, longitude)
}""" % (midX_, midY_, zoomlevel, lifetrace)
# Google Maps Markers only...
elif self.googleopts == "Markers":
if (not midX_ and not midY_):
midX_, midY_ = conv_lat_lon(place_lat_long[0][0], place_lat_long[0][1], "D.D8")
jsc += """
//<![CDATA[
var centre = new google.maps.LatLng(%s, %s);
var gpsCoords = [""" % (midX_, midY_)
var centre = new google.maps.LatLng(%s, %s);""" % (midX_, midY_)
jsc += """
var myCoordinates = ["""
for index in xrange(0, (number_markers - 1)):
latitude, longitude = place_lat_long[index][0], place_lat_long[index][1]
jsc += """ new google.maps.LatLng(%s, %s),""" % (latitude, longitude)
latitude, longitude = place_lat_long[-1][0], place_lat_long[-1][1]
dataline = place_lat_long[index]
latitude, longitude, placetitle = dataline[0], dataline[1], dataline[2]
jsc += """ new google.maps.LatLng(%s, %s),""" % (latitude, longitude)
dataline = place_lat_long[-1]
latitude, longitude, placetitle = dataline[0], dataline[1], dataline[2]
jsc += """ new google.maps.LatLng(%s, %s)
];
var markers = [];
];""" % (latitude, longitude)
jsc += """
var markers = [];
var iterator = 0;
var map;
var map;
function initialize() {
var mapOptions = {
zoom: %d,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: centre
scrollwheel: false,
scaleControl: false,
backgroundColor: '#FFFFFF',
zoom: %d,
center: centre,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
}
function drop() {
for (var i = 0; i < gpsCoords.length; i++) {
function drop() {
for (var i = 0; i < myCoordinates.length; i++) {
setTimeout(function() {
addMarker();
addMarkers();
}, i * 1000);
}
}
function addMarker() {
function addMarkers() {
markers.push(new google.maps.Marker({
position: gpsCoords[iterator],
position: myCoordinates[iterator],
map: map,
draggable: true,
animation: google.maps.Animation.DROP
}));
iterator++;
}
//]]>""" % (latitude, longitude, zoomlevel)
//]]>""" % zoomlevel
# there is no need to add an ending "</script>",
# as it will be added automatically by libhtml()!
dont = """
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
function setMarkers(map, locations) {
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < locations.length; i++) {
var coordinates = locations[i];
var myLatLng = new google.maps.LatLng(coordinates[1], coordinates[2]);
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: coordinates[0]
});
bounds.extend(locations[i]);
map.fitBounds(bounds);
}"""
with Html("div", class_ ="content", id ="FamilyMapDetail") as mapbackground:
body += mapbackground
@ -5848,9 +5907,6 @@ class IndividualPage(BasePage):
hyper = self.person_link(url, person, _NAME_STYLE_DEFAULT)
else:
hyper = self.get_name(person)
# return hyperlink to its callers
# can be an actual hyperlink or just a person's name
return hyper
def pedigree_family(self):
@ -6284,8 +6340,9 @@ class NavWebReport(Report):
self.navigation = self.options["navigation"]
self.title = self.options['title']
self.inc_gallery = self.options['gallery']
self.inc_thumbnails = self.options['inc_thumbnails']
self.create_thumbs_only = self.options['create_thumbs_only']
self.inc_contact = self.options['contactnote'] or \
self.options['contactimg']
@ -6296,9 +6353,6 @@ class NavWebReport(Report):
# include families or not?
self.inc_families = self.options['inc_families']
# create a media thumbnail preview page or not?
self.inc_thumbnails = self.options['inc_thumbnails']
# create an event pages or not?
self.inc_events = self.options['inc_events']
@ -6457,11 +6511,11 @@ class NavWebReport(Report):
# build classes MediaListPage and MediaPage
if self.inc_gallery:
self.gallery_pages(source_list)
if not self.create_thumbs_only:
self.media_pages(source_list)
# build Thumbnail Preview Page...
if self.inc_thumbnails:
self.thumbnail_preview_page()
self.thumbnail_preview_page()
# Build classes source pages a second time to pick up sources referenced
# by galleries
@ -6727,7 +6781,7 @@ class NavWebReport(Report):
self.user.step_progress()
self.user.end_progress()
def gallery_pages(self, source_list):
def media_pages(self, source_list):
"""
creates MediaListPage and MediaPage
"""
@ -7267,6 +7321,12 @@ class NavWebOptions(MenuReportOptions):
addopt( "gallery", self.__gallery )
self.__gallery.connect('value-changed', self.__gallery_changed)
self.__create_thumbs_only = BooleanOption(_("Create and only use thumbnail- sized images"), True)
self.__create_thumbs_only.set_help(_("This options allows you the choice to not create any full- sized"
"images as in the Media Page, and only a thumb- sized images or not?"))
addopt("create_thumbs_only", self.__create_thumbs_only)
self.__create_thumbs_only.connect("value-changed", self.__gallery_changed)
self.__maxinitialimagewidth = NumberOption(_("Max width of initial image"),
_DEFAULT_MAX_IMG_WIDTH, 0, 2000)
self.__maxinitialimagewidth.set_help(_("This allows you to set the maximum width "
@ -7279,12 +7339,6 @@ class NavWebOptions(MenuReportOptions):
"of the image shown on the media page. Set to 0 for no limit."))
addopt( "maxinitialimageheight", self.__maxinitialimageheight)
self.__inc_thumbnails = BooleanOption(_("Create a media thumbnails preview page"), False)
self.__inc_thumbnails.set_help(_("Whether to create a thumbnail's preview page? "
"This will be hyper- linked to the Media List Page only!")
)
addopt("inc_thumbnails", self.__inc_thumbnails)
self.__gallery_changed()
nogid = BooleanOption(_('Suppress Gramps ID'), False)
@ -7525,17 +7579,30 @@ class NavWebOptions(MenuReportOptions):
"""
Handles the changing nature of gallery
"""
_gallery_option = self.__gallery.get_value()
_create_thumbs_only_option = self.__create_thumbs_only.get_value()
if not self.__gallery.get_value():
self.__maxinitialimagewidth.set_available(False)
self.__maxinitialimageheight.set_available(False)
self.__inc_thumbnails.set_available(False)
else:
# images and media objects to be used, make all opti8ons available...
if _gallery_option:
self.__create_thumbs_only.set_available(True)
self.__maxinitialimagewidth.set_available(True)
self.__maxinitialimageheight.set_available(True)
self.__inc_thumbnails.set_available(True)
# thumbnail-sized images only...
if _create_thumbs_only_option:
self.__maxinitialimagewidth.set_available(False)
self.__maxinitialimageheight.set_available(False)
# full- sized images and Media Pages will be created...
else:
self.__maxinitialimagewidth.set_available(True)
self.__maxinitialimageheight.set_available(True)
# no images or media objects are to be used...
else:
self.__create_thumbs_only.set_available(False)
self.__maxinitialimagewidth.set_available(False)
self.__maxinitialimageheight.set_available(False)
def __living_changed(self):
"""
@ -7897,6 +7964,8 @@ def build_event_data(db, ppl_handle_list):
if event:
event_types.append(str(event.type))
event_handle_list.append(evt_ref.ref)
# return event_handle_list and event types to its caller
return event_handle_list, event_types
def check_person_database(phandle, ppl_handle_list):

View File

@ -20,14 +20,14 @@
#
# $Id: Web_Basic-Blue.css 15540 2010-06-07 16:32:00Z robhealey1 $
#
**************************************************************************************************
*************************************************
GRAMPS Cascading Style Sheet
Style Name: Basic Blue Stylesheet
Original Style Author: Jason M. Simanek (2008)
***************************************************************************************************
--------------------------------------------------------------------------------------------------
*************************************************
-------------------------------------------------
Color Palette
--------------------------------------------------------------------------------------------------
-------------------------------------------------
DK. Blue #00029D
Lt. Blue #BCEAF6
Green #13A926
@ -42,6 +42,8 @@ Unknown #000
===== Web Graphics =====
Males Web_Gender_Male.png
Females Web_Gender_Female.png
*************************************************
*/
/* NarrativeWeb Styles
@ -51,42 +53,6 @@ body {
color: #FFF;
}
/* Menu Elements
================================================= */
div#navigation ul, div#subnavigation ul {
font: normal .9em sans-serif;
background-color: #00029D;
}
div#navigation ul li,
div#subnavigation ul li {
border-color: #BCEAF6;
}
#navigation ul li:after, #subnavigation ul li:after,
#alphabet ul li:after {
color: #139A26;
}
div#navigation ul li a, div#subnavigation ul li a {
color: #FFF;
}
div#navigation ul li a:hover,
div#subnavigation ul li a:hover {
color: #000;
}
div#navigation ul li.CurrentSection a,
div#subnavigation ul li.CurrentSection a {
background-color: #BCEAF6;
font: bold 14px sans;
color: #000;
}
div#navigation ul li.CurrentSection a:hover {
background-color: #BCEAF6;
color: #000;
}
div#subnavigation ul li.CurrentSection a:hover {
background-color: #000;
color: #FFF;
}
/* General Elements
================================================= */
div {
@ -130,7 +96,7 @@ img {
padding: 2em 0 0 0;
background: none;
}
.content div.snapshot div.thumbnail a {
.content div.snapshot div.thumbnail a, .content div.snapshot div.thumbnail img {
display: block;
width: 96px;
margin: 0 auto;
@ -143,13 +109,6 @@ img {
clear: both;
}
/* Gramps Styled Notes
------------------------------------------------------- */
div#grampsstylednote a {
color: Navy;
text-decoration: underline;
}
/* General Text
----------------------------------------------------- */
h1 {
@ -214,6 +173,7 @@ ol li a:hover {
}
a {
color: #000;
text-decoration: underline;
}
a:visited {
color: #000;
@ -232,6 +192,49 @@ span.preposition {
color: #000;
}
/* Menu Elements
================================================= */
div#navigation ul, div#subnavigation ul {
font: normal .9em sans-serif;
background-color: #00029D;
}
div#navigation ul li,
div#subnavigation ul li {
border-color: #BCEAF6;
}
#navigation ul li:after, #subnavigation ul li:after,
#alphabet ul li:after {
color: #139A26;
}
div#navigation ul li a, div#subnavigation ul li a {
color: #FFF;
}
div#navigation ul li a:hover,
div#subnavigation ul li a:hover {
color: #000;
}
div#navigation ul li.CurrentSection a,
div#subnavigation ul li.CurrentSection a {
background-color: #BCEAF6;
font: bold 14px sans;
color: #000;
}
div#navigation ul li.CurrentSection a:hover {
background-color: #BCEAF6;
color: #000;
}
div#subnavigation ul li.CurrentSection a:hover {
background-color: #000;
color: #FFF;
}
/* Gramps Styled Notes
------------------------------------------------------- */
div#grampsstylednote a {
color: Navy;
text-decoration: underline;
}
/* Header
----------------------------------------------------- */
div#header {

View File

@ -1,9 +1,8 @@
/*
# encoding: utf-8
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2010 Rob G. Healey <robhealey1@gmail.com>
# Copyright (C) 2011 Rob G. Healey <robhealey1@gmail.com>
#
# 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
@ -21,31 +20,27 @@
#
# $Id$
#
#
place title Holder
------------------------------------------------- */
div#geo-info {
font: bold 11px sans-serif;
###################################################### */
body#FamilyMap {
background-color: #000;
margin-left: 7px;
margin-right: 7px;
width: 965px;
}
/* Map holder
------------------------------------------------- */
div#map_canvas {
margin: 5px;
border: solid 4px #00029D;
width: 98%;
height: 800px;
margin-left: 10px;
margin-right: 10px;
border: solid 4px #000;
width: 931px;
height: 800px;
}
/* Drop button Holder
------------------------------------------------- */
button#drop {
font-weight: bold;
margin-left: 5px;
padding: 5px;
text-align: center;
width: auto;
height: auto;
border: solid 2px #00029D;
background-color: purple;
color: #FFF;
font: bold .8em sans-serif;
padding: 10px;
margin-top: 0px;
margin-bottom: 10px;
margin-left: 10px;
border: solid 2px green;
}