diff --git a/streamdeck_ui/api.py b/streamdeck_ui/api.py index bec89a1c..4760a623 100644 --- a/streamdeck_ui/api.py +++ b/streamdeck_ui/api.py @@ -147,6 +147,15 @@ def get_deck(deck_id: str) -> Dict[str, Dict[str, Union[str, Tuple[int, int]]]]: return {"type": decks[deck_id].deck_type(), "layout": decks[deck_id].key_layout()} +def _deck_state(deck_id: str) -> dict: + return state.setdefault(deck_id, {}) # type: ignore + + +def _page_state(deck_id: str, page: int) -> dict: + buttons = state.setdefault(deck_id, {}).setdefault("buttons", {}) + return buttons.setdefault(page, {}) # type: ignore + + def _button_state(deck_id: str, page: int, button: int) -> dict: buttons = state.setdefault(deck_id, {}).setdefault("buttons", {}) buttons_state = buttons.setdefault(page, {}) # type: ignore @@ -175,6 +184,8 @@ def set_button_text(deck_id: str, page: int, button: int, text: str) -> None: _button_state(deck_id, page, button)["text"] = text image_cache.pop(f"{deck_id}.{page}.{button}", None) render() + if not bool(text): + del_none_key(deck_id, page, button, "text") _save_state() @@ -189,6 +200,8 @@ def set_button_icon(deck_id: str, page: int, button: int, icon: str) -> None: _button_state(deck_id, page, button)["icon"] = icon image_cache.pop(f"{deck_id}.{page}.{button}", None) render() + if not bool(icon): + del_none_key(deck_id, page, button, "icon") _save_state() @@ -202,6 +215,8 @@ def set_button_change_brightness(deck_id: str, page: int, button: int, amount: i if get_button_change_brightness(deck_id, page, button) != amount: _button_state(deck_id, page, button)["brightness_change"] = amount render() + if amount == 0: + del_none_key(deck_id, page, button, "brightness_change") _save_state() @@ -213,7 +228,10 @@ def get_button_change_brightness(deck_id: str, page: int, button: int) -> int: def set_button_command(deck_id: str, page: int, button: int, command: str) -> None: """Sets the command associated with the button""" if get_button_command(deck_id, page, button) != command: - _button_state(deck_id, page, button)["command"] = command + if bool(command): + _button_state(deck_id, page, button)["command"] = command + else: + del_none_key(deck_id, page, button, "command") _save_state() @@ -225,7 +243,10 @@ def get_button_command(deck_id: str, page: int, button: int) -> str: def set_button_switch_page(deck_id: str, page: int, button: int, switch_page: int) -> None: """Sets the page switch associated with the button""" if get_button_switch_page(deck_id, page, button) != switch_page: - _button_state(deck_id, page, button)["switch_page"] = switch_page + if switch_page != 0: + _button_state(deck_id, page, button)["switch_page"] = switch_page + else: + del_none_key(deck_id, page, button, "switch_page") _save_state() @@ -234,10 +255,41 @@ def get_button_switch_page(deck_id: str, page: int, button: int) -> int: return _button_state(deck_id, page, button).get("switch_page", 0) +def set_pages_name(deck_id: str, page: int, page_name: str) -> None: + """Sets the page name for this page""" + if get_pages_name(deck_id, page) != page_name: + if "page_names" in _deck_state(deck_id): + if bool(page_name): + _deck_state(deck_id)["page_names"][str(page)] = page_name + else: + del _deck_state(deck_id)["page_names"][str(page)] + else: + _deck_state(deck_id)["page_names"] = {str(page): page_name} + _save_state() + + +def get_pages_name(deck_id: str, page: int) -> str: + """Returns the page name set for the specified page. {} implies no page name.""" + return _deck_state(deck_id).get("page_names", {str(page): f"Page {page+1}"}).get(str(page), f"Page {page+1}") + + +def get_page_length(deck_id: str) -> int: + """return the number of page count""" + return _deck_state(deck_id).get("buttons", {}).__len__() + + +def del_none_key(deck_id: str, page: int, button: int, key: str) -> None: + """Delete the state if it's not bool""" + del _button_state(deck_id, page, button)[key] + + def set_button_keys(deck_id: str, page: int, button: int, keys: str) -> None: """Sets the keys associated with the button""" if get_button_keys(deck_id, page, button) != keys: - _button_state(deck_id, page, button)["keys"] = keys + if bool(keys): + _button_state(deck_id, page, button)["keys"] = keys + else: + del_none_key(deck_id, page, button, "keys") _save_state() @@ -249,7 +301,10 @@ def get_button_keys(deck_id: str, page: int, button: int) -> str: def set_button_write(deck_id: str, page: int, button: int, write: str) -> None: """Sets the text meant to be written when button is pressed""" if get_button_write(deck_id, page, button) != write: - _button_state(deck_id, page, button)["write"] = write + if bool(write): + _button_state(deck_id, page, button)["write"] = write + else: + del_none_key(deck_id, page, button, "write") _save_state() @@ -281,11 +336,20 @@ def get_page(deck_id: str) -> int: return state.get(deck_id, {}).get("page", 0) # type: ignore -def set_page(deck_id: str, page: int) -> None: +def set_page(deck_id: str, page: int, old_page: int) -> None: """Sets the current page shown on the stream deck""" if get_page(deck_id) != page: state.setdefault(deck_id, {})["page"] = page render() + + # delete the state pages who is not bool + to_delete = [] + for button in _page_state(deck_id, old_page).items(): + if not bool(button[1]): + to_delete.append(button[0]) + if _page_state(deck_id, old_page).__len__() == to_delete.__len__(): + del _deck_state(deck_id)["buttons"][old_page] + _save_state() diff --git a/streamdeck_ui/gui.py b/streamdeck_ui/gui.py index 16a5f6b6..2dabc0eb 100644 --- a/streamdeck_ui/gui.py +++ b/streamdeck_ui/gui.py @@ -294,7 +294,7 @@ def handle_keypress(deck_id: str, key: int, state: bool) -> None: switch_page = api.get_button_switch_page(deck_id, page, key) if switch_page: - api.set_page(deck_id, switch_page - 1) + api.set_page(deck_id, switch_page - 1, page) def _deck_id(ui) -> str: @@ -302,7 +302,7 @@ def _deck_id(ui) -> str: def _page(ui) -> int: - return ui.pages.currentIndex() + return ui.current_page.value()-1 def update_button_text(ui, text: str) -> None: @@ -333,9 +333,35 @@ def update_change_brightness(ui, amount: int) -> None: def update_switch_page(ui, page: int) -> None: deck_id = _deck_id(ui) + ui.page_names.setCurrentIndex(page) api.set_button_switch_page(deck_id, _page(ui), selected_button.index, page) +def update_page_name(ui, name: str) -> None: + deck_id = _deck_id(ui) + api.set_pages_name(deck_id, _page(ui), name) + _update_page_names_items(ui) + + +def _update_page_names_items(ui): + deck_id = _deck_id(ui) + ui.page_names.clear() + ui.page_names.addItem("") + for page_number in range(api.get_page_length(deck_id)): + page_name = api.get_pages_name(deck_id, page_number) + if bool(page_name): + ui.page_names.addItem(page_name) + else: + ui.page_names.addItem(f"Page {page_number+1}") + ui.switch_page.setMaximum(ui.page_names.count()-1) + + +def update_page_names(ui, index: int) -> None: + if index == -1 or ui.page_names.count() == 1: + return + ui.switch_page.setValue(index) + + def _highlight_first_button(ui) -> None: button = ui.pages.currentWidget().findChildren(QtWidgets.QToolButton)[0] button.setChecked(False) @@ -344,7 +370,9 @@ def _highlight_first_button(ui) -> None: def change_page(ui, page: int) -> None: deck_id = _deck_id(ui) - api.set_page(deck_id, page) + old_page = api.get_page(deck_id) + api.set_page(deck_id, page-1, old_page) + ui.page_name.setText(api.get_pages_name(deck_id, _page(ui))) redraw_buttons(ui) _highlight_first_button(ui) dimmers[deck_id].reset() @@ -476,17 +504,22 @@ def import_config(window) -> None: def sync(ui) -> None: api.ensure_decks_connected() - ui.pages.setCurrentIndex(api.get_page(_deck_id(ui))) + ui.pages.setCurrentIndex(0) + ui.current_page.setValue(api.get_page(_deck_id(ui))+1) def build_device(ui, _device_index=None) -> None: - for page_id in range(ui.pages.count()): - page = ui.pages.widget(page_id) - page.setStyleSheet("background-color: black") - build_buttons(ui, page) + page = ui.pages.widget(0) + page.setStyleSheet("background-color: black") + build_buttons(ui, page) # Set the active page for this device - ui.pages.setCurrentIndex(api.get_page(_deck_id(ui))) + ui.current_page.setValue(api.get_page(_deck_id(ui))+1) + + # Set the number of the active page + deck_id = _deck_id(ui) + ui.page_name.setText(api.get_pages_name(deck_id, _page(ui))) + update_page_name(ui, api.get_pages_name(deck_id, _page(ui))) # Draw the buttons for the active page redraw_buttons(ui) @@ -631,6 +664,7 @@ def start(_exit: bool = False) -> None: ui.write.textChanged.connect(partial(update_button_write, ui)) ui.change_brightness.valueChanged.connect(partial(update_change_brightness, ui)) ui.switch_page.valueChanged.connect(partial(update_switch_page, ui)) + ui.page_names.currentIndexChanged.connect(partial(update_page_names, ui)) ui.imageButton.clicked.connect(partial(select_image, main_window)) ui.removeButton.clicked.connect(partial(remove_image, main_window)) ui.settingsButton.clicked.connect(partial(show_settings, main_window)) @@ -656,7 +690,8 @@ def start(_exit: bool = False) -> None: build_device(ui) ui.device_list.currentIndexChanged.connect(partial(build_device, ui)) - ui.pages.currentChanged.connect(partial(change_page, ui)) + ui.current_page.valueChanged.connect(partial(change_page, ui)) + ui.page_name.textChanged.connect(partial(update_page_name, ui)) ui.actionExport.triggered.connect(partial(export_config, main_window)) ui.actionImport.triggered.connect(partial(import_config, main_window)) diff --git a/streamdeck_ui/main.ui b/streamdeck_ui/main.ui index f7bf4598..2fd42a21 100644 --- a/streamdeck_ui/main.ui +++ b/streamdeck_ui/main.ui @@ -45,7 +45,7 @@ 0 - + 6 @@ -110,6 +110,40 @@ + + + + + + 1 + + + 999999 + + + + + + + Page Name + + + + + + + Current Page + + + + + + + + + + + @@ -127,66 +161,15 @@ 0 + + false + - Page 1 + - - - 2 - - - - - - 3 - - - - - - 4 - - - - - - 5 - - - - - - 6 - - - - - - 7 - - - - - - 8 - - - - - - 9 - - - - - - 10 - - - @@ -297,37 +280,40 @@ 0 - 10 + 999999 0 - + Brightness +/-: - + -99 - + Write Text: - + + + + @@ -375,6 +361,11 @@ Exit + + + Test2 + + diff --git a/streamdeck_ui/ui_main.py b/streamdeck_ui/ui_main.py index 2be7b794..9242eb18 100644 --- a/streamdeck_ui/ui_main.py +++ b/streamdeck_ui/ui_main.py @@ -8,11 +8,11 @@ ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ -from PySide2.QtCore import * # type: ignore -from PySide2.QtGui import * # type: ignore -from PySide2.QtWidgets import * # type: ignore +from PySide2.QtCore import * +from PySide2.QtGui import * +from PySide2.QtWidgets import * -from . import resources_rc +import resources_rc class Ui_MainWindow(object): def setupUi(self, MainWindow): @@ -25,6 +25,8 @@ def setupUi(self, MainWindow): self.actionExport.setObjectName(u"actionExport") self.actionExit = QAction(MainWindow) self.actionExit.setObjectName(u"actionExit") + self.actionTest2 = QAction(MainWindow) + self.actionTest2.setObjectName(u"actionTest2") self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.centralwidget.setAutoFillBackground(False) @@ -68,6 +70,38 @@ def setupUi(self, MainWindow): self.left_verticalLayout.addLayout(self.deviceSettings_horizontalLayout) + self.gridLayout = QGridLayout() + self.gridLayout.setObjectName(u"gridLayout") + self.current_page = QSpinBox(self.centralwidget) + self.current_page.setObjectName(u"current_page") + self.current_page.setMinimum(1) + self.current_page.setMaximum(999999) + + self.gridLayout.addWidget(self.current_page, 0, 1, 1, 1) + + self.label_9 = QLabel(self.centralwidget) + self.label_9.setObjectName(u"label_9") + + self.gridLayout.addWidget(self.label_9, 0, 2, 1, 1) + + self.label_4 = QLabel(self.centralwidget) + self.label_4.setObjectName(u"label_4") + + self.gridLayout.addWidget(self.label_4, 0, 0, 1, 1) + + self.page_name = QLineEdit(self.centralwidget) + self.page_name.setObjectName(u"page_name") + + self.gridLayout.addWidget(self.page_name, 0, 3, 1, 1) + + + self.left_verticalLayout.addLayout(self.gridLayout) + + self.formLayout_2 = QFormLayout() + self.formLayout_2.setObjectName(u"formLayout_2") + + self.left_verticalLayout.addLayout(self.formLayout_2) + self.pages = QTabWidget(self.centralwidget) self.pages.setObjectName(u"pages") sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) @@ -77,60 +111,16 @@ def setupUi(self, MainWindow): self.pages.setSizePolicy(sizePolicy1) self.pages.setAutoFillBackground(False) self.pages.setStyleSheet(u"b") + self.pages.setTabsClosable(False) self.page_1 = QWidget() self.page_1.setObjectName(u"page_1") self.gridLayout_2 = QGridLayout(self.page_1) self.gridLayout_2.setObjectName(u"gridLayout_2") self.pages.addTab(self.page_1, "") - self.page_2 = QWidget() - self.page_2.setObjectName(u"page_2") - self.gridLayout_3 = QGridLayout(self.page_2) - self.gridLayout_3.setObjectName(u"gridLayout_3") - self.pages.addTab(self.page_2, "") - self.page_3 = QWidget() - self.page_3.setObjectName(u"page_3") - self.gridLayout_11 = QGridLayout(self.page_3) - self.gridLayout_11.setObjectName(u"gridLayout_11") - self.pages.addTab(self.page_3, "") - self.page_4 = QWidget() - self.page_4.setObjectName(u"page_4") - self.gridLayout_10 = QGridLayout(self.page_4) - self.gridLayout_10.setObjectName(u"gridLayout_10") - self.pages.addTab(self.page_4, "") - self.page_5 = QWidget() - self.page_5.setObjectName(u"page_5") - self.gridLayout_9 = QGridLayout(self.page_5) - self.gridLayout_9.setObjectName(u"gridLayout_9") - self.pages.addTab(self.page_5, "") - self.page_6 = QWidget() - self.page_6.setObjectName(u"page_6") - self.gridLayout_8 = QGridLayout(self.page_6) - self.gridLayout_8.setObjectName(u"gridLayout_8") - self.pages.addTab(self.page_6, "") - self.page_7 = QWidget() - self.page_7.setObjectName(u"page_7") - self.gridLayout_7 = QGridLayout(self.page_7) - self.gridLayout_7.setObjectName(u"gridLayout_7") - self.pages.addTab(self.page_7, "") - self.page_8 = QWidget() - self.page_8.setObjectName(u"page_8") - self.gridLayout_6 = QGridLayout(self.page_8) - self.gridLayout_6.setObjectName(u"gridLayout_6") - self.pages.addTab(self.page_8, "") - self.page_9 = QWidget() - self.page_9.setObjectName(u"page_9") - self.gridLayout_5 = QGridLayout(self.page_9) - self.gridLayout_5.setObjectName(u"gridLayout_5") - self.pages.addTab(self.page_9, "") - self.tab_10 = QWidget() - self.tab_10.setObjectName(u"tab_10") - self.gridLayout_4 = QGridLayout(self.tab_10) - self.gridLayout_4.setObjectName(u"gridLayout_4") - self.pages.addTab(self.tab_10, "") self.left_verticalLayout.addWidget(self.pages) - self.left_verticalLayout.setStretch(1, 1) + self.left_verticalLayout.setStretch(3, 1) self.main_horizontalLayout.addLayout(self.left_verticalLayout) @@ -211,7 +201,7 @@ def setupUi(self, MainWindow): self.switch_page = QSpinBox(self.groupBox) self.switch_page.setObjectName(u"switch_page") self.switch_page.setMinimum(0) - self.switch_page.setMaximum(10) + self.switch_page.setMaximum(999999) self.switch_page.setValue(0) self.formLayout.setWidget(4, QFormLayout.FieldRole, self.switch_page) @@ -219,23 +209,28 @@ def setupUi(self, MainWindow): self.label_7 = QLabel(self.groupBox) self.label_7.setObjectName(u"label_7") - self.formLayout.setWidget(5, QFormLayout.LabelRole, self.label_7) + self.formLayout.setWidget(6, QFormLayout.LabelRole, self.label_7) self.change_brightness = QSpinBox(self.groupBox) self.change_brightness.setObjectName(u"change_brightness") self.change_brightness.setMinimum(-99) - self.formLayout.setWidget(5, QFormLayout.FieldRole, self.change_brightness) + self.formLayout.setWidget(6, QFormLayout.FieldRole, self.change_brightness) self.label_6 = QLabel(self.groupBox) self.label_6.setObjectName(u"label_6") - self.formLayout.setWidget(6, QFormLayout.LabelRole, self.label_6) + self.formLayout.setWidget(7, QFormLayout.LabelRole, self.label_6) self.write = QPlainTextEdit(self.groupBox) self.write.setObjectName(u"write") - self.formLayout.setWidget(6, QFormLayout.FieldRole, self.write) + self.formLayout.setWidget(7, QFormLayout.FieldRole, self.write) + + self.page_names = QComboBox(self.groupBox) + self.page_names.setObjectName(u"page_names") + + self.formLayout.setWidget(5, QFormLayout.FieldRole, self.page_names) self.verticalLayout_3.addLayout(self.formLayout) @@ -279,17 +274,11 @@ def retranslateUi(self, MainWindow): self.actionImport.setText(QCoreApplication.translate("MainWindow", u"Import", None)) self.actionExport.setText(QCoreApplication.translate("MainWindow", u"Export", None)) self.actionExit.setText(QCoreApplication.translate("MainWindow", u"Exit", None)) + self.actionTest2.setText(QCoreApplication.translate("MainWindow", u"Test2", None)) self.settingsButton.setText("") - self.pages.setTabText(self.pages.indexOf(self.page_1), QCoreApplication.translate("MainWindow", u"Page 1", None)) - self.pages.setTabText(self.pages.indexOf(self.page_2), QCoreApplication.translate("MainWindow", u"2", None)) - self.pages.setTabText(self.pages.indexOf(self.page_3), QCoreApplication.translate("MainWindow", u"3", None)) - self.pages.setTabText(self.pages.indexOf(self.page_4), QCoreApplication.translate("MainWindow", u"4", None)) - self.pages.setTabText(self.pages.indexOf(self.page_5), QCoreApplication.translate("MainWindow", u"5", None)) - self.pages.setTabText(self.pages.indexOf(self.page_6), QCoreApplication.translate("MainWindow", u"6", None)) - self.pages.setTabText(self.pages.indexOf(self.page_7), QCoreApplication.translate("MainWindow", u"7", None)) - self.pages.setTabText(self.pages.indexOf(self.page_8), QCoreApplication.translate("MainWindow", u"8", None)) - self.pages.setTabText(self.pages.indexOf(self.page_9), QCoreApplication.translate("MainWindow", u"9", None)) - self.pages.setTabText(self.pages.indexOf(self.tab_10), QCoreApplication.translate("MainWindow", u"10", None)) + self.label_9.setText(QCoreApplication.translate("MainWindow", u"Page Name", None)) + self.label_4.setText(QCoreApplication.translate("MainWindow", u"Current Page", None)) + self.pages.setTabText(self.pages.indexOf(self.page_1), "") self.groupBox.setTitle(QCoreApplication.translate("MainWindow", u"Configure Button", None)) self.label.setText(QCoreApplication.translate("MainWindow", u"Image:", None)) self.imageButton.setText(QCoreApplication.translate("MainWindow", u"Image...", None))