2007-06-23  Alex Roitman  <shura@gramps-project.org>
	* src/plugins/RemoveUnused.py: Rewrite with single-dialog UI.
	* src/plugins/unused.glade: Add new file.
	* src/plugins/Makefile.am: Ship new file.

In po:
	* POTFILES.in: Add new files.


svn: r8646
This commit is contained in:
Alex Roitman 2007-06-24 01:26:48 +00:00
parent 4c34914b6f
commit e8c8245c05
6 changed files with 393 additions and 180 deletions

View File

@ -6,6 +6,11 @@
* src/DisplayTabs/_ButtonTab.py: add jump button
* src/glade/gramps.glade: add jump button
2007-06-23 Alex Roitman <shura@gramps-project.org>
* src/plugins/RemoveUnused.py: Rewrite with single-dialog UI.
* src/plugins/unused.glade: Add new file.
* src/plugins/Makefile.am: Ship new file.
2007-06-23 Brian Matherly <brian@gramps-project.org>
* src/Filters/Rules/Person/__init__.py:
* src/Filters/Rules/Person/Makefile.am:

View File

@ -1,5 +1,5 @@
2007-06-23 Alex Roitman <shura@gramps-project.org>
* POTFILES.in: Add new file.
* POTFILES.in: Add new files.
2007-06-16 Peter Landgren <peter.talken@telia.com>
* sv.po: Update.

View File

@ -648,6 +648,7 @@ src/plugins/vcalendarexport.glade
src/plugins/vcardexport.glade
src/plugins/verify.glade
src/plugins/writeftree.glade
src/plugins/unused.glade
#
# Files to extract from and then merge into
#

View File

@ -88,7 +88,8 @@ GLADEFILES = \
genewebexport.glade\
vcardexport.glade\
vcalendarexport.glade\
checkpoint.glade
checkpoint.glade\
unused.glade
GRAPHICS =

View File

@ -18,7 +18,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id: Check.py 7321 2006-09-13 02:57:45Z dallingham $
# $Id$
"Find unused objects and remove with the user's permission"
@ -62,34 +62,71 @@ from PluginUtils import Tool, register_tool
#
#-------------------------------------------------------------------------
class RemoveUnused(Tool.Tool,ManagedWindow.ManagedWindow,UpdateCallback):
MARK_COL = 0
OBJ_ID_COL = 1
OBJ_NAME_COL = 2
OBJ_TYPE_COL = 3
OBJ_HANDLE_COL = 4
def __init__(self, dbstate, uistate, options_class, name, callback=None):
self.label = _('Remove Unused Objects tool')
self.title = _('Unused Objects')
Tool.Tool.__init__(self, dbstate, options_class, name)
if self.db.readonly:
return
ManagedWindow.ManagedWindow.__init__(self, uistate,[],self.__class__)
UpdateCallback.__init__(self,self.uistate.pulse_progressbar)
self.dbstate = dbstate
self.uistate = uistate
if self.db.readonly:
return
self.tables = {
'events' : {'get_func': self.db.get_event_from_handle,
'remove' : self.db.remove_event,
'editor' : 'EditEvent',
'stock' : 'gramps-event',
'name_ix' : 4},
'sources' : {'get_func': self.db.get_source_from_handle,
'remove' : self.db.remove_source,
'editor' : 'EditSource',
'stock' : 'gramps-source',
'name_ix' : 2},
'places' : {'get_func': self.db.get_place_from_handle,
'remove' : self.db.remove_place,
'editor' : 'EditPlace',
'stock' : 'gramps-place',
'name_ix' : 2},
'media' : {'get_func': self.db.get_object_from_handle,
'remove' : self.db.remove_object,
'editor' : 'EditMedia',
'stock' : 'gramps-media',
'name_ix' : 4},
'repos' : {'get_func': self.db.get_repository_from_handle,
'remove' : self.db.remove_repository,
'editor' : 'EditRepository',
'stock' : 'gramps-repository',
'name_ix' : 3},
}
self.init_gui()
def init_gui(self):
window = gtk.Dialog("%s - GRAMPS" % self.label,
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
def init_gui():
base = os.path.dirname(__file__)
self.glade_file = base + os.sep + "unused.glade"
window.set_border_width(12)
window.set_has_separator(False)
self.top = gtk.glade.XML(self.glade_file,"unused","gramps")
window = self.top.get_widget("unused")
self.set_window(window,self.top.get_widget('title'),self.title)
self.events_box = gtk.CheckButton(_('Remove unused events'))
self.sources_box = gtk.CheckButton(_('Remove unused sources'))
self.places_box = gtk.CheckButton(_('Remove unused places'))
self.media_box = gtk.CheckButton(_('Remove unused media'))
self.repos_box = gtk.CheckButton(_('Remove unused repositories'))
self.events_box = self.top.get_widget('events_box')
self.sources_box = self.top.get_widget('sources_box')
self.places_box = self.top.get_widget('places_box')
self.media_box = self.top.get_widget('media_box')
self.repos_box = self.top.get_widget('repos_box')
self.find_button = self.top.get_widget('find_button')
self.remove_button = self.top.get_widget('remove_button')
self.events_box.set_active(self.options.handler.options_dict['events'])
self.sources_box.set_active(
@ -99,31 +136,73 @@ class RemoveUnused(Tool.Tool,ManagedWindow.ManagedWindow,UpdateCallback):
self.media_box.set_active(self.options.handler.options_dict['media'])
self.repos_box.set_active(self.options.handler.options_dict['repos'])
label = gtk.Label()
window.vbox.add(label)
label.set_padding(12,12)
window.vbox.add(self.events_box)
window.vbox.add(self.sources_box)
window.vbox.add(self.places_box)
window.vbox.add(self.media_box)
window.vbox.add(self.repos_box)
window.vbox.show_all()
self.warn_tree = self.top.get_widget('warn_tree')
self.warn_tree.connect('button_press_event', self.double_click)
self.set_window(window,label,self.label)
self.selection = self.warn_tree.get_selection()
self.mark_button = self.top.get_widget('mark_button')
self.mark_button.connect('clicked',self.mark_clicked)
self.unmark_button = self.top.get_widget('unmark_button')
self.unmark_button.connect('clicked',self.unmark_clicked)
self.invert_button = self.top.get_widget('invert_button')
self.invert_button.connect('clicked',self.invert_clicked)
self.real_model = gtk.ListStore(bool,str,str,str,str)
self.sort_model = gtk.TreeModelSort(self.real_model)
self.warn_tree.set_model(self.sort_model)
self.renderer = gtk.CellRendererText()
self.img_renderer = gtk.CellRendererPixbuf()
self.bool_renderer = gtk.CellRendererToggle()
self.bool_renderer.connect('toggled',self.selection_toggled)
# Add mark column
mark_column = gtk.TreeViewColumn(_('Mark'),self.bool_renderer,
active=RemoveUnused.MARK_COL)
mark_column.set_sort_column_id(RemoveUnused.MARK_COL)
self.warn_tree.append_column(mark_column)
# Add image column
img_column = gtk.TreeViewColumn(None, self.img_renderer )
img_column.set_cell_data_func(self.img_renderer,self.get_image)
self.warn_tree.append_column(img_column)
# Add column with object gramps_id
id_column = gtk.TreeViewColumn(_('ID'), self.renderer,
text=RemoveUnused.OBJ_ID_COL)
id_column.set_sort_column_id(RemoveUnused.OBJ_ID_COL)
self.warn_tree.append_column(id_column)
# Add column with object name
name_column = gtk.TreeViewColumn(_('Name'), self.renderer,
text=RemoveUnused.OBJ_NAME_COL)
name_column.set_sort_column_id(RemoveUnused.OBJ_NAME_COL)
self.warn_tree.append_column(name_column)
self.top.signal_autoconnect({
"destroy_passed_object" : self.close,
"on_remove_button_clicked": self.do_remove,
"on_find_button_clicked" : self.find,
})
self.dc_label = self.top.get_widget('dc_label')
self.sensitive_list = [self.warn_tree,self.mark_button,
self.unmark_button,self.invert_button,
self.dc_label,self.remove_button]
for item in self.sensitive_list:
item.set_sensitive(False)
self.window.connect('response',self.response_handler)
self.show()
def response_handler(self,window,response):
if response == gtk.RESPONSE_ACCEPT:
self.run_tool()
else:
self.close()
def build_menu_names(self,obj):
return (_("Tool settings"),self.label)
return (self.title,None)
def run_tool(self):
def find(self,obj):
self.options.handler.options_dict['events'] = \
int(self.events_box.get_active())
self.options.handler.options_dict['sources'] = \
@ -135,20 +214,19 @@ class RemoveUnused(Tool.Tool,ManagedWindow.ManagedWindow,UpdateCallback):
self.options.handler.options_dict['repos'] = \
int(self.repos_box.get_active())
sr = ShowResults(self.dbstate,self.uistate,self.track)
self.add_results = sr.add_results
for item in self.sensitive_list:
item.set_sensitive(True)
self.uistate.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
self.uistate.progress.show()
self.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
sr.window.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
self.real_model.clear()
self.collect_unused()
self.uistate.progress.hide()
self.uistate.window.window.set_cursor(None)
self.window.window.set_cursor(None)
sr.window.window.set_cursor(None)
self.reset()
# Save options
@ -191,171 +269,51 @@ class RemoveUnused(Tool.Tool,ManagedWindow.ManagedWindow,UpdateCallback):
cursor.close()
self.reset()
#-------------------------------------------------------------------------
#
# Show the results
#
#-------------------------------------------------------------------------
class ShowResults(ManagedWindow.ManagedWindow):
MARK_COL = 0
OBJ_ID_COL = 1
OBJ_NAME_COL = 2
OBJ_TYPE_COL = 3
OBJ_HANDLE_COL = 4
def __init__(self,dbstate,uistate,track):
self.title = _('Unused Objects')
ManagedWindow.ManagedWindow.__init__(self,uistate,track,self.__class__)
self.dbstate = dbstate
self.db = dbstate.db
self.tables = {
'events' : {'get_func': self.db.get_event_from_handle,
'remove' : self.db.remove_event,
'editor' : 'EditEvent',
'stock' : 'gramps-event',
'name_ix' : 4},
'sources' : {'get_func': self.db.get_source_from_handle,
'remove' : self.db.remove_source,
'editor' : 'EditSource',
'stock' : 'gramps-source',
'name_ix' : 2},
'places' : {'get_func': self.db.get_place_from_handle,
'remove' : self.db.remove_place,
'editor' : 'EditPlace',
'stock' : 'gramps-place',
'name_ix' : 2},
'media' : {'get_func': self.db.get_object_from_handle,
'remove' : self.db.remove_object,
'editor' : 'EditMedia',
'stock' : 'gramps-media',
'name_ix' : 4},
'repos' : {'get_func': self.db.get_repository_from_handle,
'remove' : self.db.remove_repository,
'editor' : 'EditRepository',
'stock' : 'gramps-repository',
'name_ix' : 3},
}
base = os.path.dirname(__file__)
self.glade_file = base + os.sep + "verify.glade"
self.top = gtk.glade.XML(self.glade_file,"verify_result","gramps")
window = self.top.get_widget("verify_result")
self.set_window(window,self.top.get_widget('title'),self.title)
self.top.signal_autoconnect({
"destroy_passed_object" : self.close,
})
self.warn_tree = self.top.get_widget('warn_tree')
self.warn_tree.connect('button_press_event', self.double_click)
self.selection = self.warn_tree.get_selection()
self.hide_button = self.top.get_widget('hide_button')
self.hide_button.destroy()
self.mark_button = self.top.get_widget('mark_all')
self.mark_button.connect('clicked',self.mark_clicked)
self.unmark_button = self.top.get_widget('unmark_all')
self.unmark_button.connect('clicked',self.unmark_clicked)
self.invert_button = self.top.get_widget('invert_all')
self.invert_button.connect('clicked',self.invert_clicked)
self.real_model = gtk.ListStore(bool,str,str,str,str)
self.sort_model = gtk.TreeModelSort(self.real_model)
self.warn_tree.set_model(self.sort_model)
self.renderer = gtk.CellRendererText()
self.img_renderer = gtk.CellRendererPixbuf()
self.bool_renderer = gtk.CellRendererToggle()
self.bool_renderer.connect('toggled',self.selection_toggled)
# Add mark column
mark_column = gtk.TreeViewColumn(_('Mark'),self.bool_renderer,
active=ShowResults.MARK_COL)
mark_column.set_sort_column_id(ShowResults.MARK_COL)
self.warn_tree.append_column(mark_column)
# Add image column
img_column = gtk.TreeViewColumn(None, self.img_renderer )
img_column.set_cell_data_func(self.img_renderer,self.get_image)
self.warn_tree.append_column(img_column)
# Add column with object gramps_id
id_column = gtk.TreeViewColumn(_('ID'), self.renderer,
text=ShowResults.OBJ_ID_COL)
id_column.set_sort_column_id(ShowResults.OBJ_ID_COL)
self.warn_tree.append_column(id_column)
# Add column with object name
name_column = gtk.TreeViewColumn(_('Name'), self.renderer,
text=ShowResults.OBJ_NAME_COL)
name_column.set_sort_column_id(ShowResults.OBJ_NAME_COL)
self.warn_tree.append_column(name_column)
# Add a button to remove selected objects
remove_button = self.window.add_button(gtk.STOCK_REMOVE,
gtk.RESPONSE_ACCEPT)
self.window.connect('response',self.response_handler)
self.window.show_all()
self.window_shown = False
def response_handler(self,window,response):
if response == gtk.RESPONSE_ACCEPT:
self.do_remove()
def do_remove(self):
def do_remove(self,obj):
trans = self.db.transaction_begin("",batch=False)
self.db.disable_signals()
for row_num in range(len(self.real_model)-1,-1,-1):
path = (row_num,)
row = self.real_model[path]
if not row[ShowResults.MARK_COL]:
if not row[RemoveUnused.MARK_COL]:
continue
the_type = row[ShowResults.OBJ_TYPE_COL]
handle = row[ShowResults.OBJ_HANDLE_COL]
the_type = row[RemoveUnused.OBJ_TYPE_COL]
handle = row[RemoveUnused.OBJ_HANDLE_COL]
remove_func = self.tables[the_type]['remove']
remove_func(handle, trans)
self.real_model.remove(row.iter)
self.real_model.remove(row.iter)
self.db.transaction_commit(trans, _("Remove unused objects"))
self.db.enable_signals()
self.db.request_rebuild()
self.db.request_rebuild()
def selection_toggled(self,cell,path_string):
sort_path = tuple([int (i) for i in path_string.split(':')])
real_path = self.sort_model.convert_path_to_child_path(sort_path)
row = self.real_model[real_path]
row[ShowResults.MARK_COL] = not row[ShowResults.MARK_COL]
row[RemoveUnused.MARK_COL] = not row[RemoveUnused.MARK_COL]
self.real_model.row_changed(real_path,row.iter)
def mark_clicked(self,mark_button):
for row_num in range(len(self.real_model)):
path = (row_num,)
row = self.real_model[path]
row[ShowResults.MARK_COL] = True
row[RemoveUnused.MARK_COL] = True
def unmark_clicked(self,unmark_button):
for row_num in range(len(self.real_model)):
path = (row_num,)
row = self.real_model[path]
row[ShowResults.MARK_COL] = False
row[RemoveUnused.MARK_COL] = False
def invert_clicked(self,invert_button):
for row_num in range(len(self.real_model)):
path = (row_num,)
row = self.real_model[path]
row[ShowResults.MARK_COL] = not row[ShowResults.MARK_COL]
row[RemoveUnused.MARK_COL] = not row[RemoveUnused.MARK_COL]
def double_click(self,obj,event):
if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1:
@ -365,8 +323,8 @@ class ShowResults(ManagedWindow.ManagedWindow):
sort_path = self.sort_model.get_path(node)
real_path = self.sort_model.convert_path_to_child_path(sort_path)
row = self.real_model[real_path]
the_type = row[ShowResults.OBJ_TYPE_COL]
handle = row[ShowResults.OBJ_HANDLE_COL]
the_type = row[RemoveUnused.OBJ_TYPE_COL]
handle = row[RemoveUnused.OBJ_HANDLE_COL]
self.call_editor(the_type,handle)
def call_editor(self,the_type,handle):
@ -380,7 +338,7 @@ class ShowResults(ManagedWindow.ManagedWindow):
pass
def get_image(self, column, cell, model, iter, user_data=None):
the_type = model.get_value(iter, ShowResults.OBJ_TYPE_COL)
the_type = model.get_value(iter, RemoveUnused.OBJ_TYPE_COL)
the_stock = self.tables[the_type]['stock']
cell.set_property('stock-id', the_stock)
@ -393,13 +351,6 @@ class ShowResults(ManagedWindow.ManagedWindow):
self.real_model.append(row=[False,gramps_id,name,the_type,handle])
if not self.window_shown:
self.show()
self.window_shown = True
def build_menu_names(self,obj):
return (self.title,None)
#------------------------------------------------------------------------
#
#

255
src/plugins/unused.glade Normal file
View File

@ -0,0 +1,255 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--*- mode: xml -*-->
<glade-interface>
<widget class="GtkDialog" id="unused">
<property name="visible">True</property>
<property name="default_width">500</property>
<property name="default_height">300</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="has_separator">False</property>
<signal name="delete_event" handler="on_result_delete_event"/>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox2">
<property name="visible">True</property>
<child>
<widget class="GtkVBox" id="vbox5">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="spacing">6</property>
<child>
<widget class="GtkLabel" id="title">
<property name="visible">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="padding">6</property>
</packing>
</child>
<child>
<widget class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkVButtonBox" id="vbuttonbox1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkCheckButton" id="events_box">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Search for events</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
</child>
<child>
<widget class="GtkCheckButton" id="sources_box">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Search for sources</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="places_box">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Search for places</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="media_box">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Search for media</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">3</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="repos_box">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Search for repositories</property>
<property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
<property name="position">4</property>
</packing>
</child>
</widget>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<widget class="GtkButton" id="find_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">gtk-find</property>
<property name="use_stock">True</property>
<property name="response_id">0</property>
<signal name="clicked" handler="on_find_button_clicked"/>
</widget>
</child>
</widget>
<packing>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow4">
<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>
<child>
<widget class="GtkTreeView" id="warn_tree">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="rules_hint">True</property>
</widget>
</child>
</widget>
<packing>
<property name="padding">6</property>
<property name="position">2</property>
</packing>
</child>
<child>
<widget class="GtkHButtonBox" id="hbuttonbox2">
<property name="visible">True</property>
<property name="spacing">6</property>
<property name="layout_style">GTK_BUTTONBOX_SPREAD</property>
<child>
<widget class="GtkButton" id="mark_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="label" translatable="yes">_Mark all</property>
<property name="use_underline">True</property>
<property name="response_id">0</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="unmark_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="label" translatable="yes">_Unmark all</property>
<property name="use_underline">True</property>
<property name="response_id">0</property>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="invert_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="label" translatable="yes">In_vert marks</property>
<property name="use_underline">True</property>
<property name="response_id">0</property>
</widget>
<packing>
<property name="position">2</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="dc_label">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Double-click on a row to view/edit data&lt;/b&gt;</property>
<property name="use_markup">True</property>
</widget>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">4</property>
</packing>
</child>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area2">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="remove_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">gtk-remove</property>
<property name="use_stock">True</property>
<property name="response_id">-3</property>
<signal name="clicked" handler="on_remove_button_clicked"/>
</widget>
</child>
<child>
<widget class="GtkButton" id="closebutton1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="response_id">-7</property>
<signal name="clicked" handler="destroy_passed_object"/>
</widget>
<packing>
<property name="position">1</property>
</packing>
</child>
</widget>
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface>