""" Copyright 2007 Free Software Foundation, Inc. This file is part of GNU Radio GNU Radio Companion is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GNU Radio Companion is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ from __future__ import absolute_import from os import path from gi.repository import Gtk from . import Constants, Preferences, Utils from .Dialogs import MessageDialogWrapper ################################################## # 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): """ A wrapper class for the gtk file chooser dialog. Implement a file chooser dialog with only necessary parameters. """ def __init__(self, parent, action, title): """ FileDialogHelper contructor. 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.FileChooserAction.OPEN or Gtk.FileChooserAction.SAVE title: the title of the dialog (string) """ ok_stock = { Gtk.FileChooserAction.OPEN: 'gtk-open', Gtk.FileChooserAction.SAVE: 'gtk-save' }[action] Gtk.FileChooserDialog.__init__( self, title=title, action=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()) class FileDialog(FileDialogHelper): """A dialog box to save or open flow graph files. This is a base class, do not use.""" def __init__(self, parent, current_file_path=''): """ FileDialog constructor. 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. Args: filter: a gtk file filter. """ self.add_filter(filter) self.set_filter(filter) def get_rectified_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. If the file name with the extension already exists, show a overwrite dialog. If this is an open dialog, return a list of filenames. 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. Returns: the filename or None if a close/cancel occurred. """ filename = self.get_rectified_filename() self.destroy() return filename class OpenFlowGraph(FileDialog): type = OPEN_FLOW_GRAPH class SaveFlowGraph(FileDialog): type = SAVE_FLOW_GRAPH class OpenQSS(FileDialog): type = OPEN_QSS_THEME class SaveConsole(FileDialog): type = SAVE_CONSOLE class SaveImageFileDialog(FileDialog): type = SAVE_IMAGE class SaveScreenShot(SaveImageFileDialog): def __init__(self, parent, current_file_path=''): SaveImageFileDialog.__init__(self, 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 run(self): filename = SaveImageFileDialog.run(self) bg_transparent = self._button.get_active() Preferences.screen_shot_background_transparent(bg_transparent) return filename, bg_transparent