diff --git a/gramps/src/AutoComp.py b/gramps/src/AutoComp.py
index 2f2b43b0d..1b18763be 100644
--- a/gramps/src/AutoComp.py
+++ b/gramps/src/AutoComp.py
@@ -27,7 +27,10 @@ import string
import gtk
class AutoComp:
-
+ """
+ Allows allow completion of the GtkEntry widget with the entries
+ in the passed string list.
+ """
def __init__(self,widget,plist):
self.entry = widget
self.nlist = [("","")]
diff --git a/gramps/src/Plugins.py b/gramps/src/Plugins.py
index 75eae2793..e9c9474e9 100644
--- a/gramps/src/Plugins.py
+++ b/gramps/src/Plugins.py
@@ -18,20 +18,26 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+"""
+The core of the GRAMPS plugin system. This module provides tasks to load
+plugins from specfied directories, build menus for the different categories,
+and provide dialog to select and execute plugins.
+
+Plugins are divided into several categories. This are: reports, tools,
+filters, importer, exporters, and document generators.
+"""
+
#-------------------------------------------------------------------------
#
-#
+# GTK libraries
#
#-------------------------------------------------------------------------
import gtk
import libglade
-from intl import gettext
-_ = gettext
-
#-------------------------------------------------------------------------
#
-#
+# Standard Python modules
#
#-------------------------------------------------------------------------
import os
@@ -40,15 +46,18 @@ from re import compile
#-------------------------------------------------------------------------
#
-#
+# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
import utils
+import Config
+from intl import gettext
+_ = gettext
#-------------------------------------------------------------------------
#
-#
+# Global lists
#
#-------------------------------------------------------------------------
_reports = []
@@ -59,10 +68,12 @@ _success = []
_failed = []
_attempt = []
_loaddir = []
+_textdoc = []
+_drawdoc = []
#-------------------------------------------------------------------------
#
-#
+# Constants
#
#-------------------------------------------------------------------------
DOCSTRING = "d"
@@ -71,36 +82,45 @@ TASK = "f"
TITLE = "t"
STATUS = "s"
-pymod = compile(r"^(.*)\.py$")
-
#-------------------------------------------------------------------------
#
-#
+# ReportPlugins interface class
#
#-------------------------------------------------------------------------
class ReportPlugins:
+ """Displays the dialog box that allows the user to select the
+ report that is desired."""
def __init__(self,db,active):
+ """Display the dialog box, and build up the list of available
+ reports. This is used to build the selection tree on the left
+ hand side of the dailog box."""
+
self.db = db
self.active = active
self.dialog = libglade.GladeXML(const.pluginsFile,"report")
self.dialog.signal_autoconnect({
- "on_report_apply_clicked" : self.on_report_apply_clicked,
- "on_report_ok_clicked" : self.on_report_apply_clicked,
+ "on_report_apply_clicked" : self.on_apply_clicked,
+ "on_report_ok_clicked" : self.on_apply_clicked,
"destroy_passed_object" : utils.destroy_passed_object
})
tree = self.dialog.get_widget("tree1")
self.run_tool = None
- build_tree(tree,_reports,self.on_report_node_selected)
+ build_tree(tree,_reports,self.on_node_selected)
+
+ def on_apply_clicked(self,obj):
+ """Execute the selected report"""
- def on_report_apply_clicked(self,obj):
utils.destroy_passed_object(obj)
if self.run_tool:
self.run_tool(self.db,self.active)
- def on_report_node_selected(self,obj):
+ def on_node_selected(self,obj):
+ """Updates the informational display on the right hand side of
+ the dialog box with the description of the selected report"""
+
doc = obj.get_data(DOCSTRING)
xpm = obj.get_data(IMAGE)
status = ": %s" % obj.get_data(STATUS)
@@ -119,11 +139,18 @@ class ReportPlugins:
#-------------------------------------------------------------------------
#
-#
+# ToolPlugins interface class
#
#-------------------------------------------------------------------------
class ToolPlugins:
+ """Displays the dialog box that allows the user to select the tool
+ that is desired."""
+
def __init__(self,db,active,update):
+ """Display the dialog box, and build up the list of available
+ reports. This is used to build the selection tree on the left
+ hand side of the dailog box."""
+
self.db = db
self.active = active
self.update = update
@@ -140,11 +167,16 @@ class ToolPlugins:
build_tree(tree,_tools,self.on_node_selected)
def on_apply_clicked(self,obj):
+ """Execute the selected tool."""
+
utils.destroy_passed_object(obj)
if self.run_tool:
self.run_tool(self.db,self.active,self.update)
def on_node_selected(self,obj):
+ """Updates the informational display on the right hand side of
+ the dialog box with the description of the selected tool."""
+
doc = obj.get_data(DOCSTRING)
title = obj.get_data(TITLE)
@@ -154,10 +186,20 @@ class ToolPlugins:
#-------------------------------------------------------------------------
#
-#
+# build_tree
#
#-------------------------------------------------------------------------
def build_tree(tree,list,task):
+ """Populates a GtkTree with each menu item assocated with a entry
+ in the lists. The list must consist of a tuples with the following
+ format:
+
+ (task_to_call, category of report, report name, description, image, status)
+
+ Items in the same category are grouped under the same submen. The
+ task_to_call is bound to the 'select' callback of the menu entry."""
+
+ # build the tree items and group together based on the category name
item_hash = {}
for report in list:
item = gtk.GtkTreeItem(report[2])
@@ -173,6 +215,8 @@ def build_tree(tree,list,task):
else:
item_hash[report[1]] = [item]
+ # add a submenu for each category, and populate it with the GtkTreeItems
+ # that are associated with it.
key_list = item_hash.keys()
key_list.sort()
for key in key_list:
@@ -189,19 +233,38 @@ def build_tree(tree,list,task):
#-------------------------------------------------------------------------
#
-#
+# load_plugins
#
#-------------------------------------------------------------------------
def load_plugins(dir):
+ """Searches the specified directory, and attempts to load any python
+ modules that it finds, adding name to the _attempts list. If the module
+ successfully loads, it is added to the _success list. Each plugin is
+ responsible for registering itself in the correct manner. No attempt
+ is done in this routine to register the tasks."""
+
global _success,_failed,_attempt,_loaddir
+ # if the directory does not exist, do nothing
if not os.path.isdir(dir):
return
+ # if the path has not already been loaded, save it in the _loaddir
+ # list for use on reloading
+
if dir not in _loaddir:
_loaddir.append(dir)
+ # add the directory to the python search path
sys.path.append(dir)
+
+ pymod = compile(r"^(.*)\.py$")
+
+ # loop through each file in the directory, looking for files that
+ # have a .py extention, and attempt to load the file. If it succeeds,
+ # add it to the _success list. If it fails, add it to the _failure
+ # list
+
for file in os.listdir(dir):
name = os.path.split(file)
match = pymod.match(name[1])
@@ -218,7 +281,19 @@ def load_plugins(dir):
traceback.print_exc()
_failed.append(plugin)
+#-------------------------------------------------------------------------
+#
+# reload_plugins
+#
+#-------------------------------------------------------------------------
def reload_plugins(obj):
+ """Treated as a callback, causes all plugins to get reloaded. This is
+ useful when writing and debugging a plugin"""
+
+ pymod = compile(r"^(.*)\.py$")
+
+ # attempt to reload all plugins that have succeeded
+ # in the past
for plugin in _success:
try:
reload(plugin)
@@ -227,6 +302,9 @@ def reload_plugins(obj):
import traceback
traceback.print_exc()
_failed.append(plugin)
+
+ # attempt to load the plugins that have failed in the past
+
for plugin in _failed:
try:
__import__(plugin)
@@ -236,12 +314,15 @@ def reload_plugins(obj):
traceback.print_exc()
_failed.append(plugin)
+ # attempt to load any new files found
for dir in _loaddir:
for file in os.listdir(dir):
name = os.path.split(file)
match = pymod.match(name[1])
if not match:
continue
+ if file in _attempt:
+ return
_attempt.append(file)
plugin = match.groups()[0]
try:
@@ -259,9 +340,11 @@ def reload_plugins(obj):
#
#-------------------------------------------------------------------------
def register_export(task, name):
+ """Register an export filter, taking the task and name"""
_exports.append((task, name))
def register_import(task, name):
+ """Register an import filter, taking the task and name"""
_imports.append((task, name))
def register_report(task, name,
@@ -269,28 +352,36 @@ def register_report(task, name,
description=_("No description was provided"),
xpm=None,
status=_("Unknown")):
+ """Register a report with the plugin system"""
+
if xpm == None:
- xpm_data = no_image()
- elif type(xpm) == type([]):
- xpm_data = xpm
- else:
- xpm_data = xpm
-
- _reports.append((task, category, name, description, xpm_data, status))
+ xpm = no_image()
+ _reports.append((task, category, name, description, xpm, status))
def register_tool(task, name,
category=_("Uncategorized"),
description=_("No description was provided"),
xpm=None,
status=_("Unknown")):
+ """Register a tool with the plugin system"""
if xpm == None:
- xpm_data = no_image()
- elif type(xpm) == type([]):
- xpm_data = xpm
- else:
- xpm_data = xpm
+ xpm = no_image()
+ _tools.append((task, category, name, description, xpm, status))
- _tools.append((task, category, name, description, xpm_data, status))
+
+def register_text_doc(name,classref, table, paper, style):
+ """Register a text document generator"""
+ for n in _textdoc:
+ if n[0] == name:
+ return
+ _textdoc.append((name,classref,table,paper,style))
+
+def register_draw_doc(name,classref):
+ """Register a drawing document generator"""
+ for n in _drawdoc:
+ if n[0] == name:
+ return
+ _drawdoc.append((name,classref))
#-------------------------------------------------------------------------
#
@@ -326,12 +417,27 @@ def build_menu(top_menu,list,callback):
submenu.append(subentry)
top_menu.set_submenu(report_menu)
+#-------------------------------------------------------------------------
+#
+# build_report_menu
+#
+#-------------------------------------------------------------------------
def build_report_menu(top_menu,callback):
build_menu(top_menu,_reports,callback)
+#-------------------------------------------------------------------------
+#
+# build_tools_menu
+#
+#-------------------------------------------------------------------------
def build_tools_menu(top_menu,callback):
build_menu(top_menu,_tools,callback)
+#-------------------------------------------------------------------------
+#
+# build_export_menu
+#
+#-------------------------------------------------------------------------
def build_export_menu(top_menu,callback):
myMenu = gtk.GtkMenu()
@@ -342,6 +448,11 @@ def build_export_menu(top_menu,callback):
myMenu.append(item)
top_menu.set_submenu(myMenu)
+#-------------------------------------------------------------------------
+#
+# build_import_menu
+#
+#-------------------------------------------------------------------------
def build_import_menu(top_menu,callback):
myMenu = gtk.GtkMenu()
@@ -352,13 +463,66 @@ def build_import_menu(top_menu,callback):
myMenu.append(item)
top_menu.set_submenu(myMenu)
+#-------------------------------------------------------------------------
+#
+# get_text_doc_menu
+#
+#-------------------------------------------------------------------------
+def get_text_doc_menu(main_menu,tables,callback,obj=None):
+
+ index = 0
+ myMenu = gtk.GtkMenu()
+ _textdoc.sort()
+ for item in _textdoc:
+ if tables and item[2] == 0:
+ continue
+ name = item[0]
+ menuitem = gtk.GtkMenuItem(name)
+ menuitem.set_data("name",item[1])
+ menuitem.set_data("styles",item[4])
+ menuitem.set_data("paper",item[3])
+ menuitem.set_data("obj",obj)
+ if callback:
+ menuitem.connect("activate",callback)
+ menuitem.show()
+ myMenu.append(menuitem)
+ if name == Config.output_preference:
+ myMenu.set_active(index)
+ callback(menuitem)
+ index = index + 1
+ main_menu.set_menu(myMenu)
#-------------------------------------------------------------------------
#
-#
+# get_draw_doc_menu
+#
+#-------------------------------------------------------------------------
+def get_draw_doc_menu(main_menu,callback=None,obj=None):
+
+ index = 0
+ myMenu = gtk.GtkMenu()
+ for (name,classref) in _drawdoc:
+ menuitem = gtk.GtkMenuItem(name)
+ menuitem.set_data("name",classref)
+ menuitem.set_data("obj",obj)
+ if callback:
+ menuitem.connect("activate",callback)
+ menuitem.show()
+ myMenu.append(menuitem)
+ if name == Config.output_preference:
+ myMenu.set_active(index)
+ if callback:
+ callback(menuitem)
+ index = index + 1
+ main_menu.set_menu(myMenu)
+
+#-------------------------------------------------------------------------
+#
+# no_image
#
#-------------------------------------------------------------------------
def no_image():
+ """Returns XPM data for basic 48x48 icon"""
return [
"48 48 5 1",
" c None",
diff --git a/gramps/src/Report.py b/gramps/src/Report.py
index c6e27b7af..9da4051d1 100644
--- a/gramps/src/Report.py
+++ b/gramps/src/Report.py
@@ -28,6 +28,7 @@ import sort
import string
import utils
import intl
+import Plugins
_ = intl.gettext
@@ -35,7 +36,6 @@ from TextDoc import *
from StyleEditor import *
import Config
-import FindDoc
import PaperMenu
from gtk import *
@@ -898,14 +898,13 @@ class TextReportDialog(ReportDialog):
"""Build a menu of document types that are appropriate for
this text report. This menu will be generated based upon
whether the document requires table support, etc."""
- FindDoc.get_text_doc_menu(self.format_menu, self.doc_uses_tables(),
+ Plugins.get_text_doc_menu(self.format_menu, self.doc_uses_tables(),
self.doc_type_changed)
def make_document(self):
"""Create a document of the type requested by the user."""
- self.doc = FindDoc.make_text_doc(self.selected_style,self.format,
- self.paper,self.orien,
- self.template_name)
+ self.doc = self.format(self.selected_style,self.paper,
+ self.template_name,self.orien)
#------------------------------------------------------------------------
#
@@ -942,9 +941,8 @@ class DrawReportDialog(ReportDialog):
def make_doc_menu(self):
"""Build a menu of document types that are appropriate for
this drawing report."""
- FindDoc.get_draw_doc_menu(self.format_menu)
+ Plugins.get_draw_doc_menu(self.format_menu)
def make_document(self):
"""Create a document of the type requested by the user."""
- self.doc = FindDoc.make_draw_doc(self.selected_style,self.format,
- self.paper,self.orien)
+ self.doc = self.format(self.selected_style,self.paper,self.orien)
diff --git a/gramps/src/TextDoc.py b/gramps/src/TextDoc.py
index 7169a33a9..22af3d7bd 100644
--- a/gramps/src/TextDoc.py
+++ b/gramps/src/TextDoc.py
@@ -572,8 +572,9 @@ class SheetParser(handler.ContentHandler):
#
#------------------------------------------------------------------------
class TextDoc:
- def __init__(self,styles,type,orientation=PAPER_PORTRAIT):
+ def __init__(self,styles,type,template,orientation=PAPER_PORTRAIT):
self.orientation = orientation
+ self.template = template
if orientation == PAPER_PORTRAIT:
self.width = type.get_width()
self.height = type.get_height()
diff --git a/gramps/src/const.py b/gramps/src/const.py
index 771925510..0433f1946 100644
--- a/gramps/src/const.py
+++ b/gramps/src/const.py
@@ -74,6 +74,7 @@ findFile = "%s/find.glade" % rootDir
mergeFile = "%s/mergedata.glade" % rootDir
traceFile = "%s/trace.glade" % rootDir
pluginsDir = "%s/plugins" % rootDir
+docgenDir = "%s/docgen" % rootDir
filtersDir = "%s/filters" % rootDir
dataDir = "%s/data" % rootDir
gtkrcFile = "%s/gtkrc" % rootDir
diff --git a/gramps/src/docgen/AbiWordDoc.py b/gramps/src/docgen/AbiWordDoc.py
new file mode 100644
index 000000000..4499dc023
--- /dev/null
+++ b/gramps/src/docgen/AbiWordDoc.py
@@ -0,0 +1,242 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+"""
+Provides a TextDoc based interface to the AbiWord document format.
+"""
+
+#-------------------------------------------------------------------------
+#
+# Imported Modules
+#
+#-------------------------------------------------------------------------
+import os
+import base64
+
+from TextDoc import *
+from latin_utf8 import latin_to_utf8
+import const
+import string
+import Plugins
+import intl
+_ = intl.gettext
+
+#-------------------------------------------------------------------------
+#
+# Attemp to import the Python Imaging Library
+#
+#-------------------------------------------------------------------------
+try:
+ import PIL.Image
+ no_pil = 0
+except:
+ no_pil = 1
+
+#-------------------------------------------------------------------------
+#
+# Class Definitions
+#
+#-------------------------------------------------------------------------
+class AbiWordDoc(TextDoc):
+ """AbiWord document generator. Inherits from the TextDoc generic
+ document interface class."""
+
+ def __init__(self,styles,type,orientation):
+ """Initializes the AbiWordDoc class, calling the __init__ routine
+ of the parent TextDoc class"""
+ TextDoc.__init__(self,styles,type,orientation)
+ self.f = None
+ self.level = 0
+ self.new_page = 0
+
+ def open(self,filename):
+ """Opens the document, writing the necessary header information.
+ AbiWord uses an XML format, so the document format is pretty easy
+ to understand"""
+ if filename[-4:] != ".abw":
+ self.filename = "%s.abw" % filename
+ else:
+ self.filename = filename
+
+ self.f = open(self.filename,"w")
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ def close(self):
+ """Write the trailing information and closes the file"""
+ self.f.write('\n')
+ if len(self.photo_list) > 0:
+ self.f.write('\n')
+ for file_tuple in self.photo_list:
+ file = file_tuple[0]
+ width = file_tuple[1]
+ height = file_tuple[2]
+ base = "/tmp/%s.png" % os.path.basename(file)
+ tag = string.replace(base,'.','_')
+
+ if no_pil:
+ cmd = "%s -geometry %dx%d '%s' '%s'" % (const.convert,width,height,file,base)
+ os.system(cmd)
+ else:
+ im = PIL.Image.open(file)
+ im.thumbnail((width,height))
+ im.save(base,"PNG")
+
+ self.f.write('\n')
+ f = open(base,"rb")
+ base64.encode(f,self.f)
+ f.close()
+ os.unlink(base)
+ self.f.write('\n')
+ self.f.write('\n')
+
+ self.f.write('\n')
+ self.f.close()
+
+ def add_photo(self,pos,name,x_cm,y_cm):
+ import gtk
+ import GdkImlib
+
+ image = GdkImlib.Image(name)
+ scale = float(image.rgb_width)/float(image.rgb_height)
+ act_width = int(((x_cm * scale)*2.54)*72)
+ act_height = int(((y_cm * scale)*2.54)*72)
+
+ self.photo_list.append((name,act_width,act_height))
+
+ base = "/tmp/%s.png" % os.path.basename(name)
+ tag = string.replace(base,'.','_')
+
+ self.f.write('' % act_height)
+
+ def start_paragraph(self,style_name,leader=None):
+ style = self.style_list[style_name]
+ self.current_style = style
+ self.f.write('
')
+ font = style.get_font()
+ self.f.write('')
+ if self.new_page == 1:
+ self.new_page = 0
+ self.f.write('')
+ if leader != None:
+ self.f.write(leader)
+ self.f.write('\t')
+
+ def page_break(self):
+ self.new_page = 1
+
+ def end_paragraph(self):
+ self.f.write('
\n')
+
+ def write_text(self,text):
+ text = string.replace(text,'&','&'); # Must be first
+ text = string.replace(text,'<','<');
+ text = string.replace(text,'>','>');
+ self.f.write(text)
+
+ def start_bold(self):
+ font = self.current_style.get_font()
+ self.f.write('')
+
+ def end_bold(self):
+ font = self.current_style.get_font()
+ self.f.write('')
+
+
+Plugins.register_text_doc(_("AbiWord"),AbiWordDoc,0,1,1)
diff --git a/gramps/src/docgen/HtmlDoc.py b/gramps/src/docgen/HtmlDoc.py
new file mode 100644
index 000000000..69e6131bb
--- /dev/null
+++ b/gramps/src/docgen/HtmlDoc.py
@@ -0,0 +1,340 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+import os
+import string
+import re
+import utils
+import gnome.ui
+import Plugins
+
+from intl import gettext
+_ = gettext
+
+from TextDoc import *
+
+#------------------------------------------------------------------------
+#
+# Attempt to load the Python Imaging Library for the handling of photos.
+#
+#------------------------------------------------------------------------
+try:
+ import PIL.Image
+ no_pil = 0
+except:
+ no_pil = 1
+
+t_header_line_re = re.compile(r"(.*)(.*)(.*)", re.DOTALL|re.IGNORECASE|re.MULTILINE)
+
+#------------------------------------------------------------------------
+#
+# Default template
+#
+#------------------------------------------------------------------------
+_top = [
+ '\n',
+ '\n',
+ '\n',
+ ' \n',
+ ' \n',
+ ' \n',
+ ' \n',
+ '\n',
+ '\n',
+ ' \n'
+ ]
+
+_bottom = [
+ ' \n',
+ '\n',
+ '\n'
+ ]
+
+class HtmlDoc(TextDoc):
+
+ def __init__(self,styles,type,template,orientation,source=None):
+ TextDoc.__init__(self,styles,PaperStyle("",0,0),template,None)
+ if source == None:
+ self.f = None
+ self.filename = None
+ self.top = []
+ self.bottom = []
+ self.base = ""
+
+ self.load_template()
+ self.build_header()
+ self.build_style_declaration()
+
+ else:
+ self.f = None
+ self.filename = source.filename
+ self.template = None
+ self.top = source.top
+ self.bottom = source.bottom
+ self.base = source.base
+ self.file_header = source.file_header
+ self.style_declaration = source.style_declaration
+ self.table_styles = source.table_styles;
+ self.cell_styles = source.cell_styles;
+
+ def load_template(self):
+ start = re.compile(r"")
+ stop = re.compile(r"")
+ top_add = 1
+ bottom_add = 0
+ if self.template and self.template != "":
+ try:
+ templateFile = open(self.template,"r")
+ for line in templateFile.readlines():
+ if top_add == 1:
+ self.top.append(line)
+ match = start.search(line)
+ if match:
+ top_add = 0
+ elif bottom_add == 0:
+ match = stop.search(line)
+ if match != None:
+ bottom_add = 1
+ self.bottom.append(line)
+ else:
+ self.bottom.append(line)
+ templateFile.close()
+
+ if top_add == 1:
+ mymsg = _("The marker '' was not in the template")
+ gnome.ui.GnomeErrorDialog(mymsg)
+ except IOError,msg:
+
+ mymsg = _("Could not open %s\nUsing the default template") % \
+ self.template
+ mymsg = "%s\n%s" % (mymsg,msg)
+ gnome.ui.GnomeWarningDialog(mymsg)
+ self.bottom = _bottom
+ self.top = _top
+ except:
+ mymsg = _("Could not open %s\nUsing the default template") % \
+ self.template
+ gnome.ui.GnomeWarningDialog(mymsg)
+ self.bottom = _bottom
+ self.top = _top
+ else:
+ self.bottom = _bottom
+ self.top = _top
+
+ def open(self,filename):
+ if filename[-5:] == ".html" or filename[-4:0] == ".htm":
+ self.filename = filename
+ else:
+ self.filename = filename + ".html"
+
+ self.base = os.path.dirname(self.filename)
+
+ self.f = open(self.filename,"w")
+ self.f.write(self.file_header)
+ self.f.write(self.style_declaration)
+
+ def build_header(self):
+ top = string.join(self.top, "")
+ match = t_header_line_re.match(top)
+ if match:
+ m = match.groups()
+ self.file_header = '%s%s%s\n' % (m[0],m[1],m[2])
+ else:
+ self.file_header = top
+
+ def build_style_declaration(self):
+ text = ['')
+ self.style_declaration = string.join(text,'\n')
+
+ def close(self):
+ for line in self.bottom:
+ self.f.write(line)
+ self.f.close()
+
+ def add_photo(self,name,pos,x,y):
+ if no_pil:
+ return
+
+ self.empty = 0
+ try:
+ im = PIL.Image.open(name)
+ except:
+ return
+
+ nx,ny = im.size
+
+ scale = float(nx)/float(ny)
+ if scale > 1.0:
+ scale = 1.0/scale
+ act_width = float(x)
+ act_height = float(y * scale)
+ else:
+ act_width = float(x * scale)
+ act_height = float(y)
+
+ cmtopt = float(150.0/2.54)
+ pixx = int(act_width*cmtopt)
+ pixy = int(act_height*cmtopt)
+ im.thumbnail((pixx,pixy))
+
+ imdir = self.base + os.sep + "images"
+ if not os.path.isdir(imdir):
+ try:
+ os.mkdir(imdir)
+ except:
+ return
+
+ refname = "is%s" % os.path.basename(name)
+ try:
+ im.save(imdir + os.sep + refname)
+ except:
+ return
+
+ if pos == "right":
+ xtra = ' align="right"'
+ elif pos == "left" :
+ xtra = ' align="left"'
+ else:
+ xtra = ''
+
+ self.f.write('\n' % \
+ (refname,pixx,pixy,xtra))
+
+ def start_table(self,name,style):
+ self.tbl = self.table_styles[style]
+ self.f.write('\n')
+
+ def end_table(self):
+ self.f.write('
\n')
+
+ def start_row(self):
+ self.col = 0
+ self.f.write('\n')
+
+ def end_row(self):
+ self.f.write('
\n')
+
+ def start_cell(self,style_name,span=1):
+ self.empty = 1
+ self.f.write(' 1:
+ self.f.write(' colspan="' + str(span) + '"')
+ self.col = self.col + 1
+ else:
+ self.f.write(' width="')
+ self.f.write(str(self.tbl.get_column_width(self.col)))
+ self.f.write('%"')
+ self.f.write(' class="')
+ self.f.write(style_name)
+ self.f.write('">')
+ self.col = self.col + 1
+
+ def end_cell(self):
+ self.f.write(' | \n')
+
+ def start_paragraph(self,style_name,leader=None):
+ self.f.write('')
+ if leader != None:
+ self.f.write(leader)
+ self.f.write(' ')
+
+ def end_paragraph(self):
+ if self.empty == 1:
+ self.f.write(' ')
+ self.empty = 0
+ self.f.write('
\n')
+
+ def write_text(self,text):
+ if text != "":
+ self.empty = 0
+ text = string.replace(text,'\n','
')
+ self.f.write(text)
+
+Plugins.register_text_doc(_("HTML"),HtmlDoc,1,0,1)
diff --git a/gramps/src/docgen/KwordDoc.py b/gramps/src/docgen/KwordDoc.py
new file mode 100644
index 000000000..3e20eb412
--- /dev/null
+++ b/gramps/src/docgen/KwordDoc.py
@@ -0,0 +1,441 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+from TextDoc import *
+from latin_utf8 import latin_to_utf8
+import utils
+import time
+import StringIO
+import os
+import gzip
+from TarFile import TarFile
+import Plugins
+import intl
+_ = intl.gettext
+
+try:
+ import PIL.Image
+ no_pil = 0
+except:
+ no_pil = 1
+
+def points(val):
+ inch = float(val)/2.54
+ return (int(inch*72))
+
+#------------------------------------------------------------------------
+#
+#
+#
+#------------------------------------------------------------------------
+class KwordDoc(TextDoc):
+
+ def open(self,filename):
+ self.photo_list = []
+
+ if filename[-4:] != ".kwd":
+ self.filename = filename + ".kwd"
+ else:
+ self.filename = filename
+
+ self.f = StringIO.StringIO()
+ self.m = StringIO.StringIO()
+
+ self.m.write('')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+ self.m.write('\n')
+
+ self.f.write('')
+ self.f.write('')
+ self.f.write('\n')
+ self.mtime = time.time()
+
+ if self.paper.name == "A3":
+ self.f.write('\n')
+ self.f.write('' % points(self.lmargin))
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ for p in self.photo_list:
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ for name in self.style_list.keys():
+ self.f.write('\n')
+
+ self.f.write('\n')
+ self.f.write('\n')
+ for file in self.photo_list:
+ self.f.write('\n' % a[0])
+ self.f.write('\n')
+ self.f.write('\n')
+
+ tar = TarFile(self.filename)
+ tar.add_file("documentinfo.xml",self.mtime,self.m)
+ tar.add_file("maindoc.xml",self.mtime,self.f)
+ for file in self.photo_list:
+ f = open(file[0],"r")
+ tar.add_file(file[1],self.mtime,f)
+ f.close()
+ tar.close()
+
+ self.f.close()
+ self.m.close()
+
+ def start_page(self,orientation=None):
+ pass
+
+ def end_page(self):
+ pass
+
+ def start_paragraph(self,style_name,leader=None):
+ self.format_list = []
+ self.bold_start = 0
+ self.text = ""
+ self.style_name = style_name
+ self.p = self.style_list[self.style_name]
+ self.font = self.p.get_font()
+ if self.font.get_type_face() == FONT_SERIF:
+ self.font_face = "times"
+ else:
+ self.font_face = "helvetica"
+
+ if leader != None:
+ self.text = leader + '\t'
+ txt = '\n' % (len(leader)+1)
+ txt = txt + '\n\n' % self.font_face
+ self.format_list.append(txt)
+
+ self.bold_stop = len(self.text)
+
+ def end_paragraph(self):
+ if self.bold_start != 0 and self.bold_stop != len(self.text):
+ txt = '\n\n\n' % self.font_face
+ self.format_list.append(txt)
+
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(latin_to_utf8(self.text))
+ self.f.write('\n')
+ self.f.write('\n')
+ for format in self.format_list:
+ self.f.write(format)
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n' % self.style_name)
+
+ pad = points(self.p.get_padding())/2
+ self.f.write('\n' % (pad,pad))
+
+ if self.p.get_alignment() == PARA_ALIGN_CENTER:
+ self.f.write('\n')
+ elif self.p.get_alignment() == PARA_ALIGN_JUSTIFY:
+ self.f.write('\n')
+ elif self.p.get_alignment() == PARA_ALIGN_RIGHT:
+ self.f.write('\n')
+ else:
+ self.f.write('\n')
+
+ first = self.p.get_first_indent()
+ left = self.p.get_left_margin()
+ right = self.p.get_right_margin()
+ self.f.write('\n' % (points(left),points(right)))
+
+ self.f.write('\n')
+ self.f.write('\n' % self.font_face)
+ self.f.write('\n' % self.font.get_size())
+ self.f.write('\n' % self.font.get_color())
+ if self.font.get_bold():
+ self.f.write('\n')
+ if self.font.get_italic():
+ self.f.write('\n')
+ if self.font.get_underline():
+ self.f.write('\n')
+ if self.p.get_top_border():
+ self.f.write('\n')
+ if self.p.get_bottom_border():
+ self.f.write('\n')
+ if self.p.get_right_border():
+ self.f.write('\n')
+ if self.p.get_left_border():
+ self.f.write('\n')
+ self.f.write('\n')
+ if left != 0:
+ self.f.write('\n' % points(left))
+ self.f.write('\n')
+ self.f.write('\n')
+
+ def start_bold(self):
+ self.bold_start = len(self.text)
+ if self.bold_stop != self.bold_start:
+ length = self.bold_stop - self.bold_start
+ txt = '\n' % (self.bold_stop,length)
+ txt = txt + '\n\n' % self.font_face
+ self.format_list.append(txt)
+
+ def end_bold(self):
+ self.bold_stop = len(self.text)
+ length = self.bold_stop - self.bold_start
+ txt = '\n' % (self.bold_start,length)
+ txt = txt + '\n\n\n' % self.font_face
+ self.format_list.append(txt)
+
+ def start_table(self,name,style_name):
+ pass
+
+ def end_table(self):
+ pass
+
+ def start_row(self):
+ pass
+
+ def end_row(self):
+ pass
+
+ def start_cell(self,style_name,span=1):
+ pass
+
+ def end_cell(self):
+ pass
+
+ def add_photo(self,name,pos,x,y):
+ if no_pil:
+ return
+
+ im = PIL.Image.open(name)
+ nx,ny = im.size
+
+ scale = float(nx)/float(ny)
+ x = points(x)
+ y = points(y)
+
+ if scale > 1.0:
+ scale = 1.0/scale
+ act_width = x
+ act_height = y * scale
+ else:
+ act_width = x * scale
+ act_height = y
+
+ index = len(self.photo_list)+1
+ tag = 'pictures/picture%d.jpeg' % index
+ self.photo_list.append((name,tag,act_width,act_height))
+ txt = '\n' % len(self.text)
+ txt = txt + '\n' % tag
+ txt = txt + '\n'
+
+ self.bold_stop = len(self.text)
+ self.format_list.append(txt)
+
+ self.text = self.text + '#'
+
+ def horizontal_line(self):
+ pass
+
+ def write_text(self,text):
+ self.text = self.text + text
+
+
+if __name__ == "__main__":
+
+ paper = PaperStyle("Letter",27.94,21.59)
+
+ styles = StyleSheet()
+ foo = FontStyle()
+ foo.set_type_face(FONT_SANS_SERIF)
+ foo.set_color((255,0,0))
+ foo.set_size(24)
+ foo.set_underline(1)
+ foo.set_bold(1)
+ foo.set_italic(1)
+
+ para = ParagraphStyle()
+ para.set_alignment(PARA_ALIGN_RIGHT)
+ para.set_font(foo)
+ styles.add_style("Title",para)
+
+ foo = FontStyle()
+ foo.set_type_face(FONT_SERIF)
+ foo.set_size(12)
+
+ para = ParagraphStyle()
+ para.set_font(foo)
+ styles.add_style("Normal",para)
+
+ doc = KwordDoc(styles,paper,PAPER_PORTRAIT)
+ doc.open("/home/dona/test")
+
+ doc.start_paragraph("Title")
+ doc.write_text("My Title")
+ doc.end_paragraph()
+
+ doc.start_paragraph("Normal")
+ doc.write_text("Hello there. This is fun")
+ doc.end_paragraph()
+
+ doc.start_paragraph("Normal")
+ doc.write_text("This is fun. ")
+ doc.add_photo("/home/dona/dad.jpg",2.0,2.0)
+ doc.write_text("So is this. ")
+ doc.end_paragraph()
+
+ doc.close()
+
+Plugins.register_text_doc(_("KWord"),KwordDoc,0,1,1)
diff --git a/gramps/src/docgen/LaTeXDoc.py b/gramps/src/docgen/LaTeXDoc.py
new file mode 100644
index 000000000..a34910a53
--- /dev/null
+++ b/gramps/src/docgen/LaTeXDoc.py
@@ -0,0 +1,136 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+from TextDoc import *
+from latin_utf8 import latin_to_utf8
+import Plugins
+import intl
+_ = intl.gettext
+
+#------------------------------------------------------------------------
+#
+#
+#
+#------------------------------------------------------------------------
+class LaTeXDoc(TextDoc):
+
+ def open(self,filename):
+ if filename[-4:] != ".tex":
+ self.filename = filename + ".tex"
+ else:
+ self.filename = filename
+
+ self.f = open(self.filename,"w")
+ options = "12pt"
+
+ if self.orientation == PAPER_LANDSCAPE:
+ options = options + ",landscape"
+
+ if self.paper.name == "A4":
+ options = options + ",a4paper"
+ elif self.paper.name == "A5":
+ options = options + ",a5paper"
+ elif self.paper.name == "B5":
+ options = options + ",b4paper"
+
+ self.f.write('\\documentclass[%s]{article}\n' % options)
+ self.f.write('\\usepackage[T1]{fontenc}\n')
+ self.f.write('\\usepackage[latin1]{inputenc}\n')
+ self.f.write('\\begin{document}\n')
+ self.f.write("\\title{}\n")
+ self.f.write("\\author{}\n")
+ self.in_list = 0
+
+ def close(self):
+ if self.in_list:
+ self.f.write('\\end{description}\n')
+ self.f.write('\\end{document}\n')
+ self.f.close()
+
+ def start_page(self,orientation=None):
+ pass
+
+ def end_page(self):
+ self.f.write('\\newpage')
+
+ def start_paragraph(self,style_name,leader=None):
+ style = self.style_list[style_name]
+ self.level = style.get_header_level()
+
+ if leader == None and self.in_list:
+ self.f.write('\\end{description}\n')
+ self.in_list = 0
+
+ if self.level == 1 :
+ self.f.write('\\section*{')
+ elif self.level == 2:
+ self.f.write('\\subsection*{')
+ elif self.level == 3:
+ self.f.write('\\subsubsection*{')
+ if leader != None and not self.in_list:
+ self.f.write('\\begin{description}\n')
+ self.in_list = 1
+ if leader != None:
+ self.f.write('\\item{%s} ' % leader)
+
+ def end_paragraph(self):
+ if self.level > 0:
+ self.f.write('}\n')
+ elif not self.in_list:
+ self.f.write('\n\\par\\noindent\n')
+ else:
+ self.f.write('\n')
+
+ def start_bold(self):
+ self.f.write('\\bfseries ')
+ pass
+
+ def end_bold(self):
+ self.f.write('\\mdseries ')
+ pass
+
+ def start_table(self,name,style_name):
+ pass
+
+ def end_table(self):
+ pass
+
+ def start_row(self):
+ pass
+
+ def end_row(self):
+ pass
+
+ def start_cell(self,style_name,span=1):
+ pass
+
+ def end_cell(self):
+ pass
+
+ def add_photo(self,name,pos,x,y):
+ pass
+
+ def horizontal_line(self):
+ pass
+
+ def write_text(self,text):
+ self.f.write(text)
+
+Plugins.register_text_doc(_("LaTeX"),LaTeXDoc,0,1,0)
diff --git a/gramps/src/docgen/OpenDrawDoc.py b/gramps/src/docgen/OpenDrawDoc.py
new file mode 100644
index 000000000..57679afe1
--- /dev/null
+++ b/gramps/src/docgen/OpenDrawDoc.py
@@ -0,0 +1,449 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+import os
+import tempfile
+import string
+import Plugins
+import intl
+_ = intl.gettext
+
+from TextDoc import *
+from DrawDoc import *
+
+from latin_utf8 import latin_to_utf8
+import const
+
+try:
+ from codecs import *
+except:
+ def EncodedFile(a,b,c):
+ return a
+
+
+class OpenDrawDoc(DrawDoc):
+
+ def __init__(self,styles,type,orientation):
+ DrawDoc.__init__(self,styles,type,orientation)
+ self.f = None
+ self.filename = None
+ self.level = 0
+ self.time = "0000-00-00T00:00:00"
+ self.page = 0
+
+ def open(self,filename):
+ import time
+
+ t = time.localtime(time.time())
+ self.time = "%04d-%02d-%02dT%02d:%02d:%02d" % \
+ (t[0],t[1],t[2],t[3],t[4],t[5])
+
+ if filename[-4:] != ".sxd":
+ self.filename = filename + ".sxd"
+ else:
+ self.filename = filename
+
+ tempfile.tempdir = "/tmp"
+ self.tempdir = tempfile.mktemp()
+ os.mkdir(self.tempdir,0700)
+ os.mkdir(self.tempdir + os.sep + "Pictures")
+ os.mkdir(self.tempdir + os.sep + "META-INF")
+
+ fname = self.tempdir + os.sep + "content.xml"
+ self.f = EncodedFile(open(fname,"wb"),'latin-1','utf-8')
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ for key in self.style_list.keys():
+ style = self.style_list[key]
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ def close(self):
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.close()
+ self._write_styles_file()
+ self._write_manifest()
+ self._write_meta_file()
+ self._write_zip()
+
+ def _write_zip(self):
+
+ if os.path.isfile(self.filename):
+ os.unlink(self.filename)
+
+ os.system("cd " + self.tempdir + "; " + const.zipcmd + " " \
+ + self.filename + " .")
+
+ os.unlink(self.tempdir + os.sep + "META-INF" + os.sep + "manifest.xml")
+ os.unlink(self.tempdir + os.sep + "content.xml")
+ os.unlink(self.tempdir + os.sep + "meta.xml")
+ os.unlink(self.tempdir + os.sep + "styles.xml")
+# for image in self.image_list:
+# os.unlink(self.tempdir + os.sep + "Pictures" + os.sep + image)
+ os.rmdir(self.tempdir + os.sep + "Pictures")
+ os.rmdir(self.tempdir + os.sep + "META-INF")
+ os.rmdir(self.tempdir)
+
+ def _write_styles_file(self):
+ file = self.tempdir + os.sep + "styles.xml"
+ self.f = EncodedFile(open(file,"wb"),'latin-1','utf-8')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ for style_name in self.draw_styles.keys():
+ style = self.draw_styles[style_name]
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ self.f.write('\n')
+ for key in self.style_list.keys():
+ style = self.style_list[key]
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ # Current no leading number format for headers
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n' % self.rmargin)
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.close()
+
+ def start_paragraph(self,style_name):
+ self.f.write('' % style_name)
+
+ def end_paragraph(self):
+ self.f.write('\n')
+
+ def write_text(self,text):
+ text = string.replace(text,'\t','')
+ text = string.replace(text,'\n','')
+ self.f.write(latin_to_utf8(text))
+
+ def _write_manifest(self):
+ file = self.tempdir + os.sep + "META-INF" + os.sep + "manifest.xml"
+ self.f = EncodedFile(open(file,"wb"),'latin-1','utf-8')
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ #self.f.write('')
+ self.f.write('\n')
+ self.f.close()
+
+ def _write_meta_file(self):
+ file = self.tempdir + os.sep + "meta.xml"
+ name = latin_to_utf8(self.name)
+ self.f = EncodedFile(open(file,"wb"),'latin-1','utf-8')
+ self.f.write('\n')
+ self.f.write('\n');
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(const.progName + ' ' + const.version)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(name)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(self.time)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(name)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(self.time)
+ self.f.write('\n')
+ self.f.write('0-00-00T00:00:00\n')
+ self.f.write('en-US\n')
+ self.f.write('1\n')
+ self.f.write('PT0S\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.close()
+
+ def start_page(self,orientation=None):
+ self.page = self.page + 1
+ self.f.write('\n')
+
+ def end_page(self):
+ self.f.write('\n')
+
+ def draw_line(self,style,x1,y1,x2,y2):
+ self.f.write('\n' % y2)
+
+ def draw_box(self,style,text,x,y):
+ box_style = self.draw_styles[style]
+ para_name = box_style.get_paragraph_style()
+
+ self.f.write('')
+ text = latin_to_utf8(string.replace(text,'\n',''))
+ self.f.write('>\n')
+ self.f.write('')
+ self.f.write('' % para_name)
+ self.f.write(text)
+ self.f.write('\n')
+ self.f.write('\n')
+ else:
+ self.f.write('/>\n')
+
+Plugins.register_draw_doc(_("OpenOffice/StarOffice 6"),OpenDrawDoc);
diff --git a/gramps/src/docgen/OpenOfficeDoc.py b/gramps/src/docgen/OpenOfficeDoc.py
new file mode 100644
index 000000000..dd010d155
--- /dev/null
+++ b/gramps/src/docgen/OpenOfficeDoc.py
@@ -0,0 +1,579 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+import os
+import tempfile
+import string
+
+from TextDoc import *
+from latin_utf8 import latin_to_utf8
+import const
+import utils
+import Plugins
+import intl
+_ = intl.gettext
+
+try:
+ import PIL.Image
+ no_pil = 0
+except:
+ no_pil = 1
+
+try:
+ from codecs import *
+except:
+ def EncodedFile(a,b,c):
+ return a
+
+class OpenOfficeDoc(TextDoc):
+
+ def __init__(self,styles,type,template,orientation):
+ TextDoc.__init__(self,styles,type,template,orientation)
+ self.f = None
+ self.filename = None
+ self.level = 0
+ self.time = "0000-00-00T00:00:00"
+ self.new_page = 0
+
+ def open(self,filename):
+ import time
+
+ t = time.localtime(time.time())
+ self.time = "%04d-%02d-%02dT%02d:%02d:%02d" % \
+ (t[0],t[1],t[2],t[3],t[4],t[5])
+
+ if filename[-4:] != ".sxw":
+ self.filename = filename + ".sxw"
+ else:
+ self.filename = filename
+
+ tempfile.tempdir = "/tmp"
+ self.tempdir = tempfile.mktemp()
+ os.mkdir(self.tempdir,0700)
+ os.mkdir(self.tempdir + os.sep + "Pictures")
+ os.mkdir(self.tempdir + os.sep + "META-INF")
+
+ fname = self.tempdir + os.sep + "content.xml"
+ self.f = EncodedFile(open(fname,"wb"),'latin-1','utf-8')
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ for style_name in self.style_list.keys():
+ style = self.style_list[style_name]
+ self.f.write('\n\n')
+ self.f.write('\n')
+ for style_name in self.table_styles.keys():
+ style = self.table_styles[style_name]
+ self.f.write('\n')
+ table_width = float(self.get_usable_width())
+ table_width_str = "%.4f" % table_width
+ self.f.write('\n')
+ self.f.write('\n')
+ for col in range(0,style.get_columns()):
+ self.f.write('')
+ width = table_width * float(style.get_column_width(col)/100.0)
+ width_str = "%.4f" % width
+ self.f.write('' % width_str)
+ self.f.write('\n')
+ for cell in self.cell_styles.keys():
+ cell_style = self.cell_styles[cell]
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ #Begin photo style
+ self.f.write('')
+ self.f.write('')
+ self.f.write('\n')
+
+ self.f.write('')
+ self.f.write('')
+ self.f.write('\n')
+
+ self.f.write('')
+ self.f.write('')
+ self.f.write('\n')
+
+ self.f.write('')
+ self.f.write('')
+ self.f.write('\n')
+
+ #end of Photo style edits
+
+ self.f.write('\n')
+ self.f.write('\n')
+
+ def close(self):
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.close()
+ self._write_styles_file()
+ self._write_manifest()
+ self._write_meta_file()
+ self._write_photos()
+ self._write_zip()
+
+ def add_photo(self,name,pos,x_cm,y_cm):
+ import gtk
+ import GdkImlib
+
+ image = GdkImlib.Image(name)
+ scale = float(image.rgb_width)/float(image.rgb_height)
+ act_width = int(((x_cm * scale)*2.54)*72)
+ act_height = int(((y_cm * scale)*2.54)*72)
+
+ self.photo_list.append((name,act_width,act_height))
+
+ base = os.path.basename(name)
+ tag = string.replace(base,'.','_')
+
+ if pos == "left":
+ self.f.write('\n')
+
+ def start_table(self,name,style_name):
+ self.f.write('\n')
+ table = self.table_styles[style_name]
+ for col in range(0,table.get_columns()):
+ self.f.write('\n')
+
+ def end_table(self):
+ self.f.write('\n')
+
+ def start_row(self):
+ self.f.write('\n')
+
+ def end_row(self):
+ self.f.write('\n')
+
+ def start_cell(self,style_name,span=1):
+ self.span = span
+ self.f.write(' 1:
+ self.f.write(' table:number-columns-spanned="' + str(span) + '">\n')
+ else:
+ self.f.write('>\n')
+
+ def end_cell(self):
+ self.f.write('\n')
+ for col in range(1,self.span):
+ self.f.write('\n')
+
+ def start_bold(self):
+ self.f.write('')
+
+ def end_bold(self):
+ self.f.write('')
+
+ def _write_zip(self):
+
+ if os.path.isfile(self.filename):
+ os.unlink(self.filename)
+
+ os.system("cd " + self.tempdir + "; " + const.zipcmd + " " \
+ + self.filename + " .")
+
+ os.unlink(self.tempdir + os.sep + "META-INF" + os.sep + "manifest.xml")
+ os.unlink(self.tempdir + os.sep + "content.xml")
+ os.unlink(self.tempdir + os.sep + "meta.xml")
+ os.unlink(self.tempdir + os.sep + "styles.xml")
+ for image in self.photo_list:
+ base = os.path.basename(image[0])
+ os.unlink(self.tempdir + os.sep + "Pictures" + os.sep + base)
+ os.rmdir(self.tempdir + os.sep + "Pictures")
+ os.rmdir(self.tempdir + os.sep + "META-INF")
+ os.rmdir(self.tempdir)
+
+ def _write_styles_file(self):
+ file = self.tempdir + os.sep + "styles.xml"
+
+ self.f = EncodedFile(open(file,"wb"),'latin-1','utf-8')
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ for key in self.style_list.keys():
+ style = self.style_list[key]
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ # Current no leading number format for headers
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.close()
+
+ def page_break(self):
+ self.new_page = 1
+
+ def start_paragraph(self,style_name,leader=None):
+ style = self.style_list[style_name]
+ self.level = style.get_header_level()
+ if self.new_page == 1:
+ self.new_page = 0
+ name = "NL%s" % style_name
+ else:
+ name = style_name
+ if self.level == 0:
+ self.f.write('' % name)
+ else:
+ self.f.write('')
+ if leader != None:
+ self.f.write(latin_to_utf8(leader))
+ self.f.write('')
+
+ def end_paragraph(self):
+ if self.level == 0:
+ self.f.write('\n')
+ else:
+ self.f.write('\n')
+
+ def write_text(self,text):
+ text = string.replace(text,'\n','')
+ self.f.write(latin_to_utf8(text))
+
+ def _write_photos(self):
+
+ for file_tuple in self.photo_list:
+ file = file_tuple[0]
+ width = file_tuple[1]
+ height = file_tuple[2]
+ base = os.path.basename(file)
+ image_name = self.tempdir + os.sep + "Pictures" + os.sep + base
+ if no_pil:
+ cmd = "%s -geometry %dx%d '%s' '%s'" % (const.convert,width,height,file,image_name)
+ os.system(cmd)
+ else:
+ im = PIL.Image.open(file)
+ im.thumbnail((width,height))
+ im.save(image_name,"JPEG")
+
+ def _write_manifest(self):
+ file = self.tempdir + os.sep + "META-INF" + os.sep + "manifest.xml"
+ self.f = EncodedFile(open(file,"wb"),'latin-1','utf-8')
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write('')
+ for image in self.photo_list:
+ i = image[0]
+ base = os.path.basename(i)
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('\n')
+ self.f.close()
+
+ def _write_meta_file(self):
+ file = self.tempdir + os.sep + "meta.xml"
+ name = latin_to_utf8(self.name)
+ self.f = EncodedFile(open(file,"wb"),'latin-1','utf-8')
+ self.f.write('\n')
+ self.f.write('\n');
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(const.progName + ' ' + const.version)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(name)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(self.time)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(name)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(self.time)
+ self.f.write('\n')
+ self.f.write('0-00-00T00:00:00\n')
+ self.f.write('en-US\n')
+ self.f.write('1\n')
+ self.f.write('PT0S\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.close()
+
+Plugins.register_text_doc(_("OpenOffice/StarOffice 6"),OpenOfficeDoc,1,1,1)
diff --git a/gramps/src/docgen/OpenSpreadSheet.py b/gramps/src/docgen/OpenSpreadSheet.py
new file mode 100644
index 000000000..427f2e279
--- /dev/null
+++ b/gramps/src/docgen/OpenSpreadSheet.py
@@ -0,0 +1,457 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+import os
+import tempfile
+import string
+
+from TextDoc import *
+from SpreadSheetDoc import *
+
+from latin_utf8 import latin_to_utf8
+import const
+
+class OpenSpreadSheet(SpreadSheetDoc):
+
+ def __init__(self,type,orientation):
+ SpreadSheetDoc.__init__(self,type,orientation)
+ self.f = None
+ self.filename = None
+ self.level = 0
+ self.time = "0000-00-00T00:00:00"
+
+ def open(self,filename):
+ import time
+
+ t = time.localtime(time.time())
+ self.time = "%04d-%02d-%02dT%02d:%02d:%02d" % \
+ (t[0],t[1],t[2],t[3],t[4],t[5])
+
+ if filename[-4:] != ".sxc":
+ self.filename = filename + ".sxc"
+ else:
+ self.filename = filename
+
+ tempfile.tempdir = "/tmp"
+ self.tempdir = tempfile.mktemp()
+ os.mkdir(self.tempdir,0700)
+ os.mkdir(self.tempdir + os.sep + "Pictures")
+ os.mkdir(self.tempdir + os.sep + "META-INF")
+
+ self.f = open(self.tempdir + os.sep + "content.xml","w")
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ for key in self.table_styles.keys():
+ table = self.table_styles[key]
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ for index in range(0,table.get_columns()):
+ self.f.write('\n')
+ self.f.write('\n' % table.get_column_width(index))
+ self.f.write('\n')
+
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ for key in self.style_list.keys():
+ style = self.style_list[key]
+ font = style.get_font()
+ self.f.write('\n')
+ self.f.write('\n')
+ else:
+ self.f.write('fo:font-weight="normal"/>\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+
+ def close(self):
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.close()
+ self._write_styles_file()
+ self._write_manifest()
+ self._write_meta_file()
+ self._write_zip()
+
+ def start_row(self):
+ self.f.write('\n')
+
+ def end_row(self):
+ self.f.write('\n')
+
+ def start_cell(self,style_name,span=1):
+ self.content = 0
+ self.span = span
+ self.f.write(' 1:
+ self.f.write(' table:number-columns-spanned="' + str(span) + '">\n')
+ else:
+ self.f.write('>\n')
+
+ def end_cell(self):
+ if self.content == 0:
+ self.f.write('\n')
+ else:
+ self.f.write('\n')
+ self.f.write('\n')
+ for col in range(1,self.span):
+ self.f.write('\n')
+
+ def _write_zip(self):
+
+ if os.path.isfile(self.filename):
+ os.unlink(self.filename)
+
+ os.system("cd " + self.tempdir + "; " + const.zipcmd + " " \
+ + self.filename + " .")
+
+ os.unlink(self.tempdir + os.sep + "META-INF" + os.sep + "manifest.xml")
+ os.unlink(self.tempdir + os.sep + "content.xml")
+ os.unlink(self.tempdir + os.sep + "meta.xml")
+ os.unlink(self.tempdir + os.sep + "styles.xml")
+# for image in self.image_list:
+# os.unlink(self.tempdir + os.sep + "Pictures" + os.sep + image)
+ os.rmdir(self.tempdir + os.sep + "Pictures")
+ os.rmdir(self.tempdir + os.sep + "META-INF")
+ os.rmdir(self.tempdir)
+
+ def _write_styles_file(self):
+ file = self.tempdir + os.sep + "styles.xml"
+ self.f = open(file,"w")
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('???\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('Page 1\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('??? ')
+ self.f.write('(???)\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('05/16/2001, ')
+ self.f.write('10:53:17\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('Page 1 / ')
+ self.f.write('99\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.close()
+
+ def start_page(self,name,style_name):
+ table = self.table_styles[style_name]
+ self.f.write('\n')
+ for col in range(0,table.get_columns()):
+ self.f.write('\n')
+
+ def end_page(self):
+ self.f.write('\n')
+
+ def write_text(self,text):
+ if text == "":
+ return
+ if self.content == 0:
+ self.f.write('')
+ self.content = 1
+ text = string.replace(text,'\t','')
+ text = string.replace(text,'\n','')
+ self.f.write(latin_to_utf8(text))
+
+ def _write_manifest(self):
+ file = self.tempdir + os.sep + "META-INF" + os.sep + "manifest.xml"
+ self.f = open(file,"w")
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ self.f.write('')
+ #self.f.write('')
+ self.f.write('\n')
+ self.f.close()
+
+ def _write_meta_file(self):
+ file = self.tempdir + os.sep + "meta.xml"
+ name = latin_to_utf8(self.name)
+ self.f = open(file,"w")
+ self.f.write('\n')
+ self.f.write('\n');
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(const.progName + ' ' + const.version)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(name)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(self.time)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(name)
+ self.f.write('\n')
+ self.f.write('')
+ self.f.write(self.time)
+ self.f.write('\n')
+ self.f.write('0-00-00T00:00:00\n')
+ self.f.write('en-US\n')
+ self.f.write('1\n')
+ self.f.write('PT0S\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.write('\n')
+ self.f.close()
+
+if __name__ == "__main__":
+
+ doc = OpenSpreadSheet(PaperStyle("junk",21.59,27),PAPER_PORTRAIT)
+
+ t = TableStyle()
+ t.set_columns(3)
+ t.set_column_width(0,4)
+ t.set_column_width(1,2)
+ t.set_column_width(2,1)
+ doc.add_table_style("mytblstyle",t)
+
+ f = FontStyle()
+ f.set_type_face(FONT_SANS_SERIF)
+ f.set_size(16)
+ f.set_bold(1)
+ p = ParagraphStyle()
+ p.set_font(f)
+ p.set_background_color((0xcc,0xff,0xff))
+ p.set_padding(0.5)
+ doc.add_style("p1",p)
+
+ doc.open("/home/dona/test")
+ doc.start_page("Page 1","mytblstyle")
+ doc.start_row()
+ doc.start_cell("p1")
+ doc.write_text("Hello")
+ doc.end_cell()
+ doc.end_row()
+ doc.end_page()
+ doc.close()
diff --git a/gramps/src/docgen/PSDrawDoc.py b/gramps/src/docgen/PSDrawDoc.py
new file mode 100644
index 000000000..28b79e181
--- /dev/null
+++ b/gramps/src/docgen/PSDrawDoc.py
@@ -0,0 +1,168 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+import os
+import tempfile
+import string
+import Plugins
+import intl
+_ = intl.gettext
+
+from TextDoc import *
+from DrawDoc import *
+
+
+class PSDrawDoc(DrawDoc):
+
+ def __init__(self,styles,type,orientation):
+ DrawDoc.__init__(self,styles,type,orientation)
+ self.f = None
+ self.filename = None
+ self.level = 0
+ self.time = "0000-00-00T00:00:00"
+ self.page = 0
+
+ def translate(self,x,y):
+ return (x,self.height-y)
+
+ def fontdef(self,para):
+ font = para.get_font()
+ if font.get_type_face() == FONT_SERIF:
+ if font.get_bold():
+ if font.get_italic():
+ font_name = "/Times-BoldItalic"
+ else:
+ font_name = "/Times-Bold"
+ else:
+ if font.get_italic():
+ font_name = "/Times-Italic"
+ else:
+ font_name = "/Times-Roman"
+ else:
+ if font.get_bold():
+ if font.get_italic():
+ font_name = "/Helvetica-BoldOblique"
+ else:
+ font_name = "/Helvetica-Bold"
+ else:
+ if font.get_italic():
+ font_name = "/Helvetica-Oblique"
+ else:
+ font_name = "/Helvetica"
+
+ return "%s findfont %d scalefont setfont\n" % (font_name,font.get_size())
+
+ def open(self,filename):
+ if filename[-4:] != ".ps":
+ self.filename = filename + ".ps"
+ else:
+ self.filename = filename
+ self.f = open(filename,"w")
+ self.f.write('%!PS-Adobe-3.0\n')
+ self.f.write('%%LanguageLevel: 2\n')
+ self.f.write('%%Pages: (atend)\n')
+ self.f.write('%%PageOrder: Ascend\n')
+ self.f.write('%%EndComments\n')
+ self.f.write('/cm { 28.34 mul } def\n')
+
+ def close(self):
+ self.f.write('%%Trailer\n')
+ self.f.write('%%Pages: ')
+ self.f.write('%d\n' % self.page)
+ self.f.write('%%EOF\n')
+ self.f.close()
+
+ def start_paragraph(self,style_name):
+ pass
+
+ def end_paragraph(self):
+ pass
+
+ def write_text(self,text):
+ pass
+
+ def start_page(self,orientation=None):
+ self.page = self.page + 1
+ self.f.write("%%Page:")
+ self.f.write("%d %d\n" % (self.page,self.page))
+
+ def end_page(self):
+ self.f.write('showpage\n')
+ self.f.write('%%PageTrailer\n')
+
+ def draw_line(self,style,x1,y1,x2,y2):
+ self.f.write('gsave\n')
+ self.f.write('newpath\n')
+ self.f.write('%f cm %f cm moveto\n' % self.translate(x1,y1))
+ self.f.write('%f cm %f cm lineto\n' % self.translate(x2,y2))
+ self.f.write('1 setlinewidth\n')
+ self.f.write('2 setlinecap\n')
+ self.f.write('stroke\n')
+ self.f.write('grestore\n')
+
+ def draw_box(self,style,text,x,y):
+ box_style = self.draw_styles[style]
+ para_name = box_style.get_paragraph_style()
+ p = self.style_list[para_name]
+
+ bh = box_style.get_height()
+ bw = box_style.get_width()
+ self.f.write('gsave\n')
+ self.f.write('newpath\n')
+ self.f.write('%f cm %f cm moveto\n' % self.translate(x+0.15,y+0.15))
+ self.f.write('0 -%f cm rlineto\n' % bh)
+ self.f.write('%f cm 0 rlineto\n' % bw)
+ self.f.write('0 %f cm rlineto\n' % bh)
+ self.f.write('closepath\n')
+ self.f.write('.5 setgray\n')
+ self.f.write('fill\n')
+ self.f.write('newpath\n')
+ self.f.write('%f cm %f cm moveto\n' % self.translate(x,y))
+ self.f.write('0 -%f cm rlineto\n' % bh)
+ self.f.write('%f cm 0 rlineto\n' % bw)
+ self.f.write('0 %f cm rlineto\n' % bh)
+ self.f.write('closepath\n')
+ self.f.write('1 setgray\n')
+ self.f.write('fill\n')
+ self.f.write('newpath\n')
+ self.f.write('%f cm %f cm moveto\n' % self.translate(x,y))
+ self.f.write('0 -%f cm rlineto\n' % bh)
+ self.f.write('%f cm 0 rlineto\n' % bw)
+ self.f.write('0 %f cm rlineto\n' % bh)
+ self.f.write('closepath\n')
+ self.f.write('0 setgray\n')
+ self.f.write('1 setlinewidth\n')
+ self.f.write('stroke\n')
+ if text != "":
+ self.f.write(self.fontdef(p))
+ lines = string.split(text,'\n')
+ nlines = len(lines)
+ mar = 10/28.35
+ f_in_cm = p.get_font().get_size()/28.35
+ fs = f_in_cm * 1.2
+ center = y + (bh + fs)/2.0 + (fs*0.2)
+ ystart = center - (fs/2.0) * nlines
+ for i in range(nlines):
+ ypos = ystart + (i * fs)
+ self.f.write('%f cm %f cm moveto\n' % self.translate(x+mar,ypos))
+ self.f.write("(%s) show\n" % lines[i])
+ self.f.write('grestore\n')
+
+Plugins.register_draw_doc(_("PostScript"),PSDrawDoc);
diff --git a/gramps/src/docgen/PdfDoc.py b/gramps/src/docgen/PdfDoc.py
new file mode 100644
index 000000000..bde2e4733
--- /dev/null
+++ b/gramps/src/docgen/PdfDoc.py
@@ -0,0 +1,284 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+from TextDoc import *
+import Plugins
+import intl
+_ = intl.gettext
+
+import reportlab.platypus.tables
+from reportlab.platypus import *
+from reportlab.lib.units import cm
+from reportlab.lib.colors import Color
+from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
+import reportlab.lib.styles
+
+from latin_utf8 import latin_to_utf8
+
+try:
+ import PIL.Image
+ no_pil = 0
+except:
+ no_pil = 1
+
+#------------------------------------------------------------------------
+#
+#
+#
+#------------------------------------------------------------------------
+class GrampsDocTemplate(BaseDocTemplate):
+
+ def build(self,flowables):
+ self._calc() #in case we changed margins sizes etc
+ BaseDocTemplate.build(self,flowables)
+
+#------------------------------------------------------------------------
+#
+#
+#
+#------------------------------------------------------------------------
+def make_color(color):
+ return Color(float(color[0])/255.0, float(color[1])/255.0,
+ float(color[2])/255.0)
+
+#------------------------------------------------------------------------
+#
+#
+#
+#------------------------------------------------------------------------
+class PdfDoc(TextDoc):
+
+ def open(self,filename):
+ if filename[-4:] != ".pdf":
+ self.filename = filename + ".pdf"
+ else:
+ self.filename = filename
+
+ self.pagesize = (self.width*cm,self.height*cm)
+
+ self.doc = GrampsDocTemplate(self.filename,
+ pagesize=self.pagesize,
+ allowSplitting=1,
+ _pageBreakQuick=0,
+ leftMargin=self.lmargin*cm,
+ rightMargin=self.rmargin*cm,
+ topMargin=self.tmargin*cm,
+ bottomMargin=self.bmargin*cm)
+ frameT = Frame(0,0,self.width*cm,self.height*cm,
+ self.lmargin*cm, self.bmargin*cm, \
+ self.rmargin*cm,self.tmargin*cm,\
+ id='normal')
+ ptemp = PageTemplate(frames=frameT,pagesize=self.pagesize)
+ self.doc.addPageTemplates([ptemp])
+
+ self.pdfstyles = {}
+
+ for style_name in self.style_list.keys():
+ style = self.style_list[style_name]
+ font = style.get_font()
+
+ pdf_style = reportlab.lib.styles.ParagraphStyle(name=style_name)
+ pdf_style.fontSize = font.get_size()
+ pdf_style.bulletFontSize = font.get_size()
+
+ if font.get_type_face() == FONT_SERIF:
+ if font.get_bold():
+ if font.get_italic():
+ pdf_style.fontName = "Times-BoldItalic"
+ else:
+ pdf_style.fontName = "Times-Bold"
+ else:
+ if font.get_italic():
+ pdf_style.fontName = "Times-Italic"
+ else:
+ pdf_style.fontName = "Times-Roman"
+ else:
+ if font.get_bold():
+ if font.get_italic():
+ pdf_style.fontName = "Helvetica-BoldOblique"
+ else:
+ pdf_style.fontName = "Helvetica-Bold"
+ else:
+ if font.get_italic():
+ pdf_style.fontName = "Helvetica-Oblique"
+ else:
+ pdf_style.fontName = "Helvetica"
+ pdf_style.bulletFontName = pdf_style.fontName
+
+
+ right = style.get_right_margin()*cm
+ left = style.get_left_margin()*cm
+ first = left + style.get_first_indent()*cm
+
+ pdf_style.rightIndent = right
+ pdf_style.leftIndent = left
+ pdf_style.firstLineIndent = first
+ pdf_style.bulletIndent = first
+
+ align = style.get_alignment()
+ if align == PARA_ALIGN_RIGHT:
+ pdf_style.alignment = TA_RIGHT
+ elif align == PARA_ALIGN_LEFT:
+ pdf_style.alignment = TA_LEFT
+ elif align == PARA_ALIGN_CENTER:
+ pdf_style.alignment = TA_CENTER
+ else:
+ pdf_style.alignment = TA_JUSTIFY
+ pdf_style.spaceBefore = style.get_padding()
+ pdf_style.spaceAfter = style.get_padding()
+ pdf_style.textColor = make_color(font.get_color())
+ self.pdfstyles[style_name] = pdf_style
+
+ self.story = []
+ self.in_table = 0
+
+ def close(self):
+ self.doc.build(self.story)
+
+ def end_page(self):
+ self.story.append(PageBreak())
+
+ def start_paragraph(self,style_name,leader=None):
+ self.current_para = self.pdfstyles[style_name]
+ self.my_para = self.style_list[style_name]
+ if leader==None:
+ self.text = ''
+ else:
+ self.text = '%s' % leader
+ self.image = 0
+
+ def end_paragraph(self):
+ if self.in_table == 0 and self.image == 0:
+ self.story.append(Paragraph(self.text,self.current_para))
+ self.story.append(Spacer(1,0.5*cm))
+ else:
+ self.image = 0
+
+ def start_bold(self):
+ self.text = self.text + ''
+
+ def end_bold(self):
+ self.text = self.text + ''
+
+ def start_table(self,name,style_name):
+ self.in_table = 1
+ self.cur_table = self.table_styles[style_name]
+ self.row = -1
+ self.col = 0
+ self.cur_row = []
+ self.table_data = []
+
+ self.tblstyle = []
+ self.cur_table_cols = []
+ width = float(self.cur_table.get_width()/100.0) * self.get_usable_width()
+ for val in range(self.cur_table.get_columns()):
+ percent = float(self.cur_table.get_column_width(val))/100.0
+ self.cur_table_cols.append(int(width * percent * cm))
+
+ def end_table(self):
+ ts = reportlab.platypus.tables.TableStyle(self.tblstyle)
+ tbl = reportlab.platypus.tables.Table(data=self.table_data,
+ colWidths=self.cur_table_cols,
+ style=ts)
+ self.story.append(tbl)
+ self.in_table = 0
+
+ def start_row(self):
+ self.row = self.row + 1
+ self.col = 0
+ self.cur_row = []
+
+ def end_row(self):
+ self.table_data.append(self.cur_row)
+
+ def start_cell(self,style_name,span=1):
+ self.span = span
+ self.my_table_style = self.cell_styles[style_name]
+ pass
+
+ def end_cell(self):
+ if self.span == 1:
+# self.cur_row.append(self.text)
+ self.cur_row.append(Paragraph(self.text,self.current_para))
+ else:
+ self.cur_row.append(self.text)
+ for val in range(1,self.span):
+ self.cur_row.append("")
+
+ p = self.my_para
+ f = p.get_font()
+ if f.get_type_face() == FONT_SANS_SERIF:
+ if f.get_bold():
+ fn = 'Helvetica-Bold'
+ else:
+ fn = 'Helvetica'
+ else:
+ if f.get_bold():
+ fn = 'Times-Bold'
+ else:
+ fn = 'Times-Roman'
+
+ black = Color(0,0,0)
+
+ for inc in range(self.col,self.col+self.span):
+ loc = (inc,self.row)
+ self.tblstyle.append(('FONT', loc, loc, fn, f.get_size()))
+ if self.span == 1 or inc == self.col + self.span - 1:
+ if self.my_table_style.get_right_border():
+ self.tblstyle.append('LINEAFTER', loc, loc, 1, black)
+ if self.span == 1 or inc == self.col:
+ if self.my_table_style.get_left_border():
+ self.tblstyle.append('LINEBEFORE', loc, loc, 1, black)
+ if self.my_table_style.get_top_border():
+ self.tblstyle.append('LINEABOVE', loc, loc, 1, black)
+ if self.my_table_style.get_bottom_border():
+ self.tblstyle.append('LINEBELOW', loc, loc, 1, black)
+ if p.get_alignment() == PARA_ALIGN_LEFT:
+ self.tblstyle.append('ALIGN', loc, loc, 'LEFT')
+ elif p.get_alignment() == PARA_ALIGN_RIGHT:
+ self.tblstyle.append('ALIGN', loc, loc, 'RIGHT')
+ else:
+ self.tblstyle.append('ALIGN', loc, loc, 'CENTER')
+ self.tblstyle.append('VALIGN', loc, loc, 'TOP')
+
+ self.col = self.col + self.span
+
+ def add_photo(self,name,pos,x,y):
+ if no_pil == 0:
+ im = PIL.Image.open(name)
+
+ nx,ny = im.size
+ scale = float(nx)/float(ny)
+ if scale > 1.0:
+ scale = 1.0/scale
+ act_width = x
+ act_height = y * scale
+ else:
+ act_width = x * scale
+ act_height = y
+
+ self.story.append(Image(name,act_width*cm,act_height*cm))
+ self.story.append(Spacer(1,0.5*cm))
+ self.image = 1
+
+ def write_text(self,text):
+ self.text = self.text + text
+
+Plugins.register_text_doc(_("PDF"),PdfDoc,1,1,1)
diff --git a/gramps/src/docgen/PdfDrawDoc.py b/gramps/src/docgen/PdfDrawDoc.py
new file mode 100644
index 000000000..7b4189177
--- /dev/null
+++ b/gramps/src/docgen/PdfDrawDoc.py
@@ -0,0 +1,185 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+import os
+import string
+
+from TextDoc import *
+from DrawDoc import *
+import Plugins
+import intl
+_ = intl.gettext
+
+from reportlab.pdfgen import canvas
+from reportlab.lib.units import cm
+from reportlab.lib.colors import Color
+
+def make_color(color):
+ return Color(float(color[0])/255.0, float(color[1])/255.0,
+ float(color[2])/255.0)
+
+class PdfDrawDoc(DrawDoc):
+
+ def __init__(self,styles,type,orientation):
+ DrawDoc.__init__(self,styles,type,orientation)
+ self.f = None
+ self.filename = None
+ self.level = 0
+ self.time = "0000-00-00T00:00:00"
+ self.page = 0
+
+ def open(self,filename):
+
+ if filename[-4:] != ".pdf":
+ self.filename = filename + ".pdf"
+ else:
+ self.filename = filename
+ self.f = canvas.Canvas(self.filename,(self.width*cm,self.height*cm),0)
+ if self.name:
+ self.f.setAuthor(self.name)
+
+ def close(self):
+ self.f.save()
+
+ def start_paragraph(self,style_name):
+ pass
+
+ def end_paragraph(self):
+ pass
+
+ def write_text(self,text):
+ pass
+
+ def start_page(self,orientation=None):
+ pass
+
+ def end_page(self):
+ self.f.showPage()
+
+ def draw_line(self,style,x1,y1,x2,y2):
+ self.f.line(x1*cm,y1*cm,x2*cm,y2*cm)
+
+ def draw_box(self,style,text,x,y):
+ box_style = self.draw_styles[style]
+ para_name = box_style.get_paragraph_style()
+ p = self.style_list[para_name]
+
+ w = box_style.get_width()*cm
+ h = box_style.get_height()*cm
+
+ if box_style.get_shadow():
+ self.f.setFillColorRGB(0.5,0.5,0.5)
+ self.f.rect((x+0.3)*cm,(y+0.3)*cm,w,h,fill=1,stroke=0)
+
+ font = p.get_font()
+
+ self.f.setStrokeColor(make_color(font.get_color()))
+ self.f.setFillColor(make_color(box_style.get_color()))
+
+ self.f.rect(x*cm,y*cm,w,h,fill=1)
+
+ if text != "":
+ lines = string.split(text,'\n')
+ self.center_print(lines,font,x*cm,y*cm,w,h)
+
+ def write_at(self,style,text,x,y):
+ p = self.style_list[style]
+ font = p.get_font()
+
+ self.f.setStrokeColor(make_color(font.get_color()))
+
+ self.left_print(text,font,x*cm,y*cm)
+
+ def center_print(self,lines,font,x,y,w,h):
+ l = len(lines)
+ size = font.get_size()
+ start_y = (y + h/2.0 + l/2.0 + l) - ((l*size) + ((l-1)*0.2))/2.0
+ start_x = (x + w/2.0)
+
+ self.f.saveState()
+ self.f.setFillColor(make_color(font.get_color()))
+ if font.get_type_face() == FONT_SANS_SERIF:
+ if font.get_bold():
+ self.f.setFont("Helvetica-Bold",font.get_size())
+ else:
+ self.f.setFont("Helvetica",font.get_size())
+ else:
+ if font.get_bold():
+ self.f.setFont("Times-Bold",font.get_size())
+ else:
+ self.f.setFont("Times-Roman",font.get_size())
+
+ for text in lines:
+ self.f.drawCentredString(start_x,start_y,text)
+ start_y = start_y + size*1.2
+ start_y = start_y + size*1.2
+
+ self.f.restoreState()
+
+ def left_print(self,text,font,x,y):
+ size = font.get_size()
+ start_y = y
+ start_x = x
+
+ self.f.saveState()
+ self.f.setFillColor(make_color(font.get_color()))
+ if font.get_type_face() == FONT_SANS_SERIF:
+ if font.get_bold():
+ self.f.setFont("Helvetica-Bold",font.get_size())
+ else:
+ self.f.setFont("Helvetica",font.get_size())
+ else:
+ if font.get_bold():
+ self.f.setFont("Times-Bold",font.get_size())
+ else:
+ self.f.setFont("Times-Roman",font.get_size())
+
+ self.f.drawString(start_x,start_y,text)
+ self.f.restoreState()
+
+if __name__ == "__main__":
+
+
+
+ s = PaperStyle("Junk",27.94,21.59)
+ x = PdfDrawDoc(s,PAPER_PORTRAIT)
+ f = FontStyle()
+ f.set_type_face(FONT_SANS_SERIF)
+ f.set_size(14)
+ p = ParagraphStyle()
+ p.set_font(f)
+ x.add_paragraph_style("mytest",p)
+
+ g = GraphicsStyle()
+ g.set_width(4)
+ g.set_height(2)
+
+ g.set_color((0xff,0xcc,0xff))
+ g.set_paragraph_style("mytest")
+ g.set_shadow(1)
+ x.add_draw_style("mybox",g)
+
+ x.open("test")
+ x.start_page()
+ x.draw_box("mybox","Hello\nThis is Fun",4,4)
+ x.end_page()
+ x.close()
+
+Plugins.register_draw_doc(_("PDF"),PdfDrawDoc);
diff --git a/gramps/src/docgen/RTFDoc.py b/gramps/src/docgen/RTFDoc.py
new file mode 100644
index 000000000..90c0d2ff8
--- /dev/null
+++ b/gramps/src/docgen/RTFDoc.py
@@ -0,0 +1,525 @@
+#
+# Gramps - a GTK+/GNOME based genealogy program
+#
+# Copyright (C) 2000 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
+#
+
+#------------------------------------------------------------------------
+#
+# Load the base TextDoc class
+#
+#------------------------------------------------------------------------
+from TextDoc import *
+import Plugins
+import intl
+_ = intl.gettext
+
+#------------------------------------------------------------------------
+#
+# Attempt to load the Python Imaging Library for the handling of photos.
+#
+#------------------------------------------------------------------------
+try:
+ import PIL.Image
+ no_pil = 0
+except:
+ no_pil = 1
+
+#------------------------------------------------------------------------
+#
+# RTF uses a unit called "twips" for its measurements. According to the
+# RTF specification, 1 point is 20 twips. This routines converts
+# centimeters to twips
+#
+# 2.54 cm/inch 72pts/inch, 20twips/pt
+#
+#------------------------------------------------------------------------
+def twips(cm):
+ return int(((cm/2.54)*72)+0.5)*20
+
+#------------------------------------------------------------------------
+#
+# Rich Text Format Document interface. The current inteface does not
+# use style sheets. Instead it writes raw formatting.
+#
+#------------------------------------------------------------------------
+class RTFDoc(TextDoc):
+
+ #--------------------------------------------------------------------
+ #
+ # Opens the file, and writes the header. Builds the color and font
+ # tables. Fonts are chosen using the MS TrueType fonts, since it
+ # is assumed that if you are generating RTF, you are probably
+ # targeting Word. This generator assumes a Western Europe character
+ # set.
+ #
+ #--------------------------------------------------------------------
+ def open(self,filename):
+ if filename[-4:] != ".rtf":
+ self.filename = filename + ".rtf"
+ else:
+ self.filename = filename
+
+ self.f = open(self.filename,"w")
+ self.f.write('{\\rtf1\\ansi\\ansicpg1252\\deff0\n')
+ self.f.write('{\\fonttbl\n')
+ self.f.write('{\\f0\\froman\\fcharset0\\fprq0 Times New Roman;}\n')
+ self.f.write('{\\f1\\fswiss\\fcharset0\\fprq0 Arial;}}\n')
+ self.f.write('{\colortbl\n')
+ self.color_map = {}
+ index = 1
+ self.color_map[(0,0,0)] = 0
+ self.f.write('\\red0\\green0\\blue0;')
+ for style_name in self.style_list.keys():
+ style = self.style_list[style_name]
+ fgcolor = style.get_font().get_color()
+ bgcolor = style.get_background_color()
+ if not self.color_map.has_key(fgcolor):
+ self.color_map[fgcolor] = index
+ self.f.write('\\red%d\\green%d\\blue%d;' % fgcolor)
+ index = index + 1
+ if not self.color_map.has_key(bgcolor):
+ self.f.write('\\red%d\\green%d\\blue%d;' % bgcolor)
+ self.color_map[bgcolor] = index
+ index = index + 1
+ self.f.write('}\n')
+ self.f.write('\\kerning0\\cf0\\viewkind1')
+ self.f.write('\\paperw%d' % twips(self.width))
+ self.f.write('\\paperh%d' % twips(self.height))
+ self.f.write('\\margl%d' % twips(self.lmargin))
+ self.f.write('\\margr%d' % twips(self.rmargin))
+ self.f.write('\\margt%d' % twips(self.tmargin))
+ self.f.write('\\margb%d' % twips(self.bmargin))
+ self.f.write('\\widowctl\n')
+ self.in_table = 0
+ self.text = ""
+
+ #--------------------------------------------------------------------
+ #
+ # Write the closing brace, and close the file.
+ #
+ #--------------------------------------------------------------------
+ def close(self):
+ self.f.write('}\n')
+ self.f.close()
+
+ #--------------------------------------------------------------------
+ #
+ # Force a section page break
+ #
+ #--------------------------------------------------------------------
+ def end_page(self):
+ self.f.write('\\sbkpage\n')
+
+ #--------------------------------------------------------------------
+ #
+ # Starts a paragraph. Instead of using a style sheet, generate the
+ # the style for each paragraph on the fly. Not the ideal, but it
+ # does work.
+ #
+ #--------------------------------------------------------------------
+ def start_paragraph(self,style_name,leader=None):
+ self.opened = 0
+ p = self.style_list[style_name]
+
+ # build font information
+
+ f = p.get_font()
+ size = f.get_size()*2
+ bgindex = self.color_map[p.get_background_color()]
+ fgindex = self.color_map[f.get_color()]
+ if f.get_type_face() == FONT_SERIF:
+ self.font_type = '\\f0\\fs%d\\cf%d\\cb%d' % (size,fgindex,bgindex)
+ else:
+ self.font_type = '\\f1\\fs%d\\cf%d\\cb%d' % (size,fgindex,bgindex)
+ if f.get_bold():
+ self.font_type = self.font_type + "\\b"
+ if f.get_underline():
+ self.font_type = self.font_type + "\\ul"
+ if f.get_italic():
+ self.font_type = self.font_type + "\\i"
+
+ # build paragraph information
+
+ if not self.in_table:
+ self.f.write('\\pard')
+ if p.get_alignment() == PARA_ALIGN_RIGHT:
+ self.f.write('\\qr')
+ elif p.get_alignment() == PARA_ALIGN_CENTER:
+ self.f.write('\\qc')
+ self.f.write('\\ri%d' % twips(p.get_right_margin()))
+ self.f.write('\\li%d' % twips(p.get_left_margin()))
+ self.f.write('\\fi%d' % twips(p.get_first_indent()))
+ if p.get_alignment() == PARA_ALIGN_JUSTIFY:
+ self.f.write('\\qj')
+ if p.get_padding():
+ self.f.write('\\sa%d' % twips(p.get_padding()/2.0))
+ if p.get_top_border():
+ self.f.write('\\brdrt\\brdrs')
+ if p.get_bottom_border():
+ self.f.write('\\brdrb\\brdrs')
+ if p.get_left_border():
+ self.f.write('\\brdrl\\brdrs')
+ if p.get_right_border():
+ self.f.write('\\brdrr\\brdrs')
+ if p.get_first_indent():
+ self.f.write('\\fi%d' % twips(p.get_first_indent()))
+ if p.get_left_margin():
+ self.f.write('\\li%d' % twips(p.get_left_margin()))
+ if p.get_right_margin():
+ self.f.write('\\ri%d' % twips(p.get_right_margin()))
+
+ if leader:
+ self.opened = 1
+ self.f.write('\\tx%d' % twips(p.get_left_margin()))
+ self.f.write('{%s ' % self.font_type)
+ self.write_text(leader)
+ self.f.write('\\tab}')
+ self.opened = 0
+
+ #--------------------------------------------------------------------
+ #
+ # Ends a paragraph. Care has to be taken to make sure that the
+ # braces are closed properly. The self.opened flag is used to indicate
+ # if braces are currently open. If the last write was the end of
+ # a bold-faced phrase, braces may already be closed.
+ #
+ #--------------------------------------------------------------------
+ def end_paragraph(self):
+ if not self.in_table:
+ self.f.write(self.text)
+ if self.opened:
+ self.f.write('}')
+ self.text = ""
+ self.opened = 0
+ self.f.write('\n\\par')
+ else:
+ if self.text == "":
+ self.write_text(" ")
+ self.text = self.text + '}'
+
+ #--------------------------------------------------------------------
+ #
+ # Starts boldfaced text, enclosed the braces
+ #
+ #--------------------------------------------------------------------
+ def start_bold(self):
+ if self.opened:
+ self.f.write('}')
+ self.f.write('{%s\\b ' % self.font_type)
+ self.opened = 1
+
+ #--------------------------------------------------------------------
+ #
+ # Ends boldfaced text, closing the braces
+ #
+ #--------------------------------------------------------------------
+ def end_bold(self):
+ self.opened = 0
+ self.f.write('}')
+
+ #--------------------------------------------------------------------
+ #
+ # Start a table. Grab the table style, and store it. Keep a flag to
+ # indicate that we are in a table. This helps us deal with paragraphs
+ # internal to a table. RTF does not require anything to start a
+ # table, since a table is treated as a bunch of rows.
+ #
+ #--------------------------------------------------------------------
+ def start_table(self,name,style_name):
+ self.in_table = 1
+ self.tbl_style = self.table_styles[style_name]
+
+ #--------------------------------------------------------------------
+ #
+ # End a table. Turn off the table flag
+ #
+ #--------------------------------------------------------------------
+ def end_table(self):
+ self.in_table = 0
+
+ #--------------------------------------------------------------------
+ #
+ # Start a row. RTF uses the \trowd to start a row. RTF also specifies
+ # all the cell data after it has specified the cell definitions for
+ # the row. Therefore it is necessary to keep a list of cell contents
+ # that is to be written after all the cells are defined.
+ #
+ #--------------------------------------------------------------------
+ def start_row(self):
+ self.contents = []
+ self.cell = 0
+ self.prev = 0
+ self.cell_percent = 0.0
+ self.f.write('\\trowd\n')
+
+ #--------------------------------------------------------------------
+ #
+ # End a row. Write the cell contents, separated by the \cell marker,
+ # then terminate the row
+ #
+ #--------------------------------------------------------------------
+ def end_row(self):
+ self.f.write('{')
+ for line in self.contents:
+ self.f.write(line)
+ self.f.write('\\cell ')
+ self.f.write('}\\pard\\intbl\\row\n')
+
+ #--------------------------------------------------------------------
+ #
+ # Start a cell. Dump out the cell specifics, such as borders. Cell
+ # widths are kind of interesting. RTF doesn't specify how wide a cell
+ # is, but rather where it's right edge is in relationship to the
+ # left margin. This means that each cell is the cumlative of the
+ # previous cells plus its own width.
+ #
+ #--------------------------------------------------------------------
+ def start_cell(self,style_name,span=1):
+ s = self.cell_styles[style_name]
+ self.remain = span -1
+ if s.get_top_border():
+ self.f.write('\\clbrdrt\\brdrs\\brdrw10\n')
+ if s.get_bottom_border():
+ self.f.write('\\clbrdrb\\brdrs\\brdrw10\n')
+ if s.get_left_border():
+ self.f.write('\\clbrdrl\\brdrs\\brdrw10\n')
+ if s.get_right_border():
+ self.f.write('\\clbrdrr\\brdrs\\brdrw10\n')
+ table_width = float(self.get_usable_width())
+ for cell in range(self.cell,self.cell+span):
+ self.cell_percent = self.cell_percent + float(self.tbl_style.get_column_width(cell))
+ cell_width = twips((table_width * self.cell_percent)/100.0)
+ self.f.write('\\cellx%d\\pard\intbl\n' % cell_width)
+ self.cell = self.cell+1
+
+ #--------------------------------------------------------------------
+ #
+ # End a cell. Save the current text in the content lists, since data
+ # must be saved until all cells are defined.
+ #
+ #--------------------------------------------------------------------
+ def end_cell(self):
+ self.contents.append(self.text)
+ self.text = ""
+
+ #--------------------------------------------------------------------
+ #
+ # Add a photo. Embed the photo in the document. Use the Python
+ # imaging library to load and scale the photo. The image is converted
+ # to JPEG, since it is smaller, and supported by RTF. The data is
+ # dumped as a string of HEX numbers.
+ #
+ # If the PIL library is not loaded, ignore the request to load the
+ # photo.
+ #
+ #--------------------------------------------------------------------
+ def add_photo(self,name,pos,x_cm,y_cm):
+ if no_pil:
+ return
+
+ im = PIL.Image.open(name)
+ nx,ny = im.size
+ buf = im.tostring("jpeg","RGB")
+
+ scale = float(ny)/float(nx)
+ if scale > 1:
+ scale = 1.0/scale
+ act_width = twips(x_cm * scale)
+ act_height = twips(y_cm * scale)
+ im.thumbnail((int(act_width*40),int(act_height*40)))
+
+ self.f.write('{\*\shppict{\\pict\\jpegblip')
+ self.f.write('\\picwgoal%d\\pichgoal%d\n' % (act_width,act_height))
+ index = 1
+ for i in buf:
+ self.f.write('%02x' % ord(i))
+ if index%32==0:
+ self.f.write('\n')
+ index = index+1
+ self.f.write('}}\\par\n')
+
+ #--------------------------------------------------------------------
+ #
+ # Writes text. If braces are not currently open, open them. Loop
+ # character by character (terribly inefficient, but it works). If a
+ # character is 8 bit (>127), convert it to a hex representation in
+ # the form of \`XX. Make sure to escape braces.
+ #
+ #--------------------------------------------------------------------
+ def write_text(self,text):
+ if self.opened == 0:
+ self.opened = 1
+ self.text = self.text + '{%s ' % self.font_type
+ for i in text:
+ if ord(i) > 127:
+ self.text = self.text + '\\\'%2x' % ord(i)
+ elif i == '{' or i == '}' :
+ self.text = self.text + '\\%s' % i
+ else:
+ self.text = self.text + i
+
+
+if __name__ == "__main__":
+
+ paper = PaperStyle("Letter",27.94,21.59)
+
+ styles = StyleSheet()
+ foo = FontStyle()
+ foo.set_type_face(FONT_SANS_SERIF)
+ foo.set_color((255,0,0))
+ foo.set_size(24)
+ foo.set_underline(1)
+ foo.set_bold(1)
+ foo.set_italic(1)
+
+ para = ParagraphStyle()
+ para.set_alignment(PARA_ALIGN_RIGHT)
+ para.set_font(foo)
+ styles.add_style("Title",para)
+
+ foo = FontStyle()
+ foo.set_type_face(FONT_SERIF)
+ foo.set_size(12)
+
+ para = ParagraphStyle()
+ para.set_font(foo)
+ styles.add_style("Normal",para)
+
+ foo = FontStyle()
+ foo.set_type_face(FONT_SERIF)
+ foo.set_size(12)
+
+ para = ParagraphStyle()
+ para.set_font(foo)
+ para.set_top_border(1)
+ para.set_left_border(1)
+ para.set_right_border(1)
+ para.set_bottom_border(1)
+ styles.add_style("Box",para)
+
+ doc = RTFDoc(styles,paper,PAPER_PORTRAIT)
+
+ cell = TableCellStyle()
+ cell.set_padding(0.2)
+ cell.set_top_border(1)
+ cell.set_bottom_border(1)
+ cell.set_right_border(1)
+ cell.set_left_border(1)
+ doc.add_cell_style('ParentHead',cell)
+
+ cell = TableCellStyle()
+ cell.set_padding(0.1)
+ cell.set_bottom_border(1)
+ cell.set_left_border(1)
+ doc.add_cell_style('TextContents',cell)
+
+ cell = TableCellStyle()
+ cell.set_padding(0.1)
+ cell.set_bottom_border(0)
+ cell.set_left_border(1)
+ cell.set_padding(0.1)
+ doc.add_cell_style('TextChild1',cell)
+
+ cell = TableCellStyle()
+ cell.set_padding(0.1)
+ cell.set_bottom_border(1)
+ cell.set_left_border(1)
+ cell.set_padding(0.1)
+ doc.add_cell_style('TextChild2',cell)
+
+ cell = TableCellStyle()
+ cell.set_padding(0.1)
+ cell.set_bottom_border(1)
+ cell.set_right_border(1)
+ cell.set_left_border(1)
+ doc.add_cell_style('TextContentsEnd',cell)
+
+ cell = TableCellStyle()
+ cell.set_padding(0.2)
+ cell.set_bottom_border(1)
+ cell.set_right_border(1)
+ cell.set_left_border(1)
+ doc.add_cell_style('ChildName',cell)
+
+ table = TableStyle()
+ table.set_width(100)
+ table.set_columns(3)
+ table.set_column_width(0,20)
+ table.set_column_width(1,40)
+ table.set_column_width(2,40)
+ doc.add_table_style('ParentTable',table)
+
+ table = TableStyle()
+ table.set_width(100)
+ table.set_columns(4)
+ table.set_column_width(0,5)
+ table.set_column_width(1,15)
+ table.set_column_width(2,40)
+ table.set_column_width(3,40)
+ doc.add_table_style('ChildTable',table)
+
+ doc.open("test")
+
+ doc.start_paragraph("Title")
+ doc.write_text("My Title")
+ doc.end_paragraph()
+
+ doc.start_paragraph("Normal")
+ doc.write_text("Hello there. This is fun")
+ doc.end_paragraph()
+
+ doc.start_paragraph("Box")
+ doc.write_text("This is my box")
+ doc.end_paragraph()
+
+ doc.start_paragraph("Normal")
+ doc.add_photo("foo.png",200,200)
+ doc.end_paragraph()
+
+ doc.start_table(id,'ParentTable')
+ doc.start_row()
+ doc.start_cell('ParentHead',3)
+ doc.start_paragraph('Normal')
+ doc.write_text('Banana : Smith ')
+ doc.end_paragraph()
+ doc.end_cell()
+ doc.end_row()
+
+ doc.start_row()
+ doc.start_cell("TextContents")
+ doc.start_paragraph('Normal')
+ doc.write_text("some event")
+ doc.end_paragraph()
+ doc.end_cell()
+ doc.start_cell("TextContents")
+ doc.start_paragraph('Normal')
+ doc.write_text("someday")
+ doc.end_paragraph()
+ doc.end_cell()
+ doc.start_cell("TextContentsEnd")
+ doc.start_paragraph('Normal')
+ doc.write_text("somewhere")
+ doc.end_paragraph()
+ doc.end_cell()
+ doc.end_row()
+
+ doc.end_table()
+
+ doc.close()
+
+Plugins.register_text_doc(_("Rich Text Format (RTF)"),RTFDoc,1,1,1)
diff --git a/gramps/src/gramps_main.py b/gramps/src/gramps_main.py
index 45ea49e81..dba3e0e7f 100755
--- a/gramps/src/gramps_main.py
+++ b/gramps/src/gramps_main.py
@@ -2009,6 +2009,8 @@ def main(arg):
database = RelDataBase()
+ Plugins.load_plugins(const.docgenDir)
+ Plugins.load_plugins(os.path.expanduser("~/.gramps/docgen"))
Plugins.load_plugins(const.pluginsDir)
Plugins.load_plugins(os.path.expanduser("~/.gramps/plugins"))
Filter.load_filters(const.filtersDir)
diff --git a/gramps/src/plugins/AncestorChart.py b/gramps/src/plugins/AncestorChart.py
index 83821e546..a720127c8 100644
--- a/gramps/src/plugins/AncestorChart.py
+++ b/gramps/src/plugins/AncestorChart.py
@@ -146,7 +146,7 @@ class AncestorChart:
page = page + 1
generation = generation + 3
try:
- self.doc.close()
+ self.doc.close()
except:
print _("Document write failure")