00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 import os
00032 import traceback
00033
00034 from dbus import Interface
00035 from dbus.connection import Connection
00036 from .plugin_handler_direct import PluginHandlerDirect
00037 from python_qt_binding.QtCore import qCritical, qDebug, Qt, qWarning, Slot
00038 from python_qt_binding.QtGui import QVBoxLayout, QX11EmbedWidget
00039 from .settings import Settings
00040 from .window_title_changed_signaler import WindowTitleChangedSignaler
00041
00042
00043 class PluginHandlerXEmbedClient(PluginHandlerDirect):
00044
00045 """
00046 Client part of the `PluginHandlerXEmbed`.
00047 It utilizes the `PluginHandlerDBusService` of the `PluginHandlerXEmbedContainer` through a peer-to-peer DBus connection.
00048 """
00049
00050 def __init__(self, parent, main_window, instance_id, application_context, container_manager, argv, dbus_object_path):
00051 super(PluginHandlerXEmbedClient, self).__init__(parent, main_window, instance_id, application_context, container_manager, argv)
00052 self.setObjectName('PluginHandlerXEmbedClient')
00053 self._dbus_object_path = dbus_object_path
00054 self._remote_container = None
00055 self._remote_plugin_settings = None
00056 self._remote_instance_settings = None
00057
00058 self._embed_widgets = {}
00059
00060 def _load(self):
00061 conn = Connection(self._application_context.options.embed_plugin_address)
00062 proxy = conn.get_object(None, self._dbus_object_path)
00063 self._remote_container = Interface(proxy, 'org.ros.qt_gui.PluginHandlerContainer')
00064 self._remote_container.connect_to_signal('shutdown_plugin', self._shutdown_plugin)
00065 self._remote_container.connect_to_signal('save_settings', self._save_settings_from_remote)
00066 self._remote_container.connect_to_signal('restore_settings', self._restore_settings_from_remote)
00067 self._remote_container.connect_to_signal('trigger_configuration', self._trigger_configuration)
00068 self._remote_container.connect_to_signal('toolbar_orientation_changed', self._toolbar_orientation_changed)
00069
00070 proxy = conn.get_object(None, self._dbus_object_path + '/plugin')
00071 self._remote_plugin_settings = Interface(proxy, 'org.ros.qt_gui.Settings')
00072 proxy = conn.get_object(None, self._dbus_object_path + '/instance')
00073 self._remote_instance_settings = Interface(proxy, 'org.ros.qt_gui.Settings')
00074
00075 super(PluginHandlerXEmbedClient, self)._load()
00076
00077 def _emit_load_completed(self, exception=None):
00078
00079 if exception is not None:
00080 self._remote_container.load_completed(False, False)
00081 super(PluginHandlerXEmbedClient, self)._emit_load_completed(exception)
00082
00083 if exception is None:
00084 self._remote_container.load_completed(True, self._plugin_has_configuration)
00085
00086 def shutdown_plugin(self, callback):
00087
00088 assert(False)
00089
00090 def emit_shutdown_plugin_completed(self):
00091 self._remote_container.shutdown_plugin_completed()
00092
00093 def save_settings(self, plugin_settings, instance_settings, callback=None):
00094
00095 assert(False)
00096
00097 def _save_settings_from_remote(self):
00098 qDebug('PluginHandlerXEmbedClient._save_settings_from_remote()')
00099 try:
00100 plugin_settings = Settings(self._remote_plugin_settings, '')
00101 instance_settings = Settings(self._remote_instance_settings, '')
00102 self._save_settings(plugin_settings, instance_settings)
00103 except Exception:
00104 qCritical('PluginHandlerXEmbedClient._save_settings_from_remote() plugin "%s" raised an exception:\n%s' % (str(self._instance_id), traceback.format_exc()))
00105 self.emit_save_settings_completed()
00106
00107 def emit_save_settings_completed(self):
00108 self._remote_container.save_settings_completed()
00109
00110 def restore_settings(self, plugin_settings, instance_settings, callback=None):
00111
00112 assert(False)
00113
00114 def _restore_settings_from_remote(self):
00115 qDebug('PluginHandlerXEmbedClient._restore_settings_from_remote()')
00116 try:
00117 plugin_settings = Settings(self._remote_plugin_settings, '')
00118 instance_settings = Settings(self._remote_instance_settings, '')
00119 self._restore_settings(plugin_settings, instance_settings)
00120 except Exception:
00121 qCritical('PluginHandlerXEmbedClient._restore_settings_from_remote() plugin "%s" raised an exception:\n%s' % (str(self._instance_id), traceback.format_exc()))
00122 self.emit_restore_settings_completed()
00123
00124 def emit_restore_settings_completed(self):
00125 self._remote_container.restore_settings_completed()
00126
00127
00128 @Slot('QWidget*')
00129 def add_widget(self, widget):
00130 if widget in self._embed_widgets:
00131 qWarning('PluginHandlerXEmbedClient.add_widget() widget "%s" already added' % widget.objectName())
00132 return
00133 embed_widget = QX11EmbedWidget()
00134 layout = QVBoxLayout()
00135 layout.setContentsMargins(0, 0, 0, 0)
00136 layout.addWidget(widget)
00137 embed_widget.setLayout(layout)
00138
00139
00140
00141
00142
00143 embed_container_window_id = self._remote_container.embed_widget(os.getpid(), widget.objectName())
00144 embed_widget.embedInto(embed_container_window_id)
00145
00146 signaler = WindowTitleChangedSignaler(widget, widget)
00147 signaler.window_title_changed_signal.connect(self._on_embed_widget_title_changed)
00148 self._embed_widgets[widget] = embed_widget, signaler
00149
00150 signaler.window_title_changed_signal.emit(widget)
00151
00152 embed_widget.show()
00153
00154 def _on_embed_widget_title_changed(self, widget):
00155 self._remote_container.update_embedded_widget_title(widget.objectName(), widget.windowTitle())
00156
00157
00158 @Slot('QWidget*')
00159 def remove_widget(self, widget):
00160 embed_widget, signaler = self._embed_widgets[widget]
00161 del self._embed_widgets[widget]
00162 signaler.window_title_changed_signal.disconnect(self._on_embed_widget_title_changed)
00163 self._remote_container.unembed_widget(widget.objectName())
00164
00165 widget.setParent(None)
00166 embed_widget.deleteLater()
00167
00168
00169
00170 @Slot('QToolBar*')
00171 def add_toolbar(self, toolbar):
00172 if toolbar in self._embed_widgets:
00173 qWarning('PluginHandlerXEmbedClient.add_toolbar() toolbar "%s" already added' % toolbar.objectName())
00174 return
00175 embed_widget = QX11EmbedWidget()
00176 layout = QVBoxLayout()
00177 layout.setContentsMargins(0, 0, 0, 0)
00178 layout.addWidget(toolbar)
00179 embed_widget.setLayout(layout)
00180
00181
00182
00183
00184 def foo():
00185 print('embed_widget.containerClosed')
00186 embed_widget.containerClosed.connect(foo)
00187
00188 embed_container_window_id = self._remote_container.embed_toolbar(os.getpid(), toolbar.objectName())
00189 embed_widget.embedInto(embed_container_window_id)
00190
00191 self._embed_widgets[toolbar] = embed_widget, None
00192
00193 embed_widget.show()
00194
00195 def _toolbar_orientation_changed(self, win_id, is_horizontal):
00196 for toolbar, (embed_widget, _) in self._embed_widgets.items():
00197 if embed_widget.containerWinId() == win_id:
00198 toolbar.setOrientation(Qt.Horizontal if is_horizontal else Qt.Vertical)
00199 break
00200
00201
00202 @Slot('QToolBar*')
00203 def remove_toolbar(self, toolbar):
00204 embed_widget, _ = self._embed_widgets[toolbar]
00205 del self._embed_widgets[toolbar]
00206 self._remote_container.unembed_widget(toolbar.objectName())
00207
00208 toolbar.setParent(None)
00209 embed_widget.deleteLater()
00210
00211
00212 def _emit_close_plugin(self):
00213 self._remote_container.close_plugin()