def delete_log(cls, nodename, grpc_uri, auto_pw_request=False, user=None, pw=None):
        '''
        Deletes the log file associated with the given node.

        :param  str nodename: the name of the node (with name space)
        :param str grpc_uri: uri of the node manager daemon where to delete log
        :raise Exception: on errors while resolving host
        :see: :meth:`fkie_node_manager.is_local()`
        '''
        try:
            nm.nmd().screen.delete_log(grpc_uri, [nodename])
        except Exception as err:
            rospy.logwarn("delete log using SSH because of error: %s" % utf8(err))
            host = get_hostname(grpc_uri)
            if nm.is_local(host):
                screenLog = screen.get_logfile(node=nodename)
                pidFile = screen.get_pidfile(node=nodename)
                roslog = screen.get_ros_logfile(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.delete_log, {'nodename': nodename, 'grpc_uri': host, 'auto_pw_request': auto_pw_request, 'user': user, 'pw': pw})
Example #2
0
 def closeEvent(self, event):
     '''
     Test the open files for changes and save this if needed.
     '''
     changed = []
     # get the names of all changed files
     for i in range(self.tabWidget.count()):
         w = self.tabWidget.widget(i)
         if w.document().isModified():
             changed.append(self.__getTabName(w.filename))
     if changed:
         # ask the user for save changes
         if self.isHidden():
             buttons = MessageBox.Yes | MessageBox.No
         else:
             buttons = MessageBox.Yes | MessageBox.No | MessageBox.Cancel
         result = MessageBox.question(self, "Unsaved Changes", '\n\n'.join(["Save the file before closing?", '\n'.join(changed)]), buttons=buttons)
         if result == MessageBox.Yes:
             for i in range(self.tabWidget.count()):
                 w = self.tabWidget.widget(i).save()
             self.graph_view.clear_cache()
             event.accept()
         elif result == MessageBox.No:
             event.accept()
         elif rospy.is_shutdown():
             event.ignore()
     else:
         event.accept()
     if event.isAccepted():
         self.storeSetting()
         nm.nmd().file.changed_file.disconnect(self.on_changed_file)
         nm.nmd().file.packages_available.connect(self._on_new_packages)
         self.finished_signal.emit(self.init_filenames)
 def reload_current_path(self, clear_cache=False):
     '''
     Reloads the current path.
     '''
     self.expand_item(self._current_path, PathItem.FOLDER, clear_cache)
     if clear_cache:
         nm.nmd().clear_cache()
Example #4
0
 def clear_cache(self):
     if self._root_path:
         nm.nmd().clear_cache(self._root_path)
     self._created_tree = False
     self.graphTreeView.model().clear()
     crp = self._current_path
     self._current_path = None
     self.set_file(crp, self._root_path, force_rebuild=True)
Example #5
0
 def reload_current_path(self, clear_cache=False):
     '''
     Reloads the current path.
     '''
     self.expand_item(self._current_path, PathItem.FOLDER, clear_cache)
     if clear_cache:
         nm.nmd().clear_cache()
         nm.nmd().launch.reset_package_path_threaded(self._current_path)
Example #6
0
 def set_current_master(self, masteruri, mastername):
     self._current_master = masteruri.rstrip(os.path.sep)
     self._current_master_name = mastername
     if self._is_root(self._current_path):
         nm.nmd().file.list_path_threaded(self._current_path)
         if nmdurl.equal_uri(self._current_path, masteruri_from_master()):
             self._add_path(nmdurl.nmduri(self._current_master),
                            PathItem.REMOTE_DAEMON, 0, 0,
                            get_hostname(self._current_master_name))
Example #7
0
 def kill_screens(cls,
                  node,
                  grpc_url,
                  auto_ok_request=True,
                  user=None,
                  pw=None):
     '''
     Searches for the screen associated with the given node and kill this screens.
     :param str node: the name of the node those screen output to kill
     :param str grpc_url: the url of node manager daemon where the screen is running
     '''
     if node is None or len(node) == 0:
         return False
     try:
         # get the available screens
         screens = nm.nmd().screen.get_screens(grpc_url, node)
         if screens:
             do_kill = True
             if auto_ok_request:
                 from fkie_node_manager.detailed_msg_box import MessageBox
                 result = MessageBox.question(
                     None,
                     "Kill SCREENs?",
                     '\n'.join(list(screens.keys())),
                     buttons=MessageBox.Ok | MessageBox.Cancel)
                 if result == MessageBox.Ok:
                     do_kill = True
             if do_kill:
                 host = get_hostname(grpc_url)
                 for sname, _nname in screens.items():
                     pid, _, _ = sname.partition('.')
                     if pid:
                         try:
                             nm.nmd().monitor.kill_process(
                                 int(pid), grpc_url)
                             # nm.starter()._kill_wo(host, int(pid), auto_ok_request, user, pw)
                         except Exception:
                             import traceback
                             rospy.logwarn(
                                 "Error while kill screen (PID: %s) on host '%s': %s",
                                 utf8(pid), utf8(host),
                                 traceback.format_exc(1))
                 nm.nmd().screen.wipe_screens(grpc_url)
                 # if nm.is_local(host):
                 #     SupervisedPopen([screen.SCREEN, '-wipe'], object_id='screen -wipe', description="screen: clean up the socket with -wipe")
                 # else:
                 #     nm.ssh().ssh_exec(host, [screen.SCREEN, '-wipe'], close_stdin=True, close_stdout=True, close_stderr=True)
     except nm.AuthenticationRequest as e:
         raise nm.InteractionNeededError(
             e, cls.kill_screens, {
                 'node': node,
                 'grpc_url': grpc_url,
                 'auto_ok_request': auto_ok_request,
                 'user': user,
                 'pw': pw
             })
Example #8
0
    def expand_item(self, path, path_id, clear_cache=False):
        '''
        Returns for the given item and path the file path if this is a file. Otherwise the
        folder will be expanded and None will be returned.

        :param str path: the real path of the item
        :param int path_id: the id of the path
        :param bool clear_cache: clear cache before reload
        :return: path of the launch file or None
        :rtype: str
        :raise Exception: if no path to given item was found
        '''
        if path_id in [PathItem.NOTHING]:
            return None
        has_shift_mod = Qt.ShiftModifier & QApplication.keyboardModifiers()
        if path_id in [
                PathItem.LAUNCH_FILE, PathItem.CFG_FILE, PathItem.PROFILE,
                PathItem.FILE, PathItem.RECENT_FILE, PathItem.LAUNCH_FILE
        ]:
            if not has_shift_mod:
                return path
        root = self.invisibleRootItem()
        while root.rowCount():
            root.removeRow(0)
        self.pyqt_workaround.clear()
        if has_shift_mod:
            if path_id in [
                    PathItem.LAUNCH_FILE, PathItem.CFG_FILE, PathItem.PROFILE,
                    PathItem.FILE, PathItem.RECENT_FILE, PathItem.LAUNCH_FILE
            ]:
                self._current_path = os.path.dirname(path)
            else:
                self._current_path = nmdurl.nmduri()
        else:
            if path_id in [PathItem.ROOT]:
                surl, spath = nmdurl.split(path, with_scheme=True)
                if self._is_root(path) or spath in ['', os.path.sep]:
                    self._current_path = nmdurl.nmduri()
                elif self._is_ros_root(path):
                    self._current_path = surl
                else:
                    dir_path = os.path.dirname(spath)
                    self._current_path = nmdurl.join(surl, dir_path)
            elif self._current_path != path:
                self._current_path = path
        self._add_path(self._current_path, PathItem.ROOT, 0, 0, 'loading...')
        nm.nmd().file.list_path_threaded(self._current_path, clear_cache)
        # TODO: add functionality to go deep automatically
        #         else:
        #             key_mod = QApplication.keyboardModifiers()
        #             onestep = False
        #             if key_mod & Qt.ControlModifier:
        #                 onestep = True
        #             root_path, items = self._moveDown(path, onestep)
        #        self._setNewList((root_path, items))
        return None
Example #9
0
 def search_for_node(self, search_text, path, recursive=False, args={}, count=1):
     '''
     Searches for node in this document and all included files.
     :param str search_text: node to find with 'name="' prefix
     :return: the list with all files contain the text
     :rtype: [str, ...]
     '''
     if path and not (path.endswith('.launch') or path.find('.launch.') > 0):
         return
     if not self._isrunning:
         return
     data = self._get_text(path)
     launch_node = self._get_launch_element(data, path)
     if launch_node is None:
         # something goes wrong while parse XML content
         # backup solution to search without resolve arguments
         self.search(search_text, path, recursive, args, count)
     else:
         # read XML content and update the arguments
         rospy.logdebug("search for node '%s' in %s with args: %s, recursive: %s" % (search_text, path, args, recursive))
         resolve_args = dict(args)
         if not resolve_args:
             resolve_args.update(nm.nmd().launch.launch_args(path))
         my_resolved_args = self._resolve_args(launch_node, resolve_args, path)
         # replace arguments and search for node in data
         search_for_name = search_text.replace('name="', '').replace('"', '')
         occur_idx = 0
         for aname, _rname, span in self._next_node_name(data, search_for_name, my_resolved_args, path):
             # found, now test in XML for if and unless statements
             if self._check_node_conditions(launch_node, search_for_name, occur_idx, my_resolved_args, path):
                 self._found += 1
                 self.search_result_signal.emit(search_text, True, path, span[0], span[1], -1, aname)
             else:
                 self.warning_signal.emit("%s in %s ignored because of conditions." % (search_text, path))
             occur_idx += 1
         if self._isrunning and recursive:
             queue = []
             inc_files = nm.nmd().launch.get_included_files(path, False, include_args=args, search_in_ext=['.launch', '.xml'])
             # read first all included files in current file
             for inc_file in inc_files:
                 if not self._isrunning:
                     return
                 if inc_file.exists:
                     queue.append((search_text, inc_file.inc_path, recursive, inc_file.args))
                 elif inc_file.inc_path.endswith('.launch') or inc_file.inc_path.find('.launch.') > 0:
                     rospy.logwarn("skip parsing of not existing included file: %s" % inc_file.inc_path)
             # search in all files
             for search_text, inc_path, recursive, include_args in queue:
                 new_dict = dict(my_resolved_args)
                 new_dict.update(include_args)
                 # skip search in not launch files
                 if inc_path.endswith('.launch') or inc_path.find('.launch.') > 0:
                     self.search_for_node(search_text, inc_path, recursive, new_dict, count + 1)
     if self._path == path and self._found == 0:
         self.warning_signal.emit("not found '%s' in %s (%srecursive)" % (search_text, path, '' if recursive else 'not '))
Example #10
0
 def keyPressEvent(self, event):
     '''
     Enable the mouse tracking by X{setMouseTracking()} if the control key is pressed.
     '''
     if self.isReadOnly():
         if event.key() == Qt.Key_F5:
             nm.nmd().file.get_file_content_threaded(self.filename)
         else:
             event.accept()
             return
     if event.key() == Qt.Key_Control or event.key() == Qt.Key_Shift:
         self.setMouseTracking(True)
     if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_7:
         self.commentText()
     elif event.modifiers(
     ) == Qt.ControlModifier | Qt.ShiftModifier and event.key(
     ) == Qt.Key_Slash:
         self.commentText()
     elif event.modifiers(
     ) == Qt.ControlModifier | Qt.ShiftModifier and event.key() == Qt.Key_F:
         if isinstance(self.hl, XmlHighlighter):
             self.toprettyxml()
         else:
             self.toprettyyaml()
     elif event.modifiers() == Qt.AltModifier and event.key(
     ) == Qt.Key_Space:
         ext = os.path.splitext(self.filename)
         if ext[1] in self.CONTEXT_FILE_EXT:
             menu = self._create_context_substitution_menu(False)
             if menu is None:
                 menu = self._create_context_menu_for_tag()
             if menu:
                 menu.exec_(
                     self.mapToGlobal(self.cursorRect().bottomRight()))
     elif event.key() != Qt.Key_Escape:
         # handle the shifting of the block
         if event.modifiers() == Qt.NoModifier and event.key(
         ) == Qt.Key_Tab:
             self.shiftText()
         elif event.modifiers() == Qt.ShiftModifier and event.key(
         ) == Qt.Key_Backtab:
             self.shiftText(back=True)
         else:
             event.accept()
             if event.key() in [Qt.Key_Enter, Qt.Key_Return]:
                 ident = self.getIdentOfCurretLine()
             QTextEdit.keyPressEvent(self, event)
             if event.key() in [Qt.Key_Enter, Qt.Key_Return]:
                 self.indentCurrentLine(ident - self.getIdentOfCurretLine())
     else:
         QTextEdit.keyPressEvent(self, event)
 def _rosclean_wo(self, grpc_uri, auto_pw_request=False, user=None, pw=None):
     try:
         nm.nmd().screen.rosclean(grpc_uri)
     except Exception as err:
         host = get_hostname(grpc_uri)
         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.logwarn("use SSH to run 'rosclean' because of error: %s" % utf8(err))
             # kill on a remote machine
             cmd = ['rosclean purge -y']
             _ = nm.ssh().ssh_x11_exec(host, cmd, 'rosclean purge on %s' % host, user)
    def transfer_file_nmd(cls, grpc_url, path, auto_pw_request=False, user=None, pw=None):
        '''
        Copies the given file to the remote host. Uses caching of remote paths.

        :param str grpc_url: destination grpc server
        :param str path: file to transfer
        '''
        try:
            nm.nmd().file.copy(path, grpc_url)
        except Exception as err:
            host = get_hostname(grpc_url)
            _uri, path = nmdurl.split(path)
            rospy.logwarn("use SSH to transfer file '%s' to '%s', because of error: %s" % (path, host, utf8(err)))
            cls.transfer_files(host, path, auto_pw_request, user, pw)
 def paste_from_clipboard(self):
     '''
     Copy the file or folder to new position...
     '''
     if QApplication.clipboard().mimeData().hasText(
     ) and self._current_path:
         text = QApplication.clipboard().mimeData().text()
         if self.current_path and text.startswith('grpc://'):
             basename = os.path.basename(text)
             dest_path = os.path.join(self._current_path, basename)
             try:
                 nm.nmd().file.copy(text, dest_path)
                 self.reload_current_path(clear_cache=True)
             except Exception:
                 import traceback
                 print(traceback.format_exc())
Example #14
0
 def find_default_args(self, path, inc_args):
     '''
     Searches for args with default value not overwritten by including file.
     :param str path: file content or a launch file path
     :param dict(str,str) inc_args: a dictionary with arguments set while include the given path.
     :return: a dictinary with default arguments not overwriting while include.
     :rtype: dict(str: str)
     '''
     not_set_args = {}
     if path and not (path.endswith('.launch') or path.find('.launch.') > 0):
         return not_set_args
     if rospy.is_shutdown():
         return not_set_args
     try:
         # get file content
         _, _, data = nm.nmd().file.get_file_content(path)
         launch_node = None
         # create xml node
         xml_nodes = minidom.parseString(data.encode('utf-8')).getElementsByTagName('launch')
         if xml_nodes:
             launch_node = xml_nodes[-1]
         if launch_node is not None:
             # read XML content and get default arguments
             default_args = get_internal_args(data, only_default=True)
             for arg_in_file, arg_value in default_args.items():
                 if arg_in_file not in inc_args:
                     not_set_args[arg_in_file] = arg_value
     except Exception as err:
         msg = "can't get default arguments for %s: %s" % (path, utf8(err))
         self.error.emit(msg)
         rospy.logwarn(msg)
     return not_set_args
Example #15
0
 def run(self):
     '''
     '''
     try:
         self.info_signal.emit("build tree: start for %s" % self.root_path, False)
         result = []
         filelist = nm.nmd().launch.get_included_files(self.root_path, recursive=True, search_in_ext=nm.settings().SEARCH_IN_EXT)
         for inc_file in filelist:
             rospy.logdebug("build tree: append file: %s" % inc_file)
             inc_file.unset_default_args = self.find_default_args(inc_file.inc_path, inc_file.args)
             result.append(inc_file)
             if not inc_file.exists:
                 self.info_signal.emit("build tree: skip parse %s, not exist" % inc_file.inc_path, True)
         self.graph.emit(result)
     except exceptions.GrpcTimeout as tout:
         rospy.logwarn("Build launch tree failed! Daemon not responded within %.2f seconds while"
                       " get configuration file: %s\nYou can try to increase"
                       " the timeout for GRPC requests in node manager settings." % (nm.settings().timeout_grpc, tout.remote))
         self.error.emit('failed: timeout')
     except Exception:
         import traceback
         # print("Error while parse launch file for includes:\n\t%s" % traceback.format_exc())
         formatted_lines = traceback.format_exc(1).splitlines()
         try:
             rospy.logwarn("Error while parse launch file for includes:\n\t%s", formatted_lines[-5])
         except Exception:
             pass
         self.error.emit('failed: %s' % formatted_lines[-1])
Example #16
0
def package_name(path):
    '''
    Returns for given directory a tuple of package name and package path or None values.
    The results are cached!

    :rtype: tuple(name, path)
    '''
    return nm.nmd().file.package_name(path)
Example #17
0
 def on_error_on_path(self, gpath):
     if gpath == self._current_search or gpath == self.launchlist_model.current_path:
         self.ui_search_line.set_process_active(False)
     if self.launchlist_model.is_in_root:
         self._reload_timer = threading.Timer(
             2.,
             nm.nmd().file.list_path_threaded)
         self._reload_timer.start()
Example #18
0
    def __init__(self, filename, parent=None):
        self.parent = parent
        QTextEdit.__init__(self, parent)
        self.setObjectName('Editor - %s' % filename)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_custom_context_menu)
#        self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.setAcceptRichText(False)
        font = QFont()
        font.setFamily("Fixed".decode("utf-8"))
        font.setPointSize(12)
        self.setFont(font)
        self.setLineWrapMode(QTextEdit.NoWrap)
        self.setTabStopWidth(25)
        self.setAcceptRichText(False)
        self.setCursorWidth(2)
        self.setFontFamily("courier new")
        self.setProperty("backgroundVisible", True)
        bg_style = "QTextEdit { background-color: #fffffc;}"
        self.setStyleSheet("%s" % (bg_style))
        self.setTextColor(QColor(0, 0, 0))
        self.regexp_list = [QRegExp("\\binclude\\b"), QRegExp("\\btextfile\\b"),
                            QRegExp("\\bfile\\b"), QRegExp("\\bvalue=.*pkg:\/\/\\b"),
                            QRegExp("\\bvalue=.*package:\/\/\\b"),
                            QRegExp("\\bvalue=.*\$\(find\\b"),
                            QRegExp("\\bargs=.*\$\(find\\b"),
                            QRegExp("\\bdefault=.*\$\(find\\b")]
        self.filename = filename
        self.file_mtime = 0
#             f = QFile(filename)
#             if f.open(QIODevice.ReadOnly | QIODevice.Text):
#                 self.file_info = QFileInfo(filename)
#                 self.setText(unicode(f.readAll(), "utf-8"))

        self.path = '.'
        # enables drop events
        self.setAcceptDrops(True)
        # variables for threaded search
        self._search_thread = None
        self._stop = False
        self._internal_args = {}
        ext = os.path.splitext(filename)
        if self.filename:
            self.setText("")
            _, self.file_mtime, file_content = nm.nmd().file.get_file_content(filename)
            if ext[1] in ['.launch', '.xml']:
                self._internal_args = get_internal_args(file_content)
            self.setText(file_content)
        self._is_launchfile = False
        if ext[1] in ['.launch', '.xml', '.xacro', '.srdf', '.urdf']:
            if ext[1] in ['.launch']:
                self._is_launchfile = True
            self.hl = XmlHighlighter(self.document(), is_launch=False)
            self.cursorPositionChanged.connect(self._document_position_changed)
        else:
            self.hl = YamlHighlighter(self.document())
Example #19
0
 def search(self, search_text, path, recursive=False, args={}, count=1):
     '''
     Searches for given text in this document and all included files.
     :param str search_text: text to find
     :return: the list with all files contain the text
     :rtype: [str, ...]
     '''
     if not self._isrunning:
         return
     data = self._get_text(path)
     pos = data.find(search_text)
     slen = len(search_text)
     while pos != -1 and self._isrunning:
         if self._isrunning:
             doemit = True
             line = self._strip_text(data, pos)
             if self._only_launch:
                 doemit = path.endswith(
                     '.launch') or path.find('.launch.') > 0
             if doemit:
                 self._found += 1
                 self.search_result_signal.emit(
                     search_text, True, path, pos, pos + len(search_text),
                     data.count('\n', 0, pos) + 1, line)
         if self._count_results > 0 and self._count_results < self._found:
             # break search if found the requested count of occurrences
             return
         pos += slen
         pos = data.find(search_text, pos)
     if self._isrunning:
         if recursive:
             queue = []
             inc_files = nm.nmd().launch.get_included_files(
                 path, False, include_args=args)
             # read first all included files in current file
             for inc_file in inc_files:
                 if not self._isrunning:
                     return
                 if inc_file.exists:
                     queue.append((search_text, inc_file.inc_path,
                                   recursive, inc_file.args))
             # search in all files
             for search_text, inc_path, recursive, include_args in queue:
                 new_dict = dict(args)
                 new_dict.update(include_args)
                 # test search string for 'name=' and skip search in not launch files
                 if self._only_launch or inc_path.endswith(
                         '.launch') or path.find('.launch.') > 0:
                     self.search(search_text, inc_path, recursive, new_dict,
                                 count + 1)
     if self._path == path and self._found == 0:
         self.warning_signal.emit(
             "not found '%s' in %s (%srecursive)" %
             (search_text, path, '' if recursive else 'not '))
Example #20
0
 def _refill_tree(self, tree, create_tree=True):
     deep = 0
     file_dsrc = self._root_path
     try:
         file_dsrc = os.path.basename(self._root_path)
     except Exception:
         pass
     self.setWindowTitle("Include Graph - %s" % file_dsrc)
     if not self._created_tree and create_tree:
         has_none_packages = False
         self.graphTreeView.model().clear()
         pkg, _ = package_name(os.path.dirname(self._root_path))
         if pkg is None:
             has_none_packages = True
         itemstr = '%s [%s]' % (os.path.basename(self._root_path), pkg)
         inc_item = QStandardItem('%s' % itemstr)
         inc_item.setData(self.ITEM_TYPE_INC_FILE, self.ITEM_TYPE)
         inc_item.setData(self._root_path, self.DATA_FILE)
         inc_item.setData(-1, self.DATA_LINE)
         inc_item.setData(self._root_path, self.DATA_INC_FILE)
         inc_item.setData(deep, self.DATA_LEVEL)
         # add included arguments for root file
         launch_args = nm.nmd().launch.launch_args(self._root_path)
         if launch_args:
             arg_item = QStandardItem('arguments')
             arg_item.setData(self.ITEM_TYPE_INC_GROUP_ARG, self.ITEM_TYPE)
             for da_name, da_value in launch_args.items():
                 da_item = QStandardItem('<arg>%s: %s' % (da_name, da_value))
                 da_item.setData(self.ITEM_TYPE_INC_ARG, self.ITEM_TYPE)
                 da_item.setData(self._root_path, self.DATA_FILE)
                 da_item.setData(da_name, self.DATA_ARG_NAME)
                 arg_item.appendRow(da_item)
             inc_item.appendRow(arg_item)
         self._append_items(inc_item, deep, tree)
         self.graphTreeView.model().appendRow(inc_item)
         # self.graphTreeView.expand(self.graphTreeView.model().indexFromItem(inc_item))
         self._created_tree = True
         self.has_none_packages = has_none_packages
     items = self.graphTreeView.model().match(self.graphTreeView.model().index(0, 0), self.DATA_INC_FILE, self._current_path, 10, Qt.MatchRecursive)
     first = True
     self.graphTreeView.selectionModel().clear()
     for item in items:
         if first:
             self._current_deep = item.data(self.DATA_LEVEL)
             first = False
         self.graphTreeView.selectionModel().select(item, QItemSelectionModel.Select)
     self.graphTreeView.expandAll()
     # collapse argument nodes
     proxy = self.graphTreeView.model()
     for row in range(proxy.rowCount()):
         index = proxy.index(row, 0)
         item = proxy.itemFromIndex(index)
         self._collapse_args(item)
     self.finished_signal.emit()
Example #21
0
 def _get_text(self, path):
     result = ''
     try:
         result = self._path_text[path]
     except KeyError:
         try:
             _, _, data = nm.nmd().file.get_file_content(path)
             result = utf8(data)
         except Exception as err:
             rospy.logwarn("can't get content: %s" % (utf8(err)))
     return result
Example #22
0
 def run(self):
     '''
     '''
     if self._grpc_url:
         try:
             self._result = nm.nmd().file.get_package_binaries(
                 self._package, nmdurl.nmduri(self._grpc_url))
             if not self._canceled:
                 self.binaries_signal.emit(self._package, self._result)
         except Exception:
             import traceback
             print(traceback.format_exc())
 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))
Example #24
0
 def __init__(self, parent=None, progress_queue=None, viewobj=None):
     '''
     Creates a new list model.
     '''
     QStandardItemModel.__init__(self, parent)
     self.viewobj = viewobj
     self.setColumnCount(len(LaunchListModel.header))
     self.setHorizontalHeaderLabels(
         [label for label, _width in LaunchListModel.header])
     self.pyqt_workaround = dict(
     )  # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass
     self.items = []
     self._roots = {}
     self._current_path = nmdurl.nmduri()
     self._current_master = masteruri_from_master()
     self._current_master_name = ''
     self.ros_root_paths = {}  # {url: [root pasth(str)]}
     self.ros_root_paths[self._current_path] = [
         os.path.normpath(p)
         for p in os.getenv("ROS_PACKAGE_PATH").split(':')
     ]
     self._progress_queue = progress_queue
     nm.nmd().file.listed_path.connect(self._listed_path)
     nm.nmd().file.packages_available.connect(self._on_new_packages)
     nm.nmd().file.error.connect(self._nmd_error)
Example #25
0
 def paste_from_clipboard(self):
     '''
     Copy the file or folder to new position...
     '''
     if QApplication.clipboard().mimeData().hasText(
     ) and self._current_path:
         text = QApplication.clipboard().mimeData().text()
         if self.current_path and text.startswith('grpc://'):
             basename = os.path.basename(text)
             dest_path = os.path.join(self._current_path, basename)
             try:
                 if text == dest_path:
                     dest_path = self._autorename(dest_path)
                     rospy.logdebug("Autorename destination from %s to %s" %
                                    (text, dest_path))
                 rospy.logdebug("Copy %s to %s" % (text, dest_path))
                 nm.nmd().file.copy(text, dest_path)
                 self.reload_current_path(clear_cache=True)
             except Exception as err:
                 MessageBox.warning(None, "Copy failed",
                                    "Copy failed: %s" % utf8(err))
                 import traceback
                 print(traceback.format_exc())
Example #26
0
def resolve_pkg(pkg, grpc_url):
    '''
    splits pkg url (pkg://package/launch) into package and launch file part and replace package by path.

    :rtype: str
    '''
    if pkg.startswith('pkg://'):
        url = pkg.replace('pkg://', '')
        splits = url.split(os.path.sep, 1)
        if len(splits) == 2:
            packages = nm.nmd().file.get_packages(grpc_url)
            for path, pkgname in packages.items():
                if pkgname == splits[0]:
                    return os.path.join(path, splits[1])
    raise Exception('invalid package url to split: %s' % pkg)
    def save(self, force=False):
        '''
        Saves changes to the file.

        :return: saved, errors, msg
        :rtype: bool, bool, str
        '''
        if self.isReadOnly():
            return False, True, "Cannot save, the content was not loaded properly!"
        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, utf8(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:
                    return False, True, utf8(ioe)
            except Exception as e:
                print(traceback.format_exc())
                return False, True, utf8(e)
        return False, False, ''
Example #28
0
 def show_packages(self, pattern):
     try:
         root = self.invisibleRootItem()
         while root.rowCount():
             root.removeRow(0)
         self.pyqt_workaround.clear()
         items = []
         currurl = self.current_grpc
         for url, packages in nm.nmd().file.get_packages().items():
             if url == currurl:
                 for path, name in packages.items():
                     if pattern in name:
                         items.append((path, PathItem.PACKAGE, 0, 0, name))
         self._set_new_list(self._current_path, items, add_history=False)
     except Exception:
         import traceback
         print(traceback.format_exc(2))
Example #29
0
    def __init__(self, filename, parent=None):
        self.parent = parent
        QTextEdit.__init__(self, parent)
        self.setObjectName('Editor - %s' % filename)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_custom_context_menu)
        #        self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.setAcceptRichText(False)
        font = QFont()
        font.setFamily('Fixed')
        font.setPointSize(12)
        self.setFont(font)
        self.setLineWrapMode(QTextEdit.NoWrap)
        self.setTabStopWidth(25)
        self.setAcceptRichText(False)
        self.setCursorWidth(2)
        self.setFontFamily("courier new")
        self.setProperty("backgroundVisible", True)
        bg_style = "QTextEdit { background-color: #fffffc;}"
        self.setStyleSheet("%s" % (bg_style))
        self.setTextColor(QColor(0, 0, 0))
        self.regexp_list = [
            QRegExp("\\binclude\\b"),
            QRegExp("\\btextfile\\b"),
            QRegExp("\\bfile\\b"),
            QRegExp("\\bvalue=.*pkg:\/\/\\b"),
            QRegExp("\\bvalue=.*package:\/\/\\b"),
            QRegExp("\\bvalue=.*\$\(find\\b"),
            QRegExp("\\bargs=.*\$\(find\\b"),
            QRegExp("\\bdefault=.*\$\(find\\b")
        ]
        self.filename = filename
        self.file_mtime = 0
        #             f = QFile(filename)
        #             if f.open(QIODevice.ReadOnly | QIODevice.Text):
        #                 self.file_info = QFileInfo(filename)
        #                 self.setText(unicode(f.readAll(), "utf-8"))

        self.path = '.'
        # variables for threaded search
        self._search_thread = None
        self._stop = False
        self._internal_args = {}
        self._ext = os.path.splitext(filename)[1]
        self.setText("Loading file content ... press F5 to reload!")
        self.setReadOnly(True)
        self._to_select = []
        nm.nmd().file.file_content.connect(self._apply_file_content)
        nm.nmd().file.error.connect(self._on_nmd_error)
        if self.filename:
            nm.nmd().file.get_file_content_threaded(filename)
Example #30
0
 def setData(self, value, role=Qt.EditRole):
     if role == Qt.EditRole:
         # rename the file or folder
         if (self.name != value or self._isnew) and self.id in [
                 self.RECENT_FILE, self.LAUNCH_FILE, self.RECENT_PROFILE,
                 self.PROFILE, self.CFG_FILE, self.FOLDER
         ]:
             if self.name != value:
                 # some sanity checks
                 if self.model()._exists(value):
                     result = MessageBox.question(
                         self.model().viewobj,
                         "File exists",
                         "File '%s' exists. Override?" % value,
                         buttons=MessageBox.Yes | MessageBox.No)
                     if result == MessageBox.No:
                         return QStandardItem.setData(self, value, role)
                 if self.id not in [self.FOLDER]:
                     _filename, file_extension = os.path.splitext(value)
                     if file_extension not in nm.settings(
                     ).launch_view_file_ext:
                         result = MessageBox.question(
                             self.model().viewobj,
                             "Unknown extension",
                             "New name has unknown extension '%s'. Rename anyway?"
                             % file_extension,
                             buttons=MessageBox.Yes | MessageBox.No)
                         if result == MessageBox.No:
                             return QStandardItem.setData(self, value, role)
             new_path = os.path.join(os.path.dirname(self.path), value)
             try:
                 # save a new file or rename existing file?
                 content = b''
                 new_id = self._identify_path_on_ext(new_path, self.id)
                 if self._isnew:
                     if new_id in [self.FOLDER]:
                         nm.nmd().file.new(new_path, 1)
                     elif new_id in [self.LAUNCH_FILE]:
                         content = (
                             b'<launch>\n'
                             b'    <arg name="robot_ns" default="my_robot"/>\n'
                             b'    <group ns="$(arg robot_ns)">\n'
                             b'        <node pkg="my_pkg" type="my_node" name="my_name" >\n'
                             b'            <param name="capability_group" value="MY_GROUP"/>\n'
                             b'        </node>\n'
                             b'    </group>\n'
                             b'</launch>\n')
                         nm.nmd().file.save_file(new_path, content, 0)
                     else:
                         nm.nmd().file.new(new_path, 0)
                     self._isnew = False
                 else:
                     nm.nmd().file.rename(self.path, new_path)
                 # check for new file extension
                 if new_id != self.id:
                     self.id = new_id
                     self._update_icon()
                 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
             except Exception as err:
                 import traceback
                 rospy.logwarn("Error while save new file: %s" %
                               traceback.format_exc())
                 MessageBox.warning(None, "Rename failed", utf8(err))
     return QStandardItem.setData(self, value, role)