예제 #1
0
파일: models.py 프로젝트: sergeneren/anima
 def hasChildren(self, index):
     """returns True or False depending on to the index and the item on the
     index
     """
     logger.debug(
         'TaskTreeModel.hasChildren() is started for index: %s' % index)
     if not index.isValid():
         if self.user_tasks_only:
             if self.user_id:
                 projects_count = db.DBSession.query(ProjectUser.id)\
                     .filter(ProjectUser.user_id == self.user_id)\
                     .count()
             else:
                 projects_count = 0
         else:
             projects_count = db.DBSession.query(Project.id).count()
         return_value = projects_count > 0
     else:
         item = self.itemFromIndex(index)
         return_value = False
         if item:
             return_value = item.hasChildren()
     logger.debug(
         'TaskTreeModel.hasChildren() is finished for index: %s' % index)
     return return_value
예제 #2
0
파일: external.py 프로젝트: eoyilmaz/anima
    def initialize_structure(self, version):
        """Initializes the environment folder structure

        :return:
        """
        # check version type
        from stalker import Version
        if not isinstance(version, Version):
            raise TypeError(
                '"version" argument in %s.initialize_structureshould be a '
                'stalker.version.Version instance, not %s' % (
                    self.__class__.__name__,
                    version.__class__.__name__
                )
            )

        # create the folder in version.absolute_path
        extension = version.extension
        version.update_paths()
        version.extension = extension
        for folder in self.structure:
            folder_path = os.path.join(version.absolute_path, folder)
            logger.debug('creating: %s' % folder_path)
            try:
                os.makedirs(folder_path)
            except OSError:
                # dir exists
                pass
예제 #3
0
파일: fusion.py 프로젝트: theomission/anima
    def get_version_from_recent_files(self):
        """It will try to create a
        :class:`~oyProjectManager.models.version.Version` instance by looking
        at the recent files list.

        It will return None if it can not find one.

        :return: :class:`~oyProjectManager.models.version.Version`
        """
        # full_path = self.fusion_prefs["LastCompFile"]
        # return self.get_version_from_full_path(full_path)

        version = None
        rfm = RecentFileManager()

        try:
            recent_files = rfm[self.name]
        except KeyError:
            logger.debug('no recent files')
            recent_files = None

        if recent_files is not None:
            for i in range(len(recent_files)):
                version = self.get_version_from_full_path(recent_files[i])
                if version is not None:
                    break

            logger.debug("version from recent files is: %s" % version)

        return version
예제 #4
0
파일: models.py 프로젝트: theomission/anima
 def __init__(self, *args, **kwargs):
     QtGui.QStandardItemModel.__init__(self, *args, **kwargs)
     logger.debug('TaskTreeModel.__init__() is started')
     self.user = None
     self.root = None
     self.user_tasks_only = False
     logger.debug('TaskTreeModel.__init__() is finished')
예제 #5
0
파일: version.py 프로젝트: eoyilmaz/anima
 def __init__(self, flat_view=False, *args, **kwargs):
     QtGui.QStandardItemModel.__init__(self, *args, **kwargs)
     logger.debug('VersionTreeModel.__init__() is started')
     self.root = None
     self.root_versions = []
     self.reference_resolution = None
     self.flat_view = flat_view
     logger.debug('VersionTreeModel.__init__() is finished')
예제 #6
0
파일: task.py 프로젝트: eoyilmaz/anima
 def clone(self):
     """returns a copy of this item
     """
     logger.debug('TaskItem.clone() is started for item: %s' % self.text())
     new_item = TaskItem(entity=self.task)
     new_item.parent = self.parent
     new_item.fetched_all = self.fetched_all
     logger.debug('TaskItem.clone() is finished for item: %s' % self.text())
     return new_item
예제 #7
0
파일: models.py 프로젝트: theomission/anima
 def current_take_name(self, take_name):
     """sets the current take name
     """
     logger.debug('finding take with name: %s' % take_name)
     items = self.findItems(
         take_name,
         QtCore.Qt.MatchExactly
     )
     if items:
         self.setCurrentItem(items[0])
예제 #8
0
파일: models.py 프로젝트: theomission/anima
 def hasChildren(self):
     logger.debug(
         'VersionItem.hasChildren() is started for item: %s' % self.text())
     if self.version:
         return_value = bool(self.version.inputs)
     else:
         return_value = False
     logger.debug(
         'VersionItem.hasChildren() is finished for item: %s' % self.text())
     return return_value
예제 #9
0
파일: models.py 프로젝트: theomission/anima
 def clone(self):
     """returns a copy of this item
     """
     logger.debug('VersionItem.clone() is started for item: %s' % self.text())
     new_item = VersionItem()
     new_item.version = self.version
     new_item.parent = self.parent
     new_item.fetched_all = self.fetched_all
     logger.debug('VersionItem.clone() is finished for item: %s' % self.text())
     return new_item
예제 #10
0
파일: task.py 프로젝트: eoyilmaz/anima
    def hasChildren(self):
        logger.debug(
            'TaskItem.hasChildren() is started for item: %s' % self.text()
        )
        return_value = self.task.has_children

        logger.debug(
            'TaskItem.hasChildren() is finished for item: %s' % self.text()
        )
        return return_value
예제 #11
0
파일: models.py 프로젝트: theomission/anima
 def canFetchMore(self):
     logger.debug(
         'VersionItem.canFetchMore() is started for item: %s' % self.text())
     if self.version and not self.fetched_all:
         return_value = bool(self.version.inputs)
     else:
         return_value = False
     logger.debug(
         'VersionItem.canFetchMore() is finished for item: %s' % self.text())
     return return_value
예제 #12
0
파일: models.py 프로젝트: theomission/anima
 def fetchMore(self, index):
     """fetches more elements
     """
     logger.debug(
         'TaskTreeModel.canFetchMore() is started for index: %s' % index)
     if index.isValid():
         item = self.itemFromIndex(index)
         item.fetchMore()
     logger.debug(
         'TaskTreeModel.canFetchMore() is finished for index: %s' % index)
예제 #13
0
    def _show_versions_treeView_context_menu(self, position):
        """the custom context menu for the versions_treeView
        """
        # convert the position to global screen position
        global_position = \
            self.versions_treeView.mapToGlobal(position)

        index = self.versions_treeView.indexAt(position)
        model = self.versions_treeView.model()

        # get the column 0 item which holds the Version instance
        # index = self.versions_treeView.model().index(index.row(), 0)
        item = model.itemFromIndex(index)
        logger.debug('itemAt(position) : %s' % item)

        if not item:
            return

        if not hasattr(item, 'version'):
            return

        version = item.version
        latest_published_version = None
        if version:
            latest_published_version = version.latest_published_version

        item_action = item.action

        # if item_action != 'create':
        #    return

        from stalker import Version
        if not isinstance(version, Version):
            return

        # create the menu
        menu = QtWidgets.QMenu()

        # Add "Open..." action
        # Always open the latest published version
        absolute_full_path = version.absolute_full_path
        if absolute_full_path:
            action = menu.addAction('Open...')
            if latest_published_version:
                action.version = latest_published_version
            else:
                action.version = version

        selected_action = menu.exec_(global_position)

        if selected_action:
            choice = selected_action.text()
            if choice == 'Open...':
                self.open_version(selected_action.version)
예제 #14
0
파일: models.py 프로젝트: theomission/anima
 def canFetchMore(self, index):
     logger.debug(
         'TaskTreeModel.canFetchMore() is started for index: %s' % index)
     if not index.isValid():
         return_value = False
     else:
         item = self.itemFromIndex(index)
         return_value = item.canFetchMore()
     logger.debug(
         'TaskTreeModel.canFetchMore() is finished for index: %s' % index)
     return return_value
예제 #15
0
파일: task.py 프로젝트: eoyilmaz/anima
 def get_item_indices_containing_text(cls, text, tree_view):
     """returns the indexes of the item indices containing the given text
     """
     model = tree_view.model()
     logger.debug('searching for text : %s' % text)
     return model.match(
         model.index(0, 0),
         0,
         text,
         -1,
         QtCore.Qt.MatchRecursive
     )
예제 #16
0
파일: models.py 프로젝트: theomission/anima
 def __init__(self, *args, **kwargs):
     QtGui.QStandardItem.__init__(self, *args, **kwargs)
     logger.debug(
         'VersionItem.__init__() is started for item: %s' % self.text())
     self.loaded = False
     self.version = None
     self.parent = None
     self.pseudo_model = None
     self.fetched_all = False
     self.setEditable(False)
     logger.debug(
         'VersionItem.__init__() is finished for item: %s' % self.text())
예제 #17
0
파일: reviewer.py 프로젝트: eoyilmaz/anima
    def execute(self, context):
        logger.debug('inside %s.execute()' % self.__class__.__name__)

        # get the scene and all the shots under it
        scene = Task.query.get(self.stalker_entity_id)

        logger.debug('scene: %s' % scene)

        # generate storyboard
        strip_gen = StripGenerator()
        strip_gen.previs(scene)

        return set(['FINISHED'])
예제 #18
0
    def show(self):
        """overridden show method
        """
        logger.debug('MainDialog.show is started')
        self.logged_in_user = self.get_logged_in_user()
        if not self.logged_in_user:
            self.close()
            return_val = None
        else:
            return_val = super(MainDialog, self).show()

        logger.debug('MainDialog.show is finished')
        return return_val
예제 #19
0
파일: task.py 프로젝트: eoyilmaz/anima
 def canFetchMore(self):
     logger.debug(
         'TaskItem.canFetchMore() is started for item: %s' % self.text()
     )
     # return_value = False
     if self.task and self.task.id and not self.fetched_all:
         return_value = self.task.has_children
     else:
         return_value = False
     logger.debug(
         'TaskItem.canFetchMore() is finished for item: %s' % self.text()
     )
     return return_value
예제 #20
0
파일: models.py 프로젝트: theomission/anima
    def update(self, completion_prefix):
        tasks = Task.query \
            .filter(Task.name.ilike('%' + completion_prefix + '%')) \
            .all()
        logger.debug('completer tasks : %s' % tasks)
        task_names = [task.name for task in tasks]
        model = QtGui.QStringListModel(task_names)
        self.setModel(model)
        # self.setCompletionPrefix(completion_prefix)
        self.setCompletionPrefix('')

        # if completion_prefix.strip() != '':
        self.complete()
예제 #21
0
    def flatten(self, path, project_name='DefaultProject'):
        """Flattens the given maya scene in to a new default project externally
        that is without opening it and returns the project path.

        It will also flatten all the referenced files, textures, image planes
        and Arnold Scene Source files.

        :param path: The path to the file which wanted to be flattened
        :return:
        """
        # create a new Default Project
        tempdir = tempfile.gettempdir()
        from stalker import Repository
        all_repos = Repository.query.all()

        default_project_path = \
            self.create_default_project(path=tempdir, name=project_name)

        logger.debug(
            'creating new default project at: %s' % default_project_path
        )

        ref_paths = \
            self._move_file_and_fix_references(path, default_project_path)

        while len(ref_paths):
            ref_path = ref_paths.pop(0)

            if self.exclude_mask \
               and os.path.splitext(ref_path)[1] in self.exclude_mask:
                    logger.debug('skipping: %s' % ref_path)
                    continue

            # fix different OS paths
            for repo in all_repos:
                if repo.is_in_repo(ref_path):
                    ref_path = repo.to_native_path(ref_path)

            new_ref_paths = \
                self._move_file_and_fix_references(
                    ref_path,
                    default_project_path,
                    scenes_folder='scenes/refs'
                )

            # extend ref_paths with new ones
            for new_ref_path in new_ref_paths:
                if new_ref_path not in ref_paths:
                    ref_paths.append(new_ref_path)

        return default_project_path
예제 #22
0
    def _setup_signals(self):
        """sets up the signals
        """
        logger.debug("start setting up interface signals")

        # Dialog buttons
        QtCore.QObject.connect(
            self.dialog_button_box,
            QtCore.SIGNAL("accepted()"),
            self.accept
        )
        QtCore.QObject.connect(
            self.dialog_button_box,
            QtCore.SIGNAL("rejected()"),
            self.reject
        )

        # tasks_combo_box
        QtCore.QObject.connect(
            self.tasks_combo_box,
            QtCore.SIGNAL('currentIndexChanged(QString)'),
            self.tasks_combo_box_index_changed
        )

        # start_time_edit
        QtCore.QObject.connect(
            self.start_time_edit,
            QtCore.SIGNAL('timeChanged(QTime)'),
            self.start_time_changed
        )

        # end_time_edit
        QtCore.QObject.connect(
            self.end_time_edit,
            QtCore.SIGNAL('timeChanged(QTime)'),
            self.end_time_changed
        )

        # resource changed
        QtCore.QObject.connect(
            self.resource_combo_box,
            QtCore.SIGNAL('currentIndexChanged(QString)'),
            self.resource_changed
        )

        # calendar day selected
        QtCore.QObject.connect(
            self.calendar_widget,
            QtCore.SIGNAL("selectionChanged()"),
            self.calendar_widget_selection_changed
        )
예제 #23
0
    def _move_file_and_fix_references(self, path, project_path,
                                      scenes_folder='scenes',
                                      refs_folder='scenes/refs'):
        """Moves the given maya file to the given project path and moves any
        references of it to

        :param str path: The path of the maya file
        :param str project_path: The project path
        :param str scenes_folder: The scenes folder to store the original maya
          scene.
        :param str refs_folder: The references folder to replace reference
          paths with.
        :return list: returns a list of paths
        """
        # fix any env vars
        path = os.path.expandvars(path)

        original_file_name = os.path.basename(path)
        logger.debug('original_file_name: %s' % original_file_name)

        new_file_path = \
            os.path.join(project_path, scenes_folder, original_file_name)

        ref_paths = []

        # only get new ref paths for '.ma' files
        if path.endswith('.ma'):
            # read the data of the original file
            with open(path) as f:
                data = f.read()

            ref_paths = self._extract_references(data)
            # fix all reference paths
            for ref_path in ref_paths:
                data = data.replace(
                    ref_path,
                    '%s/%s' % (refs_folder, os.path.basename(ref_path))
                )

            # now write all the data back to a new temp scene
            with open(new_file_path, 'w+') as f:
                f.write(data)
        else:
            # just copy the file
            try:
                shutil.copy(path, new_file_path)
            except IOError:
                pass

        return ref_paths
예제 #24
0
    def fill_versions_treeView(self):
        """sets up the versions_treeView
        """
        logger.debug('start filling versions_treeView')
        logger.debug('creating a new model')

        version_tree_model = VersionTreeModel()
        version_tree_model.reference_resolution = self.reference_resolution

        # populate with all update items
        version_tree_model.populateTree(self.reference_resolution['root'])

        self.versions_treeView.setModel(version_tree_model)

        logger.debug('setting up signals for versions_treeView_changed')
        # versions_treeView
        # QtCore.QObject.connect(
        #     self.versions_treeView.selectionModel(),
        #     QtCore.SIGNAL('selectionChanged(const QItemSelection &, '
        #                   'const QItemSelection &)'),
        #     self.versions_treeView_changed
        # )

        self.versions_treeView.is_updating = False
        self.versions_treeView_auto_fit_column()
        logger.debug('finished filling versions_treeView')
예제 #25
0
파일: models.py 프로젝트: theomission/anima
 def __init__(self, *args, **kwargs):
     QtGui.QStandardItem.__init__(self, *args, **kwargs)
     logger.debug(
         'TaskItem.__init__() is started for item: %s' % self.text()
     )
     self.loaded = False
     self.task = None
     self.parent = None
     self.fetched_all = False
     self.setEditable(False)
     self.user = None
     self.user_tasks_only = False
     logger.debug(
         'TaskItem.__init__() is finished for item: %s' % self.text()
     )
예제 #26
0
파일: reviewer.py 프로젝트: eoyilmaz/anima
    def execute(self, context):
        logger.debug('inside %s.execute()' % self.__class__.__name__)

        # get the scene and all the shots under it
        shot = Shot.query.get(self.stalker_entity_id)

        logger.debug('shot: %s' % shot)

        # find Previs, Animation, Lighting and Comp tasks

        # # generate storyboard
        # strip_gen = StripGenerator()
        # strip_gen.comp(shot)

        return set(['FINISHED'])
예제 #27
0
    def clean_up(self):
        """cleans up the scene
        """
        num_of_items_deleted = pm.mel.eval('MLdeleteUnused')

        logger.debug('deleting unknown references')
        delete_nodes_types = ['reference', 'unknown']
        for node in pm.ls(type=delete_nodes_types):
            node.unlock()

        logger.debug('deleting "delete_nodes_types"')
        try:
            pm.delete(pm.ls(type=delete_nodes_types))
        except RuntimeError:
            pass
예제 #28
0
파일: models.py 프로젝트: theomission/anima
 def canFetchMore(self):
     logger.debug(
         'TaskItem.canFetchMore() is started for item: %s' % self.text()
     )
     return_value = False
     if self.task and not self.fetched_all:
         if isinstance(self.task, Task):
             return_value = self.task.is_container
         elif isinstance(self.task, Project):
             return_value = len(self.task.root_tasks) > 0
     else:
         return_value = False
     logger.debug(
         'TaskItem.canFetchMore() is finished for item: %s' % self.text()
     )
     return return_value
예제 #29
0
파일: models.py 프로젝트: theomission/anima
    def fetchMore(self):
        logger.debug(
            'VersionItem.fetchMore() is started for item: %s' % self.text())

        if self.canFetchMore():
            # model = self.model() # This will cause a SEGFAULT
            versions = sorted(self.version.inputs, key=lambda x: x.full_path)

            for version in versions:
                self.appendRow(
                    self.generate_version_row(self, self.pseudo_model, version)
                )

            self.fetched_all = True
        logger.debug(
            'VersionItem.fetchMore() is finished for item: %s' % self.text())
예제 #30
0
파일: version.py 프로젝트: eoyilmaz/anima
 def populateTree(self, versions):
     """populates tree with root versions
     """
     logger.debug('VersionTreeModel.populateTree() is started')
     self.setColumnCount(7)
     self.setHorizontalHeaderLabels(
         ['Do Update?', 'Thumbnail', 'Task', 'Take', 'Current', 'Latest',
          'Action', 'Updated By', 'Notes']
     )
     
     self.root_versions = versions
     for version in versions:
         self.appendRow(
             VersionItem.generate_version_row(None, self, version)
         )
     
     logger.debug('VersionTreeModel.populateTree() is finished')
예제 #31
0
파일: task.py 프로젝트: yazici/anima
    def show_context_menu(self, position):
        """the custom context menu
        """
        # convert the position to global screen position
        global_position = self.mapToGlobal(position)

        index = self.indexAt(position)
        model = self.model()
        item = model.itemFromIndex(index)
        logger.debug('itemAt(position) : %s' % item)
        task_id = None
        entity = None

        # if not item:
        #     return

        # if item and not hasattr(item, 'task'):
        #     return

        from anima.ui.models.task import TaskItem
        #if not isinstance(item, TaskItem):
        #    return

        if item and item.task:
            task_id = item.task.id

        # if not task_id:
        #     return

        from anima import utils
        file_browser_name = utils.file_browser_name()

        # create the menu
        menu = QtWidgets.QMenu()  # Open in browser

        # sub menus
        create_sub_menu = menu.addMenu('Create')
        update_sub_menu = menu.addMenu('Update')

        # -----------------------------------
        # actions created in different scopes
        create_time_log_action = None
        create_project_action = None
        update_task_action = None
        create_child_task_action = None
        duplicate_task_hierarchy_action = None
        delete_task_action = None
        no_deps_action = None
        create_project_structure_action = None
        create_task_structure_action = None
        update_project_action = None
        assign_users_action = None
        open_in_web_browser_action = None
        open_in_file_browser_action = None
        copy_url_action = None
        copy_id_to_clipboard = None
        fix_task_status_action = None
        change_status_menu_actions = []

        from anima import defaults
        from stalker import LocalSession
        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user

        from stalker import SimpleEntity, Task, Project
        # TODO: Update this to use only task_id
        if task_id:
            entity = SimpleEntity.query.get(task_id)

        if defaults.is_power_user(logged_in_user):
            # create the Create Project menu item
            create_project_action = \
                create_sub_menu.addAction(u'\uf0e8 Create Project...')

            if isinstance(entity, Project):
                # this is a project!
                if defaults.is_power_user(logged_in_user):
                    update_project_action = \
                        update_sub_menu.addAction(u'\uf044 Update Project...')
                    assign_users_action = \
                        menu.addAction(u'\uf0c0 Assign Users...')
                    create_project_structure_action = \
                        create_sub_menu.addAction(
                            u'\uf115 Create Project Structure'
                        )
                    create_child_task_action = \
                        create_sub_menu.addAction(
                            u'\uf0ae Create Child Task...'
                        )

        if entity:
            # separate the Project and Task related menu items
            menu.addSeparator()

            open_in_web_browser_action = \
                menu.addAction(u'\uf14c Open In Web Browser...')
            open_in_file_browser_action = \
                menu.addAction(u'\uf07c Browse Folders...')
            copy_url_action = menu.addAction(u'\uf0c5 Copy URL')
            copy_id_to_clipboard = \
                menu.addAction(u'\uf0c5 Copy ID to clipboard')

            if isinstance(entity, Task):
                # this is a task
                create_task_structure_action = \
                    create_sub_menu.addAction(
                        u'\uf115 Create Task Folder Structure'
                    )

                task = entity
                from stalker import Status
                status_wfd = Status.query.filter(Status.code == 'WFD').first()
                status_prev = \
                    Status.query.filter(Status.code == 'PREV').first()
                status_cmpl = \
                    Status.query.filter(Status.code == 'CMPL').first()
                if logged_in_user in task.resources \
                        and task.status not in [status_wfd, status_prev,
                                                status_cmpl]:
                    create_sub_menu.addSeparator()
                    create_time_log_action = \
                        create_sub_menu.addAction(u'\uf073 Create TimeLog...')

                # Add Depends To menu
                menu.addSeparator()
                depends = task.depends
                if depends:
                    depends_to_menu = menu.addMenu(u'\uf090 Depends To')

                    for dTask in depends:
                        action = depends_to_menu.addAction(dTask.name)
                        action.task = dTask

                # Add Dependent Of Menu
                dependent_of = task.dependent_of
                if dependent_of:
                    dependent_of_menu = menu.addMenu(u'\uf08b Dependent Of')

                    for dTask in dependent_of:
                        action = dependent_of_menu.addAction(dTask.name)
                        action.task = dTask

                if not depends and not dependent_of:
                    no_deps_action = menu.addAction(u'\uf00d No Dependencies')
                    no_deps_action.setEnabled(False)

                # update task and create child task menu items
                menu.addSeparator()
                if defaults.is_power_user(logged_in_user):
                    create_sub_menu.addSeparator()
                    update_task_action = \
                        update_sub_menu.addAction(u'\uf044 Update Task...')

                    create_child_task_action = \
                        create_sub_menu.addAction(
                            u'\uf0ae Create Child Task...'
                        )
                    duplicate_task_hierarchy_action = \
                        create_sub_menu.addAction(
                            u'\uf0c5 Duplicate Task Hierarchy...'
                        )
                    delete_task_action = \
                        menu.addAction(u'\uf1f8 Delete Task...')

                # create the status_menu
                status_menu = update_sub_menu.addMenu('Status')

                fix_task_status_action = \
                    status_menu.addAction(u'\uf0e8 Fix Task Status')

                assert isinstance(status_menu, QtWidgets.QMenu)
                status_menu.addSeparator()

                # get all task statuses
                from anima import defaults

                menu_style_sheet = ''
                defaults_status_colors = defaults.status_colors
                for status_code in defaults.status_colors:
                    change_status_menu_action = \
                        status_menu.addAction(status_code)

                    change_status_menu_action.setObjectName('status_%s' %
                                                            status_code)

                    change_status_menu_actions.append(
                        change_status_menu_action)

                    menu_style_sheet = "%s %s" % (
                        menu_style_sheet,
                        "QMenu#status_%s { background: %s %s %s}" % (
                            status_code,
                            defaults_status_colors[status_code][0],
                            defaults_status_colors[status_code][1],
                            defaults_status_colors[status_code][2],
                        ))

                # change the BG Color of the status
                status_menu.setStyleSheet(menu_style_sheet)

        try:
            # PySide and PySide2
            accepted = QtWidgets.QDialog.DialogCode.Accepted
        except AttributeError:
            # PyQt4
            accepted = QtWidgets.QDialog.Accepted

        selected_item = menu.exec_(global_position)
        if selected_item:
            if create_project_action \
               and selected_item == create_project_action:
                from anima.ui import project_dialog
                project_main_dialog = project_dialog.MainDialog(parent=self,
                                                                project=None)
                project_main_dialog.exec_()
                result = project_main_dialog.result()

                # refresh the task list
                if result == accepted:
                    self.fill()

                project_main_dialog.deleteLater()

            if entity:
                from anima import defaults
                url = 'http://%s/%ss/%s/view' % (
                    defaults.stalker_server_internal_address,
                    entity.entity_type.lower(), entity.id)

                if selected_item is open_in_web_browser_action:
                    import webbrowser
                    webbrowser.open(url)
                elif selected_item is open_in_file_browser_action:
                    from anima import utils
                    try:
                        utils.open_browser_in_location(entity.absolute_path)
                    except IOError as e:
                        QtWidgets.QMessageBox.critical(
                            self, "Error", "%s" % e, QtWidgets.QMessageBox.Ok)
                elif selected_item is copy_url_action:
                    clipboard = QtWidgets.QApplication.clipboard()
                    clipboard.setText(url)

                    # and warn the user about a new version is created and the
                    # clipboard is set to the new version full path
                    QtWidgets.QMessageBox.warning(
                        self, "URL Copied To Clipboard",
                        "URL:<br><br>%s<br><br>is copied to clipboard!" % url,
                        QtWidgets.QMessageBox.Ok)
                elif selected_item is copy_id_to_clipboard:
                    clipboard = QtWidgets.QApplication.clipboard()
                    clipboard.setText('%s' % entity.id)

                    # and warn the user about a new version is created and the
                    # clipboard is set to the new version full path
                    QtWidgets.QMessageBox.warning(
                        self, "ID Copied To Clipboard",
                        "ID %s is copied to clipboard!" % entity.id,
                        QtWidgets.QMessageBox.Ok)

                elif selected_item is create_time_log_action:
                    from anima.ui import time_log_dialog
                    time_log_dialog_main_dialog = time_log_dialog.MainDialog(
                        parent=self,
                        task=entity,
                    )
                    time_log_dialog_main_dialog.exec_()
                    result = time_log_dialog_main_dialog.result()
                    time_log_dialog_main_dialog.deleteLater()

                    if result == accepted:
                        # refresh the task list
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()

                        # reselect the same task
                        self.find_and_select_entity_item(entity)

                elif selected_item is update_task_action:
                    from anima.ui import task_dialog
                    task_main_dialog = task_dialog.MainDialog(parent=self,
                                                              task=entity)
                    task_main_dialog.exec_()
                    result = task_main_dialog.result()
                    task_main_dialog.deleteLater()

                    # refresh the task list
                    if result == accepted:
                        # just reload the same item
                        if item.parent:
                            item.parent.reload()
                        else:
                            # reload the entire
                            self.fill()
                        self.find_and_select_entity_item(entity)

                elif selected_item == create_child_task_action:
                    from anima.ui import task_dialog
                    task_main_dialog = task_dialog.MainDialog(
                        parent=self, parent_task=entity)
                    task_main_dialog.exec_()
                    result = task_main_dialog.result()
                    task = task_main_dialog.task
                    task_main_dialog.deleteLater()

                    if result == accepted and task:
                        # reload the parent item
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()
                        self.find_and_select_entity_item(task)

                elif selected_item is duplicate_task_hierarchy_action:
                    duplicate_task_hierarchy_dialog = \
                        DuplicateTaskHierarchyDialog(
                            parent=self, duplicated_task_name=item.task.name
                        )
                    duplicate_task_hierarchy_dialog.exec_()

                    result = duplicate_task_hierarchy_dialog.result()
                    if result == accepted:
                        new_task_name = \
                            duplicate_task_hierarchy_dialog.line_edit.text()

                        keep_resources = \
                            duplicate_task_hierarchy_dialog\
                                .check_box.checkState()

                        from anima import utils
                        from stalker import Task
                        task = Task.query.get(item.task.id)
                        new_task = utils.duplicate_task_hierarchy(
                            task,
                            None,
                            new_task_name,
                            description='Duplicated from Task(%s)' % task.id,
                            user=logged_in_user,
                            keep_resources=keep_resources)
                        if new_task:
                            from stalker.db.session import DBSession
                            DBSession.commit()
                            item.parent.reload()
                            self.find_and_select_entity_item(new_task)

                elif selected_item is delete_task_action:
                    answer = QtWidgets.QMessageBox.question(
                        self, 'Delete Task?',
                        "Delete the task and children?<br><br>(NO UNDO!!!!)",
                        QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
                    if answer == QtWidgets.QMessageBox.Yes:
                        from stalker.db.session import DBSession
                        from stalker import Task
                        task = Task.query.get(item.task.id)
                        DBSession.delete(task)
                        DBSession.commit()
                        # reload the parent
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()
                        self.find_and_select_entity_item(item.parent.task)

                elif selected_item == create_project_structure_action:
                    answer = QtWidgets.QMessageBox.question(
                        self, 'Create Project Folder Structure?',
                        "This will create project folders, OK?",
                        QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
                    if answer == QtWidgets.QMessageBox.Yes:
                        from anima import utils
                        try:
                            utils.create_project_structure(entity)
                        except Exception as e:
                            pass
                        finally:
                            QtWidgets.QMessageBox.information(
                                self,
                                'Project Folder Structure is created!',
                                'Project Folder Structure is created!',
                            )
                    else:
                        return

                elif selected_item == create_task_structure_action:
                    answer = QtWidgets.QMessageBox.question(
                        self, 'Create Folder Structure?',
                        "This will create task folders, OK?",
                        QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
                    if answer == QtWidgets.QMessageBox.Yes:
                        from anima import utils
                        try:
                            utils.create_task_structure(entity)
                        except Exception as e:
                            pass
                        finally:
                            QtWidgets.QMessageBox.information(
                                self,
                                'Folder Structure is created!',
                                'Folder Structure is created!',
                            )
                    else:
                        return

                elif selected_item == fix_task_status_action:
                    from stalker import Task
                    if isinstance(entity, Task):
                        from anima import utils
                        utils.fix_task_statuses(entity)

                        from stalker.db.session import DBSession
                        DBSession.add(entity)
                        DBSession.commit()

                        if item.parent:
                            item.parent.reload()

                elif selected_item == update_project_action:
                    from anima.ui import project_dialog
                    project_main_dialog = project_dialog.MainDialog(
                        parent=self, project=entity)
                    project_main_dialog.exec_()
                    result = project_main_dialog.result()

                    # refresh the task list
                    if result == accepted:
                        self.fill()

                        # reselect the same task
                        self.find_and_select_entity_item(entity)

                    project_main_dialog.deleteLater()

                elif selected_item == assign_users_action:
                    from anima.ui import project_users_dialog
                    project_users_main_dialog = \
                        project_users_dialog.MainDialog(
                            parent=self,
                            project=entity
                        )
                    project_users_main_dialog.exec_()
                    result = project_users_main_dialog.result()

                    project_users_main_dialog.deleteLater()

                elif selected_item in change_status_menu_actions:
                    # get the status code
                    status_code = selected_item.text()

                    from sqlalchemy import func
                    status = \
                        Status.query.filter(
                            func.lower(Status.code) == func.lower(status_code)
                        ).first()

                    # change the status of the entity
                    # if it is a leaf task
                    # if it doesn't have any dependent_of
                    # assert isinstance(entity, Task)
                    if isinstance(entity, Task):
                        if entity.is_leaf and not entity.dependent_of:
                            # then we can update it
                            entity.status = status

                            # # fix other task statuses
                            # from anima import utils
                            # utils.fix_task_statuses(entity)

                            # refresh the tree
                            from stalker.db.session import DBSession
                            DBSession.add(entity)
                            DBSession.commit()

                            if item.parent:
                                item.parent.reload()
                                self.find_and_select_entity_item(entity)
                else:
                    try:
                        # go to the dependencies
                        dep_task = selected_item.task
                        self.find_and_select_entity_item(dep_task, self)
                    except AttributeError:
                        pass
예제 #32
0
    def generate_video_thumbnail(self, file_full_path):
        """Generates a thumbnail for the given video link

        :param str file_full_path: A string showing the full path of the video
          file.
        """
        # TODO: split this in to two different methods, one generating
        #       thumbnails from the video and another one accepting three
        #       images
        media_info = self.get_video_info(file_full_path)
        video_info = media_info['video_info']

        # get the correct stream
        video_stream = None
        for stream in media_info['stream_info']:
            if stream['codec_type'] == 'video':
                video_stream = stream

        nb_frames = video_stream.get('nb_frames')
        if nb_frames is None or nb_frames == 'N/A':
            # no nb_frames
            # first try to use "r_frame_rate" and "duration"
            frame_rate = video_stream.get('r_frame_rate')

            if frame_rate is None:  # still no frame rate
                # try to use the video_info and duration
                # and try to get frame rate
                frame_rate = float(video_info.get('TAG:framerate', 23.976))
            else:
                # check if it is in Number/Number format
                if '/' in frame_rate:
                    nominator, denominator = frame_rate.split('/')
                    frame_rate = float(nominator) / float(denominator)

            # get duration
            duration = video_stream.get('duration')
            if duration == 'N/A':  # no duration
                duration = float(video_info.get('duration', 1))
            else:
                duration = float(duration)

            # at this stage we should have enough info, may not be correct but
            # we should have something
            # calculate nb_frames
            logger.debug('duration  : %s' % duration)
            logger.debug('frame_rate: %s' % frame_rate)
            nb_frames = int(duration * frame_rate)
        nb_frames = int(nb_frames)

        start_thumb_path = tempfile.mktemp(suffix=self.thumbnail_format)
        mid_thumb_path = tempfile.mktemp(suffix=self.thumbnail_format)
        end_thumb_path = tempfile.mktemp(suffix=self.thumbnail_format)

        thumbnail_path = tempfile.mktemp(suffix=self.thumbnail_format)

        # generate three thumbnails from the start, middle and end of the file
        start_frame = int(nb_frames * 0.10)
        mid_frame = int(nb_frames * 0.5)
        end_frame = int(nb_frames * 0.90) - 1

        # start_frame
        self.ffmpeg(
            **{
                'i': file_full_path,
                'vf': "select='eq(n,0)'",
                'vframes': start_frame,
                'o': start_thumb_path
            })
        # mid_frame
        self.ffmpeg(
            **{
                'i': file_full_path,
                'vf': "select='eq(n,%s)'" % mid_frame,
                'vframes': 1,
                'o': mid_thumb_path
            })
        # end_frame
        self.ffmpeg(
            **{
                'i': file_full_path,
                'vf': "select='eq(n,%s)'" % end_frame,
                'vframes': 1,
                'o': end_thumb_path
            })

        # check if all of the thumbnails are present
        if not os.path.exists(start_thumb_path):
            if os.path.exists(mid_thumb_path):
                start_thumb_path = mid_thumb_path
            elif os.path.exists(end_thumb_path):
                start_thumb_path = end_thumb_path
                mid_thumb_path = end_thumb_path

        if not os.path.exists(mid_thumb_path):
            if os.path.exists(start_thumb_path):
                mid_thumb_path = start_thumb_path
            else:
                start_thumb_path = end_thumb_path
                mid_thumb_path = end_thumb_path

        if not os.path.exists(end_thumb_path):
            # use the mid frame if available or the start frame
            if os.path.exists(mid_thumb_path):
                end_thumb_path = mid_thumb_path
            else:
                mid_thumb_path = start_thumb_path
                end_thumb_path = start_thumb_path

        # now merge them
        self.ffmpeg(
            **{
                'i': [start_thumb_path, mid_thumb_path, end_thumb_path],
                'filter_complex':
                '[0:0]scale=3*%(tw)s/4:-1,pad=%(tw)s:%(th)s[s];'
                '[1:0]scale=3*%(tw)s/4:-1,fade=out:300:30:alpha=1[m];'
                '[2:0]scale=3*%(tw)s/4:-1,fade=out:300:30:alpha=1[e];'
                '[s][e]overlay=%(tw)s/4:%(th)s-h[x];'
                '[x][m]overlay=%(tw)s/8:%(th)s/2-h/2' % {
                    'tw': self.thumbnail_width,
                    'th': self.thumbnail_height
                },
                'o': thumbnail_path
            })

        # remove the intermediate data
        try:
            os.remove(start_thumb_path)
        except OSError:
            pass

        try:
            os.remove(mid_thumb_path)
        except OSError:
            pass

        try:
            os.remove(end_thumb_path)
        except OSError:
            pass

        return thumbnail_path
예제 #33
0
def ldap_server():
    """creates a mock ldap server for tests
    """
    global __here__

    # set some default ldap settings
    from anima import defaults
    defaults.enable_ldap_authentication = True
    defaults.ldap_server_address = 'localhost'
    defaults.ldap_base_dn = 'DC=animagpu,DC=local'

    # create mapping from LDAP groups to Stalker Groups
    defaults.ldap_user_group_map = {
        'Administrators': 'admins',
        'Users': 'Normal Users',
        'GPU Users': 'Normal Users',
        'GPU Users Admin': 'Power Users'
    }

    from ldap3 import Server, Connection, MOCK_SYNC
    test_ldap_server_info_path = os.path.join(__here__, 'data',
                                              'LDAP_server_info.json')
    test_ldap_server_schema_path = os.path.join(__here__, 'data',
                                                'LDAP_server_schema.json')
    test_ldap_server_entries_path = os.path.join(__here__, 'data',
                                                 'LDAP_server_entries.json')

    # Mock Server with example data
    class MockServer(Server):
        def __init__(self, *args, **kwargs):
            logger.debug("Initializing the Mock Server!")
            super(MockServer, self).__init__(*args, **kwargs)

            # load the data
            logger.debug("Loading mock server data")
            self.from_definition('fake_server', test_ldap_server_info_path,
                                 test_ldap_server_schema_path)

    # Mock the Connection class to always use MOCK_SYNC as strategy
    # and fill it with fake data
    class MockConnection(Connection):
        def __init__(self, *args, **kwargs):
            logger.debug("Initializing the Mock Connection!")
            kwargs['client_strategy'] = MOCK_SYNC
            super(MockConnection, self).__init__(*args, **kwargs)

            # load the mock data
            logger.debug("Loading mock connection data")
            logger.debug("test_ldap_server_entries_path: %s" %
                         test_ldap_server_entries_path)
            self.strategy.entries_from_json(test_ldap_server_entries_path)

            # load a fake user for Simple binding
            logger.debug("Loading a fake user for Simple binding")
            self.strategy.add_entry(
                defaults.ldap_base_dn,
                {
                    "cn":
                    "admin",
                    "codePage":
                    0,
                    "displayName":
                    "admin",
                    "distinguishedName":
                    "CN=admin,OU=GPU Users Admin,DC=animagpu,DC=local",
                    "givenName":
                    "admin",
                    "instanceType":
                    4,
                    "memberOf":
                    ["CN=GPU Users Admin,CN=Users,DC=animagpu,DC=local"],
                    "name":
                    "admin",
                    "objectCategory":
                    "CN=Person,CN=Schema,CN=Configuration,DC=animagpu,DC=local",
                    # "objectCategory": "CN=Person,CN=Schema,CN=Configuration,%s" % defaults.ldap_base_dn,
                    "objectClass":
                    ["top", "person", "organizationalPerson", "user"],
                    "objectGUID":
                    "{9d96ef4a-14e7-4a77-b5b1-97b2fa239f9f}",
                    "objectSid":
                    "S-1-5-21-2227021422-3894238547-674366654-1131",
                    "primaryGroupID":
                    513,
                    "revision":
                    0,
                    "sAMAccountName":
                    "admin",
                    "sAMAccountType":
                    805306368,
                    "sn":
                    "admin",
                    "uSNChanged":
                    423892,
                    "uSNCreated":
                    314308,
                    "userAccountControl":
                    66048,
                    "userPassword":
                    "******",
                    "userPrincipalName":
                    "*****@*****.**",
                })

        def bind(self, *args, **kwargs):
            """mock the bind return value
            """
            super(MockConnection, self).bind(*args, **kwargs)
            # always return True if the user is "pipeline"
            allowed_users = [
                "pipeline", "CN=Pipeline,CN=Users,DC=animagpu,DC=local",
                "CN=admin,OU=GPU Users Admin,DC=animagpu,DC=local"
            ]
            if self.user in allowed_users and self.password == "password":
                return True
            return False

    logger.debug("Replacing original ldap3.Server class")
    import ldap3
    orig_server_class = ldap3.Server
    ldap3.Server = MockServer
    logger.debug("ldap3.Server: %s" % ldap3.Server)

    logger.debug("Replacing original ldap3.Connection class")
    orig_connection_class = ldap3.Connection
    ldap3.Connection = MockConnection
    logger.debug("ldap3.Connection: %s" % ldap3.Connection)

    yield MockServer, MockConnection

    # restore the class
    logger.debug("Restoring original ldap3.Server class")
    ldap3.Server = orig_server_class
    logger.debug("ldap3.Server: %s" % ldap3.Server)
    logger.debug("Restoring original ldap3.Connection class")
    ldap3.Connection = orig_connection_class
    logger.debug("ldap3.Connection: %s" % ldap3.Connection)
예제 #34
0
    def show_context_menu(self, position):
        """the custom context menu
        """
        # convert the position to global screen position
        global_position = self.mapToGlobal(position)

        index = self.indexAt(position)
        model = self.model()
        item = model.itemFromIndex(index)
        logger.debug('itemAt(position) : %s' % item)
        task_id = None
        entity = None

        # if not item:
        #     return

        # if item and not hasattr(item, 'task'):
        #     return

        # from anima.ui.models.task import TaskItem
        # if not isinstance(item, TaskItem):
        #     return

        if item:
            try:
                if item.task:
                    task_id = item.task.id
            except AttributeError:
                return

        # if not task_id:
        #     return

        from anima import utils
        file_browser_name = utils.file_browser_name()

        # create the menu
        menu = QtWidgets.QMenu()  # Open in browser

        # -----------------------------------
        # actions created in different scopes
        create_time_log_action = None
        create_project_action = None
        update_task_action = None
        upload_thumbnail_action = None
        create_child_task_action = None
        duplicate_task_hierarchy_action = None
        delete_task_action = None
        export_to_json_action = None
        import_from_json_action = None
        no_deps_action = None
        create_project_structure_action = None
        update_project_action = None
        assign_users_action = None
        open_in_web_browser_action = None
        open_in_file_browser_action = None
        copy_url_action = None
        copy_id_to_clipboard = None
        fix_task_status_action = None
        change_status_menu_actions = []

        from anima import defaults
        from stalker import LocalSession
        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user

        from stalker import SimpleEntity, Task, Project
        # TODO: Update this to use only task_id
        if task_id:
            entity = SimpleEntity.query.get(task_id)

        reload_action = menu.addAction(u'\uf0e8 Reload')

        # sub menus
        create_sub_menu = menu.addMenu('Create')
        update_sub_menu = menu.addMenu('Update')

        if defaults.is_power_user(logged_in_user):
            # create the Create Project menu item
            create_project_action = create_sub_menu.addAction(
                u'\uf0e8 Create Project...')

            if isinstance(entity, Project):
                # this is a project!
                if defaults.is_power_user(logged_in_user):
                    update_project_action = update_sub_menu.addAction(
                        u'\uf044 Update Project...')
                    assign_users_action = menu.addAction(
                        u'\uf0c0 Assign Users...')
                    create_project_structure_action = create_sub_menu.addAction(
                        u'\uf115 Create Project Structure')
                    create_child_task_action = create_sub_menu.addAction(
                        u'\uf0ae Create Child Task...')
                    # Export and Import JSON
                    create_sub_menu.addSeparator()
                    # export_to_json_action = create_sub_menu.addAction(u'\uf1f8 Export To JSON...')

                    import_from_json_action = create_sub_menu.addAction(
                        u'\uf1f8 Import From JSON...')

        if entity:
            # separate the Project and Task related menu items
            menu.addSeparator()

            open_in_web_browser_action = menu.addAction(
                u'\uf14c Open In Web Browser...')
            open_in_file_browser_action = menu.addAction(
                u'\uf07c Browse Folders...')
            copy_url_action = menu.addAction(u'\uf0c5 Copy URL')
            copy_id_to_clipboard = menu.addAction(
                u'\uf0c5 Copy ID to clipboard')

            if isinstance(entity, Task):
                # this is a task
                create_project_structure_action = create_sub_menu.addAction(
                    u'\uf115 Create Task Folder Structure')

                task = entity
                from stalker import Status
                status_wfd = Status.query.filter(Status.code == 'WFD').first()
                status_prev = Status.query.filter(
                    Status.code == 'PREV').first()
                status_cmpl = Status.query.filter(
                    Status.code == 'CMPL').first()
                if logged_in_user in task.resources and task.status not in [
                        status_wfd, status_prev, status_cmpl
                ]:
                    create_sub_menu.addSeparator()
                    create_time_log_action = create_sub_menu.addAction(
                        u'\uf073 Create TimeLog...')

                # Add Depends To menu
                menu.addSeparator()
                depends = task.depends
                if depends:
                    depends_to_menu = menu.addMenu(u'\uf090 Depends To')

                    for dTask in depends:
                        action = depends_to_menu.addAction(dTask.name)
                        action.task = dTask

                # Add Dependent Of Menu
                dependent_of = task.dependent_of
                if dependent_of:
                    dependent_of_menu = menu.addMenu(u'\uf08b Dependent Of')

                    for dTask in dependent_of:
                        action = dependent_of_menu.addAction(dTask.name)
                        action.task = dTask

                if not depends and not dependent_of:
                    no_deps_action = menu.addAction(u'\uf00d No Dependencies')
                    no_deps_action.setEnabled(False)

                # update task and create child task menu items
                menu.addSeparator()
                if defaults.is_power_user(logged_in_user):
                    create_sub_menu.addSeparator()
                    update_task_action = update_sub_menu.addAction(
                        u'\uf044 Update Task...')

                    upload_thumbnail_action = update_sub_menu.addAction(
                        u'\uf03e Upload Thumbnail...')

                    # Export and Import JSON
                    create_sub_menu.addSeparator()
                    export_to_json_action = create_sub_menu.addAction(
                        u'\uf1f8 Export To JSON...')

                    import_from_json_action = create_sub_menu.addAction(
                        u'\uf1f8 Import From JSON...')
                    create_sub_menu.addSeparator()

                    create_child_task_action = create_sub_menu.addAction(
                        u'\uf0ae Create Child Task...')

                    duplicate_task_hierarchy_action = create_sub_menu.addAction(
                        u'\uf0c5 Duplicate Task Hierarchy...')
                    delete_task_action = menu.addAction(
                        u'\uf1f8 Delete Task...')

                    menu.addSeparator()

                # create the status_menu
                status_menu = update_sub_menu.addMenu('Status')

                fix_task_status_action = status_menu.addAction(
                    u'\uf0e8 Fix Task Status')

                assert isinstance(status_menu, QtWidgets.QMenu)
                status_menu.addSeparator()

                # get all task statuses
                from anima import defaults

                menu_style_sheet = ''
                defaults_status_colors = defaults.status_colors
                for status_code in defaults.status_colors:
                    change_status_menu_action = status_menu.addAction(
                        status_code)

                    change_status_menu_action.setObjectName('status_%s' %
                                                            status_code)

                    change_status_menu_actions.append(
                        change_status_menu_action)

                    menu_style_sheet = "%s %s" % (
                        menu_style_sheet,
                        "QMenu#status_%s { background: %s %s %s}" % (
                            status_code,
                            defaults_status_colors[status_code][0],
                            defaults_status_colors[status_code][1],
                            defaults_status_colors[status_code][2],
                        ))

                # change the BG Color of the status
                status_menu.setStyleSheet(menu_style_sheet)

        try:
            # PySide and PySide2
            accepted = QtWidgets.QDialog.DialogCode.Accepted
        except AttributeError:
            # PyQt4
            accepted = QtWidgets.QDialog.Accepted

        selected_action = menu.exec_(global_position)
        if selected_action:
            if selected_action is reload_action:
                if isinstance(entity, Project):
                    self.fill()
                    self.find_and_select_entity_item(item.task)
                else:
                    for item in self.get_selected_task_items():
                        item.reload()

            if create_project_action \
               and selected_action is create_project_action:
                from anima.ui import project_dialog
                project_main_dialog = project_dialog.MainDialog(parent=self,
                                                                project=None)
                project_main_dialog.exec_()
                result = project_main_dialog.result()

                # refresh the task list
                if result == accepted:
                    self.fill()

                project_main_dialog.deleteLater()

            if entity:
                from anima import defaults
                url = 'http://%s/%ss/%s/view' % (
                    defaults.stalker_server_internal_address,
                    entity.entity_type.lower(), entity.id)

                if selected_action is open_in_web_browser_action:
                    import webbrowser
                    webbrowser.open(url)
                elif selected_action is open_in_file_browser_action:
                    from anima import utils
                    try:
                        utils.open_browser_in_location(entity.absolute_path)
                    except IOError as e:
                        QtWidgets.QMessageBox.critical(
                            self, "Error", "%s" % e, QtWidgets.QMessageBox.Ok)
                elif selected_action is copy_url_action:
                    clipboard = QtWidgets.QApplication.clipboard()
                    clipboard.setText(url)

                    # and warn the user about a new version is created and the
                    # clipboard is set to the new version full path
                    QtWidgets.QMessageBox.warning(
                        self, "URL Copied To Clipboard",
                        "URL:<br><br>%s<br><br>is copied to clipboard!" % url,
                        QtWidgets.QMessageBox.Ok)
                elif selected_action is copy_id_to_clipboard:

                    clipboard = QtWidgets.QApplication.clipboard()
                    selected_entity_ids = ', '.join(
                        list(map(str, self.get_selected_task_ids())))
                    clipboard.setText(selected_entity_ids)

                    # and warn the user about a new version is created and the
                    # clipboard is set to the new version full path
                    QtWidgets.QMessageBox.warning(
                        self, "ID Copied To Clipboard",
                        "IDs are copied to clipboard!<br>%s" %
                        selected_entity_ids, QtWidgets.QMessageBox.Ok)

                elif selected_action is create_time_log_action:
                    from anima.ui import time_log_dialog
                    time_log_dialog_main_dialog = time_log_dialog.MainDialog(
                        parent=self,
                        task=entity,
                    )
                    time_log_dialog_main_dialog.exec_()
                    result = time_log_dialog_main_dialog.result()
                    time_log_dialog_main_dialog.deleteLater()

                    if result == accepted:
                        # refresh the task list
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()

                        # reselect the same task
                        self.find_and_select_entity_item(entity)

                elif selected_action is update_task_action:
                    from anima.ui import task_dialog
                    task_main_dialog = task_dialog.MainDialog(
                        parent=self, tasks=self.get_selected_tasks())
                    task_main_dialog.exec_()
                    result = task_main_dialog.result()
                    task_main_dialog.deleteLater()

                    # refresh the task list
                    if result == accepted:
                        # just reload the same item
                        if item.parent:
                            item.parent.reload()
                        else:
                            # reload the entire
                            self.fill()
                        self.find_and_select_entity_item(entity)

                elif selected_action is upload_thumbnail_action:
                    from anima.ui import utils as ui_utils
                    thumbnail_full_path = ui_utils.choose_thumbnail(
                        self,
                        start_path=entity.absolute_path,
                        dialog_title="Choose Thumbnail For: %s" % entity.name)

                    # if the thumbnail_full_path is empty do not do anything
                    if thumbnail_full_path == "":
                        return

                    # get the current task
                    anima.utils.upload_thumbnail(entity, thumbnail_full_path)

                elif selected_action is create_child_task_action:
                    from anima.ui import task_dialog
                    task_main_dialog = task_dialog.MainDialog(
                        parent=self, parent_task=entity)
                    task_main_dialog.exec_()
                    result = task_main_dialog.result()
                    tasks = task_main_dialog.tasks
                    task_main_dialog.deleteLater()

                    if result == accepted and tasks:
                        # reload the parent item
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()
                        self.find_and_select_entity_item(tasks[0])

                elif selected_action is duplicate_task_hierarchy_action:
                    duplicate_task_hierarchy_dialog = \
                        DuplicateTaskHierarchyDialog(
                            parent=self, duplicated_task_name=item.task.name
                        )
                    duplicate_task_hierarchy_dialog.exec_()

                    result = duplicate_task_hierarchy_dialog.result()
                    if result == accepted:
                        new_task_name = duplicate_task_hierarchy_dialog.line_edit.text(
                        )
                        keep_resources = duplicate_task_hierarchy_dialog.check_box.checkState(
                        )

                        from anima import utils
                        from stalker import Task
                        task = Task.query.get(item.task.id)
                        new_task = utils.duplicate_task_hierarchy(
                            task,
                            None,
                            new_task_name,
                            description='Duplicated from Task(%s)' % task.id,
                            user=logged_in_user,
                            keep_resources=keep_resources)
                        if new_task:
                            from stalker.db.session import DBSession
                            DBSession.commit()
                            item.parent.reload()
                            self.find_and_select_entity_item(new_task)

                elif selected_action is delete_task_action:
                    answer = QtWidgets.QMessageBox.question(
                        self, 'Delete Task?',
                        "Delete the task and children?<br><br>(NO UNDO!!!!)",
                        QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
                    if answer == QtWidgets.QMessageBox.Yes:
                        from stalker.db.session import DBSession
                        from stalker import Task

                        tasks = self.get_selected_tasks()
                        logger.debug("tasks   : %s" % tasks)

                        task = Task.query.get(item.task.id)

                        # get the next sibling or the previous
                        # to select after deletion
                        select_task = item.parent.task
                        if task.parent:
                            all_siblings = list(
                                Task.query.filter(
                                    Task.parent == task.parent).order_by(
                                        Task.name).all())
                            if len(all_siblings) > 1:
                                sibling_index = all_siblings.index(task)
                                if sibling_index < len(all_siblings) - 1:
                                    # this is not the last task in the list
                                    # select next one
                                    select_task = all_siblings[sibling_index +
                                                               1]
                                elif sibling_index == len(all_siblings) - 1:
                                    # this is the last task
                                    # select previous task
                                    select_task = all_siblings[sibling_index -
                                                               1]

                        for task in tasks:
                            DBSession.delete(task)
                        DBSession.commit()
                        # reload the parent
                        unique_parent_items = []
                        for item in self.get_selected_task_items():
                            if item.parent and item.parent not in unique_parent_items:
                                unique_parent_items.append(item.parent)

                        if unique_parent_items:
                            for parent_item in unique_parent_items:
                                parent_item.reload()
                        else:
                            self.fill()
                        # either select the next or previous task or the parent
                        self.find_and_select_entity_item(select_task)

                elif selected_action is export_to_json_action:
                    # show a file browser
                    dialog = QtWidgets.QFileDialog(self, "Choose file")
                    dialog.setNameFilter("JSON Files (*.json)")
                    dialog.setFileMode(QtWidgets.QFileDialog.AnyFile)
                    if dialog.exec_():
                        file_path = dialog.selectedFiles()[0]
                        if file_path:
                            import os
                            import json
                            from anima.utils import task_hierarchy_io

                            # check file extension
                            parts = os.path.splitext(file_path)

                            if not parts[1]:
                                file_path = '%s%s' % (parts[0], '.json')

                            data = json.dumps(
                                entity,
                                cls=task_hierarchy_io.StalkerEntityEncoder,
                                check_circular=False,
                                indent=4)
                            try:
                                with open(file_path, 'w') as f:
                                    f.write(data)
                            except Exception as e:
                                pass
                            finally:
                                QtWidgets.QMessageBox.information(
                                    self,
                                    'Task data Export to JSON!',
                                    'Task data Export to JSON!',
                                )

                elif selected_action is import_from_json_action:
                    # show a file browser
                    dialog = QtWidgets.QFileDialog(self, "Choose file")
                    dialog.setNameFilter("JSON Files (*.json)")
                    dialog.setFileMode(QtWidgets.QFileDialog.ExistingFile)
                    if dialog.exec_():
                        file_path = dialog.selectedFiles()[0]
                        if file_path:
                            import json
                            with open(file_path) as f:
                                data = json.load(f)
                            from anima.utils import task_hierarchy_io
                            if isinstance(entity, Task):
                                project = entity.project
                            elif isinstance(entity, Project):
                                project = entity

                            parent = None
                            if isinstance(entity, Task):
                                parent = entity

                            decoder = \
                                task_hierarchy_io.StalkerEntityDecoder(
                                    project=project
                                )
                            loaded_entity = decoder.loads(data, parent=parent)

                            try:
                                from stalker.db.session import DBSession
                                DBSession.add(loaded_entity)
                                DBSession.commit()
                            except Exception as e:
                                QtWidgets.QMessageBox.critical(
                                    self, "Error!", "%s" % e,
                                    QtWidgets.QMessageBox.Ok)
                            else:
                                item.reload()
                                QtWidgets.QMessageBox.information(
                                    self,
                                    'New Tasks are created!',
                                    'New Tasks are created',
                                )

                elif selected_action is create_project_structure_action:
                    answer = QtWidgets.QMessageBox.question(
                        self, 'Create Project Folder Structure?',
                        "This will create project folders, OK?",
                        QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
                    if answer == QtWidgets.QMessageBox.Yes:
                        from anima import utils
                        try:
                            for task in self.get_selected_tasks():
                                utils.create_structure(task)
                        except Exception as e:
                            QtWidgets.QMessageBox.critical(
                                self, "Error", str(e))
                        finally:
                            QtWidgets.QMessageBox.information(
                                self,
                                'Project Folder Structure is created!',
                                'Project Folder Structure is created!',
                            )
                    else:
                        return

                elif selected_action is fix_task_status_action:
                    from stalker.db.session import DBSession
                    from stalker import SimpleEntity, Task
                    from anima import utils
                    for entity in self.get_selected_tasks():
                        if isinstance(entity, Task):
                            utils.fix_task_statuses(entity)
                            utils.fix_task_computed_time(entity)
                            DBSession.add(entity)
                    DBSession.commit()

                    unique_parent_items = []
                    for item in self.get_selected_task_items():
                        if item.parent and item.parent not in unique_parent_items:
                            unique_parent_items.append(item.parent)

                    for parent_item in unique_parent_items:
                        parent_item.reload()

                elif selected_action is update_project_action:
                    from anima.ui import project_dialog
                    project_main_dialog = project_dialog.MainDialog(
                        parent=self, project=entity)
                    project_main_dialog.exec_()
                    result = project_main_dialog.result()

                    # refresh the task list
                    if result == accepted:
                        self.fill()

                        # reselect the same task
                        self.find_and_select_entity_item(entity)

                    project_main_dialog.deleteLater()

                elif selected_action is assign_users_action:
                    from anima.ui import project_users_dialog
                    project_users_main_dialog = \
                        project_users_dialog.MainDialog(
                            parent=self,
                            project=entity
                        )
                    project_users_main_dialog.exec_()
                    result = project_users_main_dialog.result()

                    project_users_main_dialog.deleteLater()

                elif selected_action in change_status_menu_actions:
                    # get the status code
                    status_code = selected_action.text()

                    from sqlalchemy import func
                    status = Status.query.filter(
                        func.lower(Status.code) == func.lower(
                            status_code)).first()

                    # change the status of the entity
                    # if it is a leaf task
                    # if it doesn't have any dependent_of
                    # assert isinstance(entity, Task)
                    for task in self.get_selected_tasks():
                        if task.is_leaf and not task.dependent_of:
                            # then we can update it
                            task.status = status

                            # # fix other task statuses
                            # from anima import utils
                            # utils.fix_task_statuses(entity)

                            # refresh the tree
                            from stalker.db.session import DBSession
                            DBSession.add(task)
                            DBSession.commit()

                            if item.parent:
                                item.parent.reload()
                                self.find_and_select_entity_item(entity)
                else:
                    try:
                        # go to the dependencies
                        dep_task = selected_action.task
                        self.find_and_select_entity_item(dep_task, self)
                    except AttributeError:
                        pass
예제 #35
0
파일: reviewer.py 프로젝트: yazici/anima
def draw_stalker_entity_menu_item(self, context):
    """draws one menu item
    """
    logger.debug('entity_id   : %s' % self.stalker_entity_id)
    logger.debug('entity_name : %s' % self.stalker_entity_name)
예제 #36
0
파일: lib.py 프로젝트: theomission/anima
# -*- coding: utf-8 -*-
# Copyright (c) 2012-2015, Anima Istanbul
#
# This module is part of anima-tools and is released under the BSD 2
# License: http://www.opensource.org/licenses/BSD-2-Clause

from anima import logger
from anima.ui import IS_PYSIDE, IS_PYQT4

if IS_PYQT4():
    logger.debug('importing PyQt4')
    import sip
    sip.setapi('QString', 2)
    sip.setapi('QVariant', 2)
    from PyQt4 import QtGui, QtCore
elif IS_PYSIDE():
    logger.debug('importing PySide')
    from PySide import QtGui, QtCore
예제 #37
0
def get_icon(icon_name):
    """Returns an icon from ui library
    """
    import time
    start_time = time.time()
    # get the icon from cache if possible
    from anima.ui import ICON_CACHE
    q_icon = ICON_CACHE.get(icon_name)
    if not q_icon:
        logger.debug("getting icon from the cache!")
        # use the local icon cache
        import os
        from anima import defaults
        local_icon_cache_path = os.path.normpath(
            os.path.expanduser(
                os.path.join(defaults.local_cache_folder, "icons")))
        local_icon_full_path = os.path.join(local_icon_cache_path,
                                            "%s.png" % icon_name)
        logger.debug("local_icon_full_path: %s" % local_icon_full_path)
        if not os.path.exists(local_icon_full_path):
            logger.debug("local icon cache not found: %s" % icon_name)
            logger.debug("retrieving icon from library!")
            here = os.path.abspath(os.path.dirname(__file__))
            images_path = os.path.join(here, 'images')
            icon_full_path = os.path.join(images_path, "%s.png" % icon_name)
            logger.debug("icon_full_path: %s" % icon_full_path)

            # copy to local cache folder
            try:
                os.makedirs(local_icon_cache_path)
            except OSError:
                pass

            import shutil
            try:
                shutil.copy(icon_full_path, local_icon_full_path)
            except OSError:
                # original icon doesn't exist
                pass
        q_icon = QtGui.QIcon(local_icon_full_path)
        ICON_CACHE[icon_name] = q_icon
    logger.debug("get_icon took: %0.6f s" % (time.time() - start_time))
    return q_icon
예제 #38
0
def load_font(font_filename):
    """loads extra fonts from the fonts folder
    """
    import time
    start_time = time.time()
    # get the font from cache if possible
    from anima.ui import FONT_CACHE
    font_family = FONT_CACHE.get(font_filename)
    if not font_family:
        logger.debug("font not found in runtime cache!")
        logger.debug("getting font from local cache!")
        # use the local font cache
        import os
        from anima import defaults
        local_font_cache_path = os.path.normpath(
            os.path.expanduser(
                os.path.join(defaults.local_cache_folder, "fonts")))
        local_font_full_path = os.path.join(local_font_cache_path,
                                            font_filename)
        logger.debug("local_font_full_path: %s" % local_font_full_path)
        if not os.path.exists(local_font_full_path):
            logger.debug("local font cache not found: %s" % font_filename)
            logger.debug("retrieving font from library!")
            here = os.path.dirname(os.path.realpath(__file__))
            font_full_path = os.path.join(here, 'fonts', font_filename)
            logger.debug("font_full_path: %s" % font_full_path)

            # copy to local cache folder
            try:
                os.makedirs(local_font_cache_path)
            except OSError:
                pass

            import shutil
            try:
                shutil.copy(font_full_path, local_font_full_path)
            except OSError:
                # original font doesn't exist either
                pass

        font_id = QtGui.QFontDatabase.addApplicationFont(local_font_full_path)
        font_family = QtGui.QFontDatabase.applicationFontFamilies(font_id)
        FONT_CACHE[font_filename] = font_family
    else:
        logger.debug("font found in runtime cache!")

    logger.debug("load_font took: %0.6f s" % (time.time() - start_time))
    return font_family
예제 #39
0
파일: archive.py 프로젝트: ktSevindik/anima
    def _move_file_and_fix_references(self,
                                      path,
                                      project_path,
                                      scenes_folder='scenes',
                                      refs_folder='scenes/refs'):
        """Moves the given maya file to the given project path and moves any
        references of it to

        :param str path: The path of the maya file
        :param str project_path: The project path
        :param str scenes_folder: The scenes folder to store the original maya
          scene.
        :param str refs_folder: The references folder to replace reference
          paths with.
        :return list: returns a list of paths
        """
        # fix any env vars
        path = os.path.expandvars(path)

        original_file_name = os.path.basename(path)
        logger.debug('original_file_name: %s' % original_file_name)

        new_file_path = \
            os.path.join(project_path, scenes_folder, original_file_name)

        scenes_folder_lut = {
            '.ma': 'scenes/refs',

            # image files
            '.jpg': 'sourceimages',
            '.png': 'sourceimages',
            '.tif': 'sourceimages',
            '.tga': 'sourceimages',
            '.exr': 'sourceimages',
            '.hdr': 'sourceimages',

            # RSProxy and arnold proxies
            '.rs': 'sourceimages',
            '.ass': 'sourceimages',
        }

        ref_paths = []
        # skip the file if it doesn't exist
        if not os.path.exists(path):
            # return early
            return ref_paths

        # only get new ref paths for '.ma' files
        if path.endswith('.ma'):
            # read the data of the original file
            with open(path) as f:
                data = f.read()

            ref_paths = self._extract_references(data)
            # fix all reference paths
            for ref_path in ref_paths:
                ref_ext = os.path.splitext(ref_path)[-1]
                data = data.replace(
                    ref_path, '%s/%s' % (scenes_folder_lut.get(
                        ref_ext, refs_folder), os.path.basename(ref_path)))

            # now write all the data back to a new temp scene
            with open(new_file_path, 'w+') as f:
                f.write(data)
        else:
            # fix for UDIM texture paths
            # if the path contains 1001 or u1_v1 than find the other
            # textures

            # dirty patch
            # move image files in to the sourceimages folder
            # along with the RedshiftProxy files
            file_extension = os.path.splitext(path)[1]

            new_file_path = \
                os.path.join(
                    project_path,
                    scenes_folder_lut.get(
                        file_extension,
                        refs_folder
                    ),
                    original_file_name
                )

            import glob
            new_file_paths = [new_file_path]
            if '1001' in new_file_path or 'u1_v1' in new_file_path.lower():
                # get the rest of the textures
                new_file_paths = glob.glob(
                    new_file_path.replace('1001', '*').replace(
                        'u1_v1', 'u*_v*').replace('U1_V1', 'U*_V*'))
                for p in new_file_paths:
                    print(p)

            # just copy the file
            for new_file_path in new_file_paths:
                try:
                    shutil.copy(path, new_file_path)
                except IOError:
                    pass

        return ref_paths
예제 #40
0
    def __init__(self, parent=None, task=None, timelog=None):
        logger.debug("initializing the interface")
        # store the logged in user
        self.logged_in_user = None
        self.no_time_left = False
        self.extended_hours = None
        self.extended_minutes = None

        self.timelog = timelog
        self.timelog_created = False
        self.task = task

        super(MainDialog, self).__init__(parent)
        self.setupUi(self)

        # customize the ui elements
        from anima.ui.widgets import TaskComboBox
        self.tasks_comboBox = TaskComboBox(self)
        self.tasks_comboBox.setObjectName("tasks_comboBox")
        self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole,
                                  self.tasks_comboBox)

        # self.start_timeEdit.deleteLater()
        from anima.ui.widgets import TimeEdit
        self.start_timeEdit = TimeEdit(self, resolution=timing_resolution)
        self.start_timeEdit.setCurrentSection(
            QtWidgets.QDateTimeEdit.MinuteSection)
        self.start_timeEdit.setCalendarPopup(True)
        self.start_timeEdit.setObjectName("start_timeEdit")
        self.start_timeEdit.setWrapping(True)
        self.formLayout.insertRow(4, self.label, self.start_timeEdit)
        self.start_timeEdit.setDisplayFormat("HH:mm")

        # self.end_timeEdit.deleteLater()
        self.end_timeEdit = TimeEdit(self, resolution=timing_resolution)
        self.end_timeEdit.setCurrentSection(
            QtWidgets.QDateTimeEdit.MinuteSection)
        self.end_timeEdit.setCalendarPopup(True)
        self.end_timeEdit.setObjectName("end_timeEdit")
        self.end_timeEdit.setWrapping(True)
        self.formLayout.insertRow(5, self.label_2, self.end_timeEdit)
        self.end_timeEdit.setDisplayFormat("HH:mm")

        current_time = QtCore.QTime.currentTime()
        # round the minutes to the resolution
        minute = current_time.minute()
        hour = current_time.hour()
        minute = int(minute / float(timing_resolution)) * timing_resolution

        current_time = QtCore.QTime(hour, minute)

        self.start_timeEdit.setTime(current_time)
        self.end_timeEdit.setTime(current_time.addSecs(timing_resolution * 60))

        self.calendarWidget.resource_id = -1

        # setup signals
        self._setup_signals()

        # setup defaults
        self._set_defaults()

        # center window
        self.center_window()
예제 #41
0
파일: task.py 프로젝트: blam8090/anima
    def show_context_menu(self, position):
        """the custom context menu
        """
        # convert the position to global screen position
        global_position = self.mapToGlobal(position)

        index = self.indexAt(position)
        model = self.model()
        item = model.itemFromIndex(index)
        logger.debug('itemAt(position) : %s' % item)
        task_id = None
        entity = None

        # if not item:
        #     return

        # if item and not hasattr(item, 'task'):
        #     return

        if item and item.task:
            task_id = item.task.id

        # if not task_id:
        #     return

        from anima import utils
        file_browser_name = utils.file_browser_name()

        # create the menu
        menu = QtWidgets.QMenu()  # Open in browser
        # -----------------------------------
        # actions created in different scopes
        create_time_log_action = None
        create_project_action = None
        update_task_action = None
        create_child_task_action = None
        duplicate_task_hierarchy_action = None
        delete_task_action = None
        no_deps_action = None
        create_project_structure_action = None
        create_task_structure_action = None
        update_project_action = None
        open_in_web_browser_action = None
        open_in_file_browser_action = None
        copy_url_action = None
        copy_id_to_clipboard = None

        from anima import defaults
        from stalker import LocalSession
        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user

        from stalker import SimpleEntity, Task, Project
        # TODO: Update this to use only task_id
        if task_id:
            entity = SimpleEntity.query.get(task_id)

        if defaults.is_power_user(logged_in_user):
            # create the Create Project menu item
            create_project_action = menu.addAction(u'\uf0e8 Create Project...')

            if isinstance(entity, Project):
                # this is a project!
                if defaults.is_power_user(logged_in_user):
                    update_project_action = \
                        menu.addAction(u'\uf044 Update Project...')
                    create_project_structure_action = \
                        menu.addAction(u'\uf115 Create Project Structure')
                    create_child_task_action = \
                        menu.addAction(u'\uf0ae Create Child Task...')

        if entity:
            # separate the Project and Task related menu items
            menu.addSeparator()

            open_in_web_browser_action = \
                menu.addAction(u'\uf14c Open In Web Browser...')
            open_in_file_browser_action = \
                menu.addAction(u'\uf07c Open In %s...' % file_browser_name)
            copy_url_action = menu.addAction(u'\uf0c5 Copy URL')
            copy_id_to_clipboard = \
                menu.addAction(u'\uf0c5 Copy ID to clipboard')

            if isinstance(entity, Task):
                # this is a task
                create_task_structure_action = \
                    menu.addAction(u'\uf115 Create Task Structure')

                task = entity
                from stalker import Status
                status_wfd = Status.query.filter(Status.code == 'WFD').first()
                status_prev = \
                    Status.query.filter(Status.code == 'PREV').first()
                status_cmpl = \
                    Status.query.filter(Status.code == 'CMPL').first()
                if logged_in_user in task.resources \
                        and task.status not in [status_wfd, status_prev,
                                                status_cmpl]:
                    menu.addSeparator()
                    create_time_log_action = \
                        menu.addAction(u'\uf073 Create TimeLog...')

                # update task and create child task menu items
                if defaults.is_power_user(logged_in_user):
                    menu.addSeparator()
                    update_task_action = \
                        menu.addAction(u'\uf044 Update Task...')
                    create_child_task_action = \
                        menu.addAction(u'\uf0ae Create Child Task...')
                    duplicate_task_hierarchy_action = \
                        menu.addAction(u'\uf0c5 Duplicate Task Hierarchy...')
                    delete_task_action = \
                        menu.addAction(u'\uf1f8 Delete Task...')

                menu.addSeparator()

                # Add Depends To menu
                depends = task.depends
                if depends:
                    depends_to_menu = menu.addMenu(u'\uf090 Depends To')

                    for dTask in depends:
                        action = depends_to_menu.addAction(dTask.name)
                        action.task = dTask

                # Add Dependent Of Menu
                dependent_of = task.dependent_of
                if dependent_of:
                    dependent_of_menu = menu.addMenu(u'\uf08b Dependent Of')

                    for dTask in dependent_of:
                        action = dependent_of_menu.addAction(dTask.name)
                        action.task = dTask

                if not depends and not dependent_of:
                    no_deps_action = menu.addAction(u'\uf00d No Dependencies')
                    no_deps_action.setEnabled(False)

        try:
            # PySide and PySide2
            accepted = QtWidgets.QDialog.DialogCode.Accepted
        except AttributeError:
            # PyQt4
            accepted = QtWidgets.QDialog.Accepted

        selected_item = menu.exec_(global_position)
        if selected_item:
            if create_project_action \
               and selected_item == create_project_action:
                from anima.ui import project_dialog
                project_main_dialog = project_dialog.MainDialog(parent=self,
                                                                project=None)
                project_main_dialog.exec_()
                result = project_main_dialog.result()

                # refresh the task list
                if result == accepted:
                    self.fill()

                project_main_dialog.deleteLater()

            if entity:
                from anima import defaults
                url = 'http://%s/%ss/%s/view' % (
                    defaults.stalker_server_internal_address,
                    entity.entity_type.lower(), entity.id)

                if selected_item is open_in_web_browser_action:
                    import webbrowser
                    webbrowser.open(url)
                elif selected_item is open_in_file_browser_action:
                    from anima import utils
                    utils.open_browser_in_location(entity.absolute_path)
                elif selected_item is copy_url_action:
                    clipboard = QtWidgets.QApplication.clipboard()
                    clipboard.setText(url)

                    # and warn the user about a new version is created and the
                    # clipboard is set to the new version full path
                    QtWidgets.QMessageBox.warning(
                        self, "URL Copied To Clipboard",
                        "URL:<br><br>%s<br><br>is copied to clipboard!" % url,
                        QtWidgets.QMessageBox.Ok)
                elif selected_item is copy_id_to_clipboard:
                    clipboard = QtWidgets.QApplication.clipboard()
                    clipboard.setText('%s' % entity.id)

                    # and warn the user about a new version is created and the
                    # clipboard is set to the new version full path
                    QtWidgets.QMessageBox.warning(
                        self, "ID Copied To Clipboard",
                        "ID %s is copied to clipboard!" % entity.id,
                        QtWidgets.QMessageBox.Ok)

                elif selected_item is create_time_log_action:
                    from anima.ui import time_log_dialog
                    time_log_dialog_main_dialog = time_log_dialog.MainDialog(
                        parent=self,
                        task=entity,
                    )
                    time_log_dialog_main_dialog.exec_()
                    result = time_log_dialog_main_dialog.result()
                    time_log_dialog_main_dialog.deleteLater()

                    if result == accepted:
                        # refresh the task list
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()

                        # reselect the same task
                        self.find_and_select_entity_item(entity)

                elif selected_item is update_task_action:
                    from anima.ui import task_dialog
                    task_main_dialog = task_dialog.MainDialog(parent=self,
                                                              task=entity)
                    task_main_dialog.exec_()
                    result = task_main_dialog.result()
                    task_main_dialog.deleteLater()

                    # refresh the task list
                    if result == accepted:
                        # just reload the same item
                        if item.parent:
                            item.parent.reload()
                        else:
                            # reload the entire
                            self.fill()
                        self.find_and_select_entity_item(entity)

                elif selected_item == create_child_task_action:
                    from anima.ui import task_dialog
                    task_main_dialog = task_dialog.MainDialog(
                        parent=self, parent_task=entity)
                    task_main_dialog.exec_()
                    result = task_main_dialog.result()
                    task = task_main_dialog.task
                    task_main_dialog.deleteLater()

                    if result == accepted and task:
                        # reload the parent item
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()
                        self.find_and_select_entity_item(task)

                elif selected_item is duplicate_task_hierarchy_action:
                    new_task_name, result = QtWidgets.QInputDialog.getText(
                        self, "Input Dialog", "Duplicated Task Name:",
                        QtWidgets.QLineEdit.Normal, item.task.name)
                    if result:
                        from anima import utils
                        from stalker import Task
                        task = Task.query.get(item.task.id)
                        new_task = utils.duplicate_task_hierarchy(
                            task,
                            None,
                            new_task_name,
                            description='Duplicated from Task(%s)' % task.id,
                            user=logged_in_user)
                        if new_task:
                            from stalker.db.session import DBSession
                            DBSession.commit()
                            item.parent.reload()
                            self.find_and_select_entity_item(new_task)

                elif selected_item is delete_task_action:
                    answer = QtWidgets.QMessageBox.question(
                        self, 'Delete Task?',
                        "Delete the task and children?<br><br>(NO UNDO!!!!)",
                        QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
                    if answer == QtWidgets.QMessageBox.Yes:
                        from stalker.db.session import DBSession
                        from stalker import Task
                        task = Task.query.get(item.task.id)
                        DBSession.delete(task)
                        DBSession.commit()
                        # reload the parent
                        if item.parent:
                            item.parent.reload()
                        else:
                            self.fill()
                        self.find_and_select_entity_item(item.parent.task)

                elif selected_item == create_project_structure_action:
                    answer = QtWidgets.QMessageBox.question(
                        self, 'Create Project Structure?',
                        "This will create project folders, OK?",
                        QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
                    if answer == QtWidgets.QMessageBox.Yes:
                        from anima import utils
                        try:
                            utils.create_project_structure(entity)
                        except Exception as e:
                            pass
                        finally:
                            QtWidgets.QMessageBox.information(
                                self,
                                'Project Structure is created!',
                                'Project Structure is created!',
                            )
                    else:
                        return

                elif selected_item == create_task_structure_action:
                    answer = QtWidgets.QMessageBox.question(
                        self, 'Create Task Structure?',
                        "This will create task folders, OK?",
                        QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
                    if answer == QtWidgets.QMessageBox.Yes:
                        from anima import utils
                        try:
                            utils.create_task_structure(entity)
                        except Exception as e:
                            pass
                        finally:
                            QtWidgets.QMessageBox.information(
                                self,
                                'Task Structure is created!',
                                'Task Structure is created!',
                            )
                    else:
                        return

                elif selected_item == update_project_action:
                    from anima.ui import project_dialog
                    project_main_dialog = project_dialog.MainDialog(
                        parent=self, project=entity)
                    project_main_dialog.exec_()
                    result = project_main_dialog.result()

                    # refresh the task list
                    if result == accepted:
                        self.fill()

                        # reselect the same task
                        self.find_and_select_entity_item(entity)

                    project_main_dialog.deleteLater()

                else:
                    # go to the dependencies
                    dep_task = selected_item.task
                    self.find_and_select_entity_item(dep_task, self)
예제 #42
0
    def generate_gpu(self):
        """generates the GPU representation of the current scene
        """
        # validate the version first
        self.version = self._validate_version(self.version)

        self.open_version(self.version)

        # load necessary plugins
        pm.loadPlugin('gpuCache')
        pm.loadPlugin('AbcExport')
        pm.loadPlugin('AbcImport')

        # check if all references have an GPU repr first
        refs_with_no_gpu_repr = []
        for ref in pm.listReferences():
            if ref.version and not ref.has_repr('GPU'):
                refs_with_no_gpu_repr.append(ref)

        if len(refs_with_no_gpu_repr):
            raise RuntimeError(
                'Please generate the GPU Representation of the references '
                'first!!!\n%s' %
                '\n'.join(map(lambda x: str(x.path), refs_with_no_gpu_repr))
            )

        # unload all references
        for ref in pm.listReferences():
            ref.unload()

        # for local models generate an ABC file
        output_path = os.path.join(
            self.version.absolute_path,
            'Outputs/alembic/'
        ).replace('\\', '/')

        abc_command = \
            'AbcExport -j "-frameRange %(start_frame)s ' \
            '%(end_frame)s ' \
            '-ro -stripNamespaces ' \
            '-uvWrite ' \
            '-wholeFrameGeo ' \
            '-worldSpace ' \
            '-root |%(node)s -file %(file_path)s";'

        gpu_command = \
            'gpuCache -startTime %(start_frame)s ' \
            '-endTime %(end_frame)s ' \
            '-optimize -optimizationThreshold 40000 ' \
            '-writeMaterials ' \
            '-directory "%(path)s" ' \
            '-fileName "%(filename)s" ' \
            '%(node)s;'

        start_frame = end_frame = int(pm.currentTime(q=1))

        if not self.is_scene_assembly_task(self.version.task):

            if self.is_vegetation_task(self.version.task):
                # in vegetation files, we export the GPU files directly from
                # the Base version, also we use the geometry under
                # "pfxPolygons" and parent the resulting Stand-In nodes to the
                # pfxPolygons
                # load all references
                for ref in pm.listReferences():
                    ref.load()

                # find the _pfxPolygons node
                pfx_polygons_node = pm.PyNode('kks___vegetation_pfxPolygons')

                for node in pfx_polygons_node.getChildren():
                    for child_node in node.getChildren():
                        child_node_name = child_node.name().split('___')[-1]
                        child_node_shape = child_node.getShape()
                        child_node_shape_name = None

                        if child_node_shape:
                            child_node_shape_name = child_node_shape.name()

                        pm.select(child_node)
                        temp_output_fullpath = \
                            tempfile.mktemp().replace('\\', '/')
                        temp_output_path, temp_output_filename = \
                            os.path.split(temp_output_fullpath)

                        output_filename = '%s_%s' % (
                            self.version.nice_name,
                            child_node_name.split(':')[-1]
                            .replace(':', '_')
                            .replace('|', '_')
                        )

                        # run the mel command
                        # check if file exists
                        pm.mel.eval(
                            gpu_command % {
                                'start_frame': start_frame,
                                'end_frame': end_frame,
                                'node': child_node.fullPath(),
                                'path': temp_output_path,
                                'filename': temp_output_filename
                            }
                        )

                        cache_file_full_path = \
                            os.path\
                            .join(output_path, output_filename + '.abc')\
                            .replace('\\', '/')

                        # create the intermediate directories
                        try:
                            os.makedirs(
                                os.path.dirname(cache_file_full_path)
                            )
                        except OSError:
                            # directory exists
                            pass

                        # now move in to its place
                        shutil.move(
                            temp_output_fullpath + '.abc',
                            cache_file_full_path
                        )

                        # set rotate and scale pivots
                        rp = pm.xform(child_node, q=1, ws=1, rp=1)
                        sp = pm.xform(child_node, q=1, ws=1, sp=1)
                        #child_node.setRotatePivotTranslation([0, 0, 0])

                        # delete the child and add a GPU node instead
                        pm.delete(child_node)

                        # check if file exists and create nodes
                        if os.path.exists(cache_file_full_path):
                            gpu_node = pm.createNode('gpuCache')
                            gpu_node_tra = gpu_node.getParent()

                            pm.parent(gpu_node_tra, node)
                            gpu_node_tra.rename(child_node_name)

                            if child_node_shape_name is not None:
                                gpu_node.rename(child_node_shape_name)

                            pm.xform(gpu_node_tra, ws=1, rp=rp)
                            pm.xform(gpu_node_tra, ws=1, sp=sp)

                            gpu_node.setAttr(
                                'cacheFileName',
                                cache_file_full_path,
                                type="string"
                            )
                        else:
                            print('File not found!: %s' % cache_file_full_path)

                # clean up other nodes
                pm.delete('kks___vegetation_pfxStrokes')
                pm.delete('kks___vegetation_paintableGeos')

            else:
                root_nodes = self.get_local_root_nodes()
                if len(root_nodes):
                    for root_node in root_nodes:
                        # export each child of each root as separate nodes
                        for child_node in root_node.getChildren():

                            # check if it is a transform node
                            if not isinstance(child_node, pm.nt.Transform):
                                continue

                            if not auxiliary.has_shape(child_node):
                                continue

                            child_name = child_node.name()
                            child_shape = child_node.getShape()
                            child_shape_name = None
                            if child_shape:
                                child_shape_name = child_shape.name()

                            child_full_path = \
                                child_node.fullPath()[1:].replace('|', '_')

                            temp_output_fullpath = \
                                tempfile.mktemp().replace('\\', '/')
                            temp_output_path, temp_output_filename = \
                                os.path.split(temp_output_fullpath)

                            output_filename =\
                                '%s_%s' % (
                                    self.version.nice_name,
                                    child_full_path
                                )

                            # run the mel command
                            # check if file exists
                            pm.mel.eval(
                                gpu_command % {
                                    'start_frame': start_frame,
                                    'end_frame': end_frame,
                                    'node': child_node.fullPath(),
                                    'path': temp_output_path,
                                    'filename': temp_output_filename
                                }
                            )

                            cache_file_full_path = \
                                os.path\
                                .join(
                                    output_path,
                                    '%s.abc' % (
                                        output_filename
                                    )
                                )\
                                .replace('\\', '/')

                            # create the intermediate directories
                            try:
                                os.makedirs(
                                    os.path.dirname(cache_file_full_path)
                                )
                            except OSError:
                                # directory exists
                                pass

                            # now move in to its place
                            shutil.move(
                                temp_output_fullpath + '.abc',
                                cache_file_full_path
                            )

                            # set rotate and scale pivots
                            rp = pm.xform(child_node, q=1, ws=1, rp=1)
                            sp = pm.xform(child_node, q=1, ws=1, sp=1)
                            # rpt = child_node.getRotatePivotTranslation()

                            # delete the child and add a GPU node instead
                            pm.delete(child_node)

                            # check if file exists
                            if os.path.exists(cache_file_full_path):
                                gpu_node = pm.createNode('gpuCache')
                                gpu_node_tra = gpu_node.getParent()

                                pm.parent(gpu_node_tra, root_node)
                                gpu_node_tra.rename(child_name)

                                if child_shape_name is not None:
                                    gpu_node.rename(child_shape_name)

                                pm.xform(gpu_node_tra, ws=1, rp=rp)
                                pm.xform(gpu_node_tra, ws=1, sp=sp)
                                # child_node.setRotatePivotTranslation(rpt)

                                gpu_node.setAttr(
                                    'cacheFileName',
                                    cache_file_full_path,
                                    type="string"
                                )

        # load all references again
        # convert all references to GPU
        logger.debug('converting all references to GPU')
        for ref in pm.listReferences():
            # check if this is a Model reference
            ref.to_repr('GPU')
            ref.load()

        # if this is an Exterior/Interior -> Layout -> Hires task flatten it
        task = self.version.task

        is_exterior_or_interior_task = self.is_exterior_or_interior_task(task)
        if is_exterior_or_interior_task:
            logger.debug('importing all references')
            # and import all of the references
            all_refs = pm.listReferences()
            while len(all_refs) != 0:
                for ref in all_refs:
                    if not ref.isLoaded():
                        ref.load()
                    ref.importContents()
                all_refs = pm.listReferences()

            # assign lambert1 to all GPU nodes
            pm.sets('initialShadingGroup', e=1, fe=auxiliary.get_root_nodes())

            # clean up
            self.clean_up()

        # 6. save the scene as {{original_take}}___GPU
        # use maya
        take_name = '%s%s%s' % (
            self.base_take_name, Representation.repr_separator, 'GPU'
        )
        v = self.get_latest_repr_version(take_name)
        self.maya_env.save_as(v)

        # export the root nodes under the same file
        if is_exterior_or_interior_task:
            logger.debug('exporting root nodes')
            pm.select(auxiliary.get_root_nodes())
            pm.exportSelected(
                v.absolute_full_path,
                type='mayaAscii',
                force=True
            )

        logger.debug('renewing scene')
        # clear scene
        pm.newFile(force=True)
예제 #43
0
# -*- coding: utf-8 -*-

from anima import logger
from anima.ui import IS_PYSIDE, IS_PYSIDE2, IS_PYQT4, IS_QTPY

if IS_PYQT4():
    logger.debug('importing PyQt4')
    import sip
    sip.setapi('QString', 2)
    sip.setapi('QVariant', 2)
    from PyQt4 import QtGui, QtCore
    QtWidgets = QtGui
elif IS_PYSIDE():
    logger.debug('importing PySide')
    from PySide import QtGui, QtCore
    QtWidgets = QtGui
elif IS_PYSIDE2():
    logger.debug('importing PySide2')
    from PySide2 import QtGui, QtCore, QtWidgets
elif IS_QTPY():
    logger.debug('importing Qt.py')
    from Qt import QtGui, QtCore, QtWidgets
예제 #44
0
파일: task.py 프로젝트: ktSevindik/anima
 def __init__(self, *args, **kwargs):
     QtGui.QStandardItemModel.__init__(self, *args, **kwargs)
     logger.debug('TaskTreeModel.__init__() is started')
     self.root = None
     logger.debug('TaskTreeModel.__init__() is finished')
예제 #45
0
    def fetchMore(self):
        logger.debug(
            'TaskItem.fetchMore() is started for item: %s' % self.text()
        )

        if self.canFetchMore():
            from sqlalchemy import alias
            from stalker import Task
            from stalker.db.session import DBSession

            inner_tasks = alias(Task.__table__)
            subquery = DBSession.query(Task.id)\
                .filter(Task.id == inner_tasks.c.parent_id)
            query = DBSession.query(
                Task.id,
                Task.name,
                Task.entity_type,
                Task.status_id,
                subquery.exists().label('has_children')
            )

            if self.task.entity_type != 'Project':
                # query child tasks
                query = query.filter(Task.parent_id == self.task.id)
            else:
                # query only root tasks
                query = query.filter(Task.project_id == self.task.id)\
                    .filter(Task.parent_id==None)

            tasks = query.order_by(Task.name).all()

            # # model = self.model() # This will cause a SEGFAULT
            # # TODO: update it later on

            # start = time.time()
            from anima import defaults
            task_items = []
            for task in tasks:
                task_item = TaskItem(0, 3, entity=task)
                task_item.parent = self

                # color with task status
                task_item.setData(
                    QtGui.QColor(
                        *defaults.status_colors_by_id[task.status_id]
                    ),
                    QtCore.Qt.BackgroundRole
                )

                # use black text
                task_item.setForeground(
                    QtGui.QBrush(QtGui.QColor(0, 0, 0))
                )

                task_items.append(task_item)

            if task_items:
                self.appendRows(task_items)

            self.fetched_all = True

        logger.debug(
            'TaskItem.fetchMore() is finished for item: %s' % self.text()
        )
예제 #46
0
    def set_environment_variables(self, version):
        """sets the environment variables according to the given Version
        instance
        """
        if not version:
            return

        # set the $JOB variable to the parent of version.full_path
        from anima import logger
        logger.debug('version: %s' % version)
        logger.debug('version.path: %s' % version.absolute_path)
        logger.debug('version.filename: %s' % version.filename)
        logger.debug('version.full_path: %s' % version.absolute_full_path)
        logger.debug('version.full_path (calculated): %s' % os.path.join(
            version.absolute_full_path, version.filename).replace("\\", "/"))
        job = str(version.absolute_path)
        hip = job
        hip_name = os.path.splitext(
            os.path.basename(str(version.absolute_full_path)))[0]

        logger.debug('job     : %s' % job)
        logger.debug('hip     : %s' % hip)
        logger.debug('hipName : %s' % hip_name)

        self.set_environment_variable('JOB', job)
        self.set_environment_variable('HIP', hip)
        self.set_environment_variable('HIPNAME', hip_name)
예제 #47
0
파일: models.py 프로젝트: dushyantk/anima
    def fetchMore(self):
        logger.debug(
            'TaskItem.fetchMore() is started for item: %s' % self.text()
        )

        if self.canFetchMore():
            tasks = []

            if self.task_name is None:
                self.task_name, self.task_entity_type = \
                    db.DBSession \
                        .query(SimpleEntity.name, SimpleEntity.entity_type) \
                    .filter(SimpleEntity.id == self.task_id) \
                    .first()

            if self.task_children_data is None:
                if self.task_entity_type in self.task_entity_types:
                    self.task_children_data = db.DBSession \
                        .query(Task.id, Task.name, Task.entity_type, Task.status_id) \
                        .filter(Task.parent_id == self.task_id) \
                        .order_by(Task.name) \
                        .all()

                elif self.task_entity_type == 'Project':
                    self.task_children_data = db.DBSession\
                        .query(Task.id, Task.name, Task.entity_type, Task.status_id) \
                        .filter(Task.parent_id == None) \
                        .filter(Task.project_id == self.task_id) \
                        .order_by(Task.name) \
                        .all()

                tasks = self.task_children_data

            # # model = self.model() # This will cause a SEGFAULT
            # # TODO: update it later on
            # if self.user_tasks_only:
            #     user_tasks_and_parents = []
            #     # need to filter tasks which do not belong to user
            #     for task in tasks:
            #         for user_task in self.user.tasks:
            #             if task in user_task.parents or \
            #                task is user_task or \
            #                task in self.user.projects:
            #                 user_tasks_and_parents.append(task)
            #                 break
            #
            #     tasks = user_tasks_and_parents
            # # tasks = sorted(tasks, key=lambda x: x.name)

            # start = time.time()
            task_items = []
            for task in tasks:
                task_item = TaskItem(0, 3)
                task_item.parent = self
                task_item.task_id = task[0]
                task_item.user_id = self.user_id
                task_item.user_tasks_only = self.user_tasks_only

                # set the font
                # name_item = QtGui.QStandardItem(task.name)
                # entity_type_item = QtGui.QStandardItem(task.entity_type)
                # task_item.setItem(0, 0, name_item)
                # task_item.setItem(0, 1, entity_type_item)
                task_item.setText(task[1])

                # make_bold = False
                # if task_item.canFetchMore():
                #     make_bold = True
                # if task[2] in self.task_entity_types:
                #     children_count = \
                #         db.DBSession.query(Task.id)\
                #             .filter(Task.parent_id == task[0])\
                #             .count()
                #     if children_count:
                #         make_bold = True
                # elif task[2] == 'Project':
                #     make_bold = True

                # if make_bold:
                #     my_font = task_item.font()
                #     my_font.setBold(True)
                #     task_item.setFont(my_font)

                # color with task status
                task_item.setData(
                    QtGui.QColor(
                        *status_colors_by_id[task[3]]
                    ),
                    QtCore.Qt.BackgroundRole
                )

                # use black text
                task_item.setForeground(
                    QtGui.QBrush(QtGui.QColor(0, 0, 0))
                )

                task_items.append(task_item)

            if task_items:
                self.appendRows(task_items)

            self.fetched_all = True

        logger.debug(
            'TaskItem.fetchMore() is finished for item: %s' % self.text()
        )
예제 #48
0
 def close(self):
     logger.debug('closing the ui')
     QtWidgets.QDialog.close(self)
예제 #49
0
        def __init__(self, *args, **kwargs):
            logger.debug("Initializing the Mock Connection!")
            kwargs['client_strategy'] = MOCK_SYNC
            super(MockConnection, self).__init__(*args, **kwargs)

            # load the mock data
            logger.debug("Loading mock connection data")
            logger.debug("test_ldap_server_entries_path: %s" %
                         test_ldap_server_entries_path)
            self.strategy.entries_from_json(test_ldap_server_entries_path)

            # load a fake user for Simple binding
            logger.debug("Loading a fake user for Simple binding")
            self.strategy.add_entry(
                defaults.ldap_base_dn,
                {
                    "cn":
                    "admin",
                    "codePage":
                    0,
                    "displayName":
                    "admin",
                    "distinguishedName":
                    "CN=admin,OU=GPU Users Admin,DC=animagpu,DC=local",
                    "givenName":
                    "admin",
                    "instanceType":
                    4,
                    "memberOf":
                    ["CN=GPU Users Admin,CN=Users,DC=animagpu,DC=local"],
                    "name":
                    "admin",
                    "objectCategory":
                    "CN=Person,CN=Schema,CN=Configuration,DC=animagpu,DC=local",
                    # "objectCategory": "CN=Person,CN=Schema,CN=Configuration,%s" % defaults.ldap_base_dn,
                    "objectClass":
                    ["top", "person", "organizationalPerson", "user"],
                    "objectGUID":
                    "{9d96ef4a-14e7-4a77-b5b1-97b2fa239f9f}",
                    "objectSid":
                    "S-1-5-21-2227021422-3894238547-674366654-1131",
                    "primaryGroupID":
                    513,
                    "revision":
                    0,
                    "sAMAccountName":
                    "admin",
                    "sAMAccountType":
                    805306368,
                    "sn":
                    "admin",
                    "uSNChanged":
                    423892,
                    "uSNCreated":
                    314308,
                    "userAccountControl":
                    66048,
                    "userPassword":
                    "******",
                    "userPrincipalName":
                    "*****@*****.**",
                })
예제 #50
0
    def ffmpeg(self, **kwargs):
        """A simple python wrapper for ``ffmpeg`` command.
        """
        # there is only one special keyword called 'o'

        # this will raise KeyError if there is no 'o' key which is good to
        # prevent the rest to execute
        output = kwargs.get('o')
        try:
            kwargs.pop('o')
        except KeyError:  # no output
            pass

        # generate args
        args = [self.ffmpeg_command_path]
        for key in kwargs:
            flag = '-' + key
            value = kwargs[key]
            if not isinstance(value, list):
                # append the flag
                args.append(flag)
                # append the value
                args.append(str(value))
            else:
                # it is a multi flag
                # so append the flag every time you append the key
                for v in value:
                    args.append(flag)
                    args.append(str(v))

            # overwrite output

        # if output format is not a jpg or png
        if output.split('.')[-1] not in ['jpg', 'jpeg', 'png', 'tga']:
            # use all cpus
            import multiprocessing
            num_of_threads = multiprocessing.cpu_count()
            args.append('-threads')
            args.append('%s' % num_of_threads)

        # overwrite any file
        args.append('-y')

        # append the output
        if output != '' and output is not None:  # for info only
            args.append(output)

        logger.debug('calling ffmpeg with args: %s' % args)

        process = subprocess.Popen(args, stderr=subprocess.PIPE)

        # loop until process finishes and capture stderr output
        stderr_buffer = []
        while True:
            stderr = process.stderr.readline()

            if stderr == '' and process.poll() is not None:
                break

            if stderr != '':
                stderr_buffer.append(stderr)

        # if process.returncode:
        #     # there is an error
        #     raise RuntimeError(stderr_buffer)

        logger.debug(stderr_buffer)
        logger.debug('process completed!')
        return stderr_buffer
예제 #51
0
파일: task.py 프로젝트: ktSevindik/anima
    def fetchMore(self):
        logger.debug('TaskItem.fetchMore() is started for item: %s' %
                     self.text())

        if self.canFetchMore():
            from sqlalchemy.orm import aliased
            from sqlalchemy.dialects.postgresql import array_agg
            from stalker import Task, User
            from stalker.models.task import Task_Resources
            from stalker.db.session import DBSession

            inner_tasks = aliased(Task)
            subquery = DBSession.query(Task.id) \
                .filter(Task.id == inner_tasks.parent_id)

            query = DBSession.query(
                Task.id,
                Task.name,
                Task.entity_type,
                Task.status_id,
                subquery.exists().label('has_children'),
                array_agg(User.name).label('resources')
            ) \
                .outerjoin(Task_Resources, Task.__table__.c.id == Task_Resources.c.task_id) \
                .outerjoin(User, Task_Resources.c.resource_id == User.id) \
                .group_by(
                Task.id,
                Task.name,
                Task.entity_type,
                Task.status_id,
                subquery.exists().label('has_children')
            )

            if self.task.entity_type != 'Project':
                # query child tasks
                query = query.filter(Task.parent_id == self.task.id)
            else:
                # query only root tasks
                query = query.filter(Task.project_id == self.task.id)\
                    .filter(Task.parent_id==None)

            tasks = query.order_by(Task.name).all()

            # # model = self.model() # This will cause a SEGFAULT
            # # TODO: update it later on

            # start = time.time()
            from anima import defaults
            task_items = []
            for task in tasks:
                task_item = TaskItem(0, 4, task=task)
                task_item.parent = self

                # color with task status
                task_item.setData(
                    QtGui.QColor(
                        *defaults.status_colors_by_id[task.status_id]),
                    QtCore.Qt.BackgroundRole)

                # use black text
                task_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0)))

                task_items.append(task_item)

            if task_items:
                # self.appendRows(task_items)
                for task_item in task_items:
                    # TODO: Create a custom QStandardItem for each data type in different columns
                    entity_type_item = QtGui.QStandardItem()
                    entity_type_item.setData(task_item.task.entity_type,
                                             QtCore.Qt.DisplayRole)

                    resources_item = QtGui.QStandardItem()
                    if task_item.task.resources != [None]:
                        resources_item.setData(
                            ', '.join(map(str, task_item.task.resources)),
                            QtCore.Qt.DisplayRole)

                    self.appendRow(
                        [task_item, entity_type_item, resources_item])

            self.fetched_all = True

        logger.debug('TaskItem.fetchMore() is finished for item: %s' %
                     self.text())
예제 #52
0
파일: archive.py 프로젝트: blam8090/anima
    def _move_file_and_fix_references(self, path, project_path,
                                      scenes_folder='scenes',
                                      refs_folder='scenes/refs'):
        """Moves the given maya file to the given project path and moves any
        references of it to

        :param str path: The path of the maya file
        :param str project_path: The project path
        :param str scenes_folder: The scenes folder to store the original maya
          scene.
        :param str refs_folder: The references folder to replace reference
          paths with.
        :return list: returns a list of paths
        """
        # fix any env vars
        path = os.path.expandvars(path)

        original_file_name = os.path.basename(path)
        logger.debug('original_file_name: %s' % original_file_name)

        new_file_path = \
            os.path.join(project_path, scenes_folder, original_file_name)

        ref_paths = []

        # only get new ref paths for '.ma' files
        if path.endswith('.ma'):
            # read the data of the original file
            with open(path) as f:
                data = f.read()

            ref_paths = self._extract_references(data)
            # fix all reference paths
            for ref_path in ref_paths:
                data = data.replace(
                    ref_path,
                    '%s/%s' % (refs_folder, os.path.basename(ref_path))
                )

            # now write all the data back to a new temp scene
            with open(new_file_path, 'w+') as f:
                f.write(data)
        else:
            # fix for UDIM texture paths
            # if the path contains 1001 or u1_v1 than find the other
            # textures
            import glob
            new_file_paths = [new_file_path]
            if '1001' in new_file_path or 'u1_v1' in new_file_path.lower():
                # get the rest of the textures
                new_file_paths = glob.glob(
                    new_file_path
                        .replace('1001', '*')
                        .replace('u1_v1', 'u*_v*')
                        .replace('U1_V1', 'U*_V*')
                )
                for p in new_file_paths:
                    print(p)

            # just copy the file
            for new_file_path in new_file_paths:
                try:
                    shutil.copy(path, new_file_path)
                except IOError:
                    pass

        return ref_paths
예제 #53
0
    def update_content(self, versions):
        """updates the content with the given versions data
        """
        import os
        import datetime

        logger.debug('VersionsTableWidget.update_content() is started')

        self.clear()
        self.versions = versions
        self.setRowCount(len(versions))

        def set_published_font(item):
            """sets the font for the given item

            :param item: the a QTableWidgetItem
            """
            my_font = item.font()
            my_font.setBold(True)

            item.setFont(my_font)

            foreground = item.foreground()
            foreground.setColor(QtGui.QColor(0, 192, 0))
            item.setForeground(foreground)

        # update the previous versions list
        from anima import defaults
        for i, version in enumerate(versions):
            is_published = version.is_published
            absolute_full_path = os.path.normpath(
                os.path.expandvars(version.full_path)).replace('\\', '/')
            version_file_exists = os.path.exists(absolute_full_path)

            c = 0

            # ------------------------------------
            # version_number
            item = QtWidgets.QTableWidgetItem(str(version.version_number))
            # align to center and vertical center
            item.setTextAlignment(0x0004 | 0x0080)

            if is_published:
                set_published_font(item)

            if not version_file_exists:
                item.setBackground(QtGui.QColor(64, 0, 0))

            self.setItem(i, c, item)
            c += 1
            # ------------------------------------

            # ------------------------------------
            # created_with
            item = QtWidgets.QTableWidgetItem()
            if version.created_with:
                from anima.ui import utils as ui_utils
                item.setIcon(ui_utils.get_icon(version.created_with.lower()))

            if is_published:
                set_published_font(item)

            if not version_file_exists:
                item.setBackground(QtGui.QColor(64, 0, 0))

            self.setItem(i, c, item)
            c += 1
            # ------------------------------------

            # ------------------------------------
            # user.name
            created_by = ''
            if version.created_by_id:
                created_by = defaults.user_names_lut[version.created_by_id]
            item = QtWidgets.QTableWidgetItem(created_by)
            # align to left and vertical center
            item.setTextAlignment(0x0001 | 0x0080)

            if is_published:
                set_published_font(item)

            if not version_file_exists:
                item.setBackground(QtGui.QColor(64, 0, 0))

            self.setItem(i, c, item)
            c += 1
            # ------------------------------------

            # ------------------------------------
            # user.name
            updated_by = ''
            if version.updated_by_id:
                updated_by = defaults.user_names_lut[version.updated_by_id]
            item = QtWidgets.QTableWidgetItem(updated_by)
            # align to left and vertical center
            item.setTextAlignment(0x0001 | 0x0080)

            if is_published:
                set_published_font(item)

            if not version_file_exists:
                item.setBackground(QtGui.QColor(64, 0, 0))

            self.setItem(i, c, item)
            c += 1
            # ------------------------------------

            # ------------------------------------
            # file size

            # get the file size
            # file_size_format = "%.2f MB"
            file_size = -1
            if version_file_exists:
                file_size = float(
                    os.path.getsize(absolute_full_path)) / 1048576

            from anima import defaults
            item = QtWidgets.QTableWidgetItem(defaults.file_size_format %
                                              file_size)
            # align to left and vertical center
            item.setTextAlignment(0x0001 | 0x0080)

            if is_published:
                set_published_font(item)

            if not version_file_exists:
                item.setBackground(QtGui.QColor(64, 0, 0))

            self.setItem(i, c, item)
            c += 1
            # ------------------------------------

            # ------------------------------------
            # date

            # get the file date
            file_date = datetime.datetime.today()
            if version_file_exists:
                file_date = datetime.datetime.fromtimestamp(
                    os.path.getmtime(absolute_full_path))
            item = QtWidgets.QTableWidgetItem(
                file_date.strftime(defaults.date_time_format))

            # align to left and vertical center
            item.setTextAlignment(0x0001 | 0x0080)

            if is_published:
                set_published_font(item)

            if not version_file_exists:
                item.setBackground(QtGui.QColor(64, 0, 0))

            self.setItem(i, c, item)
            c += 1
            # ------------------------------------

            # ------------------------------------
            # description
            item = QtWidgets.QTableWidgetItem(version.description)
            # align to left and vertical center
            item.setTextAlignment(0x0001 | 0x0080)

            if is_published:
                set_published_font(item)

            if not version_file_exists:
                item.setBackground(QtGui.QColor(64, 0, 0))

            self.setItem(i, c, item)
            c += 1
            # ------------------------------------

        # resize the first column
        self.resizeRowsToContents()
        self.resizeColumnsToContents()
        self.resizeRowsToContents()
        logger.debug('VersionsTableWidget.update_content() is finished')
예제 #54
0
파일: reviewer.py 프로젝트: yazici/anima
    def add_output(self, full_path, name=None, channel=1):
        """adds the media in the given path to the time line

        :param str full_path: The path of the file
        """
        logger.debug('adding output from: %s' % full_path)
        extension = os.path.splitext(full_path)[-1].lower()

        logger.debug('extension: %s' % extension)

        output_type = None
        for key in output_types.keys():
            if extension in output_types[key]:
                output_type = key
                break

        if output_type == 'image':
            logger.debug('output is image')
            bpy.ops.sequencer.image_strip_add(
                directory=os.path.dirname(full_path),
                files=[{
                    "name": os.path.basename(full_path),
                    # "name": os.path.basename(full_path)
                }],
                relative_path=True,
                frame_start=1,
                frame_end=26,
                channel=channel)
        elif output_type == 'movie':
            logger.debug('output is movie')
            logger.debug('full_path: %s' % full_path)
            bpy.ops.sequencer.movie_strip_add(
                filepath=full_path,
                files=[{
                    "name": os.path.basename(full_path),
                    # "name": os.path.basename(full_path)
                }],
                relative_path=True,
                frame_start=1,
                channel=channel)
        else:
            logger.debug('output_type is unknown: %s' % output_type)
예제 #55
0
파일: base.py 프로젝트: MehmetErer/anima
    def update_version_inputs(self, parent_ref=None):
        """updates the references list of the current version

        :param parent_ref: the parent ref, if given will override the given
          version argument and a Version instance will be get from the given
          parent_ref.path.
        """
        logger.debug('parent_ref: %s' % parent_ref)

        logger.debug('get a version')
        if not parent_ref:
            logger.debug('got no parent_ref')
            version = self.get_current_version()
        else:
            logger.debug('have a parent_ref')
            version = self.get_version_from_full_path(parent_ref.path)

        if version:
            logger.debug('got a version: %s' % version.absolute_full_path)
            # use the original version if it is a Repr version
            from anima.representation import Representation
            if Representation.repr_separator in version.take_name \
               and version.parent:
                version = version.parent
                logger.debug(
                    'this is a representation switching to its parent: %s' %
                    version
                )

            # update the reference list
            referenced_versions = self.get_referenced_versions(parent_ref)
            version.inputs = referenced_versions

            # commit data to the database
            from stalker.db.session import DBSession
            DBSession.add(version)
            DBSession.commit()
예제 #56
0
파일: __init__.py 프로젝트: cgmafia/anima
def SET_PYSIDE2():
    logger.debug('setting environment to PySide2')
    global qt_lib
    qt_lib = PYSIDE2
예제 #57
0
파일: __init__.py 프로젝트: cgmafia/anima
def SET_PYQT4():
    logger.debug('setting environment to PyQt4')
    global qt_lib
    qt_lib = PYQT4
예제 #58
0
파일: __init__.py 프로젝트: cgmafia/anima
def SET_QT():
    logger.debug('setting environment to Qt')
    global qt_lib
    qt_lib = PYQT4
예제 #59
0
    def _set_defaults(self):
        """sets the defaults for the ui
        """
        logger.debug("started setting up interface defaults")

        # Set Default Value for time
        current_time = QtCore.QTime.currentTime()
        # round the minutes to the resolution
        minute = current_time.minute()
        hour = current_time.hour()
        minute = int(minute / float(timing_resolution)) * timing_resolution

        current_time = QtCore.QTime(hour, minute)

        self.start_time_edit.setTime(current_time)
        self.end_time_edit.setTime(current_time.addSecs(timing_resolution * 60))

        self.calendar_widget.resource_id = -1

        # enter revision types
        revision_types = [
            'Yetistiremedim',
            'Ajans',
            'Yonetmen',
            'Ic Revizyon',
        ]

        self.revision_type_combo_box.addItems(revision_types)

        if not self.logged_in_user:
            self.logged_in_user = self.get_logged_in_user()

        # fill the tasks comboBox
        from stalker import Status, Task
        status_wfd = Status.query.filter(Status.code == 'WFD').first()
        status_cmpl = Status.query.filter(Status.code == 'CMPL').first()
        status_prev = Status.query.filter(Status.code == 'PREV').first()

        if not self.timelog:
            # dialog is in create TimeLog mode
            # if a task has been given just feed that task to the comboBox
            if self.task:
                all_tasks = [self.task]
            else:
                # no Task is given nor updating a TimeLog
                # show all the suitable tasks of the logged_in_user
                all_tasks = Task.query \
                    .filter(Task.resources.contains(self.logged_in_user)) \
                    .filter(Task.status != status_wfd) \
                    .filter(Task.status != status_cmpl) \
                    .filter(Task.status != status_prev) \
                    .all()
                # sort the task labels
                all_tasks = sorted(
                    all_tasks,
                    key=lambda task:
                    '%s | %s' % (
                        task.project.name.lower(),
                        ' | '.join(map(lambda x: x.name.lower(), task.parents))
                    )
                )
        else:
            # dialog is working in update TimeLog mode
            all_tasks = [self.timelog.task]

        self.tasks_combo_box.setSizeAdjustPolicy(
            QtWidgets.QComboBox.AdjustToContentsOnFirstShow
        )
        self.tasks_combo_box.setFixedWidth(360)
        self.tasks_combo_box.clear()
        self.tasks_combo_box.addTasks(all_tasks)

        self.tasks_combo_box.setSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.Minimum
        )

        # if a time log is given set the fields from the given time log
        if self.timelog:
            # first update Task
            try:
                self.tasks_combo_box.setCurrentTask(self.timelog.task)
            except IndexError as e:
                return

            # set the resource

            # and disable the tasks_combo_box and resource_combo_box
            self.tasks_combo_box.setEnabled(False)
            self.resource_combo_box.setEnabled(False)

            # set the start and end time
            from anima.utils import utc_to_local
            start_date = utc_to_local(self.timelog.start)
            end_date = utc_to_local(self.timelog.end)

            # set the date
            self.calendar_widget.setSelectedDate(
                QtCore.QDate(start_date.year, start_date.month, start_date.day)
            )

            # first reset the start and end time values
            self.start_time_edit.setTime(QtCore.QTime(0, 0))
            self.end_time_edit.setTime(QtCore.QTime(23, 50))

            # now set the timelog time
            self.start_time_edit.setTime(
                QtCore.QTime(
                    start_date.hour,
                    start_date.minute
                )
            )
            self.end_time_edit.setTime(
                QtCore.QTime(
                    end_date.hour,
                    end_date.minute
                )
            )

        self.fill_calendar_with_time_logs()

        # also trigger an update to the side info bar
        self.calendar_widget_selection_changed()
예제 #60
0
파일: models.py 프로젝트: theomission/anima
    def fetchMore(self):
        logger.debug(
            'TaskItem.fetchMore() is started for item: %s' % self.text()
        )

        if self.canFetchMore():
            tasks = []
            if isinstance(self.task, Task):
                tasks = self.task.children
            elif isinstance(self.task, Project):
                tasks = self.task.root_tasks

            # model = self.model() # This will cause a SEGFAULT
            if self.user_tasks_only:
                user_tasks_and_parents = []
                # need to filter tasks which do not belong to user
                for task in tasks:
                    for user_task in self.user.tasks:
                        if task in user_task.parents or \
                           task is user_task or \
                           task in self.user.projects:
                            user_tasks_and_parents.append(task)
                            break

                tasks = user_tasks_and_parents
            tasks = sorted(tasks, key=lambda x: x.name)

            for task in tasks:
                task_item = TaskItem(0, 3)
                task_item.parent = self
                task_item.task = task
                task_item.user = self.user
                task_item.user_tasks_only = self.user_tasks_only

                # set the font
                # name_item = QtGui.QStandardItem(task.name)
                # entity_type_item = QtGui.QStandardItem(task.entity_type)
                # task_item.setItem(0, 0, name_item)
                # task_item.setItem(0, 1, entity_type_item)
                task_item.setText(task.name)

                make_bold = False
                if isinstance(task, Task):
                    if task.is_container:
                        make_bold = True
                elif isinstance(task, Project):
                    make_bold = True

                if make_bold:
                    my_font = task_item.font()
                    my_font.setBold(True)
                    task_item.setFont(my_font)

                # color with task status
                task_item.setData(
                    QtGui.QColor(
                        *status_colors[task_item.task.status.code.lower()]
                    ),
                    QtCore.Qt.BackgroundRole
                )

                # use black text
                task_item.setForeground(
                    QtGui.QBrush(QtGui.QColor(0, 0, 0))
                )

                self.appendRow(task_item)

            self.fetched_all = True
        logger.debug(
            'TaskItem.fetchMore() is finished for item: %s' % self.text()
        )