diff --git a/client/ayon_core/tools/workfiles/widgets/files_widget.py b/client/ayon_core/tools/workfiles/widgets/files_widget.py
index f0b74f4289..b57192b27a 100644
--- a/client/ayon_core/tools/workfiles/widgets/files_widget.py
+++ b/client/ayon_core/tools/workfiles/widgets/files_widget.py
@@ -212,9 +212,11 @@ class FilesWidget(QtWidgets.QWidget):
return
self._controller.duplicate_workfile(
filepath,
- result["workdir"],
+ result["rootless_workdir"],
result["filename"],
- artist_note=result["artist_note"]
+ version=result["version"],
+ comment=result["comment"],
+ description=result["description"]
)
def _on_workarea_browse_clicked(self):
@@ -259,10 +261,12 @@ class FilesWidget(QtWidgets.QWidget):
self._controller.save_as_workfile(
result["folder_id"],
result["task_id"],
- result["workdir"],
+ result["rootless_workdir"],
result["filename"],
result["template_key"],
- artist_note=result["artist_note"]
+ version=result["version"],
+ comment=result["comment"],
+ description=result["description"]
)
def _on_workarea_path_changed(self, event):
@@ -315,7 +319,9 @@ class FilesWidget(QtWidgets.QWidget):
result["workdir"],
result["filename"],
result["template_key"],
- artist_note=result["artist_note"]
+ version=result["version"],
+ comment=result["comment"],
+ description=result["description"],
)
def _on_save_as_request(self):
diff --git a/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py b/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py
index 7f76b6a8ab..47d4902812 100644
--- a/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py
+++ b/client/ayon_core/tools/workfiles/widgets/files_widget_workarea.py
@@ -1,3 +1,5 @@
+import os
+
import qtawesome
from qtpy import QtWidgets, QtCore, QtGui
@@ -10,8 +12,10 @@ from ayon_core.tools.utils.delegates import PrettyTimeDelegate
FILENAME_ROLE = QtCore.Qt.UserRole + 1
FILEPATH_ROLE = QtCore.Qt.UserRole + 2
-AUTHOR_ROLE = QtCore.Qt.UserRole + 3
-DATE_MODIFIED_ROLE = QtCore.Qt.UserRole + 4
+ROOTLESS_PATH_ROLE = QtCore.Qt.UserRole + 3
+AUTHOR_ROLE = QtCore.Qt.UserRole + 4
+DATE_MODIFIED_ROLE = QtCore.Qt.UserRole + 5
+WORKFILE_ENTITY_ID_ROLE = QtCore.Qt.UserRole + 6
class WorkAreaFilesModel(QtGui.QStandardItemModel):
@@ -198,7 +202,7 @@ class WorkAreaFilesModel(QtGui.QStandardItemModel):
items_to_remove = set(self._items_by_filename.keys())
new_items = []
for file_item in file_items:
- filename = file_item.filename
+ filename = os.path.basename(file_item.filepath)
if filename in self._items_by_filename:
items_to_remove.discard(filename)
item = self._items_by_filename[filename]
@@ -206,23 +210,28 @@ class WorkAreaFilesModel(QtGui.QStandardItemModel):
item = QtGui.QStandardItem()
new_items.append(item)
item.setColumnCount(self.columnCount())
- item.setFlags(
- QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
- )
item.setData(self._file_icon, QtCore.Qt.DecorationRole)
- item.setData(file_item.filename, QtCore.Qt.DisplayRole)
- item.setData(file_item.filename, FILENAME_ROLE)
+ item.setData(filename, QtCore.Qt.DisplayRole)
+ item.setData(filename, FILENAME_ROLE)
+ flags = QtCore.Qt.ItemIsSelectable
+ if file_item.available:
+ flags |= QtCore.Qt.ItemIsEnabled
+ item.setFlags(flags)
updated_by = file_item.updated_by
user_item = user_items_by_name.get(updated_by)
if user_item is not None and user_item.full_name:
updated_by = user_item.full_name
+ item.setData(
+ file_item.workfile_entity_id, WORKFILE_ENTITY_ID_ROLE
+ )
item.setData(file_item.filepath, FILEPATH_ROLE)
+ item.setData(file_item.rootless_path, ROOTLESS_PATH_ROLE)
+ item.setData(file_item.file_modified, DATE_MODIFIED_ROLE)
item.setData(updated_by, AUTHOR_ROLE)
- item.setData(file_item.modified, DATE_MODIFIED_ROLE)
- self._items_by_filename[file_item.filename] = item
+ self._items_by_filename[filename] = item
if new_items:
root_item.appendRows(new_items)
@@ -354,14 +363,18 @@ class WorkAreaFilesWidget(QtWidgets.QWidget):
def _get_selected_info(self):
selection_model = self._view.selectionModel()
- filepath = None
- filename = None
+ workfile_entity_id = filename = rootless_path = filepath = None
for index in selection_model.selectedIndexes():
filepath = index.data(FILEPATH_ROLE)
+ rootless_path = index.data(ROOTLESS_PATH_ROLE)
filename = index.data(FILENAME_ROLE)
+ workfile_entity_id = index.data(WORKFILE_ENTITY_ID_ROLE)
+
return {
"filepath": filepath,
+ "rootless_path": rootless_path,
"filename": filename,
+ "workfile_entity_id": workfile_entity_id,
}
def get_selected_path(self):
@@ -374,8 +387,12 @@ class WorkAreaFilesWidget(QtWidgets.QWidget):
return self._get_selected_info()["filepath"]
def _on_selection_change(self):
- filepath = self.get_selected_path()
- self._controller.set_selected_workfile_path(filepath)
+ info = self._get_selected_info()
+ self._controller.set_selected_workfile_path(
+ info["rootless_path"],
+ info["filepath"],
+ info["workfile_entity_id"],
+ )
def _on_mouse_double_click(self, event):
if event.button() == QtCore.Qt.LeftButton:
@@ -430,19 +447,25 @@ class WorkAreaFilesWidget(QtWidgets.QWidget):
)
def _on_model_refresh(self):
- if (
- not self._change_selection_on_refresh
- or self._proxy_model.rowCount() < 1
- ):
+ if not self._change_selection_on_refresh:
return
# Find the row with latest date modified
+ indexes = [
+ self._proxy_model.index(idx, 0)
+ for idx in range(self._proxy_model.rowCount())
+ ]
+ filtered_indexes = [
+ index
+ for index in indexes
+ if self._proxy_model.flags(index) & QtCore.Qt.ItemIsEnabled
+ ]
+ if not filtered_indexes:
+ return
+
latest_index = max(
- (
- self._proxy_model.index(idx, 0)
- for idx in range(self._proxy_model.rowCount())
- ),
- key=lambda model_index: model_index.data(DATE_MODIFIED_ROLE)
+ filtered_indexes,
+ key=lambda model_index: model_index.data(DATE_MODIFIED_ROLE) or 0
)
# Select row of latest modified
diff --git a/client/ayon_core/tools/workfiles/widgets/save_as_dialog.py b/client/ayon_core/tools/workfiles/widgets/save_as_dialog.py
index bddff816fe..24d64319ca 100644
--- a/client/ayon_core/tools/workfiles/widgets/save_as_dialog.py
+++ b/client/ayon_core/tools/workfiles/widgets/save_as_dialog.py
@@ -108,6 +108,7 @@ class SaveAsDialog(QtWidgets.QDialog):
self._ext_value = None
self._filename = None
self._workdir = None
+ self._rootless_workdir = None
self._result = None
@@ -144,8 +145,8 @@ class SaveAsDialog(QtWidgets.QDialog):
version_layout.addWidget(last_version_check)
# Artist note widget
- artist_note_input = PlaceholderPlainTextEdit(inputs_widget)
- artist_note_input.setPlaceholderText(
+ description_input = PlaceholderPlainTextEdit(inputs_widget)
+ description_input.setPlaceholderText(
"Provide a note about this workfile.")
# Preview widget
@@ -166,7 +167,7 @@ class SaveAsDialog(QtWidgets.QDialog):
subversion_label = QtWidgets.QLabel("Subversion:", inputs_widget)
extension_label = QtWidgets.QLabel("Extension:", inputs_widget)
preview_label = QtWidgets.QLabel("Preview:", inputs_widget)
- artist_note_label = QtWidgets.QLabel("Artist Note:", inputs_widget)
+ description_label = QtWidgets.QLabel("Artist Note:", inputs_widget)
# Build inputs
inputs_layout = QtWidgets.QGridLayout(inputs_widget)
@@ -178,8 +179,8 @@ class SaveAsDialog(QtWidgets.QDialog):
inputs_layout.addWidget(extension_combobox, 2, 1)
inputs_layout.addWidget(preview_label, 3, 0)
inputs_layout.addWidget(preview_widget, 3, 1)
- inputs_layout.addWidget(artist_note_label, 4, 0, 1, 2)
- inputs_layout.addWidget(artist_note_input, 5, 0, 1, 2)
+ inputs_layout.addWidget(description_label, 4, 0, 1, 2)
+ inputs_layout.addWidget(description_input, 5, 0, 1, 2)
# Build layout
main_layout = QtWidgets.QVBoxLayout(self)
@@ -214,13 +215,13 @@ class SaveAsDialog(QtWidgets.QDialog):
self._extension_combobox = extension_combobox
self._subversion_input = subversion_input
self._preview_widget = preview_widget
- self._artist_note_input = artist_note_input
+ self._description_input = description_input
self._version_label = version_label
self._subversion_label = subversion_label
self._extension_label = extension_label
self._preview_label = preview_label
- self._artist_note_label = artist_note_label
+ self._description_label = description_label
# Post init setup
@@ -255,6 +256,7 @@ class SaveAsDialog(QtWidgets.QDialog):
self._folder_id = folder_id
self._task_id = task_id
self._workdir = data["workdir"]
+ self._rootless_workdir = data["rootless_workdir"]
self._comment_value = data["comment"]
self._ext_value = data["ext"]
self._template_key = data["template_key"]
@@ -329,10 +331,13 @@ class SaveAsDialog(QtWidgets.QDialog):
self._result = {
"filename": self._filename,
"workdir": self._workdir,
+ "rootless_workdir": self._rootless_workdir,
"folder_id": self._folder_id,
"task_id": self._task_id,
"template_key": self._template_key,
- "artist_note": self._artist_note_input.toPlainText(),
+ "version": self._version_value,
+ "comment": self._comment_value,
+ "description": self._description_input.toPlainText(),
}
self.close()
diff --git a/client/ayon_core/tools/workfiles/widgets/side_panel.py b/client/ayon_core/tools/workfiles/widgets/side_panel.py
index 7ba60b5544..2e146fddbe 100644
--- a/client/ayon_core/tools/workfiles/widgets/side_panel.py
+++ b/client/ayon_core/tools/workfiles/widgets/side_panel.py
@@ -4,6 +4,8 @@ from qtpy import QtWidgets, QtCore
def file_size_to_string(file_size):
+ if not file_size:
+ return "N/A"
size = 0
size_ending_mapping = {
"KB": 1024 ** 1,
@@ -43,44 +45,45 @@ class SidePanelWidget(QtWidgets.QWidget):
details_input = QtWidgets.QPlainTextEdit(self)
details_input.setReadOnly(True)
- artist_note_widget = QtWidgets.QWidget(self)
- note_label = QtWidgets.QLabel("Artist note", artist_note_widget)
- note_input = QtWidgets.QPlainTextEdit(artist_note_widget)
- btn_note_save = QtWidgets.QPushButton("Save note", artist_note_widget)
+ description_widget = QtWidgets.QWidget(self)
+ description_label = QtWidgets.QLabel("Artist note", description_widget)
+ description_input = QtWidgets.QPlainTextEdit(description_widget)
+ btn_description_save = QtWidgets.QPushButton("Save note", description_widget)
- artist_note_layout = QtWidgets.QVBoxLayout(artist_note_widget)
- artist_note_layout.setContentsMargins(0, 0, 0, 0)
- artist_note_layout.addWidget(note_label, 0)
- artist_note_layout.addWidget(note_input, 1)
- artist_note_layout.addWidget(
- btn_note_save, 0, alignment=QtCore.Qt.AlignRight
+ description_layout = QtWidgets.QVBoxLayout(description_widget)
+ description_layout.setContentsMargins(0, 0, 0, 0)
+ description_layout.addWidget(description_label, 0)
+ description_layout.addWidget(description_input, 1)
+ description_layout.addWidget(
+ btn_description_save, 0, alignment=QtCore.Qt.AlignRight
)
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.addWidget(details_label, 0)
main_layout.addWidget(details_input, 1)
- main_layout.addWidget(artist_note_widget, 1)
+ main_layout.addWidget(description_widget, 1)
- note_input.textChanged.connect(self._on_note_change)
- btn_note_save.clicked.connect(self._on_save_click)
+ description_input.textChanged.connect(self._on_description_change)
+ btn_description_save.clicked.connect(self._on_save_click)
controller.register_event_callback(
"selection.workarea.changed", self._on_selection_change
)
self._details_input = details_input
- self._artist_note_widget = artist_note_widget
- self._note_input = note_input
- self._btn_note_save = btn_note_save
+ self._description_widget = description_widget
+ self._description_input = description_input
+ self._btn_description_save = btn_description_save
self._folder_id = None
- self._task_name = None
+ self._task_id = None
self._filepath = None
- self._orig_note = ""
+ self._rootless_path = None
+ self._orig_description = ""
self._controller = controller
- self._set_context(None, None, None)
+ self._set_context(None, None, None, None)
def set_published_mode(self, published_mode):
"""Change published mode.
@@ -89,64 +92,69 @@ class SidePanelWidget(QtWidgets.QWidget):
published_mode (bool): Published mode enabled.
"""
- self._artist_note_widget.setVisible(not published_mode)
+ self._description_widget.setVisible(not published_mode)
def _on_selection_change(self, event):
folder_id = event["folder_id"]
- task_name = event["task_name"]
+ task_id = event["task_id"]
filepath = event["path"]
+ rootless_path = event["rootless_path"]
- self._set_context(folder_id, task_name, filepath)
+ self._set_context(folder_id, task_id, rootless_path, filepath)
- def _on_note_change(self):
- text = self._note_input.toPlainText()
- self._btn_note_save.setEnabled(self._orig_note != text)
+ def _on_description_change(self):
+ text = self._description_input.toPlainText()
+ self._btn_description_save.setEnabled(self._orig_description != text)
def _on_save_click(self):
- note = self._note_input.toPlainText()
+ description = self._description_input.toPlainText()
self._controller.save_workfile_info(
- self._folder_id,
- self._task_name,
- self._filepath,
- note
+ self._task_id,
+ self._rootless_path,
+ description=description,
)
- self._orig_note = note
- self._btn_note_save.setEnabled(False)
+ self._orig_description = description
+ self._btn_description_save.setEnabled(False)
- def _set_context(self, folder_id, task_name, filepath):
+ def _set_context(self, folder_id, task_id, rootless_path, filepath):
workfile_info = None
# Check if folder, task and file are selected
- if bool(folder_id) and bool(task_name) and bool(filepath):
+ if folder_id and task_id and rootless_path:
workfile_info = self._controller.get_workfile_info(
- folder_id, task_name, filepath
+ folder_id, task_id, rootless_path
)
enabled = workfile_info is not None
self._details_input.setEnabled(enabled)
- self._note_input.setEnabled(enabled)
- self._btn_note_save.setEnabled(enabled)
+ self._description_input.setEnabled(enabled)
+ self._btn_description_save.setEnabled(enabled)
self._folder_id = folder_id
- self._task_name = task_name
+ self._task_id = task_id
self._filepath = filepath
+ self._rootless_path = rootless_path
# Disable inputs and remove texts if any required arguments are
# missing
if not enabled:
- self._orig_note = ""
+ self._orig_description = ""
self._details_input.setPlainText("")
- self._note_input.setPlainText("")
+ self._description_input.setPlainText("")
return
- note = workfile_info.note
- size_value = file_size_to_string(workfile_info.filesize)
+ description = workfile_info.description
+ size_value = file_size_to_string(workfile_info.file_size)
# Append html string
datetime_format = "%b %d %Y %H:%M:%S"
- creation_time = datetime.datetime.fromtimestamp(
- workfile_info.creation_time)
- modification_time = datetime.datetime.fromtimestamp(
- workfile_info.modification_time)
+ file_created = workfile_info.file_created
+ modification_time = workfile_info.file_modified
+ if file_created:
+ file_created = datetime.datetime.fromtimestamp(file_created)
+
+ if modification_time:
+ modification_time = datetime.datetime.fromtimestamp(
+ modification_time)
user_items_by_name = self._controller.get_user_items_by_name()
@@ -156,33 +164,38 @@ class SidePanelWidget(QtWidgets.QWidget):
return user_item.full_name
return username
- created_lines = [
- creation_time.strftime(datetime_format)
- ]
+ created_lines = []
if workfile_info.created_by:
- created_lines.insert(
- 0, convert_username(workfile_info.created_by)
+ created_lines.append(
+ convert_username(workfile_info.created_by)
)
+ if file_created:
+ created_lines.append(file_created.strftime(datetime_format))
- modified_lines = [
- modification_time.strftime(datetime_format)
- ]
+ if created_lines:
+ created_lines.insert(0, "Created:")
+
+ modified_lines = []
if workfile_info.updated_by:
- modified_lines.insert(
- 0, convert_username(workfile_info.updated_by)
+ modified_lines.append(
+ convert_username(workfile_info.updated_by)
)
+ if modification_time:
+ modified_lines.append(
+ modification_time.strftime(datetime_format)
+ )
+ if modified_lines:
+ modified_lines.insert(0, "Modified:")
lines = (
"Size:",
size_value,
- "Created:",
"
".join(created_lines),
- "Modified:",
"
".join(modified_lines),
)
- self._orig_note = note
- self._note_input.setPlainText(note)
+ self._orig_description = description
+ self._description_input.setPlainText(description)
# Set as empty string
self._details_input.setPlainText("")
- self._details_input.appendHtml("
".join(lines))
+ self._details_input.appendHtml("
".join(lines))