Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/model/media_assets/asset.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import TYPE_CHECKING
from uuid import uuid4

from model.media_assets.registry import register
from model.media_assets.registry import register, unregister

if TYPE_CHECKING:
from PySide6.QtGui import QPixmap
Expand Down Expand Up @@ -102,3 +102,7 @@ def is_local_resource(self) -> bool:
Non-local resources need to be provided and copied together with the show file.
"""
return False

def unregister(self) -> None:
"""Unregister this asset."""
unregister(self)
19 changes: 19 additions & 0 deletions src/model/media_assets/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ def register(asset: MediaAsset, uuid: str) -> bool:
d[uuid] = asset
return True

def unregister(asset: MediaAsset) -> bool:
"""Method unregisters a media asset.

Args:
asset: the media asset to unregister

Returns:
True if the asset was successfully unregistered, False otherwise.

"""
reg = _asset_library.get(asset.get_type())
if reg is None:
return False
try:
reg.pop(asset.id)
return True
except KeyError:
return False

def get_asset_by_uuid(uuid: str) -> MediaAsset | None:
"""Get a media asset by its UUID.

Expand Down
17 changes: 16 additions & 1 deletion src/view/dialogs/asset_mgmt_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ def __init__(self, parent: QWidget | None = None, show_file_path: str | None = N
self._load_asset_file.setText("Load asset from file")
self._load_asset_file.triggered.connect(self._open_file)
self._action_button_group.addAction(self._load_asset_file)
self._delete_selected_asset_action = QAction()
self._delete_selected_asset_action.setIcon(QIcon.fromTheme("edit-delete"))
self._delete_selected_asset_action.setText("Delete selected asset")
self._delete_selected_asset_action.triggered.connect(self._delete_selected_asset)
self._delete_selected_asset_action.setEnabled(False)
self._action_button_group.addAction(self._delete_selected_asset_action)

layout.addWidget(self._action_button_group)

self._asset_display = AssetSelectionWidget(self)
self._asset_display = AssetSelectionWidget(self, multiselection_allowed=True)
layout.addWidget(self._asset_display)

self._close_button_group = QDialogButtonBox(QDialogButtonBox.StandardButton.Close)
Expand All @@ -51,6 +57,7 @@ def __init__(self, parent: QWidget | None = None, show_file_path: str | None = N
self._dialog: QFileDialog | None = None
self._show_file_path = show_file_path if show_file_path is not None else ""
self.setMinimumWidth(800)
self._asset_display.asset_selection_changed.connect(self._selected_asset_changed)

def _open_file(self) -> None:
self._dialog = QFileDialog(self, "Open file")
Expand Down Expand Up @@ -90,3 +97,11 @@ def _process_loading_files(self, list_of_files: list[str]) -> None:
detailedText=accumulated_errors)
msg_box.show()
self._dialog = msg_box

def _selected_asset_changed(self) -> None:
self._delete_selected_asset_action.setEnabled(len(self._asset_display.selected_asset) > 0)

def _delete_selected_asset(self) -> None:
for asset in self._asset_display.selected_asset:
asset.unregister()
self._asset_display.reload_model()
52 changes: 52 additions & 0 deletions src/view/dialogs/asset_selection_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Provide a dialog for selecting assets."""

from __future__ import annotations

from typing import TYPE_CHECKING, override

from PySide6.QtCore import Qt, Signal
from PySide6.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QWidget
from qasync import QApplication

from model.media_assets.asset import MediaAsset
from view.utility_widgets.asset_selection_widget import AssetSelectionWidget

if TYPE_CHECKING:
from model.media_assets.media_type import MediaType


class AssetSelectionDialog(QDialog):
"""A dialog for selecting assets."""

asset_selected: Signal = Signal(MediaAsset)

def __init__(self, parent: QWidget | None = None,
allowed_types: list[MediaType] | None = None, multiselection_allowed: bool = False) -> None:
"""Initialize the dialog."""
super().__init__(parent)
layout = QVBoxLayout()

self._asset_view = AssetSelectionWidget(self, allowed_types, multiselection_allowed)
layout.addWidget(self._asset_view)

button_box = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, Qt.Orientation.Horizontal, self
)
layout.addWidget(button_box)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
self.setMinimumWidth(800)
self.setMinimumHeight(600)
self.setLayout(layout)

@override
def accept(self) -> None:
self.asset_selected.emit(self._asset_view.selected_asset)
QApplication.processEvents()
super().accept()
self.close()

@override
def reject(self) -> None:
super().reject()
self.close()
32 changes: 24 additions & 8 deletions src/view/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from view.misc.console_dock_widget import ConsoleDockWidget
from view.misc.settings.settings_dialog import SettingsDialog
from view.patch_view.patch_mode import PatchMode
from view.show_mode.editor.node_editor_widgets.cue_editor.yes_no_dialog import YesNoDialog
from view.show_mode.editor.showmanager import ShowEditorWidget
from view.show_mode.player.showplayer import ShowPlayerWidget
from view.utility_widgets.wizzards.patch_plan_export import PatchPlanExportWizard
Expand Down Expand Up @@ -136,6 +137,7 @@ def __init__(self, parent: QWidget = None) -> None:
self._terminal_widget: ConsoleDockWidget | None = None

self.setWindowIcon(QPixmap(resource_path(os.path.join("resources", "logo.png"))))
self._close_now = False

@property
def fish_connector(self) -> NetworkManager:
Expand Down Expand Up @@ -216,14 +218,6 @@ def _setup_menubar(self) -> None:
self._add_entries_to_menu(menu, entries)
self.menuBar().addAction(menu.menuAction())

@override
def closeEvent(self, event: QCloseEvent, /) -> None:
# TODO use event.ignore() here is there's still stuff to do
super().closeEvent(event)
QApplication.processEvents()
self._broadcaster.application_closing.emit()
QApplication.processEvents()

def _start_connection(self) -> None: # TODO rework to signals
self._fish_connector.start(True)

Expand Down Expand Up @@ -405,3 +399,25 @@ def _toggle_terminal(self) -> None:
def _open_asset_mgmt_dialog(self) -> None:
self._settings_dialog = AssetManagementDialog(self, self._board_configuration.file_path)
self._settings_dialog.show()

@override
def closeEvent(self, event: QCloseEvent) -> None:
if self._close_now:
super().closeEvent(event)
QApplication.processEvents()
self._broadcaster.application_closing.emit()
QApplication.processEvents()
else:
event.ignore()
self._settings_dialog = YesNoDialog(
self,
"Close Editor",
"Do you really want to close this window? Any unsaved changes will be lost.",
self._close_callback
)
self._settings_dialog.setModal(True)
self._settings_dialog.show()

def _close_callback(self) -> None:
self._close_now = True
self.close()
42 changes: 35 additions & 7 deletions src/view/show_mode/show_ui_widgets/macro_buttons_ui_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@
from model.media_assets.registry import get_asset_by_uuid
from utility import resource_path
from view.action_setup_view._command_insertion_dialog import escape_argument
from view.dialogs.asset_selection_dialog import AssetSelectionDialog
from view.show_mode.editor.editor_tab_widgets.ui_widget_editor._widget_holder import UIWidgetHolder
from view.show_mode.editor.show_browser.annotated_item import AnnotatedListWidgetItem
from view.utility_widgets.asset_selection_widget import AssetSelectionWidget
from view.utility_widgets.box_grid_renderer import BoxGridItem, BoxGridRenderer

if TYPE_CHECKING:
from model import UIPage
from model.media_assets.asset import MediaAsset


class _AddMacroActionDialog(QDialog):
Expand Down Expand Up @@ -108,12 +110,9 @@ def __init__(self, parent: QListWidget, item_def: dict[str, str], index: int, up
self._icon_bt.setIcon(self._NO_ICON)
layout.addWidget(self._icon_bt)
layout.addStretch()
icon_label = QLabel(self)
if self._item_def.get("icon", "") != "":
asset = get_asset_by_uuid(self._item_def["icon"])
if asset is not None:
icon_label.setPixmap(asset.get_thumbnail())
layout.addWidget(icon_label)
self.icon_label = QLabel(self)
self._update_displayed_icon()
layout.addWidget(self.icon_label)
layout.addStretch()
self._text_tb = QLineEdit(self)
self._text_tb.setText(item_def["text"])
Expand All @@ -125,7 +124,18 @@ def __init__(self, parent: QListWidget, item_def: dict[str, str], index: int, up
self._command_tb.textChanged.connect(self._command_changed)
layout.addWidget(self._command_tb)
self.setLayout(layout)
# TODO implement icon changing functionality
self._dialog: QDialog | None = None
self._icon_bt.pressed.connect(self._change_icon_of_button)

def _update_displayed_icon(self) -> None:
found_icon = False
if self._item_def.get("icon", "") != "":
asset = get_asset_by_uuid(self._item_def["icon"])
if asset is not None:
self.icon_label.setPixmap(asset.get_thumbnail())
found_icon = True
if not found_icon:
self.icon_label.setPixmap(self._NO_ICON.pixmap(64, 64))

def _text_changed(self, text: str) -> None:
self._item_def["text"] = text
Expand All @@ -135,6 +145,24 @@ def _command_changed(self, text: str) -> None:
self._item_def["command"] = text
self._update_button.setEnabled(True)

def _change_icon_of_button(self) -> None:
self._dialog = AssetSelectionDialog(self, allowed_types=[MediaType.IMAGE], multiselection_allowed=False)
self._dialog.setModal(True)
self._dialog.asset_selected.connect(self._icon_changed)
self._dialog.open()

def _icon_changed(self, asset: list[MediaAsset]) -> None:
self._dialog = None
if len(asset) == 0:
asset_id = ""
else:
asset = asset[-1]
asset_id = asset.id if asset is not None else ""
if asset_id != self._item_def.get("icon", ""):
self._update_button.setEnabled(True)
self._item_def["icon"] = asset_id
self._update_displayed_icon()

@property
def item_def(self) -> dict[str, str]:
return self._item_def
Expand Down
5 changes: 4 additions & 1 deletion src/view/utility_widgets/asset_selection_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import os
from typing import TYPE_CHECKING, Any, override

from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt
from PySide6.QtCore import QAbstractTableModel, QModelIndex, Qt, Signal
from PySide6.QtGui import QAction, QIcon
from PySide6.QtWidgets import QAbstractItemView, QLineEdit, QTableView, QToolBar, QVBoxLayout, QWidget

Expand Down Expand Up @@ -148,6 +148,8 @@ def get_row_indicies(self, assets: list[MediaAsset]) -> list[int]:
class AssetSelectionWidget(QWidget):
"""Provide a sortable and searchable selection widget for assets."""

asset_selection_changed: Signal = Signal()

def __init__(self, parent: QWidget | None = None, allowed_types: list[MediaType] | None = None,
multiselection_allowed: bool = True) -> None:
"""Initialize the asset selection widget.
Expand Down Expand Up @@ -199,6 +201,7 @@ def __init__(self, parent: QWidget | None = None, allowed_types: list[MediaType]

self.setLayout(layout)
self._update_filter()
self._asset_view.selectionModel().selectionChanged.connect(lambda: self.asset_selection_changed.emit())

def _update_filter(self, force: bool = False) -> None:
selected_types: set[MediaType] = set()
Expand Down