Statistics
| Branch: | Tag: | Revision:

root / grc / gui / MainWindow.py @ af1d0a61

History | View | Annotate | Download (10.4 kB)

1
"""
2
Copyright 2008, 2009, 2011 Free Software Foundation, Inc.
3
This file is part of GNU Radio
4
5
GNU Radio Companion is free software; you can redistribute it and/or
6
modify it under the terms of the GNU General Public License
7
as published by the Free Software Foundation; either version 2
8
of the License, or (at your option) any later version.
9
10
GNU Radio Companion is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18
"""
19
20
from Constants import \
21
        NEW_FLOGRAPH_TITLE, DEFAULT_REPORTS_WINDOW_WIDTH
22
import Actions
23
import pygtk
24
pygtk.require('2.0')
25
import gtk
26
import Bars
27
from BlockTreeWindow import BlockTreeWindow
28
from Dialogs import TextDisplay, MessageDialogHelper
29
from NotebookPage import NotebookPage
30
import Preferences
31
import Messages
32
import Utils
33
import os
34
35
MAIN_WINDOW_TITLE_TMPL = """\
36
#if not $saved
37
*#slurp
38
#end if
39
#if $basename
40
$basename#slurp
41
#else
42
$new_flowgraph_title#slurp
43
#end if
44
#if $read_only
45
 (read only)#slurp
46
#end if
47
#if $dirname
48
 - $dirname#slurp
49
#end if
50
 - $platform_name#slurp
51
"""
52
53
PAGE_TITLE_MARKUP_TMPL = """\
54
#set $foreground = $saved and 'black' or 'red'
55
<span foreground="$foreground">$encode($title or $new_flowgraph_title)</span>#slurp
56
#if $read_only
57
 (ro)#slurp
58
#end if
59
"""
60
61
############################################################
62
# Main window
63
############################################################
64
65
class MainWindow(gtk.Window):
66
        """The topmost window with menus, the tool bar, and other major windows."""
67
68
        def __init__(self, platform):
69
                """
70
                MainWindow contructor
71
                Setup the menu, toolbar, flowgraph editor notebook, block selection window...
72
                """
73
                self._platform = platform
74
                #setup window
75
                gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
76
                vbox = gtk.VBox()
77
                self.hpaned = gtk.HPaned()
78
                self.add(vbox)
79
                #create the menu bar and toolbar
80
                self.add_accel_group(Actions.get_accel_group())
81
                vbox.pack_start(Bars.MenuBar(), False)
82
                vbox.pack_start(Bars.Toolbar(), False)
83
                vbox.pack_start(self.hpaned)
84
                #create the notebook
85
                self.notebook = gtk.Notebook()
86
                self.page_to_be_closed = None
87
                self.current_page = None
88
                self.notebook.set_show_border(False)
89
                self.notebook.set_scrollable(True) #scroll arrows for page tabs
90
                self.notebook.connect('switch-page', self._handle_page_change)
91
                #setup containers
92
                self.flow_graph_vpaned = gtk.VPaned()
93
                #flow_graph_box.pack_start(self.scrolled_window)
94
                self.flow_graph_vpaned.pack1(self.notebook)
95
                self.hpaned.pack1(self.flow_graph_vpaned)
96
                self.hpaned.pack2(BlockTreeWindow(platform, self.get_flow_graph), False) #dont allow resize
97
                #create the reports window
98
                self.text_display = TextDisplay()
99
                #house the reports in a scrolled window
100
                self.reports_scrolled_window = gtk.ScrolledWindow()
101
                self.reports_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
102
                self.reports_scrolled_window.add_with_viewport(self.text_display)
103
                self.reports_scrolled_window.set_size_request(-1, DEFAULT_REPORTS_WINDOW_WIDTH)
104
                self.flow_graph_vpaned.pack2(self.reports_scrolled_window, False) #dont allow resize
105
                #load preferences and show the main window
106
                Preferences.load(platform)
107
                self.resize(*Preferences.main_window_size())
108
                self.flow_graph_vpaned.set_position(Preferences.reports_window_position())
109
                self.hpaned.set_position(Preferences.blocks_window_position())
110
                self.show_all()
111
112
        ############################################################
113
        # Event Handlers
114
        ############################################################
115
116
        def _quit(self, window, event):
117
                """
118
                Handle the delete event from the main window.
119
                Generated by pressing X to close, alt+f4, or right click+close.
120
                This method in turns calls the state handler to quit.
121
                @return true
122
                """
123
                Actions.APPLICATION_QUIT()
124
                return True
125
126
        def _handle_page_change(self, notebook, page, page_num):
127
                """
128
                Handle a page change. When the user clicks on a new tab,
129
                reload the flow graph to update the vars window and
130
                call handle states (select nothing) to update the buttons.
131
                @param notebook the notebook
132
                @param page new page
133
                @param page_num new page number
134
                """
135
                self.current_page = self.notebook.get_nth_page(page_num)
136
                Messages.send_page_switch(self.current_page.get_file_path())
137
                Actions.PAGE_CHANGE()
138
139
        ############################################################
140
        # Report Window
141
        ############################################################
142
143
        def add_report_line(self, line):
144
                """
145
                Place line at the end of the text buffer, then scroll its window all the way down.
146
                @param line the new text
147
                """
148
                self.text_display.insert(line)
149
                vadj = self.reports_scrolled_window.get_vadjustment()
150
                vadj.set_value(vadj.upper)
151
                vadj.emit('changed')
152
153
        ############################################################
154
        # Pages: create and close
155
        ############################################################
156
157
        def new_page(self, file_path='', show=False):
158
                """
159
                Create a new notebook page.
160
                Set the tab to be selected.
161
                @param file_path optional file to load into the flow graph
162
                @param show true if the page should be shown after loading
163
                """
164
                #if the file is already open, show the open page and return
165
                if file_path and file_path in self._get_files(): #already open
166
                        page = self.notebook.get_nth_page(self._get_files().index(file_path))
167
                        self._set_page(page)
168
                        return
169
                try: #try to load from file
170
                        if file_path: Messages.send_start_load(file_path)
171
                        flow_graph = self._platform.get_new_flow_graph()
172
                        page = NotebookPage(
173
                                self,
174
                                flow_graph=flow_graph,
175
                                file_path=file_path,
176
                        )
177
                        if file_path: Messages.send_end_load()
178
                except Exception, e: #return on failure
179
                        Messages.send_fail_load(e)
180
                        return
181
                #add this page to the notebook
182
                self.notebook.append_page(page, page.get_tab())
183
                try: self.notebook.set_tab_reorderable(page, True)
184
                except: pass #gtk too old
185
                self.notebook.set_tab_label_packing(page, False, False, gtk.PACK_START)
186
                #only show if blank or manual
187
                if not file_path or show: self._set_page(page)
188
189
        def close_pages(self):
190
                """
191
                Close all the pages in this notebook.
192
                @return true if all closed
193
                """
194
                open_files = filter(lambda file: file, self._get_files()) #filter blank files
195
                open_file = self.get_page().get_file_path()
196
                #close each page
197
                for page in self._get_pages():
198
                        self.page_to_be_closed = page
199
                        self.close_page(False)
200
                if self.notebook.get_n_pages(): return False
201
                #save state before closing
202
                Preferences.files_open(open_files)
203
                Preferences.file_open(open_file)
204
                Preferences.main_window_size(self.get_size())
205
                Preferences.reports_window_position(self.flow_graph_vpaned.get_position())
206
                Preferences.blocks_window_position(self.hpaned.get_position())
207
                Preferences.save()
208
                return True
209
210
        def close_page(self, ensure=True):
211
                """
212
                Close the current page.
213
                If the notebook becomes empty, and ensure is true,
214
                call new page upon exit to ensure that at least one page exists.
215
                @param ensure boolean
216
                """
217
                if not self.page_to_be_closed: self.page_to_be_closed = self.get_page()
218
                #show the page if it has an executing flow graph or is unsaved
219
                if self.page_to_be_closed.get_proc() or not self.page_to_be_closed.get_saved():
220
                        self._set_page(self.page_to_be_closed)
221
                #unsaved? ask the user
222
                if not self.page_to_be_closed.get_saved() and self._save_changes():
223
                        Actions.FLOW_GRAPH_SAVE() #try to save
224
                        if not self.page_to_be_closed.get_saved(): #still unsaved?
225
                                self.page_to_be_closed = None #set the page to be closed back to None
226
                                return
227
                #stop the flow graph if executing
228
                if self.page_to_be_closed.get_proc(): Actions.FLOW_GRAPH_KILL()
229
                #remove the page
230
                self.notebook.remove_page(self.notebook.page_num(self.page_to_be_closed))
231
                if ensure and self.notebook.get_n_pages() == 0: self.new_page() #no pages, make a new one
232
                self.page_to_be_closed = None #set the page to be closed back to None
233
234
        ############################################################
235
        # Misc
236
        ############################################################
237
238
        def update(self):
239
                """
240
                Set the title of the main window.
241
                Set the titles on the page tabs.
242
                Show/hide the reports window.
243
                @param title the window title
244
                """
245
                gtk.Window.set_title(self, Utils.parse_template(MAIN_WINDOW_TITLE_TMPL,
246
                                basename=os.path.basename(self.get_page().get_file_path()),
247
                                dirname=os.path.dirname(self.get_page().get_file_path()),
248
                                new_flowgraph_title=NEW_FLOGRAPH_TITLE,
249
                                read_only=self.get_page().get_read_only(),
250
                                saved=self.get_page().get_saved(),
251
                                platform_name=self._platform.get_name(),
252
                        )
253
                )
254
                #set tab titles
255
                for page in self._get_pages(): page.set_markup(
256
                        Utils.parse_template(PAGE_TITLE_MARKUP_TMPL,
257
                                #get filename and strip out file extension
258
                                title=os.path.splitext(os.path.basename(page.get_file_path()))[0],
259
                                read_only=page.get_read_only(), saved=page.get_saved(),
260
                                new_flowgraph_title=NEW_FLOGRAPH_TITLE,
261
                        )
262
                )
263
                #show/hide notebook tabs
264
                self.notebook.set_show_tabs(len(self._get_pages()) > 1)
265
266
        def get_page(self):
267
                """
268
                Get the selected page.
269
                @return the selected page
270
                """
271
                return self.current_page
272
273
        def get_flow_graph(self):
274
                """
275
                Get the selected flow graph.
276
                @return the selected flow graph
277
                """
278
                return self.get_page().get_flow_graph()
279
280
        def get_focus_flag(self):
281
                """
282
                Get the focus flag from the current page.
283
                @return the focus flag
284
                """
285
                return self.get_page().get_drawing_area().get_focus_flag()
286
287
        ############################################################
288
        # Helpers
289
        ############################################################
290
291
        def _set_page(self, page):
292
                """
293
                Set the current page.
294
                @param page the page widget
295
                """
296
                self.current_page = page
297
                self.notebook.set_current_page(self.notebook.page_num(self.current_page))
298
299
        def _save_changes(self):
300
                """
301
                Save changes to flow graph?
302
                @return true if yes
303
                """
304
                return MessageDialogHelper(
305
                        gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Unsaved Changes!',
306
                        'Would you like to save changes before closing?'
307
                ) == gtk.RESPONSE_YES
308
309
        def _get_files(self):
310
                """
311
                Get the file names for all the pages, in order.
312
                @return list of file paths
313
                """
314
                return map(lambda page: page.get_file_path(), self._get_pages())
315
316
        def _get_pages(self):
317
                """
318
                Get a list of all pages in the notebook.
319
                @return list of pages
320
                """
321
                return [self.notebook.get_nth_page(page_num) for page_num in range(self.notebook.get_n_pages())]