Enhance Book Report

The main change is that now output-related options will also
be saved to (and restored from) the books.xml file.  If the
user has three books for instance, each will keep the last
filename it was written to, and present that filename to the
user in the final dialog, for acceptance or modification.
Similarly for things like paper size and orientation.

Also, the error reporting mechanism was enhanced, so that
now if a report inside a book has a ReportError the user
will be told gracefully (instead of gramps crashing).  The
(translated) name of the report will also be shown.

A few more dialogs were given a "parent" also.
This commit is contained in:
Paul Franklin 2016-07-11 12:16:58 -07:00
parent 4dfa354322
commit f73821eabf
2 changed files with 104 additions and 33 deletions

View File

@ -752,8 +752,9 @@ def cl_book(database, name, book, options_str_dict):
item.option_class.set_document(doc) item.option_class.set_document(doc)
report_class = item.get_write_item() report_class = item.get_write_item()
obj = write_book_item(database, obj = (write_book_item(database,
report_class, item.option_class, user) report_class, item.option_class, user),
item.get_translated_name())
if obj: if obj:
append_styles(selected_style, item) append_styles(selected_style, item)
rptlist.append(obj) rptlist.append(obj)
@ -762,13 +763,21 @@ def cl_book(database, name, book, options_str_dict):
doc.open(clr.option_class.get_output()) doc.open(clr.option_class.get_output())
doc.init() doc.init()
newpage = 0 newpage = 0
for rpt in rptlist: err_msg = _("Failed to make '%s' report.")
try:
for (rpt, name) in rptlist:
if newpage: if newpage:
doc.page_break() doc.page_break()
newpage = 1 newpage = 1
rpt.begin_report() rpt.begin_report()
rpt.write_report() rpt.write_report()
doc.close() doc.close()
except ReportError as msg:
(m1, m2) = msg.messages()
print(err_msg % name, file=sys.stderr) # which report has the error?
print(m1, file=sys.stderr)
if m2:
print(m2, file=sys.stderr)
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #

View File

@ -52,7 +52,7 @@ from gi.repository import GObject
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# gramps modules # Gramps modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale from gramps.gen.const import GRAMPS_LOCALE as glocale
@ -239,7 +239,8 @@ class BookListDisplay:
_('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'),
parent=self.top)
if not qqq.run(): if not qqq.run():
self.top.run() self.top.run()
@ -548,8 +549,6 @@ class BookSelector(ManagedWindow):
_('Please select a book item to configure.'), _('Please select a book item to configure.'),
parent=self.window) parent=self.window)
return return
## data = self.book_model.get_data(the_iter,
## list(range(self.book_nr_cols)))
row = self.book_model.get_selected_row() row = self.book_model.get_selected_row()
item = self.book.get_item(row) item = self.book.get_item(row)
option_class = item.option_class option_class = item.option_class
@ -577,6 +576,11 @@ class BookSelector(ManagedWindow):
#just stop, in ManagedWindow, delete-event is already coupled to #just stop, in ManagedWindow, delete-event is already coupled to
#correct action. #correct action.
break break
opt_dict = option_class.handler.options_dict
for optname in opt_dict:
menu_option = option_class.menu.get_option_by_name(optname)
if menu_option:
menu_option.set_value(opt_dict[optname])
def book_button_press(self, obj, event): def book_button_press(self, obj, event):
""" """
@ -675,9 +679,35 @@ class BookSelector(ManagedWindow):
Run final BookDialog with the current book. Run final BookDialog with the current book.
""" """
if self.book.item_list: if self.book.item_list:
old_paper_name = self.book.get_paper_name() # from books.xml
old_orientation = self.book.get_orientation()
old_paper_metric = self.book.get_paper_metric()
old_custom_paper_size = self.book.get_custom_paper_size()
old_margins = self.book.get_margins()
old_format_name = self.book.get_format_name()
old_output = self.book.get_output()
BookDialog(self.dbstate, self.uistate, self.book, BookOptions)
new_paper_name = self.book.get_paper_name()
new_orientation = self.book.get_orientation()
new_paper_metric = self.book.get_paper_metric()
new_custom_paper_size = self.book.get_custom_paper_size()
new_margins = self.book.get_margins()
new_format_name = self.book.get_format_name()
new_output = self.book.get_output()
# only books in the booklist have a name (not "ad hoc" ones)
if (self.book.get_name() and
(old_paper_name != new_paper_name or
old_orientation != new_orientation or
old_paper_metric != new_paper_metric or
old_custom_paper_size != new_custom_paper_size or
old_margins != new_margins or
old_format_name != new_format_name or
old_output != new_output)):
self.book.set_dbname(self._db.get_save_path())
self.book_list.set_book(self.book.get_name(), self.book)
self.book_list.set_needs_saving(True)
if self.book_list.get_needs_saving(): if self.book_list.get_needs_saving():
self.book_list.save() self.book_list.save()
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.'),
parent=self.window) parent=self.window)
@ -706,10 +736,26 @@ class BookSelector(ManagedWindow):
parent=self.window) parent=self.window)
if not qqq.run(): if not qqq.run():
return return
# previously, the same book could be added to the booklist
# under multiple names, which became different books once the
# booklist was saved into a file so everything was fine, but
# this created a problem once the paper settings were added
# to the Book object in the BookDialog, since those settings
# were retrieved from the Book object in Book.save, so mutiple
# books (differentiated by their names) were assigned the
# same paper values, so the solution is to make each Book be
# unique in the booklist, so if multiple copies are saved away
# only the last one will get the paper values assigned to it
# (although when the earlier books are then eventually run,
# they'll be assigned paper values also)
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.set_needs_saving(True) # user clicked on save self.book_list.set_needs_saving(True) # user clicked on save
self.book = Book(self.book, exact_copy=False) # regenerate old items
self.book.set_name(name)
self.book.set_dbname(self._db.get_save_path())
def on_open_clicked(self, obj): def on_open_clicked(self, obj):
""" """
@ -937,8 +983,9 @@ class BookDialog(DocReportDialog):
for item in self.book.get_item_list(): for item in self.book.get_item_list():
item.option_class.set_document(self.doc) item.option_class.set_document(self.doc)
report_class = item.get_write_item() report_class = item.get_write_item()
obj = write_book_item(self.database, report_class, obj = (write_book_item(self.database, report_class,
item.option_class, user) item.option_class, user),
item.get_translated_name())
self.rptlist.append(obj) self.rptlist.append(obj)
append_styles(selected_style, item) append_styles(selected_style, item)
@ -946,12 +993,16 @@ class BookDialog(DocReportDialog):
self.doc.open(self.target_path) self.doc.open(self.target_path)
def make_book(self): def make_book(self):
"""The actual book. Start it out, then go through the item list """
and call each item's write_book_item method.""" The actual book. Start it out, then go through the item list
and call each item's write_book_item method (which were loaded
by the previous make_document method).
"""
try:
self.doc.init() self.doc.init()
newpage = 0 newpage = 0
for rpt in self.rptlist: for (rpt, name) in self.rptlist:
if newpage: if newpage:
self.doc.page_break() self.doc.page_break()
newpage = 1 newpage = 1
@ -959,6 +1010,15 @@ class BookDialog(DocReportDialog):
rpt.begin_report() rpt.begin_report()
rpt.write_report() rpt.write_report()
self.doc.close() self.doc.close()
except ReportError as msg:
(msg1, msg2) = msg.messages()
msg2 += ' (%s)' % name # which report has the error?
ErrorDialog(msg1, msg2, parent=self.uistate.window)
except FilterError as msg:
(msg1, msg2) = msg.messages()
ErrorDialog(msg1, msg2, parent=self.uistate.window)
finally:
return
if self.open_with_app.get_active(): if self.open_with_app.get_active():
open_file_with_default_application(self.target_path) open_file_with_default_application(self.target_path)
@ -993,16 +1053,18 @@ class BookDialog(DocReportDialog):
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
def write_book_item(database, report_class, options, user): def write_book_item(database, report_class, options, user):
"""Write the report using options set. """
All user dialog has already been handled and the output file opened.""" Write the report using options set.
All user dialog has already been handled and the output file opened.
"""
try: try:
return report_class(database, options, user) return report_class(database, options, user)
except ReportError as msg: except ReportError as msg:
(msg1, msg2) = msg.messages() (msg1, msg2) = msg.messages()
ErrorDialog(msg1, msg2) ErrorDialog(msg1, msg2, parent=user.uistate.window)
except FilterError as msg: except FilterError as msg:
(msg1, msg2) = msg.messages() (msg1, msg2) = msg.messages()
ErrorDialog(msg1, msg2) ErrorDialog(msg1, msg2, parent=user.uistate.window)
except: except:
LOG.error("Failed to write book item.", exc_info=True) LOG.error("Failed to write book item.", exc_info=True)
return None return None