示例#1
0
    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)
示例#2
0
    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()
示例#3
0
    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!')
示例#6
0
    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()
示例#9
0
    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
示例#11
0
    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)
示例#12
0
    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)
示例#13
0
    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()
示例#14
0
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)
示例#17
0
    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)