Bug 2616. Fixes for memory leaks in event editor

svn: r12116
This commit is contained in:
Gary Burton 2009-02-25 18:18:19 +00:00
parent 99376d8691
commit 2334b8058d
7 changed files with 108 additions and 28 deletions

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# Copyright (C) 2009 Gary Burton
#
# 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
@ -64,6 +65,7 @@ class BackRefList(EmbeddedList):
_('_References'), refmodel)
self._callback = callback
self.model.connect('row-inserted', self.update_label)
self.track_ref_for_deletion("model")
def update_label(self, *obj):
if self.model.count > 0:
@ -99,6 +101,11 @@ class BackRefList(EmbeddedList):
self.add_btn = None
self.del_btn = None
self.track_ref_for_deletion("edit_btn")
self.track_ref_for_deletion("tooltips")
self.track_ref_for_deletion("add_btn")
self.track_ref_for_deletion("del_btn")
def _selection_changed(self, obj=None):
if self.dirty_selection:
return

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2009 Gary Burton
#
# 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
@ -99,6 +100,7 @@ class ButtonTab(GrampsTab):
self.dirty_selection = False
GrampsTab.__init__(self,dbstate, uistate, track, name)
self.tooltips = gtk.Tooltips()
self.track_ref_for_deletion("tooltips")
self.create_buttons(share_button, move_buttons, jump_button)
def create_buttons(self, share_button, move_buttons, jump_button):
@ -112,6 +114,9 @@ class ButtonTab(GrampsTab):
self.add_btn = SimpleButton(gtk.STOCK_ADD, self.add_button_clicked)
self.edit_btn = SimpleButton(gtk.STOCK_EDIT, self.edit_button_clicked)
self.del_btn = SimpleButton(gtk.STOCK_REMOVE, self.del_button_clicked)
self.track_ref_for_deletion("add_btn")
self.track_ref_for_deletion("edit_btn")
self.track_ref_for_deletion("del_btn")
self.tooltips.set_tip(self.add_btn, self._MSG['add'])
self.tooltips.set_tip(self.edit_btn, self._MSG['edit'])
@ -120,6 +125,7 @@ class ButtonTab(GrampsTab):
if share_button:
self.share_btn = SimpleButton(gtk.STOCK_INDEX, self.share_button_clicked)
self.tooltips.set_tip(self.share_btn, self._MSG['share'])
self.track_ref_for_deletion("share_btn")
else:
self.share_btn = None
@ -129,6 +135,8 @@ class ButtonTab(GrampsTab):
self.down_btn = SimpleButton(gtk.STOCK_GO_DOWN,
self.down_button_clicked)
self.tooltips.set_tip(self.down_btn, self._MSG['down'])
self.track_ref_for_deletion("up_btn")
self.track_ref_for_deletion("down_btn")
else:
self.up_btn = None
self.down_btn = None
@ -146,6 +154,7 @@ class ButtonTab(GrampsTab):
if jump_button:
self.jump_btn = SimpleButton(gtk.STOCK_JUMP_TO, self.jump_button_clicked)
self.track_ref_for_deletion("jump_btn")
self.tooltips.set_tip(self.jump_btn, self._MSG['jump'])
else:
self.jump_btn = None

View File

@ -73,6 +73,7 @@ class EmbeddedList(ButtonTab):
# handle the selection
self.selection = self.tree.get_selection()
self.selection.connect('changed', self._selection_changed)
self.track_ref_for_deletion("selection")
# build the columns
self.columns = []
@ -341,6 +342,7 @@ class EmbeddedList(ButtonTab):
self.tree.set_rules_hint(True)
self.tree.connect('button_press_event', self.double_click)
self.tree.connect('key_press_event', self.key_pressed)
self.track_ref_for_deletion("tree")
# create the scrolled window, and attach the treeview
scroll = gtk.ScrolledWindow()
@ -428,6 +430,7 @@ class EmbeddedList(ButtonTab):
column.set_sort_column_id(self._column_names[pair[1]][1])
self.columns.append(column)
self.tree.append_column(column)
self.track_ref_for_deletion("columns")
def rebuild(self):
"""
@ -450,4 +453,3 @@ class EmbeddedList(ButtonTab):
#model and tree are reset, allow _selection_changed again, and force it
self.dirty_selection = False
self._selection_changed()

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2009 Gary Burton
#
# 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
@ -72,8 +73,8 @@ class GalleryTab(ButtonTab):
def __init__(self, dbstate, uistate, track, media_list, update=None):
self.iconlist = gtk.IconView()
ButtonTab.__init__(self, dbstate, uistate, track, _('_Gallery'), True)
self.track_ref_for_deletion("iconlist")
self.media_list = media_list
self.update = update
@ -146,6 +147,7 @@ class GalleryTab(ButtonTab):
def _build_icon_model(self):
self.iconmodel = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING,
object)
self.track_ref_for_deletion("iconmodel")
def _connect_icon_model(self):
self.iconlist.set_model(self.iconmodel)

View File

@ -2,6 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# Copyright (C) 2009 Gary Burton
#
# 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
@ -70,6 +71,7 @@ class GrampsTab(gtk.VBox):
self.uistate = uistate
self.track = track
self.changed = False
self.__refs_for_deletion = []
self._add_db_signal = None
@ -77,7 +79,9 @@ class GrampsTab(gtk.VBox):
# for the label
self.tab_name = name
self.track_ref_for_deletion("tab_name")
self.label_container = self.build_label_widget()
self.track_ref_for_deletion("label_container")
# build the interface
self.share_btn = None
@ -116,7 +120,9 @@ class GrampsTab(gtk.VBox):
name = icon
self.tab_image = func(name, gtk.ICON_SIZE_MENU)
self.track_ref_for_deletion("tab_image")
self.label = gtk.Label(self.tab_name)
self.track_ref_for_deletion("label")
hbox.pack_start(self.tab_image)
hbox.set_spacing(6)
hbox.add(self.label)
@ -213,6 +219,7 @@ class GrampsTab(gtk.VBox):
def set_parent_notebook(self, book):
self.parent_notebook = book
self.track_ref_for_deletion("parent_notebook")
def next_page(self):
if self.parent_notebook:
@ -222,3 +229,19 @@ class GrampsTab(gtk.VBox):
if self.parent_notebook:
self.parent_notebook.prev_page()
def track_ref_for_deletion(self, ref):
"""
Record references of instance variables that need to be removed
from scope so that the class can be garbage collected
"""
if ref not in self.__refs_for_deletion:
self.__refs_for_deletion.append(ref)
def clean_up(self):
"""
Remove any instance variables from scope which point to non-glade
GTK objects so that the class can be garbage collected.
"""
while len(self.__refs_for_deletion):
attr = self.__refs_for_deletion.pop()
delattr(self, attr)

View File

@ -2,7 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2007 Donald N. Allingham
# 2009 Gary Burton
# Copyright (C) 2009 Gary Burton
#
# 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
@ -155,37 +155,52 @@ class EditEvent(EditPrimary):
"""
notebook = gtk.Notebook()
self.srcref_list = self._add_tab(
notebook,
SourceEmbedList(self.dbstate,self.uistate,self.track,self.obj))
self.source_list = SourceEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj)
self._add_tab(notebook, self.source_list)
self.note_tab = self._add_tab(
notebook,
NoteTab(self.dbstate, self.uistate, self.track,
self.obj.get_note_list(), notetype=gen.lib.NoteType.EVENT))
self.note_list = NoteTab(self.dbstate,
self.uistate,
self.track,
self.obj.get_note_list(),
notetype=gen.lib.NoteType.EVENT)
self._add_tab(notebook, self.note_list)
self.gallery_tab = self._add_tab(
notebook,
GalleryTab(self.dbstate, self.uistate, self.track,
self.obj.get_media_list()))
self.attr_ref_list = self._add_tab(
notebook,
AttrEmbedList(self.dbstate, self.uistate, self.track,
self.obj.get_attribute_list()))
self.gallery_list = GalleryTab(self.dbstate,
self.uistate,
self.track,
self.obj.get_media_list())
self._add_tab(notebook, self.gallery_list)
self.backref_tab = self._add_tab(
notebook,
EventBackRefList(self.dbstate, self.uistate, self.track,
self.dbstate.db.find_backlink_handles(self.obj.handle)))
self.attr_list = AttrEmbedList(self.dbstate,
self.uistate,
self.track,
self.obj.get_attribute_list())
self._add_tab(notebook, self.attr_list)
self._setup_notebook_tabs( notebook)
handle_list = self.dbstate.db.find_backlink_handles(self.obj.handle)
self.backref_list = EventBackRefList(self.dbstate,
self.uistate,
self.track,
handle_list)
self._add_tab(notebook, self.backref_list)
self._setup_notebook_tabs(notebook)
notebook.show_all()
self.top.get_widget('vbox').pack_start(notebook, True)
self.track_ref_for_deletion("source_list")
self.track_ref_for_deletion("note_list")
self.track_ref_for_deletion("gallery_list")
self.track_ref_for_deletion("attr_list")
self.track_ref_for_deletion("backref_list")
def _cleanup_on_exit(self):
self.backref_tab.close()
self.backref_list.close()
def build_menu_names(self, event):
return (_('Edit Event'), self.get_menu_title())

View File

@ -2,7 +2,7 @@
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2000-2006 Donald N. Allingham
# 2009 Gary Burton
# Copyright (C) 2009 Gary Burton
#
# 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
@ -334,6 +334,7 @@ class ManagedWindow:
self.isWindow = None
self.width_key = None
self.height_key = None
self.__refs_for_deletion = []
if uistate.gwm.get_item_from_id(window_key):
uistate.gwm.get_item_from_id(window_key).present()
@ -466,6 +467,7 @@ class ManagedWindow:
Takes care of closing children and removing itself from menu.
"""
self.clean_up()
self._save_size()
self.uistate.gwm.close_track(self.track)
self.opened = False
@ -500,6 +502,26 @@ class ManagedWindow:
Config.set(self.width_key, width)
Config.set(self.height_key, height)
Config.sync()
def track_ref_for_deletion(self, ref):
"""
Record references of instance variables that need to be removed
from scope so that the class can be garbage collected
"""
if ref not in self.__refs_for_deletion:
self.__refs_for_deletion.append(ref)
def clean_up(self):
"""
Remove any instance variables from scope which point to non-glade
GTK objects so that the class can be garbage collected.
Run the clean_up method on the object first before removing it.
"""
while len(self.__refs_for_deletion):
attr = self.__refs_for_deletion.pop()
obj = getattr(self, attr)
obj.clean_up()
delattr(self, attr)
#-------------------------------------------------------------------------
#
# Helper functions