From 9988664127b367fa8fee4409f8460673d6f265e1 Mon Sep 17 00:00:00 2001 From: jblum Date: Tue, 23 Jun 2009 20:38:18 +0000 Subject: Merging r11186:11273 from grc branch. Fixes, features, and reorganization for grc. Minor fixes and features for wxgui forms. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@11274 221aa14e-8319-0410-a670-987f0aec2ac5 --- grc/gui/ActionHandler.py | 411 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 411 insertions(+) create mode 100644 grc/gui/ActionHandler.py (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py new file mode 100644 index 000000000..2c411a175 --- /dev/null +++ b/grc/gui/ActionHandler.py @@ -0,0 +1,411 @@ +""" +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 .. base import ParseXML +import random +from 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(platform) + #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.COLORS_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(self.get_flow_graph().get_parent()) + elif state == Actions.HELP_WINDOW_DISPLAY: + Dialogs.HelpDialog() + elif state == Actions.COLORS_WINDOW_DISPLAY: + Dialogs.ColorsDialog(self.get_flow_graph().get_parent()) + ################################################## + # 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() -- cgit From 03a27276e566e1e641d115fce129d3351ea52d81 Mon Sep 17 00:00:00 2001 From: jblum Date: Mon, 29 Jun 2009 23:36:20 +0000 Subject: fixed screenshot capability, calls get pixbuf in drawing area git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@11307 221aa14e-8319-0410-a670-987f0aec2ac5 --- grc/gui/ActionHandler.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 2c411a175..ff137f669 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -297,10 +297,7 @@ class ActionHandler: 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 = self.get_flow_graph().get_drawing_area().get_pixbuf() pixbuf.save(file_path, IMAGE_FILE_EXTENSION[1:]) ################################################## # Gen/Exec/Stop -- cgit From b8df6584312f1f03d0bf86375945b8d743b6a6d7 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 24 Aug 2009 20:40:36 -0700 Subject: renamed the colors dialog to types --- grc/gui/ActionHandler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index ff137f669..9af580e8e 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -133,7 +133,7 @@ class ActionHandler: 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.COLORS_WINDOW_DISPLAY, + Actions.TYPES_WINDOW_DISPLAY, ): Actions.get_action_from_name(action).set_sensitive(True) if not self.init_file_paths: self.init_file_paths = Preferences.files_open() @@ -237,8 +237,8 @@ class ActionHandler: Dialogs.AboutDialog(self.get_flow_graph().get_parent()) elif state == Actions.HELP_WINDOW_DISPLAY: Dialogs.HelpDialog() - elif state == Actions.COLORS_WINDOW_DISPLAY: - Dialogs.ColorsDialog(self.get_flow_graph().get_parent()) + elif state == Actions.TYPES_WINDOW_DISPLAY: + Dialogs.TypesDialog(self.get_flow_graph().get_parent()) ################################################## # Param Modifications ################################################## -- cgit From 854bed10dfb61e9f9feab5259a75e809941089ab Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Aug 2009 11:23:23 -0700 Subject: Added virtual sink and logic to clone port. Tweaks to the base validation routines. Validate twice in the update until rewrite functions are implemented. --- grc/gui/ActionHandler.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 9af580e8e..0e64aa89d 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -221,13 +221,11 @@ class ActionHandler: 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) ################################################## -- cgit From 152fcbc219cd2e4f6df7b38843844bc85fdf2bc2 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 30 Aug 2009 10:34:10 -0700 Subject: Switched the python classes to inherit from the base and gui classes. Use only **kwargs so all contructor parameters must be passed with keys. Moved gui input forms classes from base to gui param module. --- grc/gui/ActionHandler.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 0e64aa89d..8f317d6a8 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -30,7 +30,6 @@ from threading import Thread import Messages from .. base import ParseXML import random -from Platform import Platform from MainWindow import MainWindow from ParamsDialog import ParamsDialog import Dialogs @@ -53,7 +52,6 @@ class ActionHandler: @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) -- cgit From 79bace9eb9e441405535e082f3f0ee1a26740fe0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 5 Sep 2009 21:11:51 -0700 Subject: renamed params dialog to props dialog --- grc/gui/ActionHandler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 8f317d6a8..f12893579 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -31,7 +31,7 @@ import Messages from .. base import ParseXML import random from MainWindow import MainWindow -from ParamsDialog import ParamsDialog +from PropsDialog import PropsDialog import Dialogs from FileDialogs import OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, SaveImageFileDialog @@ -240,7 +240,7 @@ class ActionHandler: ################################################## elif state == Actions.BLOCK_PARAM_MODIFY: selected_block = self.get_flow_graph().get_selected_block() - if selected_block and ParamsDialog(selected_block).run(): + if selected_block and PropsDialog(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) -- cgit From bced51e1fe3694e073bebf053b2c69bc5128e00b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 9 Sep 2009 21:35:58 -0700 Subject: properties dialog with ok/cancel buttons --- grc/gui/ActionHandler.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index f12893579..656f99c37 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -240,10 +240,17 @@ class ActionHandler: ################################################## elif state == Actions.BLOCK_PARAM_MODIFY: selected_block = self.get_flow_graph().get_selected_block() - if selected_block and PropsDialog(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) + if selected_block: + if PropsDialog(selected_block).run(): + #save the new state + 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) + else: + #restore the current state + n = self.get_page().get_state_cache().get_current_state() + self.get_flow_graph().import_data(n) + self.get_flow_graph().update() ################################################## # Undo/Redo ################################################## -- cgit From 417bb0aacf320043994ac1a0a5f49b977d1a9d22 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 10 Sep 2009 14:47:53 -0700 Subject: ignore irrelevant modifiers and events pending --- grc/gui/ActionHandler.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 656f99c37..970b731c8 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -79,8 +79,6 @@ class ActionHandler: 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 -- cgit From ab55c4a6e5f9a21ea743b78ea5a8206cf3d4ffe6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 10 Sep 2009 16:17:25 -0700 Subject: use the keymap's translate_keyboard_state, use the key value rather than name --- grc/gui/ActionHandler.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 970b731c8..0d39ea5fd 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -79,10 +79,11 @@ class ActionHandler: When not in focus, gtk and the accelerators handle the the key press. @return false to let gtk handle the key action """ + keyval, egroup, level, consumed = \ + gtk.gdk.keymap_get_default().translate_keyboard_state( + event.hardware_keycode, event.state, event.group) #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) + action_name = Actions.get_action_name_from_key_press(keyval, event.state & ~consumed) #handle the action if flow graph is in focus if action_name and self.get_focus_flag(): self.handle_states(action_name) -- cgit From 9dd47b6732c9d6a94fc0e15717d7332fc6c8270f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 13 Sep 2009 00:04:58 -0700 Subject: Move key press extraction logic into actions module. Replaced xml encode with gtk escape text. Added templates for category and docs tool tips. Other various code tweaks in gui modules. --- grc/gui/ActionHandler.py | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 0d39ea5fd..901619e69 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -79,16 +79,11 @@ class ActionHandler: When not in focus, gtk and the accelerators handle the the key press. @return false to let gtk handle the key action """ - keyval, egroup, level, consumed = \ - gtk.gdk.keymap_get_default().translate_keyboard_state( - event.hardware_keycode, event.state, event.group) - #extract action name from this key press - action_name = Actions.get_action_name_from_key_press(keyval, event.state & ~consumed) - #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 + try: assert self.get_focus_flag() + except AssertionError: return False + try: self.handle_states(Actions.get_action_name_from_key_press(event)) + except KeyError: return False + return True #handled by this method def _quit(self, window, event): """ @@ -100,13 +95,14 @@ class ActionHandler: self.handle_states(Actions.APPLICATION_QUIT) return True - def _handle_actions(self, event): + def _handle_actions(self, action): """ 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()) + self.handle_states(action.get_name()) + return True def handle_states(self, state=''): """ -- cgit From 91a83e6f1fda6483bfd4b449a1ef7903a00af0ab Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 13 Sep 2009 02:14:27 -0700 Subject: Reworked actions api and actions objects: Created standardized Action object for all gui actions. Actions module constants are actual Action objects (not strings). Keypresses, labels, tooltips, stock icons, etc all associate in the Action constructor. Usage of the action's signaling call () eliminated the need for a reference to handle_states. --- grc/gui/ActionHandler.py | 151 +++++++++++++++++++++-------------------------- 1 file changed, 67 insertions(+), 84 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 901619e69..59e535bd4 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -52,10 +52,10 @@ class ActionHandler: @param platform platform module """ self.clipboard = None - for action in Actions.get_all_actions(): action.connect('activate', self._handle_actions) + for action in Actions.get_all_actions(): action.connect('activate', self._handle_action) #setup the main window - self.main_window = MainWindow(self.handle_states, platform) - self.main_window.connect('delete_event', self._quit) + self.main_window = MainWindow(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 @@ -65,7 +65,7 @@ class ActionHandler: Messages.send_init(platform) #initialize self.init_file_paths = file_paths - self.handle_states(Actions.APPLICATION_INITIALIZE) + Actions.APPLICATION_INITIALIZE() #enter the mainloop gtk.main() @@ -81,7 +81,7 @@ class ActionHandler: """ try: assert self.get_focus_flag() except AssertionError: return False - try: self.handle_states(Actions.get_action_name_from_key_press(event)) + try: Actions.get_action_from_key_press(event)() except KeyError: return False return True #handled by this method @@ -92,42 +92,24 @@ class ActionHandler: This method in turns calls the state handler to quit. @return true """ - self.handle_states(Actions.APPLICATION_QUIT) + Actions.APPLICATION_QUIT() return True - def _handle_actions(self, action): - """ - 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(action.get_name()) - return True - - 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 + def _handle_action(self, action): + #print action ################################################## # Initalize/Quit ################################################## - if state == Actions.APPLICATION_INITIALIZE: + if action == Actions.APPLICATION_INITIALIZE: for action in Actions.get_all_actions(): action.set_sensitive(False) #set all actions disabled - # enable a select few actions + #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.TYPES_WINDOW_DISPLAY, - ): Actions.get_action_from_name(action).set_sensitive(True) + ): 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 = [''] @@ -136,26 +118,26 @@ class ActionHandler: 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: + elif action == Actions.APPLICATION_QUIT: if self.main_window.close_pages(): gtk.main_quit() exit(0) ################################################## # Selections ################################################## - elif state == Actions.ELEMENT_SELECT: + elif action == Actions.ELEMENT_SELECT: pass #do nothing, update routines below - elif state == Actions.NOTHING_SELECT: + elif action == Actions.NOTHING_SELECT: self.get_flow_graph().unselect() ################################################## # Enable/Disable ################################################## - elif state == Actions.BLOCK_ENABLE: + elif action == 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: + elif action == 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()) @@ -163,12 +145,12 @@ class ActionHandler: ################################################## # 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: + elif action == Actions.BLOCK_CUT: + Actions.BLOCK_COPY() + Actions.ELEMENT_DELETE() + elif action == Actions.BLOCK_COPY: self.clipboard = self.get_flow_graph().copy_to_clipboard() - elif state == Actions.BLOCK_PASTE: + elif action == Actions.BLOCK_PASTE: if self.clipboard: self.get_flow_graph().paste_from_clipboard(self.clipboard) self.get_flow_graph().update() @@ -177,46 +159,46 @@ class ActionHandler: ################################################## # Move/Rotate/Delete/Create ################################################## - elif state == Actions.BLOCK_MOVE: + elif action == 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: + elif action == 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: + elif action == 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: + elif action == 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) + Actions.NOTHING_SELECT() self.get_page().set_saved(False) - elif state == Actions.ELEMENT_CREATE: + elif action == 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) + Actions.NOTHING_SELECT() self.get_page().set_saved(False) - elif state == Actions.BLOCK_INC_TYPE: + elif action == 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: + elif action == 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: + elif action == Actions.PORT_CONTROLLER_INC: if self.get_flow_graph().port_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_DEC: + elif action == Actions.PORT_CONTROLLER_DEC: if self.get_flow_graph().port_controller_modify_selected(-1): self.get_flow_graph().update() self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data()) @@ -224,16 +206,16 @@ class ActionHandler: ################################################## # Window stuff ################################################## - elif state == Actions.ABOUT_WINDOW_DISPLAY: + elif action == Actions.ABOUT_WINDOW_DISPLAY: Dialogs.AboutDialog(self.get_flow_graph().get_parent()) - elif state == Actions.HELP_WINDOW_DISPLAY: + elif action == Actions.HELP_WINDOW_DISPLAY: Dialogs.HelpDialog() - elif state == Actions.TYPES_WINDOW_DISPLAY: + elif action == Actions.TYPES_WINDOW_DISPLAY: Dialogs.TypesDialog(self.get_flow_graph().get_parent()) ################################################## # Param Modifications ################################################## - elif state == Actions.BLOCK_PARAM_MODIFY: + elif action == Actions.BLOCK_PARAM_MODIFY: selected_block = self.get_flow_graph().get_selected_block() if selected_block: if PropsDialog(selected_block).run(): @@ -249,14 +231,14 @@ class ActionHandler: ################################################## # Undo/Redo ################################################## - elif state == Actions.FLOW_GRAPH_UNDO: + elif action == 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: + elif action == Actions.FLOW_GRAPH_REDO: n = self.get_page().get_state_cache().get_next_state() if n: self.get_flow_graph().unselect() @@ -266,19 +248,19 @@ class ActionHandler: ################################################## # New/Open/Save/Close ################################################## - elif state == Actions.FLOW_GRAPH_NEW: + elif action == Actions.FLOW_GRAPH_NEW: self.main_window.new_page() - elif state == Actions.FLOW_GRAPH_OPEN: + elif action == 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: + elif action == Actions.FLOW_GRAPH_CLOSE: self.main_window.close_page() - elif state == Actions.FLOW_GRAPH_SAVE: + elif action == 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) + Actions.FLOW_GRAPH_SAVE_AS() #otherwise try to save else: try: @@ -287,12 +269,12 @@ class ActionHandler: 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: + elif action == 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: + Actions.FLOW_GRAPH_SAVE() + elif action == Actions.FLOW_GRAPH_SCREEN_CAPTURE: file_path = SaveImageFileDialog(self.get_page().get_file_path()).run() if file_path is not None: pixbuf = self.get_flow_graph().get_drawing_area().get_pixbuf() @@ -300,10 +282,10 @@ class ActionHandler: ################################################## # Gen/Exec/Stop ################################################## - elif state == Actions.FLOW_GRAPH_GEN: + elif action == 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 + 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: @@ -311,37 +293,37 @@ class ActionHandler: generator.write() except Exception,e: Messages.send_fail_gen(e) else: self.generator = None - elif state == Actions.FLOW_GRAPH_EXEC: + elif action == Actions.FLOW_GRAPH_EXEC: if not self.get_page().get_pid(): - self.handle_states(Actions.FLOW_GRAPH_GEN) + 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: + elif action == 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 + elif action == Actions.PAGE_CHANGE: #pass and run the global actions pass - else: print '!!! State "%s" not handled !!!'%state + else: print '!!! Action "%s" not handled !!!'%action ################################################## # 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())) + Actions.ELEMENT_DELETE.set_sensitive(bool(self.get_flow_graph().get_selected_elements())) + Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(self.get_flow_graph().get_selected_block())) + Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + 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)) + Actions.BLOCK_CUT.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.BLOCK_COPY.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + 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())) + Actions.BLOCK_ENABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + 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()) + 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') @@ -351,6 +333,7 @@ class ActionHandler: #draw the flow graph self.get_flow_graph().update_selected() self.get_flow_graph().queue_draw() + return True #action was handled def update_exec_stop(self): """ @@ -358,9 +341,9 @@ class ActionHandler: 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) + Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive) + Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive) + 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.""" -- cgit From ae3c009666f2bba0e10e054b0747d8f82a29515f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 13 Sep 2009 03:25:56 -0700 Subject: tweaked key handling callbacks --- grc/gui/ActionHandler.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 59e535bd4..361be1cf8 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -81,9 +81,7 @@ class ActionHandler: """ try: assert self.get_focus_flag() except AssertionError: return False - try: Actions.get_action_from_key_press(event)() - except KeyError: return False - return True #handled by this method + return Actions.handle_key_press(event) def _quit(self, window, event): """ -- cgit From 14895064d7345c2223ff2b8ff3b9cbcdf69dd8c9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 18 Sep 2009 02:10:13 -0700 Subject: added errors dialog to show all error messages in flow graph --- grc/gui/ActionHandler.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 361be1cf8..ee3e19a6c 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -210,6 +210,8 @@ class ActionHandler: Dialogs.HelpDialog() elif action == Actions.TYPES_WINDOW_DISPLAY: Dialogs.TypesDialog(self.get_flow_graph().get_parent()) + elif action == Actions.ERRORS_WINDOW_DISPLAY: + Dialogs.ErrorsDialog(self.get_flow_graph()) ################################################## # Param Modifications ################################################## @@ -307,6 +309,7 @@ class ActionHandler: # Global Actions for all States ################################################## #update general buttons + Actions.ERRORS_WINDOW_DISPLAY.set_sensitive(not self.get_flow_graph().is_valid()) Actions.ELEMENT_DELETE.set_sensitive(bool(self.get_flow_graph().get_selected_elements())) Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(self.get_flow_graph().get_selected_block())) Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) -- cgit From 61830989ce554e6dfac41bba2ced7006c424e0bc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 6 Dec 2009 23:18:27 -0500 Subject: removed unused import statements, thanks pyflakes --- grc/gui/ActionHandler.py | 1 - 1 file changed, 1 deletion(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index ee3e19a6c..108e23a23 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -29,7 +29,6 @@ import Preferences from threading import Thread import Messages from .. base import ParseXML -import random from MainWindow import MainWindow from PropsDialog import PropsDialog import Dialogs -- cgit From 21158d425ff8d8b1ba8bbc6a89609b33fb4252b4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 13 Mar 2011 11:36:03 -0700 Subject: grc: swap store the subprocess object rather than the pid when executing For some reason os.kill(p.pid, SIGKILL) does not work on windows. However, the subprocess p.kill() works just fine for both systems. --- grc/gui/ActionHandler.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 108e23a23..350b297bb 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -1,5 +1,5 @@ """ -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +Copyright 2007, 2008, 2009, 2011 Free Software Foundation, Inc. This file is part of GNU Radio GNU Radio Companion is free software; you can redistribute it and/or @@ -282,7 +282,7 @@ class ActionHandler: # Gen/Exec/Stop ################################################## elif action == Actions.FLOW_GRAPH_GEN: - if not self.get_page().get_pid(): + if not self.get_page().get_proc(): if not self.get_page().get_saved() or not self.get_page().get_file_path(): 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(): @@ -293,14 +293,14 @@ class ActionHandler: except Exception,e: Messages.send_fail_gen(e) else: self.generator = None elif action == Actions.FLOW_GRAPH_EXEC: - if not self.get_page().get_pid(): + if not self.get_page().get_proc(): Actions.FLOW_GRAPH_GEN() if self.get_page().get_saved() and self.get_page().get_file_path(): ExecFlowGraphThread(self) elif action == 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() + if self.get_page().get_proc(): + try: self.get_page().get_proc().kill() + except: print "could not kill process: %d"%self.get_page().get_proc().pid elif action == Actions.PAGE_CHANGE: #pass and run the global actions pass else: print '!!! Action "%s" not handled !!!'%action @@ -340,10 +340,10 @@ class ActionHandler: 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() + sensitive = self.get_flow_graph().is_valid() and not self.get_page().get_proc() Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive) Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive) - Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_pid() != None) + Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() != None) class ExecFlowGraphThread(Thread): """Execute the flow graph as a new process and wait on it to finish.""" @@ -362,7 +362,7 @@ class ExecFlowGraphThread(Thread): #get the popen try: self.p = self.page.get_generator().get_popen() - self.page.set_pid(self.p.pid) + self.page.set_proc(self.p) #update self.update_exec_stop() self.start() @@ -385,5 +385,5 @@ class ExecFlowGraphThread(Thread): def done(self): """Perform end of execution tasks.""" Messages.send_end_exec() - self.page.set_pid(None) + self.page.set_proc(None) self.update_exec_stop() -- cgit From af1d0a61d01c7c17dedcb5388ed8a077213d4b4f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 14 Apr 2011 10:49:23 -0700 Subject: grc: replaced asserts in gui subdirectory --- grc/gui/ActionHandler.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 350b297bb..15785f2ee 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -1,5 +1,5 @@ """ -Copyright 2007, 2008, 2009, 2011 Free Software Foundation, Inc. +Copyright 2007-2011 Free Software Foundation, Inc. This file is part of GNU Radio GNU Radio Companion is free software; you can redistribute it and/or @@ -78,8 +78,7 @@ class ActionHandler: When not in focus, gtk and the accelerators handle the the key press. @return false to let gtk handle the key action """ - try: assert self.get_focus_flag() - except AssertionError: return False + if not self.get_focus_flag(): return False return Actions.handle_key_press(event) def _quit(self, window, event): -- cgit From f919f9dcbb54a08e6e26d6c229ce92fb784fa1b2 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Fri, 13 Apr 2012 18:36:53 -0400 Subject: Removed whitespace and added dtools/bin/remove-whitespace as a tool to do this in the future. The sed script was provided by Moritz Fischer. --- grc/gui/ActionHandler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 15785f2ee..476c82b4f 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -18,7 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ import os -import signal +import signal from Constants import IMAGE_FILE_EXTENSION import Actions import pygtk -- cgit From a07fe1904412af78b3d70a6225e6efe10c9efbe5 Mon Sep 17 00:00:00 2001 From: Tim O'Shea Date: Tue, 25 Sep 2012 11:40:10 -0400 Subject: adding GRC Reload Block XML action --- grc/gui/ActionHandler.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 476c82b4f..5600edc06 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -53,6 +53,7 @@ class ActionHandler: self.clipboard = None for action in Actions.get_all_actions(): action.connect('activate', self._handle_action) #setup the main window + self.platform = platform; self.main_window = MainWindow(platform) self.main_window.connect('delete-event', self._quit) self.main_window.connect('key-press-event', self._handle_key_press) @@ -302,6 +303,10 @@ class ActionHandler: except: print "could not kill process: %d"%self.get_page().get_proc().pid elif action == Actions.PAGE_CHANGE: #pass and run the global actions pass + elif action == Actions.RELOAD_BLOCKS: + self.platform.loadblocks() + self.main_window.btwin.clear(); + self.platform.load_block_tree(self.main_window.btwin); else: print '!!! Action "%s" not handled !!!'%action ################################################## # Global Actions for all States @@ -319,6 +324,7 @@ class ActionHandler: #update enable/disable Actions.BLOCK_ENABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) Actions.BLOCK_DISABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.RELOAD_BLOCKS.set_sensitive(True) #set the exec and stop buttons self.update_exec_stop() #saved status -- cgit From 515d1b6f91f5dd28997525b1e88006bbfc0f170a Mon Sep 17 00:00:00 2001 From: Tim O'Shea Date: Wed, 26 Sep 2012 14:18:30 -0400 Subject: added the ability to open custom GRC hier block definitions from graphs using an instance of them --- grc/gui/ActionHandler.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 5600edc06..d1491db0b 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -307,6 +307,11 @@ class ActionHandler: self.platform.loadblocks() self.main_window.btwin.clear(); self.platform.load_block_tree(self.main_window.btwin); + elif action == Actions.OPEN_HIER: + bn = []; + for b in self.get_flow_graph().get_selected_blocks(): + if b._grc_source: + self.main_window.new_page(b._grc_source, show=True); else: print '!!! Action "%s" not handled !!!'%action ################################################## # Global Actions for all States @@ -324,6 +329,7 @@ class ActionHandler: #update enable/disable Actions.BLOCK_ENABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) Actions.BLOCK_DISABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.OPEN_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) Actions.RELOAD_BLOCKS.set_sensitive(True) #set the exec and stop buttons self.update_exec_stop() -- cgit From de014bd0cb98226d90bdec6bcf4c7a20cc4ba6b9 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 3 Oct 2012 11:01:04 -0400 Subject: grc: populate file variable correctly when we save. --- grc/gui/ActionHandler.py | 1 + 1 file changed, 1 insertion(+) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index d1491db0b..430a05fc2 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -264,6 +264,7 @@ class ActionHandler: else: try: ParseXML.to_file(self.get_flow_graph().export_data(), self.get_page().get_file_path()) + self.get_flow_graph().grc_file_path = self.get_page().get_file_path() self.get_page().set_saved(True) except IOError: Messages.send_fail_save(self.get_page().get_file_path()) -- cgit From d7b57e43f186097f147534ad49c6337edc4fdc88 Mon Sep 17 00:00:00 2001 From: Tom Rondeau Date: Wed, 3 Oct 2012 11:10:11 -0400 Subject: grc: ability to automatically create hier_blocks from a flowgraph. Highlight a set of blocks and hit 'c' or right-click and 'Create Hier' to automatically build a new hier_block that opens in GRC with the probes in place. Any parameter/variables become parameters in the new graph. Save, generate, and hit the 'Reload Blocks' to get access to new block. --- grc/gui/ActionHandler.py | 129 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) (limited to 'grc/gui/ActionHandler.py') diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py index 430a05fc2..9fb5e4ebf 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/ActionHandler.py @@ -153,6 +153,134 @@ class ActionHandler: 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) + ################################################## + # Create heir block + ################################################## + elif action == Actions.BLOCK_CREATE_HIER: + + # keeping track of coordinates for pasting later + coords = self.get_flow_graph().get_selected_blocks()[0].get_coordinate() + x,y = coords + x_min = x + y_min = y + + pads = []; + params = []; + + # Save the state of the leaf blocks + for block in self.get_flow_graph().get_selected_blocks(): + + # Check for string variables within the blocks + for param in block.get_params(): + for variable in self.get_flow_graph().get_variables(): + # If a block parameter exists that is a variable, create a parameter for it + if param.get_value() == variable.get_id(): + params.append(param.get_value()) + for flow_param in self.get_flow_graph().get_parameters(): + # If a block parameter exists that is a parameter, create a parameter for it + if param.get_value() == flow_param.get_id(): + params.append(param.get_value()) + + + # keep track of x,y mins for pasting later + (x,y) = block.get_coordinate() + if x < x_min: + x_min = x + if y < y_min: + y_min = y + + for connection in block.get_connections(): + + # Get id of connected blocks + source_id = connection.get_source().get_parent().get_id() + sink_id = connection.get_sink().get_parent().get_id() + + # If connected block is not in the list of selected blocks create a pad for it + if self.get_flow_graph().get_block(source_id) not in self.get_flow_graph().get_selected_blocks(): + pads.append({'key': connection.get_sink().get_key(), 'coord': connection.get_source().get_coordinate(), 'block_id' : block.get_id(), 'direction': 'source'}) + + if self.get_flow_graph().get_block(sink_id) not in self.get_flow_graph().get_selected_blocks(): + pads.append({'key': connection.get_source().get_key(), 'coord': connection.get_sink().get_coordinate(), 'block_id' : block.get_id(), 'direction': 'sink'}) + + + # Copy the selected blocks and paste them into a new page + # then move the flowgraph to a reasonable position + Actions.BLOCK_COPY() + self.main_window.new_page() + Actions.BLOCK_PASTE() + coords = (x_min,y_min) + self.get_flow_graph().move_selected(coords) + + + # Set flow graph to heir block type + top_block = self.get_flow_graph().get_block("top_block") + top_block.get_param('generate_options').set_value('hb') + + # this needs to be a unique name + top_block.get_param('id').set_value('new_heir') + + # Remove the default samp_rate variable block that is created + remove_me = self.get_flow_graph().get_block("samp_rate") + self.get_flow_graph().remove_element(remove_me) + + + # Add the param blocks along the top of the window + x_pos = 150 + for param in params: + param_id = self.get_flow_graph().add_new_block('parameter',(x_pos,10)) + param_block = self.get_flow_graph().get_block(param_id) + param_block.get_param('id').set_value(param) + x_pos = x_pos + 100 + + for pad in pads: + # Add the pad sources and sinks within the new heir block + if pad['direction'] == 'sink': + + # Add new PAD_SINK block to the canvas + pad_id = self.get_flow_graph().add_new_block('pad_sink', pad['coord']) + + # setup the references to the sink and source + pad_block = self.get_flow_graph().get_block(pad_id) + pad_sink = pad_block.get_sinks()[0] + + source_block = self.get_flow_graph().get_block(pad['block_id']) + source = source_block.get_source(pad['key']) + + # Ensure the port types match + while pad_sink.get_type() != source.get_type(): + + # Special case for some blocks that have non-standard type names, e.g. uhd + if pad_sink.get_type() == 'complex' and source.get_type() == 'fc32': + break; + pad_block.type_controller_modify(1) + + # Connect the pad to the proper sinks + new_connection = self.get_flow_graph().connect(source,pad_sink) + + elif pad['direction'] == 'source': + pad_id = self.get_flow_graph().add_new_block('pad_source', pad['coord']) + + # setup the references to the sink and source + pad_block = self.get_flow_graph().get_block(pad_id) + pad_source = pad_block.get_sources()[0] + + sink_block = self.get_flow_graph().get_block(pad['block_id']) + sink = sink_block.get_sink(pad['key']) + + # Ensure the port types match + while sink.get_type() != pad_source.get_type(): + # Special case for some blocks that have non-standard type names, e.g. uhd + if pad_source.get_type() == 'complex' and sink.get_type() == 'fc32': + break; + pad_block.type_controller_modify(1) + + # Connect the pad to the proper sinks + new_connection = self.get_flow_graph().connect(pad_source,sink) + + # update the new heir block flow graph + self.get_flow_graph().update() + + ################################################## # Move/Rotate/Delete/Create ################################################## @@ -330,6 +458,7 @@ class ActionHandler: #update enable/disable Actions.BLOCK_ENABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) Actions.BLOCK_DISABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) + Actions.BLOCK_CREATE_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) Actions.OPEN_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks())) Actions.RELOAD_BLOCKS.set_sensitive(True) #set the exec and stop buttons -- cgit