2007-12-24 20:26:15 +05:30
|
|
|
#
|
|
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
|
|
#
|
|
|
|
# Copyright (C) 2000-2007 Donald N. Allingham
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#
|
|
|
|
|
|
|
|
# $Id: _MyGrampsView.py $
|
|
|
|
|
|
|
|
"""
|
|
|
|
MyGrampsView interface
|
|
|
|
"""
|
|
|
|
|
|
|
|
__author__ = "Doug Blank"
|
|
|
|
__revision__ = "$Revision: $"
|
|
|
|
|
|
|
|
import gtk
|
|
|
|
import gobject
|
|
|
|
import traceback
|
|
|
|
import time
|
2007-12-29 23:05:07 +05:30
|
|
|
import types
|
2007-12-25 10:04:42 +05:30
|
|
|
import pango
|
2007-12-26 13:56:33 +05:30
|
|
|
import os
|
2007-12-28 11:53:50 +05:30
|
|
|
from gettext import gettext as _
|
2007-12-25 10:04:42 +05:30
|
|
|
|
|
|
|
import Errors
|
|
|
|
import const
|
|
|
|
import PageView
|
2007-12-25 23:21:37 +05:30
|
|
|
import ManagedWindow
|
2007-12-26 13:56:33 +05:30
|
|
|
import ConfigParser
|
|
|
|
import Utils
|
2007-12-30 09:16:39 +05:30
|
|
|
from QuickReports import run_quick_report_by_name
|
2007-12-24 20:26:15 +05:30
|
|
|
|
2007-12-27 04:44:13 +05:30
|
|
|
AVAILABLE_GADGETS = {}
|
2007-12-26 13:56:33 +05:30
|
|
|
GADGET_FILENAME = os.path.join(const.HOME_DIR,"gadgets.ini")
|
|
|
|
NL = "\n"
|
2007-12-24 20:26:15 +05:30
|
|
|
|
2007-12-26 22:49:26 +05:30
|
|
|
debug = False
|
2007-12-24 20:26:15 +05:30
|
|
|
|
|
|
|
def register_gadget(data_dict):
|
|
|
|
global AVAILABLE_GADGETS
|
2007-12-27 04:44:13 +05:30
|
|
|
base_opts = {"name":"Unnamed Gadget",
|
|
|
|
"state":"maximized",
|
2007-12-27 20:36:28 +05:30
|
|
|
"column": -1, "row": -1,
|
|
|
|
"data": []}
|
2007-12-26 13:56:33 +05:30
|
|
|
base_opts.update(data_dict)
|
2007-12-27 04:44:13 +05:30
|
|
|
AVAILABLE_GADGETS[base_opts["name"]] = base_opts
|
2007-12-24 20:26:15 +05:30
|
|
|
|
|
|
|
def register(**data):
|
|
|
|
if "type" in data:
|
|
|
|
if data["type"].lower() == "gadget":
|
|
|
|
register_gadget(data)
|
2007-12-27 04:44:13 +05:30
|
|
|
else:
|
|
|
|
print ("Unknown plugin type: '%s'" % data["type"])
|
|
|
|
else:
|
|
|
|
print ("Plugin did not define type.")
|
2007-12-24 20:26:15 +05:30
|
|
|
|
|
|
|
def get_gadget_opts(name, opts):
|
2007-12-27 04:44:13 +05:30
|
|
|
if name in AVAILABLE_GADGETS:
|
|
|
|
data = AVAILABLE_GADGETS[name]
|
|
|
|
my_data = data.copy()
|
|
|
|
my_data.update(opts)
|
|
|
|
return my_data
|
|
|
|
else:
|
|
|
|
print ("Unknown gadget name: '%s'" % name)
|
|
|
|
return {}
|
2007-12-24 20:26:15 +05:30
|
|
|
|
2007-12-26 13:56:33 +05:30
|
|
|
def get_gadget_options_by_name(name):
|
|
|
|
if debug: print "name:", name
|
2007-12-27 04:44:13 +05:30
|
|
|
if name in AVAILABLE_GADGETS:
|
|
|
|
return AVAILABLE_GADGETS[name].copy()
|
|
|
|
else:
|
|
|
|
print ("Unknown gadget name: '%s'" % name)
|
|
|
|
return None
|
2007-12-26 13:56:33 +05:30
|
|
|
|
2007-12-25 05:06:11 +05:30
|
|
|
def make_requested_gadget(viewpage, name, opts, dbstate, uistate):
|
2007-12-27 04:44:13 +05:30
|
|
|
if name in AVAILABLE_GADGETS:
|
|
|
|
gui = GuiGadget(viewpage, dbstate, uistate, **opts)
|
|
|
|
if opts.get("content", None):
|
|
|
|
opts["content"](gui)
|
|
|
|
# now that we have user code, set the tooltips
|
|
|
|
msg = None
|
|
|
|
if gui.pui:
|
|
|
|
msg = gui.pui.tooltip
|
|
|
|
if msg == None:
|
|
|
|
msg = _("Drag Properties Button to move and click it for setup")
|
|
|
|
if msg:
|
|
|
|
gui.tooltips = gtk.Tooltips()
|
2007-12-31 10:10:21 +05:30
|
|
|
gui.tooltips.set_tip(gui.scrolledwindow, msg)
|
2007-12-27 04:44:13 +05:30
|
|
|
return gui
|
2007-12-24 20:26:15 +05:30
|
|
|
return None
|
|
|
|
|
2007-12-25 10:04:42 +05:30
|
|
|
class LinkTag(gtk.TextTag):
|
|
|
|
lid = 0
|
|
|
|
def __init__(self, buffer):
|
|
|
|
LinkTag.lid += 1
|
|
|
|
gtk.TextTag.__init__(self, str(LinkTag.lid))
|
|
|
|
tag_table = buffer.get_tag_table()
|
|
|
|
self.set_property('foreground', "#0000ff")
|
2007-12-28 11:53:50 +05:30
|
|
|
#self.set_property('underline', pango.UNDERLINE_SINGLE)
|
2007-12-25 10:04:42 +05:30
|
|
|
tag_table.add(self)
|
|
|
|
|
2007-12-25 23:21:37 +05:30
|
|
|
class GadgetWindow(ManagedWindow.ManagedWindow):
|
|
|
|
def __init__(self, gadget):
|
|
|
|
self.title = gadget.title + " Gadget"
|
|
|
|
self.gadget = gadget
|
|
|
|
ManagedWindow.ManagedWindow.__init__(self, gadget.uistate, [], gadget)
|
|
|
|
self.set_window(gtk.Dialog("",gadget.uistate.window,
|
|
|
|
gtk.DIALOG_DESTROY_WITH_PARENT,
|
|
|
|
(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)),
|
|
|
|
None, self.title)
|
|
|
|
self.window.set_size_request(400,300)
|
|
|
|
self.window.connect('response', self.close)
|
|
|
|
self.gadget.mainframe.reparent(self.window.vbox)
|
2007-12-26 13:56:33 +05:30
|
|
|
self.window.show()
|
2007-12-25 23:21:37 +05:30
|
|
|
|
|
|
|
def build_menu_names(self, obj):
|
|
|
|
return (self.title, 'Gadget')
|
|
|
|
|
|
|
|
def get_title(self):
|
|
|
|
return self.title
|
|
|
|
|
|
|
|
def close(self, *args):
|
2007-12-26 13:56:33 +05:30
|
|
|
"""
|
|
|
|
Closes the detached GadgetWindow.
|
|
|
|
"""
|
|
|
|
self.gadget.gvclose.show()
|
|
|
|
self.gadget.gvstate.show()
|
|
|
|
self.gadget.gvproperties.show()
|
2007-12-28 11:53:50 +05:30
|
|
|
self.gadget.viewpage.detached_gadgets.remove(self.gadget)
|
2007-12-25 23:21:37 +05:30
|
|
|
self.gadget.state = "maximized"
|
|
|
|
self.gadget.mainframe.reparent(self.gadget.parent)
|
2007-12-29 23:26:23 +05:30
|
|
|
expand,fill,padding,pack = self.gadget.parent.query_child_packing(self.gadget.mainframe)
|
|
|
|
self.gadget.parent.set_child_packing(self.gadget.mainframe,self.gadget.expand,fill,padding,pack)
|
2007-12-25 23:21:37 +05:30
|
|
|
ManagedWindow.ManagedWindow.close(self, *args)
|
|
|
|
|
|
|
|
#------------------------------------------------------------------------
|
|
|
|
|
2007-12-24 20:26:15 +05:30
|
|
|
class Gadget(object):
|
|
|
|
def __init__(self, gui):
|
|
|
|
self._idle_id = 0
|
|
|
|
self._generator = None
|
|
|
|
self._need_to_update = False
|
2007-12-25 10:04:42 +05:30
|
|
|
self._tags = []
|
2007-12-27 04:44:13 +05:30
|
|
|
self.tooltip = None
|
2007-12-25 10:04:42 +05:30
|
|
|
self.link_cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
|
|
|
|
self.standard_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM)
|
2007-12-26 22:18:51 +05:30
|
|
|
# links to each other:
|
|
|
|
self.gui = gui # plugin gadget has link to gui
|
|
|
|
gui.pui = self # gui has link to plugin ui
|
2007-12-24 20:26:15 +05:30
|
|
|
self.dbstate = gui.dbstate
|
|
|
|
self.init()
|
2007-12-26 22:18:51 +05:30
|
|
|
self.on_load()
|
2007-12-24 20:26:15 +05:30
|
|
|
self.dbstate.connect('database-changed', self._db_changed)
|
|
|
|
self.dbstate.connect('active-changed', self.active_changed)
|
2007-12-25 10:04:42 +05:30
|
|
|
self.gui.textview.connect('button-press-event',
|
|
|
|
self.on_button_press)
|
|
|
|
self.gui.textview.connect('motion-notify-event',
|
|
|
|
self.on_motion)
|
2007-12-28 11:53:50 +05:30
|
|
|
if self.dbstate.active: # already changed
|
|
|
|
self._db_changed(self.dbstate.db)
|
|
|
|
self.active_changed(self.dbstate.active.handle)
|
2007-12-24 20:26:15 +05:30
|
|
|
|
2007-12-27 04:44:13 +05:30
|
|
|
def init(self): # once, constructor
|
|
|
|
pass
|
|
|
|
|
2007-12-29 17:19:15 +05:30
|
|
|
def main(self): # return false finishes
|
2007-12-27 04:44:13 +05:30
|
|
|
"""
|
|
|
|
Generator which will be run in the background.
|
|
|
|
"""
|
|
|
|
if debug: print "%s dummy" % self.gui.title
|
|
|
|
yield False
|
|
|
|
|
2007-12-26 22:18:51 +05:30
|
|
|
def on_load(self):
|
|
|
|
"""
|
|
|
|
Gadgets should override this to take care of loading previously
|
|
|
|
their special data.
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def on_save(self):
|
|
|
|
"""
|
|
|
|
Gadgets should override this to take care of saving their
|
|
|
|
special data.
|
|
|
|
"""
|
2007-12-26 22:53:02 +05:30
|
|
|
if debug: print ("on_save: '%s'" % self.gui.title)
|
2007-12-26 22:48:43 +05:30
|
|
|
return
|
2007-12-26 22:18:51 +05:30
|
|
|
|
2007-12-24 20:26:15 +05:30
|
|
|
def active_changed(self, handle):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def db_changed(self):
|
|
|
|
if debug: print "%s is connecting" % self.gui.title
|
|
|
|
pass
|
|
|
|
|
2007-12-30 06:54:33 +05:30
|
|
|
def link(self, text, link_type, data):
|
2007-12-27 04:44:13 +05:30
|
|
|
buffer = self.gui.buffer
|
|
|
|
iter = buffer.get_end_iter()
|
|
|
|
offset = buffer.get_char_count()
|
|
|
|
self.append_text(text)
|
|
|
|
start = buffer.get_iter_at_offset(offset)
|
|
|
|
end = buffer.get_end_iter()
|
2007-12-30 06:54:33 +05:30
|
|
|
self._tags.append((LinkTag(buffer), link_type, data))
|
2007-12-27 04:44:13 +05:30
|
|
|
buffer.apply_tag(self._tags[-1][0], start, end)
|
2007-12-24 20:26:15 +05:30
|
|
|
|
2007-12-27 20:36:28 +05:30
|
|
|
def get_text(self):
|
|
|
|
start = self.gui.buffer.get_start_iter()
|
|
|
|
end = self.gui.buffer.get_end_iter()
|
|
|
|
return self.gui.buffer.get_text(start, end)
|
|
|
|
|
2007-12-27 04:44:13 +05:30
|
|
|
def insert_text(self, text):
|
|
|
|
self.gui.buffer.insert_at_cursor(text)
|
|
|
|
|
|
|
|
def clear_text(self):
|
|
|
|
self.gui.buffer.set_text('')
|
|
|
|
|
2007-12-27 20:36:28 +05:30
|
|
|
def set_text(self, text, scroll_to='start'):
|
|
|
|
self.gui.buffer.set_text('')
|
|
|
|
self.append_text(text, scroll_to)
|
2007-12-27 04:44:13 +05:30
|
|
|
|
|
|
|
def append_text(self, text, scroll_to="end"):
|
|
|
|
enditer = self.gui.buffer.get_end_iter()
|
|
|
|
start = self.gui.buffer.create_mark(None, enditer, True)
|
|
|
|
self.gui.buffer.insert(enditer, text)
|
|
|
|
if scroll_to == "end":
|
|
|
|
enditer = self.gui.buffer.get_end_iter()
|
|
|
|
end = self.gui.buffer.create_mark(None, enditer, True)
|
|
|
|
self.gui.textview.scroll_to_mark(end, 0.0, True, 0, 0)
|
|
|
|
else:
|
|
|
|
self.gui.textview.scroll_to_mark(start, 0.0, True, 0, 0)
|
2007-12-24 20:26:15 +05:30
|
|
|
|
2007-12-27 20:36:28 +05:30
|
|
|
def load_data_to_text(self, pos=0):
|
|
|
|
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):
|
|
|
|
text = self.get_text()
|
|
|
|
text = text.replace(chr(10), "\\n")
|
|
|
|
self.gui.data.append(text)
|
|
|
|
|
2007-12-29 18:06:28 +05:30
|
|
|
def update(self, *args):
|
2007-12-24 20:26:15 +05:30
|
|
|
if self._idle_id != 0:
|
|
|
|
if debug: print "%s interrupt!" % self.gui.title
|
|
|
|
self.interrupt()
|
|
|
|
if debug: print "%s creating generator" % self.gui.title
|
2007-12-29 17:19:15 +05:30
|
|
|
self._generator = self.main()
|
2007-12-24 20:26:15 +05:30
|
|
|
if debug: print "%s adding to gobject" % self.gui.title
|
|
|
|
self._idle_id = gobject.idle_add(self._updater,
|
2007-12-29 22:23:14 +05:30
|
|
|
priority=gobject.PRIORITY_LOW - 10)
|
2007-12-24 20:26:15 +05:30
|
|
|
|
|
|
|
def interrupt(self):
|
|
|
|
"""
|
|
|
|
Force the generator to stop running.
|
|
|
|
"""
|
|
|
|
if self._idle_id == 0:
|
|
|
|
if debug: print "%s removing from gobject" % self.gui.title
|
|
|
|
gobject.source_remove(self._idle_id)
|
|
|
|
self._idle_id = 0
|
|
|
|
|
2007-12-27 04:44:13 +05:30
|
|
|
def _db_changed(self, db):
|
|
|
|
if debug: print "%s is _connecting" % self.gui.title
|
|
|
|
self.dbstate.db = db
|
|
|
|
self.gui.dbstate.db = db
|
|
|
|
self.db_changed()
|
|
|
|
self.update()
|
|
|
|
|
2007-12-24 20:26:15 +05:30
|
|
|
def _updater(self):
|
2007-12-26 13:56:33 +05:30
|
|
|
"""
|
|
|
|
Runs the generator.
|
|
|
|
"""
|
2007-12-24 20:26:15 +05:30
|
|
|
if debug: print "%s _updater" % self.gui.title
|
2007-12-29 23:05:07 +05:30
|
|
|
if type(self._generator) != types.GeneratorType:
|
|
|
|
self._idle_id = 0
|
|
|
|
return False
|
2007-12-24 20:26:15 +05:30
|
|
|
try:
|
|
|
|
retval = self._generator.next()
|
|
|
|
if retval == False:
|
|
|
|
self._idle_id = 0
|
|
|
|
return retval
|
|
|
|
except StopIteration:
|
|
|
|
self._idle_id = 0
|
|
|
|
return False
|
|
|
|
except Exception, e:
|
2007-12-29 23:05:07 +05:30
|
|
|
print "Gadget gave an error"
|
2007-12-24 20:26:15 +05:30
|
|
|
traceback.print_exc()
|
2007-12-29 23:05:07 +05:30
|
|
|
print "Continuing after gadget error..."
|
2007-12-24 20:26:15 +05:30
|
|
|
self._idle_id = 0
|
|
|
|
return False
|
|
|
|
|
2007-12-25 10:04:42 +05:30
|
|
|
def on_motion(self, view, event):
|
|
|
|
buffer_location = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
|
|
|
|
int(event.x),
|
|
|
|
int(event.y))
|
|
|
|
iter = view.get_iter_at_location(*buffer_location)
|
2007-12-28 11:53:50 +05:30
|
|
|
cursor = self.standard_cursor
|
2007-12-30 06:54:33 +05:30
|
|
|
for (tag, link_type, handle) in self._tags:
|
2007-12-25 10:04:42 +05:30
|
|
|
if iter.has_tag(tag):
|
2007-12-28 11:53:50 +05:30
|
|
|
tag.set_property('underline', pango.UNDERLINE_SINGLE)
|
|
|
|
cursor = self.link_cursor
|
|
|
|
else:
|
|
|
|
tag.set_property('underline', pango.UNDERLINE_NONE)
|
|
|
|
view.get_window(gtk.TEXT_WINDOW_TEXT).set_cursor(cursor)
|
2007-12-25 10:04:42 +05:30
|
|
|
return False # handle event further, if necessary
|
|
|
|
|
|
|
|
def on_button_press(self, view, event):
|
|
|
|
from Editors import EditPerson
|
|
|
|
buffer_location = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
|
|
|
|
int(event.x),
|
|
|
|
int(event.y))
|
|
|
|
iter = view.get_iter_at_location(*buffer_location)
|
2007-12-30 06:54:33 +05:30
|
|
|
for (tag, link_type, handle) in self._tags:
|
2007-12-25 10:04:42 +05:30
|
|
|
if iter.has_tag(tag):
|
2007-12-30 06:54:33 +05:30
|
|
|
if link_type == 'Person':
|
|
|
|
person = self.dbstate.db.get_person_from_handle(handle)
|
|
|
|
if person != None:
|
|
|
|
if event.button == 1: # left mouse
|
|
|
|
if event.type == gtk.gdk._2BUTTON_PRESS: # double
|
|
|
|
try:
|
|
|
|
EditPerson(self.gui.dbstate,
|
|
|
|
self.gui.uistate,
|
|
|
|
[], person)
|
|
|
|
return True # handled event
|
|
|
|
except Errors.WindowActiveError:
|
|
|
|
pass
|
|
|
|
else: # single click
|
|
|
|
self.gui.dbstate.change_active_person(person)
|
|
|
|
return True # handled event
|
|
|
|
elif link_type == 'Surname':
|
2007-12-30 09:16:39 +05:30
|
|
|
if event.button == 1: # left mouse
|
|
|
|
if event.type == gtk.gdk._2BUTTON_PRESS: # double
|
|
|
|
run_quick_report_by_name(self.gui.dbstate,
|
|
|
|
self.gui.uistate,
|
|
|
|
'samesurnames',
|
|
|
|
handle)
|
2007-12-30 06:54:33 +05:30
|
|
|
return True
|
2007-12-25 10:04:42 +05:30
|
|
|
return False # did not handle event
|
2007-12-24 20:26:15 +05:30
|
|
|
|
2007-12-26 13:56:33 +05:30
|
|
|
def logical_true(value):
|
|
|
|
return value in ["True", True, 1, "1"]
|
2007-12-24 20:26:15 +05:30
|
|
|
|
|
|
|
class GuiGadget:
|
|
|
|
"""
|
|
|
|
Class that handles the plugin interfaces for the MyGrampsView.
|
|
|
|
"""
|
|
|
|
TARGET_TYPE_FRAME = 80
|
|
|
|
LOCAL_DRAG_TYPE = 'GADGET'
|
|
|
|
LOCAL_DRAG_TARGET = (LOCAL_DRAG_TYPE, 0, TARGET_TYPE_FRAME)
|
2007-12-25 05:06:11 +05:30
|
|
|
def __init__(self, viewpage, dbstate, uistate, title, **kwargs):
|
2007-12-24 20:26:15 +05:30
|
|
|
self.viewpage = viewpage
|
|
|
|
self.dbstate = dbstate
|
2007-12-25 05:06:11 +05:30
|
|
|
self.uistate = uistate
|
2007-12-24 20:26:15 +05:30
|
|
|
self.title = title
|
|
|
|
########## Set defaults
|
2007-12-26 13:56:33 +05:30
|
|
|
self.name = kwargs.get("name", "Unnamed Gadget")
|
|
|
|
self.expand = logical_true(kwargs.get("expand", False))
|
|
|
|
self.height = int(kwargs.get("height", 200))
|
|
|
|
self.column = int(kwargs.get("column", -1))
|
|
|
|
self.row = int(kwargs.get("row", -1))
|
2007-12-24 20:26:15 +05:30
|
|
|
self.state = kwargs.get("state", "maximized")
|
2007-12-27 20:36:28 +05:30
|
|
|
self.data = kwargs.get("data", [])
|
2007-12-24 20:26:15 +05:30
|
|
|
##########
|
2007-12-26 22:48:43 +05:30
|
|
|
self.pui = None # user code
|
2007-12-24 20:26:15 +05:30
|
|
|
self.xml = gtk.glade.XML(const.GLADE_FILE, 'gvgadget', "gramps")
|
|
|
|
self.mainframe = self.xml.get_widget('gvgadget')
|
|
|
|
self.textview = self.xml.get_widget('gvtextview')
|
|
|
|
self.buffer = self.textview.get_buffer()
|
|
|
|
self.scrolledwindow = self.xml.get_widget('gvscrolledwindow')
|
|
|
|
self.titlelabel = self.xml.get_widget('gvtitle')
|
|
|
|
self.titlelabel.set_text("<b><i>%s</i></b>" % self.title)
|
|
|
|
self.titlelabel.set_use_markup(True)
|
2007-12-26 13:56:33 +05:30
|
|
|
self.gvclose = self.xml.get_widget('gvclose')
|
|
|
|
self.gvclose.connect('clicked', self.close)
|
|
|
|
self.gvstate = self.xml.get_widget('gvstate')
|
|
|
|
self.gvstate.connect('clicked', self.change_state)
|
|
|
|
self.gvproperties = self.xml.get_widget('gvproperties')
|
|
|
|
self.gvproperties.connect('clicked', self.set_properties)
|
2007-12-24 20:26:15 +05:30
|
|
|
self.xml.get_widget('gvcloseimage').set_from_stock(gtk.STOCK_CLOSE,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
|
|
|
self.xml.get_widget('gvstateimage').set_from_stock(gtk.STOCK_REMOVE,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
|
|
|
self.xml.get_widget('gvpropertiesimage').set_from_stock(gtk.STOCK_PROPERTIES,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
|
|
|
|
|
|
|
# source:
|
2007-12-26 13:56:33 +05:30
|
|
|
drag = self.gvproperties
|
2007-12-24 20:26:15 +05:30
|
|
|
drag.drag_source_set(gtk.gdk.BUTTON1_MASK,
|
|
|
|
[GuiGadget.LOCAL_DRAG_TARGET],
|
|
|
|
gtk.gdk.ACTION_COPY)
|
|
|
|
|
2007-12-28 11:53:50 +05:30
|
|
|
def close(self, *obj):
|
2007-12-26 13:56:33 +05:30
|
|
|
if self.state == "windowed":
|
|
|
|
return
|
2007-12-28 11:53:50 +05:30
|
|
|
self.state = "closed"
|
|
|
|
self.viewpage.closed_gadgets.append(self)
|
|
|
|
self.mainframe.get_parent().remove(self.mainframe)
|
2007-12-24 20:26:15 +05:30
|
|
|
|
2007-12-26 22:18:51 +05:30
|
|
|
def detach(self):
|
2007-12-26 13:56:33 +05:30
|
|
|
# hide buttons:
|
2007-12-27 04:44:13 +05:30
|
|
|
self.set_state("maximized")
|
2007-12-26 13:56:33 +05:30
|
|
|
self.gvclose.hide()
|
|
|
|
self.gvstate.hide()
|
|
|
|
self.gvproperties.hide()
|
2007-12-25 23:21:37 +05:30
|
|
|
# keep a pointer to old parent frame:
|
|
|
|
self.parent = self.mainframe.get_parent()
|
2007-12-28 11:53:50 +05:30
|
|
|
self.viewpage.detached_gadgets.append(self)
|
2007-12-25 23:21:37 +05:30
|
|
|
# make a window, and attach it there
|
|
|
|
self.detached_window = GadgetWindow(self)
|
2007-12-26 13:56:33 +05:30
|
|
|
self.state = "windowed"
|
2007-12-25 23:21:37 +05:30
|
|
|
|
2007-12-25 10:04:42 +05:30
|
|
|
def set_state(self, state):
|
|
|
|
self.state = state
|
|
|
|
if state == "minimized":
|
2007-12-24 20:26:15 +05:30
|
|
|
self.scrolledwindow.hide()
|
|
|
|
self.xml.get_widget('gvstateimage').set_from_stock(gtk.STOCK_ADD,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
2007-12-25 10:04:42 +05:30
|
|
|
column = self.mainframe.get_parent() # column
|
|
|
|
expand,fill,padding,pack = column.query_child_packing(self.mainframe)
|
|
|
|
column.set_child_packing(self.mainframe,False,fill,padding,pack)
|
|
|
|
|
2007-12-24 20:26:15 +05:30
|
|
|
else:
|
|
|
|
self.scrolledwindow.show()
|
|
|
|
self.xml.get_widget('gvstateimage').set_from_stock(gtk.STOCK_REMOVE,
|
|
|
|
gtk.ICON_SIZE_MENU)
|
|
|
|
column = self.mainframe.get_parent() # column
|
|
|
|
expand,fill,padding,pack = column.query_child_packing(self.mainframe)
|
2007-12-25 10:04:42 +05:30
|
|
|
column.set_child_packing(self.mainframe,self.expand,fill,padding,pack)
|
|
|
|
|
|
|
|
def change_state(self, obj):
|
2007-12-25 23:25:42 +05:30
|
|
|
if self.state == "windowed":
|
|
|
|
pass # don't change if windowed
|
2007-12-25 10:04:42 +05:30
|
|
|
else:
|
2007-12-25 23:25:42 +05:30
|
|
|
if self.state == "maximized":
|
|
|
|
self.set_state("minimized")
|
|
|
|
else:
|
|
|
|
self.set_state("maximized")
|
|
|
|
|
2007-12-24 20:26:15 +05:30
|
|
|
def set_properties(self, obj):
|
2007-12-25 23:21:37 +05:30
|
|
|
if self.state == "windowed":
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
self.detach()
|
|
|
|
return
|
2007-12-26 13:56:33 +05:30
|
|
|
# FIXME: add control for expand AND detach
|
2007-12-24 20:26:15 +05:30
|
|
|
self.expand = not self.expand
|
|
|
|
if self.state == "maximized":
|
|
|
|
column = self.mainframe.get_parent() # column
|
|
|
|
expand,fill,padding,pack = column.query_child_packing(self.mainframe)
|
|
|
|
column.set_child_packing(self.mainframe,self.expand,fill,padding,pack)
|
|
|
|
|
|
|
|
def append_text(self, text):
|
|
|
|
self.buffer.insert_at_cursor(text)
|
|
|
|
|
|
|
|
def clear_text(self):
|
|
|
|
self.buffer.set_text('')
|
|
|
|
|
|
|
|
def set_text(self, text):
|
|
|
|
self.buffer.set_text(text)
|
|
|
|
|
2007-12-26 13:56:33 +05:30
|
|
|
def get_source_widget(self):
|
|
|
|
"""
|
|
|
|
Hack to allow us to send this object to the drop_widget
|
|
|
|
method as a context.
|
|
|
|
"""
|
|
|
|
return self.gvproperties
|
|
|
|
|
|
|
|
class MyScrolledWindow(gtk.ScrolledWindow):
|
|
|
|
def show_all(self):
|
|
|
|
# first show them all:
|
|
|
|
gtk.ScrolledWindow.show_all(self)
|
|
|
|
# Hack to get around show_all that shows hidden items
|
|
|
|
# do once, the first time showing
|
|
|
|
if self.viewpage:
|
2007-12-28 11:53:50 +05:30
|
|
|
gadgets = [g for g in self.viewpage.gadget_map.values() if g != None]
|
2007-12-26 13:56:33 +05:30
|
|
|
self.viewpage = None
|
|
|
|
for gadget in gadgets:
|
|
|
|
if gadget.state == "minimized":
|
|
|
|
gadget.set_state("minimized")
|
2007-12-24 20:26:15 +05:30
|
|
|
|
|
|
|
class MyGrampsView(PageView.PageView):
|
|
|
|
"""
|
|
|
|
MyGrampsView interface
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, dbstate, uistate):
|
|
|
|
"""
|
|
|
|
Creates a MyGrampsView, with the current dbstate and uistate
|
|
|
|
"""
|
|
|
|
PageView.PageView.__init__(self, _('My Gramps'), dbstate, uistate)
|
2007-12-26 13:56:33 +05:30
|
|
|
self._popup_xy = None
|
2007-12-24 20:26:15 +05:30
|
|
|
|
|
|
|
def change_db(self, event):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
|
# FIXME: remove/add widgets from new db ini file
|
|
|
|
pass
|
|
|
|
|
|
|
|
def build_widget(self):
|
|
|
|
"""
|
|
|
|
Builds the container widget for the interface. Must be overridden by the
|
|
|
|
the base class. Returns a gtk container widget.
|
|
|
|
"""
|
2007-12-26 13:56:33 +05:30
|
|
|
# load the user's gadgets and set columns, etc
|
|
|
|
user_gadgets = self.load_gadgets()
|
|
|
|
# build the GUI:
|
|
|
|
frame = MyScrolledWindow()
|
2007-12-27 04:44:13 +05:30
|
|
|
msg = _("Right click to add gadgets")
|
|
|
|
self.tooltips = gtk.Tooltips()
|
|
|
|
self.tooltips.set_tip(frame, msg)
|
2007-12-26 13:56:33 +05:30
|
|
|
frame.viewpage = self
|
2007-12-24 20:26:15 +05:30
|
|
|
frame.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
2007-12-26 13:56:33 +05:30
|
|
|
self.hbox = gtk.HBox(homogeneous=True)
|
2007-12-24 20:26:15 +05:30
|
|
|
# Set up drag and drop
|
|
|
|
frame.drag_dest_set(gtk.DEST_DEFAULT_MOTION |
|
|
|
|
gtk.DEST_DEFAULT_HIGHLIGHT |
|
|
|
|
gtk.DEST_DEFAULT_DROP,
|
|
|
|
[('GADGET', 0, 80)],
|
|
|
|
gtk.gdk.ACTION_COPY)
|
|
|
|
frame.connect('drag_drop', self.drop_widget)
|
2007-12-26 13:56:33 +05:30
|
|
|
frame.connect('button-press-event', self._button_press)
|
2007-12-24 20:26:15 +05:30
|
|
|
|
2007-12-26 13:56:33 +05:30
|
|
|
frame.add_with_viewport(self.hbox)
|
2007-12-24 20:26:15 +05:30
|
|
|
# Create the columns:
|
|
|
|
self.columns = []
|
|
|
|
for i in range(self.column_count):
|
|
|
|
self.columns.append(gtk.VBox())
|
2007-12-26 13:56:33 +05:30
|
|
|
self.hbox.pack_start(self.columns[-1],expand=True)
|
2007-12-24 20:26:15 +05:30
|
|
|
# Load the gadgets
|
|
|
|
self.gadget_map = {} # title->gadget
|
|
|
|
self.frame_map = {} # frame->gadget
|
2007-12-28 11:53:50 +05:30
|
|
|
self.detached_gadgets = [] # list of detached gadgets
|
|
|
|
self.closed_gadgets = [] # list of closed gadgets
|
|
|
|
self.closed_opts = [] # list of closed options from ini file
|
2007-12-26 13:56:33 +05:30
|
|
|
# get the user's gadgets from ~/.gramps/gadgets.ini
|
2007-12-24 20:26:15 +05:30
|
|
|
# Load the user's gadgets:
|
2007-12-26 13:56:33 +05:30
|
|
|
for (name, opts) in user_gadgets:
|
2007-12-24 20:26:15 +05:30
|
|
|
all_opts = get_gadget_opts(name, opts)
|
|
|
|
if "title" not in all_opts:
|
|
|
|
all_opts["title"] = "Untitled Gadget"
|
2007-12-28 13:16:26 +05:30
|
|
|
if "state" not in all_opts:
|
|
|
|
all_opts["state"] = "maximized"
|
2007-12-24 20:26:15 +05:30
|
|
|
# uniqify titles:
|
|
|
|
unique = all_opts["title"]
|
|
|
|
cnt = 1
|
|
|
|
while unique in self.gadget_map:
|
|
|
|
unique = all_opts["title"] + ("-%d" % cnt)
|
|
|
|
cnt += 1
|
|
|
|
all_opts["title"] = unique
|
2007-12-28 11:53:50 +05:30
|
|
|
if all_opts["state"] == "closed":
|
|
|
|
self.gadget_map[all_opts["title"]] = None # save closed name
|
|
|
|
self.closed_opts.append(all_opts)
|
|
|
|
continue
|
|
|
|
g = make_requested_gadget(self, name, all_opts,
|
|
|
|
self.dbstate, self.uistate)
|
|
|
|
if g:
|
|
|
|
self.gadget_map[all_opts["title"]] = g
|
|
|
|
self.frame_map[str(g.mainframe)] = g
|
2007-12-24 20:26:15 +05:30
|
|
|
else:
|
2007-12-28 11:53:50 +05:30
|
|
|
print "Can't make gadget of type '%s'." % name
|
2007-12-26 13:56:33 +05:30
|
|
|
self.place_gadgets()
|
|
|
|
return frame
|
|
|
|
|
|
|
|
def clear_gadgets(self):
|
|
|
|
"""
|
|
|
|
Detach all of the mainframe gadgets from the columns.
|
|
|
|
"""
|
2007-12-28 11:53:50 +05:30
|
|
|
gadgets = [g for g in self.gadget_map.values() if g != None]
|
2007-12-26 13:56:33 +05:30
|
|
|
for gadget in gadgets:
|
|
|
|
column = gadget.mainframe.get_parent()
|
|
|
|
column.remove(gadget.mainframe)
|
|
|
|
|
|
|
|
def place_gadgets(self):
|
|
|
|
"""
|
|
|
|
Place the gadget mainframes in the columns.
|
|
|
|
"""
|
2007-12-28 11:53:50 +05:30
|
|
|
gadgets = [g for g in self.gadget_map.values() if g != None]
|
2007-12-24 20:26:15 +05:30
|
|
|
# put the gadgets where they go:
|
2007-12-26 13:56:33 +05:30
|
|
|
# sort by row
|
|
|
|
gadgets.sort(lambda a, b: cmp(a.row, b.row))
|
2007-12-24 20:26:15 +05:30
|
|
|
cnt = 0
|
2007-12-26 13:56:33 +05:30
|
|
|
for gadget in gadgets:
|
2007-12-24 20:26:15 +05:30
|
|
|
# see if the user wants this in a particular location:
|
|
|
|
# and if there are that many columns
|
2007-12-26 13:56:33 +05:30
|
|
|
if gadget.column >= 0 and gadget.column < self.column_count:
|
2007-12-24 20:26:15 +05:30
|
|
|
pos = gadget.column
|
|
|
|
else:
|
|
|
|
# else, spread them out:
|
2007-12-26 13:56:33 +05:30
|
|
|
pos = cnt % self.column_count
|
2007-12-24 20:26:15 +05:30
|
|
|
self.columns[pos].pack_start(gadget.mainframe, expand=gadget.expand)
|
2007-12-26 13:56:33 +05:30
|
|
|
gadget.column = pos
|
2007-12-24 20:26:15 +05:30
|
|
|
# set height on gadget.scrolledwindow here:
|
|
|
|
gadget.scrolledwindow.set_size_request(-1, gadget.height)
|
2007-12-26 13:56:33 +05:30
|
|
|
# Can't minimize here, because GRAMPS calls show_all later:
|
2007-12-25 10:04:42 +05:30
|
|
|
#if gadget.state == "minimized": # starts max, change to min it
|
2007-12-26 13:56:33 +05:30
|
|
|
# gadget.set_state("minimized") # minimize it
|
2007-12-29 23:26:23 +05:30
|
|
|
# set minimized is called in page subclass hack (above)
|
2007-12-26 13:56:33 +05:30
|
|
|
if gadget.state == "windowed":
|
2007-12-26 22:18:51 +05:30
|
|
|
gadget.detach()
|
2007-12-28 11:53:50 +05:30
|
|
|
elif gadget.state == "closed":
|
|
|
|
gadget.close()
|
2007-12-24 20:26:15 +05:30
|
|
|
cnt += 1
|
2007-12-26 13:56:33 +05:30
|
|
|
|
|
|
|
def load_gadgets(self):
|
2007-12-27 04:44:13 +05:30
|
|
|
self.column_count = 2 # default for new user
|
2007-12-26 13:56:33 +05:30
|
|
|
retval = []
|
|
|
|
filename = GADGET_FILENAME
|
|
|
|
if filename and os.path.exists(filename):
|
|
|
|
cp = ConfigParser.ConfigParser()
|
|
|
|
cp.read(filename)
|
|
|
|
for sec in cp.sections():
|
|
|
|
if sec == "My Gramps View Options":
|
|
|
|
if "column_count" in cp.options(sec):
|
|
|
|
self.column_count = int(cp.get(sec, "column_count"))
|
|
|
|
else:
|
2007-12-29 23:26:23 +05:30
|
|
|
data = {"title": sec}
|
2007-12-26 13:56:33 +05:30
|
|
|
for opt in cp.options(sec):
|
2007-12-27 20:36:28 +05:30
|
|
|
if opt.startswith("data["):
|
|
|
|
temp = data.get("data", [])
|
|
|
|
temp.append(cp.get(sec, opt).strip())
|
|
|
|
data["data"] = temp
|
|
|
|
else:
|
|
|
|
data[opt] = cp.get(sec, opt).strip()
|
2007-12-26 13:56:33 +05:30
|
|
|
if "name" not in data:
|
|
|
|
data["name"] = "Unnamed Gadget"
|
|
|
|
retval.append((data["name"], data)) # name, opts
|
|
|
|
else:
|
|
|
|
# give defaults as currently known
|
2007-12-27 04:44:13 +05:30
|
|
|
for name in ["Top Surnames Gadget", "Welcome Gadget"]:
|
|
|
|
if name in AVAILABLE_GADGETS:
|
|
|
|
retval.append((name, AVAILABLE_GADGETS[name]))
|
2007-12-26 13:56:33 +05:30
|
|
|
return retval
|
|
|
|
|
|
|
|
def save(self, *args):
|
|
|
|
if debug: print "saving"
|
2007-12-29 22:23:14 +05:30
|
|
|
if len(self.frame_map.keys() +
|
|
|
|
self.detached_gadgets +
|
|
|
|
self.closed_gadgets) == 0:
|
|
|
|
return # something is the matter
|
2007-12-26 13:56:33 +05:30
|
|
|
filename = GADGET_FILENAME
|
2007-12-27 20:36:28 +05:30
|
|
|
try:
|
|
|
|
fp = open(filename, "w")
|
|
|
|
except:
|
|
|
|
print "Failed writing '%s'; gadgets not saved" % filename
|
|
|
|
return
|
2007-12-26 13:56:33 +05:30
|
|
|
fp.write(";; Gramps gadgets file" + NL)
|
|
|
|
fp.write((";; Automatically created at %s" % time.strftime("%Y/%m/%d %H:%M:%S")) + NL + NL)
|
|
|
|
fp.write("[My Gramps View Options]" + NL)
|
|
|
|
fp.write(("column_count=%d" + NL + NL) % self.column_count)
|
2007-12-28 11:53:50 +05:30
|
|
|
# showing gadgets:
|
2007-12-26 13:56:33 +05:30
|
|
|
for col in range(self.column_count):
|
|
|
|
row = 0
|
|
|
|
for gframe in self.columns[col]:
|
|
|
|
gadget = self.frame_map[str(gframe)]
|
|
|
|
opts = get_gadget_options_by_name(gadget.name)
|
|
|
|
if opts != None:
|
|
|
|
base_opts = opts.copy()
|
|
|
|
for key in base_opts:
|
|
|
|
if key in gadget.__dict__:
|
|
|
|
base_opts[key] = gadget.__dict__[key]
|
|
|
|
fp.write(("[%s]" + NL) % gadget.title)
|
|
|
|
for key in base_opts:
|
|
|
|
if key == "content": continue
|
2007-12-28 11:53:50 +05:30
|
|
|
elif key == "title": continue
|
|
|
|
elif key == "column": continue
|
|
|
|
elif key == "row": continue
|
|
|
|
elif key == "data":
|
2007-12-28 13:16:26 +05:30
|
|
|
if type(base_opts["data"]) not in [list, tuple]:
|
|
|
|
fp.write(("data[0]=%s" + NL) % base_opts["data"])
|
|
|
|
else:
|
|
|
|
cnt = 0
|
|
|
|
for item in base_opts["data"]:
|
|
|
|
fp.write(("data[%d]=%s" + NL) % (cnt, item))
|
|
|
|
cnt += 1
|
2007-12-27 20:36:28 +05:30
|
|
|
else:
|
|
|
|
fp.write(("%s=%s" + NL)% (key, base_opts[key]))
|
2007-12-26 13:56:33 +05:30
|
|
|
fp.write(("column=%d" + NL) % col)
|
|
|
|
fp.write(("row=%d" + NL) % row)
|
|
|
|
fp.write(NL)
|
|
|
|
row += 1
|
2007-12-28 11:53:50 +05:30
|
|
|
for gadget in self.detached_gadgets + self.closed_gadgets:
|
2007-12-26 13:56:33 +05:30
|
|
|
opts = get_gadget_options_by_name(gadget.name)
|
|
|
|
if opts != None:
|
|
|
|
base_opts = opts.copy()
|
|
|
|
for key in base_opts:
|
|
|
|
if key in gadget.__dict__:
|
|
|
|
base_opts[key] = gadget.__dict__[key]
|
|
|
|
fp.write(("[%s]" + NL) % gadget.title)
|
|
|
|
for key in base_opts:
|
|
|
|
if key == "content": continue
|
2007-12-28 11:53:50 +05:30
|
|
|
elif key == "title": continue
|
|
|
|
elif key == "data":
|
2007-12-28 13:16:26 +05:30
|
|
|
if type(base_opts["data"]) not in [list, tuple]:
|
|
|
|
fp.write(("data[0]=%s" + NL) % base_opts["data"])
|
|
|
|
else:
|
|
|
|
cnt = 0
|
|
|
|
for item in base_opts["data"]:
|
|
|
|
fp.write(("data[%d]=%s" + NL) % (cnt, item))
|
|
|
|
cnt += 1
|
2007-12-28 11:53:50 +05:30
|
|
|
else:
|
|
|
|
fp.write(("%s=%s" + NL)% (key, base_opts[key]))
|
2007-12-26 13:56:33 +05:30
|
|
|
fp.write(NL)
|
2007-12-28 11:53:50 +05:30
|
|
|
for opts in self.closed_opts:
|
|
|
|
fp.write(("[%s]" + NL) % opts["title"])
|
|
|
|
for key in opts:
|
|
|
|
if key == "content": continue
|
|
|
|
elif key == "title": continue
|
|
|
|
elif key == "data":
|
2007-12-28 13:16:26 +05:30
|
|
|
if type(opts["data"]) not in [list, tuple]:
|
|
|
|
fp.write(("data[0]=%s" + NL) % opts["data"])
|
|
|
|
else:
|
|
|
|
cnt = 0
|
|
|
|
for item in opts["data"]:
|
|
|
|
fp.write(("data[%d]=%s" + NL) % (cnt, item))
|
|
|
|
cnt += 1
|
2007-12-28 11:53:50 +05:30
|
|
|
else:
|
|
|
|
fp.write(("%s=%s" + NL)% (key, opts[key]))
|
|
|
|
fp.write(NL)
|
2007-12-26 13:56:33 +05:30
|
|
|
fp.close()
|
2007-12-24 20:26:15 +05:30
|
|
|
|
|
|
|
def drop_widget(self, source, context, x, y, timedata):
|
2007-12-26 13:56:33 +05:30
|
|
|
"""
|
|
|
|
This is the destination method for handling drag and drop
|
|
|
|
of a gadget onto the main scrolled window.
|
|
|
|
"""
|
2007-12-24 20:26:15 +05:30
|
|
|
button = context.get_source_widget()
|
|
|
|
hbox = button.get_parent()
|
|
|
|
mainframe = hbox.get_parent()
|
|
|
|
rect = source.get_allocation()
|
|
|
|
sx, sy = rect.width, rect.height
|
|
|
|
# first, find column:
|
|
|
|
col = 0
|
|
|
|
for i in range(len(self.columns)):
|
|
|
|
if x < (sx/len(self.columns) * (i + 1)):
|
|
|
|
col = i
|
|
|
|
break
|
|
|
|
fromcol = mainframe.get_parent()
|
2007-12-28 11:53:50 +05:30
|
|
|
if fromcol:
|
|
|
|
fromcol.remove(mainframe)
|
2007-12-24 20:26:15 +05:30
|
|
|
# now find where to insert in column:
|
|
|
|
stack = []
|
|
|
|
for gframe in self.columns[col]:
|
|
|
|
rect = gframe.get_allocation()
|
|
|
|
if y < (rect.y + 15): # starts at 0, this allows insert before
|
|
|
|
self.columns[col].remove(gframe)
|
|
|
|
stack.append(gframe)
|
2007-12-28 11:53:50 +05:30
|
|
|
maingadget = self.frame_map.get(str(mainframe), None)
|
2007-12-26 13:56:33 +05:30
|
|
|
maingadget.column = col
|
2007-12-24 20:26:15 +05:30
|
|
|
if maingadget.state == "maximized":
|
|
|
|
expand = maingadget.expand
|
|
|
|
else:
|
|
|
|
expand = False
|
|
|
|
self.columns[col].pack_start(mainframe, expand=expand)
|
|
|
|
for gframe in stack:
|
|
|
|
gadget = self.frame_map[str(gframe)]
|
|
|
|
if gadget.state == "maximized":
|
|
|
|
expand = gadget.expand
|
|
|
|
else:
|
|
|
|
expand = False
|
|
|
|
self.columns[col].pack_start(gframe, expand=expand)
|
|
|
|
return True
|
|
|
|
|
|
|
|
def define_actions(self):
|
|
|
|
"""
|
|
|
|
Defines the UIManager actions. Called by the ViewManager to set up the
|
|
|
|
View. The user typically defines self.action_list and
|
|
|
|
self.action_toggle_list in this function.
|
|
|
|
"""
|
2007-12-26 13:56:33 +05:30
|
|
|
self.action = gtk.ActionGroup(self.title + "/Gadgets")
|
|
|
|
self.action.add_actions([('AddGadget',gtk.STOCK_ADD,_("_Add a gadget")),
|
2007-12-28 11:53:50 +05:30
|
|
|
('RestoreGadget',None,_("_Restore a gadget")),
|
2007-12-28 12:18:45 +05:30
|
|
|
('DeleteGadget',None,_("_Delete a gadget")),
|
|
|
|
('Columns1',None,_("Set columns to _1"),
|
2007-12-26 13:56:33 +05:30
|
|
|
None,None,
|
|
|
|
lambda obj:self.set_columns(1)),
|
2007-12-28 12:18:45 +05:30
|
|
|
('Columns2',None,_("Set columns to _2"),
|
2007-12-26 13:56:33 +05:30
|
|
|
None,None,
|
|
|
|
lambda obj:self.set_columns(2)),
|
2007-12-28 12:18:45 +05:30
|
|
|
('Columns3',None,_("Set columns to _3"),
|
2007-12-26 13:56:33 +05:30
|
|
|
None,None,
|
|
|
|
lambda obj:self.set_columns(3)),
|
|
|
|
])
|
|
|
|
self._add_action_group(self.action)
|
|
|
|
|
|
|
|
def set_columns(self, num):
|
|
|
|
# clear the gadgets:
|
|
|
|
self.clear_gadgets()
|
|
|
|
# clear the columns:
|
|
|
|
for column in self.columns:
|
|
|
|
frame = column.get_parent()
|
|
|
|
frame.remove(column)
|
|
|
|
del column
|
|
|
|
# create the new ones:
|
|
|
|
self.column_count = num
|
|
|
|
self.columns = []
|
|
|
|
for i in range(self.column_count):
|
|
|
|
self.columns.append(gtk.VBox())
|
|
|
|
self.columns[-1].show()
|
|
|
|
self.hbox.pack_start(self.columns[-1],expand=True)
|
|
|
|
# place the gadgets back in the new columns
|
|
|
|
self.place_gadgets()
|
|
|
|
self.widget.show()
|
|
|
|
|
2007-12-28 12:18:45 +05:30
|
|
|
def delete_gadget(self, obj):
|
|
|
|
name = obj.get_child().get_label()
|
|
|
|
############### First kind: from current session
|
|
|
|
for gadget in self.closed_gadgets:
|
|
|
|
if gadget.title == name:
|
|
|
|
self.closed_gadgets.remove(gadget)
|
|
|
|
self.gadget_map[gadget.title]
|
|
|
|
self.frame_map[str(gadget.mainframe)]
|
|
|
|
del gadget
|
|
|
|
return
|
|
|
|
################ Second kind: from options
|
|
|
|
for opts in self.closed_opts:
|
|
|
|
if opts["title"] == name:
|
|
|
|
self.closed_opts.remove(opts)
|
|
|
|
return
|
|
|
|
|
2007-12-28 11:53:50 +05:30
|
|
|
def restore_gadget(self, obj):
|
|
|
|
name = obj.get_child().get_label()
|
|
|
|
############### First kind: from current session
|
|
|
|
for gadget in self.closed_gadgets:
|
|
|
|
if gadget.title == name:
|
|
|
|
gadget.state = "maximized"
|
|
|
|
self.closed_gadgets.remove(gadget)
|
|
|
|
if self._popup_xy != None:
|
|
|
|
self.drop_widget(self.widget, gadget,
|
|
|
|
self._popup_xy[0], self._popup_xy[1], 0)
|
|
|
|
else:
|
|
|
|
self.drop_widget(self.widget, gadget, 0, 0, 0)
|
|
|
|
return
|
|
|
|
################ Second kind: from options
|
|
|
|
for opts in self.closed_opts:
|
|
|
|
if opts["title"] == name:
|
|
|
|
self.closed_opts.remove(opts)
|
|
|
|
g = make_requested_gadget(self, opts["name"], opts,
|
|
|
|
self.dbstate, self.uistate)
|
|
|
|
if g:
|
|
|
|
self.gadget_map[opts["title"]] = g
|
|
|
|
self.frame_map[str(g.mainframe)] = g
|
|
|
|
else:
|
|
|
|
print "Can't make gadget of type '%s'." % name
|
|
|
|
if g:
|
|
|
|
gadget = g
|
|
|
|
gadget.state = "maximized"
|
|
|
|
if gadget.column >= 0 and gadget.column < len(self.columns):
|
|
|
|
pos = gadget.column
|
|
|
|
else:
|
|
|
|
pos = 0
|
|
|
|
self.columns[pos].pack_start(gadget.mainframe, expand=gadget.expand)
|
|
|
|
# set height on gadget.scrolledwindow here:
|
|
|
|
gadget.scrolledwindow.set_size_request(-1, gadget.height)
|
|
|
|
## now drop it in right place
|
|
|
|
if self._popup_xy != None:
|
|
|
|
self.drop_widget(self.widget, gadget,
|
|
|
|
self._popup_xy[0], self._popup_xy[1], 0)
|
|
|
|
else:
|
|
|
|
self.drop_widget(self.widget, gadget, 0, 0, 0)
|
|
|
|
|
2007-12-26 13:56:33 +05:30
|
|
|
def add_gadget(self, obj):
|
|
|
|
name = obj.get_child().get_label()
|
|
|
|
all_opts = get_gadget_options_by_name(name)
|
2007-12-30 23:13:19 +05:30
|
|
|
if all_opts == None:
|
|
|
|
print "Unknown gadget type: '%s'; bad gadgets.ini file?" % name
|
|
|
|
return
|
2007-12-26 13:56:33 +05:30
|
|
|
if "title" not in all_opts:
|
|
|
|
all_opts["title"] = "Untitled Gadget"
|
|
|
|
# uniqify titles:
|
|
|
|
unique = all_opts["title"]
|
|
|
|
cnt = 1
|
|
|
|
while unique in self.gadget_map:
|
|
|
|
unique = all_opts["title"] + ("-%d" % cnt)
|
|
|
|
cnt += 1
|
|
|
|
all_opts["title"] = unique
|
|
|
|
if all_opts["title"] not in self.gadget_map:
|
2007-12-28 11:55:46 +05:30
|
|
|
g = make_requested_gadget(self, name, all_opts,
|
|
|
|
self.dbstate, self.uistate)
|
2007-12-26 13:56:33 +05:30
|
|
|
if g:
|
2007-12-28 11:53:50 +05:30
|
|
|
self.gadget_map[all_opts["title"]] = g
|
|
|
|
self.frame_map[str(g.mainframe)] = g
|
2007-12-26 13:56:33 +05:30
|
|
|
gadget = g
|
|
|
|
if gadget.column >= 0 and gadget.column < len(self.columns):
|
|
|
|
pos = gadget.column
|
|
|
|
else:
|
|
|
|
pos = 0
|
|
|
|
self.columns[pos].pack_start(gadget.mainframe, expand=gadget.expand)
|
|
|
|
# set height on gadget.scrolledwindow here:
|
|
|
|
gadget.scrolledwindow.set_size_request(-1, gadget.height)
|
2007-12-28 11:53:50 +05:30
|
|
|
## now drop it in right place
|
|
|
|
if self._popup_xy != None:
|
|
|
|
self.drop_widget(self.widget, gadget,
|
|
|
|
self._popup_xy[0], self._popup_xy[1], 0)
|
|
|
|
else:
|
|
|
|
self.drop_widget(self.widget, gadget, 0, 0, 0)
|
|
|
|
else:
|
|
|
|
print "Can't make gadget of type '%s'." % name
|
2007-12-24 20:26:15 +05:30
|
|
|
|
|
|
|
def get_stock(self):
|
|
|
|
"""
|
|
|
|
Returns image associated with the view, which is used for the
|
|
|
|
icon for the button.
|
|
|
|
"""
|
|
|
|
return 'gtk-home'
|
|
|
|
|
|
|
|
def build_tree(self):
|
|
|
|
return
|
|
|
|
|
2007-12-26 13:56:33 +05:30
|
|
|
def ui_definition(self):
|
|
|
|
return """
|
|
|
|
<ui>
|
2007-12-27 04:44:13 +05:30
|
|
|
<menubar name="MenuBar">
|
|
|
|
<menu action="ViewMenu">
|
|
|
|
<menuitem action="Columns1"/>
|
|
|
|
<menuitem action="Columns2"/>
|
|
|
|
<menuitem action="Columns3"/>
|
|
|
|
</menu>
|
|
|
|
</menubar>
|
2007-12-26 13:56:33 +05:30
|
|
|
<popup name="Popup">
|
|
|
|
<menuitem action="AddGadget"/>
|
2007-12-28 11:53:50 +05:30
|
|
|
<menuitem action="RestoreGadget"/>
|
2007-12-28 12:18:45 +05:30
|
|
|
<menuitem action="DeleteGadget"/>
|
2007-12-26 13:56:33 +05:30
|
|
|
<separator/>
|
|
|
|
<menuitem action="Columns1"/>
|
|
|
|
<menuitem action="Columns2"/>
|
|
|
|
<menuitem action="Columns3"/>
|
|
|
|
</popup>
|
|
|
|
</ui>
|
|
|
|
"""
|
|
|
|
|
|
|
|
def _button_press(self, obj, event):
|
2007-12-28 11:53:50 +05:30
|
|
|
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
|
2007-12-26 13:56:33 +05:30
|
|
|
self._popup_xy = (event.x, event.y)
|
|
|
|
menu = self.uistate.uimanager.get_widget('/Popup')
|
2007-12-27 04:44:13 +05:30
|
|
|
ag_menu = self.uistate.uimanager.get_widget('/Popup/AddGadget')
|
|
|
|
if ag_menu:
|
|
|
|
qr_menu = ag_menu.get_submenu()
|
|
|
|
if qr_menu == None:
|
|
|
|
qr_menu = gtk.Menu()
|
|
|
|
names = AVAILABLE_GADGETS.keys()
|
|
|
|
names.sort()
|
|
|
|
for name in names:
|
|
|
|
Utils.add_menuitem(qr_menu, name,
|
|
|
|
None, self.add_gadget)
|
|
|
|
self.uistate.uimanager.get_widget('/Popup/AddGadget').set_submenu(qr_menu)
|
2007-12-28 11:53:50 +05:30
|
|
|
rg_menu = self.uistate.uimanager.get_widget('/Popup/RestoreGadget')
|
2007-12-28 12:18:45 +05:30
|
|
|
dg_menu = self.uistate.uimanager.get_widget('/Popup/DeleteGadget')
|
2007-12-28 11:53:50 +05:30
|
|
|
if rg_menu:
|
|
|
|
qr_menu = rg_menu.get_submenu()
|
|
|
|
if qr_menu != None:
|
|
|
|
rg_menu.remove_submenu()
|
2007-12-28 12:18:45 +05:30
|
|
|
qr2_menu = dg_menu.get_submenu()
|
|
|
|
if qr2_menu != None:
|
|
|
|
dg_menu.remove_submenu()
|
2007-12-28 11:53:50 +05:30
|
|
|
names = []
|
|
|
|
for gadget in self.closed_gadgets:
|
|
|
|
names.append(gadget.title)
|
|
|
|
for opts in self.closed_opts:
|
|
|
|
names.append(opts["title"])
|
|
|
|
names.sort()
|
|
|
|
if len(names) > 0:
|
|
|
|
qr_menu = gtk.Menu()
|
2007-12-28 12:18:45 +05:30
|
|
|
qr2_menu = gtk.Menu()
|
2007-12-28 11:53:50 +05:30
|
|
|
for name in names:
|
|
|
|
Utils.add_menuitem(qr_menu, name,
|
|
|
|
None, self.restore_gadget)
|
2007-12-28 12:18:45 +05:30
|
|
|
Utils.add_menuitem(qr2_menu, name,
|
|
|
|
None, self.delete_gadget)
|
2007-12-28 11:53:50 +05:30
|
|
|
self.uistate.uimanager.get_widget('/Popup/RestoreGadget').set_submenu(qr_menu)
|
2007-12-28 12:18:45 +05:30
|
|
|
self.uistate.uimanager.get_widget('/Popup/DeleteGadget').set_submenu(qr2_menu)
|
2007-12-26 13:56:33 +05:30
|
|
|
if menu:
|
|
|
|
menu.popup(None, None, None, event.button, event.time)
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2007-12-26 22:18:51 +05:30
|
|
|
def on_delete(self):
|
2007-12-28 11:53:50 +05:30
|
|
|
gadgets = [g for g in self.gadget_map.values() if g != None]
|
2007-12-26 22:18:51 +05:30
|
|
|
for gadget in gadgets:
|
|
|
|
# this is the only place where the gui runs user code directly
|
2007-12-26 22:48:43 +05:30
|
|
|
if gadget.pui:
|
|
|
|
gadget.pui.on_save()
|
2007-12-26 22:18:51 +05:30
|
|
|
self.save()
|