Skip to content
74 changes: 69 additions & 5 deletions streamdeck_ui/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()


Expand All @@ -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()


Expand All @@ -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()


Expand All @@ -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()


Expand All @@ -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()


Expand All @@ -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()


Expand All @@ -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()


Expand Down Expand Up @@ -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()


Expand Down
55 changes: 45 additions & 10 deletions streamdeck_ui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,15 +294,15 @@ 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:
return ui.device_list.itemData(ui.device_list.currentIndex())


def _page(ui) -> int:
return ui.pages.currentIndex()
return ui.current_page.value()-1


def update_button_text(ui, text: str) -> None:
Expand Down Expand Up @@ -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)
Expand All @@ -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()
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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))
Expand All @@ -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))
Expand Down
Loading