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()
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()
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()
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'))
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 __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 __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())
def resizeEvent(self, event): settings = QSettings("OCS", "footstep_param_control") settings.setValue("mainWindowGeometry", self.saveGeometry())
def resizeEvent(self, event): settings = QSettings("OCS", "pelvis_pose") settings.setValue("mainWindowGeometry", self.saveGeometry())
def moveEvent(self, event): settings = QSettings("OCS", "position_mode") settings.setValue("mainWindowGeometry", self.saveGeometry())
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_()
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_()
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
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)
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
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)
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_()