gramps/src/gen/plug/_gramplet.py

356 lines
11 KiB
Python
Raw Normal View History

2009-10-26 04:02:34 +05:30
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2009 Douglas S. Blank <doug.blank@gmail.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# 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$
import types
from gettext import gettext as _
class Gramplet(object):
"""
Base class for non-graphical gramplet code.
"""
def __init__(self, gui):
"""
Internal constructor for non-graphical gramplets.
"""
self._idle_id = 0
self._pause = False
self._generator = None
self._need_to_update = False
self.option_dict = {}
self._signal = {}
2009-10-26 04:02:34 +05:30
self.option_order = []
# links to each other:
self.gui = gui # plugin gramplet has link to gui
gui.pui = self # gui has link to plugin ui
self.dbstate = gui.dbstate
self.uistate = gui.uistate
self.init()
self.on_load()
self.build_options()
self.connect(self.dbstate, "database-changed", self._db_changed)
self.connect(self.dbstate, "active-changed", self._active_changed)
self.connect(self.gui.textview, "button-press-event",
self.gui.on_button_press)
self.connect(self.gui.textview, "motion-notify-event",
self.gui.on_motion)
2009-10-26 04:02:34 +05:30
if self.dbstate.active: # already changed
self._db_changed(self.dbstate.db)
self._active_changed(self.dbstate.active.handle)
self.post_init()
2009-10-26 04:02:34 +05:30
def init(self): # once, constructor
"""
External constructor for developers to put their initialization
code. Designed to be overridden.
"""
pass
def post_init(self):
pass
2009-10-26 04:02:34 +05:30
def build_options(self):
"""
External constructor for developers to put code for building
options.
"""
pass
def main(self): # return false finishes
"""
The main place for the gramplet's code. This is a generator.
Generator which will be run in the background, through update().
"""
yield False
def on_load(self):
"""
Gramplets should override this to take care of loading previously
their special data.
"""
pass
def on_save(self):
"""
Gramplets should override this to take care of saving their
special data.
"""
return
def active_changed(self, handle):
"""
Developers should put their code that occurs when the active
person is changed.
"""
pass
def _active_changed(self, handle):
"""
Private code that updates the GUI when active_person is changed.
"""
self.uistate.push_message(self.gui.dbstate,
_("Gramplet %s is running") % self.gui.title)
self.active_changed(handle)
def db_changed(self):
"""
Method executed when the database is changed.
"""
pass
def link(self, text, link_type, data, size=None, tooltip=None):
"""
Creates a clickable link in the textview area.
"""
self.gui.link(text, link_type, data, size, tooltip)
# Shortcuts to the gui functionality:
def set_tooltip(self, tip):
"""
Sets the tooltip for this gramplet.
"""
self.gui.tooltip = tip
def get_text(self):
"""
Returns the current text of the textview.
"""
return self.gui.get_text()
def insert_text(self, text):
"""
Insert the given text in the textview at the cursor.
"""
self.gui.insert_text(text)
def render_text(self, text):
"""
Render the given text, given that set_use_markup is on.
"""
self.gui.render_text(text)
def clear_text(self):
"""
Clear all of the text from the textview.
"""
self.gui.clear_text()
def set_text(self, text, scroll_to='start'):
"""
Clear and set the text to the given text. Additionally, move the
cursor to the position given. Positions are:
'start': start of textview
'end': end of textview
'begin': begin of line, before setting the text.
"""
self.gui.set_text(text, scroll_to)
def append_text(self, text, scroll_to="end"):
"""
Append the text to the textview. Additionally, move the
cursor to the position given. Positions are:
'start': start of textview
'end': end of textview
'begin': begin of line, before setting the text.
"""
self.gui.append_text(text, scroll_to)
def set_use_markup(self, value):
"""
Allows the use of render_text to show markup.
"""
self.gui.set_use_markup(value)
def set_wrap(self, value):
"""
Set the textview to wrap or not.
"""
import gtk
self.gui.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC,
gtk.POLICY_AUTOMATIC)
# gtk.WRAP_NONE, gtk.WRAP_CHAR, gtk.WRAP_WORD or gtk.WRAP_WORD_CHAR.
if value in [True, 1]:
self.gui.textview.set_wrap_mode(gtk.WRAP_WORD)
elif value in [False, 0, None]:
self.gui.textview.set_wrap_mode(gtk.WRAP_NONE)
elif value in ["char"]:
self.gui.textview.set_wrap_mode(gtk.WRAP_CHAR)
elif value in ["word char"]:
self.gui.textview.set_wrap_mode(gtk.WRAP_WORD_CHAR)
else:
raise Exception("Unknown wrap mode: '%s': use 0,1,'char' or 'word char')" % value)
def no_wrap(self):
"""
The view in gramplet should not wrap. DEPRICATED: use set_wrap instead.
"""
self.set_wrap(False)
# Other functions of the gramplet:
def load_data_to_text(self, pos=0):
"""
Load information from the data portion of the saved
Gramplet to the textview.
"""
if len(self.gui.data) >= pos + 1:
text = self.gui.data[pos]
text = text.replace("\\n", chr(10))
self.set_text(text, 'end')
def save_text_to_data(self):
"""
Save the textview to the data portion of a saved gramplet.
"""
text = self.get_text()
text = text.replace(chr(10), "\\n")
self.gui.data.append(text)
def update(self, *args):
"""
The main interface for running the main method.
"""
import gobject
if (self.gui.state in ["closed", "minimized"] and
not self.gui.force_update): return
if self._idle_id != 0:
self.interrupt()
self._generator = self.main()
self._pause = False
self._idle_id = gobject.idle_add(self._updater,
priority=gobject.PRIORITY_LOW - 10)
def _updater(self):
"""
Runs the generator.
"""
if not isinstance(self._generator, types.GeneratorType):
self._idle_id = 0
return False
try:
retval = self._generator.next()
if not retval:
self._idle_id = 0
if self._pause:
return False
return retval
except StopIteration:
self._idle_id = 0
return False
except Exception, e:
import traceback
2009-10-26 04:02:34 +05:30
print "Gramplet gave an error"
traceback.print_exc()
print "Continuing after gramplet error..."
self._idle_id = 0
return False
def pause(self, *args):
"""
Pause the main method.
"""
self._pause = True
def resume(self, *args):
"""
Resume the main method that has previously paused.
"""
import gobject
self._pause = False
self._idle_id = gobject.idle_add(self._updater,
priority=gobject.PRIORITY_LOW - 10)
def update_all(self, *args):
"""
Force the main loop to run right now (as opposed to running in background).
"""
self._generator = self.main()
if isinstance(self._generator, types.GeneratorType):
for step in self._generator:
pass
def interrupt(self, *args):
"""
Force the generator to stop running.
"""
import gobject
self._pause = True
if self._idle_id == 0:
gobject.source_remove(self._idle_id)
self._idle_id = 0
def _db_changed(self, db):
"""
Internal method for handling items that should happen when the
database changes. This will push a message to the GUI status bar.
"""
self.uistate.push_message(self.dbstate,
_("Gramplet %s is running") % self.gui.title)
self.dbstate.db = db
self.gui.dbstate.db = db
self.db_changed()
self.update()
def get_option_widget(self, label):
"""
Retrieve an option's widget by its label text.
"""
return self.option_dict[label][0]
def get_option(self, label):
"""
Retireve an option by its label text.
"""
return self.option_dict[label][1]
def add_option(self, option):
"""
Add an option to the GUI gramplet.
"""
from PluginUtils import make_gui_option
#tooltips, dbstate, uistate, track
widget, label = make_gui_option(
option, self.dbstate, self.uistate,None)
self.option_dict.update({option.get_label(): (widget, option)})
self.option_order.append(option.get_label())
def save_update_options(self, obj):
"""
Save a gramplet's options to file.
"""
self.save_options()
self.update()
def save_options(self):
pass
def connect(self, signal_obj, signal, method):
id = signal_obj.connect(signal, method)
self._signal[signal] = (id, signal_obj)
def disconnect(self, signal):
if signal in self._signal:
(id, signal_obj) = self._signal[signal]
signal_obj.disconnect(id)
else:
raise AttributeError("unknown signal: '%s'" % signal)