Ejemplo n.º 1
0
    def get_logged_in_user(self):
        """returns the logged in user
        """
        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user
        if not logged_in_user:
            from anima.ui import login_dialog
            dialog = login_dialog.MainDialog(parent=self)
            dialog.exec_()
            logger.debug("dialog.DialogCode: %s" % dialog.DialogCode)

            try:
                # PySide
                accepted = QtGui.QDialog.DialogCode.Accepted
            except AttributeError:
                # PyQt4
                accepted = QtGui.QDialog.Accepted

            if dialog.DialogCode == accepted:
                local_session = LocalSession()
                logged_in_user = local_session.logged_in_user
            else:
                # close the ui
                # logged_in_user = self.get_logged_in_user()
                logger.debug("no logged in user")
                self.close()

        return logged_in_user
Ejemplo n.º 2
0
    def get_logged_in_user(self):
        """returns the logged in user
        """
        local_session = LocalSession()
        from stalker.db.session import DBSession
        with DBSession.no_autoflush:
            logged_in_user = local_session.logged_in_user

        if not logged_in_user:
            from anima.ui import login_dialog
            dialog = login_dialog.MainDialog(parent=self)
            # dialog.deleteLater()
            dialog.exec_()
            result = dialog.result()

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

            if result == accepted:
                local_session = LocalSession()
                logged_in_user = local_session.logged_in_user
            else:
                # close the ui
                # logged_in_user = self.get_logged_in_user()
                logger.debug("no logged in user")
                self.close()

        return logged_in_user
Ejemplo n.º 3
0
    def test_delete_will_delete_the_session_cache(self):
        """testing if the LocalSession.delete() will delete the current cache
        file
        """
        # create a new user
        from stalker import db, User
        new_user = User(
            name='Test User',
            login='******',
            email='*****@*****.**',
            password='******'
        )

        # save it to the Database
        db.DBSession.add(new_user)
        db.DBSession.commit()

        self.assertTrue(new_user.id is not None)

        # save it to the local storage
        from stalker import LocalSession
        local_session = LocalSession()
        local_session.store_user(new_user)

        # save the session
        local_session.save()

        # check if the file is created
        # check if a file is created in the users local storage
        import os
        from stalker import defaults
        self.assertTrue(
            os.path.exists(
                os.path.join(
                    defaults.local_storage_path,
                    defaults.local_session_data_file_name
                )
            )
        )

        # now delete the session by calling delete()
        local_session.delete()

        # check if the file is gone
        # check if a file is created in the users local storage
        self.assertFalse(
            os.path.exists(
                os.path.join(
                    defaults.local_storage_path,
                    defaults.local_session_data_file_name
                )
            )
        )

        # delete a second time
        # this should not raise an OSError
        local_session.delete()
Ejemplo n.º 4
0
    def logout(self):
        """log the current user out
        """
        from stalker import LocalSession
        session = LocalSession()
        session.delete()

        self.logged_in_user = None
        # update file menu actions
        # self.logout_action.setVisible(False)
        # self.login_action.setVisible(True)
        self.close()
Ejemplo n.º 5
0
    def logout(self):
        """log the current user out
        """
        from stalker import LocalSession
        session = LocalSession()
        session.delete()

        self.logged_in_user = None
        # update file menu actions
        # self.logout_action.setVisible(False)
        # self.login_action.setVisible(True)
        self.close()
Ejemplo n.º 6
0
    def test_LocalSession_will_not_use_the_stored_data_if_it_is_invalid(self):
        """testing if the LocalSession will not use the stored session if it is
        not valid anymore
        """
        # create a new user
        from stalker import db, User, LocalSession
        new_user = User(
            name='Test User',
            login='******',
            email='*****@*****.**',
            password='******'
        )

        # save it to the Database
        db.DBSession.add(new_user)
        db.DBSession.commit()

        self.assertTrue(new_user.id is not None)

        # save it to the local storage
        local_session = LocalSession()
        local_session.store_user(new_user)

        # save the session
        local_session.save()

        # set the valid time to an early date
        import pytz
        import datetime
        local_session.valid_to = \
            datetime.datetime.now(pytz.utc) - datetime.timedelta(10)

        # pickle the data
        import json
        data = json.dumps(
            {
                'valid_to': local_session.valid_to,
                'logged_in_user_id': -1
            },
            default=local_session.default_json_serializer
        )
        print('data: %s' % data)
        local_session._write_data(data)

        # now get it back with a new local_session
        local_session2 = LocalSession()

        self.assertEqual(
            local_session2.logged_in_user_id, None
        )

        self.assertTrue(local_session2.logged_in_user is None)
Ejemplo n.º 7
0
    def test_save_serializes_the_class_itself(self):
        """testing if the save function serializes the class to the filesystem
        """
        from stalker import LocalSession
        new_local_session = LocalSession()
        new_local_session.save()

        # check if a file is created in the users local storage
        import os
        from stalker import defaults
        assert os.path.exists(
            os.path.join(defaults.local_storage_path,
                         defaults.local_session_data_file_name))
Ejemplo n.º 8
0
    def fix_reference_namespace(cls):
        """fixes reference namespace
        """
        ref_count = len(pm.listReferences(recursive=True))

        if ref_count > 25:
            result = pm.windows.confirmBox(
                'Fix Reference Namespace',
                'You have %s references in your scene,\n'
                'this will take too much time\n\nIs that Ok?' % ref_count
            )
            if not result:
                return

        from stalker import LocalSession
        from anima.env import mayaEnv
        m = mayaEnv.Maya()

        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user

        if not logged_in_user:
            raise RuntimeError('Please login before running the script')

        versions = m.fix_reference_namespaces()
        for version in versions:
            version.created_by = logged_in_user

        from stalker.db.session import DBSession
        DBSession.commit()
Ejemplo n.º 9
0
    def test_logged_in_user_returns_the_stored_User_instance_from_last_time(
            self):
        """testing if logged_in_user returns the logged in user
        """
        # create a new user
        from stalker import User
        new_user = User(name='Test User',
                        login='******',
                        email='*****@*****.**',
                        password='******')

        # save it to the Database
        from stalker.db.session import DBSession
        DBSession.add(new_user)
        DBSession.commit()
        assert new_user.id is not None

        # save it to the local storage
        from stalker import LocalSession
        local_session = LocalSession()
        local_session.store_user(new_user)

        # save the session
        local_session.save()

        # now get it back with a new local_session
        local_session2 = LocalSession()

        assert local_session2.logged_in_user_id == new_user.id
        assert local_session2.logged_in_user == new_user
Ejemplo n.º 10
0
    def __init__(self, version=None):
        local_session = LocalSession()
        self.logged_in_user = local_session.logged_in_user

        if not self.logged_in_user:
            raise RuntimeError('Please login first!')

        from anima.env.mayaEnv import Maya
        self.maya_env = Maya()

        self.base_take_name = None
        self.version = version
Ejemplo n.º 11
0
    def get_logged_in_user(cls):
        """returns the logged in user
        """
        # get logged in user
        from stalker import LocalSession
        from stalker.db.session import DBSession

        local_session = LocalSession()
        with DBSession.no_autoflush:
            logged_in_user = local_session.logged_in_user

        if not logged_in_user:
            raise RuntimeError("Please login first!")

        return logged_in_user
Ejemplo n.º 12
0
def update_audit_info():
    """updates the audit info of the version
    """
    from stalker import LocalSession
    local_session = LocalSession()
    logged_in_user = local_session.logged_in_user
    if logged_in_user:
        # update the version updated_by
        from anima.env import mayaEnv
        m_env = mayaEnv.Maya()
        v = m_env.get_current_version()
        if v:
            v.updated_by = logged_in_user

            from stalker import db
            db.DBSession.commit()
Ejemplo n.º 13
0
def check_smartass_animator():
    """checks if the smartass animator is trying to create a new version for a
    completed animation scene silently
    """
    from stalker.models import walk_hierarchy
    # check the status of this task
    v = staging.get('version')
    t = v.task

    if t.status.code in ['CMPL']:
        # get the dependent tasks
        dependent_tasks = t.dependent_of

        # generate a white list for the resources
        # so anybody in the white list can publish it
        white_list_resources = []
        dependent_tasks_all_hierarchy = []

        for dt in dependent_tasks:
            for task in walk_hierarchy(dt, 'dependent_of'):
                white_list_resources.extend(task.resources)
                white_list_resources.extend(task.responsible)
                dependent_tasks_all_hierarchy.append(task)

        white_list_resources = list(set(white_list_resources))

        # get the logged in user
        from stalker import LocalSession
        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user

        # if any of the dependent task has been started so the status is not
        # WFD or RTS in any of then
        #
        # also check if the logged in user is one of the resources of the
        # dependent tasks
        if any([t.status.code not in ['WFD', 'RTS']
                for t in dependent_tasks_all_hierarchy]) \
           and logged_in_user not in white_list_resources:
            # so the animator is trying to stab behind us
            # simply f**k him/her
            # by not allowing to publish the file
            raise PublishError(
                "You're not allowed to publish for this task:<br><br>"
                "Please <b>Request a REVISION</b>!!!!<br>")
Ejemplo n.º 14
0
    def save_as(self, shot_name, child_task_name='Previs'):
        """saves the file under the given shot name
        """
        # first find the shot
        from stalker import Version, Shot, Task
        shot = Shot.query.filter(Shot.name == shot_name).first()
        if not shot:
            raise RuntimeError('No shot found with shot name: %s' % shot_name)

        # get the child task
        child_task = Task.query\
            .filter(Task.parent == shot)\
            .filter(Task.name == child_task_name)\
            .first()

        logged_in_user = LocalSession().logged_in_user

        v = Version(task=child_task, created_by=logged_in_user)
        self.m_env.save_as(v)
Ejemplo n.º 15
0
def export_camera():
    """exports camera and the related shot node
    """
    from stalker import Task, Version
    from anima.env import mayaEnv

    m = mayaEnv.Maya()

    v = m.get_current_version()

    shot = pm.ls(type='shot')[0]
    try:
        sequencer = pm.ls(shot.message.connections(), type='sequencer')[0]
    except IndexError:
        sequencer = None

    camera = None
    if shot:
        camera = shot.currentCamera.get()

    camera_task = \
        Task.query\
            .filter(Task.parent == v.task.parent)\
            .filter(Task.name == 'Camera').first()

    if camera_task:
        from stalker import LocalSession
        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user

        cam_v = Version(task=camera_task,
                        description='Exported from %s task on Publish' %
                        v.task.name)
        cam_v.update_paths()
        cam_v.extension = '.ma'
        cam_v.is_published = True
        cam_v.created_by = cam_v.updated_by = logged_in_user

        pm.select([shot, camera, sequencer])

        m.export_as(cam_v)
Ejemplo n.º 16
0
    def test_LocalSession_initialized_with_previous_session_data(self):
        """testing if the when creating a new LocalSession instance the class
        is restored from previous time
        """
        # test data
        logged_in_user_id = -10

        # create a local_session
        from stalker import LocalSession
        local_session = LocalSession()

        # store some data
        local_session.logged_in_user_id = logged_in_user_id
        local_session.save()

        # now create a new LocalSession
        local_session2 = LocalSession()

        # now try to get the data back
        assert local_session2.logged_in_user_id == logged_in_user_id
Ejemplo n.º 17
0
    def setUp(self):
        """setup the tests
        """
        # -----------------------------------------------------------------
        # start of the setUp
        # create the environment variable and point it to a temp directory
        db.setup()
        db.init()

        self.temp_repo_path = tempfile.mkdtemp()

        self.user1 = User(name='User 1',
                          login='******',
                          email='*****@*****.**',
                          password='******')
        db.DBSession.add(self.user1)
        db.DBSession.commit()

        # login as self.user1
        from stalker import LocalSession
        local_session = LocalSession()
        local_session.store_user(self.user1)
        local_session.save()

        self.repo1 = Repository(name='Test Project Repository',
                                linux_path=self.temp_repo_path,
                                windows_path=self.temp_repo_path,
                                osx_path=self.temp_repo_path)

        self.status_new = Status.query.filter_by(code='NEW').first()
        self.status_wip = Status.query.filter_by(code='WIP').first()
        self.status_comp = Status.query.filter_by(code='CMPL').first()

        self.task_template = FilenameTemplate(
            name='Task Template',
            target_entity_type='Task',
            path='{{project.code}}/'
            '{%- for parent_task in parent_tasks -%}'
            '{{parent_task.nice_name}}/'
            '{%- endfor -%}',
            filename='{{version.nice_name}}'
            '_v{{"%03d"|format(version.version_number)}}',
        )

        self.asset_template = FilenameTemplate(
            name='Asset Template',
            target_entity_type='Asset',
            path='{{project.code}}/'
            '{%- for parent_task in parent_tasks -%}'
            '{{parent_task.nice_name}}/'
            '{%- endfor -%}',
            filename='{{version.nice_name}}'
            '_v{{"%03d"|format(version.version_number)}}',
        )

        self.shot_template = FilenameTemplate(
            name='Shot Template',
            target_entity_type='Shot',
            path='{{project.code}}/'
            '{%- for parent_task in parent_tasks -%}'
            '{{parent_task.nice_name}}/'
            '{%- endfor -%}',
            filename='{{version.nice_name}}'
            '_v{{"%03d"|format(version.version_number)}}',
        )

        self.sequence_template = FilenameTemplate(
            name='Sequence Template',
            target_entity_type='Sequence',
            path='{{project.code}}/'
            '{%- for parent_task in parent_tasks -%}'
            '{{parent_task.nice_name}}/'
            '{%- endfor -%}',
            filename='{{version.nice_name}}'
            '_v{{"%03d"|format(version.version_number)}}',
        )

        self.structure = Structure(name='Project Struture',
                                   templates=[
                                       self.task_template, self.asset_template,
                                       self.shot_template,
                                       self.sequence_template
                                   ])

        self.project_status_list = StatusList(
            name='Project Statuses',
            target_entity_type='Project',
            statuses=[self.status_new, self.status_wip, self.status_comp])

        self.image_format = ImageFormat(name='HD 1080',
                                        width=1920,
                                        height=1080,
                                        pixel_aspect=1.0)

        # create a test project
        self.project = Project(name='Test Project',
                               code='TP',
                               repository=self.repo1,
                               status_list=self.project_status_list,
                               structure=self.structure,
                               image_format=self.image_format)

        self.task_status_list =\
            StatusList.query.filter_by(target_entity_type='Task').first()
        self.asset_status_list =\
            StatusList.query.filter_by(target_entity_type='Asset').first()
        self.shot_status_list =\
            StatusList.query.filter_by(target_entity_type='Shot').first()
        self.sequence_status_list =\
            StatusList.query.filter_by(target_entity_type='Sequence').first()

        self.character_type = Type(name='Character',
                                   code='CHAR',
                                   target_entity_type='Asset')

        # create a test series of root task
        self.task1 = Task(name='Test Task 1', project=self.project)
        self.task2 = Task(name='Test Task 2', project=self.project)
        self.task3 = Task(name='Test Task 3', project=self.project)

        # then a couple of child tasks
        self.task4 = Task(name='Test Task 4', parent=self.task1)
        self.task5 = Task(name='Test Task 5', parent=self.task1)
        self.task6 = Task(name='Test Task 6', parent=self.task1)

        # create a root asset
        self.asset1 = Asset(name='Asset 1',
                            code='asset1',
                            type=self.character_type,
                            project=self.project)

        # create a child asset
        self.asset2 = Asset(name='Asset 2',
                            code='asset2',
                            type=self.character_type,
                            parent=self.task4)

        # create a root Sequence
        self.sequence1 = Sequence(name='Sequence1',
                                  code='SEQ1',
                                  project=self.project)

        # create a child Sequence
        self.sequence2 = Sequence(name='Sequence2',
                                  code='SEQ2',
                                  parent=self.task2)

        # create a root Shot
        self.shot1 = Shot(name='SH001', code='SH001', project=self.project)

        # create a child Shot (child of a Sequence)
        self.shot2 = Shot(name='SH002', code='SH002', parent=self.sequence1)

        # create a child Shot (child of a child Sequence)
        self.shot3 = Shot(name='SH003', code='SH003', parent=self.sequence2)

        # commit everything
        db.DBSession.add_all([
            self.repo1, self.status_new, self.status_wip, self.status_comp,
            self.project_status_list, self.project, self.task_status_list,
            self.asset_status_list, self.shot_status_list,
            self.sequence_status_list, self.task1, self.task2, self.task3,
            self.task4, self.task5, self.task6, self.asset1, self.asset2,
            self.shot1, self.shot2, self.shot3, self.sequence1, self.sequence2,
            self.task_template, self.asset_template, self.shot_template,
            self.sequence_template
        ])
        db.DBSession.commit()

        # now create versions
        def create_version(task, take_name):
            """Creates a new version
            :param task: the task
            :param take_name: the take_name name
            :return: the version
            """
            # just renew the scene
            #pymel.core.newFile(force=True)

            v = Version(task=task, take_name=take_name)
            v.update_paths()
            db.DBSession.add(v)
            db.DBSession.commit()
            #self.maya_env.save_as(v)
            return v

        # asset2
        self.version1 = create_version(self.asset2, 'Main')
        self.version2 = create_version(self.asset2, 'Main')
        self.version3 = create_version(self.asset2, 'Main')
        self.version3.description = 'Test Description'

        self.version4 = create_version(self.asset2, 'Take1')
        self.version5 = create_version(self.asset2, 'Take1')
        self.version6 = create_version(self.asset2, 'Take1')

        # task5
        self.version7 = create_version(self.task5, 'Main')
        self.version8 = create_version(self.task5, 'Main')
        self.version9 = create_version(self.task5, 'Main')

        self.version10 = create_version(self.task5, 'Take1')
        self.version11 = create_version(self.task5, 'Take1')
        self.version12 = create_version(self.task5, 'Take1')

        # task6
        self.version13 = create_version(self.task6, 'Main')
        self.version14 = create_version(self.task6, 'Main')
        self.version15 = create_version(self.task6, 'Main')

        self.version16 = create_version(self.task6, 'Take1')
        self.version17 = create_version(self.task6, 'Take1')
        self.version18 = create_version(self.task6, 'Take1')

        # shot3
        self.version19 = create_version(self.shot3, 'Main')
        self.version20 = create_version(self.shot3, 'Main')
        self.version21 = create_version(self.shot3, 'Main')

        self.version22 = create_version(self.shot3, 'Take1')
        self.version23 = create_version(self.shot3, 'Take1')
        self.version24 = create_version(self.shot3, 'Take1')

        # task3
        self.version25 = create_version(self.task3, 'Main')
        self.version26 = create_version(self.task3, 'Main')
        self.version27 = create_version(self.task3, 'Main')

        self.version28 = create_version(self.task3, 'Take1')
        self.version29 = create_version(self.task3, 'Take1')
        self.version30 = create_version(self.task3, 'Take1')

        # asset1
        self.version31 = create_version(self.asset1, 'Main')
        self.version32 = create_version(self.asset1, 'Main')
        self.version33 = create_version(self.asset1, 'Main')

        self.version34 = create_version(self.asset1, 'Take1')
        self.version35 = create_version(self.asset1, 'Take1')
        self.version36 = create_version(self.asset1, 'Take1')

        # shot2
        self.version37 = create_version(self.shot2, 'Main')
        self.version38 = create_version(self.shot2, 'Main')
        self.version39 = create_version(self.shot2, 'Main')

        self.version40 = create_version(self.shot2, 'Take1')
        self.version41 = create_version(self.shot2, 'Take1')
        self.version42 = create_version(self.shot2, 'Take1')

        # shot1
        self.version43 = create_version(self.shot1, 'Main')
        self.version44 = create_version(self.shot1, 'Main')
        self.version45 = create_version(self.shot1, 'Main')

        self.version46 = create_version(self.shot1, 'Take1')
        self.version47 = create_version(self.shot1, 'Take1')
        self.version48 = create_version(self.shot1, 'Take1')

        # +- task1
        # |  |
        # |  +- task4
        # |  |  |
        # |  |  +- asset2
        # |  |     +- Main
        # |  |     |  +- version1
        # |  |     |  +- version2 (P)
        # |  |     |  +- version3 (P)
        # |  |     +- Take1
        # |  |        +- version4 (P)
        # |  |        +- version5
        # |  |        +- version6 (P)
        # |  |
        # |  +- task5
        # |  |  +- Main
        # |  |  |  +- version7
        # |  |  |  +- version8
        # |  |  |  +- version9
        # |  |  +- Take1
        # |  |     +- version10
        # |  |     +- version11
        # |  |     +- version12 (P)
        # |  |
        # |  +- task6
        # |     +- Main
        # |     |  +- version13
        # |     |  +- version14
        # |     |  +- version15
        # |     +- Take1
        # |        +- version16 (P)
        # |        +- version17
        # |        +- version18 (P)
        # |
        # +- task2
        # |  |
        # |  +- sequence2
        # |     |
        # |     +- shot3
        # |        +- Main
        # |        |  +- version19
        # |        |  +- version20
        # |        |  +- version21
        # |        +- Take1
        # |           +- version22
        # |           +- version23
        # |           +- version24
        # |
        # +- task3
        # |  +- Main
        # |  |  +- version25
        # |  |  +- version26
        # |  |  +- version27
        # |  +- Take1
        # |     +- version28
        # |     +- version29
        # |     +- version30
        # |
        # +- asset1
        # |  +- Main
        # |  |  +- version31
        # |  |  +- version32
        # |  |  +- version33
        # |  +- Take1
        # |     +- version34
        # |     +- version35
        # |     +- version36
        # |
        # +- sequence1
        # |  |
        # |  +- shot2
        # |     +- Main
        # |     |  +- version37
        # |     |  +- version38
        # |     |  +- version39
        # |     +- Take1
        # |        +- version40
        # |        +- version41
        # |        +- version42
        # |
        # +- shot1
        #    +- Main
        #    |  +- version43
        #    |  +- version44
        #    |  +- version45
        #    +- Take1
        #       +- version46
        #       +- version47
        #       +- version48

        # Start Condition:
        #
        # version15
        #   version12
        #     version5
        #       version2 -> has new published version (version3)
        #     version5 -> Referenced a second time
        #       version2 -> has new published version (version3)
        #   version12 -> Referenced a second time
        #     version5
        #       version2 -> has new published version (version3)
        #     version5
        #       version2 -> has new published version (version3)
        #   version45 -> no change
        #     version48 -> no change
        #
        # Expected Final Result
        # version15A -> Derived from version15
        #   version12A -> Derived from version12
        #     version5A -> Derived from version5
        #       version3 -> has new published version (version3)
        #     version5A -> Derived from version5
        #       version3 -> has new published version (version3)
        #   version12A -> Derived from version12 - The second reference
        #     version5A -> Derived from version5
        #       version3 -> has new published version (version3)
        #     version5A -> Derived from version5
        #       version3 -> has new published version (version3)
        #   version45 -> no change
        #     version48 -> no change

        # create a deep relation
        self.version2.is_published = True
        self.version3.is_published = True

        # new scene
        # version5 references version2
        self.version5.inputs.append(self.version2)
        self.version5.is_published = True

        # version12 references version5
        self.version12.inputs.append(self.version5)
        self.version12.is_published = True

        # version45 references version48
        self.version45.is_published = True
        self.version48.is_published = True
        self.version45.inputs.append(self.version48)

        # version15 references version12 and version48
        self.version15.inputs.append(self.version12)
        self.version15.inputs.append(self.version45)

        # reference_resolution
        self.reference_resolution = {
            'root': [self.version12, self.version45],
            'leave': [self.version48, self.version45],
            'update': [self.version2],
            'create': [self.version5, self.version12]
        }

        # create a buffer for extra created files, which are to be removed
        self.remove_these_files_buffer = []

        self.test_environment = TestEnvironment(name='Test Environment')
        self.test_environment._version = self.version15

        if not QtGui.QApplication.instance():
            logger.debug('creating a new QApplication')
            self.app = QtGui.QApplication(sys.argv)
        else:
            logger.debug('using the present QApplication: %s' % QtGui.qApp)
            # self.app = QtGui.qApp
            self.app = QtGui.QApplication.instance()

        self.dialog = version_updater.MainDialog(
            environment=self.test_environment,
            reference_resolution=self.reference_resolution)
Ejemplo n.º 18
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 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
        upload_thumbnail_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...')

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

                    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 is upload_thumbnail_action:
                    from anima.ui import utils as ui_utils
                    thumbnail_full_path = ui_utils.choose_thumbnail(self)

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

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

                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
Ejemplo n.º 19
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

        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)
Ejemplo n.º 20
0
    def __init__(self):
        from anima.utils import do_db_setup
        from stalker import Type, LocalSession
        from anima.env import mayaEnv

        do_db_setup()
        m = mayaEnv.Maya()

        local_session = LocalSession()
        self.logged_in_user = local_session.logged_in_user
        if not self.logged_in_user:
            raise RuntimeError('Please login to Stalker')

        if not m.get_current_version():
            raise RuntimeError('This scene is not saved with Stalker')

        self.anim_type = Type.query.filter(Type.name == "Animation").first()
        self.prev_type = Type.query.filter(Type.name == "Previs").first()

        # get current task info
        self.current_version = m.get_current_version()
        self.current_task = self.current_version.task
        self.current_type = self.current_task.type

        # check task type
        if self.current_type not in [self.anim_type, self.prev_type]:
            raise RuntimeError(
                'Task must be either an Animation or Previs Task.')

        # query sequenceManager
        if len(pm.ls(type='sequenceManager')) is not 1:
            raise RuntimeError('There must be just 1 sequenceManager.')
        self.sm = pm.ls('sequenceManager1')[0]

        # query sequencer
        seqs = [
            seq for seq in pm.ls(type='sequencer')
            if seq.referenceFile() is None
        ]
        if len(seqs) is not 1:
            raise RuntimeError('There must be just 1 sequencer.')

        self.sequencer = self.sm.sequences.get()[0]

        # query all shots in sequencer
        self.shot_list = self.sequencer.shots.get()

        # query shots in time based descending order
        shots = self.shot_list
        shots_sorted = []
        shots_mid_frames = []
        mid_frames = []
        for shot in shots:
            start = shot.getSequenceStartTime()
            end = shot.getSequenceEndTime()
            mid_frame = int(start + ((end - start) / 2))
            shots_mid_frames.append([shot, mid_frame])
            mid_frames.append(mid_frame)

        mid_frames.sort()
        inc = -1
        for frame in mid_frames:
            inc += 1
            for shot in shots_mid_frames:
                if frame == shot[1]:
                    if shot[0] not in shots_sorted:
                        shots_sorted.append(shot[0])

        self.shots_descending = shots_sorted

        # query all shot tasks from current scene
        shot_task = None
        parent_task = None
        if self.current_type is self.prev_type:
            parent_task = self.current_task.parent
        elif self.current_type is self.anim_type:
            parent_task = self.current_task.parent.parent
        if parent_task is None:
            raise RuntimeError('Current Task does not have Proper Parents.')
        for task in parent_task.walk_hierarchy():
            if task.nice_name == 'Shots':
                shot_task = task
                break
        if shot_task is None:
            raise RuntimeError('Shots Task can not be found.')

        self.scene_shot_tasks = shot_task.tasks
Ejemplo n.º 21
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
Ejemplo n.º 22
0
    def publish_model_as_look_dev(cls):
        """Publishes Model versions as LookDev versions of the same task.

        Also handles references etc.
        """
        #
        # Create LookDev for Current Model Task
        #

        from stalker import Task, Version, Type, LocalSession
        from stalker.db.session import DBSession
        from anima import defaults
        from anima.env import mayaEnv

        do_db_setup()
        m = mayaEnv.Maya()

        local_session = LocalSession()
        logged_in_user = local_session.logged_in_user
        if not logged_in_user:
            raise RuntimeError('Please login to Stalker')

        model_type = Type.query.filter(Type.name=="Model").first()
        look_dev_type = \
            Type.query.filter(Type.name=="Look Development").first()

        current_version = m.get_current_version()
        model_task = current_version.task

        if model_task.type != model_type:
            raise RuntimeError('This is not a Model version')

        if not current_version.is_published:
            raise RuntimeError('Please Publish this maya scene')

        if current_version.take_name != 'Main':
            raise RuntimeError('This is not the Main take')

        # find lookDev
        look_dev = Task.query\
            .filter(Task.parent == model_task.parent)\
            .filter(Task.type == look_dev_type).first()

        if not look_dev:
            raise RuntimeError(
                'There is no LookDev task, please inform your Stalker admin'
            )

        previous_look_dev_version = \
            Version.query\
                .filter(Version.task == look_dev)\
                .filter(Version.take_name == 'Main')\
                .first()

        description = 'Auto Created By %s ' % logged_in_user.name
        take_name = defaults.version_take_name
        if not previous_look_dev_version:
            # do the trick
            pm.newFile(f=1)

            # create a new version
            new_version = Version(
                task=look_dev,
                description=description,
                take_name=take_name,
                created_by=logged_in_user
            )
            new_version.is_published = True

            m.save_as(new_version)

            # reference the model version
            pm.createReference(
                current_version.absolute_full_path,
                gl=True,
                namespace=current_version.nice_name,
                options='v=0'
            )

            pm.saveFile()
            DBSession.add(new_version)

        else:
            latest_look_dev_version = previous_look_dev_version.latest_version
            reference_resolution = m.open(latest_look_dev_version, force=True,
                                          skip_update_check=True)
            m.update_versions(reference_resolution)

            if reference_resolution['update'] \
               or reference_resolution['create']:
                # create a new version
                new_version = Version(
                    task=look_dev,
                    description=description,
                    take_name=take_name,
                    created_by=logged_in_user,
                    parent=latest_look_dev_version
                )
                new_version.is_published = True

                m.save_as(new_version)

        # reopen model scene
        m.open(current_version, force=True, skip_update_check=True)
Ejemplo n.º 23
0
    def setUp(self):
        """setup the tests
        """
        # -----------------------------------------------------------------
        # start of the setUp
        # create the environment variable and point it to a temp directory
        db.setup()
        db.init()

        self.temp_repo_path = tempfile.mkdtemp()

        self.user1 = User(
            name='User 1',
            login='******',
            email='*****@*****.**',
            password='******'
        )
        db.DBSession.add(self.user1)
        db.DBSession.commit()

        # login as self.user1
        from stalker import LocalSession
        local_session = LocalSession()
        local_session.store_user(self.user1)
        local_session.save()

        self.repo1 = Repository(
            name='Test Project Repository',
            linux_path=self.temp_repo_path,
            windows_path=self.temp_repo_path,
            osx_path=self.temp_repo_path
        )

        self.status_new = Status.query.filter_by(code='NEW').first()
        self.status_wip = Status.query.filter_by(code='WIP').first()
        self.status_comp = Status.query.filter_by(code='CMPL').first()

        self.task_template = FilenameTemplate(
            name='Task Template',
            target_entity_type='Task',
            path='{{project.code}}/'
                 '{%- for parent_task in parent_tasks -%}'
                 '{{parent_task.nice_name}}/'
                 '{%- endfor -%}',
            filename='{{version.nice_name}}'
                     '_v{{"%03d"|format(version.version_number)}}',
        )

        self.asset_template = FilenameTemplate(
            name='Asset Template',
            target_entity_type='Asset',
            path='{{project.code}}/'
                 '{%- for parent_task in parent_tasks -%}'
                 '{{parent_task.nice_name}}/'
                 '{%- endfor -%}',
            filename='{{version.nice_name}}'
                     '_v{{"%03d"|format(version.version_number)}}',
        )

        self.shot_template = FilenameTemplate(
            name='Shot Template',
            target_entity_type='Shot',
            path='{{project.code}}/'
                 '{%- for parent_task in parent_tasks -%}'
                 '{{parent_task.nice_name}}/'
                 '{%- endfor -%}',
            filename='{{version.nice_name}}'
                     '_v{{"%03d"|format(version.version_number)}}',
        )

        self.sequence_template = FilenameTemplate(
            name='Sequence Template',
            target_entity_type='Sequence',
            path='{{project.code}}/'
                 '{%- for parent_task in parent_tasks -%}'
                 '{{parent_task.nice_name}}/'
                 '{%- endfor -%}',
            filename='{{version.nice_name}}'
                     '_v{{"%03d"|format(version.version_number)}}',
        )

        self.structure = Structure(
            name='Project Struture',
            templates=[self.task_template, self.asset_template,
                       self.shot_template, self.sequence_template]
        )

        self.project_status_list = StatusList(
            name='Project Statuses',
            target_entity_type='Project',
            statuses=[self.status_new, self.status_wip, self.status_comp]
        )

        self.image_format = ImageFormat(
            name='HD 1080',
            width=1920,
            height=1080,
            pixel_aspect=1.0
        )

        # create a test project
        self.project = Project(
            name='Test Project',
            code='TP',
            repository=self.repo1,
            status_list=self.project_status_list,
            structure=self.structure,
            image_format=self.image_format
        )

        self.task_status_list =\
            StatusList.query.filter_by(target_entity_type='Task').first()
        self.asset_status_list =\
            StatusList.query.filter_by(target_entity_type='Asset').first()
        self.shot_status_list =\
            StatusList.query.filter_by(target_entity_type='Shot').first()
        self.sequence_status_list =\
            StatusList.query.filter_by(target_entity_type='Sequence').first()

        self.character_type = Type(
            name='Character',
            code='CHAR',
            target_entity_type='Asset'
        )

        # create a test series of root task
        self.task1 = Task(
            name='Test Task 1',
            project=self.project
        )
        self.task2 = Task(
            name='Test Task 2',
            project=self.project
        )
        self.task3 = Task(
            name='Test Task 3',
            project=self.project
        )

        # then a couple of child tasks
        self.task4 = Task(
            name='Test Task 4',
            parent=self.task1
        )
        self.task5 = Task(
            name='Test Task 5',
            parent=self.task1
        )
        self.task6 = Task(
            name='Test Task 6',
            parent=self.task1
        )

        # create a root asset
        self.asset1 = Asset(
            name='Asset 1',
            code='asset1',
            type=self.character_type,
            project=self.project
        )

        # create a child asset
        self.asset2 = Asset(
            name='Asset 2',
            code='asset2',
            type=self.character_type,
            parent=self.task4
        )

        # create a root Sequence
        self.sequence1 = Sequence(
            name='Sequence1',
            code='SEQ1',
            project=self.project
        )

        # create a child Sequence
        self.sequence2 = Sequence(
            name='Sequence2',
            code='SEQ2',
            parent=self.task2
        )

        # create a root Shot
        self.shot1 = Shot(
            name='SH001',
            code='SH001',
            project=self.project
        )

        # create a child Shot (child of a Sequence)
        self.shot2 = Shot(
            name='SH002',
            code='SH002',
            parent=self.sequence1
        )

        # create a child Shot (child of a child Sequence)
        self.shot3 = Shot(
            name='SH003',
            code='SH003',
            parent=self.sequence2
        )

        # commit everything
        db.DBSession.add_all([
            self.repo1, self.status_new, self.status_wip, self.status_comp,
            self.project_status_list, self.project, self.task_status_list,
            self.asset_status_list, self.shot_status_list,
            self.sequence_status_list, self.task1, self.task2, self.task3,
            self.task4, self.task5, self.task6, self.asset1, self.asset2,
            self.shot1, self.shot2, self.shot3, self.sequence1, self.sequence2,
            self.task_template, self.asset_template, self.shot_template,
            self.sequence_template
        ])
        db.DBSession.commit()

        # now create versions
        def create_version(task, take_name):
            """Creates a new version
            :param task: the task
            :param take_name: the take_name name
            :return: the version
            """
            # just renew the scene
            #pymel.core.newFile(force=True)

            v = Version(task=task, take_name=take_name)
            v.update_paths()
            db.DBSession.add(v)
            db.DBSession.commit()
            #self.maya_env.save_as(v)
            return v

        # asset2
        self.version1 = create_version(self.asset2, 'Main')
        self.version2 = create_version(self.asset2, 'Main')
        self.version3 = create_version(self.asset2, 'Main')
        self.version3.description = 'Test Description'

        self.version4 = create_version(self.asset2, 'Take1')
        self.version5 = create_version(self.asset2, 'Take1')
        self.version6 = create_version(self.asset2, 'Take1')

        # task5
        self.version7 = create_version(self.task5, 'Main')
        self.version8 = create_version(self.task5, 'Main')
        self.version9 = create_version(self.task5, 'Main')

        self.version10 = create_version(self.task5, 'Take1')
        self.version11 = create_version(self.task5, 'Take1')
        self.version12 = create_version(self.task5, 'Take1')

        # task6
        self.version13 = create_version(self.task6, 'Main')
        self.version14 = create_version(self.task6, 'Main')
        self.version15 = create_version(self.task6, 'Main')

        self.version16 = create_version(self.task6, 'Take1')
        self.version17 = create_version(self.task6, 'Take1')
        self.version18 = create_version(self.task6, 'Take1')

        # shot3
        self.version19 = create_version(self.shot3, 'Main')
        self.version20 = create_version(self.shot3, 'Main')
        self.version21 = create_version(self.shot3, 'Main')

        self.version22 = create_version(self.shot3, 'Take1')
        self.version23 = create_version(self.shot3, 'Take1')
        self.version24 = create_version(self.shot3, 'Take1')

        # task3
        self.version25 = create_version(self.task3, 'Main')
        self.version26 = create_version(self.task3, 'Main')
        self.version27 = create_version(self.task3, 'Main')

        self.version28 = create_version(self.task3, 'Take1')
        self.version29 = create_version(self.task3, 'Take1')
        self.version30 = create_version(self.task3, 'Take1')

        # asset1
        self.version31 = create_version(self.asset1, 'Main')
        self.version32 = create_version(self.asset1, 'Main')
        self.version33 = create_version(self.asset1, 'Main')

        self.version34 = create_version(self.asset1, 'Take1')
        self.version35 = create_version(self.asset1, 'Take1')
        self.version36 = create_version(self.asset1, 'Take1')

        # shot2
        self.version37 = create_version(self.shot2, 'Main')
        self.version38 = create_version(self.shot2, 'Main')
        self.version39 = create_version(self.shot2, 'Main')

        self.version40 = create_version(self.shot2, 'Take1')
        self.version41 = create_version(self.shot2, 'Take1')
        self.version42 = create_version(self.shot2, 'Take1')

        # shot1
        self.version43 = create_version(self.shot1, 'Main')
        self.version44 = create_version(self.shot1, 'Main')
        self.version45 = create_version(self.shot1, 'Main')

        self.version46 = create_version(self.shot1, 'Take1')
        self.version47 = create_version(self.shot1, 'Take1')
        self.version48 = create_version(self.shot1, 'Take1')

        # +- task1
        # |  |
        # |  +- task4
        # |  |  |
        # |  |  +- asset2
        # |  |     +- Main
        # |  |     |  +- version1
        # |  |     |  +- version2 (P)
        # |  |     |  +- version3 (P)
        # |  |     +- Take1
        # |  |        +- version4 (P)
        # |  |        +- version5
        # |  |        +- version6 (P)
        # |  |
        # |  +- task5
        # |  |  +- Main
        # |  |  |  +- version7
        # |  |  |  +- version8
        # |  |  |  +- version9
        # |  |  +- Take1
        # |  |     +- version10
        # |  |     +- version11
        # |  |     +- version12 (P)
        # |  |
        # |  +- task6
        # |     +- Main
        # |     |  +- version13
        # |     |  +- version14
        # |     |  +- version15
        # |     +- Take1
        # |        +- version16 (P)
        # |        +- version17
        # |        +- version18 (P)
        # |
        # +- task2
        # |  |
        # |  +- sequence2
        # |     |
        # |     +- shot3
        # |        +- Main
        # |        |  +- version19
        # |        |  +- version20
        # |        |  +- version21
        # |        +- Take1
        # |           +- version22
        # |           +- version23
        # |           +- version24
        # |
        # +- task3
        # |  +- Main
        # |  |  +- version25
        # |  |  +- version26
        # |  |  +- version27
        # |  +- Take1
        # |     +- version28
        # |     +- version29
        # |     +- version30
        # |
        # +- asset1
        # |  +- Main
        # |  |  +- version31
        # |  |  +- version32
        # |  |  +- version33
        # |  +- Take1
        # |     +- version34
        # |     +- version35
        # |     +- version36
        # |
        # +- sequence1
        # |  |
        # |  +- shot2
        # |     +- Main
        # |     |  +- version37
        # |     |  +- version38
        # |     |  +- version39
        # |     +- Take1
        # |        +- version40
        # |        +- version41
        # |        +- version42
        # |
        # +- shot1
        #    +- Main
        #    |  +- version43
        #    |  +- version44
        #    |  +- version45
        #    +- Take1
        #       +- version46
        #       +- version47
        #       +- version48

        # Start Condition:
        #
        # version15
        #   version12
        #     version5
        #       version2 -> has new published version (version3)
        #     version5 -> Referenced a second time
        #       version2 -> has new published version (version3)
        #   version12 -> Referenced a second time
        #     version5
        #       version2 -> has new published version (version3)
        #     version5
        #       version2 -> has new published version (version3)
        #   version45 -> no change
        #     version48 -> no change
        #
        # Expected Final Result
        # version15A -> Derived from version15
        #   version12A -> Derived from version12
        #     version5A -> Derived from version5
        #       version3 -> has new published version (version3)
        #     version5A -> Derived from version5
        #       version3 -> has new published version (version3)
        #   version12A -> Derived from version12 - The second reference
        #     version5A -> Derived from version5
        #       version3 -> has new published version (version3)
        #     version5A -> Derived from version5
        #       version3 -> has new published version (version3)
        #   version45 -> no change
        #     version48 -> no change

        # create a deep relation
        self.version2.is_published = True
        self.version3.is_published = True

        # new scene
        # version5 references version2
        self.version5.inputs.append(self.version2)
        self.version5.is_published = True

        # version12 references version5
        self.version12.inputs.append(self.version5)
        self.version12.is_published = True

        # version45 references version48
        self.version45.is_published = True
        self.version48.is_published = True
        self.version45.inputs.append(self.version48)

        # version15 references version12 and version48
        self.version15.inputs.append(self.version12)
        self.version15.inputs.append(self.version45)

        # reference_resolution
        self.reference_resolution = {
            'root': [self.version12, self.version45],
            'leave': [self.version48, self.version45],
            'update': [self.version2],
            'create': [self.version5, self.version12]
        }

        # create a buffer for extra created files, which are to be removed
        self.remove_these_files_buffer = []

        self.test_environment = TestEnvironment(name='Test Environment')
        self.test_environment._version = self.version15

        if not QtGui.QApplication.instance():
            logger.debug('creating a new QApplication')
            self.app = QtGui.QApplication(sys.argv)
        else:
            logger.debug('using the present QApplication: %s' % QtGui.qApp)
            # self.app = QtGui.qApp
            self.app = QtGui.QApplication.instance()

        self.dialog = version_updater.MainDialog(
            environment=self.test_environment,
            reference_resolution=self.reference_resolution
        )