summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Koslowski <koslowski@kit.edu>2016-08-30 16:30:26 +0200
committerSebastian Koslowski <koslowski@kit.edu>2016-09-12 12:14:54 -0600
commiteb6033357a2ca8db17c4fd2cfd6f1bf789e40330 (patch)
treec928d97fd283ef74ccc04648719e12b609dda712
parentf85df8b8d9bf2a88a6b87b91d0b55fdcb8161f46 (diff)
grc: gtk3: rewrite file dialogs and support multiple extentions for screenshots
-rw-r--r--grc/gui/Constants.py4
-rw-r--r--grc/gui/FileDialogs.py273
2 files changed, 112 insertions, 165 deletions
diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py
index 516aaf92f4..2f0f7794be 100644
--- a/grc/gui/Constants.py
+++ b/grc/gui/Constants.py
@@ -27,10 +27,6 @@ from ..core.Constants import *
# default path for the open/save dialogs
DEFAULT_FILE_PATH = os.getcwd()
-# file extensions
-IMAGE_FILE_EXTENSION = '.png'
-TEXT_FILE_EXTENSION = '.txt'
-
# name for new/unsaved flow graphs
NEW_FLOGRAPH_TITLE = 'untitled'
diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py
index afd41af58c..cbb7bcaa69 100644
--- a/grc/gui/FileDialogs.py
+++ b/grc/gui/FileDialogs.py
@@ -23,64 +23,20 @@ from os import path
from gi.repository import Gtk
-from . import Constants, Preferences, Utils
-from .Dialogs import MessageDialogWrapper
+from . import Constants, Preferences, Utils, Dialogs
-##################################################
-# 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 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('*' + Constants.TEXT_FILE_EXTENSION)
- return filter
-
-
-def get_image_files_filter():
- filter = Gtk.FileFilter()
- filter.set_name('Image Files')
- filter.add_pattern('*' + Constants.IMAGE_FILE_EXTENSION)
- return filter
-
-
-def get_all_files_filter():
- filter = Gtk.FileFilter()
- filter.set_name('All Files')
- filter.add_pattern('*')
- return filter
-
-
-def get_qss_themes_filter():
- filter = Gtk.FileFilter()
- filter.set_name('QSS Themes')
- filter.add_pattern('*.qss')
- return filter
-
-
-# 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, parent, action, title):
+ def __init__(self, parent, current_file_path):
"""
FileDialogHelper contructor.
Create a save or open dialog with cancel and ok buttons.
@@ -93,66 +49,67 @@ class FileDialogHelper(Gtk.FileChooserDialog):
ok_stock = {
Gtk.FileChooserAction.OPEN: 'gtk-open',
Gtk.FileChooserAction.SAVE: 'gtk-save'
- }[action]
+ }[self.action]
- Gtk.FileChooserDialog.__init__(
- self, title=title, action=action,
- transient_for=parent
- )
+ 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 + Preferences.file_extension())
-class FileDialog(FileDialogHelper):
+ 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 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(Constants.DEFAULT_FILE_PATH,
- Constants.NEW_FLOGRAPH_TITLE + Preferences.file_extension())
- if self.type == OPEN_FLOW_GRAPH:
- FileDialogHelper.__init__(self, parent, Gtk.FileChooserAction.OPEN, 'Open a Flow Graph from a File...')
- self.add_and_set_filter(get_flow_graph_files_filter())
- self.set_select_multiple(True)
- elif self.type == SAVE_FLOW_GRAPH:
- FileDialogHelper.__init__(self, parent, Gtk.FileChooserAction.SAVE, 'Save a Flow Graph to a File...')
- 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, parent, Gtk.FileChooserAction.SAVE, 'Save Console to a File...')
- 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, parent, Gtk.FileChooserAction.SAVE, 'Save a Flow Graph Screen Shot...')
- self.add_and_set_filter(get_image_files_filter())
- current_file_path = current_file_path + Constants.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, parent, Gtk.FileChooserAction.OPEN, 'Open a QSS theme...')
- 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.
+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
- Args:
- filter: a gtk file filter.
- """
- self.add_filter(filter)
- self.set_filter(filter)
+ 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_rectified_filename(self):
+ 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.
@@ -162,86 +119,80 @@ class FileDialog(FileDialogHelper):
Returns:
the complete file path
"""
- if Gtk.FileChooserDialog.run(self) != Gtk.ResponseType.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: Constants.TEXT_FILE_EXTENSION,
- SAVE_IMAGE: Constants.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
- response = MessageDialogWrapper(
- Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, 'Confirm Overwrite!',
- 'File <b>{filename}</b> Exists!\nWould you like to overwrite the existing file?'
- ''.format(filename=Utils.encode(filename)),
- ).run_and_destroy()
- if response == Gtk.ResponseType.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
- MessageDialogWrapper(
- Gtk.MessageType.WARNING, Gtk.ButtonsType.CLOSE, 'Cannot Open!',
- 'File <b>{filename}</b> Does not Exist!'.format(filename=Utils.encode(filename)),
- ).run_and_destroy()
- return self.get_rectified_filename()
- return filenames
-
- def run(self):
- """
- Get the filename and destroy the dialog.
+ 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
- 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 = Preferences.file_extension()
-class OpenFlowGraph(FileDialog):
- type = OPEN_FLOW_GRAPH
-
-
-class SaveFlowGraph(FileDialog):
- type = SAVE_FLOW_GRAPH
+ def __init__(self, parent, current_file_path=''):
+ super(OpenFlowGraph, self).__init__(parent, current_file_path)
+ self.set_select_multiple(True)
-class OpenQSS(FileDialog):
- type = OPEN_QSS_THEME
+class OpenQSS(OpenFileDialog):
+ title = 'Open a QSS theme...'
+ filter_label = 'QSS Themes'
+ filter_ext = '.qss'
-class SaveConsole(FileDialog):
- type = SAVE_CONSOLE
+class SaveFlowGraph(SaveFileDialog):
+ title = 'Save a Flow Graph to a File...'
+ filter_label = 'Flow Graph Files'
+ filter_ext = Preferences.file_extension()
-class SaveImageFileDialog(FileDialog):
- type = SAVE_IMAGE
+class SaveConsole(SaveFileDialog):
+ title = 'Save Console to a File...'
+ filter_label = 'Test Files'
+ filter_ext = '.txt'
-class SaveScreenShot(SaveImageFileDialog):
+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=''):
- SaveImageFileDialog.__init__(self, parent, current_file_path)
+ super(SaveScreenShot, self).__init__(parent, current_file_path)
+
self._button = button = Gtk.CheckButton(label='Background transparent')
self._button.set_active(Preferences.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.destroy()
return filename, bg_transparent