summaryrefslogtreecommitdiff
path: root/grc/gui
diff options
context:
space:
mode:
authorEthan Trewhitt <ethan@trewhitt.org>2017-10-25 13:36:33 -0400
committerEthan Trewhitt <ethan@trewhitt.org>2017-10-25 21:20:38 -0400
commita3d5c7fdcef630a902b62305c2b0c57121e24209 (patch)
tree9240972f1d320f4e8c78abd1397c618436f2f1ba /grc/gui
parenta0adcd3347c7ffd6ef3c42ce7705a23978774d3b (diff)
Added parent (aka 'transient for') references to most (if not all) dialog boxes. First attempt at fixing #1494.
Diffstat (limited to 'grc/gui')
-rw-r--r--grc/gui/ActionHandler.py24
-rw-r--r--grc/gui/Dialogs.py58
-rw-r--r--grc/gui/FileDialogs.py20
-rw-r--r--grc/gui/FlowGraph.py4
-rw-r--r--grc/gui/MainWindow.py2
-rw-r--r--grc/gui/Param.py9
-rw-r--r--grc/gui/PropsDialog.py6
7 files changed, 68 insertions, 55 deletions
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 017dab3346..aba9033d74 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -384,13 +384,13 @@ class ActionHandler:
##################################################
elif action == Actions.ABOUT_WINDOW_DISPLAY:
platform = flow_graph.get_parent()
- Dialogs.AboutDialog(platform.config)
+ Dialogs.AboutDialog(platform.config, main)
elif action == Actions.HELP_WINDOW_DISPLAY:
- Dialogs.HelpDialog()
+ Dialogs.HelpDialog(main)
elif action == Actions.TYPES_WINDOW_DISPLAY:
- Dialogs.TypesDialog(flow_graph.get_parent())
+ Dialogs.TypesDialog(flow_graph.get_parent(), main)
elif action == Actions.ERRORS_WINDOW_DISPLAY:
- Dialogs.ErrorsDialog(flow_graph)
+ Dialogs.ErrorsDialog(flow_graph, main)
elif action == Actions.TOGGLE_CONSOLE_WINDOW:
main.update_panel_visibility(main.CONSOLE, action.get_active())
action.save_to_preferences()
@@ -406,7 +406,7 @@ class ActionHandler:
elif action == Actions.CLEAR_CONSOLE:
main.text_display.clear()
elif action == Actions.SAVE_CONSOLE:
- file_path = SaveConsoleFileDialog(page.get_file_path()).run()
+ file_path = SaveConsoleFileDialog(page.get_file_path(), main).run()
if file_path is not None:
main.text_display.save(file_path)
elif action == Actions.TOGGLE_HIDE_DISABLED_BLOCKS:
@@ -461,7 +461,7 @@ class ActionHandler:
else:
selected_block = flow_graph.get_selected_block()
if selected_block:
- self.dialog = PropsDialog(selected_block)
+ self.dialog = PropsDialog(selected_block, main)
response = gtk.RESPONSE_APPLY
while response == gtk.RESPONSE_APPLY: # rerun the dialog if Apply was hit
response = self.dialog.run()
@@ -520,7 +520,7 @@ class ActionHandler:
flow_graph._options_block.get_param('generate_options').set_value(args[0])
flow_graph_update(flow_graph)
elif action == Actions.FLOW_GRAPH_OPEN:
- file_paths = args if args else OpenFlowGraphFileDialog(page.get_file_path()).run()
+ file_paths = args if args else OpenFlowGraphFileDialog(main, page.get_file_path()).run()
if file_paths: #open a new page for each file, show only the first
for i,file_path in enumerate(file_paths):
main.new_page(file_path, show=(i==0))
@@ -530,7 +530,7 @@ class ActionHandler:
main.vars.update_gui()
elif action == Actions.FLOW_GRAPH_OPEN_QSS_THEME:
- file_paths = OpenQSSFileDialog(self.platform.config.install_prefix +
+ file_paths = OpenQSSFileDialog(main, self.platform.config.install_prefix +
'/share/gnuradio/themes/').run()
if file_paths:
try:
@@ -555,7 +555,7 @@ class ActionHandler:
Messages.send_fail_save(page.get_file_path())
page.set_saved(False)
elif action == Actions.FLOW_GRAPH_SAVE_AS:
- file_path = SaveFlowGraphFileDialog(page.get_file_path()).run()
+ file_path = SaveFlowGraphFileDialog(main, page.get_file_path()).run()
if file_path is not None:
page.set_file_path(file_path)
Actions.FLOW_GRAPH_SAVE()
@@ -574,7 +574,7 @@ class ActionHandler:
while os.path.exists(dup_file_path_temp):
dup_file_path_temp = dup_file_name+'('+str(count)+').grc'
count += 1
- dup_file_path_user = SaveFlowGraphFileDialog(dup_file_path_temp).run()
+ dup_file_path_user = SaveFlowGraphFileDialog(main, dup_file_path_temp).run()
if dup_file_path_user is not None:
ParseXML.to_file(flow_graph.export_data(), dup_file_path_user)
Messages.send('Saved Copy to: "' + dup_file_path_user + '"\n')
@@ -589,7 +589,7 @@ class ActionHandler:
flow_graph_update(new_flow_graph)
curr_page.set_saved(False)
elif action == Actions.FLOW_GRAPH_SCREEN_CAPTURE:
- file_path, background_transparent = SaveScreenShotDialog(page.get_file_path()).run()
+ file_path, background_transparent = SaveScreenShotDialog(main, page.get_file_path()).run()
if file_path is not None:
pixbuf = flow_graph.get_drawing_area().get_screenshot(background_transparent)
pixbuf.save(file_path, Constants.IMAGE_FILE_EXTENSION[1:])
@@ -615,7 +615,7 @@ class ActionHandler:
xterm = self.platform.config.xterm_executable
if Preferences.xterm_missing() != xterm:
if not os.path.exists(xterm):
- Dialogs.MissingXTermDialog(xterm)
+ Dialogs.MissingXTermDialog(xterm, main)
Preferences.xterm_missing(xterm)
if page.get_saved() and page.get_file_path():
Executor.ExecFlowGraphThread(
diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py
index 83ad9651b2..e23f42759a 100644
--- a/grc/gui/Dialogs.py
+++ b/grc/gui/Dialogs.py
@@ -128,16 +128,18 @@ class TextDisplay(SimpleTextDisplay):
return False
-def MessageDialogHelper(type, buttons, title=None, markup=None, default_response=None, extra_buttons=None):
+def MessageDialogHelper(type, buttons, parent, title=None, markup=None, default_response=None, extra_buttons=None):
"""
Create a modal message dialog and run it.
- Args:
+ Required args:
type: the type of message: gtk.MESSAGE_INFO, gtk.MESSAGE_WARNING, gtk.MESSAGE_QUESTION or gtk.MESSAGE_ERROR
buttons: the predefined set of buttons to use:
- gtk.BUTTONS_NONE, gtk.BUTTONS_OK, gtk.BUTTONS_CLOSE, gtk.BUTTONS_CANCEL, gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL
+ gtk.BUTTONS_NONE, gtk.BUTTONS_OK, gtk.BUTTONS_CLOSE, gtk.BUTTONS_CANCEL, gtk.BUTTONS_YES_NO,
+ gtk.BUTTONS_OK_CANCEL
+ parent: gtk parent window (which will be blocked explicitly by this modal dialog)
- Args:
+ Optional args:
title: the title of the window (string)
markup: the message text with pango markup
default_response: if set, determines which button is highlighted by default
@@ -146,7 +148,7 @@ def MessageDialogHelper(type, buttons, title=None, markup=None, default_response
Returns:
the gtk response from run()
"""
- message_dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, type, buttons)
+ message_dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL, type, buttons)
if title: message_dialog.set_title(title)
if markup: message_dialog.set_markup(markup)
if extra_buttons: message_dialog.add_buttons(*extra_buttons)
@@ -164,20 +166,23 @@ $encode($err_msg.replace('\t', ' '))
#end for"""
-def ErrorsDialog(flowgraph): MessageDialogHelper(
- type=gtk.MESSAGE_ERROR,
- buttons=gtk.BUTTONS_CLOSE,
- title='Flow Graph Errors',
- markup=Utils.parse_template(ERRORS_MARKUP_TMPL, errors=flowgraph.get_error_messages()),
-)
+def ErrorsDialog(flowgraph, parent):
+ MessageDialogHelper(
+ type=gtk.MESSAGE_ERROR,
+ buttons=gtk.BUTTONS_CLOSE,
+ parent=parent,
+ title='Flow Graph Errors',
+ markup=Utils.parse_template(ERRORS_MARKUP_TMPL, errors=flowgraph.get_error_messages()),
+ )
class AboutDialog(gtk.AboutDialog):
"""A cute little about dialog."""
- def __init__(self, config):
+ def __init__(self, config, parent):
"""AboutDialog constructor."""
gtk.AboutDialog.__init__(self)
+ self.set_transient_for(parent)
self.set_name(config.name)
self.set_version(config.version)
self.set_license(config.license)
@@ -187,11 +192,13 @@ class AboutDialog(gtk.AboutDialog):
self.destroy()
-def HelpDialog(): MessageDialogHelper(
- type=gtk.MESSAGE_INFO,
- buttons=gtk.BUTTONS_CLOSE,
- title='Help',
- markup="""\
+def HelpDialog(parent):
+ MessageDialogHelper(
+ type=gtk.MESSAGE_INFO,
+ buttons=gtk.BUTTONS_CLOSE,
+ parent=parent,
+ title='Help',
+ markup="""\
<b>Usage Tips</b>
<u>Add block</u>: drag and drop or double click a block in the block selection window.
@@ -201,7 +208,8 @@ def HelpDialog(): MessageDialogHelper(
<u>Make connection</u>: click on the source port of one block, then click on the sink port of another block.
<u>Remove connection</u>: select the connection and press delete, or drag the connection.
-* See the menu for other keyboard shortcuts.""")
+* See the menu for other keyboard shortcuts."""
+ )
COLORS_DIALOG_MARKUP_TMPL = """\
<b>Color Mapping</b>
@@ -215,20 +223,22 @@ COLORS_DIALOG_MARKUP_TMPL = """\
"""
-def TypesDialog(platform):
+def TypesDialog(platform, parent):
MessageDialogHelper(
type=gtk.MESSAGE_INFO,
buttons=gtk.BUTTONS_CLOSE,
+ parent=parent,
title='Types',
markup=Utils.parse_template(COLORS_DIALOG_MARKUP_TMPL,
colors=platform.get_colors())
)
-def MissingXTermDialog(xterm):
+def MissingXTermDialog(xterm, parent):
MessageDialogHelper(
type=gtk.MESSAGE_WARNING,
buttons=gtk.BUTTONS_OK,
+ parent=parent,
title='Warning: missing xterm executable',
markup=("The xterm executable {0!r} is missing.\n\n"
"You can change this setting in your gnuradio.conf, in "
@@ -238,7 +248,7 @@ def MissingXTermDialog(xterm):
)
-def ChooseEditorDialog(config):
+def ChooseEditorDialog(config, parent):
# Give the option to either choose an editor or use the default
# Always return true/false so the caller knows it was successful
buttons = (
@@ -247,15 +257,15 @@ def ChooseEditorDialog(config):
gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL
)
response = MessageDialogHelper(
- gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, 'Choose Editor',
- 'Would you like to choose the editor to use?', gtk.RESPONSE_YES, buttons
+ gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, parent,
+ 'Choose Editor', 'Would you like to choose the editor to use?', gtk.RESPONSE_YES, buttons
)
# Handle the inital default/choose/cancel response
# User wants to choose the editor to use
if response == gtk.RESPONSE_YES:
file_dialog = gtk.FileChooserDialog(
- 'Select an Editor...', None,
+ 'Select an Editor...', parent,
gtk.FILE_CHOOSER_ACTION_OPEN,
('gtk-cancel', gtk.RESPONSE_CANCEL, 'gtk-open', gtk.RESPONSE_OK)
)
diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py
index 9d047b1ffd..c4daae3ad6 100644
--- a/grc/gui/FileDialogs.py
+++ b/grc/gui/FileDialogs.py
@@ -88,7 +88,7 @@ class FileDialogHelper(gtk.FileChooserDialog):
Implement a file chooser dialog with only necessary parameters.
"""
- def __init__(self, action, title):
+ def __init__(self, action, title, parent):
"""
FileDialogHelper contructor.
Create a save or open dialog with cancel and ok buttons.
@@ -99,7 +99,7 @@ class FileDialogHelper(gtk.FileChooserDialog):
title: the title of the dialog (string)
"""
ok_stock = {gtk.FILE_CHOOSER_ACTION_OPEN : 'gtk-open', gtk.FILE_CHOOSER_ACTION_SAVE : 'gtk-save'}[action]
- gtk.FileChooserDialog.__init__(self, title, None, action, ('gtk-cancel', gtk.RESPONSE_CANCEL, ok_stock, gtk.RESPONSE_OK))
+ gtk.FileChooserDialog.__init__(self, title, parent, action, ('gtk-cancel', gtk.RESPONSE_CANCEL, ok_stock, gtk.RESPONSE_OK))
self.set_select_multiple(False)
self.set_local_only(True)
self.add_filter(get_all_files_filter())
@@ -108,7 +108,7 @@ class FileDialogHelper(gtk.FileChooserDialog):
class FileDialog(FileDialogHelper):
"""A dialog box to save or open flow graph files. This is a base class, do not use."""
- def __init__(self, current_file_path=''):
+ def __init__(self, parent, current_file_path=''):
"""
FileDialog constructor.
@@ -117,25 +117,25 @@ class FileDialog(FileDialogHelper):
"""
if not current_file_path: current_file_path = path.join(DEFAULT_FILE_PATH, NEW_FLOGRAPH_TITLE + Preferences.file_extension())
if self.type == OPEN_FLOW_GRAPH:
- FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 'Open a Flow Graph from a File...')
+ FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 'Open a Flow Graph from a File...', parent)
self.add_and_set_filter(get_flow_graph_files_filter())
self.set_select_multiple(True)
elif self.type == SAVE_FLOW_GRAPH:
- FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph to a File...')
+ FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph to a File...', parent)
self.add_and_set_filter(get_flow_graph_files_filter())
self.set_current_name(path.basename(current_file_path))
elif self.type == SAVE_CONSOLE:
- FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save Console to a File...')
+ FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save Console to a File...', parent)
self.add_and_set_filter(get_text_files_filter())
file_path = path.splitext(path.basename(current_file_path))[0]
self.set_current_name(file_path) #show the current filename
elif self.type == SAVE_IMAGE:
- FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph Screen Shot...')
+ FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph Screen Shot...', parent)
self.add_and_set_filter(get_image_files_filter())
current_file_path = current_file_path + IMAGE_FILE_EXTENSION
self.set_current_name(path.basename(current_file_path)) #show the current filename
elif self.type == OPEN_QSS_THEME:
- FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 'Open a QSS theme...')
+ FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 'Open a QSS theme...', parent)
self.add_and_set_filter(get_qss_themes_filter())
self.set_select_multiple(False)
self.set_current_folder(path.dirname(current_file_path)) #current directory
@@ -228,8 +228,8 @@ class SaveImageFileDialog(FileDialog):
class SaveScreenShotDialog(SaveImageFileDialog):
- def __init__(self, current_file_path=''):
- SaveImageFileDialog.__init__(self, current_file_path)
+ def __init__(self, parent, current_file_path=''):
+ SaveImageFileDialog.__init__(self, parent, current_file_path)
self._button = button = gtk.CheckButton('_Background transparent')
self._button.set_active(Preferences.screen_shot_background_transparent())
self.set_extra_widget(button)
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index e0cd7d1441..ea52a13c0c 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -82,7 +82,7 @@ class FlowGraph(Element, _Flowgraph):
break
return block_id
- def install_external_editor(self, param):
+ def install_external_editor(self, param, parent=None):
target = (param.get_parent().get_id(), param.get_key())
if target in self._external_updaters:
@@ -90,7 +90,7 @@ class FlowGraph(Element, _Flowgraph):
else:
config = self.get_parent().config
editor = (find_executable(config.editor) or
- Dialogs.ChooseEditorDialog(config))
+ Dialogs.ChooseEditorDialog(config, parent))
if not editor:
return
updater = functools.partial(
diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py
index 9a2823a7ab..205881f2e5 100644
--- a/grc/gui/MainWindow.py
+++ b/grc/gui/MainWindow.py
@@ -453,7 +453,7 @@ class MainWindow(gtk.Window):
gtk.STOCK_SAVE, gtk.RESPONSE_OK
)
return MessageDialogHelper(
- gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, 'Unsaved Changes!',
+ gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, self, 'Unsaved Changes!',
'Would you like to save changes before closing?', gtk.RESPONSE_OK, buttons
)
diff --git a/grc/gui/Param.py b/grc/gui/Param.py
index c71e1c0aa5..71acffe743 100644
--- a/grc/gui/Param.py
+++ b/grc/gui/Param.py
@@ -34,9 +34,10 @@ class InputParam(gtk.HBox):
"""The base class for an input parameter inside the input parameters dialog."""
expand = False
- def __init__(self, param, changed_callback=None, editing_callback=None):
+ def __init__(self, param, parent, changed_callback=None, editing_callback=None):
gtk.HBox.__init__(self)
self.param = param
+ self._parent = parent
self._changed_callback = changed_callback
self._editing_callback = editing_callback
self.label = gtk.Label() #no label, markup is added by set_markup
@@ -236,7 +237,7 @@ class PythonEditorParam(InputParam):
def open_editor(self, widget=None):
flowgraph = self.param.get_parent().get_parent()
- flowgraph.install_external_editor(self.param)
+ flowgraph.install_external_editor(self.param, self._parent)
def get_text(self):
pass # we never update the value from here
@@ -339,10 +340,10 @@ class FileParam(EntryParam):
#build the dialog
if self.param.get_type() == 'file_open':
- file_dialog = gtk.FileChooserDialog('Open a Data File...', None,
+ file_dialog = gtk.FileChooserDialog('Open a Data File...', self._parent,
gtk.FILE_CHOOSER_ACTION_OPEN, ('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK))
elif self.param.get_type() == 'file_save':
- file_dialog = gtk.FileChooserDialog('Save a Data File...', None,
+ file_dialog = gtk.FileChooserDialog('Save a Data File...', self._parent,
gtk.FILE_CHOOSER_ACTION_SAVE, ('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK))
file_dialog.set_do_overwrite_confirmation(True)
file_dialog.set_current_name(basename) #show the current filename
diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py
index cfea13e1a8..b299804b47 100644
--- a/grc/gui/PropsDialog.py
+++ b/grc/gui/PropsDialog.py
@@ -55,7 +55,7 @@ class PropsDialog(gtk.Dialog):
A dialog to set block parameters, view errors, and view documentation.
"""
- def __init__(self, block):
+ def __init__(self, block, parent):
"""
Properties dialog constructor.
@@ -67,6 +67,7 @@ class PropsDialog(gtk.Dialog):
gtk.Dialog.__init__(
self,
title='Properties: %s' % block.get_name(),
+ parent=parent,
buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT,
gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
gtk.STOCK_APPLY, gtk.RESPONSE_APPLY)
@@ -76,6 +77,7 @@ class PropsDialog(gtk.Dialog):
(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
))
self._block = block
+ self._parent = parent
vpaned = gtk.VPaned()
self.vbox.pack_start(vpaned)
@@ -190,7 +192,7 @@ class PropsDialog(gtk.Dialog):
if param.get_hide() == 'all':
continue
box_all_valid = box_all_valid and param.is_valid()
- input_widget = param.get_input(self._handle_changed, self._activate_apply)
+ input_widget = param.get_input(self, self._handle_changed, self._activate_apply)
vbox.pack_start(input_widget, input_widget.expand)
label.set_markup(Utils.parse_template(TAB_LABEL_MARKUP_TMPL, valid=box_all_valid, tab=tab))
# show params box with new params