diff --git a/openpype/lib/delivery.py b/openpype/lib/delivery.py index 9e87d854f5..411ae42e80 100644 --- a/openpype/lib/delivery.py +++ b/openpype/lib/delivery.py @@ -1,7 +1,5 @@ """Functions useful for delivery action or loader""" import os -from avalon import pipeline -from avalon.vendor import filelink import shutil import clique import collections @@ -17,6 +15,8 @@ def sizeof_fmt(num, suffix='B'): def path_from_represenation(representation, anatomy): + from avalon import pipeline # safer importing + try: template = representation["data"]["template"] @@ -39,6 +39,8 @@ def path_from_represenation(representation, anatomy): def copy_file(src_path, dst_path): """Hardlink file if possible(to save space), copy if not""" + from avalon.vendor import filelink # safer importing + if os.path.exists(dst_path): return try: @@ -271,43 +273,3 @@ def process_sequence( uploaded += 1 return report_items, uploaded - - -def report(report_items): - """Returns dict with final status of delivery (succes, fail etc.).""" - items = [] - title = "Delivery report" - for msg, _items in report_items.items(): - if not _items: - continue - - if items: - items.append({"type": "label", "value": "---"}) - - items.append({ - "type": "label", - "value": "# {}".format(msg) - }) - if not isinstance(_items, (list, tuple)): - _items = [_items] - __items = [] - for item in _items: - __items.append(str(item)) - - items.append({ - "type": "label", - "value": '

{}

'.format("
".join(__items)) - }) - - if not items: - return { - "success": True, - "message": "Delivery Finished" - } - - return { - "items": items, - "title": title, - "success": False, - "message": "Delivery Finished" - } diff --git a/openpype/modules/ftrack/event_handlers_user/action_delivery.py b/openpype/modules/ftrack/event_handlers_user/action_delivery.py index 7f2d9bb43a..f8553b2eac 100644 --- a/openpype/modules/ftrack/event_handlers_user/action_delivery.py +++ b/openpype/modules/ftrack/event_handlers_user/action_delivery.py @@ -13,8 +13,7 @@ from openpype.lib.delivery import ( get_format_dict, check_destination_path, process_single_file, - process_sequence, - report + process_sequence ) from avalon.api import AvalonMongoDB @@ -498,7 +497,46 @@ class Delivery(BaseAction): else: process_sequence(*args) - return report(report_items) + return self.report(report_items) + + def report(self, report_items): + """Returns dict with final status of delivery (succes, fail etc.).""" + items = [] + title = "Delivery report" + for msg, _items in report_items.items(): + if not _items: + continue + + if items: + items.append({"type": "label", "value": "---"}) + + items.append({ + "type": "label", + "value": "# {}".format(msg) + }) + if not isinstance(_items, (list, tuple)): + _items = [_items] + __items = [] + for item in _items: + __items.append(str(item)) + + items.append({ + "type": "label", + "value": '

{}

'.format("
".join(__items)) + }) + + if not items: + return { + "success": True, + "message": "Delivery Finished" + } + + return { + "items": items, + "title": title, + "success": False, + "message": "Delivery Finished" + } def register(session): diff --git a/openpype/plugins/load/delivery.py b/openpype/plugins/load/delivery.py index 53f8033c32..a905bf02c2 100644 --- a/openpype/plugins/load/delivery.py +++ b/openpype/plugins/load/delivery.py @@ -1,12 +1,13 @@ import collections import copy +from Qt import QtWidgets, QtCore, QtGui + from avalon import api, style -from avalon.vendor.Qt import QtWidgets, QtCore, QtGui from avalon.api import AvalonMongoDB + from openpype.api import Anatomy, config from openpype import resources -from openpype.api import get_anatomy_settings from openpype.lib.delivery import ( sizeof_fmt, @@ -14,8 +15,7 @@ from openpype.lib.delivery import ( get_format_dict, check_destination_path, process_single_file, - process_sequence, - report + process_sequence ) @@ -53,19 +53,18 @@ class Delivery(api.SubsetLoader): class DeliveryOptionsDialog(QtWidgets.QDialog): """Dialog to select template where to deliver selected representations.""" - SIZE_W = 950 - SIZE_H = 350 def __init__(self, contexts, log=None, parent=None): super(DeliveryOptionsDialog, self).__init__(parent=parent) - self.project = contexts[0]["project"]["name"] + project = contexts[0]["project"]["name"] + self.anatomy = Anatomy(project) self._representations = None self.log = log self.currently_uploaded = 0 self.dbcon = AvalonMongoDB() - self.dbcon.Session["AVALON_PROJECT"] = self.project + self.dbcon.Session["AVALON_PROJECT"] = project self.dbcon.install() self._set_representations(contexts) @@ -79,15 +78,9 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): QtCore.Qt.WindowMinimizeButtonHint ) self.setStyleSheet(style.load_stylesheet()) - self.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H)) - - layout = QtWidgets.QVBoxLayout() - - input_layout = QtWidgets.QFormLayout() - input_layout.setContentsMargins(10, 15, 5, 5) dropdown = QtWidgets.QComboBox() - self.templates = self._get_templates(self.project) + self.templates = self._get_templates(self.anatomy) for name, _ in self.templates.items(): dropdown.addItem(name) @@ -98,12 +91,12 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): root_line_edit = QtWidgets.QLineEdit() repre_checkboxes_layout = QtWidgets.QFormLayout() - repre_checkboxes_layout.setContentsMargins(10, 5, 5, 20) + repre_checkboxes_layout.setContentsMargins(10, 5, 5, 10) self._representation_checkboxes = {} for repre in self._get_representation_names(): checkbox = QtWidgets.QCheckBox() - checkbox.setChecked(True) + checkbox.setChecked(False) self._representation_checkboxes[repre] = checkbox checkbox.stateChanged.connect(self._update_selected_label) @@ -111,6 +104,10 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): selected_label = QtWidgets.QLabel() + input_widget = QtWidgets.QWidget(self) + input_layout = QtWidgets.QFormLayout(input_widget) + input_layout.setContentsMargins(10, 15, 5, 5) + input_layout.addRow("Selected representations", selected_label) input_layout.addRow("Delivery template", dropdown) input_layout.addRow("Template value", template_label) @@ -123,20 +120,21 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): progress_bar = QtWidgets.QProgressBar(self) progress_bar.setMinimum = 0 progress_bar.setMaximum = 100 - progress_bar.hide() + progress_bar.setVisible(False) text_area = QtWidgets.QTextEdit() text_area.setReadOnly(True) - text_area.hide() + text_area.setVisible(False) text_area.setMinimumHeight(100) - layout.addLayout(input_layout) + layout = QtWidgets.QVBoxLayout(self) + + layout.addWidget(input_widget) + layout.addStretch(1) layout.addWidget(btn_delivery) layout.addWidget(progress_bar) layout.addWidget(text_area) - self.setLayout(layout) - self.selected_label = selected_label self.template_label = template_label self.dropdown = dropdown @@ -156,26 +154,26 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): def deliver(self): """Main method to loop through all selected representations""" - self.progress_bar.show() + self.progress_bar.setVisible(True) self.btn_delivery.setEnabled(False) - # self.resize(self.width(), self.height() + 50) + QtWidgets.QApplication.processEvents() report_items = collections.defaultdict(list) selected_repres = self._get_selected_repres() - anatomy = Anatomy(self.project) + datetime_data = config.get_datetime_data() template_name = self.dropdown.currentText() - format_dict = get_format_dict(anatomy, self.root_line_edit.text()) + format_dict = get_format_dict(self.anatomy, self.root_line_edit.text()) for repre in self._representations: if repre["name"] not in selected_repres: continue - repre_path = path_from_represenation(repre, anatomy) + repre_path = path_from_represenation(repre, self.anatomy) anatomy_data = copy.deepcopy(repre["context"]) new_report_items = check_destination_path(str(repre["_id"]), - anatomy, + self.anatomy, anatomy_data, datetime_data, template_name) @@ -187,7 +185,7 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): args = [ repre_path, repre, - anatomy, + self.anatomy, template_name, anatomy_data, format_dict, @@ -197,7 +195,7 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): if repre.get("files"): for repre_file in repre["files"]: - src_path = anatomy.fill_root(repre_file["path"]) + src_path = self.anatomy.fill_root(repre_file["path"]) args[0] = src_path new_report_items, uploaded = process_single_file(*args) report_items.update(new_report_items) @@ -214,21 +212,20 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): report_items.update(new_report_items) self._update_progress(uploaded) - self.text_area.setText(self._format_report(report(report_items), - report_items)) - self.text_area.show() - - self.resize(self.width(), self.height() + 125) + self.text_area.setText(self._format_report(report_items)) + self.text_area.setVisible(True) def _get_representation_names(self): """Get set of representation names for checkbox filtering.""" return set([repre["name"] for repre in self._representations]) - def _get_templates(self, project_name): + def _get_templates(self, anatomy): """Adds list of delivery templates from Anatomy to dropdown.""" - settings = get_anatomy_settings(project_name) templates = {} - for template_name, value in settings["templates"]["delivery"].items(): + for template_name, value in anatomy.templates["delivery"].items(): + if not isinstance(value, str) or not value.startswith('{root'): + continue + templates[template_name] = value return templates @@ -297,9 +294,14 @@ class DeliveryOptionsDialog(QtWidgets.QDialog): ratio = self.currently_uploaded / self.files_selected self.progress_bar.setValue(ratio * self.progress_bar.maximum()) - def _format_report(self, result, report_items): + def _format_report(self, report_items): """Format final result and error details as html.""" - txt = "

{}

".format(result["message"]) + msg = "Delivery finished" + if not report_items: + msg += " successfully" + else: + msg += " with errors" + txt = "

{}

".format(msg) for header, data in report_items.items(): txt += "

{}

".format(header) for item in data: