8128: GtkDialog mapped without a transient parent

This commit is contained in:
Josip 2015-04-18 21:22:37 +02:00
parent ffe417f43e
commit 4ac02a4ca0
11 changed files with 90 additions and 52 deletions

View File

@ -117,7 +117,7 @@ class User(user.User):
""" """
self._fileout.write("\r100%\n") self._fileout.write("\r100%\n")
def prompt(self, title, message, accept_label, reject_label): def prompt(self, title, message, accept_label, reject_label, parent=None):
""" """
Prompt the user with a message to select an alternative. Prompt the user with a message to select an alternative.

View File

@ -97,7 +97,7 @@ class DisplayNameEditor(ManagedWindow):
def __init__(self, uistate, dbstate, track, dialog): def __init__(self, uistate, dbstate, track, dialog):
# Assumes that there are two methods: dialog.name_changed_check(), # Assumes that there are two methods: dialog.name_changed_check(),
# and dialog._build_custom_name_ui() # and dialog._build_custom_name_ui()
ManagedWindow.__init__(self, uistate, [], DisplayNameEditor) ManagedWindow.__init__(self, uistate, track, DisplayNameEditor)
self.dialog = dialog self.dialog = dialog
self.dbstate = dbstate self.dbstate = dbstate
self.set_window( self.set_window(
@ -136,7 +136,8 @@ UPPERCASE keyword forces uppercase. Extra parentheses, commas are removed. Other
ManagedWindow.close(self, *obj) ManagedWindow.close(self, *obj)
def build_menu_names(self, obj): def build_menu_names(self, obj):
return (_(" Name Editor"), _("Preferences")) # NameEditor is leaf of parent branch
return (_(" Name Editor"), None)
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -188,7 +189,6 @@ class ConfigureDialog(ManagedWindow):
self.__setup_pages(configure_page_funcs) self.__setup_pages(configure_page_funcs)
self.window.show_all()
self.show() self.show()
def __setup_pages(self, configure_page_funcs): def __setup_pages(self, configure_page_funcs):
@ -231,12 +231,12 @@ class ConfigureDialog(ManagedWindow):
except TypeError: except TypeError:
print("WARNING: ignoring invalid value for '%s'" % constant) print("WARNING: ignoring invalid value for '%s'" % constant)
ErrorDialog(_("Invalid or incomplete format definition."), ErrorDialog(_("Invalid or incomplete format definition."),
obj.get_text()) obj.get_text(), parent=self.window)
obj.set_text('<b>%s</b>') obj.set_text('<b>%s</b>')
except ValueError: except ValueError:
print("WARNING: ignoring invalid value for '%s'" % constant) print("WARNING: ignoring invalid value for '%s'" % constant)
ErrorDialog(_("Invalid or incomplete format definition."), ErrorDialog(_("Invalid or incomplete format definition."),
obj.get_text()) obj.get_text(), parent=self.window)
obj.set_text('<b>%s</b>') obj.set_text('<b>%s</b>')
self.__config.set(constant, unicode(obj.get_text())) self.__config.set(constant, unicode(obj.get_text()))
@ -770,7 +770,7 @@ class GrampsPreferences(ConfigureDialog):
# check to see if this pattern already exists # check to see if this pattern already exists
if self.__check_for_name(translation, node): if self.__check_for_name(translation, node):
ErrorDialog(_("This format exists already."), ErrorDialog(_("This format exists already."),
translation) translation, parent=self.window)
self.edit_button.emit('clicked') self.edit_button.emit('clicked')
return return
# else, change the name # else, change the name
@ -1170,13 +1170,15 @@ class GrampsPreferences(ConfigureDialog):
config.set('preferences.date-format', obj.get_active()) config.set('preferences.date-format', obj.get_active())
OkDialog(_('Change is not immediate'), OkDialog(_('Change is not immediate'),
_('Changing the date format will not take ' _('Changing the date format will not take '
'effect until the next time Gramps is started.')) 'effect until the next time Gramps is started.'),
parent=self.window)
def place_format_changed(self, obj): def place_format_changed(self, obj):
config.set('preferences.place-format', obj.get_active()) config.set('preferences.place-format', obj.get_active())
OkDialog(_('Change is not immediate'), OkDialog(_('Change is not immediate'),
_('Changing the place format will not take ' _('Changing the place format will not take '
'effect until the next time Gramps is started.')) 'effect until the next time Gramps is started.'),
parent=self.window)
def date_calendar_changed(self, obj): def date_calendar_changed(self, obj):
config.set('preferences.calendar-format-report', obj.get_active()) config.set('preferences.calendar-format-report', obj.get_active())
@ -1388,7 +1390,8 @@ class GrampsPreferences(ConfigureDialog):
def select_mediapath(self, *obj): def select_mediapath(self, *obj):
f = Gtk.FileChooserDialog( f = Gtk.FileChooserDialog(
_("Select media directory"), title=_("Select media directory"),
parent=self.window,
action=Gtk.FileChooserAction.SELECT_FOLDER, action=Gtk.FileChooserAction.SELECT_FOLDER,
buttons=(Gtk.STOCK_CANCEL, buttons=(Gtk.STOCK_CANCEL,
Gtk.ResponseType.CANCEL, Gtk.ResponseType.CANCEL,
@ -1412,7 +1415,8 @@ class GrampsPreferences(ConfigureDialog):
def select_dbpath(self, *obj): def select_dbpath(self, *obj):
f = Gtk.FileChooserDialog( f = Gtk.FileChooserDialog(
_("Select database directory"), title=_("Select database directory"),
parent=self.window,
action=Gtk.FileChooserAction.SELECT_FOLDER, action=Gtk.FileChooserAction.SELECT_FOLDER,
buttons=(Gtk.STOCK_CANCEL, buttons=(Gtk.STOCK_CANCEL,
Gtk.ResponseType.CANCEL, Gtk.ResponseType.CANCEL,
@ -1470,7 +1474,9 @@ class GrampsPreferences(ConfigureDialog):
obj.set_text(str(intval)) obj.set_text(str(intval))
def build_menu_names(self, obj): def build_menu_names(self, obj):
return (_('Preferences'), None) # Preferences editor my open other dialog so let main dialog
# be leaf in branch
return (_('Preferences'), _('Preferences'))
# FIXME: is this needed? # FIXME: is this needed?
def _set_button(self, stock): def _set_button(self, stock):

View File

@ -50,9 +50,10 @@ class Progress(object):
Mirros the same interface that the ExportAssistant uses in the Mirros the same interface that the ExportAssistant uses in the
selection, but this is for the preview selection. selection, but this is for the preview selection.
""" """
def __init__(self): def __init__(self, uistate):
from gi.repository import Gtk from gi.repository import Gtk
self.pm = ProgressMeter(_("Selecting Preview Data"), _('Selecting...')) self.pm = ProgressMeter(_("Selecting Preview Data"), _('Selecting...'),
parent=uistate.window)
self.progress_cnt = 0 self.progress_cnt = 0
self.title = _("Selecting...") self.title = _("Selecting...")
while Gtk.events_pending(): while Gtk.events_pending():
@ -239,7 +240,7 @@ class WriterOptionBox(object):
Calculate previews to see the selected data. Calculate previews to see the selected data.
""" """
self.parse_options() self.parse_options()
pm = Progress() pm = Progress(self.uistate)
self.preview_dbase = self.get_filtered_database(self.dbstate.db, pm, preview=True) self.preview_dbase = self.get_filtered_database(self.dbstate.db, pm, preview=True)
pm.close() pm.close()
self.preview_button.set_sensitive(0) self.preview_button.set_sensitive(0)

View File

@ -103,7 +103,9 @@ class BatchTool(Tool):
Should be used for tools using batch transactions. Should be used for tools using batch transactions.
""" """
def __init__(self, dbstate, user, options_class, name): def __init__(self, dbstate, user, options_class, name, parent=None):
if user.uistate:
parent = user.uistate.window
if not user.prompt( if not user.prompt(
_('Undo history warning'), _('Undo history warning'),
_('Proceeding with this tool will erase the undo history ' _('Proceeding with this tool will erase the undo history '
@ -112,7 +114,7 @@ class BatchTool(Tool):
'made prior to it.\n\n' 'made prior to it.\n\n'
'If you think you may want to revert running this tool, ' 'If you think you may want to revert running this tool, '
'please stop here and backup your database.'), 'please stop here and backup your database.'),
_('_Proceed with the tool'), _('_Stop')): _('_Proceed with the tool'), _('_Stop'), parent):
self.fail = True self.fail = True
return return

View File

@ -88,7 +88,7 @@ class User(user.User):
self._progress.close() self._progress.close()
self._progress = None self._progress = None
def prompt(self, title, message, accept_label, reject_label): def prompt(self, title, message, accept_label, reject_label, parent=None):
""" """
Prompt the user with a message to select an alternative. Prompt the user with a message to select an alternative.
@ -106,7 +106,7 @@ class User(user.User):
:returns: the user's answer to the question :returns: the user's answer to the question
:rtype: bool :rtype: bool
""" """
dialog = QuestionDialog2(title, message, accept_label, reject_label) dialog = QuestionDialog2(title, message, accept_label, reject_label, parent)
return dialog.run() return dialog.run()
def warn(self, title, warning=""): def warn(self, title, warning=""):

View File

@ -1308,7 +1308,8 @@ class ViewManager(CLIManager):
_("Backup file already exists! Overwrite?"), _("Backup file already exists! Overwrite?"),
_("The file '%s' exists.") % filename, _("The file '%s' exists.") % filename,
_("Proceed and overwrite"), _("Proceed and overwrite"),
_("Cancel the backup")) _("Cancel the backup"),
parent=self.window)
yes_no = question.run() yes_no = question.run()
if not yes_no: if not yes_no:
return return
@ -1339,7 +1340,8 @@ class ViewManager(CLIManager):
right pane, otherwise FileChooserDialog will hang. right pane, otherwise FileChooserDialog will hang.
""" """
f = Gtk.FileChooserDialog( f = Gtk.FileChooserDialog(
_("Select backup directory"), title=_("Select backup directory"),
parent=self.window,
action=Gtk.FileChooserAction.SELECT_FOLDER, action=Gtk.FileChooserAction.SELECT_FOLDER,
buttons=(Gtk.STOCK_CANCEL, buttons=(Gtk.STOCK_CANCEL,
Gtk.ResponseType.CANCEL, Gtk.ResponseType.CANCEL,

View File

@ -3,7 +3,9 @@
<interface> <interface>
<requires lib="gtk+" version="3.0"/> <requires lib="gtk+" version="3.0"/>
<object class="GtkDialog" id="check"> <object class="GtkDialog" id="check">
<!-- This dialog is ManagedWindow class
<property name="visible">True</property> <property name="visible">True</property>
-->
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="default_width">450</property> <property name="default_width">450</property>
<property name="default_height">400</property> <property name="default_height">400</property>

View File

@ -83,7 +83,7 @@ from gramps.gen.constfunc import UNITYPE, cuni, handle2internal, conv_to_unicode
strip_dict = dict.fromkeys(list(range(9))+list(range(11,13))+list(range(14, 32)), " ") strip_dict = dict.fromkeys(list(range(9))+list(range(11,13))+list(range(14, 32)), " ")
class ProgressMeter(object): class ProgressMeter(object):
def __init__(self, *args): pass def __init__(self, *args, **kwargs): pass
def set_pass(self, *args): pass def set_pass(self, *args): pass
def step(self): pass def step(self): pass
def close(self): pass def close(self): pass
@ -93,7 +93,7 @@ class ProgressMeter(object):
# Low Level repair # Low Level repair
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
def cross_table_duplicates(db): def cross_table_duplicates(db, uistate):
""" """
Function to find the presence of identical handles that occur in different Function to find the presence of identical handles that occur in different
database tables. database tables.
@ -105,7 +105,11 @@ def cross_table_duplicates(db):
:returns: the presence of cross table duplicate handles :returns: the presence of cross table duplicate handles
:rtype: bool :rtype: bool
""" """
progress = ProgressMeter(_('Checking Database'),'') if uistate:
parent = uistate.window
else:
parent = None
progress = ProgressMeter(_('Checking Database'),'', parent)
progress.set_pass(_('Looking for cross table duplicates'), 9) progress.set_pass(_('Looking for cross table duplicates'), 9)
logging.info('Looking for cross table duplicates') logging.info('Looking for cross table duplicates')
total_nr_handles = 0 total_nr_handles = 0
@ -154,7 +158,7 @@ class Check(tool.BatchTool):
# As such, we run it before starting the transaction. # As such, we run it before starting the transaction.
# We only do this for the dbdir backend. # We only do this for the dbdir backend.
if self.db.__class__.__name__ == 'DbBsddb': if self.db.__class__.__name__ == 'DbBsddb':
if cross_table_duplicates(self.db): if cross_table_duplicates(self.db, uistate):
Report(uistate, _( Report(uistate, _(
"Your Family Tree contains cross table duplicate handles.\n " "Your Family Tree contains cross table duplicate handles.\n "
"This is bad and can be fixed by making a backup of your\n" "This is bad and can be fixed by making a backup of your\n"
@ -216,6 +220,11 @@ class Check(tool.BatchTool):
class CheckIntegrity(object): class CheckIntegrity(object):
def __init__(self, dbstate, uistate, trans): def __init__(self, dbstate, uistate, trans):
self.uistate = uistate
if self.uistate:
self.parent_window = self.uistate.window
else:
self.parent_window = None
self.db = dbstate.db self.db = dbstate.db
self.trans = trans self.trans = trans
self.bad_photo = [] self.bad_photo = []
@ -243,7 +252,8 @@ class CheckIntegrity(object):
self.empty_objects = defaultdict(list) self.empty_objects = defaultdict(list)
self.replaced_sourceref = [] self.replaced_sourceref = []
self.last_img_dir = config.get('behavior.addmedia-image-dir') self.last_img_dir = config.get('behavior.addmedia-image-dir')
self.progress = ProgressMeter(_('Checking Database'),'') self.progress = ProgressMeter(_('Checking Database'),'',
parent=self.parent_window)
self.explanation = Note(_('Objects referenced by this note ' self.explanation = Note(_('Objects referenced by this note '
'were referenced but missing so that is why they have been created ' 'were referenced but missing so that is why they have been created '
'when you ran Check and Repair on %s.') % 'when you ran Check and Repair on %s.') %
@ -723,7 +733,7 @@ class CheckIntegrity(object):
"You may choose to either remove the reference from the database, " "You may choose to either remove the reference from the database, "
"keep the reference to the missing file, or select a new file." "keep the reference to the missing file, or select a new file."
) % {'file_name' : '<b>%s</b>' % photo_name}, ) % {'file_name' : '<b>%s</b>' % photo_name},
remove_clicked, leave_clicked, select_clicked) remove_clicked, leave_clicked, select_clicked, parent=self.uistate.window)
missmedia_action = mmd.default_action missmedia_action = mmd.default_action
elif missmedia_action == 1: elif missmedia_action == 1:
logging.warning(' FAIL: media object "%(desc)s" ' logging.warning(' FAIL: media object "%(desc)s" '

View File

@ -63,13 +63,22 @@ class DateParserDisplayTest(tool.Tool):
tool.Tool.__init__(self, dbstate, options_class, name) tool.Tool.__init__(self, dbstate, options_class, name)
if uistate: if uistate:
# Running with gui -> Show message # Running with gui -> Show message
QuestionDialog(_("Start date test?"),_("This test will create many persons and events in the current database. Do you really want to run this test?"),_("Run test"),self.run_tool) self.parent_window = uistate.window
QuestionDialog(_("Start date test?"),
_("This test will create many persons and events " \
"in the current database. Do you really want to " \
"run this test?"),
_("Run test"),
self.run_tool,
parent=self.parent_window)
else: else:
self.parent_window = None
self.run_tool() self.run_tool()
def run_tool(self): def run_tool(self):
self.progress = ProgressMeter(_('Running Date Test'),'') self.progress = ProgressMeter(_('Running Date Test'),'',
parent=self.parent_window)
self.progress.set_pass(_('Generating dates'), self.progress.set_pass(_('Generating dates'),
4) 4)
dates = [] dates = []

View File

@ -134,7 +134,7 @@ class EventComparison(tool.Tool,ManagedWindow):
}) })
window = self.filterDialog.toplevel window = self.filterDialog.toplevel
window.show() #window.show()
self.filters = self.filterDialog.get_object("filter_list") self.filters = self.filterDialog.get_object("filter_list")
self.label = _('Event comparison filter selection') self.label = _('Event comparison filter selection')
self.set_window(window,self.filterDialog.get_object('title'), self.set_window(window,self.filterDialog.get_object('title'),
@ -177,7 +177,8 @@ class EventComparison(tool.Tool,ManagedWindow):
def on_apply_clicked(self, obj): def on_apply_clicked(self, obj):
cfilter = self.filter_model[self.filters.get_active()][1] cfilter = self.filter_model[self.filters.get_active()][1]
progress_bar = ProgressMeter(_('Comparing events'),'') progress_bar = ProgressMeter(_('Comparing events'),'',
parent=self.window)
progress_bar.set_pass(_('Selecting people'),1) progress_bar.set_pass(_('Selecting people'),1)
plist = cfilter.apply(self.db, plist = cfilter.apply(self.db,
@ -190,7 +191,7 @@ class EventComparison(tool.Tool,ManagedWindow):
self.options.handler.save_options() self.options.handler.save_options()
if len(plist) == 0: if len(plist) == 0:
WarningDialog(_("No matches were found")) WarningDialog(_("No matches were found"), parent=self.window)
else: else:
DisplayChart(self.dbstate,self.uistate,plist,self.track) DisplayChart(self.dbstate,self.uistate,plist,self.track)
@ -238,7 +239,6 @@ class DisplayChart(ManagedWindow):
}) })
window = self.topDialog.toplevel window = self.topDialog.toplevel
window.show()
self.set_window(window, self.topDialog.get_object('title'), self.set_window(window, self.topDialog.get_object('title'),
_('Event Comparison Results')) _('Event Comparison Results'))
@ -306,7 +306,8 @@ class DisplayChart(ManagedWindow):
self.progress_bar.close() self.progress_bar.close()
def build_row_data(self): def build_row_data(self):
self.progress_bar = ProgressMeter(_('Comparing Events'),'') self.progress_bar = ProgressMeter(_('Comparing Events'),'',
parent=self.window)
self.progress_bar.set_pass(_('Building data'),len(self.my_list)) self.progress_bar.set_pass(_('Building data'),len(self.my_list))
for individual_id in self.my_list: for individual_id in self.my_list:
individual = self.db.get_person_from_handle(individual_id) individual = self.db.get_person_from_handle(individual_id)

View File

@ -129,11 +129,16 @@ class TestcaseGenerator(tool.BatchTool):
def __init__(self, dbstate, user, options_class, name, callback=None): def __init__(self, dbstate, user, options_class, name, callback=None):
uistate = user.uistate uistate = user.uistate
if uistate:
parent_window = uistate.window
else:
parent_window = None
self.person = None self.person = None
if dbstate.db.readonly: if dbstate.db.readonly:
return return
tool.BatchTool.__init__(self, dbstate, user, options_class, name) tool.BatchTool.__init__(self, dbstate, user, options_class, name,
parent=parent_window)
if self.fail: if self.fail:
return return
@ -192,7 +197,7 @@ class TestcaseGenerator(tool.BatchTool):
def init_gui(self,uistate): def init_gui(self,uistate):
title = "%s - Gramps" % _("Generate testcases") title = "%s - Gramps" % _("Generate testcases")
self.top = Gtk.Dialog(title) self.top = Gtk.Dialog(title, parent=uistate.window)
self.top.set_default_size(400,150) self.top.set_default_size(400,150)
self.top.vbox.set_spacing(5) self.top.vbox.set_spacing(5)
label = Gtk.Label(label='<span size="larger" weight="bold">%s</span>' % _("Generate testcases")) label = Gtk.Label(label='<span size="larger" weight="bold">%s</span>' % _("Generate testcases"))
@ -279,7 +284,7 @@ class TestcaseGenerator(tool.BatchTool):
while Gtk.events_pending(): while Gtk.events_pending():
Gtk.main_iteration() Gtk.main_iteration()
self.progress = ProgressMeter(_('Generating testcases'),'') self.progress = ProgressMeter(_('Generating testcases'),'', parent=self.window)
self.transaction_count = 0; self.transaction_count = 0;
if self.options.handler.options_dict['lowlevel']: if self.options.handler.options_dict['lowlevel']: