0003796: Make export available when no GUI available. Patch from jmodule (Jakim Friant).

svn: r15294
This commit is contained in:
Brian Matherly
2010-05-01 04:12:42 +00:00
parent 356f23ac98
commit df32be43de
137 changed files with 29439 additions and 9737 deletions

View File

@@ -5,6 +5,7 @@
SUBDIRS = \
editors \
plug \
selectors \
views \
widgets

78
src/gui/plug/Makefile.am Normal file
View File

@@ -0,0 +1,78 @@
# This is the src/PluginUtils level Makefile for Gramps
# We could use GNU make's ':=' syntax for nice wildcard use,
# but that is not necessarily portable.
# If not using GNU make, then list all .py files individually
SUBDIRS = report
pkgdatadir = $(datadir)/@PACKAGE@/gui/plug
pkgdata_PYTHON = \
__init__.py\
_guioptions.py\
_windows.py\
_dialogs.py
pkgpyexecdir = @pkgpyexecdir@/gui/plug
pkgpythondir = @pkgpythondir@/gui/plug
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo
GRAMPS_PY_MODPATH = "../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));
# This is the src/PluginUtils level Makefile for Gramps
# We could use GNU make's ':=' syntax for nice wildcard use,
# but that is not necessarily portable.
# If not using GNU make, then list all .py files individually
SUBDIRS = report
pkgdatadir = $(datadir)/@PACKAGE@/gui/plug
pkgdata_PYTHON = \
__init__.py\
_guioptions.py\
_windows.py\
_dialogs.py
pkgpyexecdir = @pkgpyexecdir@/gui/plug
pkgpythondir = @pkgpythondir@/gui/plug
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo
GRAMPS_PY_MODPATH = "../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));
# This is the src/PluginUtils level Makefile for Gramps
# We could use GNU make's ':=' syntax for nice wildcard use,
# but that is not necessarily portable.
# If not using GNU make, then list all .py files individually
SUBDIRS = report
pkgdatadir = $(datadir)/@PACKAGE@/gui/plug
pkgdata_PYTHON = \
__init__.py\
_guioptions.py\
_windows.py\
_dialogs.py
pkgpyexecdir = @pkgpyexecdir@/gui/plug
pkgpythondir = @pkgpythondir@/gui/plug
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo
GRAMPS_PY_MODPATH = "../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));

150
src/gui/plug/__init__.py Normal file
View File

@@ -0,0 +1,150 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008 Brian Matherly
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2010 Jakim Friant
#
# 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
#
# gui.plug.__init__.py
#
# $Id$
#
__author__="jfriant"
__date__ ="$Apr 20, 2010 3:13:24 PM$"
from gui.plug import tool
from _guioptions import GuiMenuOptions, make_gui_option
from _dialogs import ReportPluginDialog, ToolPluginDialog
import _windows as PluginWindows
# This needs to go above Tool and MenuOption as it needs both
class MenuToolOptions(GuiMenuOptions, tool.ToolOptions):
"""
The MenuToolOptions class implements the ToolOptions
functionality in a generic way so that the user does not need to
be concerned with the graphical representation of the options.
The user should inherit the MenuToolOptions class and override the
add_menu_options function. The user can add options to the menu
and the MenuToolOptions class will worry about setting up the GUI.
"""
def __init__(self, name, person_id=None, dbstate=None):
tool.ToolOptions.__init__(self, name, person_id)
GuiMenuOptions.__init__(self)
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008 Brian Matherly
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2010 Jakim Friant
#
# 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
#
# gui.plug.__init__.py
#
# $Id$
#
__author__="jfriant"
__date__ ="$Apr 20, 2010 3:13:24 PM$"
from gui.plug import tool
from _guioptions import GuiMenuOptions, make_gui_option
from _dialogs import ReportPluginDialog, ToolPluginDialog
import _windows as PluginWindows
# This needs to go above Tool and MenuOption as it needs both
class MenuToolOptions(GuiMenuOptions, tool.ToolOptions):
"""
The MenuToolOptions class implements the ToolOptions
functionality in a generic way so that the user does not need to
be concerned with the graphical representation of the options.
The user should inherit the MenuToolOptions class and override the
add_menu_options function. The user can add options to the menu
and the MenuToolOptions class will worry about setting up the GUI.
"""
def __init__(self, name, person_id=None, dbstate=None):
tool.ToolOptions.__init__(self, name, person_id)
GuiMenuOptions.__init__(self)
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008 Brian Matherly
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2010 Jakim Friant
#
# 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
#
# gui.plug.__init__.py
#
# $Id$
#
__author__="jfriant"
__date__ ="$Apr 20, 2010 3:13:24 PM$"
from gui.plug import tool
from _guioptions import GuiMenuOptions, make_gui_option
from _dialogs import ReportPluginDialog, ToolPluginDialog
import _windows as PluginWindows
# This needs to go above Tool and MenuOption as it needs both
class MenuToolOptions(GuiMenuOptions, tool.ToolOptions):
"""
The MenuToolOptions class implements the ToolOptions
functionality in a generic way so that the user does not need to
be concerned with the graphical representation of the options.
The user should inherit the MenuToolOptions class and override the
add_menu_options function. The user can add options to the menu
and the MenuToolOptions class will worry about setting up the GUI.
"""
def __init__(self, name, person_id=None, dbstate=None):
tool.ToolOptions.__init__(self, name, person_id)
GuiMenuOptions.__init__(self)

954
src/gui/plug/_dialogs.py Normal file
View File

@@ -0,0 +1,954 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GTK libraries
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
from collections import defaultdict
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
from gen.plug.report._constants import standalone_categories
from gui.plug import tool
from gen.plug import REPORT
from gui.plug.report import report
from gui.pluginmanager import GuiPluginManager
import ManagedWindow
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
_REPORTS = 0
_TOOLS = 1
_UNSUPPORTED = _("Unsupported")
#-------------------------------------------------------------------------
#
# PluginDialog interface class
#
#-------------------------------------------------------------------------
class PluginDialog(ManagedWindow.ManagedWindow):
"""
Displays the dialog box that allows the user to select the
plugin that is desired.
"""
def __init__(self, state, uistate, track, categories, msg,
label=None, button_label=None, tool_tip=None,
content=_REPORTS):
"""
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 dialog box.
"""
self.active = uistate.get_active('Person')
self.imap = {}
self.msg = msg
self.content = content
self._pmgr = GuiPluginManager.get_instance()
ManagedWindow.ManagedWindow.__init__(self, uistate, track,
self.__class__)
self.state = state
self.uistate = uistate
self.dialog = gtk.Builder()
self.dialog.add_from_file(const.PLUGINS_GLADE)
self.dialog.connect_signals({
"on_report_apply_clicked" : self.on_apply_clicked,
"destroy_passed_object" : self.close,
"on_delete_event": self.close,
})
self.tree = self.dialog.get_object("tree")
window = self.dialog.get_object("report")
self.title = self.dialog.get_object("title")
self.set_window(window, self.title, msg )
self.store = gtk.TreeStore(str)
self.selection = self.tree.get_selection()
self.selection.connect('changed', self.on_node_selected)
col = gtk.TreeViewColumn('', gtk.CellRendererText(), text=0)
self.tree.append_column(col)
self.tree.set_model(self.store)
self.description = self.dialog.get_object("description")
if label:
self.description.set_text(label)
self.status = self.dialog.get_object("report_status")
self.author_name = self.dialog.get_object("author_name")
self.author_email = self.dialog.get_object("author_email")
self.apply_button = self.dialog.get_object("apply")
if button_label:
self.apply_button.set_label(button_label)
else:
self.apply_button.set_label(_("_Apply"))
self.apply_button.set_use_underline(True)
if tool_tip:
self.apply_button.set_tooltip_text(tool_tip)
self.item = None
if content == _REPORTS:
reg_list = self._pmgr.get_reg_reports()
elif content == _TOOLS:
reg_list = self._pmgr.get_reg_tools()
else:
reg_list = []
self.build_plugin_tree(reg_list, categories)
self.show()
def rebuild(self):
# This method needs to be overridden in the subclass
assert False, "This method needs to be overridden in the subclass."
def build_menu_names(self, obj):
return (self.msg, None)
def on_apply_clicked(self, obj):
"""Execute the selected report"""
if not self.item:
return
self.run_plugin(self.item)
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"""
store, node = self.selection.get_selected()
if node:
path = store.get_path(node)
if not node or path not in self.imap:
return
pdata = self.imap[path]
#(report_class, options_class, title, category, name,
# doc,status,author,email,unsupported,require_active) = data
self.description.set_text(pdata.description)
if not pdata.supported:
status = _UNSUPPORTED
self.status.set_text(pdata.statustext())
self.title.set_text('<span weight="bold" size="larger">%s</span>' \
% pdata.name)
self.title.set_use_markup(1)
self.author_name.set_text(', '.join(pdata.authors))
self.author_email.set_text(', '.join(pdata.authors_email))
self.item = pdata
def build_plugin_tree(self, reg_list, categories):
"""Populates a GtkTree with each menu item associated with a entry
in the lists. The list consists of PluginData objects for reports or
tools.
old data was (item_class, options_class,title,category, name,
doc,status,author,email)
Items in the same category are grouped under the same submenu.
The categories must be dicts from integer to string.
"""
ilist = []
self.store.clear()
# build the tree items and group together based on the category name
item_hash = defaultdict(list)
for plugin in reg_list:
if not plugin.supported:
category = _UNSUPPORTED
else:
category = categories[plugin.category]
item_hash[category].append(plugin)
# add a submenu for each category, and populate it with the
# GtkTreeItems that are associated with it.
key_list = [item for item in item_hash if item != _UNSUPPORTED]
key_list.sort(reverse=True)
prev = None
if _UNSUPPORTED in item_hash:
key = _UNSUPPORTED
data = item_hash[key]
node = self.store.insert_after(None, prev)
self.store.set(node, 0, key)
next = None
data.sort(lambda x, y: cmp(x.name, y.name))
for item in data:
next = self.store.insert_after(node, next)
ilist.append((next, item))
self.store.set(next, 0, item.name)
for key in key_list:
data = item_hash[key]
node = self.store.insert_after(None, prev)
self.store.set(node, 0, key)
next = None
data.sort(key=lambda k:k.name)
for item in data:
next = self.store.insert_after(node, next)
ilist.append((next, item))
self.store.set(next, 0, item.name)
for next, tab in ilist:
path = self.store.get_path(next)
self.imap[path] = tab
def run_plugin(self, pdata):
"""
run a plugin based on it's PluginData:
1/ load plugin.
2/ the report is run
"""
mod = self._pmgr.load_plugin(pdata)
if not mod:
#import of plugin failed
return
if pdata.ptype == REPORT:
active_handle = self.uistate.get_active('Person')
report(self.state, self.uistate,
self.state.db.get_person_from_handle(active_handle),
eval('mod.' + pdata.reportclass),
eval('mod.' + pdata.optionclass),
pdata.name, pdata.id,
pdata.category, pdata.require_active)
else:
tool.gui_tool(self.state, self.uistate,
eval('mod.' + pdata.toolclass),
eval('mod.' + pdata.optionclass),
pdata.name, pdata.id, pdata.category,
self.state.db.request_rebuild)
#-------------------------------------------------------------------------
#
# ReportPluginDialog
#
#-------------------------------------------------------------------------
class ReportPluginDialog(PluginDialog):
"""
Displays the dialog box that allows the user to select the
report that is desired.
"""
def __init__(self, dbstate, uistate, track):
"""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."""
PluginDialog.__init__(
self,
dbstate,
uistate,
track,
standalone_categories,
_("Report Selection"),
_("Select a report from those available on the left."),
_("_Generate"), _("Generate selected report"),
_REPORTS)
self._pmgr.connect('plugins-reloaded', self.rebuild)
def rebuild(self):
report_list = self._pmgr.get_reg_reports()
self.build_plugin_tree(report_list, standalone_categories)
#-------------------------------------------------------------------------
#
# ToolPluginDialog
#
#-------------------------------------------------------------------------
class ToolPluginDialog(PluginDialog):
"""Displays the dialog box that allows the user to select the tool
that is desired."""
def __init__(self, dbstate, uistate, track):
"""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."""
PluginDialog.__init__(
self,
dbstate,
uistate,
track,
tool.tool_categories,
_("Tool Selection"),
_("Select a tool from those available on the left."),
_("_Run"),
_("Run selected tool"),
_TOOLS)
def rebuild(self):
tool_list = self._pmgr.get_reg_tools()
self.build_plugin_tree(tool_list, tool.tool_categories)
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GTK libraries
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
from collections import defaultdict
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
from gen.plug.report._constants import standalone_categories
from gui.plug import tool
from gen.plug import REPORT
from gui.plug.report import report
from gui.pluginmanager import GuiPluginManager
import ManagedWindow
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
_REPORTS = 0
_TOOLS = 1
_UNSUPPORTED = _("Unsupported")
#-------------------------------------------------------------------------
#
# PluginDialog interface class
#
#-------------------------------------------------------------------------
class PluginDialog(ManagedWindow.ManagedWindow):
"""
Displays the dialog box that allows the user to select the
plugin that is desired.
"""
def __init__(self, state, uistate, track, categories, msg,
label=None, button_label=None, tool_tip=None,
content=_REPORTS):
"""
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 dialog box.
"""
self.active = uistate.get_active('Person')
self.imap = {}
self.msg = msg
self.content = content
self._pmgr = GuiPluginManager.get_instance()
ManagedWindow.ManagedWindow.__init__(self, uistate, track,
self.__class__)
self.state = state
self.uistate = uistate
self.dialog = gtk.Builder()
self.dialog.add_from_file(const.PLUGINS_GLADE)
self.dialog.connect_signals({
"on_report_apply_clicked" : self.on_apply_clicked,
"destroy_passed_object" : self.close,
"on_delete_event": self.close,
})
self.tree = self.dialog.get_object("tree")
window = self.dialog.get_object("report")
self.title = self.dialog.get_object("title")
self.set_window(window, self.title, msg )
self.store = gtk.TreeStore(str)
self.selection = self.tree.get_selection()
self.selection.connect('changed', self.on_node_selected)
col = gtk.TreeViewColumn('', gtk.CellRendererText(), text=0)
self.tree.append_column(col)
self.tree.set_model(self.store)
self.description = self.dialog.get_object("description")
if label:
self.description.set_text(label)
self.status = self.dialog.get_object("report_status")
self.author_name = self.dialog.get_object("author_name")
self.author_email = self.dialog.get_object("author_email")
self.apply_button = self.dialog.get_object("apply")
if button_label:
self.apply_button.set_label(button_label)
else:
self.apply_button.set_label(_("_Apply"))
self.apply_button.set_use_underline(True)
if tool_tip:
self.apply_button.set_tooltip_text(tool_tip)
self.item = None
if content == _REPORTS:
reg_list = self._pmgr.get_reg_reports()
elif content == _TOOLS:
reg_list = self._pmgr.get_reg_tools()
else:
reg_list = []
self.build_plugin_tree(reg_list, categories)
self.show()
def rebuild(self):
# This method needs to be overridden in the subclass
assert False, "This method needs to be overridden in the subclass."
def build_menu_names(self, obj):
return (self.msg, None)
def on_apply_clicked(self, obj):
"""Execute the selected report"""
if not self.item:
return
self.run_plugin(self.item)
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"""
store, node = self.selection.get_selected()
if node:
path = store.get_path(node)
if not node or path not in self.imap:
return
pdata = self.imap[path]
#(report_class, options_class, title, category, name,
# doc,status,author,email,unsupported,require_active) = data
self.description.set_text(pdata.description)
if not pdata.supported:
status = _UNSUPPORTED
self.status.set_text(pdata.statustext())
self.title.set_text('<span weight="bold" size="larger">%s</span>' \
% pdata.name)
self.title.set_use_markup(1)
self.author_name.set_text(', '.join(pdata.authors))
self.author_email.set_text(', '.join(pdata.authors_email))
self.item = pdata
def build_plugin_tree(self, reg_list, categories):
"""Populates a GtkTree with each menu item associated with a entry
in the lists. The list consists of PluginData objects for reports or
tools.
old data was (item_class, options_class,title,category, name,
doc,status,author,email)
Items in the same category are grouped under the same submenu.
The categories must be dicts from integer to string.
"""
ilist = []
self.store.clear()
# build the tree items and group together based on the category name
item_hash = defaultdict(list)
for plugin in reg_list:
if not plugin.supported:
category = _UNSUPPORTED
else:
category = categories[plugin.category]
item_hash[category].append(plugin)
# add a submenu for each category, and populate it with the
# GtkTreeItems that are associated with it.
key_list = [item for item in item_hash if item != _UNSUPPORTED]
key_list.sort(reverse=True)
prev = None
if _UNSUPPORTED in item_hash:
key = _UNSUPPORTED
data = item_hash[key]
node = self.store.insert_after(None, prev)
self.store.set(node, 0, key)
next = None
data.sort(lambda x, y: cmp(x.name, y.name))
for item in data:
next = self.store.insert_after(node, next)
ilist.append((next, item))
self.store.set(next, 0, item.name)
for key in key_list:
data = item_hash[key]
node = self.store.insert_after(None, prev)
self.store.set(node, 0, key)
next = None
data.sort(key=lambda k:k.name)
for item in data:
next = self.store.insert_after(node, next)
ilist.append((next, item))
self.store.set(next, 0, item.name)
for next, tab in ilist:
path = self.store.get_path(next)
self.imap[path] = tab
def run_plugin(self, pdata):
"""
run a plugin based on it's PluginData:
1/ load plugin.
2/ the report is run
"""
mod = self._pmgr.load_plugin(pdata)
if not mod:
#import of plugin failed
return
if pdata.ptype == REPORT:
active_handle = self.uistate.get_active('Person')
report(self.state, self.uistate,
self.state.db.get_person_from_handle(active_handle),
eval('mod.' + pdata.reportclass),
eval('mod.' + pdata.optionclass),
pdata.name, pdata.id,
pdata.category, pdata.require_active)
else:
tool.gui_tool(self.state, self.uistate,
eval('mod.' + pdata.toolclass),
eval('mod.' + pdata.optionclass),
pdata.name, pdata.id, pdata.category,
self.state.db.request_rebuild)
#-------------------------------------------------------------------------
#
# ReportPluginDialog
#
#-------------------------------------------------------------------------
class ReportPluginDialog(PluginDialog):
"""
Displays the dialog box that allows the user to select the
report that is desired.
"""
def __init__(self, dbstate, uistate, track):
"""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."""
PluginDialog.__init__(
self,
dbstate,
uistate,
track,
standalone_categories,
_("Report Selection"),
_("Select a report from those available on the left."),
_("_Generate"), _("Generate selected report"),
_REPORTS)
self._pmgr.connect('plugins-reloaded', self.rebuild)
def rebuild(self):
report_list = self._pmgr.get_reg_reports()
self.build_plugin_tree(report_list, standalone_categories)
#-------------------------------------------------------------------------
#
# ToolPluginDialog
#
#-------------------------------------------------------------------------
class ToolPluginDialog(PluginDialog):
"""Displays the dialog box that allows the user to select the tool
that is desired."""
def __init__(self, dbstate, uistate, track):
"""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."""
PluginDialog.__init__(
self,
dbstate,
uistate,
track,
tool.tool_categories,
_("Tool Selection"),
_("Select a tool from those available on the left."),
_("_Run"),
_("Run selected tool"),
_TOOLS)
def rebuild(self):
tool_list = self._pmgr.get_reg_tools()
self.build_plugin_tree(tool_list, tool.tool_categories)
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GTK libraries
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# Standard Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
from collections import defaultdict
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
from gen.plug.report._constants import standalone_categories
from gui.plug import tool
from gen.plug import REPORT
from gui.plug.report import report
from gui.pluginmanager import GuiPluginManager
import ManagedWindow
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
_REPORTS = 0
_TOOLS = 1
_UNSUPPORTED = _("Unsupported")
#-------------------------------------------------------------------------
#
# PluginDialog interface class
#
#-------------------------------------------------------------------------
class PluginDialog(ManagedWindow.ManagedWindow):
"""
Displays the dialog box that allows the user to select the
plugin that is desired.
"""
def __init__(self, state, uistate, track, categories, msg,
label=None, button_label=None, tool_tip=None,
content=_REPORTS):
"""
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 dialog box.
"""
self.active = uistate.get_active('Person')
self.imap = {}
self.msg = msg
self.content = content
self._pmgr = GuiPluginManager.get_instance()
ManagedWindow.ManagedWindow.__init__(self, uistate, track,
self.__class__)
self.state = state
self.uistate = uistate
self.dialog = gtk.Builder()
self.dialog.add_from_file(const.PLUGINS_GLADE)
self.dialog.connect_signals({
"on_report_apply_clicked" : self.on_apply_clicked,
"destroy_passed_object" : self.close,
"on_delete_event": self.close,
})
self.tree = self.dialog.get_object("tree")
window = self.dialog.get_object("report")
self.title = self.dialog.get_object("title")
self.set_window(window, self.title, msg )
self.store = gtk.TreeStore(str)
self.selection = self.tree.get_selection()
self.selection.connect('changed', self.on_node_selected)
col = gtk.TreeViewColumn('', gtk.CellRendererText(), text=0)
self.tree.append_column(col)
self.tree.set_model(self.store)
self.description = self.dialog.get_object("description")
if label:
self.description.set_text(label)
self.status = self.dialog.get_object("report_status")
self.author_name = self.dialog.get_object("author_name")
self.author_email = self.dialog.get_object("author_email")
self.apply_button = self.dialog.get_object("apply")
if button_label:
self.apply_button.set_label(button_label)
else:
self.apply_button.set_label(_("_Apply"))
self.apply_button.set_use_underline(True)
if tool_tip:
self.apply_button.set_tooltip_text(tool_tip)
self.item = None
if content == _REPORTS:
reg_list = self._pmgr.get_reg_reports()
elif content == _TOOLS:
reg_list = self._pmgr.get_reg_tools()
else:
reg_list = []
self.build_plugin_tree(reg_list, categories)
self.show()
def rebuild(self):
# This method needs to be overridden in the subclass
assert False, "This method needs to be overridden in the subclass."
def build_menu_names(self, obj):
return (self.msg, None)
def on_apply_clicked(self, obj):
"""Execute the selected report"""
if not self.item:
return
self.run_plugin(self.item)
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"""
store, node = self.selection.get_selected()
if node:
path = store.get_path(node)
if not node or path not in self.imap:
return
pdata = self.imap[path]
#(report_class, options_class, title, category, name,
# doc,status,author,email,unsupported,require_active) = data
self.description.set_text(pdata.description)
if not pdata.supported:
status = _UNSUPPORTED
self.status.set_text(pdata.statustext())
self.title.set_text('<span weight="bold" size="larger">%s</span>' \
% pdata.name)
self.title.set_use_markup(1)
self.author_name.set_text(', '.join(pdata.authors))
self.author_email.set_text(', '.join(pdata.authors_email))
self.item = pdata
def build_plugin_tree(self, reg_list, categories):
"""Populates a GtkTree with each menu item associated with a entry
in the lists. The list consists of PluginData objects for reports or
tools.
old data was (item_class, options_class,title,category, name,
doc,status,author,email)
Items in the same category are grouped under the same submenu.
The categories must be dicts from integer to string.
"""
ilist = []
self.store.clear()
# build the tree items and group together based on the category name
item_hash = defaultdict(list)
for plugin in reg_list:
if not plugin.supported:
category = _UNSUPPORTED
else:
category = categories[plugin.category]
item_hash[category].append(plugin)
# add a submenu for each category, and populate it with the
# GtkTreeItems that are associated with it.
key_list = [item for item in item_hash if item != _UNSUPPORTED]
key_list.sort(reverse=True)
prev = None
if _UNSUPPORTED in item_hash:
key = _UNSUPPORTED
data = item_hash[key]
node = self.store.insert_after(None, prev)
self.store.set(node, 0, key)
next = None
data.sort(lambda x, y: cmp(x.name, y.name))
for item in data:
next = self.store.insert_after(node, next)
ilist.append((next, item))
self.store.set(next, 0, item.name)
for key in key_list:
data = item_hash[key]
node = self.store.insert_after(None, prev)
self.store.set(node, 0, key)
next = None
data.sort(key=lambda k:k.name)
for item in data:
next = self.store.insert_after(node, next)
ilist.append((next, item))
self.store.set(next, 0, item.name)
for next, tab in ilist:
path = self.store.get_path(next)
self.imap[path] = tab
def run_plugin(self, pdata):
"""
run a plugin based on it's PluginData:
1/ load plugin.
2/ the report is run
"""
mod = self._pmgr.load_plugin(pdata)
if not mod:
#import of plugin failed
return
if pdata.ptype == REPORT:
active_handle = self.uistate.get_active('Person')
report(self.state, self.uistate,
self.state.db.get_person_from_handle(active_handle),
eval('mod.' + pdata.reportclass),
eval('mod.' + pdata.optionclass),
pdata.name, pdata.id,
pdata.category, pdata.require_active)
else:
tool.gui_tool(self.state, self.uistate,
eval('mod.' + pdata.toolclass),
eval('mod.' + pdata.optionclass),
pdata.name, pdata.id, pdata.category,
self.state.db.request_rebuild)
#-------------------------------------------------------------------------
#
# ReportPluginDialog
#
#-------------------------------------------------------------------------
class ReportPluginDialog(PluginDialog):
"""
Displays the dialog box that allows the user to select the
report that is desired.
"""
def __init__(self, dbstate, uistate, track):
"""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."""
PluginDialog.__init__(
self,
dbstate,
uistate,
track,
standalone_categories,
_("Report Selection"),
_("Select a report from those available on the left."),
_("_Generate"), _("Generate selected report"),
_REPORTS)
self._pmgr.connect('plugins-reloaded', self.rebuild)
def rebuild(self):
report_list = self._pmgr.get_reg_reports()
self.build_plugin_tree(report_list, standalone_categories)
#-------------------------------------------------------------------------
#
# ToolPluginDialog
#
#-------------------------------------------------------------------------
class ToolPluginDialog(PluginDialog):
"""Displays the dialog box that allows the user to select the tool
that is desired."""
def __init__(self, dbstate, uistate, track):
"""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."""
PluginDialog.__init__(
self,
dbstate,
uistate,
track,
tool.tool_categories,
_("Tool Selection"),
_("Select a tool from those available on the left."),
_("_Run"),
_("Run selected tool"),
_TOOLS)
def rebuild(self):
tool_list = self._pmgr.get_reg_tools()
self.build_plugin_tree(tool_list, tool.tool_categories)

4617
src/gui/plug/_guioptions.py Normal file

File diff suppressed because it is too large Load Diff

3666
src/gui/plug/_windows.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
# This is the src/gui/plug/report level Makefile for Gramps
pkgdatadir = $(datadir)/@PACKAGE@/gui/plug/report
pkgdata_PYTHON = \
__init__.py\
_docreportdialog.py\
_drawreportdialog.py\
_fileentry.py\
_graphvizreportdialog.py\
_options.py\
_papermenu.py\
_reportdialog.py\
_stylecombobox.py\
_styleeditor.py\
_textreportdialog.py\
_webreportdialog.py
pkgpyexecdir = @pkgpyexecdir@/gui/plug/report
pkgpythondir = @pkgpythondir@/gui/plug/report
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo
GRAMPS_PY_MODPATH = "../../../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));
# This is the src/gui/plug/report level Makefile for Gramps
pkgdatadir = $(datadir)/@PACKAGE@/gui/plug/report
pkgdata_PYTHON = \
__init__.py\
_docreportdialog.py\
_drawreportdialog.py\
_fileentry.py\
_graphvizreportdialog.py\
_options.py\
_papermenu.py\
_reportdialog.py\
_stylecombobox.py\
_styleeditor.py\
_textreportdialog.py\
_webreportdialog.py
pkgpyexecdir = @pkgpyexecdir@/gui/plug/report
pkgpythondir = @pkgpythondir@/gui/plug/report
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo
GRAMPS_PY_MODPATH = "../../../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));
# This is the src/gui/plug/report level Makefile for Gramps
pkgdatadir = $(datadir)/@PACKAGE@/gui/plug/report
pkgdata_PYTHON = \
__init__.py\
_docreportdialog.py\
_drawreportdialog.py\
_fileentry.py\
_graphvizreportdialog.py\
_options.py\
_papermenu.py\
_reportdialog.py\
_stylecombobox.py\
_styleeditor.py\
_textreportdialog.py\
_webreportdialog.py
pkgpyexecdir = @pkgpyexecdir@/gui/plug/report
pkgpythondir = @pkgpythondir@/gui/plug/report
# Clean up all the byte-compiled files
MOSTLYCLEANFILES = *pyc *pyo
GRAMPS_PY_MODPATH = "../../../"
pycheck:
(export PYTHONPATH=$(GRAMPS_PY_MODPATH); \
pychecker $(pkgdata_PYTHON));

View File

@@ -0,0 +1,105 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001 David R. Hampton
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2007 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# 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
#
# gui.plug.report.__init__
#
# $Id$
"Report Generation Framework"
from _reportdialog import report
from _drawreportdialog import DrawReportDialog
from _textreportdialog import TextReportDialog
from _options import ReportOptions, MenuReportOptions
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001 David R. Hampton
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2007 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# 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
#
# gui.plug.report.__init__
#
# $Id$
"Report Generation Framework"
from _reportdialog import report
from _drawreportdialog import DrawReportDialog
from _textreportdialog import TextReportDialog
from _options import ReportOptions, MenuReportOptions
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001 David R. Hampton
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2007 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# 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
#
# gui.plug.report.__init__
#
# $Id$
"Report Generation Framework"
from _reportdialog import report
from _drawreportdialog import DrawReportDialog
from _textreportdialog import TextReportDialog
from _options import ReportOptions, MenuReportOptions

View File

@@ -0,0 +1,786 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2007 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
import os
from gen.ggettext import gettext as _
#-------------------------------------------------------------------------
#
# GTK+ modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
from _reportdialog import ReportDialog
from gen.plug.report._constants import CSS_FILES
from _papermenu import PaperFrame
#-------------------------------------------------------------------------
#
# ReportDialog class
#
#-------------------------------------------------------------------------
class DocReportDialog(ReportDialog):
"""
The DocReportDialog base class. This is a base class for generating
dialogs for docgen derived reports.
"""
def __init__(self, dbstate, uistate, option_class, name, trans_name):
"""Initialize a dialog to request that the user select options
for a basic *stand-alone* report."""
self.style_name = "default"
self.firstpage_added = False
ReportDialog.__init__(self, dbstate, uistate, option_class,
name, trans_name)
# Allow for post processing of the format frame, since the
# show_all task calls events that may reset values
def init_interface(self):
ReportDialog.init_interface(self)
self.doc_type_changed(self.format_menu)
#------------------------------------------------------------------------
#
# Functions related to selecting/changing the current file format.
#
#------------------------------------------------------------------------
def make_doc_menu(self, active=None):
"""Build a menu of document types that are appropriate for
this report. This menu will be generated based upon the type
of document (text, draw, graph, etc. - a subclass), whether or
not the document requires table support, etc."""
raise NotImplementedError
def make_document(self):
"""Create a document of the type requested by the user.
"""
pstyle = self.paper_frame.get_paper_style()
self.doc = self.format(self.selected_style, pstyle)
if not self.format_menu.get_active_plugin().get_paper_used():
#set css filename
self.doc.set_css_filename(const.DATA_DIR + os.sep +
self.css_filename)
self.options.set_document(self.doc)
if self.open_with_app.get_active():
self.doc.open_requested()
def doc_type_changed(self, obj):
"""This routine is called when the user selects a new file
formats for the report. It adjust the various dialog sections
to reflect the appropriate values for the currently selected
file format. For example, a HTML document doesn't need any
paper size/orientation options, but it does need a css
file. Those chances are made here."""
docgen_plugin = obj.get_active_plugin()
if docgen_plugin.get_extension():
self.open_with_app.set_sensitive (True)
else:
self.open_with_app.set_sensitive (False)
# Is this to be a printed report or an electronic report
# (i.e. a set of web pages)
if self.firstpage_added:
self.notebook.remove_page(0)
if docgen_plugin.get_paper_used():
self.paper_label = gtk.Label('<b>%s</b>'%_("Paper Options"))
self.paper_label.set_use_markup(True)
self.notebook.insert_page(self.paper_frame, self.paper_label, 0)
self.paper_frame.show_all()
else:
self.html_label = gtk.Label('<b>%s</b>' % _("HTML Options"))
self.html_label.set_use_markup(True)
self.notebook.insert_page(self.html_table, self.html_label, 0)
self.html_table.show_all()
self.firstpage_added = True
ext_val = docgen_plugin.get_extension()
if ext_val:
fname = self.target_fileentry.get_full_path(0)
(spath, ext) = os.path.splitext(fname)
fname = spath + "." + ext_val
self.target_fileentry.set_filename(fname)
self.target_fileentry.set_sensitive(True)
else:
self.target_fileentry.set_filename("")
self.target_fileentry.set_sensitive(False)
# Does this report format use styles?
if self.style_button:
self.style_button.set_sensitive(docgen_plugin.get_style_support())
self.style_menu.set_sensitive(docgen_plugin.get_style_support())
def setup_format_frame(self):
"""Set up the format frame of the dialog. This function
relies on the make_doc_menu() function to do all the hard
work."""
self.make_doc_menu(self.options.handler.get_format_name())
self.format_menu.connect('changed', self.doc_type_changed)
label = gtk.Label("%s:" % _("Output Format"))
label.set_alignment(0.0, 0.5)
self.tbl.attach(label, 1, 2, self.row, self.row+1, gtk.SHRINK|gtk.FILL)
self.tbl.attach(self.format_menu, 2, 4, self.row, self.row+1,
yoptions=gtk.SHRINK)
self.row += 1
self.open_with_app = gtk.CheckButton(_("Open with default viewer"))
self.tbl.attach(self.open_with_app, 2, 4, self.row, self.row+1,
yoptions=gtk.SHRINK)
self.row += 1
ext = self.format_menu.get_active_plugin().get_extension()
if ext is None:
ext = ""
else:
spath = self.get_default_directory()
base = "%s.%s" % (self.raw_name, ext)
spath = os.path.normpath(os.path.join(spath, base))
self.target_fileentry.set_filename(spath)
def setup_report_options_frame(self):
self.paper_frame = PaperFrame(self.options.handler.get_paper_metric(),
self.options.handler.get_paper_name(),
self.options.handler.get_orientation(),
self.options.handler.get_margins(),
self.options.handler.get_custom_paper_size()
)
self.setup_html_frame()
ReportDialog.setup_report_options_frame(self)
def setup_html_frame(self):
"""Set up the html frame of the dialog. This sole purpose of
this function is to grab a pointer for later use in the parse
html frame function."""
self.html_table = gtk.Table(3,3)
self.html_table.set_col_spacings(12)
self.html_table.set_row_spacings(6)
self.html_table.set_border_width(0)
label = gtk.Label("%s:" % _("CSS file"))
label.set_alignment(0.0,0.5)
self.html_table.attach(label, 1, 2, 1, 2, gtk.SHRINK|gtk.FILL,
yoptions=gtk.SHRINK)
self.css_combo = gtk.combo_box_new_text()
css_filename = self.options.handler.get_css_filename()
active_index = 0
index = 0
for style in CSS_FILES:
self.css_combo.append_text(style[0])
if css_filename == style[1]:
active_index = index
index += 1
self.html_table.attach(self.css_combo,2,3,1,2, yoptions=gtk.SHRINK)
self.css_combo.set_active(active_index)
def parse_format_frame(self):
"""Parse the format frame of the dialog. Save the user
selected output format for later use."""
docgen_plugin = self.format_menu.get_active_plugin()
self.format = docgen_plugin.get_basedoc()
format_name = docgen_plugin.get_extension()
self.options.handler.set_format_name(format_name)
def parse_html_frame(self):
"""Parse the html frame of the dialog. Save the user selected
html template name for later use. Note that this routine
retrieves a value whether or not the file entry box is
displayed on the screen. The subclass will know whether this
entry was enabled. This is for simplicity of programming."""
self.css_filename = CSS_FILES[self.css_combo.get_active()][1]
self.options.handler.set_css_filename(self.css_filename)
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Validate
the output file name before doing anything else. If there is
a file name, gather the options and create the report."""
# Is there a filename? This should also test file permissions, etc.
if not self.parse_target_frame():
self.window.run()
# Preparation
self.parse_format_frame()
self.parse_style_frame()
self.parse_html_frame()
self.options.handler.set_paper_metric(self.paper_frame.get_paper_metric())
self.options.handler.set_paper_name(self.paper_frame.get_paper_name())
self.options.handler.set_orientation(self.paper_frame.get_orientation())
self.options.handler.set_margins(self.paper_frame.get_paper_margins())
self.options.handler.set_custom_paper_size(self.paper_frame.get_custom_paper_size())
self.parse_user_options()
# Create the output document.
self.make_document()
# Save options
self.options.handler.save_options()
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2007 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
import os
from gen.ggettext import gettext as _
#-------------------------------------------------------------------------
#
# GTK+ modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
from _reportdialog import ReportDialog
from gen.plug.report._constants import CSS_FILES
from _papermenu import PaperFrame
#-------------------------------------------------------------------------
#
# ReportDialog class
#
#-------------------------------------------------------------------------
class DocReportDialog(ReportDialog):
"""
The DocReportDialog base class. This is a base class for generating
dialogs for docgen derived reports.
"""
def __init__(self, dbstate, uistate, option_class, name, trans_name):
"""Initialize a dialog to request that the user select options
for a basic *stand-alone* report."""
self.style_name = "default"
self.firstpage_added = False
ReportDialog.__init__(self, dbstate, uistate, option_class,
name, trans_name)
# Allow for post processing of the format frame, since the
# show_all task calls events that may reset values
def init_interface(self):
ReportDialog.init_interface(self)
self.doc_type_changed(self.format_menu)
#------------------------------------------------------------------------
#
# Functions related to selecting/changing the current file format.
#
#------------------------------------------------------------------------
def make_doc_menu(self, active=None):
"""Build a menu of document types that are appropriate for
this report. This menu will be generated based upon the type
of document (text, draw, graph, etc. - a subclass), whether or
not the document requires table support, etc."""
raise NotImplementedError
def make_document(self):
"""Create a document of the type requested by the user.
"""
pstyle = self.paper_frame.get_paper_style()
self.doc = self.format(self.selected_style, pstyle)
if not self.format_menu.get_active_plugin().get_paper_used():
#set css filename
self.doc.set_css_filename(const.DATA_DIR + os.sep +
self.css_filename)
self.options.set_document(self.doc)
if self.open_with_app.get_active():
self.doc.open_requested()
def doc_type_changed(self, obj):
"""This routine is called when the user selects a new file
formats for the report. It adjust the various dialog sections
to reflect the appropriate values for the currently selected
file format. For example, a HTML document doesn't need any
paper size/orientation options, but it does need a css
file. Those chances are made here."""
docgen_plugin = obj.get_active_plugin()
if docgen_plugin.get_extension():
self.open_with_app.set_sensitive (True)
else:
self.open_with_app.set_sensitive (False)
# Is this to be a printed report or an electronic report
# (i.e. a set of web pages)
if self.firstpage_added:
self.notebook.remove_page(0)
if docgen_plugin.get_paper_used():
self.paper_label = gtk.Label('<b>%s</b>'%_("Paper Options"))
self.paper_label.set_use_markup(True)
self.notebook.insert_page(self.paper_frame, self.paper_label, 0)
self.paper_frame.show_all()
else:
self.html_label = gtk.Label('<b>%s</b>' % _("HTML Options"))
self.html_label.set_use_markup(True)
self.notebook.insert_page(self.html_table, self.html_label, 0)
self.html_table.show_all()
self.firstpage_added = True
ext_val = docgen_plugin.get_extension()
if ext_val:
fname = self.target_fileentry.get_full_path(0)
(spath, ext) = os.path.splitext(fname)
fname = spath + "." + ext_val
self.target_fileentry.set_filename(fname)
self.target_fileentry.set_sensitive(True)
else:
self.target_fileentry.set_filename("")
self.target_fileentry.set_sensitive(False)
# Does this report format use styles?
if self.style_button:
self.style_button.set_sensitive(docgen_plugin.get_style_support())
self.style_menu.set_sensitive(docgen_plugin.get_style_support())
def setup_format_frame(self):
"""Set up the format frame of the dialog. This function
relies on the make_doc_menu() function to do all the hard
work."""
self.make_doc_menu(self.options.handler.get_format_name())
self.format_menu.connect('changed', self.doc_type_changed)
label = gtk.Label("%s:" % _("Output Format"))
label.set_alignment(0.0, 0.5)
self.tbl.attach(label, 1, 2, self.row, self.row+1, gtk.SHRINK|gtk.FILL)
self.tbl.attach(self.format_menu, 2, 4, self.row, self.row+1,
yoptions=gtk.SHRINK)
self.row += 1
self.open_with_app = gtk.CheckButton(_("Open with default viewer"))
self.tbl.attach(self.open_with_app, 2, 4, self.row, self.row+1,
yoptions=gtk.SHRINK)
self.row += 1
ext = self.format_menu.get_active_plugin().get_extension()
if ext is None:
ext = ""
else:
spath = self.get_default_directory()
base = "%s.%s" % (self.raw_name, ext)
spath = os.path.normpath(os.path.join(spath, base))
self.target_fileentry.set_filename(spath)
def setup_report_options_frame(self):
self.paper_frame = PaperFrame(self.options.handler.get_paper_metric(),
self.options.handler.get_paper_name(),
self.options.handler.get_orientation(),
self.options.handler.get_margins(),
self.options.handler.get_custom_paper_size()
)
self.setup_html_frame()
ReportDialog.setup_report_options_frame(self)
def setup_html_frame(self):
"""Set up the html frame of the dialog. This sole purpose of
this function is to grab a pointer for later use in the parse
html frame function."""
self.html_table = gtk.Table(3,3)
self.html_table.set_col_spacings(12)
self.html_table.set_row_spacings(6)
self.html_table.set_border_width(0)
label = gtk.Label("%s:" % _("CSS file"))
label.set_alignment(0.0,0.5)
self.html_table.attach(label, 1, 2, 1, 2, gtk.SHRINK|gtk.FILL,
yoptions=gtk.SHRINK)
self.css_combo = gtk.combo_box_new_text()
css_filename = self.options.handler.get_css_filename()
active_index = 0
index = 0
for style in CSS_FILES:
self.css_combo.append_text(style[0])
if css_filename == style[1]:
active_index = index
index += 1
self.html_table.attach(self.css_combo,2,3,1,2, yoptions=gtk.SHRINK)
self.css_combo.set_active(active_index)
def parse_format_frame(self):
"""Parse the format frame of the dialog. Save the user
selected output format for later use."""
docgen_plugin = self.format_menu.get_active_plugin()
self.format = docgen_plugin.get_basedoc()
format_name = docgen_plugin.get_extension()
self.options.handler.set_format_name(format_name)
def parse_html_frame(self):
"""Parse the html frame of the dialog. Save the user selected
html template name for later use. Note that this routine
retrieves a value whether or not the file entry box is
displayed on the screen. The subclass will know whether this
entry was enabled. This is for simplicity of programming."""
self.css_filename = CSS_FILES[self.css_combo.get_active()][1]
self.options.handler.set_css_filename(self.css_filename)
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Validate
the output file name before doing anything else. If there is
a file name, gather the options and create the report."""
# Is there a filename? This should also test file permissions, etc.
if not self.parse_target_frame():
self.window.run()
# Preparation
self.parse_format_frame()
self.parse_style_frame()
self.parse_html_frame()
self.options.handler.set_paper_metric(self.paper_frame.get_paper_metric())
self.options.handler.set_paper_name(self.paper_frame.get_paper_name())
self.options.handler.set_orientation(self.paper_frame.get_orientation())
self.options.handler.set_margins(self.paper_frame.get_paper_margins())
self.options.handler.set_custom_paper_size(self.paper_frame.get_custom_paper_size())
self.parse_user_options()
# Create the output document.
self.make_document()
# Save options
self.options.handler.save_options()
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2007 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
import os
from gen.ggettext import gettext as _
#-------------------------------------------------------------------------
#
# GTK+ modules
#
#-------------------------------------------------------------------------
import gtk
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
from _reportdialog import ReportDialog
from gen.plug.report._constants import CSS_FILES
from _papermenu import PaperFrame
#-------------------------------------------------------------------------
#
# ReportDialog class
#
#-------------------------------------------------------------------------
class DocReportDialog(ReportDialog):
"""
The DocReportDialog base class. This is a base class for generating
dialogs for docgen derived reports.
"""
def __init__(self, dbstate, uistate, option_class, name, trans_name):
"""Initialize a dialog to request that the user select options
for a basic *stand-alone* report."""
self.style_name = "default"
self.firstpage_added = False
ReportDialog.__init__(self, dbstate, uistate, option_class,
name, trans_name)
# Allow for post processing of the format frame, since the
# show_all task calls events that may reset values
def init_interface(self):
ReportDialog.init_interface(self)
self.doc_type_changed(self.format_menu)
#------------------------------------------------------------------------
#
# Functions related to selecting/changing the current file format.
#
#------------------------------------------------------------------------
def make_doc_menu(self, active=None):
"""Build a menu of document types that are appropriate for
this report. This menu will be generated based upon the type
of document (text, draw, graph, etc. - a subclass), whether or
not the document requires table support, etc."""
raise NotImplementedError
def make_document(self):
"""Create a document of the type requested by the user.
"""
pstyle = self.paper_frame.get_paper_style()
self.doc = self.format(self.selected_style, pstyle)
if not self.format_menu.get_active_plugin().get_paper_used():
#set css filename
self.doc.set_css_filename(const.DATA_DIR + os.sep +
self.css_filename)
self.options.set_document(self.doc)
if self.open_with_app.get_active():
self.doc.open_requested()
def doc_type_changed(self, obj):
"""This routine is called when the user selects a new file
formats for the report. It adjust the various dialog sections
to reflect the appropriate values for the currently selected
file format. For example, a HTML document doesn't need any
paper size/orientation options, but it does need a css
file. Those chances are made here."""
docgen_plugin = obj.get_active_plugin()
if docgen_plugin.get_extension():
self.open_with_app.set_sensitive (True)
else:
self.open_with_app.set_sensitive (False)
# Is this to be a printed report or an electronic report
# (i.e. a set of web pages)
if self.firstpage_added:
self.notebook.remove_page(0)
if docgen_plugin.get_paper_used():
self.paper_label = gtk.Label('<b>%s</b>'%_("Paper Options"))
self.paper_label.set_use_markup(True)
self.notebook.insert_page(self.paper_frame, self.paper_label, 0)
self.paper_frame.show_all()
else:
self.html_label = gtk.Label('<b>%s</b>' % _("HTML Options"))
self.html_label.set_use_markup(True)
self.notebook.insert_page(self.html_table, self.html_label, 0)
self.html_table.show_all()
self.firstpage_added = True
ext_val = docgen_plugin.get_extension()
if ext_val:
fname = self.target_fileentry.get_full_path(0)
(spath, ext) = os.path.splitext(fname)
fname = spath + "." + ext_val
self.target_fileentry.set_filename(fname)
self.target_fileentry.set_sensitive(True)
else:
self.target_fileentry.set_filename("")
self.target_fileentry.set_sensitive(False)
# Does this report format use styles?
if self.style_button:
self.style_button.set_sensitive(docgen_plugin.get_style_support())
self.style_menu.set_sensitive(docgen_plugin.get_style_support())
def setup_format_frame(self):
"""Set up the format frame of the dialog. This function
relies on the make_doc_menu() function to do all the hard
work."""
self.make_doc_menu(self.options.handler.get_format_name())
self.format_menu.connect('changed', self.doc_type_changed)
label = gtk.Label("%s:" % _("Output Format"))
label.set_alignment(0.0, 0.5)
self.tbl.attach(label, 1, 2, self.row, self.row+1, gtk.SHRINK|gtk.FILL)
self.tbl.attach(self.format_menu, 2, 4, self.row, self.row+1,
yoptions=gtk.SHRINK)
self.row += 1
self.open_with_app = gtk.CheckButton(_("Open with default viewer"))
self.tbl.attach(self.open_with_app, 2, 4, self.row, self.row+1,
yoptions=gtk.SHRINK)
self.row += 1
ext = self.format_menu.get_active_plugin().get_extension()
if ext is None:
ext = ""
else:
spath = self.get_default_directory()
base = "%s.%s" % (self.raw_name, ext)
spath = os.path.normpath(os.path.join(spath, base))
self.target_fileentry.set_filename(spath)
def setup_report_options_frame(self):
self.paper_frame = PaperFrame(self.options.handler.get_paper_metric(),
self.options.handler.get_paper_name(),
self.options.handler.get_orientation(),
self.options.handler.get_margins(),
self.options.handler.get_custom_paper_size()
)
self.setup_html_frame()
ReportDialog.setup_report_options_frame(self)
def setup_html_frame(self):
"""Set up the html frame of the dialog. This sole purpose of
this function is to grab a pointer for later use in the parse
html frame function."""
self.html_table = gtk.Table(3,3)
self.html_table.set_col_spacings(12)
self.html_table.set_row_spacings(6)
self.html_table.set_border_width(0)
label = gtk.Label("%s:" % _("CSS file"))
label.set_alignment(0.0,0.5)
self.html_table.attach(label, 1, 2, 1, 2, gtk.SHRINK|gtk.FILL,
yoptions=gtk.SHRINK)
self.css_combo = gtk.combo_box_new_text()
css_filename = self.options.handler.get_css_filename()
active_index = 0
index = 0
for style in CSS_FILES:
self.css_combo.append_text(style[0])
if css_filename == style[1]:
active_index = index
index += 1
self.html_table.attach(self.css_combo,2,3,1,2, yoptions=gtk.SHRINK)
self.css_combo.set_active(active_index)
def parse_format_frame(self):
"""Parse the format frame of the dialog. Save the user
selected output format for later use."""
docgen_plugin = self.format_menu.get_active_plugin()
self.format = docgen_plugin.get_basedoc()
format_name = docgen_plugin.get_extension()
self.options.handler.set_format_name(format_name)
def parse_html_frame(self):
"""Parse the html frame of the dialog. Save the user selected
html template name for later use. Note that this routine
retrieves a value whether or not the file entry box is
displayed on the screen. The subclass will know whether this
entry was enabled. This is for simplicity of programming."""
self.css_filename = CSS_FILES[self.css_combo.get_active()][1]
self.options.handler.set_css_filename(self.css_filename)
def on_ok_clicked(self, obj):
"""The user is satisfied with the dialog choices. Validate
the output file name before doing anything else. If there is
a file name, gather the options and create the report."""
# Is there a filename? This should also test file permissions, etc.
if not self.parse_target_frame():
self.window.run()
# Preparation
self.parse_format_frame()
self.parse_style_frame()
self.parse_html_frame()
self.options.handler.set_paper_metric(self.paper_frame.get_paper_metric())
self.options.handler.set_paper_name(self.paper_frame.get_paper_name())
self.options.handler.set_orientation(self.paper_frame.get_orientation())
self.options.handler.set_margins(self.paper_frame.get_paper_margins())
self.options.handler.set_custom_paper_size(self.paper_frame.get_custom_paper_size())
self.parse_user_options()
# Create the output document.
self.make_document()
# Save options
self.options.handler.save_options()

View File

@@ -0,0 +1,324 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GTK modules
#
#-------------------------------------------------------------------------
import gtk
import gobject
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gen.plug.report._constants import CATEGORY_DRAW
from _docreportdialog import DocReportDialog
from gui.pluginmanager import GuiPluginManager
#-------------------------------------------------------------------------
#
# _DrawFormatComboBox
#
#-------------------------------------------------------------------------
class _DrawFormatComboBox(gtk.ComboBox):
"""
This class is a combo box that allows the selection of a docgen plugin
from all drawdoc plugins.
"""
def __init__(self, active):
gtk.ComboBox.__init__(self)
pmgr = GuiPluginManager.get_instance()
self.__drawdoc_plugins = []
for plugin in pmgr.get_docgen_plugins():
if plugin.get_draw_support():
self.__drawdoc_plugins.append(plugin)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell, True)
self.add_attribute(cell, 'text', 0)
index = 0
active_index = 0
for plugin in self.__drawdoc_plugins:
name = plugin.get_name()
self.store.append(row=[name])
if plugin.get_extension() == active:
active_index = index
index += 1
self.set_active(active_index)
def get_active_plugin(self):
"""
Get the plugin represented by the currently active selection.
"""
return self.__drawdoc_plugins[self.get_active()]
#-----------------------------------------------------------------------
#
# DrawReportDialog
#
#-----------------------------------------------------------------------
class DrawReportDialog(DocReportDialog):
"""
A class of ReportDialog customized for drawing based reports.
"""
def __init__(self, dbstate, uistate, opt, name, translated_name):
"""
Initialize a dialog to request that the user select options
for a basic drawing report. See the ReportDialog class for
more information.
"""
self.format_menu = None
self.category = CATEGORY_DRAW
DocReportDialog.__init__(self, dbstate, uistate, opt,
name, translated_name)
def make_doc_menu(self,active=None):
"""
Build a menu of document types that are appropriate for
this drawing report.
"""
self.format_menu = _DrawFormatComboBox( active )
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GTK modules
#
#-------------------------------------------------------------------------
import gtk
import gobject
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gen.plug.report._constants import CATEGORY_DRAW
from _docreportdialog import DocReportDialog
from gui.pluginmanager import GuiPluginManager
#-------------------------------------------------------------------------
#
# _DrawFormatComboBox
#
#-------------------------------------------------------------------------
class _DrawFormatComboBox(gtk.ComboBox):
"""
This class is a combo box that allows the selection of a docgen plugin
from all drawdoc plugins.
"""
def __init__(self, active):
gtk.ComboBox.__init__(self)
pmgr = GuiPluginManager.get_instance()
self.__drawdoc_plugins = []
for plugin in pmgr.get_docgen_plugins():
if plugin.get_draw_support():
self.__drawdoc_plugins.append(plugin)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell, True)
self.add_attribute(cell, 'text', 0)
index = 0
active_index = 0
for plugin in self.__drawdoc_plugins:
name = plugin.get_name()
self.store.append(row=[name])
if plugin.get_extension() == active:
active_index = index
index += 1
self.set_active(active_index)
def get_active_plugin(self):
"""
Get the plugin represented by the currently active selection.
"""
return self.__drawdoc_plugins[self.get_active()]
#-----------------------------------------------------------------------
#
# DrawReportDialog
#
#-----------------------------------------------------------------------
class DrawReportDialog(DocReportDialog):
"""
A class of ReportDialog customized for drawing based reports.
"""
def __init__(self, dbstate, uistate, opt, name, translated_name):
"""
Initialize a dialog to request that the user select options
for a basic drawing report. See the ReportDialog class for
more information.
"""
self.format_menu = None
self.category = CATEGORY_DRAW
DocReportDialog.__init__(self, dbstate, uistate, opt,
name, translated_name)
def make_doc_menu(self,active=None):
"""
Build a menu of document types that are appropriate for
this drawing report.
"""
self.format_menu = _DrawFormatComboBox( active )
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GTK modules
#
#-------------------------------------------------------------------------
import gtk
import gobject
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gen.plug.report._constants import CATEGORY_DRAW
from _docreportdialog import DocReportDialog
from gui.pluginmanager import GuiPluginManager
#-------------------------------------------------------------------------
#
# _DrawFormatComboBox
#
#-------------------------------------------------------------------------
class _DrawFormatComboBox(gtk.ComboBox):
"""
This class is a combo box that allows the selection of a docgen plugin
from all drawdoc plugins.
"""
def __init__(self, active):
gtk.ComboBox.__init__(self)
pmgr = GuiPluginManager.get_instance()
self.__drawdoc_plugins = []
for plugin in pmgr.get_docgen_plugins():
if plugin.get_draw_support():
self.__drawdoc_plugins.append(plugin)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell, True)
self.add_attribute(cell, 'text', 0)
index = 0
active_index = 0
for plugin in self.__drawdoc_plugins:
name = plugin.get_name()
self.store.append(row=[name])
if plugin.get_extension() == active:
active_index = index
index += 1
self.set_active(active_index)
def get_active_plugin(self):
"""
Get the plugin represented by the currently active selection.
"""
return self.__drawdoc_plugins[self.get_active()]
#-----------------------------------------------------------------------
#
# DrawReportDialog
#
#-----------------------------------------------------------------------
class DrawReportDialog(DocReportDialog):
"""
A class of ReportDialog customized for drawing based reports.
"""
def __init__(self, dbstate, uistate, opt, name, translated_name):
"""
Initialize a dialog to request that the user select options
for a basic drawing report. See the ReportDialog class for
more information.
"""
self.format_menu = None
self.category = CATEGORY_DRAW
DocReportDialog.__init__(self, dbstate, uistate, opt,
name, translated_name)
def make_doc_menu(self,active=None):
"""
Build a menu of document types that are appropriate for
this drawing report.
"""
self.format_menu = _DrawFormatComboBox( active )

View File

@@ -0,0 +1,306 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2009 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id:_FileEntry.py 9912 2008-01-22 09:17:46Z acraphae $
import os
import gtk
import Utils
class FileEntry(gtk.HBox):
""" A widget that allows the user to select a file from the file system """
def __init__(self, defname, title):
gtk.HBox.__init__(self)
self.title = title
self.dir = False
self.__base_path = ""
self.__file_name = ""
self.entry = gtk.Entry()
self.entry.set_text(defname)
self.set_filename(defname)
self.set_spacing(6)
self.set_homogeneous(False)
self.button = gtk.Button()
image = gtk.Image()
image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON)
self.button.add(image)
self.button.connect('clicked', self.__select_file)
self.pack_start(self.entry, True, True)
self.pack_end(self.button, False, False)
def __select_file(self, obj):
""" Call back function to handle the open button press """
if self.dir:
my_action = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER
else:
my_action = gtk.FILE_CHOOSER_ACTION_SAVE
dialog = gtk.FileChooserDialog(self.title,
action=my_action,
buttons=(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK))
name = os.path.basename(self.entry.get_text())
if self.dir:
if os.path.isdir(name):
dialog.set_current_name(name)
elif os.path.isdir(os.path.basename(name)):
dialog.set_current_name(os.path.basename(name))
else:
dialog.set_current_name(name)
dialog.set_current_folder(self.__base_path)
dialog.present()
status = dialog.run()
if status == gtk.RESPONSE_OK:
self.set_filename(Utils.get_unicode_path(dialog.get_filename()))
dialog.destroy()
def set_filename(self, path):
""" Set the currently selected dialog. """
if not path:
return
if os.path.dirname(path):
self.__base_path = os.path.dirname(path)
self.__file_name = os.path.basename(path)
else:
self.__base_path = os.getcwd()
self.__file_name = path
self.entry.set_text(os.path.join(self.__base_path, self.__file_name))
def get_full_path(self, val):
""" Get the full path of the currently selected file. """
return self.entry.get_text()
def set_directory_entry(self, opt):
"""
Configure the FileEntry to either select a directory or a file.
Set it to True to select a directory.
Set it to False to select a file.
"""
self.dir = opt
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2009 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id:_FileEntry.py 9912 2008-01-22 09:17:46Z acraphae $
import os
import gtk
import Utils
class FileEntry(gtk.HBox):
""" A widget that allows the user to select a file from the file system """
def __init__(self, defname, title):
gtk.HBox.__init__(self)
self.title = title
self.dir = False
self.__base_path = ""
self.__file_name = ""
self.entry = gtk.Entry()
self.entry.set_text(defname)
self.set_filename(defname)
self.set_spacing(6)
self.set_homogeneous(False)
self.button = gtk.Button()
image = gtk.Image()
image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON)
self.button.add(image)
self.button.connect('clicked', self.__select_file)
self.pack_start(self.entry, True, True)
self.pack_end(self.button, False, False)
def __select_file(self, obj):
""" Call back function to handle the open button press """
if self.dir:
my_action = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER
else:
my_action = gtk.FILE_CHOOSER_ACTION_SAVE
dialog = gtk.FileChooserDialog(self.title,
action=my_action,
buttons=(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK))
name = os.path.basename(self.entry.get_text())
if self.dir:
if os.path.isdir(name):
dialog.set_current_name(name)
elif os.path.isdir(os.path.basename(name)):
dialog.set_current_name(os.path.basename(name))
else:
dialog.set_current_name(name)
dialog.set_current_folder(self.__base_path)
dialog.present()
status = dialog.run()
if status == gtk.RESPONSE_OK:
self.set_filename(Utils.get_unicode_path(dialog.get_filename()))
dialog.destroy()
def set_filename(self, path):
""" Set the currently selected dialog. """
if not path:
return
if os.path.dirname(path):
self.__base_path = os.path.dirname(path)
self.__file_name = os.path.basename(path)
else:
self.__base_path = os.getcwd()
self.__file_name = path
self.entry.set_text(os.path.join(self.__base_path, self.__file_name))
def get_full_path(self, val):
""" Get the full path of the currently selected file. """
return self.entry.get_text()
def set_directory_entry(self, opt):
"""
Configure the FileEntry to either select a directory or a file.
Set it to True to select a directory.
Set it to False to select a file.
"""
self.dir = opt
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2009 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id:_FileEntry.py 9912 2008-01-22 09:17:46Z acraphae $
import os
import gtk
import Utils
class FileEntry(gtk.HBox):
""" A widget that allows the user to select a file from the file system """
def __init__(self, defname, title):
gtk.HBox.__init__(self)
self.title = title
self.dir = False
self.__base_path = ""
self.__file_name = ""
self.entry = gtk.Entry()
self.entry.set_text(defname)
self.set_filename(defname)
self.set_spacing(6)
self.set_homogeneous(False)
self.button = gtk.Button()
image = gtk.Image()
image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON)
self.button.add(image)
self.button.connect('clicked', self.__select_file)
self.pack_start(self.entry, True, True)
self.pack_end(self.button, False, False)
def __select_file(self, obj):
""" Call back function to handle the open button press """
if self.dir:
my_action = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER
else:
my_action = gtk.FILE_CHOOSER_ACTION_SAVE
dialog = gtk.FileChooserDialog(self.title,
action=my_action,
buttons=(gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK))
name = os.path.basename(self.entry.get_text())
if self.dir:
if os.path.isdir(name):
dialog.set_current_name(name)
elif os.path.isdir(os.path.basename(name)):
dialog.set_current_name(os.path.basename(name))
else:
dialog.set_current_name(name)
dialog.set_current_folder(self.__base_path)
dialog.present()
status = dialog.run()
if status == gtk.RESPONSE_OK:
self.set_filename(Utils.get_unicode_path(dialog.get_filename()))
dialog.destroy()
def set_filename(self, path):
""" Set the currently selected dialog. """
if not path:
return
if os.path.dirname(path):
self.__base_path = os.path.dirname(path)
self.__file_name = os.path.basename(path)
else:
self.__base_path = os.getcwd()
self.__file_name = path
self.entry.set_text(os.path.join(self.__base_path, self.__file_name))
def get_full_path(self, val):
""" Get the full path of the currently selected file. """
return self.entry.get_text()
def set_directory_entry(self, opt):
"""
Configure the FileEntry to either select a directory or a file.
Set it to True to select a directory.
Set it to False to select a file.
"""
self.dir = opt

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,183 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2004-2007 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
# Written by Alex Roitman
"""
Report option handling, including saving and parsing.
"""
from gen.plug.report._options import ReportOptions
from gui.plug import GuiMenuOptions
#-------------------------------------------------------------------------
#
# MenuReportOptions
#
#-------------------------------------------------------------------------
class MenuReportOptions(GuiMenuOptions, ReportOptions):
"""
The MenuReportOptions class implements the ReportOptions
functionality in a generic way so that the user does not need to
be concerned with the graphical representation of the options.
The user should inherit the MenuReportOptions class and override the
add_menu_options function. The user can add options to the menu and the
MenuReportOptions class will worry about setting up the GUI.
"""
def __init__(self, name, dbase):
ReportOptions.__init__(self, name, dbase)
GuiMenuOptions.__init__(self)
def load_previous_values(self):
ReportOptions.load_previous_values(self)
# Pass the loaded values to the menu options so they will be displayed
# properly.
for optname in self.options_dict:
menu_option = self.menu.get_option_by_name(optname)
if menu_option:
menu_option.set_value(self.options_dict[optname])
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2004-2007 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
# Written by Alex Roitman
"""
Report option handling, including saving and parsing.
"""
from gen.plug.report._options import ReportOptions
from gui.plug import GuiMenuOptions
#-------------------------------------------------------------------------
#
# MenuReportOptions
#
#-------------------------------------------------------------------------
class MenuReportOptions(GuiMenuOptions, ReportOptions):
"""
The MenuReportOptions class implements the ReportOptions
functionality in a generic way so that the user does not need to
be concerned with the graphical representation of the options.
The user should inherit the MenuReportOptions class and override the
add_menu_options function. The user can add options to the menu and the
MenuReportOptions class will worry about setting up the GUI.
"""
def __init__(self, name, dbase):
ReportOptions.__init__(self, name, dbase)
GuiMenuOptions.__init__(self)
def load_previous_values(self):
ReportOptions.load_previous_values(self)
# Pass the loaded values to the menu options so they will be displayed
# properly.
for optname in self.options_dict:
menu_option = self.menu.get_option_by_name(optname)
if menu_option:
menu_option.set_value(self.options_dict[optname])
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2004-2007 Donald N. Allingham
# Copyright (C) 2008 Gary Burton
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
# Written by Alex Roitman
"""
Report option handling, including saving and parsing.
"""
from gen.plug.report._options import ReportOptions
from gui.plug import GuiMenuOptions
#-------------------------------------------------------------------------
#
# MenuReportOptions
#
#-------------------------------------------------------------------------
class MenuReportOptions(GuiMenuOptions, ReportOptions):
"""
The MenuReportOptions class implements the ReportOptions
functionality in a generic way so that the user does not need to
be concerned with the graphical representation of the options.
The user should inherit the MenuReportOptions class and override the
add_menu_options function. The user can add options to the menu and the
MenuReportOptions class will worry about setting up the GUI.
"""
def __init__(self, name, dbase):
ReportOptions.__init__(self, name, dbase)
GuiMenuOptions.__init__(self)
def load_previous_values(self):
ReportOptions.load_previous_values(self)
# Pass the loaded values to the menu options so they will be displayed
# properly.
for optname in self.options_dict:
menu_option = self.menu.get_option_by_name(optname)
if menu_option:
menu_option.set_value(self.options_dict[optname])

View File

@@ -0,0 +1,921 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import sgettext as _
#-------------------------------------------------------------------------
#
# GNOME modules
#
#-------------------------------------------------------------------------
import gtk
import gobject
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gen.plug.docgen import PaperStyle, PAPER_PORTRAIT, PAPER_LANDSCAPE
from gen.plug.report._paper import paper_sizes
from glade import Glade
#-------------------------------------------------------------------------
#
# PaperComboBox
#
#-------------------------------------------------------------------------
class PaperComboBox(gtk.ComboBox):
def __init__(self,default_name):
gtk.ComboBox.__init__(self)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
self.mapping = {}
index = 0
start_index = 0
for key in paper_sizes:
self.mapping[key.get_name()] = key
self.store.append(row=[key.get_name()])
if key.get_name() == default_name:
start_index = index
index += 1
self.set_active(start_index)
def get_value(self):
active = self.get_active()
if active < 0:
return None
key = unicode(self.store[active][0])
return (self.mapping[key],key)
#-------------------------------------------------------------------------
#
# OrientationComboBox
#
#-------------------------------------------------------------------------
class OrientationComboBox(gtk.ComboBox):
def __init__(self,default=PAPER_PORTRAIT):
gtk.ComboBox.__init__(self)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
self.mapping = {}
self.store.append(row=[_('Portrait')])
self.store.append(row=[_('Landscape')])
if default == PAPER_PORTRAIT:
self.set_active(0)
else:
self.set_active(1)
def set_value(self,value=0):
if value == PAPER_PORTRAIT:
self.set_active(0)
else:
self.set_active(1)
def get_value(self):
active = self.get_active()
if active < 0:
return None
if active == 0:
return PAPER_PORTRAIT
else:
return PAPER_LANDSCAPE
#-------------------------------------------------------------------------
#
# PaperFrame
#
#-------------------------------------------------------------------------
class PaperFrame(gtk.HBox):
"""PaperFrame provides all the entry necessary to specify a paper style. """
def __init__(self,default_metric,default_name,default_orientation,
margins=[2.54,2.54,2.54,2.54], custom=[29.7,21.0]):
gtk.HBox.__init__(self)
glade_xml = Glade()
self.paper_table = glade_xml.get_object('paper_table')
# get all the widgets
widgets = ('pwidth', 'pheight', 'lmargin', 'rmargin', 'tmargin',
'bmargin', 'lunits1', 'lunits2', 'lunits3', 'lunits4',
'lunits5', 'lunits6', 'metric')
for w in widgets:
setattr(self, w, glade_xml.get_object(w))
# insert custom widgets
self.papersize_menu = PaperComboBox(default_name)
self.orientation_menu = OrientationComboBox(default_orientation)
self.metric.set_active(default_metric)
# connect all widgets
format_table = glade_xml.get_object('format_table')
format_table.attach(self.papersize_menu, 1, 3, 0, 1,
yoptions=gtk.SHRINK)
format_table.attach(self.orientation_menu, 1, 3, 3, 4,
yoptions=gtk.SHRINK)
# connect signals
self.papersize_menu.connect('changed',self.size_changed)
self.metric.connect('toggled',self.units_changed)
# set initial values
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
self.pwidth.set_text("%.2f" % custom[0])
self.pheight.set_text("%.2f" % custom[1])
self.lmargin.set_text("%.2f" % margins[0])
self.rmargin.set_text("%.2f" % margins[1])
self.tmargin.set_text("%.2f" % margins[2])
self.bmargin.set_text("%.2f" % margins[3])
self.paper_table.show_all()
self.paper_table.reparent(self)
self.units_changed(self.metric)
self.size_changed(None)
def size_changed(self, obj):
"""Paper size combobox 'changed' callback."""
size, name = self.get_paper_size()
is_custom = name == _("Custom Size")
self.pwidth.set_sensitive(is_custom)
self.pheight.set_sensitive(is_custom)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % size.get_width())
self.pheight.set_text("%.2f" % size.get_height())
elif self.paper_unit == 'in.':
self.pwidth.set_text("%.2f" % size.get_width_inches())
self.pheight.set_text("%.2f" % size.get_height_inches())
else:
raise ValueError('Paper dimension unit "%s" is not allowed' %
self.paper_unit)
def units_changed(self, checkbox):
"""Metric checkbox 'toggled' callback."""
paper_size, paper_name = self.get_paper_size()
paper_margins = self.get_paper_margins()
if checkbox.get_active():
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
paper_unit_text = _("cm")
else:
self.paper_unit = 'in.'
self.paper_unit_multiplier = 2.54
paper_unit_text = _("inch|in.")
self.lunits1.set_text(paper_unit_text)
self.lunits2.set_text(paper_unit_text)
self.lunits3.set_text(paper_unit_text)
self.lunits4.set_text(paper_unit_text)
self.lunits5.set_text(paper_unit_text)
self.lunits6.set_text(paper_unit_text)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % paper_size.get_width())
self.pheight.set_text("%.2f" % paper_size.get_height())
else:
self.pwidth.set_text("%.2f" % paper_size.get_width_inches())
self.pheight.set_text("%.2f" % paper_size.get_height_inches())
self.lmargin.set_text("%.2f" %
(paper_margins[0] / self.paper_unit_multiplier))
self.rmargin.set_text("%.2f" %
(paper_margins[1] / self.paper_unit_multiplier))
self.tmargin.set_text("%.2f" %
(paper_margins[2] / self.paper_unit_multiplier))
self.bmargin.set_text("%.2f" %
(paper_margins[3] / self.paper_unit_multiplier))
def get_paper_size(self):
"""Read and validate paper size values.
If needed update the dimensions from the width, height entries,
and worst case fallback to A4 size.
"""
papersize, papername = self.papersize_menu.get_value()
# FIXME it is wrong to use translatable text in comparison.
# How can we distinguish custom size though?
if papername == _('Custom Size'):
try:
h = float(unicode(self.pheight.get_text().replace(",", ".")))
w = float(unicode(self.pwidth.get_text().replace(",", ".") ))
if h <= 1.0 or w <= 1.0:
papersize.set_height(29.7)
papersize.set_width(21.0)
else:
papersize.set_height(h * self.paper_unit_multiplier)
papersize.set_width(w * self.paper_unit_multiplier)
except:
papersize.set_height(29.7)
papersize.set_width(21.0)
return papersize, papername
def get_paper_margins(self):
"""Get and validate margin values from dialog entries.
Values returned in [cm].
"""
paper_margins = [unicode(margin.get_text()) for margin in
self.lmargin, self.rmargin, self.tmargin, self.bmargin]
for i, margin in enumerate(paper_margins):
try:
paper_margins[i] = float(margin.replace(",", "."))
paper_margins[i] = paper_margins[i] * self.paper_unit_multiplier
paper_margins[i] = max(paper_margins[i], 0)
except:
paper_margins[i] = 2.54
return paper_margins
def get_custom_paper_size(self):
width = float(self.pwidth.get_text().replace(",", ".")) * \
self.paper_unit_multiplier
height = float(self.pheight.get_text().replace(",", ".")) * \
self.paper_unit_multiplier
paper_size = [max(width, 1.0), max(height, 1.0)]
return paper_size
def get_paper_style(self):
paper_size, paper_name = self.get_paper_size()
paper_orientation = self.orientation_menu.get_value()
paper_margins = self.get_paper_margins()
pstyle = PaperStyle(paper_size,
paper_orientation,
*paper_margins)
return pstyle
def get_paper_metric(self):
return self.metric.get_active()
def get_paper_name(self):
paper_size, paper_name = self.get_paper_size()
return paper_name
def get_orientation(self):
return self.orientation_menu.get_value()
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import sgettext as _
#-------------------------------------------------------------------------
#
# GNOME modules
#
#-------------------------------------------------------------------------
import gtk
import gobject
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gen.plug.docgen import PaperStyle, PAPER_PORTRAIT, PAPER_LANDSCAPE
from gen.plug.report._paper import paper_sizes
from glade import Glade
#-------------------------------------------------------------------------
#
# PaperComboBox
#
#-------------------------------------------------------------------------
class PaperComboBox(gtk.ComboBox):
def __init__(self,default_name):
gtk.ComboBox.__init__(self)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
self.mapping = {}
index = 0
start_index = 0
for key in paper_sizes:
self.mapping[key.get_name()] = key
self.store.append(row=[key.get_name()])
if key.get_name() == default_name:
start_index = index
index += 1
self.set_active(start_index)
def get_value(self):
active = self.get_active()
if active < 0:
return None
key = unicode(self.store[active][0])
return (self.mapping[key],key)
#-------------------------------------------------------------------------
#
# OrientationComboBox
#
#-------------------------------------------------------------------------
class OrientationComboBox(gtk.ComboBox):
def __init__(self,default=PAPER_PORTRAIT):
gtk.ComboBox.__init__(self)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
self.mapping = {}
self.store.append(row=[_('Portrait')])
self.store.append(row=[_('Landscape')])
if default == PAPER_PORTRAIT:
self.set_active(0)
else:
self.set_active(1)
def set_value(self,value=0):
if value == PAPER_PORTRAIT:
self.set_active(0)
else:
self.set_active(1)
def get_value(self):
active = self.get_active()
if active < 0:
return None
if active == 0:
return PAPER_PORTRAIT
else:
return PAPER_LANDSCAPE
#-------------------------------------------------------------------------
#
# PaperFrame
#
#-------------------------------------------------------------------------
class PaperFrame(gtk.HBox):
"""PaperFrame provides all the entry necessary to specify a paper style. """
def __init__(self,default_metric,default_name,default_orientation,
margins=[2.54,2.54,2.54,2.54], custom=[29.7,21.0]):
gtk.HBox.__init__(self)
glade_xml = Glade()
self.paper_table = glade_xml.get_object('paper_table')
# get all the widgets
widgets = ('pwidth', 'pheight', 'lmargin', 'rmargin', 'tmargin',
'bmargin', 'lunits1', 'lunits2', 'lunits3', 'lunits4',
'lunits5', 'lunits6', 'metric')
for w in widgets:
setattr(self, w, glade_xml.get_object(w))
# insert custom widgets
self.papersize_menu = PaperComboBox(default_name)
self.orientation_menu = OrientationComboBox(default_orientation)
self.metric.set_active(default_metric)
# connect all widgets
format_table = glade_xml.get_object('format_table')
format_table.attach(self.papersize_menu, 1, 3, 0, 1,
yoptions=gtk.SHRINK)
format_table.attach(self.orientation_menu, 1, 3, 3, 4,
yoptions=gtk.SHRINK)
# connect signals
self.papersize_menu.connect('changed',self.size_changed)
self.metric.connect('toggled',self.units_changed)
# set initial values
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
self.pwidth.set_text("%.2f" % custom[0])
self.pheight.set_text("%.2f" % custom[1])
self.lmargin.set_text("%.2f" % margins[0])
self.rmargin.set_text("%.2f" % margins[1])
self.tmargin.set_text("%.2f" % margins[2])
self.bmargin.set_text("%.2f" % margins[3])
self.paper_table.show_all()
self.paper_table.reparent(self)
self.units_changed(self.metric)
self.size_changed(None)
def size_changed(self, obj):
"""Paper size combobox 'changed' callback."""
size, name = self.get_paper_size()
is_custom = name == _("Custom Size")
self.pwidth.set_sensitive(is_custom)
self.pheight.set_sensitive(is_custom)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % size.get_width())
self.pheight.set_text("%.2f" % size.get_height())
elif self.paper_unit == 'in.':
self.pwidth.set_text("%.2f" % size.get_width_inches())
self.pheight.set_text("%.2f" % size.get_height_inches())
else:
raise ValueError('Paper dimension unit "%s" is not allowed' %
self.paper_unit)
def units_changed(self, checkbox):
"""Metric checkbox 'toggled' callback."""
paper_size, paper_name = self.get_paper_size()
paper_margins = self.get_paper_margins()
if checkbox.get_active():
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
paper_unit_text = _("cm")
else:
self.paper_unit = 'in.'
self.paper_unit_multiplier = 2.54
paper_unit_text = _("inch|in.")
self.lunits1.set_text(paper_unit_text)
self.lunits2.set_text(paper_unit_text)
self.lunits3.set_text(paper_unit_text)
self.lunits4.set_text(paper_unit_text)
self.lunits5.set_text(paper_unit_text)
self.lunits6.set_text(paper_unit_text)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % paper_size.get_width())
self.pheight.set_text("%.2f" % paper_size.get_height())
else:
self.pwidth.set_text("%.2f" % paper_size.get_width_inches())
self.pheight.set_text("%.2f" % paper_size.get_height_inches())
self.lmargin.set_text("%.2f" %
(paper_margins[0] / self.paper_unit_multiplier))
self.rmargin.set_text("%.2f" %
(paper_margins[1] / self.paper_unit_multiplier))
self.tmargin.set_text("%.2f" %
(paper_margins[2] / self.paper_unit_multiplier))
self.bmargin.set_text("%.2f" %
(paper_margins[3] / self.paper_unit_multiplier))
def get_paper_size(self):
"""Read and validate paper size values.
If needed update the dimensions from the width, height entries,
and worst case fallback to A4 size.
"""
papersize, papername = self.papersize_menu.get_value()
# FIXME it is wrong to use translatable text in comparison.
# How can we distinguish custom size though?
if papername == _('Custom Size'):
try:
h = float(unicode(self.pheight.get_text().replace(",", ".")))
w = float(unicode(self.pwidth.get_text().replace(",", ".") ))
if h <= 1.0 or w <= 1.0:
papersize.set_height(29.7)
papersize.set_width(21.0)
else:
papersize.set_height(h * self.paper_unit_multiplier)
papersize.set_width(w * self.paper_unit_multiplier)
except:
papersize.set_height(29.7)
papersize.set_width(21.0)
return papersize, papername
def get_paper_margins(self):
"""Get and validate margin values from dialog entries.
Values returned in [cm].
"""
paper_margins = [unicode(margin.get_text()) for margin in
self.lmargin, self.rmargin, self.tmargin, self.bmargin]
for i, margin in enumerate(paper_margins):
try:
paper_margins[i] = float(margin.replace(",", "."))
paper_margins[i] = paper_margins[i] * self.paper_unit_multiplier
paper_margins[i] = max(paper_margins[i], 0)
except:
paper_margins[i] = 2.54
return paper_margins
def get_custom_paper_size(self):
width = float(self.pwidth.get_text().replace(",", ".")) * \
self.paper_unit_multiplier
height = float(self.pheight.get_text().replace(",", ".")) * \
self.paper_unit_multiplier
paper_size = [max(width, 1.0), max(height, 1.0)]
return paper_size
def get_paper_style(self):
paper_size, paper_name = self.get_paper_size()
paper_orientation = self.orientation_menu.get_value()
paper_margins = self.get_paper_margins()
pstyle = PaperStyle(paper_size,
paper_orientation,
*paper_margins)
return pstyle
def get_paper_metric(self):
return self.metric.get_active()
def get_paper_name(self):
paper_size, paper_name = self.get_paper_size()
return paper_name
def get_orientation(self):
return self.orientation_menu.get_value()
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import sgettext as _
#-------------------------------------------------------------------------
#
# GNOME modules
#
#-------------------------------------------------------------------------
import gtk
import gobject
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gen.plug.docgen import PaperStyle, PAPER_PORTRAIT, PAPER_LANDSCAPE
from gen.plug.report._paper import paper_sizes
from glade import Glade
#-------------------------------------------------------------------------
#
# PaperComboBox
#
#-------------------------------------------------------------------------
class PaperComboBox(gtk.ComboBox):
def __init__(self,default_name):
gtk.ComboBox.__init__(self)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
self.mapping = {}
index = 0
start_index = 0
for key in paper_sizes:
self.mapping[key.get_name()] = key
self.store.append(row=[key.get_name()])
if key.get_name() == default_name:
start_index = index
index += 1
self.set_active(start_index)
def get_value(self):
active = self.get_active()
if active < 0:
return None
key = unicode(self.store[active][0])
return (self.mapping[key],key)
#-------------------------------------------------------------------------
#
# OrientationComboBox
#
#-------------------------------------------------------------------------
class OrientationComboBox(gtk.ComboBox):
def __init__(self,default=PAPER_PORTRAIT):
gtk.ComboBox.__init__(self)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
self.mapping = {}
self.store.append(row=[_('Portrait')])
self.store.append(row=[_('Landscape')])
if default == PAPER_PORTRAIT:
self.set_active(0)
else:
self.set_active(1)
def set_value(self,value=0):
if value == PAPER_PORTRAIT:
self.set_active(0)
else:
self.set_active(1)
def get_value(self):
active = self.get_active()
if active < 0:
return None
if active == 0:
return PAPER_PORTRAIT
else:
return PAPER_LANDSCAPE
#-------------------------------------------------------------------------
#
# PaperFrame
#
#-------------------------------------------------------------------------
class PaperFrame(gtk.HBox):
"""PaperFrame provides all the entry necessary to specify a paper style. """
def __init__(self,default_metric,default_name,default_orientation,
margins=[2.54,2.54,2.54,2.54], custom=[29.7,21.0]):
gtk.HBox.__init__(self)
glade_xml = Glade()
self.paper_table = glade_xml.get_object('paper_table')
# get all the widgets
widgets = ('pwidth', 'pheight', 'lmargin', 'rmargin', 'tmargin',
'bmargin', 'lunits1', 'lunits2', 'lunits3', 'lunits4',
'lunits5', 'lunits6', 'metric')
for w in widgets:
setattr(self, w, glade_xml.get_object(w))
# insert custom widgets
self.papersize_menu = PaperComboBox(default_name)
self.orientation_menu = OrientationComboBox(default_orientation)
self.metric.set_active(default_metric)
# connect all widgets
format_table = glade_xml.get_object('format_table')
format_table.attach(self.papersize_menu, 1, 3, 0, 1,
yoptions=gtk.SHRINK)
format_table.attach(self.orientation_menu, 1, 3, 3, 4,
yoptions=gtk.SHRINK)
# connect signals
self.papersize_menu.connect('changed',self.size_changed)
self.metric.connect('toggled',self.units_changed)
# set initial values
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
self.pwidth.set_text("%.2f" % custom[0])
self.pheight.set_text("%.2f" % custom[1])
self.lmargin.set_text("%.2f" % margins[0])
self.rmargin.set_text("%.2f" % margins[1])
self.tmargin.set_text("%.2f" % margins[2])
self.bmargin.set_text("%.2f" % margins[3])
self.paper_table.show_all()
self.paper_table.reparent(self)
self.units_changed(self.metric)
self.size_changed(None)
def size_changed(self, obj):
"""Paper size combobox 'changed' callback."""
size, name = self.get_paper_size()
is_custom = name == _("Custom Size")
self.pwidth.set_sensitive(is_custom)
self.pheight.set_sensitive(is_custom)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % size.get_width())
self.pheight.set_text("%.2f" % size.get_height())
elif self.paper_unit == 'in.':
self.pwidth.set_text("%.2f" % size.get_width_inches())
self.pheight.set_text("%.2f" % size.get_height_inches())
else:
raise ValueError('Paper dimension unit "%s" is not allowed' %
self.paper_unit)
def units_changed(self, checkbox):
"""Metric checkbox 'toggled' callback."""
paper_size, paper_name = self.get_paper_size()
paper_margins = self.get_paper_margins()
if checkbox.get_active():
self.paper_unit = 'cm'
self.paper_unit_multiplier = 1.0
paper_unit_text = _("cm")
else:
self.paper_unit = 'in.'
self.paper_unit_multiplier = 2.54
paper_unit_text = _("inch|in.")
self.lunits1.set_text(paper_unit_text)
self.lunits2.set_text(paper_unit_text)
self.lunits3.set_text(paper_unit_text)
self.lunits4.set_text(paper_unit_text)
self.lunits5.set_text(paper_unit_text)
self.lunits6.set_text(paper_unit_text)
if self.paper_unit == 'cm':
self.pwidth.set_text("%.2f" % paper_size.get_width())
self.pheight.set_text("%.2f" % paper_size.get_height())
else:
self.pwidth.set_text("%.2f" % paper_size.get_width_inches())
self.pheight.set_text("%.2f" % paper_size.get_height_inches())
self.lmargin.set_text("%.2f" %
(paper_margins[0] / self.paper_unit_multiplier))
self.rmargin.set_text("%.2f" %
(paper_margins[1] / self.paper_unit_multiplier))
self.tmargin.set_text("%.2f" %
(paper_margins[2] / self.paper_unit_multiplier))
self.bmargin.set_text("%.2f" %
(paper_margins[3] / self.paper_unit_multiplier))
def get_paper_size(self):
"""Read and validate paper size values.
If needed update the dimensions from the width, height entries,
and worst case fallback to A4 size.
"""
papersize, papername = self.papersize_menu.get_value()
# FIXME it is wrong to use translatable text in comparison.
# How can we distinguish custom size though?
if papername == _('Custom Size'):
try:
h = float(unicode(self.pheight.get_text().replace(",", ".")))
w = float(unicode(self.pwidth.get_text().replace(",", ".") ))
if h <= 1.0 or w <= 1.0:
papersize.set_height(29.7)
papersize.set_width(21.0)
else:
papersize.set_height(h * self.paper_unit_multiplier)
papersize.set_width(w * self.paper_unit_multiplier)
except:
papersize.set_height(29.7)
papersize.set_width(21.0)
return papersize, papername
def get_paper_margins(self):
"""Get and validate margin values from dialog entries.
Values returned in [cm].
"""
paper_margins = [unicode(margin.get_text()) for margin in
self.lmargin, self.rmargin, self.tmargin, self.bmargin]
for i, margin in enumerate(paper_margins):
try:
paper_margins[i] = float(margin.replace(",", "."))
paper_margins[i] = paper_margins[i] * self.paper_unit_multiplier
paper_margins[i] = max(paper_margins[i], 0)
except:
paper_margins[i] = 2.54
return paper_margins
def get_custom_paper_size(self):
width = float(self.pwidth.get_text().replace(",", ".")) * \
self.paper_unit_multiplier
height = float(self.pheight.get_text().replace(",", ".")) * \
self.paper_unit_multiplier
paper_size = [max(width, 1.0), max(height, 1.0)]
return paper_size
def get_paper_style(self):
paper_size, paper_name = self.get_paper_size()
paper_orientation = self.orientation_menu.get_value()
paper_margins = self.get_paper_margins()
pstyle = PaperStyle(paper_size,
paper_orientation,
*paper_margins)
return pstyle
def get_paper_metric(self):
return self.metric.get_active()
def get_paper_name(self):
paper_size, paper_name = self.get_paper_size()
return paper_name
def get_orientation(self):
return self.orientation_menu.get_value()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,261 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
from gen.ggettext import gettext as _
import gtk
import gobject
#-------------------------------------------------------------------------
#
# StyleComboBox
#
#-------------------------------------------------------------------------
class StyleComboBox(gtk.ComboBox):
"""
Derived from the ComboBox, this widget provides handling of Report
Styles.
"""
def __init__(self,model=None):
"""
Initialize the combobox, building the display column.
"""
gtk.ComboBox.__init__(self,model)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
def set(self,style_map,default):
"""
Set the options for the ComboBox, using the passed style
map as the data.
@param style_map: dictionary of style names and the corresponding
style sheet
@type style_map: dictionary
@param default: Default selection in the ComboBox
@type default: str
"""
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
self.style_map = style_map
start_index = 0
for index, key in enumerate(sorted(style_map)):
if key == "default":
self.store.append(row=[_('default')])
else:
self.store.append(row=[key])
if key == default:
start_index = index
self.set_active(start_index)
def get_value(self):
"""
Return the selected key (style sheet name).
@returns: Returns the name of the selected style sheet
@rtype: str
"""
active = self.get_active()
if active < 0:
return None
key = unicode(self.store[active][0])
if key == _('default'):
key = "default"
return (key,self.style_map[key])
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
from gen.ggettext import gettext as _
import gtk
import gobject
#-------------------------------------------------------------------------
#
# StyleComboBox
#
#-------------------------------------------------------------------------
class StyleComboBox(gtk.ComboBox):
"""
Derived from the ComboBox, this widget provides handling of Report
Styles.
"""
def __init__(self,model=None):
"""
Initialize the combobox, building the display column.
"""
gtk.ComboBox.__init__(self,model)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
def set(self,style_map,default):
"""
Set the options for the ComboBox, using the passed style
map as the data.
@param style_map: dictionary of style names and the corresponding
style sheet
@type style_map: dictionary
@param default: Default selection in the ComboBox
@type default: str
"""
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
self.style_map = style_map
start_index = 0
for index, key in enumerate(sorted(style_map)):
if key == "default":
self.store.append(row=[_('default')])
else:
self.store.append(row=[key])
if key == default:
start_index = index
self.set_active(start_index)
def get_value(self):
"""
Return the selected key (style sheet name).
@returns: Returns the name of the selected style sheet
@rtype: str
"""
active = self.get_active()
if active < 0:
return None
key = unicode(self.store[active][0])
if key == _('default'):
key = "default"
return (key,self.style_map[key])
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
from gen.ggettext import gettext as _
import gtk
import gobject
#-------------------------------------------------------------------------
#
# StyleComboBox
#
#-------------------------------------------------------------------------
class StyleComboBox(gtk.ComboBox):
"""
Derived from the ComboBox, this widget provides handling of Report
Styles.
"""
def __init__(self,model=None):
"""
Initialize the combobox, building the display column.
"""
gtk.ComboBox.__init__(self,model)
cell = gtk.CellRendererText()
self.pack_start(cell,True)
self.add_attribute(cell,'text',0)
def set(self,style_map,default):
"""
Set the options for the ComboBox, using the passed style
map as the data.
@param style_map: dictionary of style names and the corresponding
style sheet
@type style_map: dictionary
@param default: Default selection in the ComboBox
@type default: str
"""
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
self.style_map = style_map
start_index = 0
for index, key in enumerate(sorted(style_map)):
if key == "default":
self.store.append(row=[_('default')])
else:
self.store.append(row=[key])
if key == default:
start_index = index
self.set_active(start_index)
def get_value(self):
"""
Return the selected key (style sheet name).
@returns: Returns the name of the selected style sheet
@rtype: str
"""
active = self.get_active()
if active < 0:
return None
key = unicode(self.store[active][0])
if key == _('default'):
key = "default"
return (key,self.style_map[key])

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,327 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008-2009 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GTK modules
#
#-------------------------------------------------------------------------
import gtk
import gobject
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gui.pluginmanager import GuiPluginManager
from gen.plug.report._constants import CATEGORY_TEXT
from _docreportdialog import DocReportDialog
#-------------------------------------------------------------------------
#
# _TextFormatComboBox
#
#-------------------------------------------------------------------------
class _TextFormatComboBox(gtk.ComboBox):
"""
This class is a combo box that allows the selection of a docgen plugin
from all textdoc plugins.
"""
def __init__(self, active):
gtk.ComboBox.__init__(self)
pmgr = GuiPluginManager.get_instance()
self.__textdoc_plugins = []
for plugin in pmgr.get_docgen_plugins():
if plugin.get_text_support():
self.__textdoc_plugins.append(plugin)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell, True)
self.add_attribute(cell, 'text', 0)
index = 0
active_index = 0
for plugin in self.__textdoc_plugins:
name = plugin.get_name()
self.store.append(row=[name])
if plugin.get_extension() == active:
active_index = index
index += 1
self.set_active(active_index)
def get_active_plugin(self):
"""
Get the plugin represented by the currently active selection.
"""
return self.__textdoc_plugins[self.get_active()]
#-----------------------------------------------------------------------
#
# TextReportDialog
#
#-----------------------------------------------------------------------
class TextReportDialog(DocReportDialog):
"""
A class of ReportDialog customized for text based reports.
"""
def __init__(self, dbstate, uistate, options, name, translated_name):
"""
Initialize a dialog to request that the user select options
for a basic text report. See the ReportDialog class for more
information.
"""
self.format_menu = None
self.category = CATEGORY_TEXT
DocReportDialog.__init__(self, dbstate, uistate, options,
name, translated_name)
def make_doc_menu(self, active=None):
"""
Build a menu of document types that are appropriate for
this text report.
"""
self.format_menu = _TextFormatComboBox( active )
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008-2009 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GTK modules
#
#-------------------------------------------------------------------------
import gtk
import gobject
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gui.pluginmanager import GuiPluginManager
from gen.plug.report._constants import CATEGORY_TEXT
from _docreportdialog import DocReportDialog
#-------------------------------------------------------------------------
#
# _TextFormatComboBox
#
#-------------------------------------------------------------------------
class _TextFormatComboBox(gtk.ComboBox):
"""
This class is a combo box that allows the selection of a docgen plugin
from all textdoc plugins.
"""
def __init__(self, active):
gtk.ComboBox.__init__(self)
pmgr = GuiPluginManager.get_instance()
self.__textdoc_plugins = []
for plugin in pmgr.get_docgen_plugins():
if plugin.get_text_support():
self.__textdoc_plugins.append(plugin)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell, True)
self.add_attribute(cell, 'text', 0)
index = 0
active_index = 0
for plugin in self.__textdoc_plugins:
name = plugin.get_name()
self.store.append(row=[name])
if plugin.get_extension() == active:
active_index = index
index += 1
self.set_active(active_index)
def get_active_plugin(self):
"""
Get the plugin represented by the currently active selection.
"""
return self.__textdoc_plugins[self.get_active()]
#-----------------------------------------------------------------------
#
# TextReportDialog
#
#-----------------------------------------------------------------------
class TextReportDialog(DocReportDialog):
"""
A class of ReportDialog customized for text based reports.
"""
def __init__(self, dbstate, uistate, options, name, translated_name):
"""
Initialize a dialog to request that the user select options
for a basic text report. See the ReportDialog class for more
information.
"""
self.format_menu = None
self.category = CATEGORY_TEXT
DocReportDialog.__init__(self, dbstate, uistate, options,
name, translated_name)
def make_doc_menu(self, active=None):
"""
Build a menu of document types that are appropriate for
this text report.
"""
self.format_menu = _TextFormatComboBox( active )
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2001-2006 Donald N. Allingham
# Copyright (C) 2008-2009 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GTK modules
#
#-------------------------------------------------------------------------
import gtk
import gobject
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from gui.pluginmanager import GuiPluginManager
from gen.plug.report._constants import CATEGORY_TEXT
from _docreportdialog import DocReportDialog
#-------------------------------------------------------------------------
#
# _TextFormatComboBox
#
#-------------------------------------------------------------------------
class _TextFormatComboBox(gtk.ComboBox):
"""
This class is a combo box that allows the selection of a docgen plugin
from all textdoc plugins.
"""
def __init__(self, active):
gtk.ComboBox.__init__(self)
pmgr = GuiPluginManager.get_instance()
self.__textdoc_plugins = []
for plugin in pmgr.get_docgen_plugins():
if plugin.get_text_support():
self.__textdoc_plugins.append(plugin)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.set_model(self.store)
cell = gtk.CellRendererText()
self.pack_start(cell, True)
self.add_attribute(cell, 'text', 0)
index = 0
active_index = 0
for plugin in self.__textdoc_plugins:
name = plugin.get_name()
self.store.append(row=[name])
if plugin.get_extension() == active:
active_index = index
index += 1
self.set_active(active_index)
def get_active_plugin(self):
"""
Get the plugin represented by the currently active selection.
"""
return self.__textdoc_plugins[self.get_active()]
#-----------------------------------------------------------------------
#
# TextReportDialog
#
#-----------------------------------------------------------------------
class TextReportDialog(DocReportDialog):
"""
A class of ReportDialog customized for text based reports.
"""
def __init__(self, dbstate, uistate, options, name, translated_name):
"""
Initialize a dialog to request that the user select options
for a basic text report. See the ReportDialog class for more
information.
"""
self.format_menu = None
self.category = CATEGORY_TEXT
DocReportDialog.__init__(self, dbstate, uistate, options,
name, translated_name)
def make_doc_menu(self, active=None):
"""
Build a menu of document types that are appropriate for
this text report.
"""
self.format_menu = _TextFormatComboBox( active )

View File

@@ -0,0 +1,174 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _reportdialog import ReportDialog
from gen.plug.report import CATEGORY_WEB
#-------------------------------------------------------------------------
#
# WebReportDialog class
#
#-------------------------------------------------------------------------
class WebReportDialog(ReportDialog):
"""
The WebReportDialog base class. This is a base class for generating
dialogs for web page reports.
"""
def __init__(self, dbstate, uistate, option_class, name, trans_name):
"""Initialize a dialog"""
self.category = CATEGORY_WEB
ReportDialog.__init__(self, dbstate, uistate, option_class,
name, trans_name)
def setup_init(self):
pass
def setup_target_frame(self):
"""Target frame is not used."""
pass
def parse_target_frame(self):
"""Target frame is not used."""
return 1
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _reportdialog import ReportDialog
from gen.plug.report import CATEGORY_WEB
#-------------------------------------------------------------------------
#
# WebReportDialog class
#
#-------------------------------------------------------------------------
class WebReportDialog(ReportDialog):
"""
The WebReportDialog base class. This is a base class for generating
dialogs for web page reports.
"""
def __init__(self, dbstate, uistate, option_class, name, trans_name):
"""Initialize a dialog"""
self.category = CATEGORY_WEB
ReportDialog.__init__(self, dbstate, uistate, option_class,
name, trans_name)
def setup_init(self):
pass
def setup_target_frame(self):
"""Target frame is not used."""
pass
def parse_target_frame(self):
"""Target frame is not used."""
return 1
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
from _reportdialog import ReportDialog
from gen.plug.report import CATEGORY_WEB
#-------------------------------------------------------------------------
#
# WebReportDialog class
#
#-------------------------------------------------------------------------
class WebReportDialog(ReportDialog):
"""
The WebReportDialog base class. This is a base class for generating
dialogs for web page reports.
"""
def __init__(self, dbstate, uistate, option_class, name, trans_name):
"""Initialize a dialog"""
self.category = CATEGORY_WEB
ReportDialog.__init__(self, dbstate, uistate, option_class,
name, trans_name)
def setup_init(self):
pass
def setup_target_frame(self):
"""Target frame is not used."""
pass
def parse_target_frame(self):
"""Target frame is not used."""
return 1

933
src/gui/plug/tool.py Normal file
View File

@@ -0,0 +1,933 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2005-2007 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"ToolGeneration Framework"
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
import logging
log = logging.getLogger(".")
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
import Utils
from gen.display.name import displayer as name_displayer
import Errors
from gen.plug._options import (Options, OptionHandler, OptionList,
OptionListCollection)
from gen.plug import (TOOL_DEBUG, TOOL_ANAL, TOOL_DBPROC, TOOL_DBFIX,
TOOL_REVCTL, TOOL_UTILS)
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
tool_categories = {
TOOL_DEBUG : _("Debug"),
TOOL_ANAL : _("Analysis and Exploration"),
TOOL_DBPROC : _("Database Processing"),
TOOL_DBFIX : _("Database Repair"),
TOOL_REVCTL : _("Revision Control"),
TOOL_UTILS : _("Utilities"),
}
#-------------------------------------------------------------------------
#
# Tool
#
#-------------------------------------------------------------------------
class Tool(object):
"""
The Tool base class. This is a base class for generating
customized tools. It cannot be used as is, but it can be easily
sub-classed to create a functional tool.
"""
def __init__(self, dbstate, options_class, name):
from gui.plug import MenuToolOptions
self.db = dbstate.db
try:
if issubclass(options_class, MenuToolOptions):
# FIXME: pass in person_id
self.options = options_class(name, None, dbstate)
else: # must be some kind of class or we get a TypeError
self.options = options_class(name)
except TypeError:
self.options = options_class
self.options.load_previous_values()
def run_tool(self):
pass
class BatchTool(Tool):
"""
Same as Tool, except the warning is displayed about the potential
loss of undo history. Should be used for tools using batch transactions.
"""
def __init__(self, dbstate, options_class, name):
# TODO: should we replace this with a callback?
from QuestionDialog import QuestionDialog2
warn_dialog = QuestionDialog2(
_('Undo history warning'),
_('Proceeding with this tool will erase the undo history '
'for this session. In particular, you will not be able '
'to revert the changes made by this tool or any changes '
'made prior to it.\n\n'
'If you think you may want to revert running this tool, '
'please stop here and backup your database.'),
_('_Proceed with the tool'), _('_Stop'))
if not warn_dialog.run():
self.fail = True
return
Tool.__init__(self, dbstate, options_class, name)
self.fail = False
class ActivePersonTool(Tool):
"""
Same as Tool , except the existence of the active person is checked
and the tool is aborted if no active person exists. Should be used
for tools that depend on active person.
"""
def __init__(self, dbstate, uistate, options_class, name):
if not uistate.get_active('Person'):
# TODO: should we replace this with a callback?
from QuestionDialog import ErrorDialog
ErrorDialog(_('Active person has not been set'),
_('You must select an active person for this '
'tool to work properly.'))
self.fail = True
return
Tool.__init__(self, dbstate, options_class, name)
self.fail = False
#------------------------------------------------------------------------
#
# Command-line tool
#
#------------------------------------------------------------------------
class CommandLineTool(object):
"""
Provide a way to run tool from the command line.
"""
def __init__(self, database, name, category, option_class, options_str_dict,
noopt=False):
self.database = database
self.category = category
self.option_class = option_class(name)
self.option_class.load_previous_values()
self.show = options_str_dict.pop('show', None)
self.options_str_dict = options_str_dict
self.init_options(noopt)
self.parse_option_str()
self.show_options()
def init_options(self, noopt):
self.options_dict = {'id' : ''}
self.options_help = {'id' : ["=ID", "Gramps ID of a central person."], }
if noopt:
return
# Add tool-specific options
for key in self.option_class.handler.options_dict:
if key not in self.options_dict:
self.options_dict[key] = self.option_class.handler.options_dict[key]
# Add help for tool-specific options
for key in self.option_class.options_help:
if key not in self.options_help:
self.options_help[key] = self.option_class.options_help[key]
def parse_option_str(self):
for opt in self.options_str_dict:
if opt in self.options_dict:
converter = Utils.get_type_converter(self.options_dict[opt])
self.options_dict[opt] = converter(self.options_str_dict[opt])
self.option_class.handler.options_dict[opt] = self.options_dict[opt]
else:
print "Ignoring unknown option: %s" % opt
person_id = self.options_dict['id']
self.person = self.database.get_person_from_gramps_id(person_id)
id_list = []
for person in self.database.iter_people():
id_list.append("%s\t%s" % (
person.get_gramps_id(),
name_displayer.display(person)))
self.options_help['id'].append(id_list)
self.options_help['id'].append(False)
def show_options(self):
if not self.show:
return
elif self.show == 'all':
print " Available options:"
for key in self.options_dict:
print " %s" % key
print " Use 'show=option' to see description and acceptable values"
elif self.show in self.options_dict:
print ' %s%s\t%s' % (self.show,
self.options_help[self.show][0],
self.options_help[self.show][1])
print " Available values are:"
vals = self.options_help[self.show][2]
if isinstance(vals, (list, tuple)):
if self.options_help[self.show][3]:
for num in range(len(vals)):
print " %d\t%s" % (num, vals[num])
else:
for val in vals:
print " %s" % val
else:
print " %s" % self.options_help[self.show][2]
else:
self.show = None
#------------------------------------------------------------------------
#
# Generic task functions for tools
#
#------------------------------------------------------------------------
# Standard GUI tool generic task
def gui_tool(dbstate, uistate, tool_class, options_class, translated_name,
name, category, callback):
"""
tool - task starts the report. The plugin system requires that the
task be in the format of task that takes a database and a person as
its arguments.
"""
try:
tool_class(dbstate, uistate, options_class, name, callback)
except Errors.WindowActiveError:
pass
except:
log.error("Failed to start tool.", exc_info=True)
# Command-line generic task
def cli_tool(dbstate, name, category, tool_class, options_class, options_str_dict):
clt = CommandLineTool(dbstate.db, name, category,
options_class, options_str_dict)
# Exit here if show option was given
if clt.show:
return
# run tool
try:
tool_class(dbstate, None, options_class, name, None)
except:
log.error("Failed to start tool.", exc_info=True)
#-------------------------------------------------------------------------
#
# Class handling options for plugins
#
#-------------------------------------------------------------------------
class ToolOptionHandler(OptionHandler):
"""
Implements handling of the options for the plugins.
"""
def __init__(self, module_name, options_dict, person_id=None):
OptionHandler.__init__(self, module_name, options_dict, person_id)
def init_subclass(self):
self.collection_class = OptionListCollection
self.list_class = OptionList
self.filename = const.TOOL_OPTIONS
#------------------------------------------------------------------------
#
# Tool Options class
#
#------------------------------------------------------------------------
class ToolOptions(Options):
"""
Defines options and provides handling interface.
This is a base Options class for the tools. All tools, options
classes should derive from it.
"""
def __init__(self, name, person_id=None):
"""
Initialize the class, performing usual house-keeping tasks.
Subclasses MUST call this in their __init__() method.
"""
self.name = name
self.person_id = person_id
self.options_dict = {}
self.options_help = {}
self.handler = None
def load_previous_values(self):
self.handler = ToolOptionHandler(self.name, self.options_dict, self.person_id)
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2005-2007 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"ToolGeneration Framework"
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
import logging
log = logging.getLogger(".")
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
import Utils
from gen.display.name import displayer as name_displayer
import Errors
from gen.plug._options import (Options, OptionHandler, OptionList,
OptionListCollection)
from gen.plug import (TOOL_DEBUG, TOOL_ANAL, TOOL_DBPROC, TOOL_DBFIX,
TOOL_REVCTL, TOOL_UTILS)
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
tool_categories = {
TOOL_DEBUG : _("Debug"),
TOOL_ANAL : _("Analysis and Exploration"),
TOOL_DBPROC : _("Database Processing"),
TOOL_DBFIX : _("Database Repair"),
TOOL_REVCTL : _("Revision Control"),
TOOL_UTILS : _("Utilities"),
}
#-------------------------------------------------------------------------
#
# Tool
#
#-------------------------------------------------------------------------
class Tool(object):
"""
The Tool base class. This is a base class for generating
customized tools. It cannot be used as is, but it can be easily
sub-classed to create a functional tool.
"""
def __init__(self, dbstate, options_class, name):
from gui.plug import MenuToolOptions
self.db = dbstate.db
try:
if issubclass(options_class, MenuToolOptions):
# FIXME: pass in person_id
self.options = options_class(name, None, dbstate)
else: # must be some kind of class or we get a TypeError
self.options = options_class(name)
except TypeError:
self.options = options_class
self.options.load_previous_values()
def run_tool(self):
pass
class BatchTool(Tool):
"""
Same as Tool, except the warning is displayed about the potential
loss of undo history. Should be used for tools using batch transactions.
"""
def __init__(self, dbstate, options_class, name):
# TODO: should we replace this with a callback?
from QuestionDialog import QuestionDialog2
warn_dialog = QuestionDialog2(
_('Undo history warning'),
_('Proceeding with this tool will erase the undo history '
'for this session. In particular, you will not be able '
'to revert the changes made by this tool or any changes '
'made prior to it.\n\n'
'If you think you may want to revert running this tool, '
'please stop here and backup your database.'),
_('_Proceed with the tool'), _('_Stop'))
if not warn_dialog.run():
self.fail = True
return
Tool.__init__(self, dbstate, options_class, name)
self.fail = False
class ActivePersonTool(Tool):
"""
Same as Tool , except the existence of the active person is checked
and the tool is aborted if no active person exists. Should be used
for tools that depend on active person.
"""
def __init__(self, dbstate, uistate, options_class, name):
if not uistate.get_active('Person'):
# TODO: should we replace this with a callback?
from QuestionDialog import ErrorDialog
ErrorDialog(_('Active person has not been set'),
_('You must select an active person for this '
'tool to work properly.'))
self.fail = True
return
Tool.__init__(self, dbstate, options_class, name)
self.fail = False
#------------------------------------------------------------------------
#
# Command-line tool
#
#------------------------------------------------------------------------
class CommandLineTool(object):
"""
Provide a way to run tool from the command line.
"""
def __init__(self, database, name, category, option_class, options_str_dict,
noopt=False):
self.database = database
self.category = category
self.option_class = option_class(name)
self.option_class.load_previous_values()
self.show = options_str_dict.pop('show', None)
self.options_str_dict = options_str_dict
self.init_options(noopt)
self.parse_option_str()
self.show_options()
def init_options(self, noopt):
self.options_dict = {'id' : ''}
self.options_help = {'id' : ["=ID", "Gramps ID of a central person."], }
if noopt:
return
# Add tool-specific options
for key in self.option_class.handler.options_dict:
if key not in self.options_dict:
self.options_dict[key] = self.option_class.handler.options_dict[key]
# Add help for tool-specific options
for key in self.option_class.options_help:
if key not in self.options_help:
self.options_help[key] = self.option_class.options_help[key]
def parse_option_str(self):
for opt in self.options_str_dict:
if opt in self.options_dict:
converter = Utils.get_type_converter(self.options_dict[opt])
self.options_dict[opt] = converter(self.options_str_dict[opt])
self.option_class.handler.options_dict[opt] = self.options_dict[opt]
else:
print "Ignoring unknown option: %s" % opt
person_id = self.options_dict['id']
self.person = self.database.get_person_from_gramps_id(person_id)
id_list = []
for person in self.database.iter_people():
id_list.append("%s\t%s" % (
person.get_gramps_id(),
name_displayer.display(person)))
self.options_help['id'].append(id_list)
self.options_help['id'].append(False)
def show_options(self):
if not self.show:
return
elif self.show == 'all':
print " Available options:"
for key in self.options_dict:
print " %s" % key
print " Use 'show=option' to see description and acceptable values"
elif self.show in self.options_dict:
print ' %s%s\t%s' % (self.show,
self.options_help[self.show][0],
self.options_help[self.show][1])
print " Available values are:"
vals = self.options_help[self.show][2]
if isinstance(vals, (list, tuple)):
if self.options_help[self.show][3]:
for num in range(len(vals)):
print " %d\t%s" % (num, vals[num])
else:
for val in vals:
print " %s" % val
else:
print " %s" % self.options_help[self.show][2]
else:
self.show = None
#------------------------------------------------------------------------
#
# Generic task functions for tools
#
#------------------------------------------------------------------------
# Standard GUI tool generic task
def gui_tool(dbstate, uistate, tool_class, options_class, translated_name,
name, category, callback):
"""
tool - task starts the report. The plugin system requires that the
task be in the format of task that takes a database and a person as
its arguments.
"""
try:
tool_class(dbstate, uistate, options_class, name, callback)
except Errors.WindowActiveError:
pass
except:
log.error("Failed to start tool.", exc_info=True)
# Command-line generic task
def cli_tool(dbstate, name, category, tool_class, options_class, options_str_dict):
clt = CommandLineTool(dbstate.db, name, category,
options_class, options_str_dict)
# Exit here if show option was given
if clt.show:
return
# run tool
try:
tool_class(dbstate, None, options_class, name, None)
except:
log.error("Failed to start tool.", exc_info=True)
#-------------------------------------------------------------------------
#
# Class handling options for plugins
#
#-------------------------------------------------------------------------
class ToolOptionHandler(OptionHandler):
"""
Implements handling of the options for the plugins.
"""
def __init__(self, module_name, options_dict, person_id=None):
OptionHandler.__init__(self, module_name, options_dict, person_id)
def init_subclass(self):
self.collection_class = OptionListCollection
self.list_class = OptionList
self.filename = const.TOOL_OPTIONS
#------------------------------------------------------------------------
#
# Tool Options class
#
#------------------------------------------------------------------------
class ToolOptions(Options):
"""
Defines options and provides handling interface.
This is a base Options class for the tools. All tools, options
classes should derive from it.
"""
def __init__(self, name, person_id=None):
"""
Initialize the class, performing usual house-keeping tasks.
Subclasses MUST call this in their __init__() method.
"""
self.name = name
self.person_id = person_id
self.options_dict = {}
self.options_help = {}
self.handler = None
def load_previous_values(self):
self.handler = ToolOptionHandler(self.name, self.options_dict, self.person_id)
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2005-2007 Donald N. Allingham
# Copyright (C) 2010 Jakim Friant
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"ToolGeneration Framework"
#-------------------------------------------------------------------------
#
# Python modules
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
import logging
log = logging.getLogger(".")
#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------
import const
import Utils
from gen.display.name import displayer as name_displayer
import Errors
from gen.plug._options import (Options, OptionHandler, OptionList,
OptionListCollection)
from gen.plug import (TOOL_DEBUG, TOOL_ANAL, TOOL_DBPROC, TOOL_DBFIX,
TOOL_REVCTL, TOOL_UTILS)
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
tool_categories = {
TOOL_DEBUG : _("Debug"),
TOOL_ANAL : _("Analysis and Exploration"),
TOOL_DBPROC : _("Database Processing"),
TOOL_DBFIX : _("Database Repair"),
TOOL_REVCTL : _("Revision Control"),
TOOL_UTILS : _("Utilities"),
}
#-------------------------------------------------------------------------
#
# Tool
#
#-------------------------------------------------------------------------
class Tool(object):
"""
The Tool base class. This is a base class for generating
customized tools. It cannot be used as is, but it can be easily
sub-classed to create a functional tool.
"""
def __init__(self, dbstate, options_class, name):
from gui.plug import MenuToolOptions
self.db = dbstate.db
try:
if issubclass(options_class, MenuToolOptions):
# FIXME: pass in person_id
self.options = options_class(name, None, dbstate)
else: # must be some kind of class or we get a TypeError
self.options = options_class(name)
except TypeError:
self.options = options_class
self.options.load_previous_values()
def run_tool(self):
pass
class BatchTool(Tool):
"""
Same as Tool, except the warning is displayed about the potential
loss of undo history. Should be used for tools using batch transactions.
"""
def __init__(self, dbstate, options_class, name):
# TODO: should we replace this with a callback?
from QuestionDialog import QuestionDialog2
warn_dialog = QuestionDialog2(
_('Undo history warning'),
_('Proceeding with this tool will erase the undo history '
'for this session. In particular, you will not be able '
'to revert the changes made by this tool or any changes '
'made prior to it.\n\n'
'If you think you may want to revert running this tool, '
'please stop here and backup your database.'),
_('_Proceed with the tool'), _('_Stop'))
if not warn_dialog.run():
self.fail = True
return
Tool.__init__(self, dbstate, options_class, name)
self.fail = False
class ActivePersonTool(Tool):
"""
Same as Tool , except the existence of the active person is checked
and the tool is aborted if no active person exists. Should be used
for tools that depend on active person.
"""
def __init__(self, dbstate, uistate, options_class, name):
if not uistate.get_active('Person'):
# TODO: should we replace this with a callback?
from QuestionDialog import ErrorDialog
ErrorDialog(_('Active person has not been set'),
_('You must select an active person for this '
'tool to work properly.'))
self.fail = True
return
Tool.__init__(self, dbstate, options_class, name)
self.fail = False
#------------------------------------------------------------------------
#
# Command-line tool
#
#------------------------------------------------------------------------
class CommandLineTool(object):
"""
Provide a way to run tool from the command line.
"""
def __init__(self, database, name, category, option_class, options_str_dict,
noopt=False):
self.database = database
self.category = category
self.option_class = option_class(name)
self.option_class.load_previous_values()
self.show = options_str_dict.pop('show', None)
self.options_str_dict = options_str_dict
self.init_options(noopt)
self.parse_option_str()
self.show_options()
def init_options(self, noopt):
self.options_dict = {'id' : ''}
self.options_help = {'id' : ["=ID", "Gramps ID of a central person."], }
if noopt:
return
# Add tool-specific options
for key in self.option_class.handler.options_dict:
if key not in self.options_dict:
self.options_dict[key] = self.option_class.handler.options_dict[key]
# Add help for tool-specific options
for key in self.option_class.options_help:
if key not in self.options_help:
self.options_help[key] = self.option_class.options_help[key]
def parse_option_str(self):
for opt in self.options_str_dict:
if opt in self.options_dict:
converter = Utils.get_type_converter(self.options_dict[opt])
self.options_dict[opt] = converter(self.options_str_dict[opt])
self.option_class.handler.options_dict[opt] = self.options_dict[opt]
else:
print "Ignoring unknown option: %s" % opt
person_id = self.options_dict['id']
self.person = self.database.get_person_from_gramps_id(person_id)
id_list = []
for person in self.database.iter_people():
id_list.append("%s\t%s" % (
person.get_gramps_id(),
name_displayer.display(person)))
self.options_help['id'].append(id_list)
self.options_help['id'].append(False)
def show_options(self):
if not self.show:
return
elif self.show == 'all':
print " Available options:"
for key in self.options_dict:
print " %s" % key
print " Use 'show=option' to see description and acceptable values"
elif self.show in self.options_dict:
print ' %s%s\t%s' % (self.show,
self.options_help[self.show][0],
self.options_help[self.show][1])
print " Available values are:"
vals = self.options_help[self.show][2]
if isinstance(vals, (list, tuple)):
if self.options_help[self.show][3]:
for num in range(len(vals)):
print " %d\t%s" % (num, vals[num])
else:
for val in vals:
print " %s" % val
else:
print " %s" % self.options_help[self.show][2]
else:
self.show = None
#------------------------------------------------------------------------
#
# Generic task functions for tools
#
#------------------------------------------------------------------------
# Standard GUI tool generic task
def gui_tool(dbstate, uistate, tool_class, options_class, translated_name,
name, category, callback):
"""
tool - task starts the report. The plugin system requires that the
task be in the format of task that takes a database and a person as
its arguments.
"""
try:
tool_class(dbstate, uistate, options_class, name, callback)
except Errors.WindowActiveError:
pass
except:
log.error("Failed to start tool.", exc_info=True)
# Command-line generic task
def cli_tool(dbstate, name, category, tool_class, options_class, options_str_dict):
clt = CommandLineTool(dbstate.db, name, category,
options_class, options_str_dict)
# Exit here if show option was given
if clt.show:
return
# run tool
try:
tool_class(dbstate, None, options_class, name, None)
except:
log.error("Failed to start tool.", exc_info=True)
#-------------------------------------------------------------------------
#
# Class handling options for plugins
#
#-------------------------------------------------------------------------
class ToolOptionHandler(OptionHandler):
"""
Implements handling of the options for the plugins.
"""
def __init__(self, module_name, options_dict, person_id=None):
OptionHandler.__init__(self, module_name, options_dict, person_id)
def init_subclass(self):
self.collection_class = OptionListCollection
self.list_class = OptionList
self.filename = const.TOOL_OPTIONS
#------------------------------------------------------------------------
#
# Tool Options class
#
#------------------------------------------------------------------------
class ToolOptions(Options):
"""
Defines options and provides handling interface.
This is a base Options class for the tools. All tools, options
classes should derive from it.
"""
def __init__(self, name, person_id=None):
"""
Initialize the class, performing usual house-keeping tasks.
Subclasses MUST call this in their __init__() method.
"""
self.name = name
self.person_id = person_id
self.options_dict = {}
self.options_help = {}
self.handler = None
def load_previous_values(self):
self.handler = ToolOptionHandler(self.name, self.options_dict, self.person_id)

View File

@@ -5,6 +5,7 @@
# Copyright (C) 2008 Brian G. Matherly
# Copyright (C) 2009 Benny Malengier
# Copyright (C) 2010 Nick Hall
# Copyright (C) 2010 Jakim Friant
#
# 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
@@ -58,13 +59,15 @@ import gtk
#
#-------------------------------------------------------------------------
from cli.grampscli import CLIManager
from PluginUtils import Tool, PluginWindows, \
ReportPluginDialog, ToolPluginDialog, gui_tool
from gen.plug import REPORT
from gui.pluginmanager import GuiPluginManager
from gui.plug import tool
from gen.plug import (START, END)
from gen.plug import REPORT
from gen.plug.report._constants import standalone_categories
from gui.plug import PluginWindows, \
ReportPluginDialog, ToolPluginDialog
from gui.plug.report import report
from gui.pluginmanager import GuiPluginManager
import Relationship
import ReportBase
import DisplayState
import const
import config
@@ -1144,7 +1147,7 @@ class ViewManager(CLIManager):
self.uistate.uimanager.remove_ui(self.tool_menu_ui_id)
self.toolactions = gtk.ActionGroup('ToolWindow')
(uidef, actions) = self.build_plugin_menu(
'ToolsMenu', tool_menu_list, Tool.tool_categories,
'ToolsMenu', tool_menu_list, tool.tool_categories,
make_plugin_callback)
self.toolactions.add_actions(actions)
self.tool_menu_ui_id = self.uistate.uimanager.add_ui_from_string(uidef)
@@ -1160,7 +1163,7 @@ class ViewManager(CLIManager):
self.uistate.uimanager.remove_ui(self.report_menu_ui_id)
self.reportactions = gtk.ActionGroup('ReportWindow')
(uidef, actions) = self.build_plugin_menu(
'ReportsMenu', report_menu_list, ReportBase.standalone_categories,
'ReportsMenu', report_menu_list, standalone_categories,
make_plugin_callback)
self.reportactions.add_actions(actions)
self.report_menu_ui_id = self.uistate.uimanager.add_ui_from_string(uidef)
@@ -1302,17 +1305,17 @@ def run_plugin(pdata, dbstate, uistate):
return
if pdata.ptype == REPORT:
ReportBase.report(dbstate, uistate, uistate.get_active('Person'),
report(dbstate, uistate, uistate.get_active('Person'),
getattr(mod, pdata.reportclass),
getattr(mod, pdata.optionclass),
pdata.name, pdata.id,
pdata.category, pdata.require_active)
else:
gui_tool(dbstate, uistate,
getattr(mod, pdata.toolclass),
getattr(mod, pdata.optionclass),
pdata.name, pdata.id, pdata.category,
dbstate.db.request_rebuild)
tool.gui_tool(dbstate, uistate,
getattr(mod, pdata.toolclass),
getattr(mod, pdata.optionclass),
pdata.name, pdata.id, pdata.category,
dbstate.db.request_rebuild)
def make_plugin_callback(pdata, dbstate, uistate):
"""