-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathUSBIPManager.py
More file actions
226 lines (183 loc) · 8.3 KB
/
USBIPManager.py
File metadata and controls
226 lines (183 loc) · 8.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
from library import bar, compatibility, config, daemon, ini, lang, log, performance, queue
from library.modal import LoadDaemon, SelfSearch, SoftwareConfig, QueueManager
from sys import argv, exit
from asyncio import sleep, all_tasks, CancelledError
from PyQt5 import uic
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QMainWindow, QMenu, QAction, QMessageBox, QApplication
async def _processing(application):
""" Process all pending events - keep interface alive """
while True:
application.processEvents()
await sleep(0)
class USBIPManagerUI(QMainWindow):
""" Main window """
def __init__(self):
super(USBIPManagerUI, self).__init__()
uic.loadUi('ui/USBIPManager.ui', self)
self.setWindowIcon(QIcon('icon/logo.png'))
self._center()
self._sw_config = ini.SWConfig(self)
self._dmn_manager = ini.DaemonManage(self)
self._manager = queue.Manager(self)
self._atch_name = 'USBIP attach all'
self._dtch_name = 'USBIP detach all'
self._shutdown_name = 'Software shutdown'
_repr = config.ProgressRepr(self.progress, self.__class__.__name__)
self._bar = bar.Manager(_repr.replace())
self._perf = performance.Manager(self)
self._perf.load()
self._log = log.Manager(self)
self._lang = lang.USBIPManagerUI
self.self_search_btn.clicked.connect(self._self_search)
self.search_btn.clicked.connect(self._search_all)
self.atch_btn.clicked.connect(self._atch_all)
self.dtch_btn.clicked.connect(self._dtch_all)
self.load_btn.clicked.connect(self._scroll_load)
self.queue_btn.clicked.connect(self._queue_manager)
self.config_btn.clicked.connect(self._configuration)
self.doc_btn.clicked.connect(self._documentation)
self._popup_param = ('scroll', 'log')
self._scroll_param = ('poweroff', 'load', 'clear')
self._log_param = ('clear', )
for action in self._popup_param:
setattr(self, f'_popup_{action}', self._popup_action(action))
_popup = getattr(self, f'_popup_{action}')
_obj = getattr(self, action)
_obj.setContextMenuPolicy(Qt.CustomContextMenu)
_obj.customContextMenuRequested.connect(_popup)
setattr(self, f'_menu_{action}', QMenu())
_menu = getattr(self, f'_menu_{action}')
_action_param = getattr(self, f'_{action}_param')
for param in _action_param:
_icon = QIcon(f'icon/{param}.png')
_lang = getattr(self._lang, f'Popup{action.capitalize()}{param.capitalize()}')
setattr(self, f'_action_{action}_{param}', QAction(_icon, _lang, _obj))
_action = getattr(self, f'_action_{action}_{param}')
_action.triggered.connect(getattr(self, f'_{action}_{param}'))
_menu.addAction(_action)
for _daemon in self.__all():
_daemon.load()
def __repr__(self):
""" Printable class representation for queue manager modal window """
return f'{self.__class__.__name__}'
def __all(self):
""" Daemon manager generator to get all from the configuration """
for ip_addr in self._dmn_manager.get_all():
yield daemon.Manager(self, ip_addr)
def _popup_action(self, action):
""" Function template for context menu instance """
def _template(coordinate):
""" Show the right-click popup menu in the action area """
_menu = getattr(self, f'_menu_{action}')
_obj = getattr(self, action)
_menu.exec_(_obj.mapToGlobal(coordinate))
return _template
async def _atch_dtch_all(self, action):
""" Attach/Detach all action with global progress bar processing """
_global_pool = list()
for _daemon in self.__all():
_global_pool += _daemon.usbip_pool()
if not _global_pool:
_lang = getattr(self._lang, f'{action.capitalize()}Separator')
self._log.setWarning(f'{_lang} : {self._lang.PoolEmpty}')
return getattr(self, f'{action}_btn').setEnabled(True)
_ep = 100 / len(_global_pool)
_span = getattr(self._sw_config, f'dev_{action}_tmo')
for _daemon in self.__all():
_local_pool = _daemon.usbip_pool()
for device in _local_pool:
self._bar.setRange(_span, _ep)
getattr(device, action)(100 / len(_local_pool))
await sleep(_span + 0.25)
return getattr(self, f'{action}_btn').setEnabled(True)
def _center(self):
""" Center main application window based on the cursor position for multiple displays """
_frame = self.frameGeometry()
# noinspection PyArgumentList
_root = QApplication.desktop()
_active_screen = _root.screenNumber(_root.cursor().pos())
_center = _root.screenGeometry(_active_screen).center()
_frame.moveCenter(_center)
self.move(_frame.topLeft())
def _self_search(self):
""" Self search application menu button action """
_dialog = SelfSearch.SelfSearchUI(self)
_dialog.show()
def _search_all(self):
""" Search all application menu button action """
for _daemon in self.__all():
_daemon.search()
def _atch_all(self):
""" Attach all application menu button action """
self.atch_btn.setEnabled(False)
self._manager.exec(self._atch_dtch_all, self._atch_name, 'atch')
def _dtch_all(self):
""" Detach all application menu button action """
self.dtch_btn.setEnabled(False)
self._manager.exec(self._atch_dtch_all, self._dtch_name, 'dtch')
def _queue_manager(self):
""" Queue manager application menu button action """
_dialog = QueueManager.QueueManagerUI(self)
_dialog.show()
def _configuration(self):
""" Configuration application menu button action """
_dialog = SoftwareConfig.SoftwareConfigUI(self)
_dialog.show()
def _documentation(self):
""" Documentation application menu button action """
pass
def _scroll_poweroff(self):
""" Scroll area right-click popup menu poweroff action """
pass
def _scroll_load(self):
""" Load daemon application menu button action """
_dialog = LoadDaemon.LoadDaemonUI(self)
_dialog.show()
def _scroll_clear(self):
""" Scroll area right-click popup menu clear action """
pass
def _log_clear(self):
""" Log area right-click popup menu clear action """
self.log.clear()
async def _shutdown(self):
""" Detach all USBIP devices and software shutdown - coroutine """
self.setEnabled(False)
await self._atch_dtch_all('dtch')
for proc in all_tasks():
proc.cancel()
def _close_ok_btn(self):
""" OK button closing action - detach all USBIP devices and software shutdown """
self._manager.exec(self._shutdown, self._shutdown_name)
def _close_cancel_btn(self):
""" Cancel button closing action - pass """
pass
def _close_selection(self, btn):
""" Switch-case structure - closing action depending on the pressed button of the warning modal window """
return {
self._lang.MessageCloseOK: self._close_ok_btn,
self._lang.MessageCloseCancel: self._close_cancel_btn
}.get(btn.text(), self._lang.MessageCloseOK)
def closeEvent(self, event):
""" Main window closing action - detach all devices """
# TODO Message API
_warning = QMessageBox()
_warning.setWindowTitle(self._lang.MessageCloseTitle)
_warning.setText(self._lang.MessageCloseText)
_warning.setIcon(1)
_ok_btn = _warning.addButton(self._lang.MessageCloseOK, QMessageBox.YesRole)
_cancel_btn = _warning.addButton(self._lang.MessageCloseCancel, QMessageBox.NoRole)
_warning.exec_()
self._close_selection(_warning.clickedButton())()
event.ignore()
if __name__ == '__main__':
_application = QApplication(argv)
_comp = compatibility.System()
_loop = _comp.loop()
_ui = USBIPManagerUI()
_ui.show()
try:
_loop.run_until_complete(_processing(_application))
except CancelledError:
exit(0)