def set_url(self, url, showinput=False): """ Sets the url and begins loading that page :param url: url to load in the webview, ''str or QUrl'' :param showinput: if true the input bar will be shown, else hidden, ''bool'' """ if url is not None: self._url = QUrl(url) self.set_show_url_input(showinput) self._view.setUrl(self._url)
def on_topic_control_btn_clicked(self): try: if self.sub is None and self.ssh_output_file is None: if self.__msg_class: self.sub = rospy.Subscriber(self.topic, self.__msg_class, self._msg_handle) else: self._on_display_anchorClicked(QUrl(self._masteruri)) self.topic_control_button.setText('stop') self.topic_control_button.setIcon( QIcon(':/icons/deleket_deviantart_stop.png')) else: if self.sub is not None: self.sub.unregister() self.sub = None elif self.ssh_output_file is not None: self.ssh_output_file.close() self.ssh_error_file.close() self.ssh_output_file = None self.topic_control_button.setText('play') self.topic_control_button.setIcon( QIcon(':/icons/deleket_deviantart_play.png')) self.no_str_checkbox.setEnabled(True) self.no_arr_checkbox.setEnabled(True) except Exception as e: rospy.logwarn('Error while stop/play echo for topic %s: %s' % (self.topic, e))
def __init__(self, parent=None): super(QVirtualJoystickView, self).__init__(parent) virtual_joystick_path = os.path.join( rospkg.RosPack().get_path('rocon_qt_library'), 'ui', 'virtual_joystick.qml') self.setSource(QUrl(virtual_joystick_path)) self.setResizeMode(QDeclarativeView.SizeRootObjectToView)
def _initialize_widget(self, url): # NOTE: Since QQuickWidget freezes if running on another thread # QQuickView is used and wrapped as QWidget # See https://stackoverflow.com/questions/52663856/qwidget-ui-freezes-when-using-a-qquickwidget view = QQuickView() view.statusChanged.connect( functools.partial(self._on_status_changed, view=view)) engine = view.engine() # aggregate plugin paths from import tags rospack = rospkg.RosPack() plugins_dir = QLibraryInfo.location(QLibraryInfo.PluginsPath) plugins_paths = rospack.get_manifest(__name__).get_export( __name__, 'plugins') for i, p in enumerate(plugins_paths): plugins_paths[i] = os.path.join(plugins_dir, p) qml_paths = rospack.get_manifest(__name__).get_export( __name__, 'imports') deps = rospack.get_depends_on(__name__) for dep in deps: pp = rospack.get_manifest(dep).get_export(__name__, 'plugins') for i in p in enumerate(pp): if not os.path.isabs(p): pp[i] = os.path.join(plugins_dir, p) plugins_paths += pp qp = rospack.get_manifest(dep).get_export(__name__, 'imports') qml_paths += qp for p in plugins_paths: rospy.logdebug('plugin path: %s', p) engine.addPluginPath(p) for p in qml_paths: rospy.logdebug('import path: %s', p) engine.addImportPath(p) qml_sys_path = QLibraryInfo.location(QLibraryInfo.ImportsPath) rospy.logdebug('import path: %s', qml_sys_path) engine.addImportPath(qml_sys_path) os.environ['QML2_IMPORT_PATH'] = ':'.join( qml_paths) + ':' + qml_sys_path # wrap QWindow class as QWidget widget = QWidget.createWindowContainer(view) # load QML url = self._args.url if not os.path.isabs(url): url = os.path.abspath(url) rospy.logdebug('Url: %s' % url) url = QUrl.fromLocalFile(url) view.setSource(url) return widget
def on_topic_control_btn_clicked(self): try: if self.sub is None and self.ssh_output_file is None: if self.__msg_class: self.sub = rospy.Subscriber(self.topic, self.__msg_class, self._msg_handle) self._start_time = time.time() else: self._on_display_anchorClicked(QUrl(self._masteruri)) self.topicControlButton.setIcon(nm.settings().icon('sekkyumu_stop.png')) else: if self.sub is not None: self.sub.unregister() self.sub = None elif self.ssh_output_file is not None: self.ssh_output_file.close() self.ssh_error_file.close() self.ssh_output_file = None self.topicControlButton.setIcon(nm.settings().icon('sekkyumu_play.png')) except Exception as e: rospy.logwarn('Error while stop/play echo for topic %s: %s' % (self.topic, utf8(e)))
class WebWidget(QWidget): def __init__(self, url=None): """ Class to load a webpage in a widget. :param url: If url is empty then a navigation bar is shown otherwise the url is loaded and the navigation bar is hidden, ''str'' """ super(WebWidget, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_web'), 'resource', 'web_widget.ui') loadUi(ui_file, self) self.setObjectName('WebWidget') self._loading = False self._stop_icon = QIcon.fromTheme('process-stop') self._reload_icon = QIcon.fromTheme('view-refresh') self._working_icon = QIcon.fromTheme('process-working') self._completer_word_list = [''] self._view = QWebView() self.verticalLayout.addWidget(self._view) if url is None: self.set_url("http://ros.org", True) else: self.set_url(url, False) self.url_lineedit.returnPressed.connect(self._handle_url_change) self._view.loadFinished[bool].connect(self._handle_load_finished) self.reload_button.clicked.connect(self._handle_reload_clicked) self._view.linkClicked.connect(self._handle_link_clicked) self._view.urlChanged[QUrl].connect(self._handle_url_changed) def set_url(self, url, showinput=False): """ Sets the url and begins loading that page :param url: url to load in the webview, ''str or QUrl'' :param showinput: if true the input bar will be shown, else hidden, ''bool'' """ if url is not None: self._url = QUrl(url) self.set_show_url_input(showinput) self._view.setUrl(self._url) def set_show_url_input(self, showinput): """ Sets the value of the show_url_input flag and hides/shows the widgets as required :param showinput: true - show inputbar false - hide , ''bool'' """ self._show_url_input = showinput self.url_lineedit.setVisible(self._show_url_input) self.reload_button.setVisible(self._show_url_input) if self._show_url_input: self._view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks) else: self._view.page().setLinkDelegationPolicy(QWebPage.DontDelegateLinks) def save_settings(self, settings): settings.set_value('url_completion', self._pack(self._completer_word_list)) settings.set_value('url_current', self._url.toString()) def restore_settings(self, settings): self._completer_word_list += self._unpack(settings.value('url_completion')) self._completer_word_list = list(set(self._completer_word_list)) url = settings.value('url_current') if url: self.set_url(url, self._show_url_input) def _handle_url_change(self): self.set_url(self.url_lineedit.text(), True) def _handle_link_clicked(self, url): self.set_url(url, True) def _handle_reload_clicked(self): if self._loading: self._view.stop() self._loading = False self.reload_button.setIcon(self._reload_icon) else: self._view.reload() self._loading = True self.reload_button.setIcon(self._stop_icon) def _handle_url_changed(self, url): # set text to the current loading item self.url_lineedit.setText(url.toString()) self.reload_button.setIcon(self._stop_icon) self._loading = True def _handle_load_finished(self, ok): self._loading = False self.reload_button.setIcon(self._reload_icon) if ok: self._add_completer_list_item(self._url.toString()) else: # need to disconnect or we will resend the signal once the error page loads self._view.loadFinished[bool].disconnect(self._handle_load_finished) self._view.page().currentFrame().setHtml('<html><h2>The url you entered seems to be faulty.</h2></html>') self._view.loadFinished[bool].connect(self._handle_load_finished) def _add_completer_list_item(self, url): self._completer_word_list.append(self.url_lineedit.text()) self._completer_word_list = list(set(self._completer_word_list)) self._completer = QCompleter(self._completer_word_list) self._completer.setCaseSensitivity(Qt.CaseInsensitive) self._completer.setCompletionMode(QCompleter.PopupCompletion) self.url_lineedit.setCompleter(self._completer) @staticmethod def _pack(data): """ Packs 'data' into a form that can be easily and readably written to an ini file :param data: A list of strings to be flattened into a string ''list'' :return: A string suitable for output to ini files ''str'' """ if len(data) == 0: return '' if len(data) == 1: return data[0] return data @staticmethod def _unpack(data): """ Unpacks the values read from an ini file :param data: An entry taken from an ini file ''list or string'' :return: A list of strings ''list'' """ if data is None or data == '': data = [] elif isinstance(data, basestring): data = [data] return data
class WebWidget(QWidget): def __init__(self, url=None): """ Class to load a webpage in a widget. :param url: If url is empty then a navigation bar is shown otherwise the url is loaded and the navigation bar is hidden, ''str'' """ super(WebWidget, self).__init__() ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'web_widget.ui') loadUi(ui_file, self) self.setObjectName('WebWidget') self._loading = False self._stop_icon = QIcon.fromTheme('process-stop') self._reload_icon = QIcon.fromTheme('view-refresh') self._working_icon = QIcon.fromTheme('process-working') self._completer_word_list = [''] self._view = QWebView() self.verticalLayout.addWidget(self._view) if url is None: self.set_url("http://ros.org", True) else: self.set_url(url, False) self.url_lineedit.returnPressed.connect(self._handle_url_change) self._view.loadFinished[bool].connect(self._handle_load_finished) self.reload_button.clicked.connect(self._handle_reload_clicked) self._view.linkClicked.connect(self._handle_link_clicked) self._view.urlChanged[QUrl].connect(self._handle_url_changed) def set_url(self, url, showinput=False): """ Sets the url and begins loading that page :param url: url to load in the webview, ''str or QUrl'' :param showinput: if true the input bar will be shown, else hidden, ''bool'' """ if url is not None: self._url = QUrl(url) self.set_show_url_input(showinput) self._view.setUrl(self._url) def set_show_url_input(self, showinput): """ Sets the value of the show_url_input flag and hides/shows the widgets as required :param showinput: true - show inputbar false - hide , ''bool'' """ self._show_url_input = showinput self.url_lineedit.setVisible(self._show_url_input) self.reload_button.setVisible(self._show_url_input) if self._show_url_input: self._view.page().setLinkDelegationPolicy( QWebPage.DelegateAllLinks) else: self._view.page().setLinkDelegationPolicy( QWebPage.DontDelegateLinks) def save_settings(self, settings): settings.set_value('url_completion', self._pack(self._completer_word_list)) settings.set_value('url_current', self._url.toString()) def restore_settings(self, settings): self._completer_word_list += self._unpack( settings.value('url_completion')) self._completer_word_list = list(set(self._completer_word_list)) url = settings.value('url_current') if url: self.set_url(url, self._show_url_input) def _handle_url_change(self): self.set_url(self.url_lineedit.text(), True) def _handle_link_clicked(self, url): self.set_url(url, True) def _handle_reload_clicked(self): if self._loading: self._view.stop() self._loading = False self.reload_button.setIcon(self._reload_icon) else: self._view.reload() self._loading = True self.reload_button.setIcon(self._stop_icon) def _handle_url_changed(self, url): # set text to the current loading item self.url_lineedit.setText(url.toString()) self.reload_button.setIcon(self._stop_icon) self._loading = True def _handle_load_finished(self, ok): self._loading = False self.reload_button.setIcon(self._reload_icon) if ok: self._add_completer_list_item(self._url.toString()) else: # need to disconnect or we will resend the signal once the error page loads self._view.loadFinished[bool].disconnect( self._handle_load_finished) self._view.page().currentFrame().setHtml( '<html><h2>The url you entered seems to be faulty.</h2></html>' ) self._view.loadFinished[bool].connect(self._handle_load_finished) def _add_completer_list_item(self, url): self._completer_word_list.append(self.url_lineedit.text()) self._completer_word_list = list(set(self._completer_word_list)) self._completer = QCompleter(self._completer_word_list) self._completer.setCaseSensitivity(Qt.CaseInsensitive) self._completer.setCompletionMode(QCompleter.PopupCompletion) self.url_lineedit.setCompleter(self._completer) @staticmethod def _pack(data): """ Packs 'data' into a form that can be easily and readably written to an ini file :param data: A list of strings to be flattened into a string ''list'' :return: A string suitable for output to ini files ''str'' """ if len(data) == 0: return '' if len(data) == 1: return data[0] return data @staticmethod def _unpack(data): """ Unpacks the values read from an ini file :param data: An entry taken from an ini file ''list or string'' :return: A list of strings ''list'' """ if data is None or data == '': data = [] elif isinstance(data, basestring): data = [data] return data
def __init__(self, topic, msg_type, show_only_rate=False, masteruri=None, use_ssh=False, parent=None): ''' Creates an input dialog. @param topic: the name of the topic @type topic: C{str} @param msg_type: the type of the topic @type msg_type: C{str} @raise Exception: if no topic class was found for the given type ''' QDialog.__init__(self, parent=parent) self._masteruri = masteruri masteruri_str = '' if masteruri is None else '[%s]' % masteruri self.setObjectName(' - '.join(['EchoDialog', topic, masteruri_str])) self.setAttribute(Qt.WA_DeleteOnClose, True) self.setWindowFlags(Qt.Window) self.setWindowTitle('%s %s %s' % ('Echo --- ' if not show_only_rate else 'Hz --- ', topic, masteruri_str)) self.resize(728, 512) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.mIcon = QIcon(":/icons/crystal_clear_prop_run_echo.png") self.setWindowIcon(self.mIcon) self.topic = topic self.show_only_rate = show_only_rate self.lock = threading.RLock() self.last_printed_count = 0 self.msg_t0 = -1. self.msg_tn = 0 self.times = [] self.message_count = 0 self._rate_message = '' self._scrapped_msgs = 0 self._scrapped_msgs_sl = 0 self._last_received_ts = 0 self.receiving_hz = self.MESSAGE_HZ_LIMIT self.line_limit = self.MESSAGE_LINE_LIMIT self.field_filter_fn = None options = QWidget(self) if not show_only_rate: hLayout = QHBoxLayout(options) hLayout.setContentsMargins(1, 1, 1, 1) self.no_str_checkbox = no_str_checkbox = QCheckBox('Hide strings') no_str_checkbox.toggled.connect(self.on_no_str_checkbox_toggled) hLayout.addWidget(no_str_checkbox) self.no_arr_checkbox = no_arr_checkbox = QCheckBox('Hide arrays') no_arr_checkbox.toggled.connect(self.on_no_arr_checkbox_toggled) hLayout.addWidget(no_arr_checkbox) self.combobox_reduce_ch = QComboBox(self) self.combobox_reduce_ch.addItems( [str(self.MESSAGE_LINE_LIMIT), '0', '80', '256', '1024']) self.combobox_reduce_ch.activated[str].connect( self.combobox_reduce_ch_activated) self.combobox_reduce_ch.setEditable(True) self.combobox_reduce_ch.setToolTip( "Set maximum line width. 0 disables the limit.") hLayout.addWidget(self.combobox_reduce_ch) # reduce_ch_label = QLabel('ch', self) # hLayout.addWidget(reduce_ch_label) # add spacer spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) hLayout.addItem(spacerItem) # add combobox for displaying frequency of messages self.combobox_displ_hz = QComboBox(self) self.combobox_displ_hz.addItems([ str(self.MESSAGE_HZ_LIMIT), '0', '0.1', '1', '50', '100', '1000' ]) self.combobox_displ_hz.activated[str].connect( self.on_combobox_hz_activated) self.combobox_displ_hz.setEditable(True) hLayout.addWidget(self.combobox_displ_hz) displ_hz_label = QLabel('Hz', self) hLayout.addWidget(displ_hz_label) # add combobox for count of displayed messages self.combobox_msgs_count = QComboBox(self) self.combobox_msgs_count.addItems( [str(self.MAX_DISPLAY_MSGS), '0', '50', '100']) self.combobox_msgs_count.activated[str].connect( self.on_combobox_count_activated) self.combobox_msgs_count.setEditable(True) self.combobox_msgs_count.setToolTip( "Set maximum displayed message count. 0 disables the limit.") hLayout.addWidget(self.combobox_msgs_count) displ_count_label = QLabel('#', self) hLayout.addWidget(displ_count_label) # add topic control button for unsubscribe and subscribe self.topic_control_button = QToolButton(self) self.topic_control_button.setText('stop') self.topic_control_button.setIcon( QIcon(':/icons/deleket_deviantart_stop.png')) self.topic_control_button.clicked.connect( self.on_topic_control_btn_clicked) hLayout.addWidget(self.topic_control_button) # add clear button clearButton = QToolButton(self) clearButton.setText('clear') clearButton.clicked.connect(self.on_clear_btn_clicked) hLayout.addWidget(clearButton) self.verticalLayout.addWidget(options) self.display = QTextBrowser(self) self.display.setReadOnly(True) self.verticalLayout.addWidget(self.display) self.display.document().setMaximumBlockCount(500) self.max_displayed_msgs = self.MAX_DISPLAY_MSGS self._blocks_in_msg = None self.display.setOpenLinks(False) self.display.anchorClicked.connect(self._on_display_anchorClicked) self.status_label = QLabel('0 messages', self) self.verticalLayout.addWidget(self.status_label) # subscribe to the topic errmsg = '' try: self.__msg_class = message.get_message_class(msg_type) if not self.__msg_class: errmsg = "Cannot load message class for [%s]. Did you build messages?" % msg_type # raise Exception("Cannot load message class for [%s]. Did you build messages?"%msg_type) except Exception as e: self.__msg_class = None errmsg = "Cannot load message class for [%s]. Did you build messagest?\nError: %s" % ( msg_type, e) # raise Exception("Cannot load message class for [%s]. Did you build messagest?\nError: %s"%(msg_type, e)) # variables for Subscriber self.msg_signal.connect(self._append_message) self.sub = None # vairables for SSH connection self.ssh_output_file = None self.ssh_error_file = None self.ssh_input_file = None self.text_signal.connect(self._append_text) self.text_hz_signal.connect(self._append_text_hz) self._current_msg = '' self._current_errmsg = '' self.text_error_signal.connect(self._append_error_text) # decide, which connection to open if use_ssh: self.__msg_class = None self._on_display_anchorClicked(QUrl(self._masteruri)) elif self.__msg_class is None: errtxt = '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">\n%s</pre>' % ( errmsg) self.display.setText('<a href="%s">open using SSH</a>' % (masteruri)) self.display.append(errtxt) else: self.sub = rospy.Subscriber(self.topic, self.__msg_class, self._msg_handle) self.print_hz_timer = QTimer() self.print_hz_timer.timeout.connect(self._on_calc_hz) self.print_hz_timer.start(1000)
def __init__(self, topic, msg_type, show_only_rate=False, masteruri=None, use_ssh=False, parent=None): ''' Creates an input dialog. @param topic: the name of the topic @type topic: C{str} @param msg_type: the type of the topic @type msg_type: C{str} @raise Exception: if no topic class was found for the given type ''' QDialog.__init__(self, parent=parent) self._masteruri = masteruri masteruri_str = '' if masteruri is None else '[%s]' % masteruri echo_dialog_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'EchoDialog.ui') loadUi(echo_dialog_file, self) self.setObjectName(' - '.join(['EchoDialog', topic, masteruri_str])) self.setAttribute(Qt.WA_DeleteOnClose, True) self.setWindowFlags(Qt.Window) self.setWindowTitle('%s %s %s' % ('Echo --- ' if not show_only_rate else 'Hz --- ', topic, masteruri_str)) self.resize(900, 512) self.topic = topic self.show_only_rate = show_only_rate self.lock = threading.RLock() self.last_printed_count = 0 self.msg_t0 = -1. self.msg_tn = 0 self.times = [] self.bytes = [] self.message_count = 0 self._state_message = '' self._state_size_message = '' self._scrapped_msgs = 0 self._scrapped_msgs_sl = 0 self._last_received_ts = 0 self.chars_limit = self.MESSAGE_CHARS_LIMIT self.receiving_hz = self.MESSAGE_HZ_LIMIT self.line_limit = self.MESSAGE_LINE_LIMIT self.max_displayed_msgs = self.MAX_DISPLAY_MSGS self.digits_after_in_array = 2 self.field_filter_fn = None self._latched = False self._msgs = [] self.filterFrame.setVisible(False) self.topicControlButton.clicked.connect(self.on_topic_control_btn_clicked) self.clearButton.clicked.connect(self.on_clear_btn_clicked) if show_only_rate: self.filterButton.setVisible(False) else: self.filterButton.clicked.connect(self.on_filter_clicked) self.showStringsCheckBox.toggled.connect(self.on_no_str_checkbox_toggled) self.maxLenStringComboBox.activated[str].connect(self.combobox_reduce_ch_activated) self.showArraysCheckBox.toggled.connect(self.on_no_arr_checkbox_toggled) self.maxDigitsComboBox.activated[str].connect(self.combobox_reduce_digits_activated) self.maxLenComboBox.activated[str].connect(self.on_combobox_chars_activated) self.maxHzComboBox.activated[str].connect(self.on_combobox_hz_activated) self.displayCountComboBox.activated[str].connect(self.on_combobox_count_activated) self.combobox_reduce_ch_activated(self.MESSAGE_LINE_LIMIT) self.on_combobox_chars_activated(self.MESSAGE_CHARS_LIMIT) self.on_combobox_hz_activated(self.MESSAGE_HZ_LIMIT) self.on_combobox_count_activated(self.MAX_DISPLAY_MSGS) self.filterButton.setFocus() self.display.setReadOnly(True) self.display.document().setMaximumBlockCount(500) self._blocks_in_msg = None self.display.setOpenLinks(False) self.display.anchorClicked.connect(self._on_display_anchorClicked) # subscribe to the topic errmsg = '' try: self.__msg_class = message.get_message_class(msg_type) if not self.__msg_class: errmsg = "Cannot load message class for [%s]. Did you build messages?" % msg_type except Exception as e: self.__msg_class = None errmsg = "Cannot load message class for [%s]. Did you build messagest?\nError: %s" % (msg_type, e) # variables for Subscriber self.msg_signal.connect(self._append_message) self.sub = None # vairables for SSH connection self.ssh_output_file = None self.ssh_error_file = None self.ssh_input_file = None self.text_signal.connect(self._append_text) self.text_hz_signal.connect(self._append_text_hz) self._current_msg = '' self._current_errmsg = '' self.text_error_signal.connect(self._append_error_text) # decide, which connection to open if use_ssh: self.__msg_class = None self._on_display_anchorClicked(QUrl(self._masteruri)) elif self.__msg_class is None: errtxt = '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">\n%s</pre>' % (errmsg) self.display.setText('<a href="%s">open using SSH</a>' % (masteruri)) self.display.append(errtxt) else: self.sub = rospy.Subscriber(self.topic, self.__msg_class, self._msg_handle) self.print_hz_timer = QTimer() self.print_hz_timer.timeout.connect(self._on_calc_hz) self.print_hz_timer.start(1000) self._start_time = time.time()