summaryrefslogtreecommitdiff
path: root/grc/gui/FileDialogs.py
blob: f064f02829ecdada49d8d0e2e5941e1d001bbb4e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
"""
Copyright 2007 Free Software Foundation, Inc.
This file is part of GNU Radio

SPDX-License-Identifier: GPL-2.0-or-later

"""

from __future__ import absolute_import

from os import path

from gi.repository import Gtk

from . import Constants, Utils, Dialogs


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, 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.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'
        }[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.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 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):
        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)


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 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.
        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
        """
        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


class OpenFlowGraph(OpenFileDialog):
    title = 'Open a Flow Graph from a File...'
    filter_label = 'Flow Graph Files'
    filter_ext = Constants.FILE_EXTENSION

    def __init__(self, parent, current_file_path=''):
        super(OpenFlowGraph, self).__init__(parent, current_file_path)
        self.set_select_multiple(True)


class OpenQSS(OpenFileDialog):
    title = 'Open a QSS theme...'
    filter_label = 'QSS Themes'
    filter_ext = '.qss'


class SaveFlowGraph(SaveFileDialog):
    title = 'Save a Flow Graph to a File...'
    filter_label = 'Flow Graph Files'
    filter_ext = Constants.FILE_EXTENSION


class SaveConsole(SaveFileDialog):
    title = 'Save Console to a File...'
    filter_label = 'Test Files'
    filter_ext = '.txt'


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)

        self.config = Gtk.Application.get_default().config

        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 Extension of <b>{filename}</b> not supported!'.format(filename=Utils.encode(filename)),
        ).run_and_destroy()

    def 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()
        self.config.screen_shot_background_transparent(bg_transparent)
        self.destroy()
        return filename, bg_transparent