8250 and 9736: avoid all other operations during export and fixes for export popup windows hidden.

This commit is contained in:
SNoiraud 2016-11-04 10:00:50 +01:00 committed by prculley
parent 4ffc5e3af4
commit f157148414
8 changed files with 128 additions and 55 deletions

View File

@ -60,7 +60,7 @@ class BaseDoc(metaclass=ABCMeta):
such as OpenOffice, AbiWord, and LaTeX are derived from this base
class, providing a common interface to all document generators.
"""
def __init__(self, styles, paper_style):
def __init__(self, styles, paper_style, track=[]):
"""
Create a BaseDoc instance, which provides a document generation
interface. This class should never be instantiated directly, but
@ -70,9 +70,11 @@ class BaseDoc(metaclass=ABCMeta):
:param paper_style: :class:`.PaperStyle` instance containing information
about the paper. If set to None, then the document
is not a page oriented document (e.g. HTML)
:param track: used in quick reports for GUI window management
"""
self.paper = paper_style
self._style_sheet = styles
self.track = track
self._creator = ""
self.init_called = False

View File

@ -408,6 +408,7 @@ class DisplayState(Callback):
self.disprel_defpers = None
self.disprel_active = None
self.set_relationship_class()
self.export = False
formatter = logging.Formatter('%(levelname)s %(name)s: %(message)s')
warnbtn = status.get_warning_button()
@ -527,6 +528,16 @@ class DisplayState(Callback):
else:
return ""
def set_export_mode(self, value):
self.set_busy_cursor(value)
if value == self.export:
return
else:
self.export = value
def get_export_mode(self):
return self.export
def set_busy_cursor(self, value):
if value == self.busy:
return

View File

@ -139,6 +139,21 @@ class GrampsWindowManager:
# Return None if the ID is not found
return self.id2item.get(item_id, None)
def get_item_from_window(self, window):
""" This finds a ManagedWindow from a Gtk top_level object (typicaly
a window).
For example, to find my managedwindow track within a class of Gtk
widget:
mywindow = self.get_toplevel() # finds top level Gtk object
managed_window = self.uistate.gwm.get_item_from_window(mywindow)
track = managed_window.track
"""
for key, item in self.id2item.items():
if item.window == window:
return self.id2item[key]
return None
def close_track(self, track):
# This is called when item needs to be closed
# Closes all its children and then removes the item from the tree.
@ -311,7 +326,7 @@ class ManagedWindow:
menu, keeping track of child windows, closing them on close/delete
event, and presenting itself when selected or attempted to create again.
"""
def __init__(self, uistate, track, obj):
def __init__(self, uistate, track, obj, modal=False):
"""
Create child windows and add itself to menu, if not there already.
@ -321,18 +336,19 @@ class ManagedWindow:
from .managedwindow import ManagedWindow
class SomeWindowClass(ManagedWindow):
def __init__(self,uistate,dbstate,track):
def __init__(self, uistate, dbstate, track, modal):
window_id = self # Or e.g. window_id = person.handle
submenu_label = None # This window cannot have children
menu_label = 'Menu label for this window'
ManagedWindow.__init__(self,
uistate,
track,
window_id,
submenu_label,
menu_label)
modal=False)
# Proceed with the class.
...
def build_menu_names(self, obj):
submenu_label = None # This window cannot have children
menu_label = 'Menu label for this window'
return (menu_label, submenu_label)
:param uistate: gramps uistate
:param track: {list of parent windows, [] if the main GRAMPS window
@ -342,7 +358,17 @@ class ManagedWindow:
which works on this obj and creates menu labels
for use in the Gramps Window Menu.
If self.submenu_label ='' then leaf, otherwise branch
:param modal: True/False, if True, this window is made modal
(always on top, and always has focus). Any child
windows are also automatically made modal by moving
the modal flag to the child. On close of a child
the modal flag is sent back to the parent.
If a modal window is used and has children, its and any child 'track'
parameters must properly be set to the parents 'self.track'.
Only one modal window can be supported by Gtk without potentially
hiding of a modal window while it has focus. So don't use direct
non managed Gtk windows as children and set them modal.
"""
window_key = self.build_window_key(obj)
@ -354,6 +380,7 @@ class ManagedWindow:
self.horiz_position_key = None
self.vert_position_key = None
self.__refs_for_deletion = []
self.modal = modal
if uistate and uistate.gwm.get_item_from_id(window_key):
uistate.gwm.get_item_from_id(window_key).present()
@ -382,10 +409,13 @@ class ManagedWindow:
parent_item_track.append(0)
# Based on the track, get item and then window object
self.parent_window = self.uistate.gwm.get_item_from_track(
parent_item_track).window
managed_parent = self.uistate.gwm.get_item_from_track(
parent_item_track)
self.parent_window = managed_parent.window
self.parent_modal = managed_parent.modal
else:
# On the top level: we use gramps top window
self.parent_modal = False
if self.uistate:
self.parent_window = self.uistate.window
else:
@ -412,11 +442,18 @@ class ManagedWindow:
self.titlelabel = title
if self.isWindow :
set_titles(self, title, text, msg)
self.window = self
else :
set_titles(window, title, text, msg)
#closing the Gtk.Window must also close ManagedWindow
self.window = window
self.window.connect('delete-event', self.close)
if self.modal:
self.window.set_modal(True)
if self.parent_modal:
self.parent_window.set_modal(False)
self.window.set_modal(True)
self.modal = True
def get_window(self):
"""
@ -513,6 +550,8 @@ class ManagedWindow:
self.clean_up()
self.uistate.gwm.close_track(self.track)
self.opened = False
if self.parent_modal:
self.parent_window.set_modal(True)
self.parent_window.present()
def present(self):

View File

@ -109,12 +109,15 @@ class ExportAssistant(Gtk.Assistant, ManagedWindow) :
self.writestarted = False
self.confirm = None
# set export mode and busy mode to avoid all other operations
self.uistate.set_export_mode(True)
#set up Assistant
Gtk.Assistant.__init__(self)
#set up ManagedWindow
self.top_title = _("Export Assistant")
ManagedWindow.__init__(self, uistate, [], self.__class__)
ManagedWindow.__init__(self, uistate, [], self.__class__, modal=True)
#set_window is present in both parent classes
ManagedWindow.set_window(self, self, None,
@ -156,7 +159,7 @@ class ExportAssistant(Gtk.Assistant, ManagedWindow) :
def build_menu_names(self, obj):
"""Override ManagedWindow method."""
return (self.top_title, None)
return (self.top_title, self.top_title)
def create_page_intro(self):
"""Create the introduction page."""
@ -272,7 +275,8 @@ class ExportAssistant(Gtk.Assistant, ManagedWindow) :
list(map(vbox.remove, vbox.get_children()))
# add new content
if config_box_class:
self.option_box_instance = config_box_class(self.person, self.dbstate, self.uistate)
self.option_box_instance = config_box_class(
self.person, self.dbstate, self.uistate, track=self.track)
box = self.option_box_instance.get_option_box()
vbox.add(box)
else:
@ -387,6 +391,7 @@ class ExportAssistant(Gtk.Assistant, ManagedWindow) :
pass
def do_close(self):
self.uistate.set_export_mode(False)
if self.writestarted :
pass
else :
@ -609,11 +614,9 @@ class ExportAssistant(Gtk.Assistant, ManagedWindow) :
page.set_child_visible(True)
self.show_all()
self.uistate.set_busy_cursor(True)
self.set_busy_cursor(1)
def post_save(self):
self.uistate.set_busy_cursor(False)
self.set_busy_cursor(0)
self.progressbar.hide()
self.writestarted = False

View File

@ -106,10 +106,11 @@ class WriterOptionBox:
the options.
"""
def __init__(self, person, dbstate, uistate):
def __init__(self, person, dbstate, uistate, track=[]):
self.person = person
self.dbstate = dbstate
self.uistate = uistate
self.track = track
self.preview_dbase = None
self.preview_button = None
self.preview_proxy_button = {}
@ -247,7 +248,8 @@ class WriterOptionBox:
run_quick_report_by_name(dbstate,
self.uistate,
'filterbyname',
'all')
'all',
track=self.track)
def preview(self, widget):
"""
@ -658,7 +660,7 @@ class WriterOptionBox:
else:
the_filter = GenericFilterFactory(namespace)()
if the_filter:
EditFilter(namespace, self.dbstate, self.uistate, [],
EditFilter(namespace, self.dbstate, self.uistate, self.track,
the_filter, filterdb,
lambda : self.edit_filter_save(filterdb, namespace))
else: # can't edit this filter

View File

@ -179,7 +179,7 @@ def get_quick_report_list(qv_category=None):
return names
def run_quick_report_by_name(dbstate, uistate, report_name, handle,
container=None, **kwargs):
container=None, track=[], **kwargs):
"""
Run a QuickView by name.
**kwargs provides a way of passing special quick views additional
@ -193,7 +193,8 @@ def run_quick_report_by_name(dbstate, uistate, report_name, handle,
break
if report:
return run_report(dbstate, uistate, report.category,
handle, report, container=container, **kwargs)
handle, report, container=container,
track=track, **kwargs)
else:
raise AttributeError("No such quick report '%s'" % report_name)
@ -226,7 +227,7 @@ def run_quick_report_by_name_direct(report_name, database, document, handle):
raise AttributeError("No such quick report id = '%s'" % report_name)
def run_report(dbstate, uistate, category, handle, pdata, container=None,
**kwargs):
track=[], **kwargs):
"""
Run a Quick Report.
Optionally container can be passed, rather than putting the report
@ -241,7 +242,7 @@ def run_report(dbstate, uistate, category, handle, pdata, container=None,
return
func = eval('mod.' + pdata.runfunc)
if handle:
d = TextBufDoc(make_basic_stylesheet(), None)
d = TextBufDoc(make_basic_stylesheet(), None, track=track)
d.dbstate = dbstate
d.uistate = uistate
if isinstance(handle, str): # a handle

View File

@ -75,6 +75,12 @@ class QuickTable(SimpleTable):
self._callback_leftdouble = callback
def button_press_event(self, treeview, event):
wid = treeview.get_toplevel()
try:
winmgr = self.simpledoc.doc.uistate.gwm
self.track = winmgr.get_item_from_window(wid).track
except:
self.track = []
index = None
button_code = None
event_time = None
@ -112,46 +118,50 @@ class QuickTable(SimpleTable):
treeview.grab_focus()
treeview.set_cursor(path, col, 0)
if store and node:
index = store.get_value(node, 0) # index Below,
index = store.get_value(node, 0) # index Below,
# you need index, treeview, path, button_code,
# func, and event_time
if index is not None:
if self._link[index]:
objclass, handle = self._link[index]
else:
return False
if (self.simpledoc.doc.uistate.get_export_mode() and
objclass != 'Filter'):
return False # avoid edition during export
self.popup = Gtk.Menu()
popup = self.popup
menu_item = Gtk.MenuItem(label=_("Copy all"))
menu_item.connect("activate", lambda widget: text_to_clipboard(model_to_text(treeview.get_model())))
menu_item.connect("activate", lambda widget: text_to_clipboard(
model_to_text(treeview.get_model())))
popup.append(menu_item)
menu_item.show()
# Now add more items to popup menu, if available
if (index is not None and self._link[index]):
# See details (edit, etc):
objclass, handle = self._link[index]
menu_item = Gtk.MenuItem(label=_("the object|See %s details") % glocale.trans_objclass(objclass))
menu_item = Gtk.MenuItem(label=_("the object|See %s details") %
glocale.trans_objclass(objclass))
menu_item.connect(
"activate", lambda widget: self.on_table_doubleclick(treeview))
popup.append(menu_item)
menu_item.show()
# Add other items to menu:
if objclass == 'Person':
menu_item = Gtk.MenuItem(label=_("the object|Make %s active")
% glocale.trans_objclass('Person'))
menu_item.connect("activate",
lambda widget: self.on_table_doubleclick(treeview))
lambda widget: self.on_table_click(treeview))
popup.append(menu_item)
menu_item.show()
# Add other items to menu:
if (self._callback_leftclick or
(index is not None and self._link[index])):
objclass, handle = self._link[index]
if objclass == 'Person':
menu_item = Gtk.MenuItem(label=_("the object|Make %s active") % glocale.trans_objclass('Person'))
menu_item.connect("activate",
lambda widget: self.on_table_click(treeview))
popup.append(menu_item)
menu_item.show()
if (self.simpledoc.doc.dbstate.db !=
self.simpledoc.doc.dbstate.db.basedb and
(index is not None and self._link[index])):
objclass, handle = self._link[index]
self.simpledoc.doc.dbstate.db.basedb):
if (objclass == 'Filter' and
handle[0] in ['Person', 'Family', 'Place', 'Event',
'Repository', 'Note', 'Media',
'Citation', 'Source']):
menu_item = Gtk.MenuItem(label=_("See data not in Filter"))
menu_item.connect("activate",
lambda widget: self.show_not_in_filter(handle[0]))
menu_item.connect(
"activate",
lambda widget: self.show_not_in_filter(handle[0]))
popup.append(menu_item)
menu_item.show()
# Show the popup menu:
@ -163,7 +173,8 @@ class QuickTable(SimpleTable):
run_quick_report_by_name(self.simpledoc.doc.dbstate,
self.simpledoc.doc.uistate,
'filterbyname',
'Inverse %s' % obj_class)
'Inverse %s' % obj_class,
track=self.track)
def on_table_doubleclick(self, obj):
"""
@ -181,6 +192,9 @@ class QuickTable(SimpleTable):
return True
elif self._link[index]:
objclass, handle = self._link[index]
# if (self.simpledoc.doc.uistate.get_export_mode() and
# objclass != 'Filter'):
# return False # avoid edition during export
if isinstance(handle, list):
handle = handle[0]
if objclass == 'Person':
@ -269,14 +283,15 @@ class QuickTable(SimpleTable):
self.simpledoc.doc.uistate,
'filterbyname',
'list of people',
handles=handle)
handle=handle,
track=self.track)
elif objclass == 'Filter':
if isinstance(handle, list):
handle = handle[0]
run_quick_report_by_name(self.simpledoc.doc.dbstate,
self.simpledoc.doc.uistate,
'filterbyname',
handle)
handle, track=self.track)
return False # didn't handle event
def on_table_click(self, obj):

View File

@ -53,14 +53,14 @@ LEFT,RIGHT,CENTER = 'LEFT','RIGHT','CENTER'
_WIDTH_IN_CHARS = 72
class DisplayBuf(ManagedWindow):
def __init__(self, title, document):
def __init__(self, title, document, track=[]):
self.title = title
ManagedWindow.__init__(self, document.uistate, [],
document)
self.set_window(Gtk.Dialog("", document.uistate.window,
Gtk.DialogFlags.DESTROY_WITH_PARENT,
(_('_Close'), Gtk.ResponseType.CLOSE)),
None, title)
ManagedWindow.__init__(self, document.uistate, track, document)
self.set_window(Gtk.Dialog(title="",
flags=Gtk.DialogFlags.DESTROY_WITH_PARENT,
buttons=(_('_Close'),
Gtk.ResponseType.CLOSE)),
None, title, True)
self.window.set_size_request(600,400)
scrolled_window = Gtk.ScrolledWindow()
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,Gtk.PolicyType.AUTOMATIC)
@ -69,7 +69,7 @@ class DisplayBuf(ManagedWindow):
self.window.connect('response', self.close)
scrolled_window.add(document.text_view)
self.window.vbox.pack_start(scrolled_window, True, True, 0)
self.window.show_all()
self.show() # should use ManagedWindow version of show
def build_menu_names(self, obj):
return ('View', _('Quick View'))
@ -154,8 +154,8 @@ class TextBufDoc(BaseDoc, TextDoc):
if container:
return DocumentManager(_('Quick View'), self, container)
else:
DisplayBuf(_('Quick View'), self)
return
DisplayBuf(_('Quick View'), self, track=self.track)
return
#--------------------------------------------------------------------
#