8250 and 9736: avoid all other operations during export and fixes for export popup windows hidden.
This commit is contained in:
parent
4ffc5e3af4
commit
f157148414
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user