plugin_handler_xembed_container.py
Go to the documentation of this file.
1 # Copyright (c) 2011, Dirk Thomas, Dorian Scholz, TU Darmstadt
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
6 # are met:
7 #
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following
12 # disclaimer in the documentation and/or other materials provided
13 # with the distribution.
14 # * Neither the name of the TU Darmstadt nor the names of its
15 # contributors may be used to endorse or promote products derived
16 # from this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 # POSSIBILITY OF SUCH DAMAGE.
30 
31 import sys
32 
33 from dbus.server import Server
34 from python_qt_binding import QT_BINDING
35 from python_qt_binding.QtCore import (QByteArray, QDataStream, qDebug, QIODevice,
36  QProcess, QSignalMapper, Qt, qWarning)
37 from python_qt_binding.QtGui import QIcon, QToolBar, QX11EmbedContainer
38 
39 from qt_gui.main import Main
40 from qt_gui.plugin_handler import PluginHandler
41 from qt_gui.plugin_handler_dbus_service import PluginHandlerDBusService
42 from qt_gui.settings_proxy_dbus_service import SettingsProxyDBusService
43 
44 
46  """
47  Server part of the `PluginHandlerXEmbed`.
48 
49  Starts the plugin in a subprocess and provides the `PluginHandlerDBusService` through a
50  peer-to-peer DBus connection.
51  """
52 
53  _serial_number = 0
54 
55  def __init__(self, parent, main_window, instance_id,
56  application_context, container_manager, argv, dbus_object_path):
57  super(PluginHandlerXEmbedContainer, self).__init__(
58  parent, main_window, instance_id, application_context, container_manager, argv)
59  self.setObjectName('PluginHandlerXEmbedContainer')
60 
61  self._dbus_object_path = dbus_object_path
62  self._dbus_server = None
66 
67  self._process = None
68  self._pid = None
69  # mapping of widget object name to their embed container
70  self._embed_containers = {}
71  # mapping of toolbar object name to the toolbar
72  self._embed_toolbars = {}
73  self._signal_mapper_toolbars = QSignalMapper(self)
74  self._signal_mapper_toolbars.mapped[str].connect(self._on_toolbar_orientation_changed)
75 
76  def _load(self):
77  if not Main.main_filename:
78  raise RuntimeError(
79  'PluginHandlerXEmbedContainer._load() '
80  'filename of initially started script is unknown')
81 
82  self._dbus_server = Server('tcp:bind=*')
83  self._dbus_server.on_connection_added.append(self._add_dbus_connection)
86  self._dbus_object_path + '/plugin')
88  self._dbus_object_path + '/instance')
89 
90  self._process = QProcess(self)
91  self._process.setProcessChannelMode(QProcess.SeparateChannels)
92  self._process.readyReadStandardOutput.connect(self._print_process_output)
93  self._process.readyReadStandardError.connect(self._print_process_error)
94  self._process.finished.connect(self._emit_close_plugin)
95  # start python with unbuffered stdout/stderr so that the order of the output is retained
96  cmd = sys.executable + ' -u'
97  cmd += ' %s' % Main.main_filename
98  cmd += ' --qt-binding=%s' % QT_BINDING
99  cmd += ' --embed-plugin=%s --embed-plugin-serial=%s --embed-plugin-address=%s' % (
100  self.instance_id().plugin_id, self.instance_id().serial_number,
101  self._dbus_server.address)
102  if self.argv():
103  cmd += ' --args %s' % ' '.join(self.argv())
104  # qDebug('PluginHandlerXEmbedContainer._load() starting command: %s' % cmd)
105  self._process.start(cmd)
106  started = self._process.waitForStarted(3000)
107  if not started:
108  self._dbus_container_service.remove_from_connection()
109  self._dbus_plugin_settings_service.remove_from_connection()
110  self._dbus_instance_settings_service.remove_from_connection()
111  raise RuntimeError(
112  'PluginHandlerXEmbedContainer._load() could not start '
113  'subprocess in reasonable time')
114  # QProcess.pid() has been added to PySide in 1.0.5
115  if hasattr(self._process, 'pid'):
116  self._pid = self._process.pid()
117  else:
118  # use serial number as a replacement for pid if not available
119  self.__class__._serial_number = self._serial_number + 1
120  self._pid = self._serial_number
121 
122  qDebug('PluginHandlerXEmbedContainer._load() started subprocess (#%s) for plugin "%s"' %
123  (self._pid, str(self._instance_id)))
124  # self._emit_load_completed is called asynchronous when client signals
125  # finished loading via dbus
126 
127  def _add_dbus_connection(self, conn):
128  self._dbus_container_service.add_to_connection(conn, self._dbus_object_path)
129  self._dbus_plugin_settings_service.add_to_connection(
130  conn, self._dbus_object_path + '/plugin')
131  self._dbus_instance_settings_service.add_to_connection(
132  conn, self._dbus_object_path + '/instance')
133 
135  self._print_process(self._process.readAllStandardOutput(), qDebug)
136 
138  self._print_process(self._process.readAllStandardError(), qWarning)
139 
140  def _print_process(self, data, method):
141  # indent process output and prefix it with the pid
142  lines = str(data).split('\n')
143  if lines[-1] == '':
144  lines.pop()
145  for line in lines:
146  method(' %d %s' % (self._pid, line))
147 
148  def load_completed(self, loaded, has_configuration):
149  # TODO timer to detect no response
150  exception = None if loaded else True
151  self._plugin_has_configuration = has_configuration
152  self._update_title_bars()
153  self._emit_load_completed(exception)
154 
155  def _shutdown_plugin(self):
156  qDebug('PluginHandlerXEmbedContainer._shutdown_plugin()')
157  self._process.finished.disconnect(self._emit_close_plugin)
159 
161  self._dbus_container_service.remove_from_connection()
162  self._dbus_plugin_settings_service.remove_from_connection()
163  self._dbus_instance_settings_service.remove_from_connection()
164 
165  self._process.close()
166  self._process.waitForFinished(5000)
167  if self._process.state() != QProcess.NotRunning:
168  self._process.kill()
169  self._process = None
170 
171  super(PluginHandlerXEmbedContainer, self).emit_shutdown_plugin_completed()
172 
173  def _unload(self):
174  qDebug('PluginHandlerXEmbedContainer._unload()')
176 
177  def _save_settings(self, plugin_settings, instance_settings):
178  qDebug('PluginHandlerXEmbedContainer._save_settings()')
179  self._dbus_plugin_settings_service.set_settings(plugin_settings)
180  self._dbus_instance_settings_service.set_settings(instance_settings)
182 
184  self._dbus_plugin_settings_service.set_settings(None)
185  self._dbus_instance_settings_service.set_settings(None)
186  super(PluginHandlerXEmbedContainer, self).emit_save_settings_completed()
187 
188  def _restore_settings(self, plugin_settings, instance_settings):
189  qDebug('PluginHandlerXEmbedContainer._restore_settings()')
190  self._dbus_plugin_settings_service.set_settings(plugin_settings)
191  self._dbus_instance_settings_service.set_settings(instance_settings)
193 
195  self._dbus_plugin_settings_service.set_settings(None)
196  self._dbus_instance_settings_service.set_settings(None)
197  super(PluginHandlerXEmbedContainer, self).emit_restore_settings_completed()
198 
200  self._dbus_container_service.trigger_configuration()
201 
202  def embed_widget(self, pid, widget_object_name):
203  dock_widget = self._create_dock_widget()
204  embed_container = QX11EmbedContainer(dock_widget)
205  # embed_container.clientClosed.connect(self._emit_close_signal)
206  self._add_dock_widget(dock_widget, embed_container)
207  # update widget title is triggered by client after embedding
208  self._embed_containers[widget_object_name] = embed_container
209  return embed_container.winId()
210 
211  def update_embedded_widget_icon(self, widget_object_name, icon_str):
212  embed_container = self._embed_containers[widget_object_name]
213  # deserialize icon base64-encoded string
214  ba = QByteArray.fromBase64(icon_str)
215  s = QDataStream(ba, QIODevice.ReadOnly)
216  icon = QIcon()
217  s >> icon
218  embed_container.setWindowIcon(icon)
219 
220  def update_embedded_widget_title(self, widget_object_name, title):
221  embed_container = self._embed_containers[widget_object_name]
222  embed_container.setWindowTitle(title)
223 
224  def unembed_widget(self, widget_object_name):
225  embed_container = self._embed_containers[widget_object_name]
226  self.remove_widget(embed_container)
227  del self._embed_containers[widget_object_name]
228 
229  def embed_toolbar(self, pid, toolbar_object_name):
230  toolbar = QToolBar()
231  toolbar.setObjectName(toolbar_object_name)
232  embed_container = QX11EmbedContainer(toolbar)
233  toolbar.addWidget(embed_container)
234  # embed_container.clientClosed.connect(self._emit_close_signal)
235  self._add_toolbar(toolbar)
236  self._embed_containers[toolbar_object_name] = embed_container
237  # setup mapping to signal change of orientation to client
238  self._embed_toolbars[toolbar_object_name] = toolbar
239  self._signal_mapper_toolbars.setMapping(toolbar, toolbar_object_name)
240  toolbar.orientationChanged.connect(self._signal_mapper_toolbars.map)
241  return embed_container.winId()
242 
243  def _on_toolbar_orientation_changed(self, toolbar_object_name):
244  embed_container = self._embed_containers[toolbar_object_name]
245  toolbar = self._embed_toolbars[toolbar_object_name]
246  self._dbus_container_service.toolbar_orientation_changed(
247  embed_container.winId(), toolbar.orientation() == Qt.Horizontal)
248 
249  def unembed_toolbar(self, toolbar_object_name):
250  embed_container = self._embed_containers[toolbar_object_name]
251  del self._embed_containers[toolbar_object_name]
252  del self._embed_toolbars[toolbar_object_name]
253  self.remove_toolbar(embed_container)
254  embed_container.close()
qt_gui.plugin_handler.PluginHandler.save_settings
def save_settings(self, plugin_settings, instance_settings, callback=None)
Definition: plugin_handler.py:181
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._pid
_pid
Definition: plugin_handler_xembed_container.py:67
qt_gui.plugin_handler.PluginHandler._instance_id
_instance_id
Definition: plugin_handler.py:61
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._add_dbus_connection
def _add_dbus_connection(self, conn)
Definition: plugin_handler_xembed_container.py:127
qt_gui.plugin_handler.PluginHandler.remove_toolbar
def remove_toolbar(self, toolbar)
Definition: plugin_handler.py:414
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.emit_shutdown_plugin_completed
def emit_shutdown_plugin_completed(self)
Definition: plugin_handler_xembed_container.py:160
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._dbus_instance_settings_service
_dbus_instance_settings_service
Definition: plugin_handler_xembed_container.py:64
qt_gui.plugin_handler.PluginHandler._create_dock_widget
def _create_dock_widget(self)
Definition: plugin_handler.py:250
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._signal_mapper_toolbars
_signal_mapper_toolbars
Definition: plugin_handler_xembed_container.py:72
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._on_toolbar_orientation_changed
def _on_toolbar_orientation_changed(self, toolbar_object_name)
Definition: plugin_handler_xembed_container.py:243
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.emit_restore_settings_completed
def emit_restore_settings_completed(self)
Definition: plugin_handler_xembed_container.py:194
qt_gui.plugin_handler_dbus_service.PluginHandlerDBusService
Definition: plugin_handler_dbus_service.py:37
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._dbus_object_path
_dbus_object_path
Definition: plugin_handler_xembed_container.py:60
qt_gui.plugin_handler.PluginHandler._plugin_has_configuration
_plugin_has_configuration
Definition: plugin_handler.py:73
qt_gui.plugin_handler.PluginHandler._emit_close_plugin
def _emit_close_plugin(self)
Definition: plugin_handler.py:428
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._dbus_plugin_settings_service
_dbus_plugin_settings_service
Definition: plugin_handler_xembed_container.py:63
qt_gui.plugin_handler.PluginHandler.remove_widget
def remove_widget(self, widget)
Definition: plugin_handler.py:368
qt_gui.plugin_handler.PluginHandler
Definition: plugin_handler.py:42
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._save_settings
def _save_settings(self, plugin_settings, instance_settings)
Definition: plugin_handler_xembed_container.py:177
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._embed_toolbars
_embed_toolbars
Definition: plugin_handler_xembed_container.py:71
qt_gui.plugin_handler.PluginHandler.argv
def argv(self)
Definition: plugin_handler.py:84
qt_gui.plugin_handler_dbus_service
Definition: plugin_handler_dbus_service.py:1
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._print_process_output
def _print_process_output(self)
Definition: plugin_handler_xembed_container.py:134
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.__init__
def __init__(self, parent, main_window, instance_id, application_context, container_manager, argv, dbus_object_path)
Definition: plugin_handler_xembed_container.py:55
qt_gui.settings_proxy_dbus_service.SettingsProxyDBusService
Definition: settings_proxy_dbus_service.py:34
qt_gui.plugin_handler.PluginHandler._emit_load_completed
def _emit_load_completed(self, exception=None)
Definition: plugin_handler.py:109
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._dbus_container_service
_dbus_container_service
Definition: plugin_handler_xembed_container.py:62
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._process
_process
Definition: plugin_handler_xembed_container.py:66
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._shutdown_plugin
def _shutdown_plugin(self)
Definition: plugin_handler_xembed_container.py:155
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._restore_settings
def _restore_settings(self, plugin_settings, instance_settings)
Definition: plugin_handler_xembed_container.py:188
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.update_embedded_widget_title
def update_embedded_widget_title(self, widget_object_name, title)
Definition: plugin_handler_xembed_container.py:220
qt_gui.plugin_handler.PluginHandler._update_title_bars
def _update_title_bars(self)
Definition: plugin_handler.py:299
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.load_completed
def load_completed(self, loaded, has_configuration)
Definition: plugin_handler_xembed_container.py:148
qt_gui.plugin_handler.PluginHandler._add_dock_widget
def _add_dock_widget(self, dock_widget, widget)
Definition: plugin_handler.py:318
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._trigger_configuration
def _trigger_configuration(self)
Definition: plugin_handler_xembed_container.py:199
qt_gui.settings_proxy_dbus_service
Definition: settings_proxy_dbus_service.py:1
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.update_embedded_widget_icon
def update_embedded_widget_icon(self, widget_object_name, icon_str)
Definition: plugin_handler_xembed_container.py:211
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.unembed_toolbar
def unembed_toolbar(self, toolbar_object_name)
Definition: plugin_handler_xembed_container.py:249
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.embed_widget
def embed_widget(self, pid, widget_object_name)
Definition: plugin_handler_xembed_container.py:202
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._serial_number
int _serial_number
Definition: plugin_handler_xembed_container.py:53
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._print_process_error
def _print_process_error(self)
Definition: plugin_handler_xembed_container.py:137
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._dbus_server
_dbus_server
Definition: plugin_handler_xembed_container.py:61
qt_gui.plugin_handler.PluginHandler.shutdown_plugin
def shutdown_plugin(self, callback)
Definition: plugin_handler.py:128
qt_gui.plugin_handler
Definition: plugin_handler.py:1
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._unload
def _unload(self)
Definition: plugin_handler_xembed_container.py:173
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.emit_save_settings_completed
def emit_save_settings_completed(self)
Definition: plugin_handler_xembed_container.py:183
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._print_process
def _print_process(self, data, method)
Definition: plugin_handler_xembed_container.py:140
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer
Definition: plugin_handler_xembed_container.py:45
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.unembed_widget
def unembed_widget(self, widget_object_name)
Definition: plugin_handler_xembed_container.py:224
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._embed_containers
_embed_containers
Definition: plugin_handler_xembed_container.py:69
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer._load
def _load(self)
Definition: plugin_handler_xembed_container.py:76
qt_gui.plugin_handler.PluginHandler.instance_id
def instance_id(self)
Definition: plugin_handler.py:81
qt_gui.plugin_handler.PluginHandler._emit_unload_completed
def _emit_unload_completed(self)
Definition: plugin_handler.py:175
qt_gui.main
Definition: main.py:1
qt_gui.plugin_handler.PluginHandler._add_toolbar
def _add_toolbar(self, toolbar)
Definition: plugin_handler.py:390
qt_gui.plugin_handler_xembed_container.PluginHandlerXEmbedContainer.embed_toolbar
def embed_toolbar(self, pid, toolbar_object_name)
Definition: plugin_handler_xembed_container.py:229
qt_gui.plugin_handler.PluginHandler.restore_settings
def restore_settings(self, plugin_settings, instance_settings, callback=None)
Definition: plugin_handler.py:221


qt_gui
Author(s): Dirk Thomas
autogenerated on Sat Jun 25 2022 02:15:05