|
1 | 1 | import logging
|
| 2 | +import asyncio |
| 3 | +import shlex |
2 | 4 |
|
3 | 5 | from quamash import QtCore, QtGui, QtWidgets
|
4 | 6 | from pyqtgraph import dockarea
|
|
8 | 10 |
|
9 | 11 |
|
10 | 12 | class AppletDock(dockarea.Dock):
|
11 |
| - def __init__(self, token, name): |
| 13 | + def __init__(self, token, name, command): |
12 | 14 | dockarea.Dock.__init__(self, "applet" + str(token),
|
13 | 15 | label="Applet: " + name,
|
14 | 16 | closable=True)
|
15 | 17 | self.setMinimumSize(QtCore.QSize(500, 400))
|
| 18 | + self.token = token |
| 19 | + self.applet_name = name |
| 20 | + self.command = command |
| 21 | + |
| 22 | + async def start(self): |
| 23 | + command = self.command.format(embed_token=self.token) |
| 24 | + logger.debug("starting command %s for %s", command, self.applet_name) |
| 25 | + try: |
| 26 | + self.process = await asyncio.create_subprocess_exec( |
| 27 | + *shlex.split(command)) |
| 28 | + except FileNotFoundError: |
| 29 | + logger.warning("Applet %s failed to start", self.applet_name) |
| 30 | + else: |
| 31 | + logger.warning("Applet %s exited", self.applet_name) |
16 | 32 |
|
17 | 33 | def capture(self, win_id):
|
| 34 | + logger.debug("capturing window 0x%x for %s", win_id, self.applet_name) |
18 | 35 | self.captured_window = QtGui.QWindow.fromWinId(win_id)
|
19 |
| - self.captured_widget = QtWidgets.QWidget.createWindowContainer(captured_window) |
20 |
| - self.addWidget(captured_widget) |
| 36 | + self.captured_widget = QtWidgets.QWidget.createWindowContainer( |
| 37 | + self.captured_window) |
| 38 | + self.addWidget(self.captured_widget) |
21 | 39 |
|
22 |
| - def terminate(self): |
| 40 | + async def terminate(self): |
23 | 41 | if hasattr(self, "captured_window"):
|
24 | 42 | self.captured_window.close()
|
25 | 43 | self.captured_widget.deleteLater()
|
26 | 44 | del self.captured_window
|
27 | 45 | del self.captured_widget
|
| 46 | + if hasattr(self, "process"): |
| 47 | + try: |
| 48 | + await asyncio.wait_for(self.process.wait(), 2.0) |
| 49 | + except: |
| 50 | + logger.warning("Applet %s failed to exit, killing", |
| 51 | + self.applet_name) |
| 52 | + try: |
| 53 | + self.process.kill() |
| 54 | + except ProcessLookupError: |
| 55 | + pass |
| 56 | + await self.process.wait() |
28 | 57 |
|
29 | 58 |
|
30 | 59 | class AppletsDock(dockarea.Dock):
|
@@ -116,18 +145,24 @@ def embed(self, token, win_id):
|
116 | 145 | logger.warning("Ignored incorrect embed token %d for winid 0x%x",
|
117 | 146 | token, win_id)
|
118 | 147 | return
|
| 148 | + self.applet_docks[token].capture(win_id) |
119 | 149 |
|
120 | 150 | def create(self, name, command):
|
121 | 151 | token = next(iter(set(range(len(self.applet_docks) + 1))
|
122 |
| - - self.applet_docks.keys())) |
123 |
| - dock = AppletDock(token, name) |
| 152 | + - self.applet_docks.keys())) |
| 153 | + dock = AppletDock(token, name, command) |
124 | 154 | self.applet_docks[token] = dock
|
125 | 155 | self.dock_area.floatDock(dock)
|
| 156 | + asyncio.ensure_future(dock.start()) |
126 | 157 | return token
|
127 | 158 |
|
128 | 159 | def delete(self, token):
|
129 | 160 | del self.applet_docks[token]
|
130 | 161 |
|
| 162 | + async def stop(self): |
| 163 | + for dock in self.applet_docks.values(): |
| 164 | + await dock.terminate() |
| 165 | + |
131 | 166 | def save_state(self):
|
132 | 167 | return dict()
|
133 | 168 |
|
|
0 commit comments