diff options
Diffstat (limited to 'grc/src/gui')
-rw-r--r-- | grc/src/gui/ActionHandler.py | 408 | ||||
-rw-r--r-- | grc/src/gui/Actions.py | 167 | ||||
-rw-r--r-- | grc/src/gui/Bars.py | 137 | ||||
-rw-r--r-- | grc/src/gui/BlockTreeWindow.py | 168 | ||||
-rw-r--r-- | grc/src/gui/Constants.py | 48 | ||||
-rw-r--r-- | grc/src/gui/Dialogs.py | 100 | ||||
-rw-r--r-- | grc/src/gui/DrawingArea.py | 126 | ||||
-rw-r--r-- | grc/src/gui/FileDialogs.py | 160 | ||||
-rw-r--r-- | grc/src/gui/MainWindow.py | 299 | ||||
-rw-r--r-- | grc/src/gui/Makefile.am | 41 | ||||
-rw-r--r-- | grc/src/gui/Messages.py | 105 | ||||
-rw-r--r-- | grc/src/gui/NotebookPage.py | 197 | ||||
-rw-r--r-- | grc/src/gui/ParamsDialog.py | 144 | ||||
-rw-r--r-- | grc/src/gui/Preferences.py | 86 | ||||
-rw-r--r-- | grc/src/gui/StateCache.py | 92 | ||||
-rw-r--r-- | grc/src/gui/__init__.py | 1 |
16 files changed, 0 insertions, 2279 deletions
diff --git a/grc/src/gui/ActionHandler.py b/grc/src/gui/ActionHandler.py deleted file mode 100644 index 06e998b31..000000000 --- a/grc/src/gui/ActionHandler.py +++ /dev/null @@ -1,408 +0,0 @@ -""" -Copyright 2007, 2008, 2009 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 -""" - -import os -import signal -from Constants import IMAGE_FILE_EXTENSION -import Actions -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import Preferences -from threading import Thread -import Messages -from .. utils import ParseXML -import random -from .. platforms.gui.Platform import Platform -from MainWindow import MainWindow -from ParamsDialog import ParamsDialog -import Dialogs -from FileDialogs import OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, SaveImageFileDialog - -gobject.threads_init() - -class ActionHandler: - """ - The action handler will setup all the major window components, - and handle button presses and flow graph operations from the GUI. - """ - - def __init__(self, file_paths, platform): - """ - ActionHandler constructor. - Create the main window, setup the message handler, import the preferences, - and connect all of the action handlers. Finally, enter the gtk main loop and block. - @param file_paths a list of flow graph file passed from command line - @param platform platform module - """ - self.clipboard = None - platform = Platform(platform) - for action in Actions.get_all_actions(): action.connect('activate', self._handle_actions) - #setup the main window - self.main_window = MainWindow(self.handle_states, platform) - self.main_window.connect('delete_event', self._quit) - self.main_window.connect('key-press-event', self._handle_key_press) - self.get_page = self.main_window.get_page - self.get_flow_graph = self.main_window.get_flow_graph - self.get_focus_flag = self.main_window.get_focus_flag - #setup the messages - Messages.register_messenger(self.main_window.add_report_line) - Messages.send_init() - #initialize - self.init_file_paths = file_paths - self.handle_states(Actions.APPLICATION_INITIALIZE) - #enter the mainloop - gtk.main() - - def _handle_key_press(self, widget, event): - """ - Handle key presses from the keyboard and translate key combinations into actions. - This key press handler is called prior to the gtk key press handler. - This handler bypasses built in accelerator key handling when in focus because - * some keys are ignored by the accelerators like the direction keys, - * some keys are not registered to any accelerators but are still used. - When not in focus, gtk and the accelerators handle the the key press. - @return false to let gtk handle the key action - """ - #dont allow key presses to queue up - if gtk.events_pending(): return True - #extract action name from this key press - key_name = gtk.gdk.keyval_name(event.keyval) - mod_mask = event.state - action_name = Actions.get_action_name_from_key_name(key_name, mod_mask) - #handle the action if flow graph is in focus - if action_name and self.get_focus_flag(): - self.handle_states(action_name) - return True #handled by this method - return False #let gtk handle the key press - - def _quit(self, window, event): - """ - Handle the delete event from the main window. - Generated by pressing X to close, alt+f4, or right click+close. - This method in turns calls the state handler to quit. - @return true - """ - self.handle_states(Actions.APPLICATION_QUIT) - return True - - def _handle_actions(self, event): - """ - Handle all of the activate signals from the gtk actions. - The action signals derive from clicking on a toolbar or menu bar button. - Forward the action to the state handler. - """ - self.handle_states(event.get_name()) - - def handle_states(self, state=''): - """ - Handle the state changes in the GUI. - Handle all of the state changes that arise from the action handler or other gui and - inputs in the application. The state passed to the handle_states method is a string descriping - the change. A series of if/elif statements handle the state by greying out action buttons, causing - changes in the flow graph, saving/opening files... The handle_states method is passed to the - contructors of many of the classes used in this application enabling them to report any state change. - @param state a string describing the state change - """ - #print state - ################################################## - # Initalize/Quit - ################################################## - if state == Actions.APPLICATION_INITIALIZE: - for action in Actions.get_all_actions(): action.set_sensitive(False) #set all actions disabled - # enable a select few actions - for action in ( - Actions.APPLICATION_QUIT, Actions.FLOW_GRAPH_NEW, - Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS, - Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY, - ): Actions.get_action_from_name(action).set_sensitive(True) - if not self.init_file_paths: - self.init_file_paths = Preferences.files_open() - if not self.init_file_paths: self.init_file_paths = [''] - for file_path in self.init_file_paths: - if file_path: self.main_window.new_page(file_path) #load pages from file paths - if Preferences.file_open() in self.init_file_paths: - self.main_window.new_page(Preferences.file_open(), show=True) - if not self.get_page(): self.main_window.new_page() #ensure that at least a blank page exists - elif state == Actions.APPLICATION_QUIT: - if self.main_window.close_pages(): - gtk.main_quit() - exit(0) - ################################################## - # Selections - ################################################## - elif state == Actions.ELEMENT_SELECT: - pass #do nothing, update routines below - elif state == Actions.NOTHING_SELECT: - self.get_flow_graph().unselect() - ################################################## - # Enable/Disable - ################################################## - elif state == Actions.BLOCK_ENABLE: - if self.get_flow_graph().enable_selected(True): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == Actions.BLOCK_DISABLE: - if self.get_flow_graph().enable_selected(False): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - ################################################## - # Cut/Copy/Paste - ################################################## - elif state == Actions.BLOCK_CUT: - self.handle_states(Actions.BLOCK_COPY) - self.handle_states(Actions.ELEMENT_DELETE) - elif state == Actions.BLOCK_COPY: - self.clipboard = self.get_flow_graph().copy_to_clipboard() - elif state == Actions.BLOCK_PASTE: - if self.clipboard: - self.get_flow_graph().paste_from_clipboard(self.clipboard) - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - ################################################## - # Move/Rotate/Delete/Create - ################################################## - elif state == Actions.BLOCK_MOVE: - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == Actions.BLOCK_ROTATE_CCW: - if self.get_flow_graph().rotate_selected(90): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == Actions.BLOCK_ROTATE_CW: - if self.get_flow_graph().rotate_selected(-90): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == Actions.ELEMENT_DELETE: - if self.get_flow_graph().remove_selected(): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.handle_states(Actions.NOTHING_SELECT) - self.get_page().set_saved(False) - elif state == Actions.ELEMENT_CREATE: - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.handle_states(Actions.NOTHING_SELECT) - self.get_page().set_saved(False) - elif state == Actions.BLOCK_INC_TYPE: - if self.get_flow_graph().type_controller_modify_selected(1): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == Actions.BLOCK_DEC_TYPE: - if self.get_flow_graph().type_controller_modify_selected(-1): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == Actions.PORT_CONTROLLER_INC: - if self.get_flow_graph().port_controller_modify_selected(1): - self.get_flow_graph().update() - self.get_flow_graph().update() #2 times - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - elif state == Actions.PORT_CONTROLLER_DEC: - if self.get_flow_graph().port_controller_modify_selected(-1): - self.get_flow_graph().update() - self.get_flow_graph().update() #2 times - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - ################################################## - # Window stuff - ################################################## - elif state == Actions.ABOUT_WINDOW_DISPLAY: - Dialogs.AboutDialog() - elif state == Actions.HELP_WINDOW_DISPLAY: - Dialogs.HelpDialog() - ################################################## - # Param Modifications - ################################################## - elif state == Actions.BLOCK_PARAM_MODIFY: - selected_block = self.get_flow_graph().get_selected_block() - if selected_block and ParamsDialog(selected_block).run(): - self.get_flow_graph().update() - self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) - self.get_page().set_saved(False) - ################################################## - # Undo/Redo - ################################################## - elif state == Actions.FLOW_GRAPH_UNDO: - n = self.get_page().get_state_cache().get_prev_state() - if n: - self.get_flow_graph().unselect() - self.get_flow_graph().import_data(n) - self.get_flow_graph().update() - self.get_page().set_saved(False) - elif state == Actions.FLOW_GRAPH_REDO: - n = self.get_page().get_state_cache().get_next_state() - if n: - self.get_flow_graph().unselect() - self.get_flow_graph().import_data(n) - self.get_flow_graph().update() - self.get_page().set_saved(False) - ################################################## - # New/Open/Save/Close - ################################################## - elif state == Actions.FLOW_GRAPH_NEW: - self.main_window.new_page() - elif state == Actions.FLOW_GRAPH_OPEN: - file_paths = OpenFlowGraphFileDialog(self.get_page().get_file_path()).run() - if file_paths: #open a new page for each file, show only the first - for i,file_path in enumerate(file_paths): - self.main_window.new_page(file_path, show=(i==0)) - elif state == Actions.FLOW_GRAPH_CLOSE: - self.main_window.close_page() - elif state == Actions.FLOW_GRAPH_SAVE: - #read-only or undefined file path, do save-as - if self.get_page().get_read_only() or not self.get_page().get_file_path(): - self.handle_states(Actions.FLOW_GRAPH_SAVE_AS) - #otherwise try to save - else: - try: - ParseXML.to_file(self.get_flow_graph().export_data(), self.get_page().get_file_path()) - self.get_page().set_saved(True) - except IOError: - Messages.send_fail_save(self.get_page().get_file_path()) - self.get_page().set_saved(False) - elif state == Actions.FLOW_GRAPH_SAVE_AS: - file_path = SaveFlowGraphFileDialog(self.get_page().get_file_path()).run() - if file_path is not None: - self.get_page().set_file_path(file_path) - self.handle_states(Actions.FLOW_GRAPH_SAVE) - elif state == Actions.FLOW_GRAPH_SCREEN_CAPTURE: - file_path = SaveImageFileDialog(self.get_page().get_file_path()).run() - if file_path is not None: - pixmap = self.get_flow_graph().get_pixmap() - width, height = pixmap.get_size() - pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, width, height) - pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, width, height) - pixbuf.save(file_path, IMAGE_FILE_EXTENSION[1:]) - ################################################## - # Gen/Exec/Stop - ################################################## - elif state == Actions.FLOW_GRAPH_GEN: - if not self.get_page().get_pid(): - if not self.get_page().get_saved() or not self.get_page().get_file_path(): - self.handle_states(Actions.FLOW_GRAPH_SAVE) #only save if file path missing or not saved - if self.get_page().get_saved() and self.get_page().get_file_path(): - generator = self.get_page().get_generator() - try: - Messages.send_start_gen(generator.get_file_path()) - generator.write() - except Exception,e: Messages.send_fail_gen(e) - else: self.generator = None - elif state == Actions.FLOW_GRAPH_EXEC: - if not self.get_page().get_pid(): - self.handle_states(Actions.FLOW_GRAPH_GEN) - if self.get_page().get_saved() and self.get_page().get_file_path(): - ExecFlowGraphThread(self) - elif state == Actions.FLOW_GRAPH_KILL: - if self.get_page().get_pid(): - try: os.kill(self.get_page().get_pid(), signal.SIGKILL) - except: print "could not kill pid: %s"%self.get_page().get_pid() - elif state == '': #pass and run the global actions - pass - else: print '!!! State "%s" not handled !!!'%state - ################################################## - # Global Actions for all States - ################################################## - #update general buttons - Actions.get_action_from_name(Actions.ELEMENT_DELETE).set_sensitive(bool(self.get_flow_graph().get_selected_elements())) - Actions.get_action_from_name(Actions.BLOCK_PARAM_MODIFY).set_sensitive(bool(self.get_flow_graph().get_selected_block())) - Actions.get_action_from_name(Actions.BLOCK_ROTATE_CCW).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - Actions.get_action_from_name(Actions.BLOCK_ROTATE_CW).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - #update cut/copy/paste - Actions.get_action_from_name(Actions.BLOCK_CUT).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - Actions.get_action_from_name(Actions.BLOCK_COPY).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - Actions.get_action_from_name(Actions.BLOCK_PASTE).set_sensitive(bool(self.clipboard)) - #update enable/disable - Actions.get_action_from_name(Actions.BLOCK_ENABLE).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - Actions.get_action_from_name(Actions.BLOCK_DISABLE).set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) - #set the exec and stop buttons - self.update_exec_stop() - #saved status - Actions.get_action_from_name(Actions.FLOW_GRAPH_SAVE).set_sensitive(not self.get_page().get_saved()) - self.main_window.update() - try: #set the size of the flow graph area (if changed) - new_size = self.get_flow_graph().get_option('window_size') - if self.get_flow_graph().get_size() != tuple(new_size): - self.get_flow_graph().set_size(*new_size) - except: pass - #draw the flow graph - self.get_flow_graph().update_selected() - self.get_flow_graph().queue_draw() - - def update_exec_stop(self): - """ - Update the exec and stop buttons. - Lock and unlock the mutex for race conditions with exec flow graph threads. - """ - sensitive = self.get_flow_graph().is_valid() and not self.get_page().get_pid() - Actions.get_action_from_name(Actions.FLOW_GRAPH_GEN).set_sensitive(sensitive) - Actions.get_action_from_name(Actions.FLOW_GRAPH_EXEC).set_sensitive(sensitive) - Actions.get_action_from_name(Actions.FLOW_GRAPH_KILL).set_sensitive(self.get_page().get_pid() != None) - -class ExecFlowGraphThread(Thread): - """Execute the flow graph as a new process and wait on it to finish.""" - - def __init__ (self, action_handler): - """ - ExecFlowGraphThread constructor. - @param action_handler an instance of an ActionHandler - """ - Thread.__init__(self) - self.update_exec_stop = action_handler.update_exec_stop - self.flow_graph = action_handler.get_flow_graph() - #store page and dont use main window calls in run - self.page = action_handler.get_page() - Messages.send_start_exec(self.page.get_generator().get_file_path()) - #get the popen - try: - self.p = self.page.get_generator().get_popen() - self.page.set_pid(self.p.pid) - #update - self.update_exec_stop() - self.start() - except Exception, e: - Messages.send_verbose_exec(str(e)) - Messages.send_end_exec() - - def run(self): - """ - Wait on the executing process by reading from its stdout. - Use gobject.idle_add when calling functions that modify gtk objects. - """ - #handle completion - r = "\n" - while(r): - gobject.idle_add(Messages.send_verbose_exec, r) - r = os.read(self.p.stdout.fileno(), 1024) - gobject.idle_add(self.done) - - def done(self): - """Perform end of execution tasks.""" - Messages.send_end_exec() - self.page.set_pid(None) - self.update_exec_stop() diff --git a/grc/src/gui/Actions.py b/grc/src/gui/Actions.py deleted file mode 100644 index 9b687df7e..000000000 --- a/grc/src/gui/Actions.py +++ /dev/null @@ -1,167 +0,0 @@ -""" -Copyright 2007, 2008, 2009 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 -""" - -import pygtk -pygtk.require('2.0') -import gtk - -###################################################################################################### -# Action Names -###################################################################################################### -APPLICATION_INITIALIZE = 'app init' -APPLICATION_QUIT = 'app quit' -PARAM_MODIFY = 'param modify' -BLOCK_MOVE = 'block move' -BLOCK_ROTATE_CCW = 'block rotate ccw' -BLOCK_ROTATE_CW = 'block rotate cw' -BLOCK_PARAM_MODIFY = 'block param modify' -BLOCK_INC_TYPE = 'block increment type' -BLOCK_DEC_TYPE = 'block decrement type' -BLOCK_ENABLE = 'block enable' -BLOCK_DISABLE = 'block disable' -BLOCK_CUT = 'block cut' -BLOCK_COPY = 'block copy' -BLOCK_PASTE = 'block paste' -PORT_CONTROLLER_INC = 'port controller increment' -PORT_CONTROLLER_DEC = 'port controller decrement' -ELEMENT_CREATE = 'element create' -ELEMENT_DELETE = 'element delete' -ELEMENT_SELECT = 'element select' -NOTHING_SELECT = 'nothing select' -FLOW_GRAPH_OPEN = 'flow graph open' -FLOW_GRAPH_UNDO = 'flow graph undo' -FLOW_GRAPH_REDO = 'flow graph redo' -FLOW_GRAPH_SAVE = 'flow graph save' -FLOW_GRAPH_SAVE_AS = 'flow graph save as' -FLOW_GRAPH_CLOSE = 'flow graph close' -FLOW_GRAPH_NEW = 'flow graph new' -FLOW_GRAPH_GEN = 'flow graph gen' -FLOW_GRAPH_EXEC = 'flow graph exec' -FLOW_GRAPH_KILL = 'flow graph kill' -FLOW_GRAPH_SCREEN_CAPTURE = 'flow graph screen capture' -ABOUT_WINDOW_DISPLAY = 'about window display' -HELP_WINDOW_DISPLAY = 'help window display' - -###################################################################################################### -# Action Key Map -###################################################################################################### -_actions_key_list = ( - #action name, key name, mod mask - (FLOW_GRAPH_NEW, 'n', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_OPEN, 'o', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_SAVE, 's', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_SAVE_AS, 's', gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK), - (FLOW_GRAPH_CLOSE, 'w', gtk.gdk.CONTROL_MASK), - (APPLICATION_QUIT, 'q', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_UNDO, 'z', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_REDO, 'y', gtk.gdk.CONTROL_MASK), - (ELEMENT_DELETE, 'Delete', 0), - (BLOCK_ROTATE_CCW, 'Left', 0), - (BLOCK_ROTATE_CW, 'Right', 0), - (BLOCK_DEC_TYPE, 'Up', 0), - (BLOCK_INC_TYPE, 'Down', 0), - (BLOCK_PARAM_MODIFY, 'Return', 0), - (BLOCK_ENABLE, 'e', 0), - (BLOCK_DISABLE, 'd', 0), - (BLOCK_CUT, 'x', gtk.gdk.CONTROL_MASK), - (BLOCK_COPY, 'c', gtk.gdk.CONTROL_MASK), - (BLOCK_PASTE, 'v', gtk.gdk.CONTROL_MASK), - (FLOW_GRAPH_GEN, 'F5', 0), - (FLOW_GRAPH_EXEC, 'F6', 0), - (FLOW_GRAPH_KILL, 'F7', 0), - (FLOW_GRAPH_SCREEN_CAPTURE, 'Print', 0), - (HELP_WINDOW_DISPLAY, 'F1', 0), - #the following have no associated gtk.Action - (PORT_CONTROLLER_INC, 'equal', 0), - (PORT_CONTROLLER_INC, 'plus', 0), - (PORT_CONTROLLER_INC, 'KP_Add', 0), - (PORT_CONTROLLER_DEC, 'minus', 0), - (PORT_CONTROLLER_DEC, 'KP_Subtract', 0), -) - -_actions_key_dict = dict(((key_name, mod_mask), action_name) for action_name, key_name, mod_mask in _actions_key_list) -def get_action_name_from_key_name(key_name, mod_mask=0): - """ - Get the action name associated with the key name and mask. - Both keyname and mask have to match. - @param key_name the name of the key - @param mod_mask the key press mask (shift, ctrl) 0 for none - @return the action name or blank string - """ - key_name_mod_mask = (key_name, mod_mask) - if key_name_mod_mask in _actions_key_dict: return _actions_key_dict[key_name_mod_mask] - return '' - -###################################################################################################### -# Actions -###################################################################################################### -_actions_list = ( - gtk.Action(FLOW_GRAPH_NEW, '_New', 'Create a new flow graph', gtk.STOCK_NEW), - gtk.Action(FLOW_GRAPH_OPEN, '_Open', 'Open an existing flow graph', gtk.STOCK_OPEN), - gtk.Action(FLOW_GRAPH_SAVE, '_Save', 'Save the current flow graph', gtk.STOCK_SAVE), - gtk.Action(FLOW_GRAPH_SAVE_AS, 'Save _As', 'Save the current flow graph as...', gtk.STOCK_SAVE_AS), - gtk.Action(FLOW_GRAPH_CLOSE, '_Close', 'Close the current flow graph', gtk.STOCK_CLOSE), - gtk.Action(APPLICATION_QUIT, '_Quit', 'Quit program', gtk.STOCK_QUIT), - gtk.Action(FLOW_GRAPH_UNDO, '_Undo', 'Undo a change to the flow graph', gtk.STOCK_UNDO), - gtk.Action(FLOW_GRAPH_REDO, '_Redo', 'Redo a change to the flow graph', gtk.STOCK_REDO), - gtk.Action(ELEMENT_DELETE, '_Delete', 'Delete the selected blocks', gtk.STOCK_DELETE), - gtk.Action(BLOCK_ROTATE_CCW, 'Rotate Counterclockwise', 'Rotate the selected blocks 90 degrees to the left', gtk.STOCK_GO_BACK), - gtk.Action(BLOCK_ROTATE_CW, 'Rotate Clockwise', 'Rotate the selected blocks 90 degrees to the right', gtk.STOCK_GO_FORWARD), - gtk.Action(BLOCK_PARAM_MODIFY, '_Properties', 'Modify params for the selected block', gtk.STOCK_PROPERTIES), - gtk.Action(BLOCK_ENABLE, 'E_nable', 'Enable the selected blocks', gtk.STOCK_CONNECT), - gtk.Action(BLOCK_DISABLE, 'D_isable', 'Disable the selected blocks', gtk.STOCK_DISCONNECT), - gtk.Action(BLOCK_CUT, 'Cu_t', 'Cut', gtk.STOCK_CUT), - gtk.Action(BLOCK_COPY, '_Copy', 'Copy', gtk.STOCK_COPY), - gtk.Action(BLOCK_PASTE, '_Paste', 'Paste', gtk.STOCK_PASTE), - gtk.Action(ABOUT_WINDOW_DISPLAY, '_About', 'About this program', gtk.STOCK_ABOUT), - gtk.Action(HELP_WINDOW_DISPLAY, '_Help', 'Usage Tips', gtk.STOCK_HELP), - gtk.Action(FLOW_GRAPH_GEN, '_Generate', 'Generate the flow graph', gtk.STOCK_CONVERT), - gtk.Action(FLOW_GRAPH_EXEC, '_Execute', 'Execute the flow graph', gtk.STOCK_EXECUTE), - gtk.Action(FLOW_GRAPH_KILL, '_Kill', 'Kill the flow graph', gtk.STOCK_STOP), - gtk.Action(FLOW_GRAPH_SCREEN_CAPTURE, 'S_creen Capture', 'Create a screen capture of the flow graph', gtk.STOCK_PRINT), -) -def get_all_actions(): return _actions_list - -_actions_dict = dict((action.get_name(), action) for action in _actions_list) -def get_action_from_name(action_name): - """ - Retrieve the action from the action list. - Search the list and find an action with said name. - @param action_name the action name(string) - @throw KeyError bad action name - @return a gtk action object - """ - if action_name in _actions_dict: return _actions_dict[action_name] - raise KeyError('Action Name: "%s" does not exist'%action_name) - -###################################################################################################### -# Accelerators -###################################################################################################### -_accel_group = gtk.AccelGroup() -def get_accel_group(): return _accel_group - -#set the accelerator group, and accelerator path -#register the key name and mod mask with the accelerator path -for action_name, key_name, mod_mask in _actions_key_list: - try: - accel_path = '<main>/'+action_name - get_action_from_name(action_name).set_accel_group(get_accel_group()) - get_action_from_name(action_name).set_accel_path(accel_path) - gtk.accel_map_add_entry(accel_path, gtk.gdk.keyval_from_name(key_name), mod_mask) - except KeyError: pass #no action was created for this action name diff --git a/grc/src/gui/Bars.py b/grc/src/gui/Bars.py deleted file mode 100644 index 52e7ba1f8..000000000 --- a/grc/src/gui/Bars.py +++ /dev/null @@ -1,137 +0,0 @@ -""" -Copyright 2007, 2008, 2009 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 -""" - -import Actions -import pygtk -pygtk.require('2.0') -import gtk - -##The list of actions for the toolbar. -TOOLBAR_LIST = ( - Actions.FLOW_GRAPH_NEW, - Actions.FLOW_GRAPH_OPEN, - Actions.FLOW_GRAPH_SAVE, - Actions.FLOW_GRAPH_CLOSE, - None, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, - None, - Actions.BLOCK_CUT, - Actions.BLOCK_COPY, - Actions.BLOCK_PASTE, - Actions.ELEMENT_DELETE, - None, - Actions.FLOW_GRAPH_UNDO, - Actions.FLOW_GRAPH_REDO, - None, - Actions.FLOW_GRAPH_GEN, - Actions.FLOW_GRAPH_EXEC, - Actions.FLOW_GRAPH_KILL, - None, - Actions.BLOCK_ROTATE_CCW, - Actions.BLOCK_ROTATE_CW, - None, - Actions.BLOCK_ENABLE, - Actions.BLOCK_DISABLE, -) - -##The list of actions and categories for the menu bar. -MENU_BAR_LIST = ( - (gtk.Action('File', '_File', None, None), [ - Actions.FLOW_GRAPH_NEW, - Actions.FLOW_GRAPH_OPEN, - None, - Actions.FLOW_GRAPH_SAVE, - Actions.FLOW_GRAPH_SAVE_AS, - None, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, - None, - Actions.FLOW_GRAPH_CLOSE, - Actions.APPLICATION_QUIT, - ]), - (gtk.Action('Edit', '_Edit', None, None), [ - Actions.FLOW_GRAPH_UNDO, - Actions.FLOW_GRAPH_REDO, - None, - Actions.BLOCK_CUT, - Actions.BLOCK_COPY, - Actions.BLOCK_PASTE, - Actions.ELEMENT_DELETE, - None, - Actions.BLOCK_ROTATE_CCW, - Actions.BLOCK_ROTATE_CW, - None, - Actions.BLOCK_ENABLE, - Actions.BLOCK_DISABLE, - None, - Actions.BLOCK_PARAM_MODIFY, - ]), - (gtk.Action('Build', '_Build', None, None), [ - Actions.FLOW_GRAPH_GEN, - Actions.FLOW_GRAPH_EXEC, - Actions.FLOW_GRAPH_KILL, - ]), - (gtk.Action('Help', '_Help', None, None), [ - Actions.HELP_WINDOW_DISPLAY, - None, - Actions.ABOUT_WINDOW_DISPLAY, - ]), -) - -class Toolbar(gtk.Toolbar): - """The gtk toolbar with actions added from the toolbar list.""" - - def __init__(self): - """ - Parse the list of action names in the toolbar list. - Look up the action for each name in the action list and add it to the toolbar. - """ - gtk.Toolbar.__init__(self) - self.set_style(gtk.TOOLBAR_ICONS) - for action_name in TOOLBAR_LIST: - if action_name: #add a tool item - action = Actions.get_action_from_name(action_name) - self.add(action.create_tool_item()) - #this reset of the tooltip property is required (after creating the tool item) for the tooltip to show - action.set_property('tooltip', action.get_property('tooltip')) - else: self.add(gtk.SeparatorToolItem()) - -class MenuBar(gtk.MenuBar): - """The gtk menu bar with actions added from the menu bar list.""" - - def __init__(self): - """ - Parse the list of submenus from the menubar list. - For each submenu, get a list of action names. - Look up the action for each name in the action list and add it to the submenu. - Add the submenu to the menu bar. - """ - gtk.MenuBar.__init__(self) - for main_action,action_names in MENU_BAR_LIST: - #create the main menu item - main_menu_item = main_action.create_menu_item() - self.append(main_menu_item) - #create the menu - main_menu = gtk.Menu() - main_menu_item.set_submenu(main_menu) - for action_name in action_names: - if action_name: #append a menu item - action = Actions.get_action_from_name(action_name) - main_menu.append(action.create_menu_item()) - else: main_menu.append(gtk.SeparatorMenuItem()) - main_menu.show_all() #this show all is required for the separators to show diff --git a/grc/src/gui/BlockTreeWindow.py b/grc/src/gui/BlockTreeWindow.py deleted file mode 100644 index 99056252c..000000000 --- a/grc/src/gui/BlockTreeWindow.py +++ /dev/null @@ -1,168 +0,0 @@ -""" -Copyright 2007, 2008, 2009 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 Constants import DEFAULT_BLOCKS_WINDOW_WIDTH, DND_TARGETS -from .. platforms.gui import Utils -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -NAME_INDEX = 0 -KEY_INDEX = 1 -DOC_INDEX = 2 - -class BlockTreeWindow(gtk.VBox): - """The block selection panel.""" - - def __init__(self, platform, get_flow_graph): - """ - BlockTreeWindow constructor. - Create a tree view of the possible blocks in the platform. - The tree view nodes will be category names, the leaves will be block names. - A mouse double click or button press action will trigger the add block event. - @param platform the particular platform will all block prototypes - @param get_flow_graph get the selected flow graph - """ - gtk.VBox.__init__(self) - self.platform = platform - self.get_flow_graph = get_flow_graph - #make the tree model for holding blocks - self.treestore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) - self.treeview = gtk.TreeView(self.treestore) - self.treeview.set_enable_search(False) #disable pop up search box - self.treeview.add_events(gtk.gdk.BUTTON_PRESS_MASK) - self.treeview.connect('button_press_event', self._handle_mouse_button_press) - selection = self.treeview.get_selection() - selection.set_mode('single') - selection.connect('changed', self._handle_selection_change) - renderer = gtk.CellRendererText() - column = gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX) - self.treeview.append_column(column) - #try to enable the tooltips (available in pygtk 2.12 and above) - try: self.treeview.set_tooltip_column(DOC_INDEX) - except: pass - #setup drag and drop - self.treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, DND_TARGETS, gtk.gdk.ACTION_COPY) - self.treeview.connect('drag-data-get', self._handle_drag_get_data) - #make the scrolled window to hold the tree view - scrolled_window = gtk.ScrolledWindow() - scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled_window.add_with_viewport(self.treeview) - scrolled_window.set_size_request(DEFAULT_BLOCKS_WINDOW_WIDTH, -1) - self.pack_start(scrolled_window) - #add button - self.add_button = gtk.Button(None, gtk.STOCK_ADD) - self.add_button.connect('clicked', self._handle_add_button) - self.pack_start(self.add_button, False) - #map categories to iters, automatic mapping for root - self._categories = {tuple(): None} - #add blocks and categories - self.platform.load_block_tree(self) - #initialize - self._update_add_button() - - ############################################################ - ## Block Tree Methods - ############################################################ - def add_block(self, category, block=None): - """ - Add a block with category to this selection window. - Add only the category when block is None. - @param category the category list or path string - @param block the block object or None - """ - if isinstance(category, str): category = category.split('/') - category = tuple(filter(lambda x: x, category)) #tuple is hashable - #add category and all sub categories - for i, cat_name in enumerate(category): - sub_category = category[:i+1] - if sub_category not in self._categories: - iter = self.treestore.insert_before(self._categories[sub_category[:-1]], None) - self.treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name) - self.treestore.set_value(iter, KEY_INDEX, '') - self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode('Category: %s'%cat_name)) - self._categories[sub_category] = iter - #add block - if block is None: return - iter = self.treestore.insert_before(self._categories[category], None) - self.treestore.set_value(iter, NAME_INDEX, block.get_name()) - self.treestore.set_value(iter, KEY_INDEX, block.get_key()) - self.treestore.set_value(iter, DOC_INDEX, Utils.xml_encode(block.get_doc() or 'undocumented')) - - ############################################################ - ## Helper Methods - ############################################################ - def _get_selected_block_key(self): - """ - Get the currently selected block key. - @return the key of the selected block or a empty string - """ - selection = self.treeview.get_selection() - treestore, iter = selection.get_selected() - return iter and treestore.get_value(iter, KEY_INDEX) or '' - - def _update_add_button(self): - """ - Update the add button's sensitivity. - The button should be active only if a block is selected. - """ - key = self._get_selected_block_key() - self.add_button.set_sensitive(bool(key)) - - def _add_selected_block(self): - """ - Add the selected block with the given key to the flow graph. - """ - key = self._get_selected_block_key() - if key: self.get_flow_graph().add_new_block(key) - - ############################################################ - ## Event Handlers - ############################################################ - def _handle_drag_get_data(self, widget, drag_context, selection_data, info, time): - """ - Handle a drag and drop by setting the key to the selection object. - This will call the destination handler for drag and drop. - Only call set when the key is valid to ignore DND from categories. - """ - key = self._get_selected_block_key() - if key: selection_data.set(selection_data.target, 8, key) - - def _handle_mouse_button_press(self, widget, event): - """ - Handle the mouse button press. - If a left double click is detected, call add selected block. - """ - if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: - self._add_selected_block() - - def _handle_selection_change(self, selection): - """ - Handle a selection change in the tree view. - If a selection changes, set the add button sensitive. - """ - self._update_add_button() - - def _handle_add_button(self, widget): - """ - Handle the add button clicked signal. - Call add selected block. - """ - self._add_selected_block() diff --git a/grc/src/gui/Constants.py b/grc/src/gui/Constants.py deleted file mode 100644 index f23ab8b13..000000000 --- a/grc/src/gui/Constants.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Copyright 2008, 2009 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 -""" - -import pygtk -pygtk.require('2.0') -import gtk -import os - -##default path for the open/save dialogs -DEFAULT_FILE_PATH = os.getcwd() - -##file extensions -IMAGE_FILE_EXTENSION = '.png' - -##name for new/unsaved flow graphs -NEW_FLOGRAPH_TITLE = 'untitled' - -##main window constraints -MIN_WINDOW_WIDTH = 600 -MIN_WINDOW_HEIGHT = 400 -##dialog constraints -MIN_DIALOG_WIDTH = 500 -MIN_DIALOG_HEIGHT = 500 -##default sizes -DEFAULT_BLOCKS_WINDOW_WIDTH = 100 -DEFAULT_REPORTS_WINDOW_WIDTH = 100 - -##The size of the state saving cache in the flow graph (for undo/redo functionality) -STATE_CACHE_SIZE = 42 - -##Shared targets for drag and drop of blocks -DND_TARGETS = [('STRING', gtk.TARGET_SAME_APP, 0)] diff --git a/grc/src/gui/Dialogs.py b/grc/src/gui/Dialogs.py deleted file mode 100644 index d526b97b4..000000000 --- a/grc/src/gui/Dialogs.py +++ /dev/null @@ -1,100 +0,0 @@ -""" -Copyright 2008, 2009 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 -""" - -import pygtk -pygtk.require('2.0') -import gtk -from .. platforms.base.Constants import PACKAGE, VERSION -import Preferences - -class TextDisplay(gtk.TextView): - """A non editable gtk text view.""" - - def __init__(self, text=''): - """ - TextDisplay constructor. - @param text the text to display (string) - """ - text_buffer = gtk.TextBuffer() - text_buffer.set_text(text) - self.set_text = text_buffer.set_text - self.insert = lambda line: text_buffer.insert(text_buffer.get_end_iter(), line) - gtk.TextView.__init__(self, text_buffer) - self.set_editable(False) - self.set_cursor_visible(False) - self.set_wrap_mode(gtk.WRAP_WORD_CHAR) - -def MessageDialogHelper(type, buttons, title=None, markup=None): - """ - Create a modal message dialog and run it. - @param type the type of message: gtk.MESSAGE_INFO, gtk.MESSAGE_WARNING, gtk.MESSAGE_QUESTION or gtk.MESSAGE_ERROR - @param buttons the predefined set of buttons to use: - gtk.BUTTONS_NONE, gtk.BUTTONS_OK, gtk.BUTTONS_CLOSE, gtk.BUTTONS_CANCEL, gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL - @param tittle the title of the window (string) - @param markup the message text with pango markup - @return the gtk response from run() - """ - message_dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, type, buttons) - if title != None: message_dialog.set_title(title) - if markup != None: message_dialog.set_markup(markup) - response = message_dialog.run() - message_dialog.destroy() - return response - -class AboutDialog(gtk.AboutDialog): - """A cute little about dialog.""" - - def __init__(self): - """AboutDialog constructor.""" - gtk.AboutDialog.__init__(self) - self.set_name(PACKAGE) - self.set_version(VERSION) - self.set_license(__doc__) - self.set_copyright(__doc__.strip().splitlines()[0]) - self.set_website('http://gnuradio.org/trac/wiki/GNURadioCompanion') - self.set_comments("""\ -Thank you to all those from the mailing list who tested GNU Radio Companion and offered advice. ------ -Special Thanks: -A. Brinton Cooper -> starting the project -Patrick Mulligan -> starting the project -CER Technology Fellowship Grant -> initial funding -William R. Kenan Jr. Fund -> usrp & computers -Patrick Strasser -> the GRC icon -Achilleas Anastasopoulos -> trellis support ------""") - self.run() - self.destroy() - -def HelpDialog(): - MessageDialogHelper( - type=gtk.MESSAGE_INFO, - buttons=gtk.BUTTONS_CLOSE, - title='Help', - markup="""\ -<b>Usage Tips</b> - -<u>Add block</u>: drag and drop or double click a block in the block selection window. -<u>Rotate block</u>: Select a block, press left/right on the keyboard. -<u>Change type</u>: Select a block, press up/down on the keyboard. -<u>Edit parameters</u>: double click on a block in the flow graph. -<u>Make connection</u>: click on the source port of one block, then click on the sink port of another block. -<u>Remove connection</u>: select the connection and press delete, or drag the connection. - -* See the menu for other keyboard shortcuts.""") diff --git a/grc/src/gui/DrawingArea.py b/grc/src/gui/DrawingArea.py deleted file mode 100644 index 6f90049c5..000000000 --- a/grc/src/gui/DrawingArea.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -Copyright 2007, 2008, 2009 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 -""" - -import pygtk -pygtk.require('2.0') -import gtk -from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS - -class DrawingArea(gtk.DrawingArea): - """ - DrawingArea is the gtk pixel map that graphical elements may draw themselves on. - The drawing area also responds to mouse and key events. - """ - - def __init__(self, flow_graph): - """ - DrawingArea contructor. - Connect event handlers. - @param main_window the main_window containing all flow graphs - """ - self.ctrl_mask = False - self._flow_graph = flow_graph - gtk.DrawingArea.__init__(self) - self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) - self.connect('realize', self._handle_window_realize) - self.connect('configure-event', self._handle_window_configure) - self.connect('expose-event', self._handle_window_expose) - self.connect('motion-notify-event', self._handle_mouse_motion) - self.connect('button-press-event', self._handle_mouse_button_press) - self.connect('button-release-event', self._handle_mouse_button_release) - self.add_events( - gtk.gdk.BUTTON_PRESS_MASK | \ - gtk.gdk.POINTER_MOTION_MASK | \ - gtk.gdk.BUTTON_RELEASE_MASK | \ - gtk.gdk.LEAVE_NOTIFY_MASK | \ - gtk.gdk.ENTER_NOTIFY_MASK - ) - #setup drag and drop - self.drag_dest_set(gtk.DEST_DEFAULT_ALL, DND_TARGETS, gtk.gdk.ACTION_COPY) - self.connect('drag-data-received', self._handle_drag_data_received) - #setup the focus flag - self._focus_flag = False - self.get_focus_flag = lambda: self._focus_flag - def _handle_focus_event(widget, event, focus_flag): self._focus_flag = focus_flag - self.connect('leave-notify-event', _handle_focus_event, False) - self.connect('enter-notify-event', _handle_focus_event, True) - - def new_pixmap(self, width, height): return gtk.gdk.Pixmap(self.window, width, height, -1) - - ########################################################################## - ## Handlers - ########################################################################## - def _handle_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time): - """ - Handle a drag and drop by adding a block at the given coordinate. - """ - self._flow_graph.add_new_block(selection_data.data, (x, y)) - - def _handle_mouse_button_press(self, widget, event): - """ - Forward button click information to the flow graph. - """ - self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK - self._flow_graph.handle_mouse_button_press( - left_click=(event.button == 1), - double_click=(event.type == gtk.gdk._2BUTTON_PRESS), - coordinate=(event.x, event.y), - ) - - def _handle_mouse_button_release(self, widget, event): - """ - Forward button release information to the flow graph. - """ - self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK - self._flow_graph.handle_mouse_button_release( - left_click=(event.button == 1), - coordinate=(event.x, event.y), - ) - - def _handle_mouse_motion(self, widget, event): - """ - Forward mouse motion information to the flow graph. - """ - self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK - self._flow_graph.handle_mouse_motion( - coordinate=(event.x, event.y), - ) - - def _handle_window_realize(self, widget): - """ - Called when the window is realized. - Update the flowgraph, which calls new pixmap. - """ - self._flow_graph.update() - - def _handle_window_configure(self, widget, event): - """ - Called when the window is resized. - Create a new pixmap for background buffer. - """ - self._pixmap = self.new_pixmap(*self.get_size_request()) - - def _handle_window_expose(self, widget, event): - """ - Called when window is exposed, or queue_draw is called. - Double buffering: draw to pixmap, then draw pixmap to window. - """ - gc = self.window.new_gc() - self._flow_graph.draw(gc, self._pixmap) - self.window.draw_drawable(gc, self._pixmap, 0, 0, 0, 0, -1, -1) diff --git a/grc/src/gui/FileDialogs.py b/grc/src/gui/FileDialogs.py deleted file mode 100644 index 7c10d9844..000000000 --- a/grc/src/gui/FileDialogs.py +++ /dev/null @@ -1,160 +0,0 @@ -""" -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 -""" - -import pygtk -pygtk.require('2.0') -import gtk -from Dialogs import MessageDialogHelper -from Constants import \ - DEFAULT_FILE_PATH, IMAGE_FILE_EXTENSION, \ - NEW_FLOGRAPH_TITLE -import Preferences -from os import path - -OPEN_FLOW_GRAPH = 'open flow graph' -SAVE_FLOW_GRAPH = 'save flow graph' -SAVE_IMAGE = 'save image' - -##the filter for flow graph files -def get_flow_graph_files_filter(): - filter = gtk.FileFilter() - filter.set_name('Flow Graph Files') - filter.add_pattern('*'+Preferences.file_extension()) - filter.add_pattern('*.xml') #TEMP - return filter - -##the filter for image files -def get_image_files_filter(): - filter = gtk.FileFilter() - filter.set_name('Image Files') - filter.add_pattern('*'+IMAGE_FILE_EXTENSION) - return filter - -##the filter for all files -def get_all_files_filter(): - filter = gtk.FileFilter() - filter.set_name('All Files') - filter.add_pattern('*') - return filter - -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, 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. - @param action gtk.FILE_CHOOSER_ACTION_OPEN or gtk.FILE_CHOOSER_ACTION_SAVE - @param 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, None, action, ('gtk-cancel', gtk.RESPONSE_CANCEL, ok_stock, gtk.RESPONSE_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, current_file_path=''): - """ - FileDialog constructor. - @param 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...') - 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...') - self.add_and_set_filter(get_flow_graph_files_filter()) - self.set_current_name(path.basename(current_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...') - 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 - 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. - @param 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. - @return 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_IMAGE): - filename = self.get_filename() - extension = { - SAVE_FLOW_GRAPH: Preferences.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, 'Confirm Overwrite!', - 'File <b>"%s"</b> Exists!\nWould you like to overwrite the existing file?'%filename, - ) == gtk.RESPONSE_NO: return self.get_rectified_filename() - return filename - ############################################# - # Handle Open Dialogs - ############################################# - elif self.type in (OPEN_FLOW_GRAPH,): - 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, 'Cannot Open!', - 'File <b>"%s"</b> Does not Exist!'%filename, - ) - return self.get_rectified_filename() - return filenames - - def run(self): - """ - Get the filename and destroy the dialog. - @return the filename or None if a close/cancel occured. - """ - filename = self.get_rectified_filename() - self.destroy() - return filename - -class OpenFlowGraphFileDialog(FileDialog): type = OPEN_FLOW_GRAPH -class SaveFlowGraphFileDialog(FileDialog): type = SAVE_FLOW_GRAPH -class SaveImageFileDialog(FileDialog): type = SAVE_IMAGE diff --git a/grc/src/gui/MainWindow.py b/grc/src/gui/MainWindow.py deleted file mode 100644 index bd5f73a80..000000000 --- a/grc/src/gui/MainWindow.py +++ /dev/null @@ -1,299 +0,0 @@ -""" -Copyright 2008 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 Constants import \ - NEW_FLOGRAPH_TITLE, DEFAULT_REPORTS_WINDOW_WIDTH -from Actions import \ - APPLICATION_QUIT, FLOW_GRAPH_KILL, \ - FLOW_GRAPH_SAVE, get_accel_group -import pygtk -pygtk.require('2.0') -import gtk -import Bars -from BlockTreeWindow import BlockTreeWindow -from Dialogs import TextDisplay, MessageDialogHelper -from NotebookPage import NotebookPage -import Preferences -import Messages -import os - -############################################################ -# Main window -############################################################ - -class MainWindow(gtk.Window): - """The topmost window with menus, the tool bar, and other major windows.""" - - def __init__(self, handle_states, platform): - """ - MainWindow contructor. - @param handle_states the callback function - """ - self._platform = platform - #setup window - self.handle_states = handle_states - gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) - vbox = gtk.VBox() - self.hpaned = gtk.HPaned() - self.add(vbox) - #create the menu bar and toolbar - self.add_accel_group(get_accel_group()) - vbox.pack_start(Bars.MenuBar(), False) - vbox.pack_start(Bars.Toolbar(), False) - vbox.pack_start(self.hpaned) - #create the notebook - self.notebook = gtk.Notebook() - self.page_to_be_closed = None - self.current_page = None - self.notebook.set_show_border(False) - self.notebook.set_scrollable(True) #scroll arrows for page tabs - self.notebook.connect('switch-page', self._handle_page_change) - #setup containers - self.flow_graph_vpaned = gtk.VPaned() - #flow_graph_box.pack_start(self.scrolled_window) - self.flow_graph_vpaned.pack1(self.notebook) - self.hpaned.pack1(self.flow_graph_vpaned) - self.hpaned.pack2(BlockTreeWindow(platform, self.get_flow_graph), False) #dont allow resize - #create the reports window - self.text_display = TextDisplay() - #house the reports in a scrolled window - self.reports_scrolled_window = gtk.ScrolledWindow() - self.reports_scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.reports_scrolled_window.add_with_viewport(self.text_display) - self.reports_scrolled_window.set_size_request(-1, DEFAULT_REPORTS_WINDOW_WIDTH) - self.flow_graph_vpaned.pack2(self.reports_scrolled_window, False) #dont allow resize - #load preferences and show the main window - Preferences.load(platform) - self.resize(*Preferences.main_window_size()) - self.flow_graph_vpaned.set_position(Preferences.reports_window_position()) - self.hpaned.set_position(Preferences.blocks_window_position()) - self.show_all() - - ############################################################ - # Event Handlers - ############################################################ - - def _quit(self, window, event): - """ - Handle the delete event from the main window. - Generated by pressing X to close, alt+f4, or right click+close. - This method in turns calls the state handler to quit. - @return true - """ - self.handle_states(APPLICATION_QUIT) - return True - - def _handle_page_change(self, notebook, page, page_num): - """ - Handle a page change. When the user clicks on a new tab, - reload the flow graph to update the vars window and - call handle states (select nothing) to update the buttons. - @param notebook the notebook - @param page new page - @param page_num new page number - """ - self.current_page = self.notebook.get_nth_page(page_num) - Messages.send_page_switch(self.current_page.get_file_path()) - self.handle_states() - - ############################################################ - # Report Window - ############################################################ - - def add_report_line(self, line): - """ - Place line at the end of the text buffer, then scroll its window all the way down. - @param line the new text - """ - self.text_display.insert(line) - vadj = self.reports_scrolled_window.get_vadjustment() - vadj.set_value(vadj.upper) - vadj.emit('changed') - - ############################################################ - # Pages: create and close - ############################################################ - - def new_page(self, file_path='', show=False): - """ - Create a new notebook page. - Set the tab to be selected. - @param file_path optional file to load into the flow graph - @param show true if the page should be shown after loading - """ - #if the file is already open, show the open page and return - if file_path and file_path in self._get_files(): #already open - page = self.notebook.get_nth_page(self._get_files().index(file_path)) - self._set_page(page) - return - try: #try to load from file - if file_path: Messages.send_start_load(file_path) - flow_graph = self._platform.get_new_flow_graph() - page = NotebookPage( - self, - flow_graph=flow_graph, - file_path=file_path, - ) - if file_path: Messages.send_end_load() - except Exception, e: #return on failure - Messages.send_fail_load(e) - return - #add this page to the notebook - self.notebook.append_page(page, page.get_tab()) - try: self.notebook.set_tab_reorderable(page, True) - except: pass #gtk too old - self.notebook.set_tab_label_packing(page, False, False, gtk.PACK_START) - #only show if blank or manual - if not file_path or show: self._set_page(page) - - def close_pages(self): - """ - Close all the pages in this notebook. - @return true if all closed - """ - open_files = filter(lambda file: file, self._get_files()) #filter blank files - open_file = self.get_page().get_file_path() - #close each page - for page in self._get_pages(): - self.page_to_be_closed = page - self.close_page(False) - if self.notebook.get_n_pages(): return False - #save state before closing - Preferences.files_open(open_files) - Preferences.file_open(open_file) - Preferences.main_window_size(self.get_size()) - Preferences.reports_window_position(self.flow_graph_vpaned.get_position()) - Preferences.blocks_window_position(self.hpaned.get_position()) - Preferences.save() - return True - - def close_page(self, ensure=True): - """ - Close the current page. - If the notebook becomes empty, and ensure is true, - call new page upon exit to ensure that at least one page exists. - @param ensure boolean - """ - if not self.page_to_be_closed: self.page_to_be_closed = self.get_page() - #show the page if it has an executing flow graph or is unsaved - if self.page_to_be_closed.get_pid() or not self.page_to_be_closed.get_saved(): - self._set_page(self.page_to_be_closed) - #unsaved? ask the user - if not self.page_to_be_closed.get_saved() and self._save_changes(): - self.handle_states(FLOW_GRAPH_SAVE) #try to save - if not self.page_to_be_closed.get_saved(): #still unsaved? - self.page_to_be_closed = None #set the page to be closed back to None - return - #stop the flow graph if executing - if self.page_to_be_closed.get_pid(): self.handle_states(FLOW_GRAPH_KILL) - #remove the page - self.notebook.remove_page(self.notebook.page_num(self.page_to_be_closed)) - if ensure and self.notebook.get_n_pages() == 0: self.new_page() #no pages, make a new one - self.page_to_be_closed = None #set the page to be closed back to None - - ############################################################ - # Misc - ############################################################ - - def update(self): - """ - Set the title of the main window. - Set the titles on the page tabs. - Show/hide the reports window. - @param title the window title - """ - title = ''.join(( - self._platform.get_name(), - ' - Editing: ', - (self.get_page().get_file_path() or NEW_FLOGRAPH_TITLE), - (self.get_page().get_saved() and ' ' or '*'), #blank must be non empty - (self.get_page().get_read_only() and ' (read-only)' or ''), - ) - ) - gtk.Window.set_title(self, title) - #set tab titles - for page in self._get_pages(): - #get filename and strip out file extension - title = os.path.splitext(os.path.basename(page.get_file_path()))[0] - page.set_text(''.join(( - (title or NEW_FLOGRAPH_TITLE), - (page.get_saved() and ' ' or '*'), #blank must be non empty - (page.get_read_only() and ' (ro)' or ''), - ) - ) - ) - #show/hide notebook tabs - self.notebook.set_show_tabs(len(self._get_pages()) > 1) - - def get_page(self): - """ - Get the selected page. - @return the selected page - """ - return self.current_page - - def get_flow_graph(self): - """ - Get the selected flow graph. - @return the selected flow graph - """ - return self.get_page().get_flow_graph() - - def get_focus_flag(self): - """ - Get the focus flag from the current page. - @return the focus flag - """ - return self.get_page().get_drawing_area().get_focus_flag() - - ############################################################ - # Helpers - ############################################################ - - def _set_page(self, page): - """ - Set the current page. - @param page the page widget - """ - self.current_page = page - self.notebook.set_current_page(self.notebook.page_num(self.current_page)) - - def _save_changes(self): - """ - Save changes to flow graph? - @return true if yes - """ - return MessageDialogHelper( - gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Unsaved Changes!', - 'Would you like to save changes before closing?' - ) == gtk.RESPONSE_YES - - def _get_files(self): - """ - Get the file names for all the pages, in order. - @return list of file paths - """ - return map(lambda page: page.get_file_path(), self._get_pages()) - - def _get_pages(self): - """ - Get a list of all pages in the notebook. - @return list of pages - """ - return [self.notebook.get_nth_page(page_num) for page_num in range(self.notebook.get_n_pages())] diff --git a/grc/src/gui/Makefile.am b/grc/src/gui/Makefile.am deleted file mode 100644 index a6639af44..000000000 --- a/grc/src/gui/Makefile.am +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2008 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio 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 3, or (at your option) -# any later version. -# -# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -include $(top_srcdir)/grc/Makefile.inc - -ourpythondir = $(grc_src_prefix)/gui - -ourpython_PYTHON = \ - ActionHandler.py \ - Actions.py \ - Bars.py \ - BlockTreeWindow.py \ - Constants.py \ - Dialogs.py \ - DrawingArea.py \ - FileDialogs.py \ - MainWindow.py \ - Messages.py \ - NotebookPage.py \ - ParamsDialog.py \ - Preferences.py \ - StateCache.py \ - __init__.py diff --git a/grc/src/gui/Messages.py b/grc/src/gui/Messages.py deleted file mode 100644 index e8939402d..000000000 --- a/grc/src/gui/Messages.py +++ /dev/null @@ -1,105 +0,0 @@ -""" -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 .. platforms.base.Constants import PACKAGE, VERSION -import traceback -import sys - -## A list of functions that can receive a message. -MESSENGERS_LIST = list() - -def register_messenger(messenger): - """ - Append the given messenger to the list of messengers. - @param messenger a method thats takes a string - """ - MESSENGERS_LIST.append(messenger) - -def send(message): - """ - Give the message to each of the messengers. - @param message a message string - """ - for messenger in MESSENGERS_LIST: messenger(message) - -#register stdout by default -register_messenger(sys.stdout.write) - -########################################################################### -# Special functions for specific program functionalities -########################################################################### -def send_init(): - send("""<<< Welcome to %s %s >>>\n"""%(PACKAGE, VERSION)) - -def send_page_switch(file_path): - send('\nShowing: "%s"\n'%file_path) - -################# functions for loading flow graphs ######################################## -def send_start_load(file_path): - send('\nLoading: "%s"'%file_path + '\n') - -def send_error_load(error): - send('>>> Error: %s\n'%error) - traceback.print_exc() - -def send_end_load(): - send('>>> Done\n') - -def send_fail_load(error): - send('Error: %s\n'%error) - send('>>> Failue\n') - traceback.print_exc() - -################# functions for generating flow graphs ######################################## -def send_start_gen(file_path): - send('\nGenerating: "%s"'%file_path + '\n') - -def send_fail_gen(error): - send('Generate Error: %s\n'%error) - send('>>> Failue\n') - traceback.print_exc() - -################# functions for executing flow graphs ######################################## -def send_start_exec(file_path): - send('\nExecuting: "%s"'%file_path + '\n') - -def send_verbose_exec(verbose): - send(verbose) - -def send_end_exec(): - send('\n>>> Done\n') - -################# functions for saving flow graphs ######################################## -def send_fail_save(file_path): - send('>>> Error: Cannot save: %s\n'%file_path) - -################# functions for connections ######################################## -def send_fail_connection(): - send('>>> Error: Cannot create connection.\n') - -################# functions for preferences ######################################## -def send_fail_load_preferences(prefs_file_path): - send('>>> Error: Cannot load preferences file: "%s"\n'%prefs_file_path) - -def send_fail_save_preferences(prefs_file_path): - send('>>> Error: Cannot save preferences file: "%s"\n'%prefs_file_path) - -################# functions for warning ######################################## -def send_warning(warning): - send('>>> Warning: %s\n'%warning) diff --git a/grc/src/gui/NotebookPage.py b/grc/src/gui/NotebookPage.py deleted file mode 100644 index a3ec5b4e2..000000000 --- a/grc/src/gui/NotebookPage.py +++ /dev/null @@ -1,197 +0,0 @@ -""" -Copyright 2008 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 Actions import FLOW_GRAPH_CLOSE -import pygtk -pygtk.require('2.0') -import gtk -from .. utils import ParseXML -from StateCache import StateCache -from .. platforms.base.Constants import FLOW_GRAPH_DTD -from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT -from DrawingArea import DrawingArea -import os - -############################################################ -## Notebook Page -############################################################ - -class NotebookPage(gtk.HBox): - """A page in the notebook.""" - - def __init__(self, main_window, flow_graph, file_path=''): - """ - Page constructor. - @param main_window main window - @param file_path path to a flow graph file - """ - self._flow_graph = flow_graph - self.set_pid(None) - #import the file - self.main_window = main_window - self.set_file_path(file_path) - file_path = file_path or flow_graph.get_parent().get_default_flow_graph() - open(file_path, 'r') #test open - ############################################################ - from .. utils import converter - converter.convert(file_path, flow_graph.get_parent()) - ############################################################ - ParseXML.validate_dtd(file_path, FLOW_GRAPH_DTD) - initial_state = ParseXML.from_file(file_path) - self.state_cache = StateCache(initial_state) - self.set_saved(True) - #import the data to the flow graph - self.get_flow_graph().import_data(initial_state) - #initialize page gui - gtk.HBox.__init__(self, False, 0) - self.show() - #tab box to hold label and close button - self.tab = gtk.HBox(False, 0) - #setup tab label - self.label = gtk.Label() - self.tab.pack_start(self.label, False) - #setup button image - image = gtk.Image() - image.set_from_stock('gtk-close', gtk.ICON_SIZE_MENU) - #setup image box - image_box = gtk.HBox(False, 0) - image_box.pack_start(image, True, False, 0) - #setup the button - button = gtk.Button() - button.connect("clicked", self._handle_button) - button.set_relief(gtk.RELIEF_NONE) - button.add(image_box) - #button size - w, h = gtk.icon_size_lookup_for_settings(button.get_settings(), gtk.ICON_SIZE_MENU) - button.set_size_request(w+6, h+6) - self.tab.pack_start(button, False) - self.tab.show_all() - #setup scroll window and drawing area - self.scrolled_window = gtk.ScrolledWindow() - self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) - self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.drawing_area = DrawingArea(self.get_flow_graph()) - self.scrolled_window.add_with_viewport(self.get_drawing_area()) - self.pack_start(self.scrolled_window) - #inject drawing area and handle states into flow graph - self.get_flow_graph().drawing_area = self.get_drawing_area() - self.get_flow_graph().handle_states = main_window.handle_states - self.show_all() - - def get_drawing_area(self): return self.drawing_area - - def get_generator(self): - """ - Get the generator object for this flow graph. - @return generator - """ - return self.get_flow_graph().get_parent().get_generator()( - self.get_flow_graph(), - self.get_file_path(), - ) - - def _handle_button(self, button): - """ - The button was clicked. - Make the current page selected, then close. - @param the button - """ - self.main_window.page_to_be_closed = self - self.main_window.handle_states(FLOW_GRAPH_CLOSE) - - def set_text(self, text): - """ - Set the text in this label. - @param text the new text - """ - self.label.set_text(text) - - def get_tab(self): - """ - Get the gtk widget for this page's tab. - @return gtk widget - """ - return self.tab - - def get_pid(self): - """ - Get the pid for the flow graph. - @return the pid number - """ - return self.pid - - def set_pid(self, pid): - """ - Set the pid number. - @param pid the new pid number - """ - self.pid = pid - - def get_flow_graph(self): - """ - Get the flow graph. - @return the flow graph - """ - return self._flow_graph - - def get_read_only(self): - """ - Get the read-only state of the file. - Always false for empty path. - @return true for read-only - """ - if not self.get_file_path(): return False - return os.path.exists(self.get_file_path()) and \ - not os.access(self.get_file_path(), os.W_OK) - - def get_file_path(self): - """ - Get the file path for the flow graph. - @return the file path or '' - """ - return self.file_path - - def set_file_path(self, file_path=''): - """ - Set the file path, '' for no file path. - @param file_path file path string - """ - if file_path: self.file_path = os.path.abspath(file_path) - else: self.file_path = '' - - def get_saved(self): - """ - Get the saved status for the flow graph. - @return true if saved - """ - return self.saved - - def set_saved(self, saved=True): - """ - Set the saved status. - @param saved boolean status - """ - self.saved = saved - - def get_state_cache(self): - """ - Get the state cache for the flow graph. - @return the state cache - """ - return self.state_cache diff --git a/grc/src/gui/ParamsDialog.py b/grc/src/gui/ParamsDialog.py deleted file mode 100644 index 6cc42e8fc..000000000 --- a/grc/src/gui/ParamsDialog.py +++ /dev/null @@ -1,144 +0,0 @@ -""" -Copyright 2007, 2008, 2009 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 -""" - -import pygtk -pygtk.require('2.0') -import gtk - -from Dialogs import TextDisplay -from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT - -def get_title_label(title): - """ - Get a title label for the params window. - The title will be bold, underlined, and left justified. - @param title the text of the title - @return a gtk object - """ - label = gtk.Label() - label.set_markup('\n<b><span underline="low">%s</span>:</b>\n'%title) - hbox = gtk.HBox() - hbox.pack_start(label, False, False, padding=11) - return hbox - -class ParamsDialog(gtk.Dialog): - """A dialog box to set block parameters.""" - - def __init__(self, block): - """ - SignalBlockParamsDialog contructor. - @param block the signal block - """ - gtk.Dialog.__init__(self, - title='Properties: %s'%block.get_name(), - buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE), - ) - self.block = block - self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT) - vbox = gtk.VBox() - #Add the title label - vbox.pack_start(get_title_label('Parameters'), False) - #Create the scrolled window to hold all the parameters - scrolled_window = gtk.ScrolledWindow() - scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled_window.add_with_viewport(vbox) - self.vbox.pack_start(scrolled_window, True) - #Error Messages for the block - self._error_box = gtk.VBox() - self._error_messages_text_display = TextDisplay() - self._error_box.pack_start(gtk.Label(), False, False, 7) #spacing - self._error_box.pack_start(get_title_label('Error Messages'), False) - self._error_box.pack_start(self._error_messages_text_display, False) - #Docs for the block - self._docs_box = err_box = gtk.VBox() - self._docs_text_display = TextDisplay() - self._docs_box.pack_start(gtk.Label(), False, False, 7) #spacing - self._docs_box.pack_start(get_title_label('Documentation'), False) - self._docs_box.pack_start(self._docs_text_display, False) - #Add all the parameters - for param in self.block.get_params(): - vbox.pack_start(param.get_input_object(self._handle_changed), False) - #Add the error and docs box - vbox.pack_start(self._error_box, False) - vbox.pack_start(self._docs_box, False) - #connect and show - self.connect('key_press_event', self._handle_key_press) - self.show_all() - #initial update - for param in self.block.get_params(): param.update() - self._update() - - def _update(self): - """ - Update the error messages box. - Hide the box if there are no errors. - Update the documentation block. - Hide the box if there are no docs. - """ - #update the errors box - if self.block.is_valid(): self._error_box.hide() - else: self._error_box.show() - messages = '\n\n'.join(self.block.get_error_messages()) - self._error_messages_text_display.set_text(messages) - #update the docs box - if self.block.get_doc(): self._docs_box.show() - else: self._docs_box.hide() - self._docs_text_display.set_text(self.block.get_doc()) - - def _handle_key_press(self, widget, event): - """ - Handle key presses from the keyboard. - Call the ok response when enter is pressed. - @return false to forward the keypress - """ - keyname = gtk.gdk.keyval_name(event.keyval) - if keyname == 'Return': self.response(gtk.RESPONSE_OK) - return False #forward the keypress - - def _handle_changed(self, param): - """ - A change occured, update any dependent parameters: - The enum inside the variable type may have changed and, - the variable param will need an external update. - @param param the graphical parameter that initiated the callback - """ - #update dependent params - if param.is_enum(): - for other_param in param.get_parent().get_params(): - if param.get_key() is not other_param.get_key() and ( - param.get_key() in other_param._type or \ - param.get_key() in other_param._hide): other_param.update() - #update - self._update() - return True - - def run(self): - """ - Call run(). - @return true if a change occured. - """ - original_data = list() - for param in self.block.get_params(): - original_data.append(param.get_value()) - gtk.Dialog.run(self) - self.destroy() - new_data = list() - for param in self.block.get_params(): - new_data.append(param.get_value()) - return original_data != new_data diff --git a/grc/src/gui/Preferences.py b/grc/src/gui/Preferences.py deleted file mode 100644 index 1d89920dd..000000000 --- a/grc/src/gui/Preferences.py +++ /dev/null @@ -1,86 +0,0 @@ -""" -Copyright 2008 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 -""" - -import ConfigParser -import os - -_platform = None -_config_parser = ConfigParser.ConfigParser() - -def file_extension(): return '.'+_platform.get_key() -def _prefs_file(): return os.path.join(os.path.expanduser('~'), file_extension()) - -def load(platform): - global _platform - _platform = platform - #create sections - _config_parser.add_section('main') - _config_parser.add_section('files_open') - try: _config_parser.read(_prefs_file()) - except: pass -def save(): - try: _config_parser.write(open(_prefs_file(), 'w')) - except: pass - -########################################################################### -# Special methods for specific program functionalities -########################################################################### - -def main_window_size(size=None): - if size is not None: - _config_parser.set('main', 'main_window_width', size[0]) - _config_parser.set('main', 'main_window_height', size[1]) - else: - try: return ( - _config_parser.getint('main', 'main_window_width'), - _config_parser.getint('main', 'main_window_height'), - ) - except: return (1, 1) - -def file_open(file=None): - if file is not None: _config_parser.set('main', 'file_open', file) - else: - try: return _config_parser.get('main', 'file_open') - except: return '' - -def files_open(files=None): - if files is not None: - _config_parser.remove_section('files_open') #clear section - _config_parser.add_section('files_open') - for i, file in enumerate(files): - _config_parser.set('files_open', 'file_open_%d'%i, file) - else: - files = list() - i = 0 - while True: - try: files.append(_config_parser.get('files_open', 'file_open_%d'%i)) - except: return files - i = i + 1 - -def reports_window_position(pos=None): - if pos is not None: _config_parser.set('main', 'reports_window_position', pos) - else: - try: return _config_parser.getint('main', 'reports_window_position') or 1 #greater than 0 - except: return -1 - -def blocks_window_position(pos=None): - if pos is not None: _config_parser.set('main', 'blocks_window_position', pos) - else: - try: return _config_parser.getint('main', 'blocks_window_position') or 1 #greater than 0 - except: return -1 diff --git a/grc/src/gui/StateCache.py b/grc/src/gui/StateCache.py deleted file mode 100644 index 04b18b18a..000000000 --- a/grc/src/gui/StateCache.py +++ /dev/null @@ -1,92 +0,0 @@ -""" -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 Actions import FLOW_GRAPH_UNDO, FLOW_GRAPH_REDO, get_action_from_name -from Constants import STATE_CACHE_SIZE - -class StateCache(object): - """ - The state cache is an interface to a list to record data/states and to revert to previous states. - States are recorded into the list in a circular fassion by using an index for the current state, - and counters for the range where states are stored. - """ - - def __init__(self, initial_state): - """ - StateCache constructor. - @param initial_state the intial state (nested data) - """ - self.states = [None] * STATE_CACHE_SIZE #fill states - self.current_state_index = 0 - self.num_prev_states = 0 - self.num_next_states = 0 - self.states[0] = initial_state - self.update_actions() - - def save_new_state(self, state): - """ - Save a new state. - Place the new state at the next index and add one to the number of previous states. - @param state the new state - """ - self.current_state_index = (self.current_state_index + 1)%STATE_CACHE_SIZE - self.states[self.current_state_index] = state - self.num_prev_states = self.num_prev_states + 1 - if self.num_prev_states == STATE_CACHE_SIZE: self.num_prev_states = STATE_CACHE_SIZE - 1 - self.num_next_states = 0 - self.update_actions() - - def get_current_state(self): - """ - Get the state at the current index. - @return the current state (nested data) - """ - self.update_actions() - return self.states[self.current_state_index] - - def get_prev_state(self): - """ - Get the previous state and decrement the current index. - @return the previous state or None - """ - if self.num_prev_states > 0: - self.current_state_index = (self.current_state_index + STATE_CACHE_SIZE -1)%STATE_CACHE_SIZE - self.num_next_states = self.num_next_states + 1 - self.num_prev_states = self.num_prev_states - 1 - return self.get_current_state() - return None - - def get_next_state(self): - """ - Get the nest state and increment the current index. - @return the next state or None - """ - if self.num_next_states > 0: - self.current_state_index = (self.current_state_index + 1)%STATE_CACHE_SIZE - self.num_next_states = self.num_next_states - 1 - self.num_prev_states = self.num_prev_states + 1 - return self.get_current_state() - return None - - def update_actions(self): - """ - Update the undo and redo actions based on the number of next and prev states. - """ - get_action_from_name(FLOW_GRAPH_REDO).set_sensitive(self.num_next_states != 0) - get_action_from_name(FLOW_GRAPH_UNDO).set_sensitive(self.num_prev_states != 0) diff --git a/grc/src/gui/__init__.py b/grc/src/gui/__init__.py deleted file mode 100644 index 8b1378917..000000000 --- a/grc/src/gui/__init__.py +++ /dev/null @@ -1 +0,0 @@ - |