* src/DataViews/_MyGrampsView.py: added tooltips, cleanup, menu work

* src/plugins/DefaultGadgets.py: fine tuning
	* src/glade/gramps.glade: added tooltips

2007-12-26  Douglas S. Blank  <dblank@cs.brynmawr.edu>


svn: r9596
This commit is contained in:
Doug Blank 2007-12-26 23:14:13 +00:00
parent 58ba8aeac3
commit 76cff3a349
4 changed files with 151 additions and 82 deletions

View File

@ -1,3 +1,8 @@
2007-12-26 Douglas S. Blank <dblank@cs.brynmawr.edu>
* src/DataViews/_MyGrampsView.py: added tooltips, cleanup, menu work
* src/plugins/DefaultGadgets.py: fine tuning
* src/glade/gramps.glade: added tooltips
2007-12-26 Douglas S. Blank <dblank@cs.brynmawr.edu>
* src/DataViews/_MyGrampsView.py: saves on quit only, load/save api

View File

@ -41,7 +41,7 @@ import ManagedWindow
import ConfigParser
import Utils
AVAILABLE_GADGETS = []
AVAILABLE_GADGETS = {}
GADGET_FILENAME = os.path.join(const.HOME_DIR,"gadgets.ini")
NL = "\n"
@ -49,39 +49,54 @@ debug = False
def register_gadget(data_dict):
global AVAILABLE_GADGETS
base_opts = {"state":"maximized",
base_opts = {"name":"Unnamed Gadget",
"state":"maximized",
"column": -1, "row": -1}
base_opts.update(data_dict)
AVAILABLE_GADGETS.append(base_opts)
AVAILABLE_GADGETS[base_opts["name"]] = base_opts
def register(**data):
if "type" in data:
if data["type"].lower() == "gadget":
register_gadget(data)
else:
print ("Unknown plugin type: '%s'" % data["type"])
else:
print ("Plugin did not define type.")
def get_gadget_opts(name, opts):
for data in AVAILABLE_GADGETS:
if data.get("name", None) == name:
my_data = data.copy()
my_data.update(opts)
return my_data
return {}
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 {}
def get_gadget_options_by_name(name):
if debug: print "name:", name
for opts in AVAILABLE_GADGETS:
gname = opts.get("name", None)
if gname == name:
return opts.copy()
return None
if name in AVAILABLE_GADGETS:
return AVAILABLE_GADGETS[name].copy()
else:
print ("Unknown gadget name: '%s'" % name)
return None
def make_requested_gadget(viewpage, name, opts, dbstate, uistate):
for data in AVAILABLE_GADGETS:
if data.get("name", None) == name:
gui = GuiGadget(viewpage, dbstate, uistate, **opts)
if opts.get("content", None):
opts["content"](gui)
return gui
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()
gui.tooltips.set_tip(gui.textview, msg)
return gui
return None
class LinkTag(gtk.TextTag):
@ -136,6 +151,7 @@ class Gadget(object):
self._need_to_update = False
self._tags = []
self.data = {}
self.tooltip = None
self.link_cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
self.standard_cursor = gtk.gdk.Cursor(gtk.gdk.XTERM)
# links to each other:
@ -151,6 +167,19 @@ class Gadget(object):
self.gui.textview.connect('motion-notify-event',
self.on_motion)
def init(self): # once, constructor
pass
def main(self): # once per db open
pass
def background(self): # return false finishes
"""
Generator which will be run in the background.
"""
if debug: print "%s dummy" % self.gui.title
yield False
def on_load(self):
"""
Gadgets should override this to take care of loading previously
@ -169,22 +198,39 @@ class Gadget(object):
def active_changed(self, handle):
pass
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()
def db_changed(self):
if debug: print "%s is connecting" % self.gui.title
pass
def init(self): # once, constructor
pass
def link(self, text, data):
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()
self._tags.append((LinkTag(buffer),data))
buffer.apply_tag(self._tags[-1][0], start, end)
def main(self): # once per db open
pass
def insert_text(self, text):
self.gui.buffer.insert_at_cursor(text)
def clear_text(self):
self.gui.buffer.set_text('')
def set_text(self, text):
self.gui.buffer.set_text(text)
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)
def update(self, *handles):
self.main()
@ -197,13 +243,6 @@ class Gadget(object):
self._idle_id = gobject.idle_add(self._updater,
priority=gobject.PRIORITY_LOW)
def background(self): # return false finishes
"""
Generator which will be run in the background.
"""
if debug: print "%s dummy" % self.gui.title
yield False
def interrupt(self):
"""
Force the generator to stop running.
@ -213,6 +252,13 @@ class Gadget(object):
gobject.source_remove(self._idle_id)
self._idle_id = 0
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()
def _updater(self):
"""
Runs the generator.
@ -235,12 +281,6 @@ class Gadget(object):
self._idle_id = 0
return False
def append_text(self, text):
end = self.gui.buffer.get_end_iter()
mark = self.gui.buffer.create_mark(None, end, True)
self.gui.buffer.insert(end, text)
self.gui.textview.scroll_to_mark(mark, 0.0, True, 0, 0)
def on_motion(self, view, event):
buffer_location = view.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT,
int(event.x),
@ -286,24 +326,6 @@ class Gadget(object):
return True # handled event
return False # did not handle event
def link(self, text, data):
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()
self._tags.append((LinkTag(buffer),data))
buffer.apply_tag(self._tags[-1][0], start, end)
def insert_text(self, text):
self.gui.buffer.insert_at_cursor(text)
def clear_text(self):
self.gui.buffer.set_text('')
def set_text(self, text):
self.gui.buffer.set_text(text)
def logical_true(value):
return value in ["True", True, 1, "1"]
@ -365,6 +387,7 @@ class GuiGadget:
def detach(self):
# hide buttons:
self.set_state("maximized")
self.gvclose.hide()
self.gvstate.hide()
self.gvproperties.hide()
@ -471,6 +494,9 @@ class MyGrampsView(PageView.PageView):
user_gadgets = self.load_gadgets()
# build the GUI:
frame = MyScrolledWindow()
msg = _("Right click to add gadgets")
self.tooltips = gtk.Tooltips()
self.tooltips.set_tip(frame, msg)
frame.viewpage = self
frame.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.hbox = gtk.HBox(homogeneous=True)
@ -558,7 +584,7 @@ class MyGrampsView(PageView.PageView):
cnt += 1
def load_gadgets(self):
self.column_count = 1
self.column_count = 2 # default for new user
retval = []
filename = GADGET_FILENAME
if filename and os.path.exists(filename):
@ -577,9 +603,9 @@ class MyGrampsView(PageView.PageView):
retval.append((data["name"], data)) # name, opts
else:
# give defaults as currently known
for item in AVAILABLE_GADGETS:
if item["name"] == "Welcome Gadget":
retval.append(("Welcome Gadget", item))
for name in ["Top Surnames Gadget", "Welcome Gadget"]:
if name in AVAILABLE_GADGETS:
retval.append((name, AVAILABLE_GADGETS[name]))
return retval
def save(self, *args):
@ -756,6 +782,15 @@ class MyGrampsView(PageView.PageView):
def ui_definition(self):
return """
<ui>
<menubar name="MenuBar">
<menu action="ViewMenu">
<menuitem action="AddGadget"/>
<separator/>
<menuitem action="Columns1"/>
<menuitem action="Columns2"/>
<menuitem action="Columns3"/>
</menu>
</menubar>
<popup name="Popup">
<menuitem action="AddGadget"/>
<separator/>
@ -767,20 +802,37 @@ class MyGrampsView(PageView.PageView):
"""
def _button_press(self, obj, event):
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 1:
self._popup_xy = None
menu = self.uistate.uimanager.get_widget('/ViewMenu')
ag_menu = self.uistate.uimanager.get_widget('/ViewMenu/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('/ViewMenu/AddGadget').set_submenu(qr_menu)
#if menu:
# menu.popup(None, None, None, event.button, event.time)
return True
elif event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
self._popup_xy = (event.x, event.y)
menu = self.uistate.uimanager.get_widget('/Popup')
qr_menu = self.uistate.uimanager.get_widget('/Popup/AddGadget').get_submenu()
if qr_menu == None:
qr_menu = gtk.Menu()
names = []
for opts in AVAILABLE_GADGETS:
names.append(opts["name"])
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)
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)
if menu:
menu.popup(None, None, None, event.button, event.time)
return True

View File

@ -16265,6 +16265,7 @@ Very High</property>
<child>
<widget class="GtkButton" id="gvproperties">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Drag to move; click to detach</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
@ -16291,6 +16292,7 @@ Very High</property>
<child>
<widget class="GtkButton" id="gvstate">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Click to expand/collapse</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
@ -16317,6 +16319,7 @@ Very High</property>
<child>
<widget class="GtkButton" id="gvclose">
<property name="visible">True</property>
<property name="tooltip" translatable="yes">Click to close</property>
<property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>

View File

@ -93,6 +93,9 @@ class LogGadget(Gadget):
self.append_text("\n")
class TopSurnamesGadget(Gadget):
def init(self):
self.set_text("No Family Tree loaded.")
def main(self):
self.set_text("Processing...\n")
@ -105,7 +108,7 @@ class TopSurnamesGadget(Gadget):
if person:
surname = person.get_primary_name().get_surname().strip()
surnames[surname] = surnames.get(surname, 0) + 1
if cnt % 500 == 0:
if cnt % 350 == 0:
yield True
cnt += 1
total_people = cnt
@ -115,7 +118,7 @@ class TopSurnamesGadget(Gadget):
for surname in surnames:
surname_sort.append( (surnames[surname], surname) )
total += surnames[surname]
if cnt % 500 == 0:
if cnt % 350 == 0:
yield True
cnt += 1
total_surnames = cnt
@ -140,6 +143,9 @@ class StatsGadget(Gadget):
self.dbstate.db.connect('family-add', self.update)
self.dbstate.db.connect('family-delete', self.update)
def init(self):
self.set_text("No Family Tree loaded.")
def background(self):
self.set_text("Processing...")
database = self.dbstate.db
@ -180,7 +186,8 @@ class StatsGadget(Gadget):
name = person.get_primary_name()
if name.get_first_name() == "" or name.get_surname() == "":
incomp_names = incomp_names + 1
if (not person.get_main_parents_family_handle()) and (not len(person.get_family_handle_list())):
if ((not person.get_main_parents_family_handle()) and
(not len(person.get_family_handle_list()))):
disconnected = disconnected + 1
birth_ref = person.get_birth_ref()
if birth_ref:
@ -197,7 +204,7 @@ class StatsGadget(Gadget):
unknowns += 1
if name.get_surname() not in namelist:
namelist.append(name.get_surname())
if cnt % 500 == 0:
if cnt % 200 == 0:
yield True
cnt += 1
@ -396,6 +403,7 @@ register(type="gadget",
register(type="gadget",
name="Stats Gadget",
height=230,
expand=True,
content = StatsGadget,
title="Stats",
)
@ -424,6 +432,7 @@ register(type="gadget",
register(type="gadget",
name="TODO Gadget",
height=300,
expand=True,
content = TODOGadget,
title="TODO List",
)