diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index 718ece46d2..fc56d3d997 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -170,6 +170,10 @@ class EditMetadataAction(InterfaceAction): list(range(self.gui.library_view.model().rowCount(QModelIndex()))) current_row = row_list.index(cr) + from calibre.utils.mem import memory + + import gc + print 'start of edit metadata:', memory()/1024**2 changed, rows_to_refresh = self.do_edit_metadata(row_list, current_row) m = self.gui.library_view.model() @@ -184,6 +188,9 @@ class EditMetadataAction(InterfaceAction): self.gui.cover_flow.dataChanged() m.current_changed(current, previous) self.gui.tags_view.recount() + for i in range(5): gc.collect(); + print 'end of edit metadata:', memory()/1024**2 + print def do_edit_metadata(self, row_list, current_row): from calibre.gui2.metadata.single import edit_metadata diff --git a/src/calibre/gui2/custom_column_widgets.py b/src/calibre/gui2/custom_column_widgets.py index 4706cce4c9..732d30e7fb 100644 --- a/src/calibre/gui2/custom_column_widgets.py +++ b/src/calibre/gui2/custom_column_widgets.py @@ -25,7 +25,7 @@ class Base(object): def __init__(self, db, col_id, parent=None): self.db, self.col_id = db, col_id self.col_metadata = db.custom_column_num_map[col_id] - self.initial_val = None + self.initial_val = self.widgets = None self.setup_ui(parent) def initialize(self, book_id): @@ -54,6 +54,9 @@ class Base(object): def normalize_ui_val(self, val): return val + def break_cycles(self): + self.db = self.widgets = self.initial_val = None + class Bool(Base): def setup_ui(self, parent): diff --git a/src/calibre/gui2/metadata/basic_widgets.py b/src/calibre/gui2/metadata/basic_widgets.py index 858aafafc6..e00af37d33 100644 --- a/src/calibre/gui2/metadata/basic_widgets.py +++ b/src/calibre/gui2/metadata/basic_widgets.py @@ -126,6 +126,9 @@ class TitleEdit(EnLineEdit): return property(fget=fget, fset=fset) + def break_cycles(self): + self.dialog = None + class TitleSortEdit(TitleEdit): TITLE_ATTR = 'title_sort' @@ -151,6 +154,7 @@ class TitleSortEdit(TitleEdit): self.title_edit.textChanged.connect(self.update_state) self.textChanged.connect(self.update_state) + self.autogen_button = autogen_button autogen_button.clicked.connect(self.auto_generate) self.update_state() @@ -169,6 +173,9 @@ class TitleSortEdit(TitleEdit): def auto_generate(self, *args): self.current_val = title_sort(self.title_edit.current_val) + self.title_edit.textChanged.disconnect() + self.textChanged.disconnect() + self.autogen_button.clicked.disconnect() # }}} @@ -186,6 +193,7 @@ class AuthorsEdit(MultiCompleteComboBox): self.setWhatsThis(self.TOOLTIP) self.setEditable(True) self.setSizeAdjustPolicy(self.AdjustToMinimumContentsLengthWithIcon) + self.manage_authors_signal = manage_authors manage_authors.triggered.connect(self.manage_authors) def manage_authors(self): @@ -270,6 +278,10 @@ class AuthorsEdit(MultiCompleteComboBox): return property(fget=fget, fset=fset) + def break_cycles(self): + self.db = self.dialog = None + self.manage_authors_signal.triggered.disconnect() + class AuthorSortEdit(EnLineEdit): TOOLTIP = _('Specify how the author(s) of this book should be sorted. ' @@ -298,6 +310,10 @@ class AuthorSortEdit(EnLineEdit): self.authors_edit.editTextChanged.connect(self.update_state_and_val) self.textChanged.connect(self.update_state) + self.autogen_button = autogen_button + self.copy_a_to_as_action = copy_a_to_as_action + self.copy_as_to_a_action = copy_as_to_a_action + autogen_button.clicked.connect(self.auto_generate) copy_a_to_as_action.triggered.connect(self.auto_generate) copy_as_to_a_action.triggered.connect(self.copy_to_authors) @@ -369,6 +385,15 @@ class AuthorSortEdit(EnLineEdit): db.set_author_sort(id_, aus, notify=False, commit=False) return True + def break_cycles(self): + self.db = None + self.authors_edit.editTextChanged.disconnect() + self.textChanged.disconnect() + self.autogen_button.clicked.disconnect() + self.copy_a_to_as_action.triggered.disconnect() + self.copy_as_to_a_action.triggered.disconnect() + self.authors_edit = None + # }}} # Series {{{ @@ -428,6 +453,10 @@ class SeriesEdit(MultiCompleteComboBox): commit=True, allow_case_change=True) return True + def break_cycles(self): + self.dialog = None + + class SeriesIndexEdit(QDoubleSpinBox): TOOLTIP = '' @@ -489,6 +518,11 @@ class SeriesIndexEdit(QDoubleSpinBox): import traceback traceback.print_exc() + def break_cycles(self): + self.series_edit.currentIndexChanged.disconnect() + self.series_edit.editTextChanged.disconnect() + self.series_edit.lineEdit().editingFinished.disconnect() + self.db = self.series_edit = self.dialog = None # }}} @@ -700,6 +734,8 @@ class FormatsManager(QWidget): # {{{ if old != prefs['read_file_metadata']: prefs['read_file_metadata'] = old + def break_cycles(self): + self.dialog = None # }}} class Cover(ImageView): # {{{ @@ -861,6 +897,10 @@ class Cover(ImageView): # {{{ db.remove_cover(id_, notify=False, commit=False) return True + def break_cycles(self): + self.cover_changed.disconnect() + self.dialog = self._cdata = self.current_val = self.original_val = None + # }}} class CommentsEdit(Editor): # {{{ diff --git a/src/calibre/gui2/metadata/single.py b/src/calibre/gui2/metadata/single.py index d818f2db2a..950d3722e5 100644 --- a/src/calibre/gui2/metadata/single.py +++ b/src/calibre/gui2/metadata/single.py @@ -481,6 +481,13 @@ class MetadataSingleDialogBase(ResizableDialog): x = getattr(self, b, None) if x is not None: disconnect(x.clicked) + for widget in self.basic_metadata_widgets: + bc = getattr(widget, 'break_cycles', None) + if bc is not None and callable(bc): + bc() + for widget in getattr(self, 'custom_metadata_widgets', []): + widget.break_cycles() + # }}} class Splitter(QSplitter): diff --git a/src/calibre/gui2/tag_view.py b/src/calibre/gui2/tag_view.py index 3b8c27866c..f2c6e38050 100644 --- a/src/calibre/gui2/tag_view.py +++ b/src/calibre/gui2/tag_view.py @@ -627,7 +627,8 @@ class TagTreeItem(object): # {{{ except: pass self.parent = self.icon_state_map = self.bold_font = self.tag = \ - self.icon = self.children = None + self.icon = self.children = self.tooltip = \ + self.py_name = self.id_set = self.category_key = None def __str__(self): if self.type == self.ROOT: @@ -1121,7 +1122,7 @@ class TagsModel(QAbstractItemModel): # {{{ self.search_restriction = s def get_node_tree(self, sort): - old_row_map = self.row_map[:] + old_row_map_len = len(self.row_map) self.row_map = [] self.categories = {} @@ -1176,13 +1177,15 @@ class TagsModel(QAbstractItemModel): # {{{ self.row_map.append(category) self.categories[category] = tb_categories[category]['name'] - if len(old_row_map) != 0 and len(old_row_map) != len(self.row_map): + if old_row_map_len != 0 and old_row_map_len != len(self.row_map): # A category has been added or removed. We must force a rebuild of # the model return None return data def refresh(self, data=None): + from calibre.utils.mem import memory + print 'start of refresh:', memory()/1024**2 sort_by = config['sort_tags_by'] if data is None: data = self.get_node_tree(sort_by) # get category data @@ -1367,11 +1370,15 @@ class TagsModel(QAbstractItemModel): # {{{ self.beginRemoveRows(self.createIndex(category.row(), 0, category), start, len(child_map)-1) category.children = ctags + for i in range(start, len(child_map)): + child_map[i].break_cycles() + child_map = None self.endRemoveRows() else: state_map = {} process_one_node(category, state_map) + print 'end of refresh:', memory()/1024**2 return True def columnCount(self, parent):