some tweaks to the book report

Formerly, the books.xml file was read in multiple times,
even if it hadn't changed at all.  And since books.xml can
contain multiple books, each of which potentially contains
multiple reports, each with multiple options, all of which
get parsed every time the books.xml file gets read in, the
process potentially can take a while.

Similarly the books.xml file was written out every time a
book was added or deleted, even if the book report continued
to be run, with potentially more changes being made.

So it's changed so that the books.xml file is only read in
once, and written out once, and only then if it needs it.
This commit is contained in:
Paul Franklin 2016-06-28 11:38:53 -07:00
parent 8e4c7234a4
commit be76d63ef6
2 changed files with 54 additions and 28 deletions

View File

@ -4,7 +4,7 @@
# Copyright (C) 2003-2007 Donald N. Allingham # Copyright (C) 2003-2007 Donald N. Allingham
# Copyright (C) 2007-2008 Brian G. Matherly # Copyright (C) 2007-2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant # Copyright (C) 2010 Jakim Friant
# Copyright (C) 2011-2014 Paul Franklin # Copyright (C) 2011-2016 Paul Franklin
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -412,6 +412,7 @@ class BookList:
""" """
self.dbase = dbase self.dbase = dbase
self.bookmap = {} self.bookmap = {}
self._needs_saving = None
self.file = os.path.join(HOME_DIR, filename) self.file = os.path.join(HOME_DIR, filename)
self.parse() self.parse()
@ -448,10 +449,28 @@ class BookList:
Add or replaces a Book in the BookList. Add or replaces a Book in the BookList.
name: name associated with the Book to add or replace. name: name associated with the Book to add or replace.
book: definition of the Book book: definition of the book -- a :class:`.Book` instance
""" """
self.bookmap[name] = book self.bookmap[name] = book
def set_needs_saving(self, needs_saving):
"""
Set the needs_saving flag for the BookList.
@param needs_saving: whether the current BookList needs saving
@type needs_saving: boolean
"""
self._needs_saving = needs_saving
def get_needs_saving(self):
"""
Return the needs_saving flag of the BookList.
@returns: returns whether the current BookList needs saving to a file
@rtype: boolean
"""
return self._needs_saving
def save(self): def save(self):
""" """
Saves the current BookList to the associated file. Saves the current BookList to the associated file.

View File

@ -5,7 +5,7 @@
# Copyright (C) 2007-2008 Brian G. Matherly # Copyright (C) 2007-2008 Brian G. Matherly
# Copyright (C) 2010 Jakim Friant # Copyright (C) 2010 Jakim Friant
# Copyright (C) 2012 Nick Hall # Copyright (C) 2012 Nick Hall
# Copyright (C) 2011-2014 Paul Franklin # Copyright (C) 2011-2016 Paul Franklin
# #
# This program is free software; you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -60,7 +60,7 @@ _ = glocale.translation.gettext
from ...listmodel import ListModel from ...listmodel import ListModel
from gramps.gen.errors import FilterError, ReportError from gramps.gen.errors import FilterError, ReportError
from ...pluginmanager import GuiPluginManager from ...pluginmanager import GuiPluginManager
from ...dialog import WarningDialog, ErrorDialog from ...dialog import WarningDialog, ErrorDialog, QuestionDialog2
from gramps.gen.plug.menu import PersonOption, FilterOption, FamilyOption from gramps.gen.plug.menu import PersonOption, FilterOption, FamilyOption
from gramps.gen.plug.docgen import StyleSheet from gramps.gen.plug.docgen import StyleSheet
from ...managedwindow import ManagedWindow, set_titles from ...managedwindow import ManagedWindow, set_titles
@ -203,13 +203,13 @@ class BookListDisplay:
Allows the user to select and/or delete a book from the list. Allows the user to select and/or delete a book from the list.
""" """
def __init__(self, booklist, nodelete=0, dosave=0): def __init__(self, booklist, nodelete=False, dosave=False):
""" """
Create a BookListDisplay object that displays the books in BookList. Create a BookListDisplay object that displays the books in BookList.
booklist: books that are displayed booklist: books that are displayed -- a :class:`.BookList` instance
nodelete: if not 0 then the Delete button is hidden nodelete: if True then the Delete button is hidden
dosave: if 1 then the book list is saved on hitting OK dosave: if True then the book list is flagged to be saved if needed
""" """
self.booklist = booklist self.booklist = booklist
@ -262,13 +262,16 @@ class BookListDisplay:
self.blist.selection.select_iter(the_iter) self.blist.selection.select_iter(the_iter)
def on_booklist_ok_clicked(self, obj): def on_booklist_ok_clicked(self, obj):
"""Return selected book. Saves the current list into xml file.""" """
Return selected book.
Also marks the current list to be saved into the xml file, if needed.
"""
store, the_iter = self.blist.get_selected() store, the_iter = self.blist.get_selected()
if the_iter: if the_iter:
data = self.blist.get_data(the_iter, [0]) data = self.blist.get_data(the_iter, [0])
self.selection = self.booklist.get_book(str(data[0])) self.selection = self.booklist.get_book(str(data[0]))
if self.dosave: if self.dosave and self.unsaved_changes:
self.booklist.save() self.booklist.set_needs_saving(True)
def on_booklist_delete_clicked(self, obj): def on_booklist_delete_clicked(self, obj):
""" """
@ -288,15 +291,12 @@ class BookListDisplay:
def on_booklist_cancel_clicked(self, obj): def on_booklist_cancel_clicked(self, obj):
""" cancel the booklist dialog """ """ cancel the booklist dialog """
if self.unsaved_changes: if self.unsaved_changes:
from ...dialog import QuestionDialog2
qqq = QuestionDialog2( qqq = QuestionDialog2(
_('Discard Unsaved Changes'), _('Discard Unsaved Changes'),
_('You have made changes which have not been saved.'), _('You have made changes which have not been saved.'),
_('Proceed'), _('Proceed'),
_('Cancel')) _('Cancel'))
if qqq.run(): if not qqq.run():
return
else:
self.top.run() self.top.run()
def on_button_press(self, obj, event): def on_button_press(self, obj, event):
@ -394,7 +394,7 @@ class BookSelector(ManagedWindow):
"on_open_clicked" : self.on_open_clicked, "on_open_clicked" : self.on_open_clicked,
"on_edit_clicked" : self.on_edit_clicked, "on_edit_clicked" : self.on_edit_clicked,
"on_book_ok_clicked" : self.on_book_ok_clicked, "on_book_ok_clicked" : self.on_book_ok_clicked,
"destroy_passed_object" : self.close, "destroy_passed_object" : self.on_close_clicked,
# Insert dummy handlers for second top level in the glade file # Insert dummy handlers for second top level in the glade file
"on_booklist_ok_clicked" : lambda _: None, "on_booklist_ok_clicked" : lambda _: None,
@ -438,6 +438,8 @@ class BookSelector(ManagedWindow):
self.draw_avail_list() self.draw_avail_list()
self.book = Book() self.book = Book()
self.book_list = BookList(self.file, self._db)
self.book_list.set_needs_saving(False) # just read in: no need to save
def build_menu_names(self, obj): def build_menu_names(self, obj):
return (_("Book selection list"), self.title) return (_("Book selection list"), self.title)
@ -716,11 +718,21 @@ class BookSelector(ManagedWindow):
self.menu2.append(item) self.menu2.append(item)
self.menu2.popup(None, None, None, None, event.button, event.time) self.menu2.popup(None, None, None, None, event.button, event.time)
def on_close_clicked(self, obj):
"""
close the BookSelector dialog, saving any changes if needed
"""
if self.book_list.get_needs_saving():
self.book_list.save()
ManagedWindow.close(self, *obj)
def on_book_ok_clicked(self, obj): def on_book_ok_clicked(self, obj):
""" """
Run final BookDialog with the current book. Run final BookDialog with the current book.
""" """
if self.book.item_list: if self.book.item_list:
if self.book_list.get_needs_saving():
self.book_list.save()
BookDialog(self.dbstate, self.uistate, self.book, BookOptions) BookDialog(self.dbstate, self.uistate, self.book, BookOptions)
else: else:
WarningDialog(_('No items'), _('This book has no items.'), WarningDialog(_('No items'), _('This book has no items.'),
@ -732,7 +744,6 @@ class BookSelector(ManagedWindow):
""" """
Save the current book in the xml booklist file. Save the current book in the xml booklist file.
""" """
self.book_list = BookList(self.file, self._db)
name = str(self.name_entry.get_text()) name = str(self.name_entry.get_text())
if not name: if not name:
WarningDialog( WarningDialog(
@ -742,7 +753,6 @@ class BookSelector(ManagedWindow):
parent=self.window) parent=self.window)
return return
if name in self.book_list.get_book_names(): if name in self.book_list.get_book_names():
from ...dialog import QuestionDialog2
qqq = QuestionDialog2( qqq = QuestionDialog2(
_('Book name already exists'), _('Book name already exists'),
_('You are about to save away a ' _('You are about to save away a '
@ -750,22 +760,19 @@ class BookSelector(ManagedWindow):
_('Proceed'), _('Proceed'),
_('Cancel'), _('Cancel'),
parent=self.window) parent=self.window)
if qqq.run(): if not qqq.run():
self.book.set_name(name)
else:
return return
else: self.book.set_name(name)
self.book.set_name(name)
self.book.set_dbname(self._db.get_save_path()) self.book.set_dbname(self._db.get_save_path())
self.book_list.set_book(name, self.book) self.book_list.set_book(name, self.book)
self.book_list.save() self.book_list.set_needs_saving(True) # user clicked on save
def on_open_clicked(self, obj): def on_open_clicked(self, obj):
""" """
Run the BookListDisplay dialog to present the choice of books to open. Run the BookListDisplay dialog to present the choice of books to open.
""" """
self.book_list = BookList(self.file, self._db) booklistdisplay = BookListDisplay(self.book_list,
booklistdisplay = BookListDisplay(self.book_list, 1, 0) nodelete=True, dosave=False)
booklistdisplay.top.destroy() booklistdisplay.top.destroy()
book = booklistdisplay.selection book = booklistdisplay.selection
if book: if book:
@ -777,8 +784,8 @@ class BookSelector(ManagedWindow):
""" """
Run the BookListDisplay dialog to present the choice of books to delete. Run the BookListDisplay dialog to present the choice of books to delete.
""" """
self.book_list = BookList(self.file, self._db) booklistdisplay = BookListDisplay(self.book_list,
booklistdisplay = BookListDisplay(self.book_list, 0, 1) nodelete=False, dosave=True)
booklistdisplay.top.destroy() booklistdisplay.top.destroy()
book = booklistdisplay.selection book = booklistdisplay.selection
if book: if book: