mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
720 lines
25 KiB
Python
720 lines
25 KiB
Python
import os
|
|
import logging
|
|
import shutil
|
|
|
|
import Qt
|
|
from Qt import QtWidgets, QtCore
|
|
from avalon import io, api
|
|
|
|
from openpype.tools.utils import PlaceholderLineEdit
|
|
from openpype.tools.utils.delegates import PrettyTimeDelegate
|
|
from openpype.lib import (
|
|
emit_event,
|
|
Anatomy,
|
|
get_workfile_template_key,
|
|
create_workdir_extra_folders,
|
|
)
|
|
from openpype.lib.avalon_context import (
|
|
update_current_task,
|
|
compute_session_changes
|
|
)
|
|
from openpype.pipeline import registered_host
|
|
from .model import (
|
|
WorkAreaFilesModel,
|
|
PublishFilesModel,
|
|
|
|
FILEPATH_ROLE,
|
|
DATE_MODIFIED_ROLE,
|
|
)
|
|
from .save_as_dialog import SaveAsDialog
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class FilesView(QtWidgets.QTreeView):
|
|
doubleClickedLeft = QtCore.Signal()
|
|
doubleClickedRight = QtCore.Signal()
|
|
|
|
def mouseDoubleClickEvent(self, event):
|
|
if event.button() == QtCore.Qt.LeftButton:
|
|
self.doubleClickedLeft.emit()
|
|
|
|
elif event.button() == QtCore.Qt.RightButton:
|
|
self.doubleClickedRight.emit()
|
|
|
|
return super(FilesView, self).mouseDoubleClickEvent(event)
|
|
|
|
|
|
class SelectContextOverlay(QtWidgets.QFrame):
|
|
def __init__(self, parent):
|
|
super(SelectContextOverlay, self).__init__(parent)
|
|
|
|
self.setObjectName("WorkfilesPublishedContextSelect")
|
|
label_widget = QtWidgets.QLabel(
|
|
"Please choose context on the left<br/><",
|
|
self
|
|
)
|
|
label_widget.setAlignment(QtCore.Qt.AlignCenter)
|
|
|
|
layout = QtWidgets.QHBoxLayout(self)
|
|
layout.addWidget(label_widget, 1, QtCore.Qt.AlignCenter)
|
|
|
|
label_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground)
|
|
|
|
parent.installEventFilter(self)
|
|
|
|
def eventFilter(self, obj, event):
|
|
if event.type() == QtCore.QEvent.Resize:
|
|
self.resize(obj.size())
|
|
|
|
return super(SelectContextOverlay, self).eventFilter(obj, event)
|
|
|
|
|
|
class FilesWidget(QtWidgets.QWidget):
|
|
"""A widget displaying files that allows to save and open files."""
|
|
file_selected = QtCore.Signal(str)
|
|
file_opened = QtCore.Signal()
|
|
workfile_created = QtCore.Signal(str)
|
|
published_visible_changed = QtCore.Signal(bool)
|
|
|
|
def __init__(self, parent):
|
|
super(FilesWidget, self).__init__(parent)
|
|
|
|
# Setup
|
|
self._asset_id = None
|
|
self._asset_doc = None
|
|
self._task_name = None
|
|
self._task_type = None
|
|
|
|
# Pype's anatomy object for current project
|
|
self.anatomy = Anatomy(io.Session["AVALON_PROJECT"])
|
|
# Template key used to get work template from anatomy templates
|
|
self.template_key = "work"
|
|
|
|
# This is not root but workfile directory
|
|
self._workfiles_root = None
|
|
self._workdir_path = None
|
|
self.host = registered_host()
|
|
|
|
# Whether to automatically select the latest modified
|
|
# file on a refresh of the files model.
|
|
self.auto_select_latest_modified = True
|
|
|
|
# Avoid crash in Blender and store the message box
|
|
# (setting parent doesn't work as it hides the message box)
|
|
self._messagebox = None
|
|
|
|
# Filtering input
|
|
filter_widget = QtWidgets.QWidget(self)
|
|
|
|
published_checkbox = QtWidgets.QCheckBox("Published", filter_widget)
|
|
|
|
filter_input = PlaceholderLineEdit(filter_widget)
|
|
filter_input.setPlaceholderText("Filter files..")
|
|
|
|
filter_layout = QtWidgets.QHBoxLayout(filter_widget)
|
|
filter_layout.setContentsMargins(0, 0, 0, 0)
|
|
filter_layout.addWidget(filter_input, 1)
|
|
filter_layout.addWidget(published_checkbox, 0)
|
|
|
|
# Create the Files models
|
|
extensions = set(self.host.file_extensions())
|
|
|
|
views_widget = QtWidgets.QWidget(self)
|
|
# --- Workarea view ---
|
|
workarea_files_model = WorkAreaFilesModel(extensions)
|
|
|
|
# Create proxy model for files to be able sort and filter
|
|
workarea_proxy_model = QtCore.QSortFilterProxyModel()
|
|
workarea_proxy_model.setSourceModel(workarea_files_model)
|
|
workarea_proxy_model.setDynamicSortFilter(True)
|
|
workarea_proxy_model.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
|
|
|
# Set up the file list tree view
|
|
workarea_files_view = FilesView(views_widget)
|
|
workarea_files_view.setModel(workarea_proxy_model)
|
|
workarea_files_view.setSortingEnabled(True)
|
|
workarea_files_view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
|
|
|
# Date modified delegate
|
|
workarea_time_delegate = PrettyTimeDelegate()
|
|
workarea_files_view.setItemDelegateForColumn(1, workarea_time_delegate)
|
|
# smaller indentation
|
|
workarea_files_view.setIndentation(3)
|
|
|
|
# Default to a wider first filename column it is what we mostly care
|
|
# about and the date modified is relatively small anyway.
|
|
workarea_files_view.setColumnWidth(0, 330)
|
|
|
|
# --- Publish files view ---
|
|
publish_files_model = PublishFilesModel(extensions, io, self.anatomy)
|
|
|
|
publish_proxy_model = QtCore.QSortFilterProxyModel()
|
|
publish_proxy_model.setSourceModel(publish_files_model)
|
|
publish_proxy_model.setDynamicSortFilter(True)
|
|
publish_proxy_model.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
|
|
|
publish_files_view = FilesView(views_widget)
|
|
publish_files_view.setModel(publish_proxy_model)
|
|
|
|
publish_files_view.setSortingEnabled(True)
|
|
publish_files_view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
|
|
|
# Date modified delegate
|
|
publish_time_delegate = PrettyTimeDelegate()
|
|
publish_files_view.setItemDelegateForColumn(1, publish_time_delegate)
|
|
# smaller indentation
|
|
publish_files_view.setIndentation(3)
|
|
|
|
# Default to a wider first filename column it is what we mostly care
|
|
# about and the date modified is relatively small anyway.
|
|
publish_files_view.setColumnWidth(0, 330)
|
|
|
|
publish_context_overlay = SelectContextOverlay(views_widget)
|
|
publish_context_overlay.setVisible(False)
|
|
|
|
views_layout = QtWidgets.QHBoxLayout(views_widget)
|
|
views_layout.setContentsMargins(0, 0, 0, 0)
|
|
views_layout.addWidget(workarea_files_view, 1)
|
|
views_layout.addWidget(publish_files_view, 1)
|
|
|
|
# Home Page
|
|
# Build buttons widget for files widget
|
|
btns_widget = QtWidgets.QWidget(self)
|
|
|
|
workarea_btns_widget = QtWidgets.QWidget(btns_widget)
|
|
btn_save = QtWidgets.QPushButton("Save As", workarea_btns_widget)
|
|
btn_browse = QtWidgets.QPushButton("Browse", workarea_btns_widget)
|
|
btn_open = QtWidgets.QPushButton("Open", workarea_btns_widget)
|
|
|
|
workarea_btns_layout = QtWidgets.QHBoxLayout(workarea_btns_widget)
|
|
workarea_btns_layout.setContentsMargins(0, 0, 0, 0)
|
|
workarea_btns_layout.addWidget(btn_open, 1)
|
|
workarea_btns_layout.addWidget(btn_browse, 1)
|
|
workarea_btns_layout.addWidget(btn_save, 1)
|
|
|
|
publish_btns_widget = QtWidgets.QWidget(btns_widget)
|
|
btn_save_as_published = QtWidgets.QPushButton(
|
|
"Copy && Open", publish_btns_widget
|
|
)
|
|
btn_change_context = QtWidgets.QPushButton(
|
|
"Choose different context", publish_btns_widget
|
|
)
|
|
btn_select_context_published = QtWidgets.QPushButton(
|
|
"Copy && Open", publish_btns_widget
|
|
)
|
|
btn_cancel_published = QtWidgets.QPushButton(
|
|
"Cancel", publish_btns_widget
|
|
)
|
|
|
|
publish_btns_layout = QtWidgets.QHBoxLayout(publish_btns_widget)
|
|
publish_btns_layout.setContentsMargins(0, 0, 0, 0)
|
|
publish_btns_layout.addWidget(btn_save_as_published, 1)
|
|
publish_btns_layout.addWidget(btn_change_context, 1)
|
|
publish_btns_layout.addWidget(btn_select_context_published, 1)
|
|
publish_btns_layout.addWidget(btn_cancel_published, 1)
|
|
|
|
btns_layout = QtWidgets.QHBoxLayout(btns_widget)
|
|
btns_layout.setContentsMargins(0, 0, 0, 0)
|
|
btns_layout.addWidget(workarea_btns_widget, 1)
|
|
btns_layout.addWidget(publish_btns_widget, 1)
|
|
|
|
# Build files widgets for home page
|
|
main_layout = QtWidgets.QVBoxLayout(self)
|
|
main_layout.setContentsMargins(0, 0, 0, 0)
|
|
main_layout.addWidget(filter_widget, 0)
|
|
main_layout.addWidget(views_widget, 1)
|
|
main_layout.addWidget(btns_widget, 0)
|
|
|
|
# Register signal callbacks
|
|
published_checkbox.stateChanged.connect(self._on_published_change)
|
|
filter_input.textChanged.connect(self._on_filter_text_change)
|
|
|
|
workarea_files_view.doubleClickedLeft.connect(
|
|
self._on_workarea_open_pressed
|
|
)
|
|
workarea_files_view.customContextMenuRequested.connect(
|
|
self._on_workarea_context_menu
|
|
)
|
|
workarea_files_view.selectionModel().selectionChanged.connect(
|
|
self.on_file_select
|
|
)
|
|
|
|
btn_open.pressed.connect(self._on_workarea_open_pressed)
|
|
btn_browse.pressed.connect(self.on_browse_pressed)
|
|
btn_save.pressed.connect(self._on_save_as_pressed)
|
|
btn_save_as_published.pressed.connect(
|
|
self._on_published_save_as_pressed
|
|
)
|
|
btn_change_context.pressed.connect(
|
|
self._on_publish_change_context_pressed
|
|
)
|
|
btn_select_context_published.pressed.connect(
|
|
self._on_publish_select_context_pressed
|
|
)
|
|
btn_cancel_published.pressed.connect(
|
|
self._on_publish_cancel_pressed
|
|
)
|
|
|
|
# Store attributes
|
|
self._published_checkbox = published_checkbox
|
|
self._filter_input = filter_input
|
|
|
|
self._workarea_time_delegate = workarea_time_delegate
|
|
self._workarea_files_view = workarea_files_view
|
|
self._workarea_files_model = workarea_files_model
|
|
self._workarea_proxy_model = workarea_proxy_model
|
|
|
|
self._publish_time_delegate = publish_time_delegate
|
|
self._publish_files_view = publish_files_view
|
|
self._publish_files_model = publish_files_model
|
|
self._publish_proxy_model = publish_proxy_model
|
|
|
|
self._publish_context_overlay = publish_context_overlay
|
|
|
|
self._workarea_btns_widget = workarea_btns_widget
|
|
self._publish_btns_widget = publish_btns_widget
|
|
self._btn_open = btn_open
|
|
self._btn_browse = btn_browse
|
|
self._btn_save = btn_save
|
|
|
|
self._btn_save_as_published = btn_save_as_published
|
|
self._btn_change_context = btn_change_context
|
|
self._btn_select_context_published = btn_select_context_published
|
|
self._btn_cancel_published = btn_cancel_published
|
|
|
|
# Create a proxy widget for files widget
|
|
self.setFocusProxy(btn_open)
|
|
|
|
# Hide publish files widgets
|
|
publish_files_view.setVisible(False)
|
|
publish_btns_widget.setVisible(False)
|
|
btn_select_context_published.setVisible(False)
|
|
btn_cancel_published.setVisible(False)
|
|
|
|
self._publish_context_select_mode = False
|
|
|
|
@property
|
|
def published_enabled(self):
|
|
return self._published_checkbox.isChecked()
|
|
|
|
def _on_published_change(self):
|
|
published_enabled = self.published_enabled
|
|
|
|
self._workarea_files_view.setVisible(not published_enabled)
|
|
self._workarea_btns_widget.setVisible(not published_enabled)
|
|
|
|
self._publish_files_view.setVisible(published_enabled)
|
|
self._publish_btns_widget.setVisible(published_enabled)
|
|
|
|
self._update_filtering()
|
|
self._update_asset_task()
|
|
|
|
self.published_visible_changed.emit(published_enabled)
|
|
|
|
self._select_last_modified_file()
|
|
|
|
def _on_filter_text_change(self):
|
|
self._update_filtering()
|
|
|
|
def _update_filtering(self):
|
|
text = self._filter_input.text()
|
|
if self.published_enabled:
|
|
self._publish_proxy_model.setFilterFixedString(text)
|
|
else:
|
|
self._workarea_proxy_model.setFilterFixedString(text)
|
|
|
|
def set_save_enabled(self, enabled):
|
|
self._btn_save.setEnabled(enabled)
|
|
if not enabled and self._published_checkbox.isChecked():
|
|
self._published_checkbox.setChecked(False)
|
|
self._published_checkbox.setVisible(enabled)
|
|
|
|
def set_asset_task(self, asset_id, task_name, task_type):
|
|
if asset_id != self._asset_id:
|
|
self._asset_doc = None
|
|
self._asset_id = asset_id
|
|
self._task_name = task_name
|
|
self._task_type = task_type
|
|
self._update_asset_task()
|
|
|
|
def _update_asset_task(self):
|
|
if self.published_enabled and not self._publish_context_select_mode:
|
|
self._publish_files_model.set_context(
|
|
self._asset_id, self._task_name
|
|
)
|
|
has_valid_items = self._publish_files_model.has_valid_items()
|
|
self._btn_save_as_published.setEnabled(has_valid_items)
|
|
self._btn_change_context.setEnabled(has_valid_items)
|
|
|
|
else:
|
|
# Define a custom session so we can query the work root
|
|
# for a "Work area" that is not our current Session.
|
|
# This way we can browse it even before we enter it.
|
|
if self._asset_id and self._task_name and self._task_type:
|
|
session = self._get_session()
|
|
self._workdir_path = session["AVALON_WORKDIR"]
|
|
self._workfiles_root = self.host.work_root(session)
|
|
self._workarea_files_model.set_root(self._workfiles_root)
|
|
|
|
else:
|
|
self._workarea_files_model.set_root(None)
|
|
|
|
# Disable/Enable buttons based on available files in model
|
|
has_valid_items = self._workarea_files_model.has_valid_items()
|
|
self._btn_browse.setEnabled(has_valid_items)
|
|
self._btn_open.setEnabled(has_valid_items)
|
|
|
|
if self._publish_context_select_mode:
|
|
self._btn_select_context_published.setEnabled(
|
|
bool(self._asset_id) and bool(self._task_name)
|
|
)
|
|
return
|
|
|
|
# Manually trigger file selection
|
|
if not has_valid_items:
|
|
self.on_file_select()
|
|
|
|
def _get_asset_doc(self):
|
|
if self._asset_id is None:
|
|
return None
|
|
|
|
if self._asset_doc is None:
|
|
self._asset_doc = io.find_one({"_id": self._asset_id})
|
|
return self._asset_doc
|
|
|
|
def _get_session(self):
|
|
"""Return a modified session for the current asset and task"""
|
|
|
|
session = api.Session.copy()
|
|
self.template_key = get_workfile_template_key(
|
|
self._task_type,
|
|
session["AVALON_APP"],
|
|
project_name=session["AVALON_PROJECT"]
|
|
)
|
|
changes = compute_session_changes(
|
|
session,
|
|
asset=self._get_asset_doc(),
|
|
task=self._task_name,
|
|
template_key=self.template_key
|
|
)
|
|
session.update(changes)
|
|
|
|
return session
|
|
|
|
def _enter_session(self):
|
|
"""Enter the asset and task session currently selected"""
|
|
|
|
session = api.Session.copy()
|
|
changes = compute_session_changes(
|
|
session,
|
|
asset=self._get_asset_doc(),
|
|
task=self._task_name,
|
|
template_key=self.template_key
|
|
)
|
|
if not changes:
|
|
# Return early if we're already in the right Session context
|
|
# to avoid any unwanted Task Changed callbacks to be triggered.
|
|
return
|
|
|
|
update_current_task(
|
|
asset=self._get_asset_doc(),
|
|
task=self._task_name,
|
|
template_key=self.template_key
|
|
)
|
|
|
|
def open_file(self, filepath):
|
|
host = self.host
|
|
if host.has_unsaved_changes():
|
|
result = self.save_changes_prompt()
|
|
if result is None:
|
|
# Cancel operation
|
|
return False
|
|
|
|
# Save first if has changes
|
|
if result:
|
|
current_file = host.current_file()
|
|
if not current_file:
|
|
# If the user requested to save the current scene
|
|
# we can't actually automatically do so if the current
|
|
# file has not been saved with a name yet. So we'll have
|
|
# to opt out.
|
|
log.error("Can't save scene with no filename. Please "
|
|
"first save your work file using 'Save As'.")
|
|
return
|
|
|
|
# Save current scene, continue to open file
|
|
host.save_file(current_file)
|
|
|
|
self._enter_session()
|
|
host.open_file(filepath)
|
|
self.file_opened.emit()
|
|
|
|
def save_changes_prompt(self):
|
|
self._messagebox = messagebox = QtWidgets.QMessageBox(parent=self)
|
|
messagebox.setWindowFlags(messagebox.windowFlags() |
|
|
QtCore.Qt.FramelessWindowHint)
|
|
messagebox.setIcon(messagebox.Warning)
|
|
messagebox.setWindowTitle("Unsaved Changes!")
|
|
messagebox.setText(
|
|
"There are unsaved changes to the current file."
|
|
"\nDo you want to save the changes?"
|
|
)
|
|
messagebox.setStandardButtons(
|
|
messagebox.Yes | messagebox.No | messagebox.Cancel
|
|
)
|
|
|
|
result = messagebox.exec_()
|
|
if result == messagebox.Yes:
|
|
return True
|
|
if result == messagebox.No:
|
|
return False
|
|
return None
|
|
|
|
def get_filename(self):
|
|
"""Show save dialog to define filename for save or duplicate
|
|
|
|
Returns:
|
|
str: The filename to create.
|
|
|
|
"""
|
|
session = self._get_session()
|
|
|
|
if self.published_enabled:
|
|
filepath = self._get_selected_filepath()
|
|
extensions = [os.path.splitext(filepath)[1]]
|
|
else:
|
|
extensions = self.host.file_extensions()
|
|
|
|
window = SaveAsDialog(
|
|
parent=self,
|
|
root=self._workfiles_root,
|
|
anatomy=self.anatomy,
|
|
template_key=self.template_key,
|
|
extensions=extensions,
|
|
session=session
|
|
)
|
|
window.exec_()
|
|
|
|
return window.get_result()
|
|
|
|
def on_duplicate_pressed(self):
|
|
work_file = self.get_filename()
|
|
if not work_file:
|
|
return
|
|
|
|
src = self._get_selected_filepath()
|
|
dst = os.path.join(self._workfiles_root, work_file)
|
|
shutil.copy(src, dst)
|
|
|
|
self.workfile_created.emit(dst)
|
|
|
|
self.refresh()
|
|
|
|
def _get_selected_filepath(self):
|
|
"""Return current filepath selected in view"""
|
|
if self.published_enabled:
|
|
source_view = self._publish_files_view
|
|
else:
|
|
source_view = self._workarea_files_view
|
|
selection = source_view.selectionModel()
|
|
index = selection.currentIndex()
|
|
if not index.isValid():
|
|
return
|
|
|
|
return index.data(FILEPATH_ROLE)
|
|
|
|
def _on_workarea_open_pressed(self):
|
|
path = self._get_selected_filepath()
|
|
if not path:
|
|
print("No file selected to open..")
|
|
return
|
|
|
|
self.open_file(path)
|
|
|
|
def on_browse_pressed(self):
|
|
ext_filter = "Work File (*{0})".format(
|
|
" *".join(self.host.file_extensions())
|
|
)
|
|
kwargs = {
|
|
"caption": "Work Files",
|
|
"filter": ext_filter
|
|
}
|
|
if Qt.__binding__ in ("PySide", "PySide2"):
|
|
kwargs["dir"] = self._workfiles_root
|
|
else:
|
|
kwargs["directory"] = self._workfiles_root
|
|
|
|
work_file = QtWidgets.QFileDialog.getOpenFileName(**kwargs)[0]
|
|
if work_file:
|
|
self.open_file(work_file)
|
|
|
|
def _on_save_as_pressed(self):
|
|
self._save_as_with_dialog()
|
|
|
|
def _save_as_with_dialog(self):
|
|
work_filename = self.get_filename()
|
|
if not work_filename:
|
|
return None
|
|
|
|
src_path = self._get_selected_filepath()
|
|
|
|
# Trigger before save event
|
|
emit_event(
|
|
"workfile.save.before",
|
|
{"filename": work_filename, "workdir_path": self._workdir_path},
|
|
source="workfiles.tool"
|
|
)
|
|
|
|
# Make sure workfiles root is updated
|
|
# - this triggers 'workio.work_root(...)' which may change value of
|
|
# '_workfiles_root'
|
|
self.set_asset_task(
|
|
self._asset_id, self._task_name, self._task_type
|
|
)
|
|
|
|
# Create workfiles root folder
|
|
if not os.path.exists(self._workfiles_root):
|
|
log.debug("Initializing Work Directory: %s", self._workfiles_root)
|
|
os.makedirs(self._workfiles_root)
|
|
|
|
# Prepare full path to workfile and save it
|
|
filepath = os.path.join(
|
|
os.path.normpath(self._workfiles_root), work_filename
|
|
)
|
|
|
|
# Update session if context has changed
|
|
self._enter_session()
|
|
|
|
if not self.published_enabled:
|
|
self.host.save_file(filepath)
|
|
else:
|
|
shutil.copy(src_path, filepath)
|
|
self.host.open_file(filepath)
|
|
|
|
# Create extra folders
|
|
create_workdir_extra_folders(
|
|
self._workdir_path,
|
|
api.Session["AVALON_APP"],
|
|
self._task_type,
|
|
self._task_name,
|
|
api.Session["AVALON_PROJECT"]
|
|
)
|
|
# Trigger after save events
|
|
emit_event(
|
|
"workfile.save.after",
|
|
{"filename": work_filename, "workdir_path": self._workdir_path},
|
|
source="workfiles.tool"
|
|
)
|
|
|
|
self.workfile_created.emit(filepath)
|
|
# Refresh files model
|
|
if self.published_enabled:
|
|
self._published_checkbox.setChecked(False)
|
|
else:
|
|
self.refresh()
|
|
return filepath
|
|
|
|
def _on_published_save_as_pressed(self):
|
|
self._save_as_with_dialog()
|
|
|
|
def _set_publish_context_select_mode(self, enabled):
|
|
self._publish_context_select_mode = enabled
|
|
|
|
# Show buttons related to context selection
|
|
self._publish_context_overlay.setVisible(enabled)
|
|
self._btn_cancel_published.setVisible(enabled)
|
|
self._btn_select_context_published.setVisible(enabled)
|
|
# Change enabled state based on select context
|
|
self._btn_select_context_published.setEnabled(
|
|
bool(self._asset_id) and bool(self._task_name)
|
|
)
|
|
|
|
self._btn_save_as_published.setVisible(not enabled)
|
|
self._btn_change_context.setVisible(not enabled)
|
|
|
|
# Change views and disable workarea view if enabled
|
|
self._workarea_files_view.setEnabled(not enabled)
|
|
if self.published_enabled:
|
|
self._workarea_files_view.setVisible(enabled)
|
|
self._publish_files_view.setVisible(not enabled)
|
|
else:
|
|
self._workarea_files_view.setVisible(True)
|
|
self._publish_files_view.setVisible(False)
|
|
|
|
# Disable filter widgets
|
|
self._published_checkbox.setEnabled(not enabled)
|
|
self._filter_input.setEnabled(not enabled)
|
|
|
|
def _on_publish_change_context_pressed(self):
|
|
self._set_publish_context_select_mode(True)
|
|
|
|
def _on_publish_select_context_pressed(self):
|
|
result = self._save_as_with_dialog()
|
|
if result is not None:
|
|
self._set_publish_context_select_mode(False)
|
|
self._update_asset_task()
|
|
|
|
def _on_publish_cancel_pressed(self):
|
|
self._set_publish_context_select_mode(False)
|
|
self._update_asset_task()
|
|
|
|
def on_file_select(self):
|
|
self.file_selected.emit(self._get_selected_filepath())
|
|
|
|
def refresh(self):
|
|
"""Refresh listed files for current selection in the interface"""
|
|
if self.published_enabled:
|
|
self._publish_files_model.refresh()
|
|
else:
|
|
self._workarea_files_model.refresh()
|
|
|
|
if self.auto_select_latest_modified:
|
|
self._select_last_modified_file()
|
|
|
|
def _on_workarea_context_menu(self, point):
|
|
index = self._workarea_files_view.indexAt(point)
|
|
if not index.isValid():
|
|
return
|
|
|
|
if not index.flags() & QtCore.Qt.ItemIsEnabled:
|
|
return
|
|
|
|
menu = QtWidgets.QMenu(self)
|
|
|
|
# Duplicate
|
|
action = QtWidgets.QAction("Duplicate", menu)
|
|
tip = "Duplicate selected file."
|
|
action.setToolTip(tip)
|
|
action.setStatusTip(tip)
|
|
action.triggered.connect(self.on_duplicate_pressed)
|
|
menu.addAction(action)
|
|
|
|
# Show the context action menu
|
|
global_point = self._workarea_files_view.mapToGlobal(point)
|
|
action = menu.exec_(global_point)
|
|
if not action:
|
|
return
|
|
|
|
def _select_last_modified_file(self):
|
|
"""Utility function to select the file with latest date modified"""
|
|
if self.published_enabled:
|
|
source_view = self._publish_files_view
|
|
else:
|
|
source_view = self._workarea_files_view
|
|
model = source_view.model()
|
|
|
|
highest_index = None
|
|
highest = 0
|
|
for row in range(model.rowCount()):
|
|
index = model.index(row, 0, parent=QtCore.QModelIndex())
|
|
if not index.isValid():
|
|
continue
|
|
|
|
modified = index.data(DATE_MODIFIED_ROLE)
|
|
if modified is not None and modified > highest:
|
|
highest_index = index
|
|
highest = modified
|
|
|
|
if highest_index:
|
|
source_view.setCurrentIndex(highest_index)
|