def sync_version(self): """ Opens selected version Override functionality for specific data """ if not self._repository_type_class: return items = self._versions_tree.selectedItems() if not items: return item = items[0] item_commit = item.text(4) if not item_commit: return res = qtutils.show_question( self, 'Syncing File', 'Are you sure you want to synchronize this file?.' '\nCurrent local file will be overwriten!') if res != QMessageBox.Yes: return self._repository_type_class.sync_file(self._repository_path, self.directory, item_commit)
def removeTab(self, index, force=False): """ Overrides removeTab function to ask permission to the user before closing the tab :param index: int, index of the tab we want to close """ total_tabs = self.count() if force: super(ScriptsTab, self).removeTab(index) else: if total_tabs > 1: if self.get_current_text(tab_index=index).strip(): if self._ask_save_before_close: if qtutils.show_question( title='Closing Script', question='Close this tab without saving?\n'. format(self.tabText(index)), parent=self) == QMessageBox.Yes: super(ScriptsTab, self).removeTab(index) else: super(ScriptsTab, self).removeTab(index) else: super(ScriptsTab, self).removeTab(index) if total_tabs == 1: self.lastTabClosed.emit()
def _update_ui(self, allow_sync=True): light_rigs_path = self.get_light_rigs_path() if not light_rigs_path: return if not os.path.exists(light_rigs_path) and allow_sync: result = qtutils.show_question( None, 'Light Rigs Folder is not available!', 'Do you want to synchronize Light Rigs Folder from Artella to your computer? \n\n{}' .format(light_rigs_path)) if result == QMessageBox.Yes: self.synchronize_light_rigs() if not os.path.exists(light_rigs_path): msg = 'Was not possible to synchronize Light Rigs folder from Artella: "{}"'.format( light_rigs_path) self.show_warning_message(msg) LOGGER.warning(msg) return else: self._stack.slide_in_index(0) return if not light_rigs_path or not os.path.isdir(light_rigs_path): return qtutils.clear_layout(self._light_rigs_layout) light_rig_file_type = self.config.get('lightrig_file_type', default='lightrig') for f in os.listdir(light_rigs_path): light_rig = self.LIGHT_RIG_CLASS(project=self._project, name=f, path=light_rigs_path, file_type=light_rig_file_type, config=self._config) self._light_rigs_layout.addWidget(light_rig) self._stack.slide_in_index(1)
def _on_sync(self): current_path = self._folder_path.text() if not current_path or not os.path.isdir(current_path): msg = 'Select a folder to sync first!' LOGGER.warning(msg) self.show_warning_message(msg) return result = qtutils.show_question( None, 'Synchronizing folder: {}'.format(current_path), 'Are you sure you want to synchronize this folder? This can take quite a lot of time!' ) if result == QMessageBox.No: return try: self._progress.setVisible(True) self._progress_lbl.setText('Synchronizing files ... Please wait!') self.repaint() artellalib.synchronize_path_with_folders(current_path, recursive=True) except Exception as e: LOGGER.error(str(e)) LOGGER.error(traceback.format_exc()) finally: self._progress.setVisible(False) self._progress_lbl.setText('') self._update_items()
def _on_sync_all_assets_of_type(self, asset_type, ask=True): """ Synchronizes all the assets of a given type :param asset_type: str :param ask: bol """ assets_to_sync = artellapipe.AssetsMgr().get_assets_by_type(asset_type) if not assets_to_sync: LOGGER.warning('No Assets found of type "{}" to sync!'.format(asset_type)) return total_assets = len(assets_to_sync) if ask: result = qtutils.show_question( None, 'Synchronizing All {} Assets ({})'.format(asset_type, total_assets), 'Are you sure you want to synchronize all {} assets ({})? This can take lot of time!'.format( asset_type, total_assets)) if result == QMessageBox.No: return for asset in assets_to_sync: asset.sync(sync_type=defines.ArtellaFileStatus.ALL) self.show_ok_message('All assets have been synced!')
def _export_file(self, file_path, *args, **kwargs): if not tp.is_maya(): LOGGER.warning('Shaders export is only supported in Maya!') return shaders_to_export = artellapipe.ShadersMgr().get_asset_shaders_to_export( asset=self._asset, return_only_shaders=False) locked_file = False if os.path.isfile(file_path): res = qtutils.show_question( None, 'Exporting Shaders Mapping File', 'Shaders Mapping File "{}" already exists. Do you want to overwrite it?'.format(file_path)) if res == QMessageBox.No: return artellapipe.FilesMgr().lock_file(file_path) locked_file = True try: with open(file_path, 'w') as fp: json.dump(shaders_to_export, fp) except Exception as exc: LOGGER.error('Error while exporting Shaders Mapping File "{}" | {}'.format(file_path, exc)) finally: if locked_file: artellapipe.FilesMgr().unlock_file(file_path) if os.path.isfile(file_path): return file_path
def restore_bind_pose(self): res = qtutils.show_question( None, 'Go to Bind Pose', 'Are you sure yo want to restore bind pose?') if res != QMessageBox.Yes: return False return self._client.restore_bind_pose()
def remove_bind_poses(self): res = qtutils.show_question( None, 'Remove Bind Poses', 'Are you sure yo want to remove all bind poses from the current scene?' ) if res != QMessageBox.Yes: return False return self._client.remove_bind_poses()
def sync_latest_published_files(self, file_type=None, ask=False): """ Synchronizes all latest published files for current asset :param file_type: str, if not given all files will be synced """ if ask: result = qtutils.show_question( None, 'Synchronizing Latest Published Files: {}'.format(self.get_name()), 'Are you sure you want to synchronize latest published files? This can take quite some time!') if result == QMessageBox.No: return valid_types = self._get_types_to_check(file_type) if not valid_types: return files_to_sync = list() for valid_type in valid_types: file_type = self.get_file_type(valid_type) if not file_type: continue latest_published_info = file_type.get_server_versions(status=defines.ArtellaFileStatus.PUBLISHED) if not latest_published_info: continue for version_info in latest_published_info: latest_version_path = version_info.get('version_path', None) if not latest_version_path: continue # We do not get latest of the file already exists if os.path.isfile(latest_version_path): continue if os.path.isdir(latest_version_path): if not len(os.listdir(latest_version_path)) == 0: continue files_to_sync.append(latest_version_path) if files_to_sync: artellapipe.FilesMgr().sync_files(files_to_sync) return files_to_sync
def _on_unlock(self): items_to_unlock = list() checked_items = self._checked_items() for item in checked_items: if not os.path.isfile(item.path): continue items_to_unlock.append(item) if not items_to_unlock: return msg = 'If changes in files are not submitted to Artella yet, submit them before unlocking the file please. ' \ '\n\n Do you want to continue?' res = qtutils.show_question(None, 'Unlock File', msg) if res != QMessageBox.Yes: return valid_unlock = False self._progress.setVisible(True) self._progress.setMinimum(0) self._progress.setMaximum(len(items_to_unlock) - 1) self._progress_lbl.setText('Unlocking files ...') self.repaint() for i, item in enumerate(items_to_unlock): self._progress.setValue(i) self._progress_lbl.setText('Unlocking: {}'.format(item.text(1))) self.repaint() valid_unlock = artellapipe.FilesMgr().unlock_file(item.path, notify=False, warn_user=False) if valid_unlock: item.setIcon(0, tp.ResourcesMgr().icon('unlock')) self.show_ok_message('File successfully unlock!') else: self.show_ok_message('Was not possible to unlock the file!') self._progress.setValue(0) self._progress_lbl.setText('') self._progress.setVisible(False) self._project.tray.show_message(title='Unlock Files', msg='Files unlocked successfully!') self.repaint() return valid_unlock
def _on_sync(self, file_type, sync_type, ask=False): """ Internal callback function that is called when the user presses Sync contextual menu action :param file_type: str :param sync_type: str :param ask: bool """ if ask: res = qtutils.show_question( None, 'Synchronize "{}" file: {}'.format(self.asset.get_name(), file_type.title()), 'Are you sure you want to sync this asset? This can take some time!' ) if res != QMessageBox.Yes: return self._sequence.sync(file_type, sync_type)
def _on_sync(self, file_type, sync_type, ask=False): """ Internal callback function that is called when the user tries to Sync an asset through UI :param file_type: str :param sync_type: str :param ask: bool """ if ask: res = qtutils.show_question( None, 'Synchronize "{}" file: {}'.format(self.asset.get_name(), file_type.title()), 'Are you sure you want to sync this asset? This can take some time!' ) if res != QMessageBox.Yes: return self.startSync.emit(self.asset, file_type, sync_type)
def _on_kitsu_logout(self): """ Internal callback function that is called when the user presses the logout button """ remove_credentials = False res = qtutils.show_question( self, 'Kitsu Logout', 'Do you want to remove Kitsu stored credentials?') if res == QMessageBox.Yes: remove_credentials = True valid = artellapipe.Tracker().logout( remove_credentials=remove_credentials) if not valid: LOGGER.warning('Error while logging out from Kitsu') return self.update_kitsu_status() self.logout.emit()
def rename_file(file_path, new_name): """ Renames given file with new given name :param file_path: str :param new_name: str """ res = qtutils.show_question( None, 'Confirm Rename', 'Are you you would like to rename "{}" to "{}"?Any references to this file will need to be updated.' .format(os.path.basename(file_path), new_name)) if res != QMessageBox.Yes: return dir_name = os.path.dirname(file_path) file_ext = os.path.splitext(file_path)[-1] if file_ext: if not new_name.endswith(file_ext): new_name += file_ext else: file_ext = os.path.splitext(file_path)[-1] if file_ext: new_name = file_ext[0] new_path = os.path.join(dir_name, new_name) spigot = get_artella_client() payload = dict() payload['cms_uri'] = getCmsUri(file_path) payload['dst_uri'] = getCmsUri(new_path) payload = json.dumps(payload) rsp = spigot.execute(command_action='do', command_name='rename', payload=payload) if isinstance(rsp, (unicode, str)): rsp = json.dumps(rsp) return rsp
def _on_sync_all_types(self, ask=True): """ Synchronizes all the assets :param ask: bol """ assets_to_sync = artellapipe.AssetsMgr().assets if not assets_to_sync: LOGGER.warning('No Assets found to sync!') return total_assets = len(assets_to_sync) if ask: result = qtutils.show_question( None, 'Synchronizing All Assets ({})'.format(total_assets), 'Are you sure you want to synchronize all assets ({})? This will take lot of time!'.format( total_assets)) if result == QMessageBox.No: return for asset in assets_to_sync: asset.sync(sync_type=defines.ArtellaFileStatus.ALL)
def _check_update(self, skip_update=False): """ Internal function that checks if files are updated or not """ not_updated_items = list() try: all_items = list(self._all_items()) self._progress.setVisible(True) self._progress.setMinimum(0) self._progress.setMaximum(len(all_items) - 1) self._progress_lbl.setText( 'Checking if files are updated ... Please wait!') for i, item in enumerate(all_items): self._progress.setValue(i) self._progress_lbl.setText( 'Checking if file is updated: {}'.format(item.text(1))) is_updated = artellalib.is_updated(item.path) if is_updated is None: item.setCheckState(0, Qt.Checked) # item.setFlags(Qt.NoItemFlags) for i in range(5): item.setBackgroundColor(i, QColor(160, 50, 40, 100)) item.setText(2, 'ONLY IN LOCAL') item.setText(3, 'ONLY IN LOCAL') # not_updated_items.append(item) elif is_updated is False: item.setCheckState(0, Qt.Unchecked) item.setFlags(Qt.NoItemFlags) for i in range(5): item.setBackgroundColor(i, QColor(170, 130, 30, 100)) item.setText(2, 'NOT LAST VERSION SYNCED') item.setText(3, 'NOT LAST VERSION SYNCED') item.is_valid = False not_updated_items.append(item) if not_updated_items and not skip_update: item_paths = [item.path for item in not_updated_items] result = qtutils.show_question( None, 'Some files are not synced', 'Following files are not synced:\n\n {}\n\nDo you want to sync them?' .format('\n'.join(item_paths))) if result == QMessageBox.Yes: self._progress.setVisible(True) self._progress.setMinimum(0) self._progress.setMaximum(len(not_updated_items) - 1) self._progress_lbl.setText('Synchronizing files ...') for i, item in enumerate(not_updated_items): self._progress.setValue(i) self._progress_lbl.setText( 'Syncronizing {} ...'.format(item.path)) item.setIcon(0, tp.ResourcesMgr().icon('sync')) artellalib.synchronize_file(item.path) item.setIcon(0, tp.ResourcesMgr().icon('ok')) self._update_items(skip_update=True) except Exception as e: LOGGER.error(str(e)) LOGGER.error(traceback.format_exc()) finally: self._progress.setValue(0) self._progress_lbl.setText('') self._progress.setVisible(False)
def refresh(self): """ Refresh shaders data """ self.clear() shaders_extensions = artellapipe.ShadersMgr().get_shaders_extensions() if not shaders_extensions: return False for shader_extension in shaders_extensions: if not shader_extension.startswith('.'): shader_extension = '.{}'.format(shader_extension) if not self._shaders_path: shaders_library_paths = artellapipe.ShadersMgr( ).get_shaders_paths() if not shaders_library_paths: LOGGER.warning( 'Current Project has no shaders paths defined!') return False else: shaders_library_paths = python.force_list(self._shaders_path) valid_state = True invalid_paths = list() for shaders_path in shaders_library_paths: if not os.path.exists(shaders_path): invalid_paths.append(shaders_path) if invalid_paths: result = qtutils.show_question( None, 'Shaders Path not found!', 'Shaders Path is not sync! To start using this tool you should sync this folder first. ' 'Do you want to do it?') if result == QMessageBox.Yes: artellapipe.ShadersMgr().update_shaders( shaders_paths=invalid_paths) for shaders_path in invalid_paths: if not os.path.exists(shaders_path): LOGGER.debug( 'Shader Library Path not found after sync. Something is wrong, please contact TD!' ) valid_state = False if not valid_state: return False for shaders_path in shaders_library_paths: for shader_file in os.listdir(shaders_path): if not shader_file.endswith(shader_extension): LOGGER.warning( 'Shader File: "{}" has invalid shader extension! Skipping ...' .format(shader_file)) continue shader_name = os.path.splitext(shader_file)[0] shader_widget = self.SHADER_VIEWER_WIDGET_CLASS( project=self._project, shader_name=shader_name) shader_widget.clicked.connect( partial(self._on_shader_widget_clicked, shader_name)) self.add_shader(shader_widget)