def __init__(self, context): super(NodeManager, self).__init__(context) # Give QObjects reasonable names self.setObjectName('NodeManagerFKIE') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print('arguments: ', args) print('unknowns: ', unknowns) fkie_node_manager.init_settings() masteruri = fkie_node_manager.settings().masteruri() fkie_node_manager.init_globals(masteruri) # Create QWidget try: self._widget = MainWindow() # self._widget.read_view_history() except Exception, e: MessageBox.critical(None, "Node Manager", utf8(e)) raise
def file_changed(self, mtime): if self.file_mtime != mtime: self.file_mtime = mtime result = MessageBox.question(self, "File changed", "File was changed, reload?", buttons=MessageBox.Yes | MessageBox.No) if result == MessageBox.Yes: try: _, self.file_mtime, file_content = nm.nmd().file.get_file_content(self.filename, force=True) self.setText(file_content) self.document().setModified(False) self.textChanged.emit() except Exception as err: MessageBox.critical(self, "Error", "Cannot open launch file %s" % self.filename, utf8(err))
def save(self, force=False): ''' Saves changes to the file. :return: saved, errors, msg :rtype: bool, bool, str ''' if force or self.document().isModified(): try: mtime = nm.nmd().file.save_file(self.filename, self.toPlainText().encode('utf-8'), 0 if force else self.file_mtime) self.file_mtime = mtime if mtime == 0: MessageBox.warning(self, "Warning", "File not saved and not error reported: %s" % os.path.basename(self.filename)) self.document().setModified(mtime == 0) ext = os.path.splitext(self.filename) # validate the xml structure of the launch files if ext[1] in self.CONTEXT_FILE_EXT: imported = False try: from lxml import etree imported = True parser = etree.XMLParser() etree.fromstring(self.toPlainText().encode('utf-8'), parser) except Exception as e: if imported: self.markLine(e.position[0]) return True, True, "%s" % e # validate the yaml structure of yaml files elif ext[1] in self.YAML_VALIDATION_FILES: try: import ruamel.yaml ruamel.yaml.load(self.toPlainText().encode('utf-8'), Loader=ruamel.yaml.Loader) except ruamel.yaml.MarkedYAMLError as e: return True, True, "YAML validation error: %s" % e return True, False, '' except IOError as ioe: if ioe.errno in [file_item.EFILE_CHANGED, file_item.EFILE_REMOVED]: result = MessageBox.question(self, "Changed file", "%s\n%s" % (utf8(ioe), "Save anyway?"), buttons=MessageBox.Yes | MessageBox.No) if result == MessageBox.Yes: return self.save(force=True) else: rospy.logwarn("Error while save file: %s" % ioe) MessageBox.critical(self, "Error", "Error while save file: %s" % os.path.basename(self.filename), detailed_text=utf8(ioe)) except Exception as e: rospy.logwarn("Error while save file: %s" % e) print(traceback.format_exc()) return False, False, ''
def __init__(self, context): super(NodeManager, self).__init__(context) # Give QObjects reasonable names self.setObjectName('NodeManagerFKIE') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print('arguments: ', args) print('unknowns: ', unknowns) fkie_node_manager.init_settings() masteruri = fkie_node_manager.settings().masteruri() fkie_node_manager.init_globals(masteruri) # Create QWidget try: self._widget = MainWindow() # self._widget.read_view_history() except Exception as e: MessageBox.critical(None, "Node Manager", utf8(e)) raise # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder # ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'MyPlugin.ui') # Extend the widget with all attributes and children from UI file # loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('NodeManagerFKIEPlugin') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget)
def on_saveButton_clicked(self): ''' Saves the current document. This method is called if the C{save button} was clicked. ''' saved, errors, msg = self.tabWidget.currentWidget().save() if errors: if msg: rospy.logwarn(msg) MessageBox.critical(self, "Error", "Error while save file: %s" % os.path.basename(self.tabWidget.currentWidget().filename), detailed_text=msg) self.tabWidget.setTabIcon(self.tabWidget.currentIndex(), self._error_icon) self.tabWidget.setTabToolTip(self.tabWidget.currentIndex(), msg) self.on_graph_info("saved failed %s: %s" % (self.tabWidget.currentWidget().filename, msg), True) elif saved: self.on_graph_info("saved %s" % self.tabWidget.currentWidget().filename) self.tabWidget.setTabIcon(self.tabWidget.currentIndex(), self._empty_icon) self.tabWidget.setTabToolTip(self.tabWidget.currentIndex(), '') self.graph_view.clear_cache()
def mouseReleaseEvent(self, event): ''' Opens the new editor, if the user clicked on the included file and sets the default cursor. ''' if self.isReadOnly(): event.accept() return if event.modifiers() == Qt.ControlModifier or event.modifiers( ) == Qt.ShiftModifier: cursor = self.cursorForPosition(event.pos()) try: textblock = self._strip_bad_parts(cursor.block().text(), cursor.positionInBlock()) for inc_file in find_included_files(textblock, False, False, search_in_ext=[]): aval = inc_file.raw_inc_path aitems = aval.split("'") for search_for in aitems: if not search_for: continue try: rospy.logdebug("try to interpret: %s" % search_for) args_in_name = get_arg_names(search_for) resolved_args = {} # if found arg in the name, try to detect values if args_in_name: rospy.logdebug( " args %s in filename found, try to resolve..." % args_in_name) resolved_args = self.parent.graph_view.get_include_args( args_in_name, search_for, self.filename) if resolved_args: params = {} self._internal_args # create parameter dialog for key, val in resolved_args.items(): values = list(val) # add args defined in current file if key in self._internal_args and self._internal_args[ key] not in values: values.append(self._internal_args[key]) params[key] = { ':type': 'string', ':value': values } dia = ParameterDialog( params, store_geometry="open_launch_on_click") dia.setFilterVisible(False) dia.setWindowTitle('Select Parameter') if dia.exec_(): params = dia.getKeywords() search_for = replace_arg( search_for, params) else: # canceled -> cancel interpretation QTextEdit.mouseReleaseEvent(self, event) return # now resolve find-statements rospy.logdebug( " send interpret request to daemon: %s" % search_for) inc_files = nm.nmd().launch.get_interpreted_path( self.filename, text=[search_for]) for path, exists in inc_files: try: rospy.logdebug( " received interpret request from daemon: %s, exists: %d" % (path, exists)) if exists: event.setAccepted(True) self.load_request_signal.emit(path) else: _filename, file_extension = os.path.splitext( path) if file_extension in nm.settings( ).launch_view_file_ext: # create a new file, if it does not exists result = MessageBox.question( self, "File not exists", '\n\n'.join([ "Create a new file?", path ]), buttons=MessageBox.Yes | MessageBox.No) if result == MessageBox.Yes: content = '<launch>\n\n</launch>' if path.endswith( '.launch') else '' nm.nmd().file.save_file( path, content.encode(), 0) event.setAccepted(True) self.load_request_signal.emit( path) except Exception as e: MessageBox.critical(self, "Error", "File not found %s" % path, detailed_text=utf8(e)) except exceptions.ResourceNotFound as not_found: MessageBox.critical( self, "Error", "Resource not found %s" % search_for, detailed_text=utf8(not_found.error)) except Exception as err: print(traceback.format_exc()) MessageBox.critical(self, "Error", "Error while request included file %s" % self.filename, detailed_text=utf8(err)) QTextEdit.mouseReleaseEvent(self, event)
def on_load_request(self, filename, search_text='', insert_index=-1, goto_line=-1, only_launch=False, count_results=0): ''' Loads a file in a new tab or focus the tab, if the file is already open. :param str filename: the path to file :param str search_text: if not empty, searches in new document for first occurrence of the given text ''' if not filename: return self.tabWidget.setUpdatesEnabled(False) try: if filename not in self.files: tab_name = self.__getTabName(filename) editor = TextEdit(filename, parent=self) linenumber_editor = LineNumberWidget(editor) tab_index = 0 if insert_index > -1: tab_index = self.tabWidget.insertTab(insert_index, linenumber_editor, tab_name) else: tab_index = self.tabWidget.addTab(linenumber_editor, tab_name) self.files.append(filename) editor.setCurrentPath(os.path.basename(filename)) editor.load_request_signal.connect(self.on_load_request) editor.document().modificationChanged.connect(self.on_editor_modificationChanged) editor.cursorPositionChanged.connect(self.on_editor_positionChanged) editor.setFocus(Qt.OtherFocusReason) # editor.textChanged.connect(self.on_text_changed) editor.undoAvailable.connect(self.on_text_changed) self.tabWidget.setCurrentIndex(tab_index) # self.find_dialog.set_search_path(filename) else: for i in range(self.tabWidget.count()): if self.tabWidget.widget(i).filename == filename: self.tabWidget.setCurrentIndex(i) break self.tabWidget.setUpdatesEnabled(True) if search_text: if only_launch: self.find_dialog.found_files_list.clear() try: self._search_thread.stop() self._search_thread = None except Exception: pass # TODO: put all text of all tabs into path_text rospy.logdebug("serach for '%s'" % search_text) self._search_node_count = 0 self._search_thread = TextSearchThread(search_text, filename, recursive=True, only_launch=only_launch, count_results=count_results) self._search_thread.search_result_signal.connect(self.on_search_result_on_open) self._search_thread.warning_signal.connect(self.on_search_result_warning) self._last_search_request = (filename, search_text, insert_index, goto_line, only_launch) if not self.graph_view.is_loading(): self.on_graph_info("search thread: start search for '%s'" % self._search_thread._search_text) self._search_thread.start() if goto_line != -1: self._goto(goto_line, True) self.upperButton.setEnabled(self.tabWidget.count() > 1) except Exception as err: self.tabWidget.setUpdatesEnabled(True) import traceback msg = "Error while open %s: %s" % (filename, traceback.format_exc()) rospy.logwarn(msg) MessageBox.critical(self, "Error", utf8(err), msg) if self.tabWidget.count() == 0: self.close()