diff --git a/python/tk_multi_workfiles/save_as.py b/python/tk_multi_workfiles/save_as.py index f092edf..e8dadab 100644 --- a/python/tk_multi_workfiles/save_as.py +++ b/python/tk_multi_workfiles/save_as.py @@ -6,7 +6,7 @@ from itertools import chain import tank -from tank.platform.qt import QtCore, QtGui +from tank.platform.qt import QtCore, QtGui from tank import TankError from pprint import pprint @@ -15,31 +15,31 @@ class SaveAs(object): """ - + """ - + @staticmethod def show_save_as_dlg(app): """ - + """ handler = SaveAs(app) handler._show_save_as_dlg() - + def __init__(self, app): """ Construction """ self._app = app - + self._work_template = self._app.get_template("template_work") self._publish_template = self._app.get_template("template_publish") - + def _show_save_as_dlg(self): """ Show the save as dialog """ - + # get the current file path: try: current_path = self._get_current_file_path() @@ -49,7 +49,7 @@ def _show_save_as_dlg(self): "Unable to continue!" % e) QtGui.QMessageBox.critical(None, "Save As Error!", msg) return - + # determine if this is a publish path or not: is_publish = self._publish_template.validate(current_path) fields = {} @@ -70,7 +70,7 @@ def _show_save_as_dlg(self): else: name = default_name fields = self._app.context.as_template_fields(self._work_template) - + try: # make sure the work file name doesn't already exist: # note, this could potentially be slow so for now lets @@ -80,71 +80,84 @@ def _show_save_as_dlg(self): test_name = name if counter > 0: test_name = "%s%d" % (name, counter) - + test_fields = fields.copy() test_fields["name"] = test_name - + existing_files = self._app.tank.paths_from_template(self._work_template, test_fields, ["version"]) if not existing_files: name = test_name break - + except TankError, e: # this shouldn't be fatal so just log a debug message: self._app.log_debug("Warning - failed to find a default name for Tank Save-As: %s" % e) - - + + worker_cb = lambda details, wp=current_path, ip=is_publish: self.generate_new_work_file_path(wp, ip, details.get("name"), details.get("reset_version")) with AsyncWorker(worker_cb) as preview_updater: while True: # show modal dialog: from .save_as_form import SaveAsForm - (res, form) = self._app.engine.show_modal(title, self._app, SaveAsForm, preview_updater, is_publish, name) - - if res == QtGui.QDialog.Accepted: + + can_snapshot = False + snapshot_app = self._app.engine.apps.get("tk-multi-snapshot") + if snapshot_app: + try: + # This might fail if the snapshot tool doesn't have + # this feature. + can_snapshot = snapshot_app.can_snapshot() + except: + can_snapshot = False + + (res, form) = self._app.engine.show_modal(title, self._app, SaveAsForm, preview_updater, is_publish, name, can_snapshot) + + if res == SaveAsForm.SHOW_SNAPSHOT_RETURN_CODE: + return snapshot_app.show_snapshot_dlg() + elif res == QtGui.QDialog.Accepted: # get details from UI: name = form.name reset_version = form.reset_version - + details = self.generate_new_work_file_path(current_path, is_publish, name, reset_version) new_path = details.get("path") msg = details.get("message") - + if not new_path: # something went wrong! QtGui.QMessageBox.information(None, "Unable to Save", "Unable to Save!\n\n%s" % msg) continue - + # ok, so do save-as: try: self.save_as(new_path) except Exception, e: self._app.log_exception("Something went wrong while saving!") - + break else: break - + def save_as(self, new_path): """ Do actual save-as of the current scene as the new path - assumes all validity checking has already been done """ - + # always try to create folders: ctx_entity = self._app.context.task if self._app.context.task else self._app.context.entity self._app.tank.create_filesystem_structure(ctx_entity.get("type"), ctx_entity.get("id")) - + # and save the current file as the new path: self._save_current_file_as(new_path) - + def _save_current_file_as(self, path): """ Use hook to get the current work/scene file path """ self._app.execute_hook("hook_scene_operation", operation="save_as", file_path=path, context = self._app.context) - + def generate_new_work_file_path(self, current_path, current_is_publish, new_name, reset_version): """ Generate a new work file path from the current path taking into @@ -158,7 +171,7 @@ def generate_new_work_file_path(self, current_path, current_is_publish, new_name if not new_name: msg = "You must enter a name!" return {"message":msg} - + if not self._work_template.keys["name"].validate(new_name): msg = "Your filename contains illegal characters!" return {"message":msg} @@ -168,7 +181,7 @@ def generate_new_work_file_path(self, current_path, current_is_publish, new_name # start with fields from context: fields = self._app.context.as_template_fields(self._work_template) - + # add in any additional fields from current path: base_template = self._publish_template if current_is_publish else self._work_template if base_template.validate(current_path): @@ -177,7 +190,7 @@ def generate_new_work_file_path(self, current_path, current_is_publish, new_name else: # just make sure there is a version fields["version"] = 1 - + current_version = fields.get("version") current_name = fields.get("name") @@ -190,52 +203,52 @@ def generate_new_work_file_path(self, current_path, current_is_publish, new_name max_work_version = versioning.get_max_workfile_version(fields) max_publish_version = versioning.get_max_publish_version(new_name) max_version = max(max_work_version, max_publish_version) - - # now depending on what the source was + + # now depending on what the source was # and if the name has been changed: new_version = None if current_is_publish and new_name == current_name: # we're ok to just copy publish across and version up can_reset_version = False new_version = max_version + 1 - + if new_version != current_version+1: #(AD) - do we need a warning here? pass - + msg = None else: if max_version: # already have a publish and/or work file can_reset_version = False new_version = max_version + 1 - + if max_version == max_work_version: msg = "A work file with this name already exists. If you proceed, your file will use the next available version number." else: msg = "A publish file with this name already exists. If you proceed, your file will use the next available version number." - + else: # don't have an existing version can_reset_version = True msg = "" if reset_version: new_version = 1 - + # now create new path if new_version: fields["version"] = new_version new_work_path = self._work_template.apply_fields(fields) - + return {"path":new_work_path, "message":msg, "can_reset_version":can_reset_version} - - + + def _get_current_file_path(self): """ Use hook to get the current work/scene file path """ return self._app.execute_hook("hook_scene_operation", operation="current_path", file_path="", context = self._app.context) - - - - \ No newline at end of file + + + + diff --git a/python/tk_multi_workfiles/save_as_form.py b/python/tk_multi_workfiles/save_as_form.py index a837233..d526d2f 100644 --- a/python/tk_multi_workfiles/save_as_form.py +++ b/python/tk_multi_workfiles/save_as_form.py @@ -11,12 +11,14 @@ class SaveAsForm(QtGui.QWidget): """ UI for saving the current tank work file """ - + + SHOW_SNAPSHOT_RETURN_CODE = 2 + @property def exit_code(self): return self._exit_code - - def __init__(self, preview_updater, is_publish, name, parent = None): + + def __init__(self, preview_updater, is_publish, name, can_snapshot, parent = None): """ Construction """ @@ -25,15 +27,15 @@ def __init__(self, preview_updater, is_publish, name, parent = None): self._preview_updater = preview_updater if self._preview_updater: self._preview_updater.work_done.connect(self._preview_info_updated) - + self._reset_version = False self._launched_from_publish = is_publish - + # set up the UI from .ui.save_as_form import Ui_SaveAsForm self._ui = Ui_SaveAsForm() self._ui.setupUi(self) - + self._ui.cancel_btn.clicked.connect(self._on_cancel) self._ui.continue_btn.clicked.connect(self._on_continue) self._ui.name_edit.textEdited.connect(self._on_name_edited) @@ -45,18 +47,23 @@ def __init__(self, preview_updater, is_publish, name, parent = None): # make sure text in name edit is selected ready to edit: self._ui.name_edit.setFocus() self._ui.name_edit.selectAll() - + # initialize the preview info: self._preview_info_updated({}, {}) - - # initialize line to be plain and the same colour as the text: + + # initialize line to be plain and the same colour as the text: self._ui.break_line.setFrameShadow(QtGui.QFrame.Plain) clr = QtGui.QApplication.palette().text().color() self._ui.break_line.setStyleSheet("#break_line{color: rgb(%d,%d,%d);}" % (clr.red() * 0.75, clr.green() * 0.75, clr.blue() * 0.75)) - # finally, start preview info update in background + if can_snapshot: + self._ui.snapshot_btn.clicked.connect( self._on_snapshot_instead ) + else: + self._ui.snapshot_btn.setVisible(False) + + # finally, start preview info update in background self._update_preview_info() - + def showEvent(self, e): """ On first show, make sure that the name edit is focused: @@ -64,67 +71,74 @@ def showEvent(self, e): self._ui.name_edit.setFocus() self._ui.name_edit.selectAll() QtGui.QWidget.showEvent(self, e) - + @property def name(self): """ Get and set the name """ return self._get_new_name() - + @property def reset_version(self): """ Get and set if the version number should be reset """ return self._should_reset_version() - + def _on_cancel(self): """ Called when the cancel button is clicked """ self._exit_code = QtGui.QDialog.Rejected self.close() - + def _on_continue(self): """ Called when the continue button is clicked """ self._exit_code = QtGui.QDialog.Accepted self.close() - + + def _on_snapshot_instead(self): + """ + Called when the Snapshot Instead button is clicked. + """ + self._exit_code = SaveAsForm.SHOW_SNAPSHOT_RETURN_CODE + self.close() + def _on_name_edited(self, txt): self._update_preview_info() - + def _on_name_return_pressed(self): self._on_continue() - + def _on_reset_version_changed(self, state): if self._ui.reset_version_cb.isEnabled(): self._reset_version = self._ui.reset_version_cb.isChecked() self._update_preview_info() - + def _get_new_name(self): return str(self._ui.name_edit.text()).strip() - + def _should_reset_version(self): return self._reset_version - + def _update_preview_info(self): """ - + """ if self._preview_updater: self._preview_updater.do({"name":self._get_new_name(), "reset_version":self._should_reset_version()}) - + def _preview_info_updated(self, details, result): """ - + """ path = result.get("path") msg = result.get("message") can_reset_version = result.get("can_reset_version") - + # update name and work area previews: path_preview = "" name_preview = "" @@ -132,7 +146,7 @@ def _preview_info_updated(self, details, result): path_preview, name_preview = os.path.split(path) self._ui.filename_preview_label.setText(name_preview) self._ui.path_preview_edit.setText(path_preview) - + # update header: header_txt = "" if msg: @@ -145,7 +159,7 @@ def _preview_info_updated(self, details, result): else: header_txt = ("Type in a name below and Tank will save the current scene") self._ui.header_label.setText(header_txt) - + # update reset version check box: if can_reset_version: self._ui.reset_version_cb.setChecked(self._reset_version) @@ -153,6 +167,6 @@ def _preview_info_updated(self, details, result): else: self._ui.reset_version_cb.setEnabled(False) self._ui.reset_version_cb.setChecked(False) - - - \ No newline at end of file + + + diff --git a/python/tk_multi_workfiles/ui/save_as_form.py b/python/tk_multi_workfiles/ui/save_as_form.py index d45759e..8a90ccc 100644 --- a/python/tk_multi_workfiles/ui/save_as_form.py +++ b/python/tk_multi_workfiles/ui/save_as_form.py @@ -122,6 +122,9 @@ def setupUi(self, SaveAsForm): self.horizontalLayout_3 = QtGui.QHBoxLayout() self.horizontalLayout_3.setContentsMargins(12, 8, 12, 12) self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.snapshot_btn = QtGui.QPushButton(SaveAsForm) + self.snapshot_btn.setObjectName("snapshot_btn") + self.horizontalLayout_3.addWidget(self.snapshot_btn) spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) self.horizontalLayout_3.addItem(spacerItem1) self.cancel_btn = QtGui.QPushButton(SaveAsForm) @@ -156,6 +159,7 @@ def retranslateUi(self, SaveAsForm): "

line 3

", None, QtGui.QApplication.UnicodeUTF8)) self.label_4.setText(QtGui.QApplication.translate("SaveAsForm", "

Preview:

", None, QtGui.QApplication.UnicodeUTF8)) self.label_6.setText(QtGui.QApplication.translate("SaveAsForm", "

Work Area:

", None, QtGui.QApplication.UnicodeUTF8)) + self.snapshot_btn.setText(QtGui.QApplication.translate("SaveAsForm", "Snapshot Instead...", None, QtGui.QApplication.UnicodeUTF8)) self.cancel_btn.setText(QtGui.QApplication.translate("SaveAsForm", "Cancel", None, QtGui.QApplication.UnicodeUTF8)) self.continue_btn.setText(QtGui.QApplication.translate("SaveAsForm", "Save", None, QtGui.QApplication.UnicodeUTF8))