def __init__(self, widget_class, name, window, *args):
        super(OCSPlugin, self).__init__(None)

        if len(args) > 0:
            self._widget = widget_class(self, args[0])
        else:
            self._widget = widget_class(self)

        self._name = name
        self._window = window

        self._window_control_sub = rospy.Subscriber("/flor/ocs/window_control", Int8, self.processWindowControl)
        self._window_control_pub = rospy.Publisher("/flor/ocs/window_control", Int8, queue_size=10)
        
        # window visibility configuration variables
        self._last_window_control_data = -self._window
        self._set_window_visibility = True

        # this is only used to make sure we close window if ros::shutdown has already been called
        self._timer = QBasicTimer()
        self._timer.start(33, self)
        
        settings = QSettings("OCS", self._name)
        if settings.value("mainWindowGeometry") != None:
            self.restoreGeometry(settings.value("mainWindowGeometry"))
    	self.geometry_ = self.geometry()
Example #2
0
 def closeEvent(self, event):
     settings = QSettings("OCS", "joint_control")
     settings.setValue("mainWindowGeometry", self.saveGeometry())
     msg = Int8()
     msg.data = -self._window
     self._window_control_pub.publish(msg)
     event.ignore()
Example #3
0
    def __init__(self, widget_class, name, window, *args):
        super(OCSPlugin, self).__init__(None)

        if len(args) > 0:
            self._widget = widget_class(self, args[0])
        else:
            self._widget = widget_class(self)

        self._name = name
        self._window = window

        self._window_control_sub = rospy.Subscriber("/flor/ocs/window_control",
                                                    Int8,
                                                    self.processWindowControl)
        self._window_control_pub = rospy.Publisher("/flor/ocs/window_control",
                                                   Int8,
                                                   queue_size=10)

        # window visibility configuration variables
        self._last_window_control_data = -self._window
        self._set_window_visibility = True

        # this is only used to make sure we close window if ros::shutdown has already been called
        self._timer = QBasicTimer()
        self._timer.start(33, self)

        settings = QSettings("OCS", self._name)
        if settings.value("mainWindowGeometry") is not None:
            self.restoreGeometry(settings.value("mainWindowGeometry"))
        self.geometry_ = self.geometry()
Example #4
0
 def closeEvent(self, event):
     settings = QSettings("OCS", self._name)
     settings.setValue("mainWindowGeometry", self.saveGeometry())
     msg = Int8()
     msg.data = -self._window
     self._window_control_pub.publish(msg)
     event.ignore()
    def __init__(self, context, bag_widget, publish_clock):
        super(AnnotatorWidget, self).__init__()
        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_bag_meri_annotator'),
                               'resource', 'MeriPlugin.ui')
        loadUi(ui_file, self, {'AnnotatorGraphicsView': AnnotatorGraphicsView})
        self.setObjectName('AnnotatorWidget')
        self.setMouseTracking(True)
        self.annotation_data = list()
        self.interaction_time = 120.0

        self.bag_widget = bag_widget
        self.bagtimeline = self.bag_widget._timeline
        self._child_index = 0
        self.settings = QSettings("UFES", "MERI Annotator Widget")
        #self.settings.setValue("Last_child_index",self._child_index)

        self.instance = vlc.Instance()
        self.mediaplayer = self.instance.media_player_new()
        self.isPaused = False
        self.msgBox = QMessageBox()
        self.msgBox.setIcon(QMessageBox.Information)
        self.msgBox.setWindowTitle('Annotator Interface Information')
        self.msgBox.setStandardButtons(QMessageBox.Ok)

        self.BtnSaveJson.clicked.connect(self.BtnSaveJsonClicked)
        self.BtnLoadJson.clicked.connect(self.BtnLoadJsonClicked)
        self.BtnNext.clicked.connect(self.BtnNextClicked)
        self.BtnSetupBag.clicked.connect(self.BtnSetupBagClicked)
        self.BtnPrevious.clicked.connect(self.BtnPreviousClicked)
        self.BtnZero.clicked.connect(self.BtnZeroClicked)
        self.BtnOne.clicked.connect(self.BtnOneClicked)
        self.BtnTwo.clicked.connect(self.BtnTwoClicked)
        self.BtnAimLess.clicked.connect(self.BtnAimLessClicked)
        self.BtnGoalOriented.clicked.connect(self.BtnGoalOrientedClicked)
        self.BtnRobotStarted.clicked.connect(self.BtnRobotStartedClicked)
        self.BtnPointing.clicked.connect(self.BtnPointingClicked)
        self.BtnFollowLor.clicked.connect(self.BtnFollowLorClicked)
        self.BtnAdultSeek.clicked.connect(self.BtnAdultSeekClicked)
        self.BtnECTwC.clicked.connect(self.BtnECTwCClicked)
        self.BtnECTwR.clicked.connect(self.BtnECTwRClicked)
        self.BtnECTwT.clicked.connect(self.BtnECTwTClicked)
        self.BtnPlay.clicked.connect(self.BtnPlayClicked)
        self.BtnPause.clicked.connect(self.BtnPauseClicked)
        self.BtnStop.clicked.connect(self.BtnStopClicked)

        self.BtnPlay.setIcon(QIcon.fromTheme('media-playback-start'))
        self.BtnPause.setIcon(QIcon.fromTheme('media-playback-pause'))
        self.BtnLoadJson.setIcon(QIcon.fromTheme('document-open'))
        self.BtnSaveJson.setIcon(QIcon.fromTheme('document-save'))
        self.BtnStop.setIcon(QIcon.fromTheme('media-playback-stop'))
        self.BtnNext.setIcon(QIcon.fromTheme('go-next'))
        self.BtnSetupBag.setIcon(QIcon.fromTheme('document-properties'))
        self.BtnPrevious.setIcon(QIcon.fromTheme('go-previous'))
Example #6
0
    def __init__(self, parent):
        """
        @type parent: LaunchMain
        """
        super(LaunchWidget, self).__init__()
        self._parent = parent

        self._config = None
        self._settings = QSettings('ros', 'rqt_launch')
        self._settings.sync()
        self._package_update = False
        self._launchfile_update = False

        # TODO: should be configurable from gui
        self._port_roscore = 11311

        self._run_id = None

        self._rospack = rospkg.RosPack()
        ui_file = os.path.join(
            self._rospack.get_path('rqt_launch'), 'resource', 'launch_widget.ui'
        )
        loadUi(ui_file, self)

        # row=0 allows any number of rows to be added.
        self._datamodel = QStandardItemModel(0, 1)

        master_uri = rosenv.get_master_uri()
        rospy.loginfo('LaunchWidget master_uri={}'.format(master_uri))
        self._delegate = NodeDelegate(master_uri, self._rospack)
        self._treeview.setModel(self._datamodel)
        self._treeview.setItemDelegate(self._delegate)

        # NodeController used in controller class for launch operation.
        self._node_controllers = []

        self._pushbutton_load_params.clicked.connect(self._parent.load_params)
        self._pushbutton_start_all.clicked.connect(self._parent.start_all)
        self._pushbutton_stop_all.clicked.connect(self._parent.stop_all)
        self._pushbutton_refresh.clicked.connect(
            self._update_pkgs_contain_launchfiles
        )
        # Bind package selection with .launch file selection.
        self._combobox_pkg.currentIndexChanged[str].connect(
            self._refresh_launchfiles
        )
        # Bind a launch file selection with launch GUI generation.
        self._combobox_launchfile_name.currentIndexChanged[str].connect(
            self._load_launchfile_slot
        )
        self._update_pkgs_contain_launchfiles()
Example #7
0
    def __init__(self, context):
        super(RqtLgsvlSimulatorConfiguratorPlugin, self).__init__(context)
        rospack = rospkg.RosPack()
        self.settings = QSettings(rospack.get_path('lgsvl_simulator_bridge')+"/config/setting.dat",QSettings.IniFormat)
        # Give QObjects reasonable names
        self.setObjectName('RqtLgsvlSimulatorConfiguratorPlugin')

        # 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('lgsvl_simulator_bridge'), 'resource', 'LgsvlSimulatorConfigratorPlugin.ui')
        # Extend the widget with all atrributes and children from UI File
        loadUi(ui_file, self._widget)
        # Give QObjects reasonable names
        self._widget.setObjectName('RqtLgsvlSimulatorConfiguratorPluginUi')
        # Show _widget.windowTitle on left-top of each plugin(when it's set in _widget).
        # This is useful when you open multiple plugins aat once. Also if you open multiple
        # instances of your plugin at once, these lines add number to make it easy to
        # tell from pane to pane.
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() + (' %d' % context.serial_number()))
        # Add widget to the user interface
        self.settings.beginGroup("simulator_params")
        context.add_widget(self._widget)
        ip = self.settings.value('ip')
        if ip != None:
            self._widget.ip_box.setText(ip)
        port = self.settings.value('port')
        if port != None:
            self._widget.port_box.setText(port)
        config_path = self.settings.value('config_path')
        if config_path != None:
            self._widget.configpath_box.setText(config_path)
        self.settings.endGroup()
        self.json_dict = {}
        self.instance_id = ""
        self.is_remote = False
        self._widget.button_config_ref.clicked[bool].connect(self._handle_config_ref_button_clicked)
        self._widget.button_config.clicked[bool].connect(self._handle_config_button_clicked)
        self._widget.launch_button.clicked[bool].connect(self._handle_launch_button_clicked)
        self._widget.terminate_button.clicked[bool].connect(self._handle_terminate_button_clicked)
Example #8
0
    def __init__(self):
        super(JointControlDialog, self).__init__(None)

        self._widget = JointControlWidget(self)
        self._window_control_sub = rospy.Subscriber("/flor/ocs/window_control", Int8, self.processWindowControl)
        self._window_control_pub = rospy.Publisher("/flor/ocs/window_control", Int8, queue_size=10)   

        # #define WINDOW_JOINT_CONTROL 7
        self._window = 7
        
        # window visibility configuration variables
        self._last_window_control_data = -self._window
        self._set_window_visibility = True

        # this is only used to make sure we close window if ros::shutdown has already been called
        self._timer = QBasicTimer()
        self._timer.start(33, self)

        settings = QSettings("OCS", "joint_control")
        if settings.value("mainWindowGeometry") is not None:
            self.restoreGeometry(settings.value("mainWindowGeometry"))
        self.geometry_ = self.geometry()
class RqtLgsvlSimulatorConfiguratorPlugin(Plugin):
    def __init__(self, context):
        super(RqtLgsvlSimulatorConfiguratorPlugin, self).__init__(context)
        rospack = rospkg.RosPack()
        self.settings = QSettings(
            rospack.get_path('lgsvl_simulator_bridge') + "/config/setting.dat",
            QSettings.IniFormat)
        # Give QObjects reasonable names
        self.setObjectName('RqtLgsvlSimulatorConfiguratorPlugin')

        # 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('lgsvl_simulator_bridge'), 'resource',
            'LgsvlSimulatorConfigratorPlugin.ui')
        # Extend the widget with all atrributes and children from UI File
        loadUi(ui_file, self._widget)
        # Give QObjects reasonable names
        self._widget.setObjectName('RqtLgsvlSimulatorConfiguratorPluginUi')
        # Show _widget.windowTitle on left-top of each plugin(when it's set in _widget).
        # This is useful when you open multiple plugins aat once. Also if you open multiple
        # instances of your plugin at once, these lines add number to make it easy to
        # tell from pane to pane.
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' %d' % context.serial_number()))
        # Add widget to the user interface
        self.settings.beginGroup("simulator_params")
        context.add_widget(self._widget)
        ip = self.settings.value('ip')
        if ip != None:
            self._widget.ip_box.setText(ip)
        port = self.settings.value('port')
        if port != None:
            self._widget.port_box.setText(port)
        config_path = self.settings.value('config_path')
        if config_path != None:
            self._widget.configpath_box.setText(config_path)
        self.settings.endGroup()
        self.json_dict = {}
        self.instance_id = ""
        self.is_remote = False
        self._widget.button_config_ref.clicked[bool].connect(
            self._handle_config_ref_button_clicked)
        self._widget.button_config.clicked[bool].connect(
            self._handle_config_button_clicked)
        self._widget.launch_button.clicked[bool].connect(
            self._handle_launch_button_clicked)
        self._widget.terminate_button.clicked[bool].connect(
            self._handle_terminate_button_clicked)

    def shutdown_plugin(self):
        # TODO unregister all publishers here
        pass

    def save_settings(self, plugin_settings, instance_settings):
        # TODO save intrinsic configuration, usually using:
        # instance_settings.get_value(k, v)
        pass

    def restore_settings(self, pluign_settings, instance_settings):
        # TODO restore intrinsic configuration, usually using:
        # v = instance_settings.value(k)
        pass

    def _handle_launch_button_clicked(self):
        if str(self._widget.ip_box.text()) == "localhost" or str(
                self._widget.ip_box.text()) == "0.0.0.0" or str(
                    self._widget.ip_box.text()) == "127.0.0.1":
            cmd = [
                "roslaunch", "lgsvl_simulator_bridge", "lgsvl_simulator.launch"
            ]
            self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
            self._widget.launch_button.setStyleSheet(
                "background-color: #8fb8e0")
            self._widget.terminate_button.setStyleSheet(
                "background-color: #FFFFFF")
            self.is_remote = False
            return
        else:
            cmd = ["roslaunch", "lgsvl_simulator_bridge", "bridge.launch"]
            self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
        address = "http://" + self._widget.ip_box.text(
        ) + ":" + self._widget.port_box.text() + "/simulator/launch"
        self.settings.beginGroup("simulator_params")
        self.settings.setValue("ip", self._widget.ip_box.text())
        self.settings.setValue("port", self._widget.port_box.text())
        self.settings.endGroup()
        try:
            response = requests.post(address, json=self.json_dict)
            self.instance_id = response.json()[u'instance_id']
        except:
            self._widget.launch_button.setStyleSheet(
                "background-color: #F5A9A9")
            return
        self.is_remote = False
        self._widget.launch_button.setStyleSheet("background-color: #8fb8e0")
        self._widget.terminate_button.setStyleSheet(
            "background-color: #FFFFFF")

    def _handle_config_ref_button_clicked(self):
        rospack = rospkg.RosPack()
        fname = QFileDialog.getOpenFileName(
            self._widget, 'Open file',
            rospack.get_path('lgsvl_simulator_bridge') + '/config')
        self._widget.configpath_box.setText(fname[0])

    def _handle_config_button_clicked(self):
        path = self._widget.configpath_box.text()
        try:
            f = open(path, "r+")
            self.json_dict = json.load(f)
            self.settings.beginGroup("simulator_params")
            self.settings.setValue("config_path", path)
            self.settings.endGroup()
        except:
            self._widget.button_config.setStyleSheet(
                "background-color: #F5A9A9")
            return
        self._widget.button_config.setStyleSheet("background-color: #8fb8e0")

    def _handle_terminate_button_clicked(self):
        address = "http://" + self._widget.ip_box.text(
        ) + ":" + self._widget.port_box.text() + "/simulator/terminate"
        self.settings.beginGroup("simulator_params")
        self.settings.setValue("ip", self._widget.ip_box.text())
        self.settings.setValue("port", self._widget.port_box.text())
        self.settings.endGroup()
        if self.instance_id == "" and self.is_remote == True:
            return
        if self.is_remote == True:
            try:
                response = requests.post(
                    address, json={u'instance_id': self.instance_id})
            except:
                self._widget.terminate_button.setStyleSheet(
                    "background-color: #F5A9A9")
                return
        try:
            self.proc.terminate()
        except:
            self._widget.terminate_button.setStyleSheet(
                "background-color: #F5A9A9")
            return
        self._widget.terminate_button.setStyleSheet(
            "background-color: #8fb8e0")
        self._widget.launch_button.setStyleSheet("background-color: #FFFFFF")
 def moveEvent(self, event):
     settings = QSettings("OCS", self._name)
     settings.setValue("mainWindowGeometry", self.saveGeometry())
Example #11
0
 def moveEvent(self, event):
     settings = QSettings("OCS", self._name)
     settings.setValue("mainWindowGeometry", self.saveGeometry())
 def resizeEvent(self, event):
     settings = QSettings("OCS", "footstep_param_control")
     settings.setValue("mainWindowGeometry", self.saveGeometry())
Example #13
0
 def resizeEvent(self, event):
     settings = QSettings("OCS", "pelvis_pose")
     settings.setValue("mainWindowGeometry", self.saveGeometry())
Example #14
0
 def moveEvent(self, event):
     settings = QSettings("OCS", "position_mode")
     settings.setValue("mainWindowGeometry", self.saveGeometry())
Example #15
0
    def main(self,
             argv=None,
             standalone=None,
             plugin_argument_provider=None,
             plugin_manager_settings_prefix=''):
        if argv is None:
            argv = sys.argv

        # extract --args and everything behind manually since argparse can not handle that
        arguments = argv[1:]

        # extract plugin specific args when not being invoked in standalone mode programmatically
        if not standalone:
            plugin_args = []
            if '--args' in arguments:
                index = arguments.index('--args')
                plugin_args = arguments[index + 1:]
                arguments = arguments[0:index + 1]

        parser = ArgumentParser(os.path.basename(Main.main_filename),
                                add_help=False)
        self.add_arguments(parser,
                           standalone=bool(standalone),
                           plugin_argument_provider=plugin_argument_provider)
        self._options = parser.parse_args(arguments)
        self._options.multi_process = False  # not supported anymore

        if standalone:
            # rerun parsing to separate common arguments from plugin specific arguments
            parser = ArgumentParser(os.path.basename(Main.main_filename),
                                    add_help=False)
            self.add_arguments(parser, standalone=bool(standalone))
            self._options, plugin_args = parser.parse_known_args(arguments)
        self._options.plugin_args = plugin_args

        # set default values for options not available in standalone mode
        if standalone:
            self._options.freeze_layout = False
            self._options.lock_perspective = False
            self._options.hide_title = False
            self._options.perspective = None
            self._options.perspective_file = None
            self._options.standalone_plugin = standalone
            self._options.list_perspectives = False
            self._options.list_plugins = False
            self._options.command_pid = None
            self._options.command_start_plugin = None
            self._options.command_switch_perspective = None
            self._options.embed_plugin = None
            self._options.embed_plugin_serial = None
            self._options.embed_plugin_address = None

        # check option dependencies
        try:
            if self._options.plugin_args and not self._options.standalone_plugin and not self._options.command_start_plugin and not self._options.embed_plugin:
                raise RuntimeError(
                    'Option --args can only be used together with either --standalone, --command-start-plugin or --embed-plugin option'
                )

            if self._options.freeze_layout and not self._options.lock_perspective:
                raise RuntimeError(
                    'Option --freeze_layout can only be used together with the --lock_perspective option'
                )

            list_options = (self._options.list_perspectives,
                            self._options.list_plugins)
            list_options_set = [
                opt for opt in list_options if opt is not False
            ]
            if len(list_options_set) > 1:
                raise RuntimeError(
                    'Only one --list-* option can be used at a time')

            command_options = (self._options.command_start_plugin,
                               self._options.command_switch_perspective)
            command_options_set = [
                opt for opt in command_options if opt is not None
            ]
            if len(command_options_set) > 0 and not self._dbus_available:
                raise RuntimeError(
                    'Without DBus support the --command-* options are not available'
                )
            if len(command_options_set) > 1:
                raise RuntimeError(
                    'Only one --command-* option can be used at a time (except --command-pid which is optional)'
                )
            if len(command_options_set
                   ) == 0 and self._options.command_pid is not None:
                raise RuntimeError(
                    'Option --command_pid can only be used together with an other --command-* option'
                )

            embed_options = (self._options.embed_plugin,
                             self._options.embed_plugin_serial,
                             self._options.embed_plugin_address)
            embed_options_set = [
                opt for opt in embed_options if opt is not None
            ]
            if len(command_options_set) > 0 and not self._dbus_available:
                raise RuntimeError(
                    'Without DBus support the --embed-* options are not available'
                )
            if len(embed_options_set) > 0 and len(embed_options_set) < len(
                    embed_options):
                raise RuntimeError(
                    'Missing option(s) - all \'--embed-*\' options must be set'
                )

            if len(embed_options_set) > 0 and self._options.clear_config:
                raise RuntimeError(
                    'Option --clear-config can only be used without any --embed-* option'
                )

            groups = (list_options_set, command_options_set, embed_options_set)
            groups_set = [opt for opt in groups if len(opt) > 0]
            if len(groups_set) > 1:
                raise RuntimeError(
                    'Options from different groups (--list, --command, --embed) can not be used together'
                )

            perspective_options = (self._options.perspective,
                                   self._options.perspective_file)
            perspective_options_set = [
                opt for opt in perspective_options if opt is not None
            ]
            if len(perspective_options_set) > 1:
                raise RuntimeError(
                    'Only one --perspective-* option can be used at a time')

            if self._options.perspective_file is not None and not os.path.isfile(
                    self._options.perspective_file):
                raise RuntimeError(
                    'Option --perspective-file must reference existing file')

        except RuntimeError as e:
            print(str(e))
            #parser.parse_args(['--help'])
            # calling --help will exit
            return 1

        # set implicit option dependencies
        if self._options.standalone_plugin is not None:
            self._options.lock_perspective = True

        # create application context containing various relevant information
        from .application_context import ApplicationContext
        context = ApplicationContext()
        context.qtgui_path = self._qtgui_path
        context.options = self._options

        if self._dbus_available:
            from dbus import DBusException, Interface, SessionBus

        # non-special applications provide various dbus interfaces
        if self._dbus_available:
            context.provide_app_dbus_interfaces = len(groups_set) == 0
            context.dbus_base_bus_name = 'org.ros.qt_gui'
            if context.provide_app_dbus_interfaces:
                context.dbus_unique_bus_name = context.dbus_base_bus_name + '.pid%d' % os.getpid(
                )

                # provide pid of application via dbus
                from .application_dbus_interface import ApplicationDBusInterface
                _dbus_server = ApplicationDBusInterface(
                    context.dbus_base_bus_name)

        # determine host bus name, either based on pid given on command line or via dbus application interface if any other instance is available
        if len(command_options_set) > 0 or len(embed_options_set) > 0:
            host_pid = None
            if self._options.command_pid is not None:
                host_pid = self._options.command_pid
            else:
                try:
                    remote_object = SessionBus().get_object(
                        context.dbus_base_bus_name, '/Application')
                except DBusException:
                    pass
                else:
                    remote_interface = Interface(
                        remote_object,
                        context.dbus_base_bus_name + '.Application')
                    host_pid = remote_interface.get_pid()
            if host_pid is not None:
                context.dbus_host_bus_name = context.dbus_base_bus_name + '.pid%d' % host_pid

        # execute command on host application instance
        if len(command_options_set) > 0:
            if self._options.command_start_plugin is not None:
                try:
                    remote_object = SessionBus().get_object(
                        context.dbus_host_bus_name, '/PluginManager')
                except DBusException:
                    (rc,
                     msg) = (1,
                             'unable to communicate with GUI instance "%s"' %
                             context.dbus_host_bus_name)
                else:
                    remote_interface = Interface(
                        remote_object,
                        context.dbus_base_bus_name + '.PluginManager')
                    (rc, msg) = remote_interface.start_plugin(
                        self._options.command_start_plugin,
                        ' '.join(self._options.plugin_args))
                if rc == 0:
                    print('qt_gui_main() started plugin "%s" in GUI "%s"' %
                          (msg, context.dbus_host_bus_name))
                else:
                    print(
                        'qt_gui_main() could not start plugin "%s" in GUI "%s": %s'
                        % (self._options.command_start_plugin,
                           context.dbus_host_bus_name, msg))
                return rc
            elif self._options.command_switch_perspective is not None:
                remote_object = SessionBus().get_object(
                    context.dbus_host_bus_name, '/PerspectiveManager')
                remote_interface = Interface(
                    remote_object,
                    context.dbus_base_bus_name + '.PerspectiveManager')
                remote_interface.switch_perspective(
                    self._options.command_switch_perspective)
                print(
                    'qt_gui_main() switched to perspective "%s" in GUI "%s"' %
                    (self._options.command_switch_perspective,
                     context.dbus_host_bus_name))
                return 0
            raise RuntimeError('Unknown command not handled')

        # choose selected or default qt binding
        setattr(sys, 'SELECT_QT_BINDING', self._options.qt_binding)
        from python_qt_binding import QT_BINDING

        from python_qt_binding.QtCore import qDebug, qInstallMessageHandler, QSettings, Qt, QtCriticalMsg, QtDebugMsg, QtFatalMsg, QTimer, QtWarningMsg
        from python_qt_binding.QtGui import QIcon
        from python_qt_binding.QtWidgets import QAction, QMenuBar

        from .about_handler import AboutHandler
        from .composite_plugin_provider import CompositePluginProvider
        from .container_manager import ContainerManager
        from .help_provider import HelpProvider
        from .icon_loader import get_icon
        from .main_window import MainWindow
        from .minimized_dock_widgets_toolbar import MinimizedDockWidgetsToolbar
        from .perspective_manager import PerspectiveManager
        from .plugin_manager import PluginManager

        # TODO PySide2 segfaults when invoking this custom message handler atm
        if QT_BINDING != 'pyside':

            def message_handler(type_, context, msg):
                colored_output = 'TERM' in os.environ and 'ANSI_COLORS_DISABLED' not in os.environ
                cyan_color = '\033[36m' if colored_output else ''
                red_color = '\033[31m' if colored_output else ''
                reset_color = '\033[0m' if colored_output else ''
                if type_ == QtDebugMsg and self._options.verbose:
                    print(msg, file=sys.stderr)
                elif type_ == QtWarningMsg:
                    print(cyan_color + msg + reset_color, file=sys.stderr)
                elif type_ == QtCriticalMsg:
                    print(red_color + msg + reset_color, file=sys.stderr)
                elif type_ == QtFatalMsg:
                    print(red_color + msg + reset_color, file=sys.stderr)
                    sys.exit(1)

            qInstallMessageHandler(message_handler)

        app = self.create_application(argv)

        self._check_icon_theme_compliance()

        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             'ros.org', self._settings_filename)
        if len(embed_options_set) == 0:
            if self._options.clear_config:
                settings.clear()

            main_window = MainWindow()
            if self._options.on_top:
                main_window.setWindowFlags(Qt.WindowStaysOnTopHint)

            main_window.statusBar()

            def sigint_handler(*args):
                qDebug('\nsigint_handler()')
                main_window.close()

            signal.signal(signal.SIGINT, sigint_handler)
            # the timer enables triggering the sigint_handler
            timer = QTimer()
            timer.start(500)
            timer.timeout.connect(lambda: None)

            if not self._options.lock_perspective:
                menu_bar = main_window.menuBar()
                file_menu = menu_bar.addMenu(menu_bar.tr('&File'))
                action = QAction(file_menu.tr('&Quit'), file_menu)
                action.setIcon(QIcon.fromTheme('application-exit'))
                action.triggered.connect(main_window.close)
                file_menu.addAction(action)
            else:
                menu_bar = None

        else:
            app.setQuitOnLastWindowClosed(False)

            main_window = None
            menu_bar = None

        self._add_plugin_providers()

        # setup plugin manager
        plugin_provider = CompositePluginProvider(self.plugin_providers)
        plugin_manager = PluginManager(
            plugin_provider,
            settings,
            context,
            settings_prefix=plugin_manager_settings_prefix)

        if self._options.list_plugins:
            # output available plugins
            print('\n'.join(sorted(plugin_manager.get_plugins().values())))
            return 0

        help_provider = HelpProvider()
        plugin_manager.plugin_help_signal.connect(
            help_provider.plugin_help_request)

        # setup perspective manager
        if main_window is not None:
            perspective_manager = PerspectiveManager(settings, context)

            if self._options.list_perspectives:
                # output available perspectives
                print('\n'.join(sorted(perspective_manager.perspectives)))
                return 0
        else:
            perspective_manager = None

        if main_window is not None:
            container_manager = ContainerManager(main_window, plugin_manager)
            plugin_manager.set_main_window(main_window, menu_bar,
                                           container_manager)

            if not self._options.freeze_layout:
                minimized_dock_widgets_toolbar = MinimizedDockWidgetsToolbar(
                    container_manager, main_window)
                main_window.addToolBar(Qt.BottomToolBarArea,
                                       minimized_dock_widgets_toolbar)
                plugin_manager.set_minimized_dock_widgets_toolbar(
                    minimized_dock_widgets_toolbar)

        if menu_bar is not None:
            perspective_menu = menu_bar.addMenu(menu_bar.tr('P&erspectives'))
            perspective_manager.set_menu(perspective_menu)

        # connect various signals and slots
        if perspective_manager is not None and main_window is not None:
            # signal changed perspective to update window title
            perspective_manager.perspective_changed_signal.connect(
                main_window.perspective_changed)
            # signal new settings due to changed perspective
            perspective_manager.save_settings_signal.connect(
                main_window.save_settings)
            perspective_manager.restore_settings_signal.connect(
                main_window.restore_settings)
            perspective_manager.restore_settings_without_plugin_changes_signal.connect(
                main_window.restore_settings)

        if perspective_manager is not None and plugin_manager is not None:
            perspective_manager.save_settings_signal.connect(
                plugin_manager.save_settings)
            plugin_manager.save_settings_completed_signal.connect(
                perspective_manager.save_settings_completed)
            perspective_manager.restore_settings_signal.connect(
                plugin_manager.restore_settings)
            perspective_manager.restore_settings_without_plugin_changes_signal.connect(
                plugin_manager.restore_settings_without_plugins)

        if plugin_manager is not None and main_window is not None:
            # signal before changing plugins to save window state
            plugin_manager.plugins_about_to_change_signal.connect(
                main_window.save_setup)
            # signal changed plugins to restore window state
            plugin_manager.plugins_changed_signal.connect(
                main_window.restore_state)
            # signal save settings to store plugin setup on close
            main_window.save_settings_before_close_signal.connect(
                plugin_manager.close_application)
            # signal save and shutdown called for all plugins, trigger closing main window again
            plugin_manager.close_application_signal.connect(
                main_window.close, type=Qt.QueuedConnection)

        if main_window is not None and menu_bar is not None:
            about_handler = AboutHandler(context.qtgui_path, main_window)
            help_menu = menu_bar.addMenu(menu_bar.tr('&Help'))
            action = QAction(help_menu.tr('&About'), help_menu)
            action.setIcon(QIcon.fromTheme('help-about'))
            action.triggered.connect(about_handler.show)
            help_menu.addAction(action)

        # set initial size - only used without saved configuration
        if main_window is not None:
            main_window.resize(600, 450)
            main_window.move(100, 100)

        # ensure that qt_gui/src is in sys.path
        src_path = os.path.realpath(
            os.path.join(os.path.dirname(__file__), '..'))
        if src_path not in sys.path:
            sys.path.append(src_path)

        # load specific plugin
        plugin = None
        plugin_serial = None
        if self._options.embed_plugin is not None:
            plugin = self._options.embed_plugin
            plugin_serial = self._options.embed_plugin_serial
        elif self._options.standalone_plugin is not None:
            plugin = self._options.standalone_plugin
            plugin_serial = 0
        if plugin is not None:
            plugins = plugin_manager.find_plugins_by_name(plugin)
            if len(plugins) == 0:
                print('qt_gui_main() found no plugin matching "%s"' % plugin)
                print('try passing the option "--force-discover"')
                return 1
            elif len(plugins) > 1:
                print(
                    'qt_gui_main() found multiple plugins matching "%s"\n%s' %
                    (plugin, '\n'.join(plugins.values())))
                return 1
            plugin = list(plugins.keys())[0]

        qDebug('QtBindingHelper using %s' % QT_BINDING)

        plugin_manager.discover()

        if self._options.reload_import:
            qDebug(
                'ReloadImporter() automatically reload all subsequent imports')
            from .reload_importer import ReloadImporter
            _reload_importer = ReloadImporter()
            self._add_reload_paths(_reload_importer)
            _reload_importer.enable()

        # switch perspective
        if perspective_manager is not None:
            if plugin:
                perspective_manager.set_perspective(
                    plugin, hide_and_without_plugin_changes=True)
            elif self._options.perspective_file:
                perspective_manager.import_perspective_from_file(
                    self._options.perspective_file,
                    perspective_manager.HIDDEN_PREFIX +
                    os.path.basename(self._options.perspective_file))
            else:
                perspective_manager.set_perspective(self._options.perspective)

        # load specific plugin
        if plugin:
            plugin_manager.load_plugin(plugin, plugin_serial,
                                       self._options.plugin_args)
            running = plugin_manager.is_plugin_running(plugin, plugin_serial)
            if not running:
                return 1
            if self._options.standalone_plugin:
                # use icon of standalone plugin (if available) for application
                plugin_descriptor = plugin_manager.get_plugin_descriptor(
                    plugin)
                action_attributes = plugin_descriptor.action_attributes()
                if 'icon' in action_attributes and action_attributes[
                        'icon'] is not None:
                    base_path = plugin_descriptor.attributes().get(
                        'plugin_path')
                    try:
                        icon = get_icon(
                            action_attributes['icon'],
                            action_attributes.get('icontype', None), base_path)
                    except UserWarning:
                        pass
                    else:
                        app.setWindowIcon(icon)

        if main_window is not None:
            main_window.show()
            if sys.platform == 'darwin':
                main_window.raise_()

        return app.exec_()
Example #16
0
    def main(self, argv=None, standalone=None, plugin_argument_provider=None, plugin_manager_settings_prefix=''):
        if argv is None:
            argv = sys.argv

        # extract --args and everything behind manually since argparse can not handle that
        arguments = argv[1:]

        # extract plugin specific args when not being invoked in standalone mode programmatically
        if not standalone:
            plugin_args = []
            if '--args' in arguments:
                index = arguments.index('--args')
                plugin_args = arguments[index + 1:]
                arguments = arguments[0:index + 1]

        parser = ArgumentParser(os.path.basename(Main.main_filename), add_help=False)
        self.add_arguments(parser, standalone=bool(standalone), plugin_argument_provider=plugin_argument_provider)
        self._options = parser.parse_args(arguments)

        if standalone:
            # rerun parsing to separate common arguments from plugin specific arguments
            parser = ArgumentParser(os.path.basename(Main.main_filename), add_help=False)
            self.add_arguments(parser, standalone=bool(standalone))
            self._options, plugin_args = parser.parse_known_args(arguments)
        self._options.plugin_args = plugin_args

        # set default values for options not available in standalone mode
        if standalone:
            self._options.freeze_layout = False
            self._options.lock_perspective = False
            self._options.multi_process = False
            self._options.perspective = None
            self._options.perspective_file = None
            self._options.standalone_plugin = standalone
            self._options.list_perspectives = False
            self._options.list_plugins = False
            self._options.command_pid = None
            self._options.command_start_plugin = None
            self._options.command_switch_perspective = None
            self._options.embed_plugin = None
            self._options.embed_plugin_serial = None
            self._options.embed_plugin_address = None

        # check option dependencies
        try:
            if self._options.plugin_args and not self._options.standalone_plugin and not self._options.command_start_plugin and not self._options.embed_plugin:
                raise RuntimeError('Option --args can only be used together with either --standalone, --command-start-plugin or --embed-plugin option')

            if self._options.freeze_layout and not self._options.lock_perspective:
                raise RuntimeError('Option --freeze_layout can only be used together with the --lock_perspective option')

            list_options = (self._options.list_perspectives, self._options.list_plugins)
            list_options_set = [opt for opt in list_options if opt is not False]
            if len(list_options_set) > 1:
                raise RuntimeError('Only one --list-* option can be used at a time')

            command_options = (self._options.command_start_plugin, self._options.command_switch_perspective)
            command_options_set = [opt for opt in command_options if opt is not None]
            if len(command_options_set) > 0 and not self._dbus_available:
                raise RuntimeError('Without DBus support the --command-* options are not available')
            if len(command_options_set) > 1:
                raise RuntimeError('Only one --command-* option can be used at a time (except --command-pid which is optional)')
            if len(command_options_set) == 0 and self._options.command_pid is not None:
                raise RuntimeError('Option --command_pid can only be used together with an other --command-* option')

            embed_options = (self._options.embed_plugin, self._options.embed_plugin_serial, self._options.embed_plugin_address)
            embed_options_set = [opt for opt in embed_options if opt is not None]
            if len(command_options_set) > 0 and not self._dbus_available:
                raise RuntimeError('Without DBus support the --embed-* options are not available')
            if len(embed_options_set) > 0 and len(embed_options_set) < len(embed_options):
                raise RuntimeError('Missing option(s) - all \'--embed-*\' options must be set')

            if len(embed_options_set) > 0 and self._options.clear_config:
                raise RuntimeError('Option --clear-config can only be used without any --embed-* option')

            groups = (list_options_set, command_options_set, embed_options_set)
            groups_set = [opt for opt in groups if len(opt) > 0]
            if len(groups_set) > 1:
                raise RuntimeError('Options from different groups (--list, --command, --embed) can not be used together')

            perspective_options = (self._options.perspective, self._options.perspective_file)
            perspective_options_set = [opt for opt in perspective_options if opt is not None]
            if len(perspective_options_set) > 1:
                raise RuntimeError('Only one --perspective-* option can be used at a time')

            if self._options.perspective_file is not None and not os.path.isfile(self._options.perspective_file):
                raise RuntimeError('Option --perspective-file must reference existing file')

        except RuntimeError as e:
            print(str(e))
            #parser.parse_args(['--help'])
            # calling --help will exit
            return 1

        # set implicit option dependencies
        if self._options.standalone_plugin is not None:
            self._options.lock_perspective = True

        # create application context containing various relevant information
        from .application_context import ApplicationContext
        context = ApplicationContext()
        context.qtgui_path = self._qtgui_path
        context.options = self._options

        if self._dbus_available:
            from dbus import DBusException, Interface, SessionBus

        # non-special applications provide various dbus interfaces
        if self._dbus_available:
            context.provide_app_dbus_interfaces = len(groups_set) == 0
            context.dbus_base_bus_name = 'org.ros.qt_gui'
            if context.provide_app_dbus_interfaces:
                context.dbus_unique_bus_name = context.dbus_base_bus_name + '.pid%d' % os.getpid()

                # provide pid of application via dbus
                from .application_dbus_interface import ApplicationDBusInterface
                _dbus_server = ApplicationDBusInterface(context.dbus_base_bus_name)

        # determine host bus name, either based on pid given on command line or via dbus application interface if any other instance is available
        if len(command_options_set) > 0 or len(embed_options_set) > 0:
            host_pid = None
            if self._options.command_pid is not None:
                host_pid = self._options.command_pid
            else:
                try:
                    remote_object = SessionBus().get_object(context.dbus_base_bus_name, '/Application')
                except DBusException:
                    pass
                else:
                    remote_interface = Interface(remote_object, context.dbus_base_bus_name + '.Application')
                    host_pid = remote_interface.get_pid()
            if host_pid is not None:
                context.dbus_host_bus_name = context.dbus_base_bus_name + '.pid%d' % host_pid

        # execute command on host application instance
        if len(command_options_set) > 0:
            if self._options.command_start_plugin is not None:
                try:
                    remote_object = SessionBus().get_object(context.dbus_host_bus_name, '/PluginManager')
                except DBusException:
                    (rc, msg) = (1, 'unable to communicate with GUI instance "%s"' % context.dbus_host_bus_name)
                else:
                    remote_interface = Interface(remote_object, context.dbus_base_bus_name + '.PluginManager')
                    (rc, msg) = remote_interface.start_plugin(self._options.command_start_plugin, ' '.join(self._options.plugin_args))
                if rc == 0:
                    print('qt_gui_main() started plugin "%s" in GUI "%s"' % (msg, context.dbus_host_bus_name))
                else:
                    print('qt_gui_main() could not start plugin "%s" in GUI "%s": %s' % (self._options.command_start_plugin, context.dbus_host_bus_name, msg))
                return rc
            elif self._options.command_switch_perspective is not None:
                remote_object = SessionBus().get_object(context.dbus_host_bus_name, '/PerspectiveManager')
                remote_interface = Interface(remote_object, context.dbus_base_bus_name + '.PerspectiveManager')
                remote_interface.switch_perspective(self._options.command_switch_perspective)
                print('qt_gui_main() switched to perspective "%s" in GUI "%s"' % (self._options.command_switch_perspective, context.dbus_host_bus_name))
                return 0
            raise RuntimeError('Unknown command not handled')

        # choose selected or default qt binding
        setattr(sys, 'SELECT_QT_BINDING', self._options.qt_binding)
        from python_qt_binding import QT_BINDING

        from python_qt_binding.QtCore import qDebug, qInstallMsgHandler, QSettings, Qt, QtCriticalMsg, QtDebugMsg, QtFatalMsg, QTimer, QtWarningMsg
        from python_qt_binding.QtGui import QAction, QIcon, QMenuBar

        from .about_handler import AboutHandler
        from .composite_plugin_provider import CompositePluginProvider
        from .container_manager import ContainerManager
        from .help_provider import HelpProvider
        from .icon_loader import get_icon
        from .main_window import MainWindow
        from .minimized_dock_widgets_toolbar import MinimizedDockWidgetsToolbar
        from .perspective_manager import PerspectiveManager
        from .plugin_manager import PluginManager

        def message_handler(type_, msg):
            colored_output = 'TERM' in os.environ and 'ANSI_COLORS_DISABLED' not in os.environ
            cyan_color = '\033[36m' if colored_output else ''
            red_color = '\033[31m' if colored_output else ''
            reset_color = '\033[0m' if colored_output else ''
            if type_ == QtDebugMsg and self._options.verbose:
                print(msg, file=sys.stderr)
            elif type_ == QtWarningMsg:
                print(cyan_color + msg + reset_color, file=sys.stderr)
            elif type_ == QtCriticalMsg:
                print(red_color + msg + reset_color, file=sys.stderr)
            elif type_ == QtFatalMsg:
                print(red_color + msg + reset_color, file=sys.stderr)
                sys.exit(1)
        qInstallMsgHandler(message_handler)

        app = self.create_application(argv)

        self._check_icon_theme_compliance()

        settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'ros.org', self._settings_filename)
        if len(embed_options_set) == 0:
            if self._options.clear_config:
                settings.clear()

            main_window = MainWindow()
            if self._options.on_top:
                main_window.setWindowFlags(Qt.WindowStaysOnTopHint)

            main_window.statusBar()

            def sigint_handler(*args):
                qDebug('\nsigint_handler()')
                main_window.close()
            signal.signal(signal.SIGINT, sigint_handler)
            # the timer enables triggering the sigint_handler
            timer = QTimer()
            timer.start(500)
            timer.timeout.connect(lambda: None)

            # create own menu bar to share one menu bar on Mac
            menu_bar = QMenuBar()
            if 'darwin' in platform.platform().lower():
                menu_bar.setNativeMenuBar(True)
            else:
                menu_bar.setNativeMenuBar(False)
            if not self._options.lock_perspective:
                main_window.setMenuBar(menu_bar)

            file_menu = menu_bar.addMenu(menu_bar.tr('&File'))
            action = QAction(file_menu.tr('&Quit'), file_menu)
            action.setIcon(QIcon.fromTheme('application-exit'))
            action.triggered.connect(main_window.close)
            file_menu.addAction(action)

        else:
            app.setQuitOnLastWindowClosed(False)

            main_window = None
            menu_bar = None

        self._add_plugin_providers()

        # setup plugin manager
        plugin_provider = CompositePluginProvider(self.plugin_providers)
        plugin_manager = PluginManager(plugin_provider, settings, context, settings_prefix=plugin_manager_settings_prefix)

        if self._options.list_plugins:
            # output available plugins
            print('\n'.join(sorted(plugin_manager.get_plugins().values())))
            return 0

        help_provider = HelpProvider()
        plugin_manager.plugin_help_signal.connect(help_provider.plugin_help_request)

        # setup perspective manager
        if main_window is not None:
            perspective_manager = PerspectiveManager(settings, context)

            if self._options.list_perspectives:
                # output available perspectives
                print('\n'.join(sorted(perspective_manager.perspectives)))
                return 0
        else:
            perspective_manager = None

        if main_window is not None:
            container_manager = ContainerManager(main_window, plugin_manager)
            plugin_manager.set_main_window(main_window, menu_bar, container_manager)

            if not self._options.freeze_layout:
                minimized_dock_widgets_toolbar = MinimizedDockWidgetsToolbar(container_manager, main_window)
                main_window.addToolBar(Qt.BottomToolBarArea, minimized_dock_widgets_toolbar)
                plugin_manager.set_minimized_dock_widgets_toolbar(minimized_dock_widgets_toolbar)

        if menu_bar is not None:
            perspective_menu = menu_bar.addMenu(menu_bar.tr('P&erspectives'))
            perspective_manager.set_menu(perspective_menu)

        # connect various signals and slots
        if perspective_manager is not None and main_window is not None:
            # signal changed perspective to update window title
            perspective_manager.perspective_changed_signal.connect(main_window.perspective_changed)
            # signal new settings due to changed perspective
            perspective_manager.save_settings_signal.connect(main_window.save_settings)
            perspective_manager.restore_settings_signal.connect(main_window.restore_settings)
            perspective_manager.restore_settings_without_plugin_changes_signal.connect(main_window.restore_settings)

        if perspective_manager is not None and plugin_manager is not None:
            perspective_manager.save_settings_signal.connect(plugin_manager.save_settings)
            plugin_manager.save_settings_completed_signal.connect(perspective_manager.save_settings_completed)
            perspective_manager.restore_settings_signal.connect(plugin_manager.restore_settings)
            perspective_manager.restore_settings_without_plugin_changes_signal.connect(plugin_manager.restore_settings_without_plugins)

        if plugin_manager is not None and main_window is not None:
            # signal before changing plugins to save window state
            plugin_manager.plugins_about_to_change_signal.connect(main_window.save_setup)
            # signal changed plugins to restore window state
            plugin_manager.plugins_changed_signal.connect(main_window.restore_state)
            # signal save settings to store plugin setup on close
            main_window.save_settings_before_close_signal.connect(plugin_manager.close_application)
            # signal save and shutdown called for all plugins, trigger closing main window again
            plugin_manager.close_application_signal.connect(main_window.close, type=Qt.QueuedConnection)

        if main_window is not None and menu_bar is not None:
            about_handler = AboutHandler(context.qtgui_path, main_window)
            help_menu = menu_bar.addMenu(menu_bar.tr('&Help'))
            action = QAction(file_menu.tr('&About'), help_menu)
            action.setIcon(QIcon.fromTheme('help-about'))
            action.triggered.connect(about_handler.show)
            help_menu.addAction(action)

        # set initial size - only used without saved configuration
        if main_window is not None:
            main_window.resize(600, 450)
            main_window.move(100, 100)

        # ensure that qt_gui/src is in sys.path
        src_path = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
        if src_path not in sys.path:
            sys.path.append(src_path)

        # load specific plugin
        plugin = None
        plugin_serial = None
        if self._options.embed_plugin is not None:
            plugin = self._options.embed_plugin
            plugin_serial = self._options.embed_plugin_serial
        elif self._options.standalone_plugin is not None:
            plugin = self._options.standalone_plugin
            plugin_serial = 0
        if plugin is not None:
            plugins = plugin_manager.find_plugins_by_name(plugin)
            if len(plugins) == 0:
                print('qt_gui_main() found no plugin matching "%s"' % plugin)
                return 1
            elif len(plugins) > 1:
                print('qt_gui_main() found multiple plugins matching "%s"\n%s' % (plugin, '\n'.join(plugins.values())))
                return 1
            plugin = plugins.keys()[0]

        qDebug('QtBindingHelper using %s' % QT_BINDING)

        plugin_manager.discover()

        if self._options.reload_import:
            qDebug('ReloadImporter() automatically reload all subsequent imports')
            from .reload_importer import ReloadImporter
            _reload_importer = ReloadImporter()
            self._add_reload_paths(_reload_importer)
            _reload_importer.enable()

        # switch perspective
        if perspective_manager is not None:
            if plugin:
                perspective_manager.set_perspective(plugin, hide_and_without_plugin_changes=True)
            elif self._options.perspective_file:
                perspective_manager.import_perspective_from_file(self._options.perspective_file, perspective_manager.HIDDEN_PREFIX + '__cli_perspective_from_file')
            else:
                perspective_manager.set_perspective(self._options.perspective)

        # load specific plugin
        if plugin:
            plugin_manager.load_plugin(plugin, plugin_serial, self._options.plugin_args)
            running = plugin_manager.is_plugin_running(plugin, plugin_serial)
            if not running:
                return 1
            if self._options.standalone_plugin:
                # use icon of standalone plugin (if available) for application
                plugin_descriptor = plugin_manager.get_plugin_descriptor(plugin)
                action_attributes = plugin_descriptor.action_attributes()
                if 'icon' in action_attributes and action_attributes['icon'] is not None:
                    base_path = plugin_descriptor.attributes().get('plugin_path')
                    try:
                        icon = get_icon(action_attributes['icon'], action_attributes.get('icontype', None), base_path)
                    except UserWarning:
                        pass
                    else:
                        app.setWindowIcon(icon)

        if main_window is not None:
            main_window.show()
            if sys.platform == 'darwin':
                main_window.raise_()

        return app.exec_()
Example #17
0
class RqtLgsvlSimulatorConfiguratorPlugin(Plugin):

    def __init__(self, context):
        super(RqtLgsvlSimulatorConfiguratorPlugin, self).__init__(context)
        rospack = rospkg.RosPack()
        self.settings = QSettings(rospack.get_path('lgsvl_simulator_bridge')+"/config/setting.dat",QSettings.IniFormat)
        # Give QObjects reasonable names
        self.setObjectName('RqtLgsvlSimulatorConfiguratorPlugin')

        # 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('lgsvl_simulator_bridge'), 'resource', 'LgsvlSimulatorConfigratorPlugin.ui')
        # Extend the widget with all atrributes and children from UI File
        loadUi(ui_file, self._widget)
        # Give QObjects reasonable names
        self._widget.setObjectName('RqtLgsvlSimulatorConfiguratorPluginUi')
        # Show _widget.windowTitle on left-top of each plugin(when it's set in _widget).
        # This is useful when you open multiple plugins aat once. Also if you open multiple
        # instances of your plugin at once, these lines add number to make it easy to
        # tell from pane to pane.
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() + (' %d' % context.serial_number()))
        # Add widget to the user interface
        self.settings.beginGroup("simulator_params")
        context.add_widget(self._widget)
        ip = self.settings.value('ip')
        if ip != None:
            self._widget.ip_box.setText(ip)
        port = self.settings.value('port')
        if port != None:
            self._widget.port_box.setText(port)
        config_path = self.settings.value('config_path')
        if config_path != None:
            self._widget.configpath_box.setText(config_path)
        self.settings.endGroup()
        self.json_dict = {}
        self.instance_id = ""
        self.is_remote = False
        self._widget.button_config_ref.clicked[bool].connect(self._handle_config_ref_button_clicked)
        self._widget.button_config.clicked[bool].connect(self._handle_config_button_clicked)
        self._widget.launch_button.clicked[bool].connect(self._handle_launch_button_clicked)
        self._widget.terminate_button.clicked[bool].connect(self._handle_terminate_button_clicked)

    def shutdown_plugin(self):
        # TODO unregister all publishers here
        pass

    def save_settings(self, plugin_settings, instance_settings):
        # TODO save intrinsic configuration, usually using:
        # instance_settings.get_value(k, v)
        pass

    def restore_settings(self, pluign_settings, instance_settings):
        # TODO restore intrinsic configuration, usually using:
        # v = instance_settings.value(k)
        pass

    def _handle_launch_button_clicked(self):
        if str(self._widget.ip_box.text()) == "localhost" or str(self._widget.ip_box.text()) == "0.0.0.0" or str(self._widget.ip_box.text()) == "127.0.0.1":
            cmd = ["roslaunch","lgsvl_simulator_bridge","lgsvl_simulator.launch"]
            self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
            self._widget.launch_button.setStyleSheet("background-color: #8fb8e0")
            self._widget.terminate_button.setStyleSheet("background-color: #FFFFFF")
            self.is_remote = False
            return
        else:
            cmd = ["roslaunch","lgsvl_simulator_bridge","bridge.launch"]
            self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)            
        address = "http://" + self._widget.ip_box.text() + ":" + self._widget.port_box.text()+"/simulator/launch"
        self.settings.beginGroup("simulator_params")
        self.settings.setValue("ip", self._widget.ip_box.text())
        self.settings.setValue("port", self._widget.port_box.text())
        self.settings.endGroup()
        try:
            response = requests.post(address,json=self.json_dict)
            self.instance_id = response.json()[u'instance_id']
        except:
            self._widget.launch_button.setStyleSheet("background-color: #F5A9A9")
            return
        self.is_remote = False
        self._widget.launch_button.setStyleSheet("background-color: #8fb8e0")
        self._widget.terminate_button.setStyleSheet("background-color: #FFFFFF")

    def _handle_config_ref_button_clicked(self):
        rospack = rospkg.RosPack()
        fname = QFileDialog.getOpenFileName(self._widget, 'Open file', rospack.get_path('lgsvl_simulator_bridge')+'/config')
        self._widget.configpath_box.setText(fname[0])

    def _handle_config_button_clicked(self):
        path = self._widget.configpath_box.text()
        try:
            f = open(path, "r+")
            self.json_dict = json.load(f)
            self.settings.beginGroup("simulator_params")
            self.settings.setValue("config_path", path)
            self.settings.endGroup()
        except:
            self._widget.button_config.setStyleSheet("background-color: #F5A9A9")
            return
        self._widget.button_config.setStyleSheet("background-color: #8fb8e0")

    def _handle_terminate_button_clicked(self):
        address = "http://" + self._widget.ip_box.text() + ":" + self._widget.port_box.text()+"/simulator/terminate"
        self.settings.beginGroup("simulator_params")
        self.settings.setValue("ip", self._widget.ip_box.text())
        self.settings.setValue("port", self._widget.port_box.text())
        self.settings.endGroup()
        if self.instance_id == "" and self.is_remote == True:
            return
        if self.is_remote == True:
            try:
                response = requests.post(address,json={u'instance_id':self.instance_id})    
            except:
                self._widget.terminate_button.setStyleSheet("background-color: #F5A9A9")
                return
        try:
            self.proc.terminate()
        except:
            self._widget.terminate_button.setStyleSheet("background-color: #F5A9A9")
            return            
        self._widget.terminate_button.setStyleSheet("background-color: #8fb8e0")
        self._widget.launch_button.setStyleSheet("background-color: #FFFFFF")
class AnnotatorWidget(QWidget):
    """
    Annotator tool viewer
    """
    #name = 'Annotator'
    set_status_text = Signal(str)

    def __init__(self, context, bag_widget, publish_clock):
        super(AnnotatorWidget, self).__init__()
        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('rqt_bag_meri_annotator'),
                               'resource', 'MeriPlugin.ui')
        loadUi(ui_file, self, {'AnnotatorGraphicsView': AnnotatorGraphicsView})
        self.setObjectName('AnnotatorWidget')
        self.setMouseTracking(True)
        self.annotation_data = list()
        self.interaction_time = 120.0

        self.bag_widget = bag_widget
        self.bagtimeline = self.bag_widget._timeline
        self._child_index = 0
        self.settings = QSettings("UFES", "MERI Annotator Widget")
        #self.settings.setValue("Last_child_index",self._child_index)

        self.instance = vlc.Instance()
        self.mediaplayer = self.instance.media_player_new()
        self.isPaused = False
        self.msgBox = QMessageBox()
        self.msgBox.setIcon(QMessageBox.Information)
        self.msgBox.setWindowTitle('Annotator Interface Information')
        self.msgBox.setStandardButtons(QMessageBox.Ok)

        self.BtnSaveJson.clicked.connect(self.BtnSaveJsonClicked)
        self.BtnLoadJson.clicked.connect(self.BtnLoadJsonClicked)
        self.BtnNext.clicked.connect(self.BtnNextClicked)
        self.BtnSetupBag.clicked.connect(self.BtnSetupBagClicked)
        self.BtnPrevious.clicked.connect(self.BtnPreviousClicked)
        self.BtnZero.clicked.connect(self.BtnZeroClicked)
        self.BtnOne.clicked.connect(self.BtnOneClicked)
        self.BtnTwo.clicked.connect(self.BtnTwoClicked)
        self.BtnAimLess.clicked.connect(self.BtnAimLessClicked)
        self.BtnGoalOriented.clicked.connect(self.BtnGoalOrientedClicked)
        self.BtnRobotStarted.clicked.connect(self.BtnRobotStartedClicked)
        self.BtnPointing.clicked.connect(self.BtnPointingClicked)
        self.BtnFollowLor.clicked.connect(self.BtnFollowLorClicked)
        self.BtnAdultSeek.clicked.connect(self.BtnAdultSeekClicked)
        self.BtnECTwC.clicked.connect(self.BtnECTwCClicked)
        self.BtnECTwR.clicked.connect(self.BtnECTwRClicked)
        self.BtnECTwT.clicked.connect(self.BtnECTwTClicked)
        self.BtnPlay.clicked.connect(self.BtnPlayClicked)
        self.BtnPause.clicked.connect(self.BtnPauseClicked)
        self.BtnStop.clicked.connect(self.BtnStopClicked)

        self.BtnPlay.setIcon(QIcon.fromTheme('media-playback-start'))
        self.BtnPause.setIcon(QIcon.fromTheme('media-playback-pause'))
        self.BtnLoadJson.setIcon(QIcon.fromTheme('document-open'))
        self.BtnSaveJson.setIcon(QIcon.fromTheme('document-save'))
        self.BtnStop.setIcon(QIcon.fromTheme('media-playback-stop'))
        self.BtnNext.setIcon(QIcon.fromTheme('go-next'))
        self.BtnSetupBag.setIcon(QIcon.fromTheme('document-properties'))
        self.BtnPrevious.setIcon(QIcon.fromTheme('go-previous'))

    def BtnSaveJsonClicked(self):
        if self.SpecialistName.text() == "":
            self.msgBox.setText(
                'Please register your name in the <html><b> Specialist_Name </b></html> box'
            )
            retval = self.msgBox.exec_()
        else:
            if len(self.annotation_data) == 0:
                self.msgBox.setText('No annotation has been recorded')
                retval = self.msgBox.exec_()
            else:
                annotationfile = [
                    self.SpecialistName.text() + "_annotation_" +
                    self._child_data[self._child_index]['ID'] + ".json"
                ]
                annotationfile_path = os.path.join(os.path.expanduser('~'),
                                                   'Documents',
                                                   'Annotation_files',
                                                   annotationfile[0])
                if os.path.exists(annotationfile_path):
                    self.msgBox.setText(
                        '<html><b>' + self.SpecialistName.text() +
                        '</b></html> already recorder annotations for child: <html><b>'
                        + self._child_data[self._child_index]['ID'] +
                        '</b></html>')
                    retval = self.msgBox.exec_()
                else:
                    with open(annotationfile_path, "w") as write_file:
                        json.dump(self.annotation_data, write_file)
                    self.msgBox.setText('Annotation File:  <html><b>' +
                                        annotationfile[0] +
                                        '</b></html> Saved!')
                    retval = self.msgBox.exec_()

    def BtnLoadJsonClicked(self):
        self._child_data = None
        json_path = self.settings.value("Last_path")
        if json_path == "":
            json_path = os.path.join(os.path.expanduser('~'), 'Documents')
        json_file = QFileDialog.getOpenFileName(self, "Open JSON File",
                                                json_path)
        self.settings.setValue("Last_path", json_file[0])
        with open(json_file[0]) as f:
            self._child_data = json.load(f)
        if self.settings.value("Last_child_index") is not None:
            self._child_index = int(self.settings.value("Last_child_index"))
        if self._child_index > len(self._child_data) - 1:
            self._child_index = 0
        self.LineChildId.setText(self._child_data[self._child_index]['ID'])
        self.msgBox.setText('Json Data of <html><b>' +
                            str(len(self._child_data)) +
                            '</b></html> Children were loaded')
        retval = self.msgBox.exec_()

    def BtnNextClicked(self):
        if self._child_index < len(self._child_data) - 1:
            self._child_index = self._child_index + 1
            self.LineChildId.setText(self._child_data[self._child_index]['ID'])
            self.settings.setValue("Last_child_index", self._child_index)

    def BtnPreviousClicked(self):
        if self._child_index > 0:
            self._child_index = self._child_index - 1
            self.LineChildId.setText(self._child_data[self._child_index]['ID'])
            self.settings.setValue("Last_child_index", self._child_index)

    def BtnSetupBagClicked(self):
        kinect2_a_bag_name = 'image_kinect2_a_' + self._child_data[
            self._child_index]['Kinect_a']
        kinect2_b_bag_name = 'image_kinect2_b_' + self._child_data[
            self._child_index]['Kinect_b']
        focus_bag_name = 'focus_data_' + self._child_data[
            self._child_index]['Focus']

        k2a_bag_file = os.path.join(os.path.expanduser('~'), "Documents",
                                    "hg_rosbag", "test_files",
                                    kinect2_a_bag_name)
        k2b_bag_file = os.path.join(os.path.expanduser('~'), "Documents",
                                    "hg_rosbag", "test_files",
                                    kinect2_b_bag_name)
        focus_bag_file = os.path.join(os.path.expanduser('~'), "Documents",
                                      "hg_rosbag", "test_files",
                                      focus_bag_name)

        self.bag_widget.load_bag(k2a_bag_file)
        self.bag_widget.load_bag(k2b_bag_file)
        #self.bag_widget.load_bag(focus_bag_file)

        audio_file_name = self._child_data[
            self._child_index]['Picture(jpg)/Audio(mp3)'] + '.mp3'
        audio_media_file = os.path.join(os.path.expanduser('~'), "Documents",
                                        "hg_rosbag", "audios", audio_file_name)
        self.OpenAudioMedia(audio_media_file)

        if self.checkCutBag.isChecked() == True:
            last_path = self.settings.value("Last_path")
            acronym_file = last_path[len(last_path) - 9:len(last_path) - 5]
            if acronym_file[0] == "s":
                config_name = ["cwa" + acronym_file + "_rs.json"]
            elif acronym_file[0] == "o":
                config_name = ["cw" + acronym_file + "_rs.json"]
            config_path = os.path.join(os.path.expanduser('~'), 'Documents',
                                       config_name[0])
            with open(config_path) as f:
                bag_config = json.load(f)

            if float(bag_config[self._child_index]
                     ['Sec']) > self.interaction_time:
                self.bagtimeline._timeline_frame._start_stamp = self.bagtimeline._timeline_frame._start_stamp + rospy.Duration.from_sec(
                    float(bag_config[self._child_index]['Sec']) -
                    self.interaction_time)
                self.annotation_data.append({
                    'key': 'Robot Started',
                    'time_stamp': 0,
                    'Sec': self.interaction_time
                })
            else:
                self.annotation_data.append({
                    'key':
                    'Robot Started',
                    'time_stamp':
                    0,
                    'Sec':
                    float(bag_config[self._child_index]['Sec'])
                })
            if (self.bagtimeline._timeline_frame._end_stamp -
                    self.bagtimeline._timeline_frame._start_stamp
                ) > rospy.Duration.from_sec(self.interaction_time * 2):
                self.bagtimeline._timeline_frame._end_stamp = self.bagtimeline._timeline_frame._start_stamp + rospy.Duration.from_sec(
                    self.interaction_time * 2)

    def BtnZeroClicked(self):
        task = self.ComBoxTask.currentText() + " 0 pts"
        self.AnnotationYamlCreator(task)

    def BtnOneClicked(self):
        task = self.ComBoxTask.currentText() + " 1 pts"
        self.AnnotationYamlCreator(task)

    def BtnTwoClicked(self):
        task = self.ComBoxTask.currentText() + " 2 pts"
        self.AnnotationYamlCreator(task)

    def BtnAimLessClicked(self):
        self.AnnotationYamlCreator('AimLess')

    def BtnGoalOrientedClicked(self):
        self.AnnotationYamlCreator('Goal Oriented')

    def BtnRobotStartedClicked(self):
        self.AnnotationYamlCreator('Robot Started')

    def BtnPointingClicked(self):
        self.AnnotationYamlCreator('Pointing')

    def BtnFollowLorClicked(self):
        self.AnnotationYamlCreator('Following LoR')

    def BtnAdultSeekClicked(self):
        self.AnnotationYamlCreator('AdultSeek')

    def BtnECTwCClicked(self):
        self.AnnotationYamlCreator('Eye Contact TwC')

    def BtnECTwRClicked(self):
        self.AnnotationYamlCreator('Eye Contact TwR')

    def BtnECTwTClicked(self):
        self.AnnotationYamlCreator('Eye Contact TwT')

    def BtnPlayClicked(self):
        self.bag_widget.play_button.setChecked(True)
        self.bag_widget.play_button.setIcon(self.bag_widget.pause_icon)
        self.bagtimeline.navigate_play()
        self.mediaplayer.play()

    def BtnPauseClicked(self):
        self.bag_widget.play_button.setChecked(False)
        self.bag_widget.play_button.setIcon(self.bag_widget.play_icon)
        self.bagtimeline.navigate_stop()
        self.mediaplayer.pause()

    def BtnStopClicked(self):
        self.bag_widget.play_button.setChecked(False)
        self.bag_widget.play_button.setIcon(self.bag_widget.play_icon)
        self.bagtimeline.navigate_stop()
        self.bagtimeline.navigate_start()
        self.mediaplayer.stop()

    def AnnotationYamlCreator(self, Annotation):
        playhead_time = self.bagtimeline._timeline_frame.playhead
        self.annotation_data.append({
            'key':
            Annotation,
            'time_stamp':
            playhead_time.to_nsec(),
            'Sec': (playhead_time -
                    self.bagtimeline._timeline_frame.start_stamp).to_sec()
        })

    def OpenAudioMedia(self, filename=None):
        """Open a media file in a MediaPlayer
          """
        self.media = self.instance.media_new(filename)
        # put the media in the media player
        self.mediaplayer.set_media(self.media)

    def shutdown_all(self):
        self.bagtimeline.handle_close()
        self.mediaplayer.stop()
        pass
Example #19
0
 def moveEvent(self, event):
     settings = QSettings("OCS", "joint_control")
     settings.setValue("mainWindowGeometry", self.saveGeometry())
    def __init__(self, context):
        super(RqtLgsvlSimulatorConfiguratorPlugin, self).__init__(context)
        rospack = rospkg.RosPack()
        self.settings = QSettings(
            rospack.get_path('lgsvl_simulator_bridge') + "/config/setting.dat",
            QSettings.IniFormat)
        # Give QObjects reasonable names
        self.setObjectName('RqtLgsvlSimulatorConfiguratorPlugin')

        # 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('lgsvl_simulator_bridge'), 'resource',
            'LgsvlSimulatorConfigratorPlugin.ui')
        # Extend the widget with all atrributes and children from UI File
        loadUi(ui_file, self._widget)
        # Give QObjects reasonable names
        self._widget.setObjectName('RqtLgsvlSimulatorConfiguratorPluginUi')
        # Show _widget.windowTitle on left-top of each plugin(when it's set in _widget).
        # This is useful when you open multiple plugins aat once. Also if you open multiple
        # instances of your plugin at once, these lines add number to make it easy to
        # tell from pane to pane.
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' %d' % context.serial_number()))
        # Add widget to the user interface
        self.settings.beginGroup("simulator_params")
        context.add_widget(self._widget)
        ip = self.settings.value('ip')
        if ip != None:
            self._widget.ip_box.setText(ip)
        port = self.settings.value('port')
        if port != None:
            self._widget.port_box.setText(port)
        config_path = self.settings.value('config_path')
        if config_path != None:
            self._widget.configpath_box.setText(config_path)
        self.settings.endGroup()
        self.json_dict = {}
        self.instance_id = ""
        self.is_remote = False
        self._widget.button_config_ref.clicked[bool].connect(
            self._handle_config_ref_button_clicked)
        self._widget.button_config.clicked[bool].connect(
            self._handle_config_button_clicked)
        self._widget.launch_button.clicked[bool].connect(
            self._handle_launch_button_clicked)
        self._widget.terminate_button.clicked[bool].connect(
            self._handle_terminate_button_clicked)
 def qsettings(self, settings_file):
     path = settings_file
     if not settings_file.startswith(os.path.sep):
         path = os.path.join(self.CFG_PATH, settings_file)
     return QSettings(path, QSettings.IniFormat)
Example #22
0
class LaunchWidget(QDialog):

    # To be connected to PluginContainerWidget
    sig_sysmsg = Signal(str)

    def __init__(self, parent):
        """
        @type parent: LaunchMain
        """
        super(LaunchWidget, self).__init__()
        self._parent = parent

        self._config = None
        self._settings = QSettings('ros', 'rqt_launch')
        self._settings.sync()
        self._package_update = False
        self._launchfile_update = False

        # TODO: should be configurable from gui
        self._port_roscore = 11311

        self._run_id = None

        self._rospack = rospkg.RosPack()
        ui_file = os.path.join(
            self._rospack.get_path('rqt_launch'), 'resource', 'launch_widget.ui'
        )
        loadUi(ui_file, self)

        # row=0 allows any number of rows to be added.
        self._datamodel = QStandardItemModel(0, 1)

        master_uri = rosenv.get_master_uri()
        rospy.loginfo('LaunchWidget master_uri={}'.format(master_uri))
        self._delegate = NodeDelegate(master_uri, self._rospack)
        self._treeview.setModel(self._datamodel)
        self._treeview.setItemDelegate(self._delegate)

        # NodeController used in controller class for launch operation.
        self._node_controllers = []

        self._pushbutton_load_params.clicked.connect(self._parent.load_params)
        self._pushbutton_start_all.clicked.connect(self._parent.start_all)
        self._pushbutton_stop_all.clicked.connect(self._parent.stop_all)
        self._pushbutton_refresh.clicked.connect(
            self._update_pkgs_contain_launchfiles
        )
        # Bind package selection with .launch file selection.
        self._combobox_pkg.currentIndexChanged[str].connect(
            self._refresh_launchfiles
        )
        # Bind a launch file selection with launch GUI generation.
        self._combobox_launchfile_name.currentIndexChanged[str].connect(
            self._load_launchfile_slot
        )
        self._update_pkgs_contain_launchfiles()

    def _load_launchfile_slot(self, launchfile_name):
        # Not yet sure why, but everytime combobox.currentIndexChanged occurs,
        # this method gets called twice with launchfile_name=='' in 1st call.
        if (
            launchfile_name is None
            or launchfile_name == ''
            or self._launchfile_update
        ):
            return
        self._settings.setValue('launchfile_name', launchfile_name)
        self._settings.sync()

        _config = None

        rospy.logdebug(
            '_load_launchfile_slot launchfile_name={}'.format(launchfile_name)
        )

        try:
            _config = self._create_launchconfig(
                launchfile_name, self._port_roscore
            )
            # TODO: folder_name_launchfile should be able to specify arbitrarily
            # _create_launchconfig takes 3rd arg for it.

        except IndexError as e:
            msg = 'IndexError={} launchfile={}'.format(e, launchfile_name)
            rospy.logerr(msg)
            self.sig_sysmsg.emit(msg)
            return
        except RLException as e:
            msg = 'RLException={} launchfile={}'.format(e, launchfile_name)
            rospy.logerr(msg)
            self.sig_sysmsg.emit(msg)
            return

        self._create_widgets_for_launchfile(_config)

    def _create_launchconfig(
        self, launchfile_name, port_roscore, folder_name_launchfile='launch'
    ):
        """
        @rtype: ROSLaunchConfig
        @raises RLException: raised by roslaunch.config.load_config_default.
        """

        pkg_name = self._combobox_pkg.currentText()

        try:
            launchfile = os.path.join(
                self._rospack.get_path(pkg_name),
                folder_name_launchfile,
                launchfile_name,
            )
        except IndexError as e:
            raise RLException('IndexError: {}'.format(e))

        try:
            launch_config = roslaunch.config.load_config_default(
                [launchfile], port_roscore
            )
        except rospkg.common.ResourceNotFound as e:
            raise RLException('ResourceNotFound: {}'.format(e))
        except RLException as e:
            raise e

        return launch_config

    def _create_widgets_for_launchfile(self, config):
        self._config = config

        # Delete old nodes' GUIs.
        del self._node_controllers[:]
        self._delegate.clear_node_widgets()
        # reset the data model
        self._datamodel.clear()
        self._datamodel.setColumnCount(1)
        self._datamodel.setRowCount(len(self._config.nodes))

        # Loop per xml element
        for i, node in enumerate(self._config.nodes):
            proxy = NodeProxy(self._run_id, self._config.master.uri, node)

            nodewidget_index = self._datamodel.index(i, 0, QModelIndex())
            node_widget = self._delegate.create_node_widget(
                nodewidget_index, proxy.config, StatusIndicator()
            )

            # TODO: use tree view delegates correctly instead of
            # empty QStandardItemModel
            self._datamodel.setItem(i, QStandardItem())
            self._treeview.setIndexWidget(nodewidget_index, node_widget)

            node_controller = NodeController(proxy, node_widget)
            self._node_controllers.append(node_controller)

            rospy.logdebug(
                'loop #%d proxy.config.namespace=%s ' + 'proxy.config.name=%s',
                i,
                proxy.config.namespace,
                proxy.config.name,
            )

        self._parent.set_node_controllers(self._node_controllers)

    def _update_pkgs_contain_launchfiles(self):
        """
        Inspired by rqt_msg.MessageWidget._update_pkgs_contain_launchfiles
        """
        self._package_update = True
        packages = sorted(
            [
                pkg_tuple[0]
                for pkg_tuple in RqtRoscommUtil.iterate_packages('launch')
            ]
        )
        self._package_list = packages
        rospy.logdebug('pkgs={}'.format(self._package_list))
        previous_package = self._settings.value('package', '')
        self._combobox_pkg.clear()
        self._combobox_pkg.addItems(self._package_list)
        if previous_package in self._package_list:
            index = self._package_list.index(previous_package)
        else:
            index = 0
        self._package_update = False
        self._combobox_pkg.setCurrentIndex(index)

    def _refresh_launchfiles(self, package=None):
        """
        Inspired by rqt_msg.MessageWidget._refresh_msgs
        """
        if package is None or len(package) == 0 or self._package_update:
            return
        self._launchfile_update = True
        previous_launchfile = self._settings.value('launchfile_name', '')
        self._settings.setValue('package', package)
        self._settings.sync()
        self._launchfile_instances = []  # Launch[]
        # TODO: RqtRoscommUtil.list_files's 2nd arg 'subdir' should NOT be
        # hardcoded later.
        _launch_instance_list = RqtRoscommUtil.list_files(package, 'launch')

        rospy.logdebug(
            '_refresh_launches package={} instance_list={}'.format(
                package, _launch_instance_list
            )
        )

        self._launchfile_instances = [
            x.split('/')[1] for x in _launch_instance_list
        ]

        self._combobox_launchfile_name.clear()
        self._combobox_launchfile_name.addItems(self._launchfile_instances)
        if previous_launchfile in self._launchfile_instances:
            index = self._launchfile_instances.index(previous_launchfile)
        else:
            index = 0
        self._launchfile_update = False
        self._combobox_launchfile_name.setCurrentIndex(index)

    def load_parameters(self):
        """
        Loads all global parameters into roscore.
        """
        run_id = (
            self._run_id
            if self._run_id is not None
            else roslaunch.rlutil.get_or_generate_uuid(None, True)
        )
        runner = roslaunch.ROSLaunchRunner(run_id, self._config)
        runner._load_parameters()

        msg = 'Loaded %d parameters to parameter server.' % len(
            self._config.params
        )
        self.sig_sysmsg.emit(msg)
        rospy.logdebug(msg)

    def save_settings(self, plugin_settings, instance_settings):
        # instance_settings.set_value('splitter', self._splitter.saveState())
        pass

    def restore_settings(self, plugin_settings, instance_settings):
        # if instance_settings.contains('splitter'):
        #     self._splitter.restoreState(instance_settings.value('splitter'))
        # else:
        #     self._splitter.setSizes([100, 100, 200])
        pass
Example #23
0
 def qsettings(self, settings_file):
     from python_qt_binding.QtCore import QSettings
     path = settings_file
     if not settings_file.startswith(os.path.sep):
         path = os.path.join(self.cfg_path, settings_file)
     return QSettings(path, QSettings.IniFormat)
Example #24
0
    def main(self, argv=None, standalone=None):
        # check if DBus is available
        try:
            import dbus
            del dbus
            self._dbus_available = True
        except ImportError:
            pass

        if argv is None:
            argv = sys.argv

        # extract --args and everything behind manually since argparse can not handle that
        arguments = argv[1:]
        args = []
        if '--args' in arguments:
            index = arguments.index('--args')
            args = arguments[index + 1:]
            arguments = arguments[0:index + 1]

        if standalone:
            arguments += ['-s', standalone]

        parser = ArgumentParser('usage: %prog [options]')
        self._add_arguments(parser)
        self._options = parser.parse_args(arguments)
        self._options.args = args

        # check option dependencies
        try:
            if self._options.args and not self._options.standalone_plugin and not self._options.command_start_plugin and not self._options.embed_plugin:
                raise RuntimeError(
                    'Option --args can only be used together with either --standalone, --command-start-plugin or --embed-plugin option'
                )

            list_options = (self._options.list_perspectives,
                            self._options.list_plugins)
            list_options_set = [
                opt for opt in list_options if opt is not False
            ]
            if len(list_options_set) > 1:
                raise RuntimeError(
                    'Only one --list-* option can be used at a time')

            command_options = (self._options.command_start_plugin,
                               self._options.command_switch_perspective)
            command_options_set = [
                opt for opt in command_options if opt is not None
            ]
            if len(command_options_set) > 0 and not self._dbus_available:
                raise RuntimeError(
                    'Without DBus support the --command-* options are not available'
                )
            if len(command_options_set) > 1:
                raise RuntimeError(
                    'Only one --command-* option can be used at a time (except --command-pid which is optional)'
                )
            if len(command_options_set
                   ) == 0 and self._options.command_pid is not None:
                raise RuntimeError(
                    'Option --command_pid can only be used together with an other --command-* option'
                )

            embed_options = (self._options.embed_plugin,
                             self._options.embed_plugin_serial,
                             self._options.embed_plugin_address)
            embed_options_set = [
                opt for opt in embed_options if opt is not None
            ]
            if len(command_options_set) > 0 and not self._dbus_available:
                raise RuntimeError(
                    'Without DBus support the --embed-* options are not available'
                )
            if len(embed_options_set) > 0 and len(embed_options_set) < len(
                    embed_options):
                raise RuntimeError(
                    'Missing option(s) - all \'--embed-*\' options must be set'
                )

            if len(embed_options_set) > 0 and self._options.clear_config:
                raise RuntimeError(
                    'Option --clear-config can only be used without any --embed-* option'
                )

            groups = (list_options_set, command_options_set, embed_options_set)
            groups_set = [opt for opt in groups if len(opt) > 0]
            if len(groups_set) > 1:
                raise RuntimeError(
                    'Options from different groups (--list, --command, --embed) can not be used together'
                )

        except RuntimeError as e:
            print(str(e))
            #parser.parse_args(['--help'])
            # calling --help will exit
            return 1

        # set implicit option dependencies
        if self._options.standalone_plugin is not None:
            self._options.lock_perspective = True

        # use qt/glib mainloop integration to get dbus mainloop working
        if self._dbus_available:
            from dbus.mainloop.glib import DBusGMainLoop
            from dbus import DBusException, Interface, SessionBus
            DBusGMainLoop(set_as_default=True)

        # create application context containing various relevant information
        from .application_context import ApplicationContext
        context = ApplicationContext()
        context.options = self._options

        # non-special applications provide various dbus interfaces
        if self._dbus_available:
            context.provide_app_dbus_interfaces = len(groups_set) == 0
            context.dbus_base_bus_name = 'org.ros.qt_gui'
            if context.provide_app_dbus_interfaces:
                context.dbus_unique_bus_name = context.dbus_base_bus_name + '.pid%d' % os.getpid(
                )

                # provide pid of application via dbus
                from .application_dbus_interface import ApplicationDBusInterface
                _dbus_server = ApplicationDBusInterface(
                    context.dbus_base_bus_name)

        # determine host bus name, either based on pid given on command line or via dbus application interface if any other instance is available
        if len(command_options_set) > 0 or len(embed_options_set) > 0:
            host_pid = None
            if self._options.command_pid is not None:
                host_pid = self._options.command_pid
            else:
                try:
                    remote_object = SessionBus().get_object(
                        context.dbus_base_bus_name, '/Application')
                except DBusException:
                    pass
                else:
                    remote_interface = Interface(
                        remote_object,
                        context.dbus_base_bus_name + '.Application')
                    host_pid = remote_interface.get_pid()
            if host_pid is not None:
                context.dbus_host_bus_name = context.dbus_base_bus_name + '.pid%d' % host_pid

        # execute command on host application instance
        if len(command_options_set) > 0:
            if self._options.command_start_plugin is not None:
                try:
                    remote_object = SessionBus().get_object(
                        context.dbus_host_bus_name, '/PluginManager')
                except DBusException:
                    (rc,
                     msg) = (1,
                             'unable to communicate with GUI instance "%s"' %
                             context.dbus_host_bus_name)
                else:
                    remote_interface = Interface(
                        remote_object,
                        context.dbus_base_bus_name + '.PluginManager')
                    (rc, msg) = remote_interface.start_plugin(
                        self._options.command_start_plugin,
                        ' '.join(self._options.args))
                if rc == 0:
                    print('qt_gui_main() started plugin "%s" in GUI "%s"' %
                          (msg, context.dbus_host_bus_name))
                else:
                    print(
                        'qt_gui_main() could not start plugin "%s" in GUI "%s": %s'
                        % (self._options.command_start_plugin,
                           context.dbus_host_bus_name, msg))
                return rc
            elif self._options.command_switch_perspective is not None:
                remote_object = SessionBus().get_object(
                    context.dbus_host_bus_name, '/PerspectiveManager')
                remote_interface = Interface(
                    remote_object,
                    context.dbus_base_bus_name + '.PerspectiveManager')
                remote_interface.switch_perspective(
                    self._options.command_switch_perspective)
                print(
                    'qt_gui_main() switched to perspective "%s" in GUI "%s"' %
                    (self._options.command_switch_perspective,
                     context.dbus_host_bus_name))
                return 0
            raise RuntimeError('Unknown command not handled')

        # choose selected or default qt binding
        setattr(sys, 'SELECT_QT_BINDING', self._options.qt_binding)
        from python_qt_binding import QT_BINDING

        from python_qt_binding.QtCore import qDebug, qInstallMsgHandler, QSettings, Qt, QtCriticalMsg, QtDebugMsg, QtFatalMsg, QTimer, QtWarningMsg
        from python_qt_binding.QtGui import QAction, QApplication, QIcon, QMenuBar

        from .about_handler import AboutHandler
        from .composite_plugin_provider import CompositePluginProvider
        from .help_provider import HelpProvider
        from .main_window import MainWindow
        from .perspective_manager import PerspectiveManager
        from .plugin_manager import PluginManager

        def message_handler(type_, msg):
            colored_output = 'TERM' in os.environ and 'ANSI_COLORS_DISABLED' not in os.environ
            cyan_color = '\033[36m' if colored_output else ''
            red_color = '\033[31m' if colored_output else ''
            reset_color = '\033[0m' if colored_output else ''
            if type_ == QtDebugMsg and self._options.verbose:
                print(msg, file=sys.stderr)
            elif type_ == QtWarningMsg:
                print(cyan_color + msg + reset_color, file=sys.stderr)
            elif type_ == QtCriticalMsg:
                print(red_color + msg + reset_color, file=sys.stderr)
            elif type_ == QtFatalMsg:
                print(red_color + msg + reset_color, file=sys.stderr)
                sys.exit(1)

        qInstallMsgHandler(message_handler)

        app = QApplication(argv)
        app.setAttribute(Qt.AA_DontShowIconsInMenus, False)

        self.__check_icon_theme_compliance()

        if len(embed_options_set) == 0:
            settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                                 'ros.org', self._settings_filename)
            if self._options.clear_config:
                settings.clear()

            main_window = MainWindow()
            main_window.setDockNestingEnabled(True)
            main_window.statusBar()

            def sigint_handler(*args):
                qDebug('\nsigint_handler()')
                main_window.close()

            signal.signal(signal.SIGINT, sigint_handler)
            # the timer enables triggering the sigint_handler
            timer = QTimer()
            timer.start(500)
            timer.timeout.connect(lambda: None)

            # create own menu bar to share one menu bar on Mac
            menu_bar = QMenuBar()
            menu_bar.setNativeMenuBar(False)
            if not self._options.lock_perspective:
                main_window.setMenuBar(menu_bar)

            file_menu = menu_bar.addMenu(menu_bar.tr('File'))
            action = QAction(file_menu.tr('Quit'), file_menu)
            action.setIcon(QIcon.fromTheme('application-exit'))
            action.triggered.connect(main_window.close)
            file_menu.addAction(action)

        else:
            app.setQuitOnLastWindowClosed(False)

            settings = None
            main_window = None
            menu_bar = None

        self._add_plugin_providers()

        # setup plugin manager
        plugin_provider = CompositePluginProvider(self.plugin_providers)
        plugin_manager = PluginManager(plugin_provider, context)

        if self._options.list_plugins:
            # output available plugins
            print('\n'.join(sorted(plugin_manager.get_plugins().values())))
            return 0

        help_provider = HelpProvider()
        plugin_manager.plugin_help_signal.connect(
            help_provider.plugin_help_request)

        # setup perspective manager
        if settings is not None:
            perspective_manager = PerspectiveManager(settings, context)

            if self._options.list_perspectives:
                # output available perspectives
                print('\n'.join(sorted(perspective_manager.perspectives)))
                return 0
        else:
            perspective_manager = None

        if main_window is not None:
            plugin_manager.set_main_window(main_window, menu_bar)

        if settings is not None and menu_bar is not None:
            perspective_menu = menu_bar.addMenu(menu_bar.tr('Perspectives'))
            perspective_manager.set_menu(perspective_menu)

        # connect various signals and slots
        if perspective_manager is not None and main_window is not None:
            # signal changed perspective to update window title
            perspective_manager.perspective_changed_signal.connect(
                main_window.perspective_changed)
            # signal new settings due to changed perspective
            perspective_manager.save_settings_signal.connect(
                main_window.save_settings)
            perspective_manager.restore_settings_signal.connect(
                main_window.restore_settings)
            perspective_manager.restore_settings_without_plugin_changes_signal.connect(
                main_window.restore_settings)

        if perspective_manager is not None and plugin_manager is not None:
            perspective_manager.save_settings_signal.connect(
                plugin_manager.save_settings)
            plugin_manager.save_settings_completed_signal.connect(
                perspective_manager.save_settings_completed)
            perspective_manager.restore_settings_signal.connect(
                plugin_manager.restore_settings)
            perspective_manager.restore_settings_without_plugin_changes_signal.connect(
                plugin_manager.restore_settings_without_plugins)

        if plugin_manager is not None and main_window is not None:
            # signal before changing plugins to save window state
            plugin_manager.plugins_about_to_change_signal.connect(
                main_window.save_setup)
            # signal changed plugins to restore window state
            plugin_manager.plugins_changed_signal.connect(
                main_window.restore_state)
            # signal save settings to store plugin setup on close
            main_window.save_settings_before_close_signal.connect(
                plugin_manager.close_application)
            # signal save and shutdown called for all plugins, trigger closing main window again
            plugin_manager.close_application_signal.connect(
                main_window.close, type=Qt.QueuedConnection)

        if main_window is not None and menu_bar is not None:
            about_handler = AboutHandler(main_window)
            help_menu = menu_bar.addMenu(menu_bar.tr('Help'))
            action = QAction(file_menu.tr('About'), help_menu)
            action.setIcon(QIcon.fromTheme('help-about'))
            action.triggered.connect(about_handler.show)
            help_menu.addAction(action)

        # set initial size - only used without saved configuration
        if main_window is not None:
            main_window.resize(600, 450)
            main_window.move(100, 100)

        # ensure that qt_gui/src is in sys.path
        src_path = os.path.realpath(
            os.path.join(os.path.dirname(__file__), '..'))
        if src_path not in sys.path:
            sys.path.append(src_path)

        # load specific plugin
        plugin = None
        plugin_serial = None
        if self._options.embed_plugin is not None:
            plugin = self._options.embed_plugin
            plugin_serial = self._options.embed_plugin_serial
        elif self._options.standalone_plugin is not None:
            plugin = self._options.standalone_plugin
            plugin_serial = 0
        if plugin is not None:
            plugins = plugin_manager.find_plugins_by_name(plugin)
            if len(plugins) == 0:
                print('qt_gui_main() found no plugin matching "%s"' % plugin)
                return 1
            elif len(plugins) > 1:
                print(
                    'qt_gui_main() found multiple plugins matching "%s"\n%s' %
                    (plugin, '\n'.join(plugins.values())))
                return 1
            plugin = plugins.keys()[0]

        qDebug('QtBindingHelper using %s' % QT_BINDING)

        plugin_manager.discover()

        self._caching_hook()

        if self._options.reload_import:
            qDebug(
                'ReloadImporter() automatically reload all subsequent imports')
            from .reload_importer import ReloadImporter
            _reload_importer = ReloadImporter()
            self._add_reload_paths(_reload_importer)
            _reload_importer.enable()

        # switch perspective
        if perspective_manager is not None:
            if not plugin:
                perspective_manager.set_perspective(self._options.perspective)
            else:
                perspective_manager.set_perspective(
                    plugin, hide_and_without_plugin_changes=True)

        # load specific plugin
        if plugin:
            plugin_manager.load_plugin(plugin, plugin_serial,
                                       self._options.args)

        if main_window is not None:
            main_window.show()

        return app.exec_()