def set_menu(self, menu): self._menu_manager = MenuManager(menu) self._perspective_mapper = QSignalMapper(menu) self._perspective_mapper.mapped[str].connect(self.switch_perspective) # generate menu create_action = QAction('&Create perspective...', self._menu_manager.menu) create_action.setIcon(QIcon.fromTheme('list-add')) create_action.triggered.connect(self._on_create_perspective) self._menu_manager.add_suffix(create_action) self._remove_action = QAction('&Remove perspective...', self._menu_manager.menu) self._remove_action.setEnabled(False) self._remove_action.setIcon(QIcon.fromTheme('list-remove')) self._remove_action.triggered.connect(self._on_remove_perspective) self._menu_manager.add_suffix(self._remove_action) self._menu_manager.add_suffix(None) import_action = QAction('&Import...', self._menu_manager.menu) import_action.setIcon(QIcon.fromTheme('document-open')) import_action.triggered.connect(self._on_import_perspective) self._menu_manager.add_suffix(import_action) export_action = QAction('&Export...', self._menu_manager.menu) export_action.setIcon(QIcon.fromTheme('document-save-as')) export_action.triggered.connect(self._on_export_perspective) self._menu_manager.add_suffix(export_action) # add perspectives to menu for name in self.perspectives: if not name.startswith(self.HIDDEN_PREFIX): self._add_perspective_action(name)
def __init__(self, timeline, parent, topic): MessageView.__init__(self, timeline, topic) self._parent = parent self._stamp = None self._name = parent.objectName() self.toolbar = QToolBar() self._first_action = QAction(QIcon.fromTheme('go-first'), '', self.toolbar) self._first_action.triggered.connect(self.navigate_first) self.toolbar.addAction(self._first_action) self._prev_action = QAction(QIcon.fromTheme('go-previous'), '', self.toolbar) self._prev_action.triggered.connect(self.navigate_previous) self.toolbar.addAction(self._prev_action) self._next_action = QAction(QIcon.fromTheme('go-next'), '', self.toolbar) self._next_action.triggered.connect(self.navigate_next) self.toolbar.addAction(self._next_action) self._last_action = QAction(QIcon.fromTheme('go-last'), '', self.toolbar) self._last_action.triggered.connect(self.navigate_last) self.toolbar.addAction(self._last_action) parent.layout().addWidget(self.toolbar)
def _rightclick_menu(self, event): """ :type event: QEvent """ # QTreeview.selectedIndexes() returns 0 when no node is selected. # This can happen when after booting no left-click has been made yet # (ie. looks like right-click doesn't count). These lines are the # workaround for that problem. selected = self._messages_tree.selectedIndexes() if len(selected) == 0: return menu = QMenu() text_action = QAction(self.tr('View Text'), menu) menu.addAction(text_action) raw_action = QAction(self.tr('View Raw'), menu) menu.addAction(raw_action) remove_action = QAction(self.tr('Remove message'), menu) menu.addAction(remove_action) action = menu.exec_(event.globalPos()) if action == raw_action or action == text_action: rospy.logdebug('_rightclick_menu selected={}'.format(selected)) selected_type = selected[1].data() if selected_type[-2:] == '[]': selected_type = selected_type[:-2] browsetext = None try: if (self._mode == rosmsg.MODE_MSG or self._mode == rosaction.MODE_ACTION): browsetext = rosmsg.get_msg_text(selected_type, action == raw_action) elif self._mode == rosmsg.MODE_SRV: browsetext = rosmsg.get_srv_text(selected_type, action == raw_action) else: raise except rosmsg.ROSMsgException as e: QMessageBox.warning( self, self.tr('Warning'), self.tr('The selected item component ' + 'does not have text to view.')) if browsetext is not None: self._browsers.append( TextBrowseDialog(browsetext, self._rospack)) self._browsers[-1].show() if action == remove_action: self._messages_tree.model().removeRow(selected[0].row())
def _update_remove_topic_menu(self): def make_remove_topic_function(x): return lambda: self.remove_topic(x) self._remove_topic_menu.clear() for topic_name in sorted(self._rosdata.keys()): action = QAction(topic_name, self._remove_topic_menu) action.triggered.connect(make_remove_topic_function(topic_name)) self._remove_topic_menu.addAction(action) if len(self._rosdata) > 1: all_action = QAction('All', self._remove_topic_menu) all_action.triggered.connect(self.clean_up_subscribers) self._remove_topic_menu.addAction(all_action)
def __init__(self, parent=None): super(PublisherTreeWidget, self).__init__(parent) self.setModel(PublisherTreeModel(self)) self._action_remove_publisher = QAction(QIcon.fromTheme('list-remove'), 'Remove Selected', self) self._action_remove_publisher.triggered[bool].connect( self._handle_action_remove_publisher) self._action_publish_once = QAction( QIcon.fromTheme('media-playback-start'), 'Publish Selected Once', self) self._action_publish_once.triggered[bool].connect( self._handle_action_publish_once) self.setItemDelegateForColumn( self.model()._column_index['rate'], SpinBoxDelegate(min_value=0, max_value=1000000, decimals=2))
def add_plugin_prefix(self, plugin_descriptor): action_attributes = plugin_descriptor.action_attributes() action = QAction(action_attributes['label'], self._plugin_menu_manager.menu) self._enrich_action(action, action_attributes) self._plugin_mapper.setMapping(action, plugin_descriptor.plugin_id()) action.triggered.connect(self._plugin_mapper.map) self._plugin_menu_manager.add_prefix(action)
def _gl_view_mouseReleaseEvent(self, event): if event.button() == Qt.RightButton: menu = QMenu(self._gl_view) action = QAction(self._gl_view.tr("Reset view"), self._gl_view) menu.addAction(action) action.triggered.connect(self._set_default_view) menu.exec_(self._gl_view.mapToGlobal(event.pos()))
def __init__(self, parent=None): super(LaunchTreeWidget, self).__init__(parent) self.setModel(LaunchTreeModel(self)) self._action_remove_publisher = QAction(QIcon.fromTheme('remove'), 'Remove Selected', self) self._action_remove_publisher.triggered[bool].connect( self._handle_action_remove_publisher)
def add_plugin(self, plugin_descriptor): base_path = plugin_descriptor.attributes().get('plugin_path') menu_manager = self._plugin_menu_manager # create submenus for group in plugin_descriptor.groups(): label = group['label'] if menu_manager.contains_menu(label): submenu = menu_manager.get_menu(label) else: submenu = QMenu(label, menu_manager.menu) menu_action = submenu.menuAction() self._enrich_action(menu_action, group, base_path) menu_manager.add_item(submenu) menu_manager = MenuManager(submenu) # create action action_attributes = plugin_descriptor.action_attributes() action = QAction(action_attributes['label'], menu_manager.menu) self._enrich_action(action, action_attributes, base_path) self._plugin_mapper.setMapping(action, plugin_descriptor.plugin_id()) action.triggered.connect(self._plugin_mapper.map) not_available = plugin_descriptor.attributes().get('not_available') if not_available: action.setEnabled(False) action.setStatusTip( self.tr('Plugin is not available: %s') % not_available) # add action to menu menu_manager.add_item(action)
def __init__(self, parent=None): super(MessageTreeWidget, self).__init__(parent) self.setDragEnabled(True) self.sortByColumn(0, Qt.AscendingOrder) try: setSectionResizeMode = self.header().setSectionResizeMode # Qt5 except AttributeError: setSectionResizeMode = self.header().setResizeMode # Qt4 setSectionResizeMode(QHeaderView.ResizeToContents) self.header().setContextMenuPolicy(Qt.CustomContextMenu) self.header().customContextMenuRequested.connect( self.handle_header_view_customContextMenuRequested) self._action_item_expand = QAction(QIcon.fromTheme('zoom-in'), 'Expand Selected', self) self._action_item_expand.triggered.connect(self._handle_action_item_expand) self._action_item_collapse = QAction(QIcon.fromTheme('zoom-out'), 'Collapse Selected', self) self._action_item_collapse.triggered.connect(self._handle_action_item_collapse) self.customContextMenuRequested.connect(self.handle_customContextMenuRequested)
def _update_remove_topic_menu(self): def make_remove_topic_function(x): return lambda: self.remove_topic(x) self._remove_topic_menu.clear() for topic_name in sorted(self._rosdata.keys()): action = QAction(topic_name, self._remove_topic_menu) action.triggered.connect(make_remove_topic_function(topic_name)) self._remove_topic_menu.addAction(action) self.remove_topic_button.setMenu(self._remove_topic_menu)
def add_instance(self, plugin_descriptor, instance_id): action_attributes = plugin_descriptor.action_attributes() action = QAction(self._get_instance_label(str(instance_id)), self._running_menu_manager.menu) base_path = plugin_descriptor.attributes().get('plugin_path') self._enrich_action(action, action_attributes, base_path) self._running_mapper.setMapping(action, str(instance_id)) action.triggered.connect(self._running_mapper.map) self._running_menu_manager.add_item(action) self._instances[instance_id] = action
def add_menu_item(self, menu_name, labels): menu_text = menu_name if self.label[labels[0]].isHidden(): menu_text = "Show " + menu_text else: menu_text = "Hide " + menu_text action = QAction(menu_text, self._widget) action.triggered.connect(partial(self.toggle_labels, labels)) self._widget.addAction(action) self.actions[menu_name] = action
def _add_perspective_action(self, name): if self._menu_manager is not None: # create action action = QAction(name, self._menu_manager.menu) action.setCheckable(True) self._perspective_mapper.setMapping(action, name) action.triggered.connect(self._perspective_mapper.map) # add action to menu self._menu_manager.add_item(action) # enable remove-action if self._menu_manager.count_items() > 1: self._remove_action.setEnabled(True)
def add_instance(self, plugin_descriptor, instance_id): action_attributes = plugin_descriptor.action_attributes() # create action label = self.tr('Close:') + ' ' + action_attributes['label'] if instance_id.serial_number != 1: label = label + ' (%s)' % str(instance_id.serial_number) action = QAction(label, self._running_menu_manager.menu) base_path = plugin_descriptor.attributes().get('plugin_path') self._enrich_action(action, action_attributes, base_path) self._running_mapper.setMapping(action, str(instance_id)) action.triggered.connect(self._running_mapper.map) self._running_menu_manager.add_item(action) self._instances[instance_id] = action
def __init__(self, menu_bar, plugin_manager): super(PluginMenu, self).__init__() self.setObjectName('PluginMenu') plugin_menu = menu_bar.addMenu(menu_bar.tr('&Plugins')) running_menu = menu_bar.addMenu(menu_bar.tr('&Running')) self._plugin_menu_manager = MenuManager(plugin_menu) self._plugin_mapper = QSignalMapper(plugin_menu) self._plugin_mapper.mapped[str].connect(self.load_plugin_signal) self._running_menu_manager = MenuManager(running_menu) action = QAction(' Hidden action to work around QTBUG-52582', self._running_menu_manager.menu) action.setVisible(False) self._running_menu_manager.add_item(action) self._running_mapper = QSignalMapper(running_menu) self._running_mapper.mapped[str].connect(self.unload_plugin_signal) self._instances = {}
def addDockWidget(self, dock_widget): # remove action for same dock widget if exists self.removeDockWidget(dock_widget) icon = dock_widget.windowIcon() if icon.isNull(): icon = QIcon.fromTheme('folder') title = dock_widget.windowTitle() action = QAction(icon, title, self) # truncate label if necessary if len(title) > MinimizedDockWidgetsToolbar.max_label_length: action.setToolTip(title) action.setIconText( title[0:MinimizedDockWidgetsToolbar.max_label_length] + '...') self._signal_mapper.setMapping(action, dock_widget) action.triggered.connect(self._signal_mapper.map) self._dock_widgets[dock_widget] = action self.addAction(action) self.show()
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 __init__(self, context): super(HandEyeCalibration, self).__init__(context) self.context = context self.node = context.node self.widget = QWidget() self.widget.setObjectName(self.PLUGIN_TITLE) self.widget.setWindowTitle(self.PLUGIN_TITLE) # Data self.Tsamples = [] # Toolbar _, path_pkg = get_resource('packages', 'handeye_dashboard') print("{}".format(path_pkg)) self.snapshot_action = QAction(QIcon.fromTheme('camera-photo'), 'Take a snapshot', self.widget) path = path_pkg + '/share/handeye_dashboard/images/capture.png' self.calibrate_action = QAction(QIcon(QPixmap.fromImage(QImage(path))), 'Get the camera/robot transform', self.widget) self.clear_action = QAction(QIcon.fromTheme('edit-clear'), 'Clear the record data.', self.widget) path = path_pkg + '/share/handeye_dashboard/images/UR5.png' self.execut_action = QAction(QIcon(QPixmap.fromImage(QImage(path))), 'EStart the publishing the TF.', self.widget) self.toolbar = QToolBar() self.toolbar.addAction(self.snapshot_action) self.toolbar.addAction(self.calibrate_action) self.toolbar.addAction(self.clear_action) self.toolbar.addAction(self.execut_action) # Toolbar0 self.l0 = QLabel(self.widget) self.l0.setText("Camera-Mount-Type: ") self.l0.setFixedWidth(150) self.l0.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.combobox = QComboBox(self.widget) self.combobox.addItem('attached on robot') self.combobox.addItem('fixed beside robot') self.toolbar0 = QToolBar() self.toolbar0.addWidget(self.l0) self.toolbar0.addWidget(self.combobox) # Toolbar1 self.l1 = QLabel(self.widget) self.l1.setText("Camera-Frame: ") self.l1.setFixedWidth(150) self.l1.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.camera_frame = QLineEdit(self.widget) self.camera_frame.setText("camera_link") self.toolbar1 = QToolBar() self.toolbar1.addWidget(self.l1) self.toolbar1.addWidget(self.camera_frame) # Toolbar2 self.l2 = QLabel(self.widget) self.l2.setText("Object-Frame: ") self.l2.setFixedWidth(150) self.l2.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.object_frame = QLineEdit(self.widget) self.object_frame.setText("calib_board") self.toolbar2 = QToolBar() self.toolbar2.addWidget(self.l2) self.toolbar2.addWidget(self.object_frame) # Toolbar3 self.l3 = QLabel(self.widget) self.l3.setText("Robot-Base-Frame: ") self.l3.setFixedWidth(150) self.l3.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.base_frame = QLineEdit(self.widget) self.base_frame.setText("base") self.toolbar3 = QToolBar() self.toolbar3.addWidget(self.l3) self.toolbar3.addWidget(self.base_frame) # Toolbar4 self.l4 = QLabel(self.widget) self.l4.setText("End-Effector-Frame: ") self.l4.setFixedWidth(150) self.l4.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.endeffector_frame = QLineEdit(self.widget) self.endeffector_frame.setText("tool0") self.toolbar4 = QToolBar() self.toolbar4.addWidget(self.l4) self.toolbar4.addWidget(self.endeffector_frame) # Toolbar5 self.l5 = QLabel(self.widget) self.l5.setText("Sample-Number: ") self.l5.setFixedWidth(150) self.l5.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.le5 = QLineEdit(self.widget) self.le5.setValidator(QIntValidator()) self.le5.setText('10') self.le5.setReadOnly(True) self.toolbar5 = QToolBar() self.toolbar5.addWidget(self.l5) self.toolbar5.addWidget(self.le5) # TreeView self.treeview = QTreeView() self.treeview.setAlternatingRowColors(True) self.model = QStandardItemModel(self.treeview) self.treeview.setModel(self.model) self.treeview.setHeaderHidden(True) # TextEdit self.textedit = QTextEdit(self.widget) self.textedit.setReadOnly(True) # Layout self.layout = QVBoxLayout() self.layout.addWidget(self.toolbar0) self.layout.addWidget(self.toolbar1) self.layout.addWidget(self.toolbar2) self.layout.addWidget(self.toolbar3) self.layout.addWidget(self.toolbar4) self.layout.addWidget(self.toolbar5) self.layout.addWidget(self.toolbar) self.layoutH = QHBoxLayout() self.layoutH.addWidget(self.treeview) self.layoutH.addWidget(self.textedit) self.layout.addLayout(self.layoutH) self.widget.setLayout(self.layout) # Add the widget to the user interface if context.serial_number() > 1: self.widget.setWindowTitle(self.widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self.widget) # Make the connections self.snapshot_action.triggered.connect(self.take_snapshot) self.calibrate_action.triggered.connect(self.calibration) self.clear_action.triggered.connect(self.clear) self.execut_action.triggered.connect(self.execution) # Package path self.path_pkg = path_pkg # Set up TF self.cli = self.node.create_client(HandeyeTF, 'handeye_tf_service') while not self.cli.wait_for_service(timeout_sec=1.0): self.node.get_logger().info( 'service not available, waiting again...') self.req = HandeyeTF.Request()
def _rightclick_menu(self, event): """ :type event: QEvent """ # QTreeview.selectedIndexes() returns 0 when no node is selected. # This can happen when after booting no left-click has been made yet # (ie. looks like right-click doesn't count). These lines are the # workaround for that problem. selected = self._messages_tree.selectedIndexes() if len(selected) == 0: return menu = QMenu() text_action = QAction(self.tr('View Text'), menu) menu.addAction(text_action) remove_action = QAction(self.tr('Remove message'), menu) menu.addAction(remove_action) action = menu.exec_(event.globalPos()) if action == text_action: self._logger.debug('_rightclick_menu selected={}'.format(selected)) selected_type = selected[1].data() # We strip any array information for loading the python classes selected_type_bare = selected_type if selected_type_bare.find('[') >= 0: selected_type_bare = selected_type_bare[:selected_type_bare. find('[')] # We use the number of '/' to determine of the selected type is a msg, action, srv, # or primitive type. # NOTE (mlautman - 2/4/19) this heuristic seems brittle and should be removed selected_type_bare_tokens_len = len(selected_type_bare.split('/')) # We only want the base class so we transform eg. pkg1/my_srv/Request -> pkg1/my_srv if selected_type_bare_tokens_len > 2: selected_type_bare = "/".join( selected_type_bare.split('/')[:2]) browsetext = None # If the type does not have '/'s then we treat it as a primitive type if selected_type_bare_tokens_len == 1: browsetext = selected_type # if the type has a single '/' then we treat it as a msg type elif selected_type_bare_tokens_len == 2: msg_class = get_message_class(selected_type_bare) browsetext = get_message_text_from_class(msg_class) # If the type has two '/'s then we treat it as a srv or action type elif selected_type_bare_tokens_len == 3: if self._mode == message_helpers.SRV_MODE: msg_class = get_service_class(selected_type_bare) browsetext = get_service_text_from_class(msg_class) elif self._mode == message_helpers.ACTION_MODE: msg_class = get_action_class(selected_type_bare) browsetext = get_action_text_from_class(msg_class) else: self._logger.warn("Unrecognized value for self._mode: {} " "for selected_type: {}".format( self._mode, selected_type)) else: self._logger.warn( "Invalid selected_type: {}".format(selected_type)) if browsetext is not None: self._browsers.append(TextBrowseDialog(browsetext)) self._browsers[-1].show() if action == remove_action: self._messages_tree.model().removeRow(selected[0].row())