Skip to content

Commit

Permalink
Merge pull request #163 from masqu3rad3/dev
Browse files Browse the repository at this point in the history
release 4.3.0
  • Loading branch information
masqu3rad3 authored Dec 17, 2024
2 parents bde85f4 + acdc28b commit 9ed4e1d
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 65 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [TIK-144] Improved filtering methodology for views.
- [TIK-142] Persistent UI size and position for the main window.
- [TIK-140] Shotgrid integration.
- [151] Added the ability to edit notes on works. Can be accessed with right-click context menu.
- Metadata improvements. Tasks can directly inherit and override metadata from upstream.

## v4.2.1
Expand Down
4 changes: 4 additions & 0 deletions tik_manager4/objects/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,10 @@ def notes(self):
"""The notes of the work version."""
return self._notes

@notes.setter
def notes(self, value):
self._notes = value

@property
def previews(self):
"""The previews of the work version."""
Expand Down
31 changes: 23 additions & 8 deletions tik_manager4/ui/mcv/version_mcv.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from tik_manager4.ui.Qt import QtWidgets, QtCore, QtGui
from tik_manager4.ui.dialog.feedback import Feedback
from tik_manager4.ui.widgets.common import TikButton, HorizontalSeparator, TikIconButton
from tik_manager4.ui.widgets.image import ImageWidget
from tik_manager4.ui.widgets.info import ImageWidget, NotesEditor
from tik_manager4.ui.dialog.bunde_ingest_dialog import BundleIngestDialog
from tik_manager4.core import filelog

Expand Down Expand Up @@ -97,7 +97,7 @@ class ElementWidgets:
@dataclass
class InfoWidgets:
notes_lbl: QtWidgets.QLabel
notes_editor: QtWidgets.QPlainTextEdit
notes_editor: NotesEditor
thumbnail: ImageWidget


Expand Down Expand Up @@ -150,7 +150,8 @@ def __init__(self, project_object, *args, **kwargs):

self.info = InfoWidgets(
notes_lbl=QtWidgets.QLabel("Notes: "),
notes_editor=QtWidgets.QPlainTextEdit(),
# notes_editor=QtWidgets.QPlainTextEdit(),
notes_editor=NotesEditor(),
thumbnail=ImageWidget()
)

Expand All @@ -164,6 +165,8 @@ def __init__(self, project_object, *args, **kwargs):
self.build_ui()
self.connect_signals()

self.set_base(self.base)

def build_ui(self):
"""Setup the UI."""
header_lay = QtWidgets.QHBoxLayout()
Expand Down Expand Up @@ -218,7 +221,7 @@ def build_ui(self):
notes_layout = QtWidgets.QVBoxLayout()
self.addLayout(notes_layout)
self.info.notes_lbl.setFont(QtGui.QFont("Arial", 10))
self.info.notes_editor.setReadOnly(True)
# self.info.notes_editor.setReadOnly(True)
notes_layout.addWidget(self.info.notes_lbl)
notes_layout.addWidget(self.info.notes_editor)

Expand Down Expand Up @@ -255,6 +258,7 @@ def connect_signals(self):
self.element.element_view_btn.clicked.connect(self.on_element_view_event)
self.header.refresh_btn.clicked.connect(self.refresh)
self.version.sync_btn.clicked.connect(self.on_sync_to_origin)
self.info.notes_editor.notes_updated.connect(self.__apply_to_base)

def on_sync_to_origin(self):
"""Sync the version to the origin."""
Expand Down Expand Up @@ -288,8 +292,7 @@ def on_sync_to_origin(self):
return
# if this is a work version, the work object should be updated as well
if _version.object_type == ObjectType.WORK_VERSION:
self.base._apply_versions()
self.base.apply_settings(force=True)
self.__apply_to_base()

self.toggle_sync_state(False)
self.status_updated.emit("Synced to origin.", 5000)
Expand Down Expand Up @@ -532,10 +535,14 @@ def set_base(self, base):
self.version.combo.setEnabled(False)
self.element.element_combo.clear()
self.info.notes_editor.clear()
self.info.notes_editor.setEnabled(False)
self.info.thumbnail.clear()
self.info.thumbnail.setEnabled(False)
self.toggle_sync_state(False)
return
self.version.combo.setEnabled(True)
self.info.notes_editor.setEnabled(True)
self.info.thumbnail.setEnabled(True)
self.base = base
self.populate_versions(base.versions)
self.version.combo.blockSignals(False)
Expand Down Expand Up @@ -622,9 +629,10 @@ def version_changed(self):
self.version.preview_btn.setEnabled(bool(_version.previews))
owner = _version.user
self.version.owner_lbl.setText(f"Owner: {owner}")
self.info.notes_editor.clear()
# self.info.notes_editor.clear()
self.info.thumbnail.clear()
self.info.notes_editor.setPlainText(_version.notes)
self.info.notes_editor.set_version(_version)
# self.info.notes_editor.setPlainText(_version.notes)
_thumbnail_path = self.base.get_abs_database_path(_version.thumbnail)
self.info.thumbnail.set_media(_thumbnail_path)
self.element.element_combo.blockSignals(False)
Expand Down Expand Up @@ -865,3 +873,10 @@ def publish_snapshot(self):
critical=False,
)

def __apply_to_base(self):
"""Apply the changes to the base object and persistent database."""
self.base._apply_versions()
self.base.apply_settings(force=True)



57 changes: 0 additions & 57 deletions tik_manager4/ui/widgets/image.py

This file was deleted.

145 changes: 145 additions & 0 deletions tik_manager4/ui/widgets/info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
"""Custom class for thumbnail section. Keeps the aspect ratio when resized."""
from pathlib import Path

from tik_manager4.core.constants import ObjectType
from tik_manager4.ui.Qt import QtWidgets, QtGui, QtCore
from tik_manager4.ui.widgets.common import TikButtonBox
from tik_manager4.ui import pick

class ImageWidget(QtWidgets.QLabel):
"""Custom class for thumbnail section. Keeps the aspect ratio when resized."""

def __init__(self):
super().__init__()
self.aspect_ratio = 1.78
size_policy = QtWidgets.QSizePolicy(
QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred
)
size_policy.setHeightForWidth(True)
self.setSizePolicy(size_policy)
self.setProperty("image", True)

self.is_movie = False
self.q_media = None

def set_media(self, media_path):
"""Set the media to the widget."""
if not Path(media_path).exists():
self.q_media = pick.pixmap("empty_thumbnail.png")
self.setPixmap(self.q_media)
self.is_movie = False
return
if Path(media_path).suffix.lower() in [".gif", ".webp"]:
self.q_media = QtGui.QMovie(media_path)
# don't start but show the first frame
self.q_media.jumpToFrame(0)
# self.q_media.start()
self.setAttribute(QtCore.Qt.WA_NoSystemBackground)
self.setMovie(self.q_media)
self.is_movie = True
else:
self.q_media = QtGui.QPixmap(media_path)
self.setPixmap(self.q_media)
self.is_movie = False

# start playing the movie if the mouse is over the widget
def enterEvent(self, _):
if self.is_movie:
self.q_media.start()

# pause playing it the mouse leaves the widget
def leaveEvent(self, _):
if self.is_movie:
self.q_media.setPaused(True)

def resizeEvent(self, _resize_event):
height = self.width()
self.setMinimumHeight(int(height / self.aspect_ratio))
self.setMaximumHeight(int(height / self.aspect_ratio))

class NotesEditor(QtWidgets.QPlainTextEdit):
"""Custom notes editor widget."""
notes_updated = QtCore.Signal()

def __init__(self, *args, **kwargs):
"""Initialize the NotesEditor."""
super().__init__(*args, **kwargs)
self.version_obj = None

self.setReadOnly(True)
self.setTabChangesFocus(True)
self.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap)

self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.right_click_menu)

def set_version(self, version_obj):
"""Set the base object."""
self.clear()
self.version_obj = version_obj
if self.version_obj:
self.setPlainText(version_obj.notes)

def can_edit(self):
"""Check if the notes can be edited."""
if not self.version_obj:
return False
if self.version_obj.object_type != ObjectType.WORK_VERSION:
return False
if self.version_obj.guard.user != self.version_obj.user:
return False
return True

def right_click_menu(self, position):
"""Right click menu for the notes editor."""
# Create the default context menu
right_click_menu = self.createStandardContextMenu()
# Add a separator
right_click_menu.addSeparator()

# Add custom actions
edit_action = QtWidgets.QAction(self.tr("Edit Notes"), self)
right_click_menu.addAction(edit_action)
edit_action.triggered.connect(self.show_edit_dialog)

# if there is no version obj, or the version is not a work version,
# disable the edit
if not self.can_edit():
edit_action.setEnabled(False)

# Execute the combined menu
right_click_menu.exec_(self.mapToGlobal(position))

def show_edit_dialog(self):
"""Pop-up a dialog to edit the notes."""
dialog = QtWidgets.QDialog(parent=self)
dialog.setModal(True)
dialog.setWindowTitle("Edit Notes")

layout = QtWidgets.QVBoxLayout()
dialog.setLayout(layout)

label = QtWidgets.QLabel("Edit Notes:")
layout.addWidget(label)

editor = QtWidgets.QPlainTextEdit()
editor.setPlainText(self.toPlainText())
layout.addWidget(editor)

buttonbox = TikButtonBox()
buttonbox.addButton("Ok", QtWidgets.QDialogButtonBox.AcceptRole)
buttonbox.addButton("Cancel", QtWidgets.QDialogButtonBox.RejectRole)
layout.addWidget(buttonbox)

buttonbox.accepted.connect(dialog.accept)
buttonbox.rejected.connect(dialog.reject)
# emit the notes_updated signal when the dialog is accepted
# buttonbox.accepted.connect(self.notes_updated.emit)

ret = dialog.exec_()
if ret:
if editor.toPlainText() == self.toPlainText():
return
self.setPlainText(editor.toPlainText())
self.version_obj.notes = self.toPlainText()
self.notes_updated.emit()

0 comments on commit 9ed4e1d

Please sign in to comment.