2005-03-15 Richard Taylor <rjt-gramps@thegrindstone.me.uk>

* src/Makefile.am : Added TreeTip.py to list of installed modules.
	* src/TreeTip.py: New module that implements tooltips on TreeView rows.
	* src/plugins/Makefile.am: Added ScratchPad.py and scratchpad.glade.
	* src/plugins/ScratchPad.py: New module to implement a scratch pad for
	temporary storage of drag and drop objects.
	* src/plugins/scratchpad.glade: New glade file for ScratchPad window.


svn: r4184
This commit is contained in:
Richard Taylor 2005-03-15 13:48:18 +00:00
parent 840c8ec4a9
commit d85c655092
6 changed files with 862 additions and 1 deletions

View File

@ -1,3 +1,11 @@
2005-03-15 Richard Taylor <rjt-gramps@thegrindstone.me.uk>
* src/Makefile.am : Added TreeTip.py to list of installed modules.
* src/TreeTip.py: New module that implements tooltips on TreeView rows.
* src/plugins/Makefile.am: Added ScratchPad.py and scratchpad.glade.
* src/plugins/ScratchPad.py: New module to implement a scratch pad for
temporary storage of drag and drop objects.
* src/plugins/scratchpad.glade: New glade file for ScratchPad window.
2005-03-15 Martin Hawlisch <Martin.Hawlisch@gmx.de>
* src/GenericFilter.py (FullTextSearch): Added new filter thad provides
a full-text search thru (nearly) all attributes and linked objexts of a person.

View File

@ -101,6 +101,7 @@ gdir_PYTHON = \
TarFile.py\
TipOfDay.py\
TransTable.py\
TreeTips.py\
UrlEdit.py\
Utils.py\
Witness.py\

248
gramps2/src/TreeTips.py Normal file
View File

@ -0,0 +1,248 @@
# File: treetips.py
# Author: Toshio Kuratomi <toshio@tiki-lounge.com>
# Date: 6 April, 2004
# Copyright: Toshio Kuratomi
# License: GPL
# Id: $Id$
"""A tooltip class for TreeViews
"""
__revision__ = "$Rev$"
#
# Support for text markup added: March 05 - rjt-gramps <at> thegrindstone.me.uk
#
import gtk
import gobject
class TreeTips(gtk.Widget):
''' A tooltips widget specialized to work with gtk.TreeView's.
TreeTips associates a column in a TreeStore with tooltips that will be
displayed when the mouse is over the row the column is for. Each row can
have one treetip.
'''
__gproperties__ = {
'tip_window' : (gobject.TYPE_PYOBJECT,
'The window that the tooltip is displayed in.',
'The window that the tooltip is displayed in.',
gobject.PARAM_READABLE),
'tip_label' : (gobject.TYPE_PYOBJECT,
'The label that displays the tooltip text.',
'The label that displays the tooltip text.',
gobject.PARAM_READABLE),
'active_tips_data' : (gobject.TYPE_PYOBJECT,
'The data associated with the active tooltip.',
'The data associated with the active tooltip.',
gobject.PARAM_READABLE),
'delay' : (gobject.TYPE_INT,
'MSecs before displaying the tooltip.',
'The delay between the mouse pausing over the widget and the display of the tooltip in msec.',
0, 60000, 500,
gobject.PARAM_READWRITE),
'enabled' : (gobject.TYPE_BOOLEAN,
'If TRUE the tooltips are enabled',
'If TRUE the tooltips are enabled',
True,
gobject.PARAM_READABLE),
'view' : (gobject.TYPE_PYOBJECT,
'gtk.TreeView that we get our data from.',
'The tip data comes from a column in a gtk.TreeView.',
gobject.PARAM_READWRITE),
'column' : (gobject.TYPE_INT,
'Column from the gtk.TreeView that holds tip data.',
'The tip data for each row is held by a column in the row. This specifies which column that data is in.',
0, 32000, 0,
gobject.PARAM_READWRITE),
'markup_enabled' : (gobject.TYPE_BOOLEAN,
'If TRUE the tooltips are in Pango Markup',
'If TRUE the tooltips are in Pango Markup',
False,
gobject.PARAM_READWRITE),
}
def __init__(self, treeview=None, column=None, markup_enabled=False):
'''Create a new TreeTips Group.
:Parameters:
treeview : gtk.TreeView === Treeview for which the tips display,
default is None.
column : integer === Column id in the Treemodel holding the treetip
text, default is None.
markup_enabled : bool === If True the tooltips are in Pango Markup,
if False the tooltips are in plain text.
'''
if treeview:
try:
treeview.connect('leave-notify-event', self.__tree_leave_notify)
treeview.connect('motion-notify-event', self.__tree_motion_notify)
except (AttributeError, TypeError):
raise TypeError, ('The value of view must be an object that'
'implements leave-notify-event and motion-notify-event '
'gsignals such as gtk.TreeStore.')
gobject.GObject.__init__(self)
self.view = treeview or None
self.delay = 500
self.enabled = True
self.column = column or 0
self.markup_enabled = markup_enabled
self.tip_window = gtk.Window(gtk.WINDOW_POPUP)
self.tip_window.set_app_paintable(True)
self.tip_window.set_border_width(4)
self.tip_window.connect('expose-event', self.__paint_window)
self.tip_label = gtk.Label('')
self.tip_label.set_line_wrap(True)
self.tip_label.set_alignment(0.5, 0.5)
self.active_tips_data = ''
self.tip_window.add(self.tip_label)
self.unique = 1 # Unique number used for timeouts
self.timeoutID = 0
self.path = None
self.screenWidth = gtk.gdk.screen_width()
self.screenHeight = gtk.gdk.screen_height()
def enable(self):
'''Enable showing of tooltips'''
self.enabled = True
def disable(self):
'''Disable showing tooltips'''
self.enabled = False
def do_get_property(self, prop):
'''Return the gproperty's value.'''
if prop.name == 'delay':
return self.delay
elif prop.name == 'enabled':
return self.enabled
elif prop.name == 'view':
return self.view
elif prop.name == 'column':
return self.column
elif prop.name == 'active-tips-data':
return self.active_tips_data
elif prop.name == 'tip-label':
return self.tip_label
elif prop.name == 'tip-window':
return self.tip_window
elif prop.name == 'markup_enabled':
return self.markup_enabled
else:
raise AttributeError, 'unknown property %s' % prop.name
def do_set_property(self, prop, value):
'''Set the property of writable properties.
'''
if prop.name == 'delay':
self.delay = value
elif prop.name == 'view':
try:
value.connect('leave-notify-event', self.__tree_leave_notify)
value.connect('motion-notify-event', self.__tree_motion_notify)
except (AttributeError, TypeError):
raise TypeError, ('The value of view must be an object that'
'implements leave-notify-event and motion-notify-event '
'gsignals')
self.view = value
elif prop.name == 'column':
self.column = value
elif prop.name == 'markup_enabled':
self.markup_enabled = value
else:
raise AttributeError, 'unknown or read only property %s' % prop.name
def __paint_window(self, window, event):
window.style.paint_flat_box(window.window, gtk.STATE_NORMAL,
gtk.SHADOW_OUT, None, window,
'tooltip', 0, 0, -1, -1)
def __tree_leave_notify(self, tree, event):
'''Hide tooltips when we leave the tree.'''
self.timeoutID = 0
self.path = None
self.tip_window.hide()
def __tree_motion_notify(self, tree, event):
'''Decide which tooltip to display when we move within the tree.'''
if not self.enabled:
return
self.tip_window.hide()
self.path = None
self.unique += 1
self.timeoutID = self.unique
gobject.timeout_add(self.delay, self.__treetip_show, tree,
int(event.x), int(event.y), self.timeoutID)
def __treetip_show(self, tree, xEvent, yEvent, ID):
'''Show the treetip window.'''
if self.timeoutID != ID:
return False
pathReturn = tree.get_path_at_pos(xEvent, yEvent)
model = tree.get_model()
if pathReturn == None:
self.path = None
elif self.path != pathReturn[0]:
self.path = pathReturn[0]
rowIter = model.get_iter(self.path)
text = model.get_value(rowIter, self.column)
self.active_tips_data = text
if not text:
if self.markup_enabled:
self.tip_label.set_markup('')
else:
self.tip_label.set_text('')
return False
if self.markup_enabled:
self.tip_label.set_markup(text)
else:
self.tip_label.set_text(text)
x, y = self.tip_label.size_request()
self.tip_window.resize(x, y)
windowWidth, windowHeight = self.tip_window.get_size()
cellInfo = tree.get_cell_area(self.path, pathReturn[1])
x, y = self.__compute_tooltip_position(cellInfo, windowWidth, windowHeight)
self.tip_window.move(int(x), int(y))
self.tip_window.show_all()
return False
def __compute_tooltip_position(self, cellInfo, popupWidth, popupHeight):
'''Figures out where the tooltip should be placed on the page::
[p] = pointer
x = [p]
+---------+
(half on each side)
y = [p]
+------------+
|____________|
If it fits else:
+------------+
|____________|
[p]
'''
xOrigin, yOrigin = self.view.get_bin_window().get_origin()
x = xOrigin + cellInfo.x + cellInfo.width/2 - popupWidth/2
if x < 0:
x = 0
elif x + popupWidth > self.screenWidth:
x = self.screenWidth - popupWidth
y = yOrigin + cellInfo.y + cellInfo.height + 3
if y + popupHeight > self.screenHeight:
y = yOrigin + cellInfo.y - 3 - popupHeight
if y < 0:
y = 0
return x, y
gobject.type_register(TreeTips)

View File

@ -35,6 +35,7 @@ pkgdata_PYTHON = \
ReadPkg.py\
RelCalc.py\
ReorderIds.py\
ScratchPad.py\
SoundGen.py\
StatisticsChart.py\
Summary.py\
@ -80,7 +81,8 @@ GLADEFILES = \
leak.glade\
book.glade\
writeftree.glade\
genewebexport.glade
genewebexport.glade\
scratchpad.glade
dist_pkgdata_DATA = $(GLADEFILES)

View File

@ -0,0 +1,489 @@
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2004 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modiy
# 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 pickle
import os
from xml.sax.saxutils import escape
#-------------------------------------------------------------------------
#
# GTK/Gnome modules
#
#-------------------------------------------------------------------------
import gtk
import gtk.gdk
import gtk.glade
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
import const
import Utils
import ListModel
import TreeTips
from gettext import gettext as _
from gtk.gdk import ACTION_COPY, BUTTON1_MASK
#-------------------------------------------------------------------------
#
# Globals
#
#-------------------------------------------------------------------------
text_targets = ['text/plain',
'TEXT',
'STRING',
'COMPOUND_TEXT',
'UTF8_STRING']
gramps_targets = ['url',
'pevent',
'pattr',
'paddr',
'srcref']
pycode_tgts = [('url', 0, 0),
('pevent', 0, 1),
('pattr', 0, 2),
('paddr', 0, 3),
('srcref', 0, 4),
('text/plain',0,0),
('TEXT', 0, 1),
('STRING', 0, 2),
('COMPOUND_TEXT', 0, 3),
('UTF8_STRING', 0, 4)]
TEXT_TARGET = 'TEXT'
target_map = {'url':('url', 0, 0),
'pevent': ('pevent', 0, 1),
'pattr': ('pattr', 0, 2),
'paddr': ('paddr', 0, 3),
'srcref': ('srcref', 0, 4),
TEXT_TARGET: ('TEXT', 0, 1)}
#-------------------------------------------------------------------------
#
# ScatchPadWindow class
#
#-------------------------------------------------------------------------
class ScratchPadWindow:
"""
The ScratchPad provides a temporary area to hold objects that can
be reused accross multiple Person records. The pad provides a window
onto which objects can be dropped and then dragged into new Person
dialogs. The objects are stored as the pickles that are built by the
origininating widget. The objects are only unpickled in order to
provide the text in the display.
No attempt is made to ensure that any references contained within
the pickles are valid. Because the pad extends the life time of drag
and drop objects, it is possible that references that were valid
when an object is copied to the pad are invalid by the time they
are dragged to a new Person. For this reason, using the pad places
a responsibility on all '_drag_data_received' methods to check the
references of objects before attempting to use them.
"""
def __init__(self,database,parent):
"""Initializes the ScratchPad class, and displays the window"""
self.db = database
self.parent = parent
self.win_key = self
self.olist = []
self.otitles = [(_('Type'),-1,150),
(_('Title'),-1,150),
(_('Value'),-1,150),
('',-1,0)] # To hold the tooltip text
base = os.path.dirname(__file__)
self.glade_file = "%s/%s" % (base,"scratchpad.glade")
self.top = gtk.glade.XML(self.glade_file,"scratchPad","gramps")
self.window = self.top.get_widget("scratchPad")
self.window.set_icon(self.parent.topWindow.get_icon())
self.object_list = self.top.get_widget('objectlist')
self.otree = ListModel.ListModel(self.object_list,self.otitles,
self.on_object_select_row,
self.on_update_object_clicked)
self.treetips = TreeTips.TreeTips(self.object_list,3,True)
self.top.signal_autoconnect({
"on_close_scratchpad" : self.on_close_scratchpad,
"on_clear_clicked": self.on_clear_clicked,
"on_clear_all_clicked": self.on_clear_all_clicked,
"on_objectlist_delete_event": self.on_delete_event,
"on_scratchPad_delete_event": self.on_delete_event
})
self.object_list.drag_dest_set(gtk.DEST_DEFAULT_ALL, pycode_tgts,
ACTION_COPY)
self.object_list.connect('drag_data_get', self.object_drag_data_get)
self.object_list.connect('drag_begin', self.object_drag_begin)
self.object_list.connect('drag_data_received',
self.object_drag_data_received)
self.add_itself_to_menu()
self.window.show()
def on_delete_event(self,obj,b):
self.remove_itself_from_menu()
def add_itself_to_menu(self):
"""Add the ScratchPad window to the list of windows in the
main GRAMPS interface. If this is the first instance to be
created a submenu is created, if it is not the first instance
then an entry is created in the existing sub menu."""
sub_menu_label = _("Scratch Pad Tool")
instance_number_key = "scratch_pad_instance_number"
self.parent.child_windows[self.win_key] = self
# First check to see if the Scratch Pad sub menu already exists.
# The MenuItems contain a list of child widgets, the first one
# should be the AccelLabel so we can check the label text on
# that one.
sub_menu_list = [ menu for menu in self.parent.winsmenu.get_children() if \
menu.get_children()[0].get_label() == sub_menu_label ]
if len(sub_menu_list) > 0:
# This list should always be of length 0 or 1 but in the unlikely
# situation that it is greater than 1 it will still be safe to use
# the first.
self.parent_menu_item = sub_menu_list[0]
else:
# There is no existing instances so we must create the submenu.
self.parent_menu_item = gtk.MenuItem(sub_menu_label)
self.parent_menu_item.set_submenu(gtk.Menu())
self.parent_menu_item.show()
self.parent.winsmenu.append(self.parent_menu_item)
# Get a handle to the submenu and remember it so that
# remove_itself_from_menu can delete it later.
self.winsmenu = self.parent_menu_item.get_submenu()
# Get the first available instance number. The instance number
# is stored in the data item store of the menu item so we can
# read it with get_data.
num = 1
existing_instances = [ menu_item.get_data(instance_number_key) \
for menu_item in self.winsmenu.get_children() ]
if len(existing_instances) > 0:
# Calculate the first available instance number.
existing_instances.sort()
for instance_num in existing_instances:
if instance_num != num:
break
else:
num += 1
# Create the instance menuitem with the instance number in the
# label.
instance_title = _('Scratch Pad - %d') % (num,)
self.menu_item = gtk.MenuItem(instance_title)
self.menu_item.set_data(instance_number_key,num)
self.menu_item.connect("activate",self.present)
self.menu_item.show()
# Set the window title to the same as the menu label.
self.window.set_title(instance_title)
# Add the item to the submenu.
self.winsmenu.append(self.menu_item)
def remove_itself_from_menu(self):
"""Remove the instance of the pad from the Window menu in the
main GRAMPS window. If this is the last pad then remove the
ScratchPad sub menu as well."""
del self.parent.child_windows[self.win_key]
self.menu_item.destroy()
if len(self.winsmenu.get_children()) == 0:
self.winsmenu.destroy()
self.parent_menu_item.destroy()
def present(self,obj):
self.window.present()
def on_close_scratchpad(self,obj):
self.remove_itself_from_menu()
self.window.destroy()
def on_clear_clicked(self,obj):
"""Deletes the selected object from the object list"""
store,node = self.otree.get_selected()
if node:
self.olist.remove(self.otree.get_object(node))
self.redraw_object_list()
def on_clear_all_clicked(self,obj):
self.olist = []
self.redraw_object_list()
def on_object_select_row(self,obj):
global target_map
global TEXT_TARGET
o = self.otree.get_selected_objects()
if len(o):
bits_per = 8; # we're going to pass a string
obj_targets = o[0]['targets']
# union with gramps_types
if len([target for target \
in obj_targets if target in gramps_targets]) > 0:
exec 'data = %s' % o[0]['data']
exec 'mytype = "%s"' % data[0]
target = target_map[mytype]
# Union with text targets
elif len([target for target \
in obj_targets if target in text_targets]) > 0:
target = target_map[TEXT_TARGET]
self.object_list.drag_source_unset()
self.object_list.drag_source_set(BUTTON1_MASK, [target], ACTION_COPY)
def on_update_object_clicked(self, obj):
pass
def object_drag_begin(self, context, a):
return
def object_drag_data_get(self,widget, context, sel_data, info, time):
global gramps_targets
global text_targets
o = self.otree.get_selected_objects()
if len(o):
bits_per = 8; # we're going to pass a string
obj_targets = o[0]['targets']
# union with gramps_types
if len([target for target \
in obj_targets if target in gramps_targets]) > 0:
exec 'data = %s' % o[0]['data']
exec 'mytype = "%s"' % data[0]
exec 'person = "%s"' % data[1]
pickled = data[2]
send_data = str((mytype,person,pickled));
# Union with text targets
elif len([target for target \
in obj_targets if target in text_targets]) > 0:
send_data = str(o[0]['data'])
sel_data.set(sel_data.target, bits_per, send_data)
def object_drag_data_received(self,widget,context,x,y,sel_data,info,time):
row = self.otree.get_row_at(x,y)
if sel_data and sel_data.data:
self.olist.insert(row,{'targets':context.targets,
'data':sel_data.data})
self.redraw_object_list()
def redraw_object_list(self):
"""Redraws the address list"""
global gramps_targets
global text_targets
self.otree.clear()
for obj in self.olist:
obj_targets = obj['targets']
# union with gramps_types
if len([target for target \
in obj_targets if target in gramps_targets]) > 0:
exec 'unpack_data = %s' % obj['data']
exec 'mytype = "%s"' % unpack_data[0]
data = pickle.loads(unpack_data[2]);
node = None
if mytype == 'paddr':
location = "%s %s %s %s" % (data.get_street(),data.get_city(),
data.get_state(),data.get_country())
node = self.otree.add([_("Address"),
data.get_date(),
location,
self.generate_addr_tooltip(data)],obj)
elif mytype == 'pevent':
node = self.otree.add([_("Event"),
const.display_pevent(data.get_name()),
data.get_description(),
self.generate_event_tooltip(data)],obj)
elif mytype == 'url':
node = self.otree.add([_("Url"),
data.get_path(),
data.get_description(),
self.generate_url_tooltip(data)],obj)
elif mytype == 'pattr':
node = self.otree.add([_("Attribute"),
const.display_pattr(data.get_type()),
data.get_value(),
self.generate_pattr_tooltip(data)],obj)
elif mytype == 'srcref':
base = self.db.get_source_from_handle(data.get_base_handle())
node = self.otree.add([_("SourceRef"),
base.get_title(),
data.get_text(),
self.generate_srcref_tooltip(data)],obj)
# Union with text targets
elif len([target for target \
in obj_targets if target in text_targets]) > 0:
node = self.otree.add([_("Text"),
"",
obj['data'],
self.generate_text_tooltip(obj['data'])],obj)
if self.olist:
self.otree.select_row(0)
def generate_addr_tooltip(self,addr):
global escape
return "<big><b>%s</b></big>\n"\
"<b>%s:</b>\t%s\n"\
"<b>%s:</b>\n"\
"\t%s\n"\
"\t%s\n"\
"\t%s\n"\
"\t%s" % (_("Address"),
_("Date"),
escape(addr.get_date()),
_("Location"),
escape(addr.get_street()),
escape(addr.get_city()),
escape(addr.get_state()),
escape(addr.get_country()))
def generate_event_tooltip(self,event):
global escape
return "<big><b>%s</b></big>\n"\
"<b>%s:</b>\t%s\n"\
"<b>%s:</b>\t%s\n" % (_("Event"),
_("Name"),
escape(const.display_pevent(event.get_name())),
_("Description"),
escape(event.get_description()))
def generate_url_tooltip(self,url):
global escape
return "<big><b>%s</b></big>\n"\
"<b>%s:</b>\t%s\n"\
"<b>%s:</b>\t%s" % (_("Url"),
_("Path"),
escape(url.get_path()),
_("Description"),
escape(url.get_description()))
def generate_pattr_tooltip(self,pattr):
global escape
return "<big><b>%s</b></big>\n"\
"<b>%s:</b>\t%s\n"\
"<b>%s:</b>\t%s" % (_("Attribute"),
_("Type"),
escape(const.display_pattr(pattr.get_type())),
_("Value"),
escape(pattr.get_value()))
def generate_srcref_tooltip(self,srcref):
global escape
base = self.db.get_source_from_handle(srcref.get_base_handle())
return "<big><b>%s</b></big>\n"\
"<b>%s:</b>\t%s\n"\
"<b>%s:</b>\t%s" % (_("SourceRef"),
_("Title"),
escape(base.get_title()),
_("Text"),
escape(srcref.get_text()))
def generate_text_tooltip(self,text):
global escape
return "<big><b>%s</b></big>\n"\
"%s" % (_("Text"),
escape(text))
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def ScratchPad(database,person,callback,parent=None):
ScratchPadWindow(database,parent)
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
from PluginMgr import register_tool
register_tool(
ScratchPad,
_("Scratch Pad"),
category=_("Utilities"),
description=_("The Scratch Pad provides a tempory note pad to store "
"objects for easy reuse.")
)

View File

@ -0,0 +1,113 @@
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
<glade-interface>
<requires lib="gnome"/>
<widget class="GtkWindow" id="scratchPad">
<property name="visible">True</property>
<property name="title" translatable="yes">Scratch Pad</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="default_width">400</property>
<property name="default_height">200</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<signal name="delete_event" handler="on_scratchPad_delete_event" object="ScratchPad" last_modification_time="Fri, 11 Mar 2005 11:35:07 GMT"/>
<child>
<widget class="GtkVBox" id="vbx_scratchpad">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow85">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
<child>
<widget class="GtkTreeView" id="objectlist">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">True</property>
<property name="rules_hint">False</property>
<property name="reorderable">False</property>
<property name="enable_search">True</property>
<signal name="delete_event" handler="on_objectlist_delete_event" object="ScratchPad" last_modification_time="Wed, 09 Mar 2005 13:48:09 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox37">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
<property name="spacing">0</property>
<child>
<widget class="GtkButton" id="btn_clear_all">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">Clear_All</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_clear_all_clicked" object="ScratchPad" last_modification_time="Tue, 08 Mar 2005 15:26:49 GMT"/>
</widget>
</child>
<child>
<widget class="GtkButton" id="btn_clear">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label" translatable="yes">C_lear</property>
<property name="use_underline">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_clear_clicked" object="ScratchPad" last_modification_time="Tue, 08 Mar 2005 15:26:40 GMT"/>
</widget>
</child>
<child>
<widget class="GtkButton" id="btn_close">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<signal name="clicked" handler="on_close_scratchpad" object="ScratchPad" last_modification_time="Tue, 08 Mar 2005 15:26:57 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="padding">3</property>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>