Beispiel #1
0
 def __init__(self, ros: Ros, parent=None):
     super(TopicGraphWidget, self).__init__(parent)
     self.ros_client = ros
     layout = QVBoxLayout()
     self._widget = QWidget()
     self._scene = QGraphicsScene()
     self._scene.setBackgroundBrush(Qt.white)
     self._graphics_view = InteractiveGraphicsView(self._widget)
     self._graphics_view.setScene(self._scene)
     self._graphics_view.setRenderHints(QPainter.Antialiasing
                                        | QPainter.HighQualityAntialiasing
                                        | QPainter.SmoothPixmapTransform
                                        | QPainter.TextAntialiasing)
     self._graphics_view.setResizeAnchor(QGraphicsView.AnchorViewCenter)
     layout.addWidget(self._graphics_view)
     self._refresh_button = QPushButton('加载数据')
     self._refresh_button.setFixedWidth(100)
     self._refresh_button.clicked.connect(self._draw_graph_view)
     btn_layout = QHBoxLayout()
     btn_layout.addWidget(self._refresh_button)
     layout.addLayout(btn_layout)
     self.setLayout(layout)
     self._current_dotcode = None
     self.dot_to_qt = DotToQtGenerator()
     self.dotcode_factory = PydotFactory()
     self.dotcode_generator = RosGraphDotcodeGenerator(self.ros_client)
     self._graph = graph.Graph(self.ros_client)
     self._graph.set_master_stale(5.0)
     self._graph.set_node_stale(5.0)
Beispiel #2
0
    def _render_dotgraph(self, dotgraph):
        """
        Render the specified dotgraph on canvas

        :type dotgraph: pydot.Dot
        """

        # Only redraw when the graph differs from the previous one
        if self._prev_dotgraph == dotgraph:
            return
        else:
            self._prev_dotgraph = dotgraph

        self._scene.clear()

        if self._widget.highlight_connections_check_box.isChecked():
            highlight_level = 3
        else:
            highlight_level = 1

        # Generate qt items from dotcode
        dotcode = PydotFactory().create_dot(dotgraph)
        nodes, edges = DotToQtGenerator().dotcode_to_qt_items(
            dotcode, highlight_level, same_label_siblings=False)

        # Add generated items to scene
        for node_item in nodes:
            self._scene.addItem(nodes.get(node_item))
        for edge_items in edges:
            for edge_item in edges.get(edge_items):
                edge_item.add_to_scene(self._scene)

        self._scene.setSceneRect(self._scene.itemsBoundingRect())
    def test_simple_integration(self):
        if DotToQtGeneratorTest._Q_APP is None:
            raise unittest.case.SkipTest

        (nodes, edges) = DotToQtGenerator().dotcode_to_qt_items(
            DotToQtGeneratorTest.DOT_CODE, 1)
        self.assertEqual(3, len(nodes))  # cluster_foo, foo and bar
        self.assertEqual(1, len(edges))  # foo -> bar
Beispiel #4
0
    def __init__(self, context):
        super(RosTfTree, self).__init__(context)
        self.initialized = False

        self.setObjectName('RosTfTree')

        self._current_dotcode = None

        self._widget = QWidget()

        # factory builds generic dotcode items
        self.dotcode_factory = PydotFactory()
        # self.dotcode_factory = PygraphvizFactory()
        # generator builds rosgraph
        self.dotcode_generator = RosTfTreeDotcodeGenerator()
        self.tf2_buffer_ = tf2_ros.Buffer()
        self.tf2_listener_ = tf2_ros.TransformListener(self.tf2_buffer_)

        # dot_to_qt transforms into Qt elements using dot layout
        self.dot_to_qt = DotToQtGenerator()

        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_tf_tree'), 'resource', 'RosTfTree.ui')
        loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('RosTfTreeUi')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))

        self._scene = QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh'))
        self._widget.refresh_graph_push_button.pressed.connect(self._update_tf_graph)

        self._widget.highlight_connections_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original'))
        self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view)

        self._widget.load_dot_push_button.setIcon(QIcon.fromTheme('document-open'))
        self._widget.load_dot_push_button.pressed.connect(self._load_dot)
        self._widget.save_dot_push_button.setIcon(QIcon.fromTheme('document-save-as'))
        self._widget.save_dot_push_button.pressed.connect(self._save_dot)
        self._widget.save_as_svg_push_button.setIcon(QIcon.fromTheme('document-save-as'))
        self._widget.save_as_svg_push_button.pressed.connect(self._save_svg)
        self._widget.save_as_image_push_button.setIcon(QIcon.fromTheme('image-x-generic'))
        self._widget.save_as_image_push_button.pressed.connect(self._save_image)

        self._deferred_fit_in_view.connect(self._fit_in_view,
                                           Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()

        context.add_widget(self._widget)

        self._force_refresh = False
Beispiel #5
0
 def __init__(self):
     #Init the base class
     QtGui.QGraphicsScene.__init__(self)
     
     # dot_to_qt transforms into Qt elements using dot layout
     self._dot_to_qt = DotToQtGenerator()
     #The pydotfactory
     self._dot_factory = PydotFactory()
     self._graph = None      
     pass
Beispiel #6
0
    def __init__(self, context):
        self._context=context
        super(ConductorGraph, self).__init__(context)
        self.initialised=False
        self.setObjectName('Conductor Graph')
        self._current_dotcode=None
        self._node_items=None
        self._edge_items=None
        self._node_item_events={}
        self._edge_item_events={}
        self._client_info_list={}
        self._widget=QWidget()
        self.cur_selected_client_name = ""
        self.pre_selected_client_name = ""
            
        # factory builds generic dotcode items
        self.dotcode_factory=PydotFactory()
        # self.dotcode_factory=PygraphvizFactory()
        self.dotcode_generator=RosGraphDotcodeGenerator()
        self.dot_to_qt=DotToQtGenerator()
        
        self._graph=ConductorGraphInfo()
        self._graph._reg_event_callback(self._update_client_list)
        self._graph._reg_period_callback(self._set_network_statisics)
        
        rospack=rospkg.RosPack()
        ui_file=os.path.join(rospack.get_path('concert_conductor_graph'), 'ui', 'conductor_graph.ui')
        loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('ConductorGraphUi')

        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))

        self._scene=QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        #self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh'))
        self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('window-new'))
        self._widget.refresh_graph_push_button.pressed.connect(self._update_conductor_graph)

        self._widget.highlight_connections_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original'))
        self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view)

        self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()
        
        self._widget.tabWidget.currentChanged.connect(self._change_client_tab)
        self._client_list_update_signal.connect(self._update_conductor_graph)
        
        #rospy.Subscriber(concert_msgs.Strings.CONCERT_CLIENT_CHANGES, ConcertClients, self._update_client_list)
        
        context.add_widget(self._widget)
Beispiel #7
0
    def __init__(self, context):
        self._context = context
        super(ConductorGraph, self).__init__(context)
        self.initialised = False
        self.setObjectName('Conductor Graph')
        self._node_items = None
        self._edge_items = None
        self._node_item_events = {}
        self._edge_item_events = {}
        self._client_info_list = {}
        self._widget = QWidget()
        self.cur_selected_client_name = ""
        self.pre_selected_client_name = ""
        # factory builds generic dotcode items
        self.dotcode_factory = PydotFactory()
        # self.dotcode_factory=PygraphvizFactory()
        self.dotcode_generator = ConductorGraphDotcodeGenerator()
        self.dot_to_qt = DotToQtGenerator()

        self._graph = ConductorGraphInfo(self._update_conductor_graph_relay,
                                         self._set_network_statisics)

        rospack = rospkg.RosPack()
        ui_file = os.path.join(rospack.get_path('concert_conductor_graph'),
                               'ui', 'conductor_graph.ui')
        loadUi(ui_file, self._widget,
               {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('ConductorGraphUi')

        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' (%d)' % context.serial_number()))

        self._scene = QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        self._widget.highlight_connections_check_box.toggled.connect(
            self._redraw_graph_view)
        self._widget.auto_fit_graph_check_box.toggled.connect(
            self._redraw_graph_view)
        self._widget.clusters_check_box.toggled.connect(
            self._redraw_graph_view)

        self.signal_deferred_fit_in_view.connect(self._fit_in_view,
                                                 Qt.QueuedConnection)
        self.signal_deferred_fit_in_view.emit()

        self._widget.tabWidget.currentChanged.connect(self._change_client_tab)
        self.signal_update_conductor_graph.connect(
            self._update_conductor_graph)

        context.add_widget(self._widget)
Beispiel #8
0
    def __init__(self, context):
        super(Ros2KnowledgeGraph, self).__init__(context)

        self._node = context.node
        self._logger = self._node.get_logger().get_child(
            'ros2_knowledge_graph_viewer.ros2_knowledge_graph.Ros2KnowledgeGraph'
        )
        self.setObjectName('Ros2KnowledgeGraph')

        self._ros2_knowledge_graph = Ros2KnowledgeGraphImpl()
        self._current_dotcode = None

        self._widget = QWidget()

        self.dotcode_factory = PydotFactory()
        self.dotcode_generator = Ros2KnowledgeGraphDotcodeGenerator()
        self.dot_to_qt = DotToQtGenerator()

        _, package_path = get_resource('packages',
                                       'ros2_knowledge_graph_viewer')
        ui_file = os.path.join(package_path, 'share',
                               'ros2_knowledge_graph_viewer', 'resource',
                               'Ros2KnowledgeGraph.ui')
        loadUi(ui_file, self._widget,
               {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('Ros2KnowledgeGraphUi')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' (%d)' % context.serial_number()))

        self._scene = QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        self._widget.save_as_svg_push_button.setIcon(
            QIcon.fromTheme('document-save-as'))
        self._widget.save_as_svg_push_button.pressed.connect(self._save_svg)
        self._widget.save_as_image_push_button.setIcon(
            QIcon.fromTheme('image'))
        self._widget.save_as_image_push_button.pressed.connect(
            self._save_image)

        self._update_ros2_knowledge_graph()
        self._deferred_fit_in_view.connect(self._fit_in_view,
                                           Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()

        context.add_widget(self._widget)

        self._updateTimer = QtCore.QTimer()
        self._updateTimer.timeout.connect(self.do_update)
        self._updateTimer.start(10)
Beispiel #9
0
    def test_label_sizes(self):
        (nodes, edges) = DotToQtGenerator().dotcode_to_qt_items(DotToQtGeneratorTest.DOT_CODE, 1)

        self.longMessage = True
        for name, node in nodes.items():
            shape_rect = node._graphics_item.sceneBoundingRect()
            label_rect = node._label.sceneBoundingRect()
            self.assertLess(
                    label_rect.width(),
                    shape_rect.width(),
                    'Label text for "%s" is wider than surrounding shape.' % name)
            self.assertLess(
                    label_rect.height(),
                    shape_rect.height(),
                    'Label text for "%s" is higher than surrounding shape.' % name)
    def test_label_sizes(self):
        if DotToQtGeneratorTest._Q_APP is None:
            raise unittest.case.SkipTest

        (nodes, edges) = DotToQtGenerator().dotcode_to_qt_items(
            DotToQtGeneratorTest.DOT_CODE, 1)

        self.longMessage = True
        for name, node in nodes.items():
            shape_rect = node._graphics_item.sceneBoundingRect()
            label_rect = node._label.sceneBoundingRect()
            self.assertLess(
                label_rect.width(), shape_rect.width(),
                "Label text for '%s' is wider than surrounding shape." % name)
            self.assertLess(
                label_rect.height(), shape_rect.height(),
                "Label text for '%s' is higher than surrounding shape." % name)
    def __init__(self, context):
        super(CapabilityGraph, self).__init__(context)
        self.setObjectName('CapabilityGraph')

        self.__current_dotcode = None

        self.__running_providers = []
        self.__spec_index = None

        self.__widget = QWidget()

        self.__dot_to_qt = DotToQtGenerator()

        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_capabilities'), 'resources',
                               'CapabilityGraph.ui')
        loadUi(
            ui_file, self.__widget, {
                'CapabilitiesInteractiveGraphicsView':
                CapabilitiesInteractiveGraphicsView
            })
        self.__widget.setObjectName('CapabilityGraphUI')
        if context.serial_number() > 1:
            self.__widget.setWindowTitle(self.__widget.windowTitle() +
                                         (' (%d)' % context.serial_number()))

        self.__scene = QGraphicsScene()
        self.__scene.setBackgroundBrush(Qt.white)
        self.__widget.graphics_view.setScene(self.__scene)

        self.__widget.refresh_graph_push_button.setIcon(
            QIcon.fromTheme('view-refresh'))
        self.__widget.refresh_graph_push_button.pressed.connect(
            self.__refresh_view)

        self.__refresh_view()
        self.__deferred_fit_in_view.connect(self.__fit_in_view,
                                            Qt.QueuedConnection)
        self.__deferred_fit_in_view.emit()
        self.__redraw_graph.connect(self.__update_capabilities_graph)

        # TODO: use user provided server node name
        rospy.Subscriber('/capability_server/events', CapabilityEvent,
                         self.__handle_event)

        context.add_widget(self.__widget)
Beispiel #12
0
    def __init__(self, dotFile, maxDistance):
        """
        * dotfile -- the path to the dot file to load
        * maxDistance -- the maximum distance from the node to allow

        """
        QtGui.QWidget.__init__(self)
        self.__dotFile = dotFile
        self.__maxDistance = maxDistance

        # Load the graph from the dot file
        self.__graph = DotFileGraph(dotFile)
        self.__dotcode = None

        # Create a layout for the widget
        self.__layout = QtGui.QVBoxLayout()
        self.setLayout(self.__layout)

        # Create the graphics scene and view to display the graph
        self.__scene = QtGui.QGraphicsScene()
        self.__scene.setBackgroundBrush(Qt.white)
        self.__view = QtGui.QGraphicsView()
        self.__view.setScene(self.__scene)
        self.__layout.addWidget(self.__view)

        # Create a slider to change the parent depth
        self.__aboveSlider, self.__aboveLabel = self.__createDistanceSlider(
            "Distance above", self.__graph.getAboveDistance(),
            self.__onAboveDistance)

        # Create a slider to change the child depth
        self.__belowSlider, self.__belowLabel = self.__createDistanceSlider(
            "Distance below", self.__graph.getBelowDistance(),
            self.__onBelowDistance)

        # Create a list to view all nodes
        self.__createNodeListWidget()

        # Generates QT widgets from dot code
        self.__dotToQt = DotToQtGenerator()

        # Do the initial display of the graph
        self.updateGraph()

        self.setGeometry(0, 0, 1000, 600)
Beispiel #13
0
    def __init__(self):
        super(BTWidget, self).__init__()

        self.setObjectName('BTWidget')

        self._graph = None
        self._current_dotcode = None
        self._initialized = False

        # dot_to_qt transforms into Qt elements using dot layout
        self.dot_to_qt = DotToQtGenerator()

        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_bt'), 'resource', 'rqt_bt.ui')
        loadUi(ui_file, self,
               {'InteractiveGraphicsView': InteractiveGraphicsView})

        self.refresh_timer = QTimer(self)
        self.refresh_timer.start(self._redraw_interval)
        self.refresh_timer.timeout.connect(self._refresh_rosgraph)

        self._scene = QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self.graphics_view.setScene(self._scene)

        self.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh'))
        self.refresh_graph_push_button.clicked.connect(self._update_rosgraph)

        self.highlight_connections_check_box.toggled.connect(
            self._redraw_graph_view)
        self.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view)

        self.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original'))
        self.fit_in_view_push_button.clicked.connect(self._fit_in_view)

        self.depth_spin_box.setMinimum(-1)
        self.depth_spin_box.valueChanged.connect(self._refresh_rosgraph)

        self.save_dot_push_button.setIcon(QIcon.fromTheme('document-save-as'))
        self.save_dot_push_button.clicked.connect(self._save_dot)

        self.save_as_svg_push_button.setIcon(
            QIcon.fromTheme('document-save-as'))
        self.save_as_svg_push_button.clicked.connect(self._save_svg)

        self.save_as_image_push_button.setIcon(QIcon.fromTheme('image'))
        self.save_as_image_push_button.clicked.connect(self._save_image)

        self.run_push_button.setIcon(QIcon.fromTheme('media-playback-pause'))
        self.run_push_button.clicked.connect(self._run_bt)

        self._update_rosgraph()
        self._deferred_fit_in_view.connect(self._fit_in_view,
                                           Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()

        # generator builds tree graph
        bt_sub_name = '/cyborg/bt/behavior_tree'
        bt_update_sub_name = '/cyborg/bt/behavior_tree_updates'
        bt_enabled_sub_name = '/cyborg/bt/enabled'
        bt_enable_srv_name = '/cyborg/bt/enable'

        self._bt_enabled = True
        rospy.Subscriber(bt_enabled_sub_name, Bool, self._bt_enabled_cb)
        self._bt_enable_srv = rospy.ServiceProxy(bt_enable_srv_name, SetBool)

        bt_data = BTData(bt_sub_name, bt_update_sub_name)
        self.dotcode_generator = RosBTDotcodeGenerator(bt_data)
Beispiel #14
0
    def __init__(self, context):
        super(VinoGraph, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('VinoGraph')

        # 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

        # Create QWidget
        self._widget = QWidget()
        # Get path to UI file which should be in the "resource" folder of this package
        ui_file = os.path.join(rospkg.RosPack().get_path('rqt_vino_plugin'),
                               'resource', 'rqt_vino_plugin.ui')
        # Extend the widget with all attributes and children from UI file
        loadUi(ui_file, self._widget,
               {'InteractiveGraphicsView': InteractiveGraphicsView})
        # Give QObjects reasonable names
        self._widget.setObjectName('VinoGraphUi')
        # Show _widget.windowTitle on left-top of each plugin (when
        # it's set in _widget). This is useful when you open multiple  QListView
        # 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()))

        #A dict which stores pipeline name and dotgraph pair
        self._dotgraphs = dict()
        #which dotgraph currently drawing on the scence
        self._current_dotcode = None
        self._current_pipeline_name = ''
        #Pydot
        self.dotcode_factory = VinoPydotFactory()
        self.dot_to_qt = DotToQtGenerator()
        self.param_manager = ParamManagerWrapper()

        #Binding scene canvas
        self._scene = QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)
        self._widget.graphics_view.setClickNodeCallback(self._edit_node)

        #QListview of pipelines
        self._listmodel = QStandardItemModel()
        self._widget.pipeline_name_listview.clicked.connect(
            self._display_choosed_pipeline)
        #self._widget.pipeline_name_listview.itemRenamed.connect(self._rename_pipeline)
        #Load pipelines from yaml file
        self._widget.load_pipeline_push_button.clicked.connect(
            self._load_pipeline)
        #Create a pipeline
        self._widget.create_pipeline_push_button.clicked.connect(
            self._create_pipeline)
        #Add input to pipeline graph
        self._widget.add_input_push_button.clicked.connect(self._add_input)
        #Add infer
        self._widget.add_inference_push_button.clicked.connect(self._add_infer)
        self._widget.add_output_push_button.clicked.connect(self._add_output)

        self._widget.save_pipeline_push_button.clicked.connect(
            self._save_pipeline)

        self.models_desc_file_path = os.path.join(
            rospkg.RosPack().get_path('vino_param_lib'), 'param',
            'models.yaml')

        # Add widget to the user interface
        context.add_widget(self._widget)
    def test_recursive(self):
        if DotToQtGeneratorTest._Q_APP is None:
            raise unittest.case.SkipTest

        gen = DotToQtGenerator()
        dotcode = r'''
        strict digraph "" {
            graph [bb="0,0,249,541",
                    compound=True,
                    rank=same,
                    rankdir=TB,
                    ranksep=0.2,
                    simplify=True
            ];
            node [label="\N"];
            subgraph "/Container" {
                    graph [bb="8,67,241,321",
                            color=None,
                            compound=True,
                            label="/Container",
                            lheight=0.21,
                            lp="124.5,309.5",
                            lwidth=0.81,
                            rank=same,
                            rankdir=TB,
                            ranksep=0.2,
                            style=bold
                    ];
                    subgraph "/Container/Subcontainer" {
                            graph [bb="84,142,233,287",
                                    color=None,
                                    compound=True,
                                    label="/Container/Subcontainer",
                                    lheight=0.21,
                                    lp="158.5,275.5",
                                    lwidth=1.85,
                                    rank=same,
                                    rankdir=TB,
                                    ranksep=0.2,
                                    style=bold
                            ];
                            "/Container/Subcontainer/logstate1" [height=0.5,
                                    label=logstate1,
                                    pos="133,235",
                                    shape=box,
                                    url=None,
                                    width=0.90278];
                            "/Container/Subcontainer/finished" [color=blue,
                                    height=0.5,
                                    label=finished,
                                    pos="133,168",
                                    shape=ellipse,
                                    url=None,
                                    width=1.0833];
                            "/Container/Subcontainer/logstate1" -> "/Container/Subcontainer/finished" [label=done,
                                    lp="146.5,201.5",
                                    pos="e,133,186.19 133,216.92 133,210.7 133,203.5 133,196.6",
                                    url=None];
                    }
                    "/Container/finished"            [color=blue,
                            height=0.5,
                            label=finished,
                            pos="86,93",
                            shape=ellipse,
                            url=None,
                            width=1.0833];
                    "/Container/Subcontainer/finished" -> "/Container/finished" [label=finished,
                            lp="132,126.5",
                            pos="e,96.623,110.5 122.33,150.44 116.39,141.19 108.85,129.5 102.19,119.15",
                            url=None];
                    "/Container/logstate"            [height=0.5,
                            label=logstate,
                            pos="46,168",
                            shape=box,
                            url=None,
                            width=0.81944];
                    "/Container/logstate" -> "/Container/finished" [label=done,
                            lp="82.5,126.5",
                            pos="e,74.304,110.45 53.482,149.8 57.712,140.5 63.287,128.93 69,119 69.051,118.91 69.102,118.82 69.153,118.74",
                            url=None];
            }
            "/finished"      [height=0.5,
                    pos="86,18",
                    width=1.1555];
            "/Container/finished" -> "/finished"     [label=finished,
                    lp="108,51.5",
                    pos="e,86,36.176 86,74.7 86,66.245 86,55.869 86,46.373",
                    url=None];
            "/start" -> "/Container/Subcontainer/logstate1"   [
                    lp="146.5,436.5",
                    pos="e,133,250.01 133,355.84 133,337.5 133,316.81 133,260.22",
                    url=None];
            "/start" -> "/Container/logstate"   [
                    lp="146.5,436.5",
                    pos="e,46,185.01 133,355.84 46,337.5 46,316.81 46,192.22",
                    url=None];
            "/start"         [height=0.5,
                    pos="133,373",
                    width=0.79437];
        }
        '''

        (nodes, edges) = gen.dotcode_to_qt_items(dotcode, 1)

        expected_nodes = [
            '"/Container"', '"/Container/Subcontainer"',
            '"/Container/Subcontainer/finished"',
            '"/Container/Subcontainer/logstate1"', '"/Container/finished"',
            '"/Container/logstate"', '"/finished"', '"/start"'
        ]
        expected_edges = [
            '/Container/Subcontainer/finished_TO_/Container/finished_finished',
            '/Container/Subcontainer/logstate1_TO_/Container/Subcontainer/finished_done',
            '/Container/finished_TO_/finished_finished',
            '/Container/logstate_TO_/Container/finished_done',
            '/start_TO_/Container/Subcontainer/logstate1',
            '/start_TO_/Container/logstate',
        ]

        nodes_sorted = list(sorted(nodes.keys()))
        edges_sorted = list(sorted(edges.keys()))

        self.assertEqual(expected_nodes, nodes_sorted)
        self.assertEqual(expected_edges, edges_sorted)
Beispiel #16
0
    def __init__(self, context):
        super(RosGraph, self).__init__(context)
        self.initialized = False
        self.setObjectName('RosGraph')

        self._graph = None
        self._current_dotcode = None

        self._widget = QWidget()

        # factory builds generic dotcode items
        self.dotcode_factory = PydotFactory()
        # self.dotcode_factory = PygraphvizFactory()
        # generator builds rosgraph
        self.dotcode_generator = RosGraphDotcodeGenerator()
        # dot_to_qt transforms into Qt elements using dot layout
        self.dot_to_qt = DotToQtGenerator()

        ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'RosGraph.ui')
        loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('RosGraphUi')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))

        self._scene = QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        self._widget.graph_type_combo_box.insertItem(0, self.tr('Nodes only'), NODE_NODE_GRAPH)
        self._widget.graph_type_combo_box.insertItem(1, self.tr('Nodes/Topics (active)'), NODE_TOPIC_GRAPH)
        self._widget.graph_type_combo_box.insertItem(2, self.tr('Nodes/Topics (all)'), NODE_TOPIC_ALL_GRAPH)
        self._widget.graph_type_combo_box.setCurrentIndex(0)
        self._widget.graph_type_combo_box.currentIndexChanged.connect(self._refresh_rosgraph)

        self.node_completionmodel = NamespaceCompletionModel(self._widget.filter_line_edit, False)
        completer = RepeatedWordCompleter(self.node_completionmodel, self)
        completer.setCompletionMode(QCompleter.PopupCompletion)
        completer.setWrapAround(True)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        self._widget.filter_line_edit.editingFinished.connect(self._refresh_rosgraph)
        self._widget.filter_line_edit.setCompleter(completer)

        self.topic_completionmodel = NamespaceCompletionModel(self._widget.topic_filter_line_edit, False)
        topic_completer = RepeatedWordCompleter(self.topic_completionmodel, self)
        topic_completer.setCompletionMode(QCompleter.PopupCompletion)
        topic_completer.setWrapAround(True)
        topic_completer.setCaseSensitivity(Qt.CaseInsensitive)
        self._widget.topic_filter_line_edit.editingFinished.connect(self._refresh_rosgraph)
        self._widget.topic_filter_line_edit.setCompleter(topic_completer)

        self._widget.namespace_cluster_check_box.clicked.connect(self._refresh_rosgraph)
        self._widget.actionlib_check_box.clicked.connect(self._refresh_rosgraph)
        self._widget.dead_sinks_check_box.clicked.connect(self._refresh_rosgraph)
        self._widget.leaf_topics_check_box.clicked.connect(self._refresh_rosgraph)
        self._widget.quiet_check_box.clicked.connect(self._refresh_rosgraph)

        self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh'))
        self._widget.refresh_graph_push_button.pressed.connect(self._update_rosgraph)

        self._widget.highlight_connections_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view)
        self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original'))
        self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view)

        self._widget.load_dot_push_button.setIcon(QIcon.fromTheme('document-open'))
        self._widget.load_dot_push_button.pressed.connect(self._load_dot)
        self._widget.save_dot_push_button.setIcon(QIcon.fromTheme('document-save-as'))
        self._widget.save_dot_push_button.pressed.connect(self._save_dot)
        self._widget.save_as_svg_push_button.setIcon(QIcon.fromTheme('document-save-as'))
        self._widget.save_as_svg_push_button.pressed.connect(self._save_svg)
        self._widget.save_as_image_push_button.setIcon(QIcon.fromTheme('image'))
        self._widget.save_as_image_push_button.pressed.connect(self._save_image)

        self._update_rosgraph()
        self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()

        context.add_widget(self._widget)
Beispiel #17
0
    def __init__(self, context):
        super(RosPackGraph, self).__init__(context)
        self.initialized = False
        self._current_dotcode = None
        self._update_thread = WorkerThread(self._update_thread_run,
                                           self._update_finished)
        self._nodes = {}
        self._edges = {}
        self._options = {}
        self._options_serialized = ''

        self.setObjectName('RosPackGraph')

        rospack = rospkg.RosPack()
        rosstack = rospkg.RosStack()

        # factory builds generic dotcode items
        self.dotcode_factory = PydotFactory()
        # self.dotcode_factory = PygraphvizFactory()
        # generator builds rosgraph
        self.dotcode_generator = RosPackageGraphDotcodeGenerator(
            rospack, rosstack)
        # dot_to_qt transforms into Qt elements using dot layout
        self.dot_to_qt = DotToQtGenerator()

        self._widget = QWidget()
        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_dep'), 'resource',
                               'RosPackGraph.ui')
        loadUi(ui_file, self._widget,
               {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('RosPackGraphUi')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' (%d)' % context.serial_number()))

        self._scene = QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        self._widget.depth_combo_box.insertItem(0, self.tr('infinite'), -1)
        self._widget.depth_combo_box.insertItem(1, self.tr('1'), 2)
        self._widget.depth_combo_box.insertItem(2, self.tr('2'), 3)
        self._widget.depth_combo_box.insertItem(3, self.tr('3'), 4)
        self._widget.depth_combo_box.insertItem(4, self.tr('4'), 5)
        self._widget.depth_combo_box.currentIndexChanged.connect(
            self._refresh_rospackgraph)

        self._widget.directions_combo_box.insertItem(0, self.tr('depends'), 0)
        self._widget.directions_combo_box.insertItem(1, self.tr('depends_on'),
                                                     1)
        self._widget.directions_combo_box.insertItem(2, self.tr('both'), 2)
        self._widget.directions_combo_box.currentIndexChanged.connect(
            self._refresh_rospackgraph)

        self._widget.package_type_combo_box.insertItem(0, self.tr('wet & dry'),
                                                       3)
        self._widget.package_type_combo_box.insertItem(1, self.tr('wet only'),
                                                       2)
        self._widget.package_type_combo_box.insertItem(2, self.tr('dry only'),
                                                       1)
        self._widget.package_type_combo_box.currentIndexChanged.connect(
            self._refresh_rospackgraph)

        completionmodel = StackageCompletionModel(
            self._widget.filter_line_edit, rospack, rosstack)
        completer = RepeatedWordCompleter(completionmodel, self)
        completer.setCompletionMode(QCompleter.PopupCompletion)
        completer.setWrapAround(True)

        completer.setCaseSensitivity(Qt.CaseInsensitive)
        self._widget.filter_line_edit.editingFinished.connect(
            self._refresh_rospackgraph)
        self._widget.filter_line_edit.setCompleter(completer)
        self._widget.filter_line_edit.selectionChanged.connect(
            self._clear_filter)

        self._widget.with_stacks_check_box.clicked.connect(
            self._refresh_rospackgraph)
        self._widget.mark_check_box.clicked.connect(self._refresh_rospackgraph)
        self._widget.colorize_check_box.clicked.connect(
            self._refresh_rospackgraph)
        self._widget.hide_transitives_check_box.clicked.connect(
            self._refresh_rospackgraph)
        self._widget.show_system_check_box.clicked.connect(
            self._refresh_rospackgraph)

        self._widget.refresh_graph_push_button.setIcon(
            QIcon.fromTheme('view-refresh'))
        self._widget.refresh_graph_push_button.pressed.connect(
            self._update_rospackgraph)

        self._widget.highlight_connections_check_box.toggled.connect(
            self._refresh_rospackgraph)
        self._widget.auto_fit_graph_check_box.toggled.connect(
            self._refresh_rospackgraph)
        self._widget.fit_in_view_push_button.setIcon(
            QIcon.fromTheme('zoom-original'))
        self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view)

        self._widget.load_dot_push_button.setIcon(
            QIcon.fromTheme('document-open'))
        self._widget.load_dot_push_button.pressed.connect(self._load_dot)
        self._widget.save_dot_push_button.setIcon(
            QIcon.fromTheme('document-save-as'))
        self._widget.save_dot_push_button.pressed.connect(self._save_dot)
        self._widget.save_as_svg_push_button.setIcon(
            QIcon.fromTheme('document-save-as'))
        self._widget.save_as_svg_push_button.pressed.connect(self._save_svg)
        self._widget.save_as_image_push_button.setIcon(
            QIcon.fromTheme('image'))
        self._widget.save_as_image_push_button.pressed.connect(
            self._save_image)

        self._deferred_fit_in_view.connect(self._fit_in_view,
                                           Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()

        context.add_widget(self._widget)

        # If in either of following case, this turnes True
        # - 1st filtering key is already input by user
        # - filtering key is restored
        self._filtering_started = False
Beispiel #18
0
 def test_simpleIntegration(self):
     gen = DotToQtGenerator()
     dotcode = 'digraph graphname {\n\tgraph [rank=same];\n\tnode [label="\\N"];\n\tgraph [bb="0,0,56,116"];\n\tsubgraph cluster_foo {\n\t\tgraph [label=foo,\n\t\t\tbb="1,1,100,101"];\n\t}\n\tfoo [label=foo, shape=box, pos="28,98", width="0.75", height="0.50"];\n\tedge_ [label=edge_, shape=box, pos="28,26", width="0.78", height="0.50"];\n\tfoo -> edge_ [pos="e,28,44 28,80 28,72 28,63 28,54"];\n}\n'
     (nodes, edges) = gen.dotcode_to_qt_items(dotcode, 1)
     self.assertEqual(3, len(nodes))  # also for stack
     self.assertEqual(1, len(nodes))
Beispiel #19
0
 def test_simple_integration(self):
     (nodes, edges) = DotToQtGenerator().dotcode_to_qt_items(DotToQtGeneratorTest.DOT_CODE, 1)
     self.assertEqual(3, len(nodes))  # cluster_foo, foo and bar
     self.assertEqual(1, len(edges))  # foo -> bar
    def __init__(self, context):
        super(RosBehaviourTree, self).__init__(context)
        self.setObjectName('RosBehaviourTree')

        parser = argparse.ArgumentParser()
        RosBehaviourTree.add_arguments(parser, False)
        # if the context doesn't have an argv attribute then assume we're running with --no-roscore
        if not hasattr(context, 'argv'):
            args = sys.argv[1:]
            # Can run the viewer with or without live updating. Running without is
            # intended for viewing of bags only
            self.live_update = False
        else:
            args = context.argv()
            self.live_update = True

        parsed_args = parser.parse_args(args)

        self.context = context
        self.initialized = False
        self._current_dotcode = None  # dotcode for the tree that is currently displayed
        self._viewing_bag = False  # true if a bag file is loaded
        # True if next or previous buttons are pressed. Reset if the tree being
        # viewed is the last one in the list.
        self._browsing_timeline = False

        self._widget = QWidget()

        # factory builds generic dotcode items
        self.dotcode_factory = PygraphvizFactory()  # PydotFactory()
        # self.dotcode_factory = PygraphvizFactory()
        # generator builds rosgraph
        self.dotcode_generator = RosBehaviourTreeDotcodeGenerator()
        self.current_topic = None
        self.behaviour_sub = None
        self._tip_message = None  # message of the tip of the tree
        self._saved_settings_topic = None  # topic subscribed to by previous instance
        self.visibility_level = py_trees.common.VisibilityLevel.DETAIL

        # dot_to_qt transforms into Qt elements using dot layout
        self.dot_to_qt = DotToQtGenerator()

        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_py_trees'), 'resource',
                               'RosBehaviourTree.ui')
        loadUi(ui_file, self._widget,
               {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('RosBehaviourTreeUi')
        if hasattr(context, 'serial_number') and context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' (%d)' % context.serial_number()))

        self._scene = QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        self._widget.highlight_connections_check_box.toggled.connect(
            self._redraw_graph_view)
        self._widget.auto_fit_graph_check_box.toggled.connect(
            self._redraw_graph_view)
        self._widget.fit_in_view_push_button.setIcon(
            QIcon.fromTheme('zoom-original'))
        self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view)

        self._widget.load_bag_push_button.setIcon(
            QIcon.fromTheme('document-open'))
        self._widget.load_bag_push_button.pressed.connect(self._load_bag)
        self._widget.load_dot_push_button.setIcon(
            QIcon.fromTheme('document-open'))
        self._widget.load_dot_push_button.pressed.connect(self._load_dot)
        self._widget.save_dot_push_button.setIcon(
            QIcon.fromTheme('document-save-as'))
        self._widget.save_dot_push_button.pressed.connect(self._save_dot)
        self._widget.save_as_svg_push_button.setIcon(
            QIcon.fromTheme('document-save-as'))
        self._widget.save_as_svg_push_button.pressed.connect(self._save_svg)
        self._widget.save_as_image_push_button.setIcon(
            QIcon.fromTheme('image'))
        self._widget.save_as_image_push_button.pressed.connect(
            self._save_image)

        for text in visibility.combo_to_py_trees:
            self._widget.visibility_level_combo_box.addItem(text)
        self._widget.visibility_level_combo_box.setCurrentIndex(
            self.visibility_level)
        self._widget.visibility_level_combo_box.currentIndexChanged[
            'QString'].connect(self._update_visibility_level)

        # set up the function that is called whenever the box is resized -
        # ensures that the timeline is correctly drawn.
        self._widget.resizeEvent = self._resize_event

        self._timeline = None
        self._timeline_listener = None

        # Connect the message changed function of this object to a corresponding
        # signal. This signal will be activated whenever the message being
        # viewed changes.
        self._message_changed.connect(self.message_changed)
        self._message_cleared.connect(self.message_cleared)

        # Set up combo box for topic selection
        # when the refresh_combo signal happens, update the combo topics available
        self._refresh_combo.connect(self._update_combo_topics)
        # filter events to catch the event which opens the combo box
        self._combo_event_filter = RosBehaviourTree.ComboBoxEventFilter(
            self._refresh_combo)
        self._widget.topic_combo_box.installEventFilter(
            self._combo_event_filter)
        self._widget.topic_combo_box.activated.connect(self._choose_topic)
        self._update_combo_topics()

        # Set up navigation buttons
        self._widget.previous_tool_button.pressed.connect(self._previous)
        self._widget.previous_tool_button.setIcon(
            QIcon.fromTheme('go-previous'))
        self._widget.next_tool_button.pressed.connect(self._next)
        self._widget.next_tool_button.setIcon(QIcon.fromTheme('go-next'))
        self._widget.first_tool_button.pressed.connect(self._first)
        self._widget.first_tool_button.setIcon(QIcon.fromTheme('go-first'))
        self._widget.last_tool_button.pressed.connect(self._last)
        self._widget.last_tool_button.setIcon(QIcon.fromTheme('go-last'))

        # play, pause and stop buttons
        self._widget.play_tool_button.pressed.connect(self._play)
        self._widget.play_tool_button.setIcon(
            QIcon.fromTheme('media-playback-start'))
        self._widget.stop_tool_button.pressed.connect(self._stop)
        self._widget.stop_tool_button.setIcon(
            QIcon.fromTheme('media-playback-stop'))
        # also connect the navigation buttons so that they stop the timer when
        # pressed while the tree is playing.
        self._widget.first_tool_button.pressed.connect(self._stop)
        self._widget.previous_tool_button.pressed.connect(self._stop)
        self._widget.last_tool_button.pressed.connect(self._stop)
        self._widget.next_tool_button.pressed.connect(self._stop)

        # set up shortcuts for navigation (vim)
        next_shortcut_vi = QShortcut(QKeySequence("l"), self._widget)
        next_shortcut_vi.activated.connect(
            self._widget.next_tool_button.pressed)
        previous_shortcut_vi = QShortcut(QKeySequence("h"), self._widget)
        previous_shortcut_vi.activated.connect(
            self._widget.previous_tool_button.pressed)
        first_shortcut_vi = QShortcut(QKeySequence("^"), self._widget)
        first_shortcut_vi.activated.connect(
            self._widget.first_tool_button.pressed)
        last_shortcut_vi = QShortcut(QKeySequence("$"), self._widget)
        last_shortcut_vi.activated.connect(
            self._widget.last_tool_button.pressed)

        # shortcuts for emacs
        next_shortcut_emacs = QShortcut(QKeySequence("Ctrl+f"), self._widget)
        next_shortcut_emacs.activated.connect(
            self._widget.next_tool_button.pressed)
        previous_shortcut_emacs = QShortcut(QKeySequence("Ctrl+b"),
                                            self._widget)
        previous_shortcut_emacs.activated.connect(
            self._widget.previous_tool_button.pressed)
        first_shortcut_emacs = QShortcut(QKeySequence("Ctrl+a"), self._widget)
        first_shortcut_emacs.activated.connect(
            self._widget.first_tool_button.pressed)
        last_shortcut_emacs = QShortcut(QKeySequence("Ctrl+e"), self._widget)
        last_shortcut_emacs.activated.connect(
            self._widget.last_tool_button.pressed)

        # set up stuff for dotcode cache
        self._dotcode_cache_capacity = 50
        self._dotcode_cache = {}
        # cache is ordered on timestamps from messages, but earliest timestamp
        # isn't necessarily the message that was viewed the longest time ago, so
        # need to store keys
        self._dotcode_cache_keys = []

        # set up stuff for scene cache (dotcode cache doesn't seem to make much difference)
        self._scene_cache_capacity = 50
        self._scene_cache = {}
        self._scene_cache_keys = []

        # Update the timeline buttons to correspond with a completely
        # uninitialised state.
        self._set_timeline_buttons(first_snapshot=False,
                                   previous_snapshot=False,
                                   next_snapshot=False,
                                   last_snapshot=False)

        self._deferred_fit_in_view.connect(self._fit_in_view,
                                           Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()

        # This is used to store a timer which controls how fast updates happen when the play button is pressed.
        self._play_timer = None

        # updates the view
        self._refresh_view.connect(self._refresh_tree_graph)

        self._force_refresh = False

        if self.live_update:
            context.add_widget(self._widget)
        else:
            self.initialized = True  # this needs to be set for trees to be displayed
            context.setCentralWidget(self._widget)

        if parsed_args.bag:
            self._load_bag(parsed_args.bag)
        elif parsed_args.latest_bag:
            # if the latest bag is requested, load it from the default directory, or
            # the one specified in the args
            bag_dir = parsed_args.bag_dir or os.getenv(
                'ROS_HOME', os.path.expanduser('~/.ros')) + '/behaviour_trees'
            self.open_latest_bag(bag_dir, parsed_args.by_time)
Beispiel #21
0
    def __init__(self, context):
        super(GatewayGraph, self).__init__(context)
        self.initialised = False
        self.setObjectName('Gateway Graph')
        self._current_dotcode = None

        self._widget = QWidget()

        # factory builds generic dotcode items
        self.dotcode_factory = PydotFactory()
        # self.dotcode_factory = PygraphvizFactory()
        self.dotcode_generator = RosGraphDotcodeGenerator()
        self.dot_to_qt = DotToQtGenerator()
        self._graph = Graph()

        rospack = rospkg.RosPack()
        ui_file = os.path.join(rospack.get_path('rocon_gateway_graph'), 'ui',
                               'gateway_graph.ui')
        #ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ui', 'gateway_graph.ui')
        loadUi(ui_file, self._widget,
               {'InteractiveGraphicsView': InteractiveGraphicsView})
        self._widget.setObjectName('GatewayGraphUi')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' (%d)' % context.serial_number()))

        self._scene = QGraphicsScene()
        self._scene.setBackgroundBrush(Qt.white)
        self._widget.graphics_view.setScene(self._scene)

        self._widget.refresh_graph_push_button.setIcon(
            QIcon.fromTheme('view-refresh'))
        self._widget.refresh_graph_push_button.pressed.connect(
            self._update_gateway_graph)

        self._widget.graph_type_combo_box.insertItem(0, self.tr('Gateways'),
                                                     GATEWAY_GATEWAY_GRAPH)
        self._widget.graph_type_combo_box.insertItem(
            1, self.tr('Pulled Connections'), GATEWAY_PULLED_GRAPH)
        self._widget.graph_type_combo_box.insertItem(
            2, self.tr('Flipped Connections'), GATEWAY_FLIPPED_GRAPH)
        self._widget.graph_type_combo_box.setCurrentIndex(0)
        self._widget.graph_type_combo_box.currentIndexChanged.connect(
            self._refresh_rosgraph)

        self.node_completionmodel = NamespaceCompletionModel(
            self._widget.filter_line_edit, False)
        completer = RepeatedWordCompleter(self.node_completionmodel, self)
        completer.setCompletionMode(QCompleter.PopupCompletion)
        completer.setWrapAround(True)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        self._widget.filter_line_edit.editingFinished.connect(
            self._refresh_rosgraph)
        self._widget.filter_line_edit.setCompleter(completer)
        self.topic_completionmodel = NamespaceCompletionModel(
            self._widget.topic_filter_line_edit, False)
        topic_completer = RepeatedWordCompleter(self.topic_completionmodel,
                                                self)
        topic_completer.setCompletionMode(QCompleter.PopupCompletion)
        topic_completer.setWrapAround(True)
        topic_completer.setCaseSensitivity(Qt.CaseInsensitive)
        self._widget.topic_filter_line_edit.editingFinished.connect(
            self._refresh_rosgraph)
        self._widget.topic_filter_line_edit.setCompleter(topic_completer)

        self._widget.namespace_cluster_check_box.clicked.connect(
            self._refresh_rosgraph)
        self._widget.watchlist_check_box.clicked.connect(
            self._refresh_rosgraph)
        self._widget.all_advertisements_check_box.clicked.connect(
            self._refresh_rosgraph)

        self._widget.highlight_connections_check_box.toggled.connect(
            self._redraw_graph_view)
        self._widget.auto_fit_graph_check_box.toggled.connect(
            self._redraw_graph_view)
        self._widget.fit_in_view_push_button.setIcon(
            QIcon.fromTheme('zoom-original'))
        self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view)

        self._widget.load_dot_push_button.setIcon(
            QIcon.fromTheme('document-open'))
        self._widget.load_dot_push_button.pressed.connect(self._load_dot)
        self._widget.save_dot_push_button.setIcon(
            QIcon.fromTheme('document-save-as'))
        self._widget.save_dot_push_button.pressed.connect(self._save_dot)
        self._widget.save_as_svg_push_button.setIcon(
            QIcon.fromTheme('document-save-as'))
        self._widget.save_as_svg_push_button.pressed.connect(self._save_svg)
        self._widget.save_as_image_push_button.setIcon(
            QIcon.fromTheme('image'))
        self._widget.save_as_image_push_button.pressed.connect(
            self._save_image)

        self._update_gateway_graph()
        self._deferred_fit_in_view.connect(self._fit_in_view,
                                           Qt.QueuedConnection)
        self._deferred_fit_in_view.emit()
        context.add_widget(self._widget)