def update_selected_elements(self): """ Update the selected elements. The update behavior depends on the state of the mouse button. When the mouse button pressed the selection will change when the control mask is set or the new selection is not in the current group. When the mouse button is released the selection will change when the mouse has moved and the control mask is set or the current group is empty. Attempt to make a new connection if the old and ports are filled. If the control mask is set, merge with the current elements. """ selected_elements = None if self.mouse_pressed: new_selections = self.what_is_selected(self.get_coordinate()) #update the selections if the new selection is not in the current selections #allows us to move entire selected groups of elements if self.get_ctrl_mask() or not (new_selections and new_selections[0] in self.get_selected_elements()): selected_elements = new_selections if self._old_selected_port: self._old_selected_port.force_label_unhidden(False) self.create_shapes() self.queue_draw() elif self._new_selected_port: self._new_selected_port.force_label_unhidden() else: # called from a mouse release if not self.element_moved and (not self.get_selected_elements() or self.get_ctrl_mask()): selected_elements = self.what_is_selected( self.get_coordinate(), self.press_coor) #this selection and the last were ports, try to connect them if self._old_selected_port and self._new_selected_port: try: self.connect(self._old_selected_port, self._new_selected_port) Actions.ELEMENT_CREATE() except: Messages.send_fail_connection() self._old_selected_port = None self._new_selected_port = None return #update selected elements if selected_elements is None: return old_elements = set(self.get_selected_elements()) self._selected_elements = list(set(selected_elements)) new_elements = set(self.get_selected_elements()) #if ctrl, set the selected elements to the union - intersection of old and new if self.get_ctrl_mask(): self._selected_elements = list( set.union(old_elements, new_elements) - set.intersection(old_elements, new_elements)) Actions.ELEMENT_SELECT()
def _handle_action(self, action): #print action ################################################## # Initialize/Quit ################################################## 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 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.TOGGLE_BLOCKS_WINDOW, Actions.TOGGLE_REPORTS_WINDOW, Actions.TOGGLE_HIDE_DISABLED_BLOCKS, Actions.TOOLS_RUN_FDESIGN, Actions.TOGGLE_SCROLL_LOCK, Actions.CLEAR_REPORTS, Actions.SAVE_REPORTS, Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, Actions.TOGGLE_SNAP_TO_GRID, Actions.TOGGLE_SHOW_BLOCK_COMMENTS, Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB, ): action.set_sensitive(True) if ParseXML.xml_failures: Messages.send_xml_errors_if_any(ParseXML.xml_failures) Actions.XML_PARSER_ERRORS_DISPLAY.set_sensitive(True) if not self.init_file_paths: self.init_file_paths = filter(os.path.exists, 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 self.main_window.btwin.search_entry.hide() for action in ( Actions.TOGGLE_REPORTS_WINDOW, Actions.TOGGLE_BLOCKS_WINDOW, Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, Actions.TOGGLE_SCROLL_LOCK, Actions.TOGGLE_SNAP_TO_GRID, Actions.TOGGLE_SHOW_BLOCK_COMMENTS, Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB, ): action.load_from_preferences() elif action == Actions.APPLICATION_QUIT: if self.main_window.close_pages(): gtk.main_quit() exit(0) ################################################## # Selections ################################################## elif action == Actions.ELEMENT_SELECT: pass #do nothing, update routines below elif action == Actions.NOTHING_SELECT: self.get_flow_graph().unselect() ################################################## # Enable/Disable ################################################## 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 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()) self.get_page().set_saved(False) elif action == Actions.BLOCK_BYPASS: if self.get_flow_graph().bypass_selected(): 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 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 action == 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) ################################################## # 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 ################################################## 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 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 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 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()) Actions.NOTHING_SELECT() self.get_page().set_saved(False) 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()) Actions.NOTHING_SELECT() self.get_page().set_saved(False) 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 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 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 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()) self.get_page().set_saved(False) ################################################## # Window stuff ################################################## elif action == Actions.ABOUT_WINDOW_DISPLAY: Dialogs.AboutDialog(self.get_flow_graph().get_parent()) elif action == Actions.HELP_WINDOW_DISPLAY: 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()) elif action == Actions.TOGGLE_REPORTS_WINDOW: if action.get_active(): self.main_window.reports_scrolled_window.show() else: self.main_window.reports_scrolled_window.hide() action.save_to_preferences() elif action == Actions.TOGGLE_BLOCKS_WINDOW: if action.get_active(): self.main_window.btwin.show() else: self.main_window.btwin.hide() action.save_to_preferences() elif action == Actions.TOGGLE_SCROLL_LOCK: active = action.get_active() self.main_window.text_display.scroll_lock = active if active: self.main_window.text_display.scroll_to_end() action.save_to_preferences() elif action == Actions.CLEAR_REPORTS: self.main_window.text_display.clear() elif action == Actions.SAVE_REPORTS: file_path = SaveReportsFileDialog( self.get_page().get_file_path()).run() if file_path is not None: self.main_window.text_display.save(file_path) elif action == Actions.TOGGLE_HIDE_DISABLED_BLOCKS: Actions.NOTHING_SELECT() elif action == Actions.TOGGLE_AUTO_HIDE_PORT_LABELS: action.save_to_preferences() for page in self.main_window.get_pages(): page.get_flow_graph().create_shapes() elif action == Actions.TOGGLE_SNAP_TO_GRID: action.save_to_preferences() elif action == Actions.TOGGLE_SHOW_BLOCK_COMMENTS: action.save_to_preferences() elif action == Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB: action.save_to_preferences() ################################################## # Param Modifications ################################################## elif action == Actions.BLOCK_PARAM_MODIFY: selected_block = self.get_flow_graph().get_selected_block() if selected_block: dialog = PropsDialog(selected_block) response = gtk.RESPONSE_APPLY while response == gtk.RESPONSE_APPLY: # rerun the dialog if Apply was hit response = dialog.run() if response in (gtk.RESPONSE_APPLY, gtk.RESPONSE_ACCEPT): 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() if response == gtk.RESPONSE_APPLY: # null action, that updates the main window Actions.ELEMENT_SELECT() dialog.destroy() ################################################## # View Parser Errors ################################################## elif action == Actions.XML_PARSER_ERRORS_DISPLAY: ParserErrorsDialog(ParseXML.xml_failures).run() ################################################## # Undo/Redo ################################################## 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 action == 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 action == Actions.FLOW_GRAPH_NEW: self.main_window.new_page() 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 action == Actions.FLOW_GRAPH_CLOSE: self.main_window.close_page() 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(): 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_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()) self.get_page().set_saved(False) 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) 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() pixbuf.save(file_path, IMAGE_FILE_EXTENSION[1:]) ################################################## # Gen/Exec/Stop ################################################## elif action == Actions.FLOW_GRAPH_GEN: 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(): 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