summaryrefslogtreecommitdiff
path: root/grc/gui/FileDialogs.py
diff options
context:
space:
mode:
authorMarcus Müller <marcus@hostalia.de>2018-09-21 00:00:57 +0200
committerMarcus Müller <marcus@hostalia.de>2018-09-21 00:00:57 +0200
commit267d669eb21c514c18a6ee979f5cf247d251f1ad (patch)
treec6120f5993f82daf13894e8bf905c4169493152e /grc/gui/FileDialogs.py
parent896d1c9da31963ecf5b0d90942c2af51ca998a69 (diff)
parent7b20b28a9e5aa4e32ee37e89e7f80d74485344e8 (diff)
Merge branch 'merge_next' (which merges next)
This has been in the making far too long. We finally merge the next branch into master, in preparation of releasing GNU Radio 3.8. There will be breakage. There will be awesomeness. There will be progress in the greatest SDR framework to ever grace the surface of the earth. Hold tight for now.
Diffstat (limited to 'grc/gui/FileDialogs.py')
-rw-r--r--grc/gui/FileDialogs.py296
1 files changed, 126 insertions, 170 deletions
diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py
index 88058c9bd4..e8c5800d6a 100644
--- a/grc/gui/FileDialogs.py
+++ b/grc/gui/FileDialogs.py
@@ -17,141 +17,99 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-import pygtk
-pygtk.require('2.0')
-import gtk
-from Dialogs import MessageDialogHelper
-from Constants import \
- DEFAULT_FILE_PATH, IMAGE_FILE_EXTENSION, TEXT_FILE_EXTENSION, \
- NEW_FLOGRAPH_TITLE
-import Preferences
-from os import path
-import Utils
-
-##################################################
-# Constants
-##################################################
-OPEN_FLOW_GRAPH = 'open flow graph'
-SAVE_FLOW_GRAPH = 'save flow graph'
-SAVE_CONSOLE = 'save console'
-SAVE_IMAGE = 'save image'
-OPEN_QSS_THEME = 'open qss theme'
-
-FILE_OVERWRITE_MARKUP_TMPL="""\
-File <b>$encode($filename)</b> Exists!\nWould you like to overwrite the existing file?"""
-
-FILE_DNE_MARKUP_TMPL="""\
-File <b>$encode($filename)</b> Does not Exist!"""
-
-
-
-# File Filters
-def get_flow_graph_files_filter():
- filter = gtk.FileFilter()
- filter.set_name('Flow Graph Files')
- filter.add_pattern('*'+Preferences.file_extension())
- return filter
-
-
-def get_text_files_filter():
- filter = gtk.FileFilter()
- filter.set_name('Text Files')
- filter.add_pattern('*'+TEXT_FILE_EXTENSION)
- return filter
-
-
-def get_image_files_filter():
- filter = gtk.FileFilter()
- filter.set_name('Image Files')
- filter.add_pattern('*'+IMAGE_FILE_EXTENSION)
- return filter
-
+from __future__ import absolute_import
-def get_all_files_filter():
- filter = gtk.FileFilter()
- filter.set_name('All Files')
- filter.add_pattern('*')
- return filter
+from os import path
+from gi.repository import Gtk
-def get_qss_themes_filter():
- filter = gtk.FileFilter()
- filter.set_name('QSS Themes')
- filter.add_pattern('*.qss')
- return filter
+from . import Constants, Utils, Dialogs
-# File Dialogs
-class FileDialogHelper(gtk.FileChooserDialog):
+class FileDialogHelper(Gtk.FileChooserDialog, object):
"""
A wrapper class for the gtk file chooser dialog.
Implement a file chooser dialog with only necessary parameters.
"""
+ title = ''
+ action = Gtk.FileChooserAction.OPEN
+ filter_label = ''
+ filter_ext = ''
- def __init__(self, action, title, parent):
+ def __init__(self, parent, current_file_path):
"""
FileDialogHelper constructor.
Create a save or open dialog with cancel and ok buttons.
Use standard settings: no multiple selection, local files only, and the * filter.
Args:
- action: gtk.FILE_CHOOSER_ACTION_OPEN or gtk.FILE_CHOOSER_ACTION_SAVE
+ action: Gtk.FileChooserAction.OPEN or Gtk.FileChooserAction.SAVE
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, parent, action, ('gtk-cancel', gtk.RESPONSE_CANCEL, ok_stock, gtk.RESPONSE_OK))
+ ok_stock = {
+ Gtk.FileChooserAction.OPEN: 'gtk-open',
+ Gtk.FileChooserAction.SAVE: 'gtk-save'
+ }[self.action]
+
+ Gtk.FileChooserDialog.__init__(self, title=self.title, action=self.action,
+ transient_for=parent)
+ self.add_buttons('gtk-cancel', Gtk.ResponseType.CANCEL, ok_stock, Gtk.ResponseType.OK)
self.set_select_multiple(False)
self.set_local_only(True)
- self.add_filter(get_all_files_filter())
+
+ self.parent = parent
+ self.current_file_path = current_file_path or path.join(
+ Constants.DEFAULT_FILE_PATH, Constants.NEW_FLOGRAPH_TITLE + Constants.FILE_EXTENSION)
+
+ self.set_current_folder(path.dirname(current_file_path)) # current directory
+ self.setup_filters()
+
+ def setup_filters(self, filters=None):
+ set_default = True
+ filters = filters or ([(self.filter_label, self.filter_ext)] if self.filter_label else [])
+ filters.append(('All Files', ''))
+ for label, ext in filters:
+ if not label:
+ continue
+ f = Gtk.FileFilter()
+ f.set_name(label)
+ f.add_pattern('*' + ext)
+ self.add_filter(f)
+ if not set_default:
+ self.set_filter(f)
+ set_default = True
+
+ def run(self):
+ """Get the filename and destroy the dialog."""
+ response = Gtk.FileChooserDialog.run(self)
+ filename = self.get_filename() if response == Gtk.ResponseType.OK else None
+ self.destroy()
+ return filename
-class FileDialog(FileDialogHelper):
+class SaveFileDialog(FileDialogHelper):
"""A dialog box to save or open flow graph files. This is a base class, do not use."""
+ action = Gtk.FileChooserAction.SAVE
- def __init__(self, parent, current_file_path=''):
- """
- FileDialog constructor.
+ def __init__(self, parent, current_file_path):
+ super(SaveFileDialog, self).__init__(parent, current_file_path)
+ self.set_current_name(path.splitext(path.basename(self.current_file_path))[0] + self.filter_ext)
+ self.set_create_folders(True)
+ self.set_do_overwrite_confirmation(True)
- Args:
- current_file_path: the current directory or path to the open flow graph
- """
- 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...', 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...', 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...', 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...', 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...', 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
-
-
- def add_and_set_filter(self, filter):
- """
- Add the gtk file filter to the list of filters and set it as the default file filter.
- Args:
- filter: a gtk file filter.
- """
- self.add_filter(filter)
- self.set_filter(filter)
+class OpenFileDialog(FileDialogHelper):
+ """A dialog box to save or open flow graph files. This is a base class, do not use."""
+ action = Gtk.FileChooserAction.OPEN
- def get_rectified_filename(self):
+ def show_missing_message(self, filename):
+ Dialogs.MessageDialogWrapper(
+ self.parent,
+ Gtk.MessageType.WARNING, Gtk.ButtonsType.CLOSE, 'Cannot Open!',
+ 'File <b>{filename}</b> Does not Exist!'.format(filename=Utils.encode(filename)),
+ ).run_and_destroy()
+
+ def get_filename(self):
"""
Run the dialog and get the filename.
If this is a save dialog and the file name is missing the extension, append the file extension.
@@ -161,84 +119,82 @@ class FileDialog(FileDialogHelper):
Returns:
the complete file path
"""
- if gtk.FileChooserDialog.run(self) != gtk.RESPONSE_OK: return None #response was cancel
- #############################################
- # Handle Save Dialogs
- #############################################
- if self.type in (SAVE_FLOW_GRAPH, SAVE_CONSOLE, SAVE_IMAGE):
- filename = self.get_filename()
- extension = {
- SAVE_FLOW_GRAPH: Preferences.file_extension(),
- SAVE_CONSOLE: TEXT_FILE_EXTENSION,
- SAVE_IMAGE: IMAGE_FILE_EXTENSION,
- }[self.type]
- #append the missing file extension if the filter matches
- if path.splitext(filename)[1].lower() != extension: filename += extension
- self.set_current_name(path.basename(filename)) #show the filename with extension
- if path.exists(filename): #ask the user to confirm overwrite
- if MessageDialogHelper(
- gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, self.parent,
- title='Confirm Overwrite!',
- markup=Utils.parse_template(FILE_OVERWRITE_MARKUP_TMPL, filename=filename),
- ) == gtk.RESPONSE_NO: return self.get_rectified_filename()
- return filename
- #############################################
- # Handle Open Dialogs
- #############################################
- elif self.type in (OPEN_FLOW_GRAPH, OPEN_QSS_THEME):
- filenames = self.get_filenames()
- for filename in filenames:
- if not path.exists(filename): #show a warning and re-run
- MessageDialogHelper(
- gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, self.parent,
- title='Cannot Open!',
- markup=Utils.parse_template(FILE_DNE_MARKUP_TMPL, filename=filename),
- )
- return self.get_rectified_filename()
- return filenames
+ filenames = Gtk.FileChooserDialog.get_filenames(self)
+ for filename in filenames:
+ if not path.exists(filename):
+ self.show_missing_message(filename)
+ return None # rerun
+ return filenames
- def run(self):
- """
- Get the filename and destroy the dialog.
-
- Returns:
- the filename or None if a close/cancel occurred.
- """
- filename = self.get_rectified_filename()
- self.destroy()
- return filename
+class OpenFlowGraph(OpenFileDialog):
+ title = 'Open a Flow Graph from a File...'
+ filter_label = 'Flow Graph Files'
+ filter_ext = Constants.FILE_EXTENSION
-class OpenFlowGraphFileDialog(FileDialog):
- type = OPEN_FLOW_GRAPH
+ def __init__(self, parent, current_file_path=''):
+ super(OpenFlowGraph, self).__init__(parent, current_file_path)
+ self.set_select_multiple(True)
-class SaveFlowGraphFileDialog(FileDialog):
- type = SAVE_FLOW_GRAPH
+class OpenQSS(OpenFileDialog):
+ title = 'Open a QSS theme...'
+ filter_label = 'QSS Themes'
+ filter_ext = '.qss'
-class OpenQSSFileDialog(FileDialog):
- type = OPEN_QSS_THEME
+class SaveFlowGraph(SaveFileDialog):
+ title = 'Save a Flow Graph to a File...'
+ filter_label = 'Flow Graph Files'
+ filter_ext = Constants.FILE_EXTENSION
-class SaveConsoleFileDialog(FileDialog):
- type = SAVE_CONSOLE
+class SaveConsole(SaveFileDialog):
+ title = 'Save Console to a File...'
+ filter_label = 'Test Files'
+ filter_ext = '.txt'
-class SaveImageFileDialog(FileDialog):
- type = SAVE_IMAGE
+class SaveScreenShot(SaveFileDialog):
+ title = 'Save a Flow Graph Screen Shot...'
+ filters = [('PDF Files', '.pdf'), ('PNG Files', '.png'), ('SVG Files', '.svg')]
+ filter_ext = '.pdf' # the default
+ def __init__(self, parent, current_file_path=''):
+ super(SaveScreenShot, self).__init__(parent, current_file_path)
-class SaveScreenShotDialog(SaveImageFileDialog):
+ self.config = Gtk.Application.get_default().config
- 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._button = button = Gtk.CheckButton(label='Background transparent')
+ self._button.set_active(self.config.screen_shot_background_transparent())
self.set_extra_widget(button)
+ def setup_filters(self, filters=None):
+ super(SaveScreenShot, self).setup_filters(self.filters)
+
+ def show_missing_message(self, filename):
+ Dialogs.MessageDialogWrapper(
+ self.parent,
+ Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, 'Can not Save!',
+ 'File Extention of <b>{filename}</b> not supported!'.format(filename=Utils.encode(filename)),
+ ).run_and_destroy()
+
def run(self):
- filename = SaveImageFileDialog.run(self)
+ valid_exts = {ext for label, ext in self.filters}
+ filename = None
+ while True:
+ response = Gtk.FileChooserDialog.run(self)
+ if response != Gtk.ResponseType.OK:
+ filename = None
+ break
+
+ filename = self.get_filename()
+ if path.splitext(filename)[1] in valid_exts:
+ break
+
+ self.show_missing_message(filename)
+
bg_transparent = self._button.get_active()
- Preferences.screen_shot_background_transparent(bg_transparent)
+ self.config.screen_shot_background_transparent(bg_transparent)
+ self.destroy()
return filename, bg_transparent