-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStreamdeck_ui_drag_drop_icons.py
398 lines (339 loc) · 18.5 KB
/
Streamdeck_ui_drag_drop_icons.py
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# Bryan Randell 2022
# The Main UI launcher
import sys
import os
from PyQt5.QtWidgets import (QApplication, QLabel, QWidget, QHBoxLayout, QGridLayout, QPushButton,
QVBoxLayout, QMessageBox)
from PyQt5.QtGui import QDrag, QPixmap, QPainter, QImage
from PyQt5.QtCore import QMimeData, Qt, QRunnable, pyqtSlot, QThreadPool, pyqtSignal
from StreamDeck.DeviceManager import DeviceManager
from Utils.Streamdeck_button_configuration_class_key import StreamDeckInit
from Utils.Streamdeck_key_class import StreamDeckPage, LabelPageList
from Utils import Streamdeck_key_class
#todo implement the streamdeck.
#todo handle multiple pages
# dummy function for testing streamdeck implementation
def function_to_implement_streamdeck(deck_key_slot): #, icon_path, string_function):
print("button assign to{}".format(deck_key_slot))
# class RespondedToWorkerSignals(QObject):
# callback_from_worker = pyqtSignal()
#
#todo maybe useless for now or I don't know how to handle it
class Worker(QRunnable):
'''
Worker thread
'''
def __init__(self, streamdecks_instance):
super(Worker, self).__init__()
self.streamdecks_thread_instance = streamdecks_instance
@pyqtSlot()
def run(self):
'''
Your code goes in this function
'''
print('starting streamdeck')
# basic_usage.run()
# streamdeck_button_configuration.main(self.args[0])
# self.instance(streamdecks)
self.streamdecks_thread_instance.main_run()
class DraggableLabel(QLabel):
"""
Label with an icon a name and a function can be dragged to the streamdeck ui
"""
def __init__(self, parent, image,text):
super(QLabel,self).__init__(parent)
self.setText(text)
self._text = text
self.setPixmap(QPixmap(image))
self.show()
def text(self):
if self._text:
return self._text
return super().text()
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.drag_start_position = event.pos()
def mouseMoveEvent(self, event):
if not (event.buttons() & Qt.LeftButton):
return
if (event.pos() - self.drag_start_position).manhattanLength() < QApplication.startDragDistance():
return
drag = QDrag(self)
mimedata = QMimeData()
mimedata.setText(self.text())
mimedata.setImageData(self.pixmap().toImage())
# mimedata.setUrls(["test"])
drag.setMimeData(mimedata)
# pixmap = QPixmap(self.size())
pixmap = QPixmap(self.size())
# pixmap.scaledToWidth(50)
painter = QPainter(pixmap)
painter.drawPixmap(self.rect(), self.grab())
painter.end()
drag.setPixmap(pixmap)
drag.setHotSpot(event.pos())
drag.exec_(Qt.CopyAction | Qt.MoveAction)
class StreamDeckLabel(QLabel):
"""
Label representing the streamdeck buttons layout so the user can drag and drop his button and assign them
to the streamdeck
"""
def __init__(self, title, index, parent):
super().__init__(title, parent)
self.parent = parent
self.title = title
self.setAcceptDrops(True)
self.drop_item_path = "default_icon64.png"
self.index = index
# put the default item in the streamdeck button
function_to_implement_streamdeck(self.title)
def dragEnterEvent(self, event):
if event.mimeData().hasImage():
print("event accepted")
event.accept()
else:
print("event rejected")
event.ignore()
def dropEvent(self, event):
if event.mimeData().hasImage():
self.setPixmap(QPixmap.fromImage(QImage(event.mimeData().imageData())))
self.drop_item_path = event.mimeData().text()
# replace the default button by the new item dropped
function_to_implement_streamdeck(self.drop_item_path)
# basic_usage.set_button()
# streamdeck_button_configuration.update_key_image(streamdecks[0], , True)
print("{} assign to {}".format(self.title, self.drop_item_path))
self.parent.update_streamdeck_keys(self.index)
class Application(QWidget):
"""
A UI to assign multiple pages and personnalized button (both icon and function) to a streamdeck
Work in paralell with the streamdeck and has to be open so the streamdeck can work with
"""
valueChanged = pyqtSignal(int)
def __init__(self, streamdecks, user_button_list):
super().__init__()
#todo declare these varibles in a more pythonic way in the streamdeck_key_class.py file
# self.label_1, self.label_2, self.label_3, self.label_4, self.label_5, self.label_7,self.label_6, self.label_8, \
# self.label_9, self.label_10, self.label_11, self.label_12,self.label_13, self.label_14, \
# self.label_15 = None, None, None, None, None, None, None, None, None, None, None, None, None, None, None
#
# self.all_labels = [self.label_1, self.label_2, self.label_3, self.label_4, self.label_5, self.label_6,
# self.label_7, self.label_8, self.label_9, self.label_10, self.label_11, self.label_12,
# self.label_13, self.label_14, self.label_15]
# self.all_labels_page = [self.all_labels]
self.setWindowTitle("drag and drop streamdeck")
# initialize the streamdeck
self.streamdeck_instance = StreamDeckInit(streamdecks)
# get the streamdeck infos for creating the UI
self.streamdeck_button_count_vertically = self.streamdeck_instance.deck.KEY_COLS
self.streamdeck_button_count_horizontally = self.streamdeck_instance.deck.KEY_ROWS
self.streamdeck_button_count_total = self.streamdeck_instance.deck.KEY_COUNT
# initialize the second thread so the streamdeck can work in paralell with PyQt5
self.threadpool = QThreadPool()
self.worker = Worker(self.streamdeck_instance)
self.threadpool.start(self.worker)
# create the grid layouts
left_grid_layout = QGridLayout()
self.right_grid_layout_list = QGridLayout()
#todo put these on the steamdeck_key_class.py
self.assets_path = "assets/"
self.default_icon = "default_icon64.png"
icon_height = 50
icon_width = 50
# create the pages list for both streamdeck and grid layout
self._streamdeck_page_index = 0
self.streamdeck_page_list = [StreamDeckPage(self.streamdeck_button_count_total,
os.path.join(self.assets_path, self.default_icon))]
self.all_labels_page = [LabelPageList(self.streamdeck_button_count_total)]
# user_button_list is for the user to create specific buttons
self.user_button_list = user_button_list
# create the grid layout with user button
left_grid_loop_count = 0
for x in range(self.streamdeck_button_count_horizontally):
for y in range(self.streamdeck_button_count_vertically):
if left_grid_loop_count >= len(self.user_button_list): break
label_drag = DraggableLabel(self,
os.path.join(self.assets_path, self.user_button_list[left_grid_loop_count].icon),
self.user_button_list[left_grid_loop_count].icon)
left_grid_layout.addWidget(label_drag, x, y)
left_grid_loop_count += 1
# create the default grid representing the streamdeck layout
button_count = 1
for x in range(self.streamdeck_button_count_horizontally):
for y in range(self.streamdeck_button_count_vertically):
# button_list_label.append(my_label("Button {}".format(x+y),self))
self.all_labels_page[self.streamdeck_page_index][button_count - 1] = \
StreamDeckLabel("Button {}".format(button_count), button_count, self)
self.all_labels_page[self.streamdeck_page_index][button_count- 1].setPixmap(QPixmap.fromImage(
QImage(os.path.join(self.assets_path,"default_icon64.png"))))
# button_list_label[x+y].resize(50,50)
#todo try make an event for instantly uploading streamdeck buttons
self.right_grid_layout_list.addWidget(self.all_labels_page[self.streamdeck_page_index][button_count - 1], x, y)
self.streamdeck_page_list[self.streamdeck_page_index][button_count] = \
self.all_labels_page[self.streamdeck_page_index][button_count - 1].drop_item_path
button_count += 1
self.main_layout = QHBoxLayout(self)
vertical_layout = QVBoxLayout()
button_next_page = QPushButton("next page", self)
button_next_page.clicked.connect(self.next_page)
vertical_layout.addWidget(button_next_page)
button_previous_page = QPushButton("previous page", self)
button_previous_page.clicked.connect(self.previous_page)
vertical_layout.addWidget(button_previous_page)
self.label_page = QLabel("Page {}".format(self.streamdeck_page_index + 1))
vertical_layout.addWidget(self.label_page)
self.main_layout.addLayout(vertical_layout)
self.main_layout.addLayout(self.right_grid_layout_list)
self.main_layout.addLayout(left_grid_layout)
self.valueChanged.connect(self.change_page_streamdeck)
# ------- function with event ---------
# trigger the value change of the page index
@property
def streamdeck_page_index(self):
return self._streamdeck_page_index
@streamdeck_page_index.setter
def streamdeck_page_index(self, value):
self._streamdeck_page_index = value
self.valueChanged.emit(value)
print('page changed')
# def change_page_streamdeck(self):
# print('page changed 3')
def keyPressEvent(self, event):
"""
a simple key press event to quit the app
:param e:
:return:
"""
if event.key() == Qt.Key_Escape:
self.close()
def closeEvent(self, event):
"""
a close event handle to quit both the UI and the streamdeck instance who work in paralell
:param event:
:return:
"""
message_box = QMessageBox.question(self,
'Window and StreamDeck Close',
'Are you sure you want to close the window and the streamdeck?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
if message_box == QMessageBox.Yes:
if self.streamdeck_instance.deck.is_open():
print("deck up")
self.streamdeck_instance.deck.reset()
self.streamdeck_instance.deck.close()
event.accept()
# self.threadpool.terminate()
print('Window closed')
else:
event.ignore()
# ------- function for streamdeck ---------
def next_page(self):
self.streamdeck_page_index += 1
if len(self.streamdeck_page_list) <= self.streamdeck_page_index:
self.streamdeck_page_list.append(StreamDeckPage(self.streamdeck_button_count_total, self.default_icon))
self.all_labels_page.append(LabelPageList(self.streamdeck_button_count_total))
# self.right_grid_layout_list.append(QGridLayout())
# self.new_page()
self.delete_widgets_grid()
self.refresh_streamdeck_page()
print(self.streamdeck_page_list[self.streamdeck_page_index])
self.label_page.setText("Page {}".format(self.streamdeck_page_index + 1))
def previous_page(self):
if self.streamdeck_page_index > 0:
self.delete_widgets_grid()
self.streamdeck_page_index -= 1
self.refresh_streamdeck_page()
print(self.streamdeck_page_list[self.streamdeck_page_index])
self.label_page.setText("Page {}".format(self.streamdeck_page_index + 1))
def delete_widgets_grid(self):
"""
trying to refresh the streamdeck grid layout
:return:
"""
button_count = 1
for x in range(self.streamdeck_button_count_horizontally):
for y in range(self.streamdeck_button_count_vertically):
self.right_grid_layout_list.removeWidget(
self.all_labels_page[self.streamdeck_page_index - 1][button_count - 1])
def refresh_streamdeck_page(self):
"""
function used when the user change the page
:return:
"""
button_count = 1
for x in range(self.streamdeck_button_count_horizontally):
for y in range(self.streamdeck_button_count_vertically):
# button_list_label.append(my_label("Button {}".format(x+y),self))
self.all_labels_page[self.streamdeck_page_index][button_count - 1] = StreamDeckLabel("Button {}".format(button_count), button_count,self)
icon = self.streamdeck_page_list[self.streamdeck_page_index][button_count]
icon_press_path = self.streamdeck_page_list[self.streamdeck_page_index][button_count].split(".")[0] + "_press." + \
self.streamdeck_page_list[self.streamdeck_page_index][button_count].split(".")[1]
self.streamdeck_instance.key_list[button_count - 1].change_icons(icon, icon_press_path)
# self.streamdeck_instance.key_list[button].change_function()
self.streamdeck_instance.update_key_image(self.streamdeck_instance.deck, button_count - 1, False)
self.all_labels_page[self.streamdeck_page_index][button_count - 1].setPixmap(QPixmap.fromImage(QImage(os.path.join(self.assets_path,
icon))))
# button_list_label[x+y].resize(50,50)
# todo try make an event for instantly uploading streamdeck buttons
self.right_grid_layout_list.addWidget(self.all_labels_page[self.streamdeck_page_index][button_count - 1], x, y)
button_count += 1
def update_streamdeck_keys(self, index):
"""
this function is triggered when a user button is dragged to the streamdeck layout and refresh the streamdeck
:param index:
:return:
"""
self.streamdeck_page_list[self.streamdeck_page_index][index] = self.all_labels_page[self.streamdeck_page_index][index - 1].drop_item_path
icon = self.streamdeck_page_list[self.streamdeck_page_index][index]
icon_press_path = self.streamdeck_page_list[self.streamdeck_page_index][index].split(".")[0] + "_press." + self.streamdeck_page_list[self.streamdeck_page_index][index].split(".")[1]
self.streamdeck_instance.key_list[index - 1].change_icons(icon, icon_press_path)
# self.streamdeck_instance.key_list[button].change_function()
self.streamdeck_instance.update_key_image(self.streamdeck_instance.deck, index - 1, False)
print(self.streamdeck_page_list[self.streamdeck_page_index])
# # function used when the user change the page
# def refresh_streamdeck_page(self):
# button_count = 1
# for x in range(self.streamdeck_button_count_horizontally):
# for y in range(self.streamdeck_button_count_vertically):
# # button_list_label.append(my_label("Button {}".format(x+y),self))
# self.all_labels_page[self.streamdeck_page_index][button_count - 1] = StreamDeckLabel("Button {}".format(button_count), button_count,self)
# icon = self.streamdeck_page_list[self.streamdeck_page_index][button_count]
# self.all_labels_page[self.streamdeck_page_index][button_count - 1].setPixmap(QPixmap.fromImage(QImage(os.path.join(self.assets_path,
# icon))))
# # button_list_label[x+y].resize(50,50)
# # todo try make an event for instantly uploading streamdeck buttons
# self.right_grid_layout_list.addWidget(self.all_labels_page[self.streamdeck_page_index][button_count - 1], x, y)
# button_count += 1
# # may be useless
# def new_page(self):
# button_count = 1
# for x in range(self.streamdeck_button_count_horizontally):
# for y in range(self.streamdeck_button_count_vertically):
# # button_list_label.append(my_label("Button {}".format(x+y),self))
# self.all_labels_page[self.streamdeck_page_index][button_count - 1] = StreamDeckLabel("Button {}".format(button_count), button_count, self)
# self.all_labels_page[self.streamdeck_page_index][button_count- 1].setPixmap(QPixmap.fromImage(QImage(os.path.join(self.assets_path,
# "default_icon64.png"))))
# # button_list_label[x+y].resize(50,50)
# #todo try make an event for instantly uploading streamdeck buttons
#
# self.right_grid_layout_list.addWidget(self.all_labels_page[self.streamdeck_page_index][button_count - 1], x, y)
# self.streamdeck_page_list[self.streamdeck_page_index][button_count] = self.all_labels_page[self.streamdeck_page_index][button_count - 1].drop_item_path
# button_count += 1
#
# @pyqtSlot()
# def push_button_update_streamdeck(self):
# for button in range(len(self.streamdeck_page_list[self.streamdeck_page_index])):
# self.streamdeck_page_list[self.streamdeck_page_index][button + 1] = self.all_labels_page[self.streamdeck_page_index][button].drop_item_path
# icon_press_path = self.all_labels_page[self.streamdeck_page_index][button].drop_item_path.split(".")[0] + "_press." + self.all_labels_page[self.streamdeck_page_index][button].drop_item_path.split(".")[1]
# self.streamdeck_instance.key_list[button].change_icons(self.all_labels_page[self.streamdeck_page_index][button].drop_item_path, icon_press_path)
# # self.streamdeck_instance.key_list[button].change_function()
# self.streamdeck_instance.update_key_image(self.streamdeck_instance.deck, button, False)
#
# print(self.streamdeck_page_list[self.streamdeck_page_index])
if __name__ == "__main__":
user_button_list = Streamdeck_key_class.user_button_list
streamdecks = DeviceManager().enumerate()
app = QApplication(sys.argv)
fenetre = Application(streamdecks, user_button_list)
fenetre.show()
sys.exit(app.exec_())