def loadCache(self, history_file): ''' Loads the content of the given file and return it as cache. @param history_file: the name of the history file @type history_file: C{str} @return: the dictionary with arguments @rtype: C{dict(str(name):[str(value), ...], ...)} ''' result = {} historyFile = os.path.join(nm.settings().cfg_path, history_file) if os.path.isfile(historyFile): with open(historyFile, 'r') as f: line = f.readline() while line: if line: line = line.strip() if line: key, sep, value = line.partition(':=') if sep: if not key in result.keys(): result[key] = [value] elif len(result[key]) <= nm.settings().param_history_length: result[key].append(value) line = f.readline() return result
def on_launch_selection_activated(self, activated): ''' Tries to load the launch file, if one was activated. ''' selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) for item in selected: try: lfile = self.launchlist_model.expandItem(item.name, item.path, item.id) self.searchPackageLine.setText('') if lfile is not None: if item.isLaunchFile(): nm.settings().launch_history_add(item.path) key_mod = QApplication.keyboardModifiers() if key_mod & Qt.ShiftModifier: self.load_as_default_signal.emit(item.path, None) elif key_mod & Qt.ControlModifier: self.launchlist_model.setPath(os.path.dirname(item.path)) else: self.load_signal.emit(item.path, [], None) elif item.isProfileFile(): nm.settings().launch_history_add(item.path) key_mod = QApplication.keyboardModifiers() if key_mod & Qt.ControlModifier: self.launchlist_model.setPath(os.path.dirname(item.path)) else: self.load_profile_signal.emit(item.path) elif item.isConfigFile(): self.edit_signal.emit([lfile]) except Exception as e: rospy.logwarn("Error while load launch file %s: %s" % (item, e)) WarningMessageBox(QMessageBox.Warning, "Load error", 'Error while load launch file:\n%s' % item.name, "%s" % e).exec_()
def keyPressEvent(self, event): ''' Defines some of shortcuts for navigation/management in launch list view or topics view. ''' key_mod = QApplication.keyboardModifiers() if not self.xmlFileView.state() == QAbstractItemView.EditingState: # remove history file from list by pressing DEL if event == QKeySequence.Delete: selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) for item in selected: nm.settings().launch_history_remove(item.path) self.launchlist_model.reloadCurrentPath() elif not key_mod and event.key() == Qt.Key_F4 and self.editXmlButton.isEnabled(): # open selected launch file in xml editor by F4 self.on_edit_xml_clicked() elif event == QKeySequence.Find: # set focus to filter box for packages self.searchPackageLine.setFocus(Qt.ActiveWindowFocusReason) elif event == QKeySequence.Paste: # paste files from clipboard self.launchlist_model.paste_from_clipboard() elif event == QKeySequence.Copy: # copy the selected items as file paths into clipboard selected = self.xmlFileView.selectionModel().selectedIndexes() indexes = [] for s in selected: indexes.append(self.launchlist_proxyModel.mapToSource(s)) self.launchlist_model.copy_to_clipboard(indexes) if self.searchPackageLine.hasFocus() and event.key() == Qt.Key_Escape: # cancel package filtering on pressing ESC self.launchlist_model.show_packages(False) self.searchPackageLine.setText('') self.xmlFileView.setFocus(Qt.ActiveWindowFocusReason) QDockWidget.keyReleaseEvent(self, event)
def on_load_as_default_at_host(self): ''' Tries to load the selected launch file as default configuration. The button is only enabled and this method is called, if the button was enabled by on_launch_selection_clicked() ''' selected = self._launchItemsFromIndexes( self.xmlFileView.selectionModel().selectedIndexes(), False) for item in selected: path = self.launchlist_model.expandItem(item.name, item.path, item.id) if path is not None: params = {'Host': ('string', 'localhost')} dia = ParameterDialog(params) dia.setFilterVisible(False) dia.setWindowTitle('Start node on...') dia.resize(350, 120) dia.setFocusField('Host') if dia.exec_(): try: params = dia.getKeywords() host = params['Host'] rospy.loginfo( "LOAD the launch file on host %s as default: %s" % (host, path)) nm.settings().launch_history_add(path) self.load_as_default_signal.emit(path, host) except Exception, e: MessageBox.warning(self, "Load default config error", 'Error while parse parameter', '%s' % utf8(e))
def setModelData(self, editor, model, index): if isinstance(editor, PathEditor): cfg_path = nm.settings().cfg_path model.setData(index, editor.path) self.reload_settings = (cfg_path != nm.settings().cfg_path) else: QtGui.QStyledItemDelegate.setModelData(self, editor, model, index)
def setModelData(self, editor, model, index): if isinstance(editor, PathEditor): cfg_path = nm.settings().cfg_path model.setData(index, editor.path) self.reload_settings = (cfg_path != nm.settings().cfg_path) else: QStyledItemDelegate.setModelData(self, editor, model, index)
def on_load_as_default_at_host(self): ''' Tries to load the selected launch file as default configuration. The button is only enabled and this method is called, if the button was enabled by on_launch_selection_clicked() ''' selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) for item in selected: path = self.launchlist_model.expandItem(item.name, item.path, item.id) if path is not None: params = {'Host': ('string', 'localhost')} dia = ParameterDialog(params) dia.setFilterVisible(False) dia.setWindowTitle('Start node on...') dia.resize(350, 120) dia.setFocusField('Host') if dia.exec_(): try: params = dia.getKeywords() host = params['Host'] rospy.loginfo("LOAD the launch file on host %s as default: %s" % (host, path)) nm.settings().launch_history_add(path) self.load_as_default_signal.emit(path, host) except Exception, e: MessageBox.warning(self, "Load default config error", 'Error while parse parameter', '%s' % utf8(e))
def get_profile_file(self): # save the profile (path, _) = QFileDialog.getSaveFileName( self, "New profile file", nm.settings().current_dialog_path, "node manager profile files (*.nmprofile);;All files (*)" ) # _:=filter if path: if not path.endswith('.nmprofile'): path = "%s.nmprofile" % path nm.settings().current_dialog_path = os.path.dirname(path) try: (pkg, _) = package_name(os.path.dirname(path)) # _:=pkg_path if pkg is None: ret = WarningMessageBox( QMessageBox.Warning, "New File Error", 'The new file is not in a ROS package', buttons=QMessageBox.Ok | QMessageBox.Cancel).exec_() if ret == QMessageBox.Cancel: return None return path except EnvironmentError as e: WarningMessageBox(QMessageBox.Warning, "New File Error", 'Error while create a new file', str(e)).exec_() return None
def on_launch_selection_activated(self, activated): ''' Tries to load the launch file, if one was activated. ''' selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) for item in selected: try: lfile = self.launchlist_model.expandItem(item.name, item.path, item.id) self.searchPackageLine.setText('') if lfile is not None: if item.isLaunchFile(): nm.settings().launch_history_add(item.path) key_mod = QApplication.keyboardModifiers() if key_mod & Qt.ShiftModifier: self.load_as_default_signal.emit(item.path, None) elif key_mod & Qt.ControlModifier: self.launchlist_model.setPath(os.path.dirname(item.path)) else: self.load_signal.emit(item.path, [], None) elif item.isProfileFile(): nm.settings().launch_history_add(item.path) key_mod = QApplication.keyboardModifiers() if key_mod & Qt.ControlModifier: self.launchlist_model.setPath(os.path.dirname(item.path)) else: self.load_profile_signal.emit(item.path) elif item.isConfigFile(): self.edit_signal.emit([lfile]) except Exception as e: rospy.logwarn("Error while load launch file %s: %s" % (item, utf8(e))) MessageBox.warning(self, "Load error", 'Error while load launch file:\n%s' % item.name, "%s" % utf8(e))
def storeSetting(self): if nm.settings().store_geometry: settings = nm.settings().qsettings(nm.settings().CFG_GUI_FILE) settings.beginGroup("editor") settings.setValue("size", self.size()) settings.setValue("pos", self.pos()) settings.setValue("maximized", self.isMaximized()) settings.endGroup()
def on_open_xml_clicked(self): (fileName, _) = QFileDialog.getOpenFileName( self, "Load launch file", self.__current_path, "Config files (*.launch);;All files (*)") if fileName: self.__current_path = os.path.dirname(fileName) nm.settings().launch_history_add(fileName) self.load_signal.emit(fileName, [], None)
def _on_checkbox_state_changed(self, state): if self.questionid == self.TYPE_NODELET: self.frameui.questionOkButton.setVisible(not state) nm.settings().check_for_nodelets_at_start = not state elif self.questionid == self.TYPE_NOSCREEN: self.frameui.questionCancelButton.setVisible(not state) nm.settings().show_noscreen_error = not state else: self._do_not_ask[self.questionid] = state
def on_open_xml_clicked(self): (fileName, _) = QFileDialog.getOpenFileName(self, "Load launch file", self.__current_path, "Config files (*.launch);;All files (*)") if fileName: self.__current_path = os.path.dirname(fileName) nm.settings().launch_history_add(fileName) self.load_signal.emit(fileName, [], None)
def readSettings(self): if nm.settings().store_geometry: settings = nm.settings().qsettings(nm.settings().CFG_GUI_FILE) settings.beginGroup("editor") maximized = settings.value("maximized", 'false') == 'true' if maximized: self.showMaximized() else: self.resize(settings.value("size", QtCore.QSize(800,640))) self.move(settings.value("pos", QtCore.QPoint(0, 0))) settings.endGroup()
def on_load_xml_clicked(self): ''' Tries to load the selected launch file. The button is only enabled and this method is called, if the button was enabled by on_launch_selection_clicked() ''' selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) for item in selected: path = self.launchlist_model.expandItem(item.name, item.path, item.id) if path is not None: nm.settings().launch_history_add(item.path) self.load_signal.emit(path, [], None)
def _storeLoadHistory(self, files): ''' Saves the list of recently loaded files to history. The existing history will be replaced! @param files: the list with filenames @type files: C{[str]} ''' historyFile = nm.settings().qsettings(nm.settings().LAUNCH_HISTORY_FILE) historyFile.beginWriteArray("launch_history") for i, file in enumerate(files): historyFile.setArrayIndex(i) historyFile.setValue("file", file) historyFile.endArray()
def includedFiles(self): ''' Returns all included files in the document. ''' result = [] b = self.document().begin() while b != self.document().end(): text = b.text() index = self.index(text) if index > -1: startIndex = text.find('"', index) if startIndex > -1: endIndex = text.find('"', startIndex + 1) fileName = text[startIndex + 1:endIndex] if len(fileName) > 0: try: path = interpret_path(fileName) f = QFile(path) ext = os.path.splitext(path) if f.exists() and ext[1] in nm.settings( ).SEARCH_IN_EXT: result.append(path) except: import traceback print traceback.format_exc(1) b = b.next() return result
def _included_files(self, path): ''' Returns all included files in the given file. ''' result = [] with open(path, 'r') as f: data = f.read() reg = QRegExp("=[\s\t]*\".*\"") reg.setMinimal(True) pos = reg.indexIn(data) while pos != -1 and self._isrunning: try: pp = interpret_path(reg.cap(0).strip('"')) f = QFile(pp) ext = os.path.splitext(pp) if f.exists() and ext[1] in nm.settings().SEARCH_IN_EXT: result.append(pp) except Exception as exp: parsed_text = pp try: parsed_text = reg.cap(0).strip('"') except: pass self.warning_signal.emit("Error while parse '%s': %s" % (parsed_text, exp)) pos += reg.matchedLength() pos = reg.indexIn(data, pos) return result
def transfer(self, host, local_file, remote_file, user=None, pw=None, auto_pw_request=False): ''' Copies a file to a remote location using paramiko sfpt. @param host: the host @type host: C{str} @param local_file: the local file @type local_file: str @param remote_file: the remote file name @type remote_file: str @param user: user name @param pw: the password ''' with self.mutex: try: ssh = self._getSSH(host, nm.settings().host_user(host) if user is None else user, pw, True, auto_pw_request) if ssh is not None: sftp = ssh.open_sftp() try: sftp.mkdir(os.path.dirname(remote_file)) except: pass sftp.put(local_file, remote_file) rospy.loginfo("SSH COPY %s -> %s@%s:%s", local_file, ssh._transport.get_username(), host, remote_file) except AuthenticationRequest as e: raise except Exception, e: raise
def setData(self, value, role=Qt.EditRole): if role == Qt.EditRole: # rename the file or folder if self.name != value and self.id in [self.RECENT_FILE, self.LAUNCH_FILE, self.RECENT_PROFILE, self.PROFILE, self.CFG_FILE, self.FOLDER]: new_path = os.path.join(os.path.dirname(self.path), value) if not os.path.exists(new_path): os.rename(self.path, new_path) if self.name != value and self.id in [self.RECENT_FILE, self.RECENT_PROFILE]: # update in history nm.settings().launch_history_add(new_path, replace=self.path) self.name = value self.path = new_path else: WarningMessageBox(QMessageBox.Warning, "Path already exists", "`%s` already exists!" % value, "Complete path: %s" % new_path).exec_() return QStandardItem.setData(self, value, role)
def readSettings(self): if nm.settings().store_geometry: settings = nm.settings().qsettings(nm.settings().CFG_GUI_FILE) settings.beginGroup("editor") maximized = settings.value("maximized", 'false') == 'true' if maximized: self.showMaximized() else: self.resize(settings.value("size", QSize(800, 640))) self.move(settings.value("pos", QPoint(0, 0))) try: self.restoreState(settings.value("window_state")) except: import traceback print traceback.format_exc() settings.endGroup()
def updateDescription(self, index, cfg, name, displayed_name, robot_type, description, images): ''' Sets the values of an existing item to the given items only if the current value is empty. ''' if index < len(self._data): obj = self._data[index] if cfg not in obj['cfgs']: obj['cfgs'].append(cfg) if not obj['name']: obj['name'] = name if not obj['displayed_name']: obj['displayed_name'] = displayed_name if not obj['type']: obj['type'] = robot_type if not obj['description']: obj['description'] = resolve_paths(description) if not obj['images']: for image_path in images: img = resolve_paths(image_path) if img and img[0] != os.path.sep: img = os.path.join(nm.settings().PACKAGE_DIR, image_path) if os.path.isfile(img): obj['images'].append(QPixmap(img))
def deleteLog(cls, nodename, host, auto_pw_request=False, user=None, pw=None): ''' Deletes the log file associated with the given node. @param nodename: the name of the node (with name space) @type nodename: C{str} @param host: the host name or ip where the log file are to delete @type host: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("delete log for '%s' on '%s'", str(nodename), str(host)) if nm.is_local(host): screenLog = nm.screen().getScreenLogFile(node=nodename) pidFile = nm.screen().getScreenPidFile(node=nodename) roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(screenLog): os.remove(screenLog) if os.path.isfile(pidFile): os.remove(pidFile) if os.path.isfile(roslog): os.remove(roslog) else: try: # output ignored: output, error, ok nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--delete_logs', nodename], user, pw, auto_pw_request, close_stdin=True, close_stdout=True, close_stderr=True) except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.deleteLog, (nodename, host, auto_pw_request))
def includedFiles(self): ''' Returns all included files in the document. ''' result = [] b = self.document().begin() while b != self.document().end(): text = b.text() index = self.index(text) if index > -1: startIndex = text.find('"', index) if startIndex > -1: endIndex = text.find('"', startIndex + 1) fileName = text[startIndex + 1:endIndex] if len(fileName) > 0: try: path = interpret_path(fileName) f = QFile(path) ext = os.path.splitext(path) if f.exists() and ext[1] in nm.settings().SEARCH_IN_EXT: result.append(path) except: import traceback print traceback.format_exc(1) b = b.next() return result
def storeCache(self, history_file, cache, history_len): ''' Stores the cache to a file. @param history_file: the name of the history file @type history_file: C{str} @param cache: the dictionary with values @type cache: C{dict} @param history_len: the maximal count of value for a key @type history_len: C{int} ''' ignored = dict() with codecs.open(os.path.join(nm.settings().cfg_path, history_file), 'w', encoding='utf-8') as f: for key in cache.keys(): count = 0 for value in cache[key]: if count < history_len: try: f.write(''.join([key, ':=', utf8(value), '\n'])) except UnicodeEncodeError, e: ignored[key] = (value, utf8(e)) except: import traceback rospy.logwarn("Storing history aborted: %s", traceback.format_exc(3)) count += 1
def openScreenTerminal(cls, host, screen_name, nodename, user=None): ''' Open the screen output in a new terminal. @param host: the host name or ip where the screen is running. @type host: C{str} @param screen_name: the name of the screen to show @type screen_name: C{str} @param nodename: the name of the node is used for the title of the terminal @type nodename: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' #create a title of the terminal # pid, session_name = cls.splitSessionName(screen_name) title_opt = 'SCREEN %s on %s' % (nodename, host) if nm.is_local(host): cmd = nm.settings().terminal_cmd([cls.SCREEN, '-x', screen_name], title_opt) rospy.loginfo("Open screen terminal: %s", cmd) ps = subprocess.Popen(shlex.split(cmd)) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start() else: ps = nm.ssh().ssh_x11_exec(host, [cls.SCREEN, '-x', screen_name], title_opt, user) rospy.loginfo("Open remote screen terminal: %s", ps) # wait for process to avoid 'defunct' processes thread = threading.Thread(target=ps.wait) thread.setDaemon(True) thread.start()
def _document_position_changed(self): if isinstance(self.hl, XmlHighlighter) and nm.settings().highlight_xml_blocks: # import time # start_time = time.time() self.hl.mark_block(self.textCursor().block(), self.textCursor().positionInBlock())
def ssh_exec(self, host, cmd, user=None, pw=None, auto_pw_request=False, get_pty=False, close_stdin=False, close_stdout=False, close_stderr=False): ''' Executes a command on remote host. Returns the output channels with execution result or None. The connection will be established using paramiko SSH library. @param host: the host @type host: C{str} @param cmd: the list with command and arguments @type cmd: C{[str,...]} @param user: user name @param pw: the password @return: the 4-tuple stdin, stdout, stderr and boolean of the executing command @rtype: C{tuple(ChannelFile, ChannelFile, ChannelFile, boolean)} @see: U{http://www.lag.net/paramiko/docs/paramiko.SSHClient-class.html#exec_command} ''' with self.mutex: try: ssh = self._getSSH(host, nm.settings().host_user(host) if user is None else user, pw, True, auto_pw_request) if not ssh is None: cmd_str = str(' '.join(cmd)) rospy.loginfo("REMOTE execute on %s@%s: %s", ssh._transport.get_username(), host, cmd_str) (stdin, stdout, stderr) = ssh.exec_command(cmd_str, get_pty=get_pty) if close_stdin: stdin.close() if close_stdout: stdout.close() if close_stderr: stderr.close() return stdin, stdout, stderr, True except AuthenticationRequest as e: raise except Exception as e: raise raise Exception('Can not login @%s'%host)
def setData(self, value, role=Qt.EditRole): if role == Qt.EditRole: # rename the file or folder if self.name != value and self.id in [self.RECENT_FILE, self.LAUNCH_FILE, self.RECENT_PROFILE, self.PROFILE, self.CFG_FILE, self.FOLDER]: new_path = os.path.join(os.path.dirname(self.path), value) if not os.path.exists(new_path): os.rename(self.path, new_path) if self.name != value and self.id in [self.RECENT_FILE, self.RECENT_PROFILE]: # update in history nm.settings().launch_history_add(new_path, replace=self.path) self.name = value self.path = new_path else: MessageBox.warning(self, "Path already exists", "`%s` already exists!" % value, "Complete path: %s" % new_path) return QStandardItem.setData(self, value, role)
def deleteLog(cls, nodename, host, auto_pw_request=False, user=None, pw=None): ''' Deletes the log file associated with the given node. @param nodename: the name of the node (with name space) @type nodename: C{str} @param host: the host name or ip where the log file are to delete @type host: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("delete log for '%s' on '%s'", utf8(nodename), utf8(host)) if nm.is_local(host): screenLog = nm.screen().getScreenLogFile(node=nodename) pidFile = nm.screen().getScreenPidFile(node=nodename) roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(screenLog): os.remove(screenLog) if os.path.isfile(pidFile): os.remove(pidFile) if os.path.isfile(roslog): os.remove(roslog) else: try: # output ignored: output, error, ok _, stdout, _, ok = nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--delete_logs', nodename], user, pw, auto_pw_request, close_stdin=True, close_stdout=False, close_stderr=True) if ok: stdout.readlines() stdout.close() except nm.AuthenticationRequest as e: raise nm.InteractionNeededError(e, cls.deleteLog, (nodename, host, auto_pw_request))
def transfer(self, host, local_file, remote_file, user=None, pw=None, auto_pw_request=False): ''' Copies a file to a remote location using paramiko sfpt. @param host: the host @type host: C{str} @param local_file: the local file @type local_file: str @param remote_file: the remote file name @type remote_file: str @param user: user name @param pw: the password ''' with self.mutex: try: ssh = self._getSSH(host, nm.settings().host_user(host) if user is None else user, pw, True, auto_pw_request) if not ssh is None: sftp = ssh.open_sftp() try: sftp.mkdir(os.path.dirname(remote_file)) except: pass sftp.put(local_file, remote_file) rospy.loginfo("SSH COPY %s -> %s@%s:%s", local_file, ssh._transport.get_username(), host, remote_file) except AuthenticationRequest as e: raise except Exception, e: raise
def openScreenTerminal(cls, host, screen_name, nodename, user=None): ''' Open the screen output in a new terminal. @param host: the host name or ip where the screen is running. @type host: C{str} @param screen_name: the name of the screen to show @type screen_name: C{str} @param nodename: the name of the node is used for the title of the terminal @type nodename: C{str} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' #create a title of the terminal # pid, session_name = cls.splitSessionName(screen_name) title_opt = 'SCREEN %s on %s' % (nodename, host) if nm.is_local(host): cmd = nm.settings().terminal_cmd([cls.SCREEN, '-x', screen_name], title_opt) rospy.loginfo("Open screen terminal: %s", cmd) SupervisedPopen(shlex.split(cmd), object_id=title_opt, description="Open screen terminal: %s" % title_opt) else: ps = nm.ssh().ssh_x11_exec(host, [cls.SCREEN, '-x', screen_name], title_opt, user) rospy.loginfo("Open remote screen terminal: %s", ps)
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 node_manager_fkie.init_settings() masteruri = node_manager_fkie.settings().masteruri() node_manager_fkie.init_globals(masteruri) # Create QWidget try: self._widget = MainWindow() # self._widget.read_view_history() except Exception, e: msgBox = QMessageBox() msgBox.setText(str(e)) msgBox.exec_() raise
def on_load_as_default(self): ''' Tries to load the selected launch file as default configuration. The button is only enabled and this method is called, if the button was enabled by on_launch_selection_clicked() ''' key_mod = QApplication.keyboardModifiers() if (key_mod & Qt.ShiftModifier): self.loadXmlAsDefaultButton.showMenu() else: selected = self._launchItemsFromIndexes(self.xmlFileView.selectionModel().selectedIndexes(), False) for item in selected: path = self.launchlist_model.expandItem(item.name, item.path, item.id) if path is not None: rospy.loginfo("LOAD the launch file as default: %s", path) nm.settings().launch_history_add(path) self.load_as_default_signal.emit(path, None)
def _identifyPath(self, path): ''' Determines the id of the given path @return: the id represents whether it is a file, package or stack @rtype: C{constants of LaunchItem} ''' if path in self.DIR_CACHE: if path in nm.settings().launch_history: if path.endswith('.nmprofile'): return LaunchItem.RECENT_PROFILE return LaunchItem.RECENT_FILE return self.DIR_CACHE[path] if os.path.basename(path)[0] != '.': if path in nm.settings().launch_history: if path.endswith('.nmprofile'): self.DIR_CACHE[path] = LaunchItem.RECENT_PROFILE return LaunchItem.RECENT_PROFILE else: self.DIR_CACHE[path] = LaunchItem.RECENT_FILE return LaunchItem.RECENT_FILE elif os.path.isfile(path): if (path.endswith('.launch')): self.DIR_CACHE[path] = LaunchItem.LAUNCH_FILE return LaunchItem.LAUNCH_FILE elif (path.endswith('.nmprofile')): self.DIR_CACHE[path] = LaunchItem.PROFILE return LaunchItem.PROFILE else: for e in nm.settings().launch_view_file_ext: if path.endswith(e): self.DIR_CACHE[path] = LaunchItem.CFG_FILE return LaunchItem.CFG_FILE elif os.path.isdir(path): fileList = os.listdir(path) if self._containsLaunches(path): if 'stack.xml' in fileList: self.DIR_CACHE[path] = LaunchItem.STACK return LaunchItem.STACK elif is_package(fileList): self.DIR_CACHE[path] = LaunchItem.PACKAGE return LaunchItem.PACKAGE else: self.DIR_CACHE[path] = LaunchItem.FOLDER return LaunchItem.FOLDER self.DIR_CACHE[path] = LaunchItem.NOT_FOUND return LaunchItem.NOT_FOUND
def included_files(cls, text_or_path, regexp_retruns=[], regexp_filelist=[QRegExp("\\btextfile\\b"), QRegExp("\\bfile\\b"), QRegExp("\\bdefault\\b"), QRegExp("\\bvalue=.*pkg:\/\/\\b"), QRegExp("\\bvalue=.*package:\/\/\\b"), QRegExp("\\bvalue=.*\$\(find\\b"), QRegExp("\\bargs=.*\$\(find\\b")], recursive=True, unique=True): ''' :param regexp_retruns: the list with patterns which are returned as result. If empy it's the same as 'regexp_filelist' :param regexp_filelist: the list with all patterns to find include files ''' result = [] lines = [] pwd = '.' f = QFile(text_or_path) if f.exists(): pwd = os.path.dirname(text_or_path) with open(text_or_path, 'r') as f: content = f.read() # remove the comments comment_pattern = QRegExp("<!--.*?-->") pos = comment_pattern.indexIn(content) while pos != -1: content = content[:pos] + content[pos + comment_pattern.matchedLength():] pos = comment_pattern.indexIn(content) lines = content.splitlines() else: lines = [text_or_path] line_index = 0 for line in lines: index = cls._index(line, regexp_filelist) if index > -1: startIndex = line.find('"', index) if startIndex > -1: endIndex = line.find('"', startIndex + 1) fileName = line[startIndex + 1:endIndex] if len(fileName) > 0: try: path = cls.interpretPath(fileName, pwd) if os.path.isfile(path): if not regexp_retruns or cls._index(line, regexp_retruns) > -1: if not unique: result.append((line_index, path)) else: result.append(path) ext = os.path.splitext(path) if recursive and ext[1] in nm.settings().SEARCH_IN_EXT: result += cls.included_files(path, regexp_retruns, regexp_filelist) except Exception: import traceback print traceback.format_exc() line_index += 1 if unique: return list(set(result)) return result
def _getLoadHistory(self): ''' Read the history of the recently loaded files from the file stored in ROS_HOME path. @return: the list with file names @rtype: C{[str]} ''' result = list() historyFile = nm.settings().qsettings(nm.settings().LAUNCH_HISTORY_FILE) size = historyFile.beginReadArray("launch_history") for i in range(size): historyFile.setArrayIndex(i) if i >= nm.settings().launch_history_length: break file = historyFile.value("file") if os.path.isfile(file): result.append(file) historyFile.endArray() return result
def _poweroff_wo(self, host, auto_pw_request=False, user=None, pw=None): if nm.is_local(host): rospy.logwarn("shutdown localhost localhost!") cmd = nm.settings().terminal_cmd(['sudo poweroff'], "poweroff") SupervisedPopen(shlex.split(cmd), object_id="poweroff", description="poweroff") else: rospy.loginfo("poweroff %s", host) # kill on a remote machine cmd = ['sudo poweroff'] _ = nm.ssh().ssh_exec(host, cmd, 'Shutdown %s' % host, user)
def _rosclean_wo(self, host, auto_pw_request=False, user=None, pw=None): if nm.is_local(host): rospy.loginfo("rosclean purge on localhost!") cmd = nm.settings().terminal_cmd(['rosclean purge -y'], "rosclean") SupervisedPopen(shlex.split(cmd), object_id="rosclean", description="rosclean") else: rospy.loginfo("rosclean %s", host) # kill on a remote machine cmd = ['rosclean purge -y'] _ = nm.ssh().ssh_x11_exec(host, cmd, 'rosclean purge on %s' % host, user)
def _poweroff_wo(self, host, auto_pw_request=False, user=None, pw=None): if nm.is_local(host): rospy.logwarn("shutdown localhost localhost!") cmd = nm.settings().terminal_cmd(['sudo poweroff'], "poweroff") SupervisedPopen(shlex.split(cmd), object_id="poweroff", description="poweroff") else: rospy.loginfo("poweroff %s", host) # kill on a remote machine cmd = ['sudo poweroff'] _ = nm.ssh().ssh_x11_exec(host, cmd, 'Shutdown %s' % host, user)
def _add2Cache(self, cache, key, value): uvalue = unicode(value) if key and uvalue: if not cache.has_key(key): cache[key] = [uvalue] elif not uvalue in cache[key]: cache[key].insert(0, uvalue) if len(cache[key]) >= nm.settings().param_history_length: cache[key].pop() else: cache[key].remove(uvalue) cache[key].insert(0, uvalue)
def add2LoadHistory(self, file): try: self.load_history.remove(file) except: pass self.load_history.append(file) try: while len(self.load_history) > nm.settings().launch_history_length: self.load_history.pop(0) except: pass self._storeLoadHistory(self.load_history)
def updateNameView(self, master, quality, item): ''' Updates the representation of the column contains the name state. @param master: the topic data @type master: master_discovery_fkie.TopicInfo @param item: corresponding item in the model @type item: L{TopicItem} ''' tooltip = ''.join(['<html><body>']) tooltip = ''.join([tooltip, '<h4>', master.uri, '</h4>']) tooltip = ''.join([tooltip, '<dl>']) tooltip = ''.join([tooltip, '<dt>', 'IP: ', str(self.master_ip), '</dt>']) if master.online: if not quality is None and quality != -1.: tooltip = ''.join([tooltip, '<dt>', 'Quality: ', str(quality),' %', '</dt>']) else: tooltip = ''.join([tooltip, '<dt>', 'Quality: not available</dt>']) # if item.checkState() == QtCore.Qt.Checked: # tooltip = ''.join([tooltip, '<dt>', 'synchronized', '</dt>']) else: tooltip = ''.join([tooltip, '<dt>', 'offline', '</dt>']) tooltip = ''.join([tooltip, '</dl>']) if item.descr: # tooltip = ''.join([tooltip, '<b><u>Description:</u></b>']) tooltip = ''.join([tooltip, item.descr]) # update the icon if master.online: timediff = abs(self._timediff) > nm.settings().max_timediff if self._master_errors or self.master_ip is None or timediff: item.setIcon(self.ICONS['warning']) if timediff: tooltip = ''.join([tooltip, '<h4>', '<font color="#CC0000">Time difference to the host is about %3.f seconds!</font>'%self._timediff, '</h4>']) item.setIcon(self.ICONS['clock_warn']) if self.master_ip is None: tooltip = ''.join([tooltip, '<h4>', '<font color="#CC0000">Host not reachable by name!!! The ROS topics may not by connected!!!</font>', '</h4>']) if self._master_errors: tooltip = ''.join([tooltip, '<h4>Errors reported by master_discovery:</h4>']) for err in self._master_errors: tooltip = ''.join([tooltip, '<dt><font color="#CC0000">%s</font></dt>'%err]) elif not quality is None and quality != -1.: if quality > 30: item.setIcon(self.ICONS['green']) elif quality > 5: item.setIcon(self.ICONS['yellow']) else: item.setIcon(self.ICONS['red']) else: item.setIcon(self.ICONS['grey']) else: item.setIcon(self.ICONS['disconnected']) tooltip = ''.join([tooltip, '</body></html>']) item.setToolTip(tooltip)
def openLog(cls, nodename, host, user=None): ''' Opens the log file associated with the given node in a new terminal. @param nodename: the name of the node (with name space) @type nodename: C{str} @param host: the host name or ip where the log file are @type host: C{str} @return: C{True}, if a log file was found @rtype: C{bool} @raise Exception: on errors while resolving host @see: L{node_manager_fkie.is_local()} ''' rospy.loginfo("show log for '%s' on '%s'", str(nodename), str(host)) title_opt = 'LOG %s on %s'%(nodename, host) if nm.is_local(host): found = False screenLog = nm.screen().getScreenLogFile(node=nodename) if os.path.isfile(screenLog): cmd = nm.settings().terminal_cmd([nm.settings().log_viewer, screenLog], title_opt) rospy.loginfo("open log: %s", cmd) SupervisedPopen(shlex.split(cmd), id="Open log", description="Open log for '%s' on '%s'"%(str(nodename), str(host))) found = True #open roslog file roslog = nm.screen().getROSLogFile(nodename) if os.path.isfile(roslog): title_opt = title_opt.replace('LOG', 'ROSLOG') cmd = nm.settings().terminal_cmd([nm.settings().log_viewer, roslog], title_opt) rospy.loginfo("open ROS log: %s", cmd) SupervisedPopen(shlex.split(cmd), id="Open log", description="Open log for '%s' on '%s'"%(str(nodename), str(host))) found = True return found else: ps = nm.ssh().ssh_x11_exec(host, [nm.settings().start_remote_script, '--show_screen_log', nodename], title_opt, user) ps = nm.ssh().ssh_x11_exec(host, [nm.settings().start_remote_script, '--show_ros_log', nodename], title_opt.replace('LOG', 'ROSLOG'), user) return False
def _on_question_cancel(self): if self.frameui.checkBox_dnaa.isChecked(): if self.questionid == self.QuestionNodelet: nm.settings().check_for_nodelets_at_start = False else: # save the decision self._do_not_ask[self.questionid] = False self._new_request = False self.frameui.setVisible(False) self.cancel_signal.emit(self.questionid, self.data) self.questionid = 0 self._clear_scroll_area() self._new_request = self._read_next_item() self._frameui_4_request(self._new_request)
def get_profile_file(self): # save the profile (path, _) = QFileDialog.getSaveFileName(self, "New profile file", nm.settings().current_dialog_path, "node manager profile files (*.nmprofile);;All files (*)") # _:=filter if path: if not path.endswith('.nmprofile'): path = "%s.nmprofile" % path nm.settings().current_dialog_path = os.path.dirname(path) try: (pkg, _) = package_name(os.path.dirname(path)) # _:=pkg_path if pkg is None: ret = MessageBox.warning(self, "New File Error", 'The new file is not in a ROS package', buttons=MessageBox.Ok | MessageBox.Cancel) if ret == MessageBox.Cancel: return None return path except EnvironmentError as e: MessageBox.warning(self, "New File Error", 'Error while create a new file', utf8(e)) return None
def ssh_x11_exec(self, host, cmd, title=None, user=None): ''' Executes a command on remote host using a terminal with X11 forwarding. @todo: establish connection using paramiko SSH library. @param host: the host @type host: C{str} @param cmd: the list with command and arguments @type cmd: C{[str,...]} @param title: the title of the new opened terminal, if it is None, no new terminal will be created @type title: C{str} or C{None} @param user: user name @return: the result of C{subprocess.Popen(command)} @see: U{http://docs.python.org/library/subprocess.html?highlight=subproces#subprocess} ''' with self.mutex: try: # workaround: use ssh in a terminal with X11 forward user = nm.settings().host_user(host) if user is None else user if host in self.SSH_AUTH: user = self.SSH_AUTH[host] # generate string for SSH command ssh_str = ' '.join(['/usr/bin/ssh', '-aqtx', '-oClearAllForwardings=yes', '-oConnectTimeout=5', '-oStrictHostKeyChecking=no', '-oVerifyHostKeyDNS=no', '-oCheckHostIP=no', ''.join([user, '@', host])]) if title is not None: cmd_str = nm.settings().terminal_cmd([ssh_str, ' '.join(cmd)], title) else: cmd_str = str(' '.join([ssh_str, ' '.join(cmd)])) rospy.loginfo("REMOTE x11 execute on %s: %s", host, cmd_str) return SupervisedPopen(shlex.split(cmd_str), object_id=str(title), description="REMOTE x11 execute on %s: %s" % (host, cmd_str)) except: raise