def main(notebookName):
    
    #Get your developer token here: https://www.evernote.com/api/DeveloperToken.action and put it here
    dev_token = 'yourEvernoteDevKey'
    
    #Put your Shotgun script details here
    sg = Shotgun('https://yourSite.shotgunstudio.com','evernote-shotgun','yourScriptKey')
    
    #Put the Shotgun HumanUser ID here for the person you want to appear as the Note's author in Shotgun
    sgUserId = 45
    
    sgUser = sg.find_one("HumanUser",[['id', 'is', sgUserId]])

    #Establish a connection to Evernote and store note and user data
    client = EvernoteClient(token=dev_token, sandbox=False)
    userStore = client.get_user_store()
    user = userStore.getUser()

    noteStore = client.get_note_store()

    #Check if the supplied notebook exists, and if it does, send to processNotebook()
    print('\nFinding notebook')
    notebooks = noteStore.listNotebooks()
    notebookNames = [notebook.name for notebook in notebooks]
    if notebookName not in notebookNames:
            print('\nSorry, there are no notebooks in your account named {0}'.format(notebookName))
    else:
        for notebook in notebooks:
            if notebook.name == notebookName:
                print('\nProcessing notebook - BEGIN')
                processNotebook(noteStore, notebook, sg, sgUser)
                print('\nProcessing notebook - DONE\n')
            else:
                continue
Пример #2
0
def addSrc():

    repo = '/mnt/karramba'

    shotFoldList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'src', 'tmp']
    seqFoldList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'shots']
    dataFoldList = ['cache', 'geo', 'render', 'shadowmap', 'sim', 'track', 'photonmap']
    outFoldList = ['dailies', 'hires']    
    
    site = 'https://chimneypot.shotgunstudio.com'    
    scriptName = 'addSrc'
    scriptKey = 'd7dac4e2c55faf486875dfb944ffc9d8e49a0c44'

    sg = Shotgun(site, scriptName, scriptKey)

    
    projList = sg.find('Project', [], ['name'])
    
    for i in projList:
        
        print 'id:' + str(i['id']) + ' ' + i['name']    
        
    prId = int(raw_input('Print project id:'))
    
    proj = sg.find_one('Project', [['id','is',prId]], ['name'])

    
    if not [x for x in os.listdir(repo) if x==proj['name']]:
        print "Project doesn't exist in repository"
        return
    


    s = os.sep
    
    prPath = repo + s + proj['name']
    seqPath = prPath + s + 'film' + s + 'sequences'
    seqList = os.listdir(prPath + s + 'src')
    
    for i in seqList:
        sequenceFold = prPath + s + 'film' + s + 'sequences'
        os.makedirs(sequenceFold + s + i)
        for j in seqFoldList:
            os.makedirs(sequenceFold + s + i + s + j)
        for d in dataFoldList:
            os.makedirs(sequenceFold + s + i + s + 'data' + s + d)
        for o in outFoldList:
            os.makedirs(sequenceFold + s + i + s + 'out' + s + o)
        shList = os.listdir(prPath + s + 'src' + s + i)
        for sh in shList:
            shFold = sequenceFold + s + i + s + 'shots'
            os.makedirs(shFold + s + sh)            
            for f in shotFoldList:
                os.makedirs(shFold + s + sh + s + f)
            for ds in dataFoldList:
                os.makedirs(shFold + s + sh + s + 'data' + s + ds)
            for ot in outFoldList:
                os.makedirs(shFold + s + sh + s + 'out' + s + ot)
            shutil.move(prPath + s + 'src' + s + i + s + sh, shFold + s + sh + s + 'src')
            os.system('ln -sf ' + shFold + s + sh + s + 'src ' + prPath + s + 'src' + s + i + s + sh)
Пример #3
0
def addSrc():

    repo = '/mnt/karramba'

    shotFoldList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'src', 'tmp']
    seqFoldList = ['anim', 'comp', 'data', 'fx', 'light', 'out', 'shots']
    dataFoldList = [
        'cache', 'geo', 'render', 'shadowmap', 'sim', 'track', 'photonmap'
    ]
    outFoldList = ['dailies', 'hires']

    site = 'https://chimneypot.shotgunstudio.com'
    scriptName = 'addSrc'
    scriptKey = 'd7dac4e2c55faf486875dfb944ffc9d8e49a0c44'

    sg = Shotgun(site, scriptName, scriptKey)

    projList = sg.find('Project', [], ['name'])

    for i in projList:

        print 'id:' + str(i['id']) + ' ' + i['name']

    prId = int(raw_input('Print project id:'))

    proj = sg.find_one('Project', [['id', 'is', prId]], ['name'])

    if not [x for x in os.listdir(repo) if x == proj['name']]:
        print "Project doesn't exist in repository"
        return

    s = os.sep

    prPath = repo + s + proj['name']
    seqPath = prPath + s + 'film' + s + 'sequences'
    seqList = os.listdir(prPath + s + 'src')

    for i in seqList:
        sequenceFold = prPath + s + 'film' + s + 'sequences'
        os.makedirs(sequenceFold + s + i)
        for j in seqFoldList:
            os.makedirs(sequenceFold + s + i + s + j)
        for d in dataFoldList:
            os.makedirs(sequenceFold + s + i + s + 'data' + s + d)
        for o in outFoldList:
            os.makedirs(sequenceFold + s + i + s + 'out' + s + o)
        shList = os.listdir(prPath + s + 'src' + s + i)
        for sh in shList:
            shFold = sequenceFold + s + i + s + 'shots'
            os.makedirs(shFold + s + sh)
            for f in shotFoldList:
                os.makedirs(shFold + s + sh + s + f)
            for ds in dataFoldList:
                os.makedirs(shFold + s + sh + s + 'data' + s + ds)
            for ot in outFoldList:
                os.makedirs(shFold + s + sh + s + 'out' + s + ot)
            shutil.move(prPath + s + 'src' + s + i + s + sh,
                        shFold + s + sh + s + 'src')
            os.system('ln -sf ' + shFold + s + sh + s + 'src ' + prPath + s +
                      'src' + s + i + s + sh)
Пример #4
0
    def _moveFilesToPublish(self):
        base_url    = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'playBlastPublisher'
        api_key     = '718daf67bfd2c7e974f24e7cbd55b86bb101c4e5618e6d5468bc4145840e4558'

        sgsrv = Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii=True, connect=True)
        selectedShots = [item.text(0) for item in self.treeWidgetItems if item.checkState(0)]
        if selectedShots:
            for each in selectedShots:
                episode = each.split('sh')[0]
                shotName = '%s_sh%s' % (each.split('sh')[0], each.split('sh')[1].split('Lay')[0])
                self.publishPath = self.publishingPath(episode, shotName)
                for root, dirs, files in os.walk(self.shFldPath):
                    for fl in sorted(files):
                        if fl.endswith('.mov') and fl == '%s.mov' % each:
                            srcPath = os.path.join(root,fl)
                            self.playblastName = fl
                            while os.path.exists(os.path.join(self.publishPath, fl)):
                                allFiles= os.listdir(self.publishPath)
                                publishFiles = []
                                if allFiles:
                                    for allFile in allFiles:
                                        if allFile.endswith('.mov'):
                                            publishFiles.append(allFile)
                                versionNumber = int(sorted(publishFiles)[-1].split('.v')[1].split('.mov')[0])
                                versionNumber += 1
                                if versionNumber < 10:
                                    publishFileName = '%sLayout.v%03d.mov' % (shotName.replace('_', ''), versionNumber)
                                    self.publishPath = os.path.join(self.publishPath, publishFileName)
                                    self.playblastName = os.path.basename(self.publishPath)
                                else:
                                    publishFileName = '%sLayout.v%02d.mov' % (shotName.replace('_', ''), versionNumber)
                                    self.publishPath = os.path.join(self.publishPath, publishFileName)
                                    self.playblastName = os.path.basename(self.publishPath)

                            shutil.copy2(srcPath, self.publishPath)
                            publishMovPath = os.path.join(self.publishingPath(episode, shotName), self.playblastName)
                            getShotTasks =  sgsrv.find_one('Shot',  filters = [["code", "is", shotName]], fields=['id', 'tasks'])

                            for key, values in getShotTasks.iteritems():
                                if key == 'tasks':
                                    for value in values:
                                        if value['name'] == 'Layout':
                                            self.taskId = value['id']
                            if self.publishPath.endswith('review'):
                                self.publishPath = os.path.join(self.publishPath,fl)
                                self.playblastName = fl
                            data = { 'project': {'type':'Project','id': 66},
                                     'code':  self.playblastName,
                                     'description': 'Layout playblast published',
                                     'sg_path_to_movie': publishMovPath,
                                     'sg_status_list': 'rev',
                                     'entity': {'type':'Shot', 'id':getShotTasks['id']},
                                     'sg_task': {'type':'Task', 'id':self.taskId},
                                     'user': {'type':'HumanUser', 'id':92} }
                            result = sgsrv.create('Version', data)
                            result2 = sgsrv.upload("Version", result['id'], publishMovPath, "sg_uploaded_movie")
                print "Done"
Пример #5
0
    def are_credentials_expired(self):
        """
        Checks if the credentials for the user are expired.

        This check is done solely on the Shotgun side. If SSO is being used,
        we do not attempt to contact the IdP to validate the session.

        :returns: True if the credentials are expired, False otherwise.
        """
        print('creation expired')
        logger.debug(
            "Connecting to shotgun to determine if credentials have expired..."
        )
        sg = Shotgun(self.get_host(),
                     session_token=self.get_session_token(),
                     http_proxy=self.get_http_proxy())
        try:
            sg.find_one("HumanUser", [])
            return False
        except ProtocolError as e:
            # One potential source of the error is that our SAML claims have
            # expired. We check if we were given a 302 and the
            # saml_login_request URL.
            # But if we get there, it means our session_token is still valid
            # as far as Shotgun is concerned.
            if (e.errcode == httplib.FOUND and "location" in e.headers
                    and e.headers["location"].endswith(
                        "/saml/saml_login_request")):
                # If we get here, the session_token is still valid.
                logger.debug(
                    "The SAML claims have expired. But the session_token is still valid"
                )
                return False
            else:
                logger.error(
                    "Unexpected exception while validating credentials: %s" %
                    e)
            return True
        except AuthenticationFault:
            return True
def get_app_store_credentials(connection):
    """ Return the validated script for this site to connect to the app store """
    (script, key) = __get_app_store_key(connection)

    # get the proxy string from the connection
    proxy = get_proxy_from_connection(connection)

    # connect to the app store
    try:
        sg_app_store = Shotgun(constants.SGTK_APP_STORE, script, key, http_proxy=proxy)

        # pull down the full script information
        app_store_script = sg_app_store.find_one(
            "ApiUser",
            [["firstname", "is", script]],
            fields=["type", "firstname", "id", "salted_password"])
    except Exception:
        return None

    return app_store_script
Пример #7
0
def get_app_store_credentials(connection, proxy):
    """ Return the validated script for this site to connect to the app store """
    (script, key) = __get_app_store_key(connection)

    # connect to the app store
    try:
        sg_app_store = Shotgun(constants.SGTK_APP_STORE,
                               script,
                               key,
                               http_proxy=proxy,
                               connect=False)

        # pull down the full script information
        app_store_script = sg_app_store.find_one(
            "ApiUser", [["firstname", "is", script]],
            fields=["type", "firstname", "id", "salted_password"])
    except AuthenticationFault:
        raise InvalidAppStoreCredentialsError(
            "The Toolkit App Store credentials found in Shotgun are invalid.")

    return app_store_script
def main(notebookName):

    #Get your developer token here: https://www.evernote.com/api/DeveloperToken.action and put it here
    dev_token = 'yourEvernoteDevKey'

    #Put your Shotgun script details here
    sg = Shotgun('https://yourSite.shotgunstudio.com', 'evernote-shotgun',
                 'yourScriptKey')

    #Put the Shotgun HumanUser ID here for the person you want to appear as the Note's author in Shotgun
    sgUserId = 45

    sgUser = sg.find_one("HumanUser", [['id', 'is', sgUserId]])

    #Establish a connection to Evernote and store note and user data
    client = EvernoteClient(token=dev_token, sandbox=False)
    userStore = client.get_user_store()
    user = userStore.getUser()

    noteStore = client.get_note_store()

    #Check if the supplied notebook exists, and if it does, send to processNotebook()
    print('\nFinding notebook')
    notebooks = noteStore.listNotebooks()
    notebookNames = [notebook.name for notebook in notebooks]
    if notebookName not in notebookNames:
        print('\nSorry, there are no notebooks in your account named {0}'.
              format(notebookName))
    else:
        for notebook in notebooks:
            if notebook.name == notebookName:
                print('\nProcessing notebook - BEGIN')
                processNotebook(noteStore, notebook, sg, sgUser)
                print('\nProcessing notebook - DONE\n')
            else:
                continue
    def _moveFilesToPublish(self):
        base_url = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'playBlastPublisher'
        api_key = '718daf67bfd2c7e974f24e7cbd55b86bb101c4e5618e6d5468bc4145840e4558'

        sgsrv = Shotgun(base_url=base_url,
                        script_name=script_name,
                        api_key=api_key,
                        ensure_ascii=True,
                        connect=True)
        selectedShots = [
            item.text(0) for item in self.treeWidgetItems if item.checkState(0)
        ]
        if selectedShots:
            for each in selectedShots:
                episode = each.split('sh')[0]
                shotName = '%s_sh%s' % (each.split('sh')[0],
                                        each.split('sh')[1].split('Lay')[0])
                self.publishPath = self.publishingPath(episode, shotName)
                for root, dirs, files in os.walk(self.shFldPath):
                    for fl in sorted(files):
                        ext = os.path.splitext(fl)[-1]
                        if (fl.endswith('.mov') and
                            (fl
                             == '%s.mov' % each)) or (fl.endswith('.MOV') and
                                                      (fl == "%s.MOV" % each)):
                            srcPath = os.path.join(root, fl)
                            #                             print srcPath, ext
                            self.playblastName = fl
                            while os.path.exists(
                                    os.path.join(self.publishPath, fl)):
                                allFiles = os.listdir(self.publishPath)
                                publishFiles = []
                                if allFiles:
                                    for allFile in allFiles:
                                        if allFile.endswith(ext):
                                            print allFile
                                            publishFiles.append(allFile)
                                versionNumber = int(
                                    sorted(publishFiles)[-1].split('.v')
                                    [1].split(ext)[0])
                                versionNumber += 1
                                if versionNumber < 10:
                                    publishFileName = '%sLayout.v%03d%s' % (
                                        shotName.replace(
                                            '_', ''), versionNumber, ext)
                                    self.publishPath = os.path.join(
                                        self.publishPath, publishFileName)
                                    self.playblastName = os.path.basename(
                                        self.publishPath)
                                else:
                                    publishFileName = '%sLayout.v%02d%s' % (
                                        shotName.replace(
                                            '_', ''), versionNumber, ext)
                                    self.publishPath = os.path.join(
                                        self.publishPath, publishFileName)
                                    self.playblastName = os.path.basename(
                                        self.publishPath)

                            shutil.copy2(srcPath, self.publishPath)

                            publishMovPath = os.path.join(
                                self.publishingPath(episode, shotName),
                                self.playblastName)

                            getShotTasks = sgsrv.find_one(
                                'Shot',
                                filters=[["code", "is", shotName]],
                                fields=['id', 'tasks'])

                            for key, values in getShotTasks.iteritems():
                                if key == 'tasks':
                                    for value in values:
                                        if value['name'] == 'Layout':
                                            self.taskId = value['id']
                            if self.publishPath.endswith('review'):
                                self.publishPath = os.path.join(
                                    self.publishPath, fl)
                                self.playblastName = fl
                            data = {
                                'project': {
                                    'type': 'Project',
                                    'id': 66
                                },
                                'code': self.playblastName,
                                'description': 'Layout playblast published',
                                'sg_path_to_movie': publishMovPath,
                                'sg_status_list': 'rev',
                                'entity': {
                                    'type': 'Shot',
                                    'id': getShotTasks['id']
                                },
                                'sg_task': {
                                    'type': 'Task',
                                    'id': self.taskId
                                },
                                'user': {
                                    'type': 'HumanUser',
                                    'id': 92
                                }
                            }
                            result = sgsrv.create('Version', data)
                            result2 = sgsrv.upload("Version", result['id'],
                                                   publishMovPath,
                                                   "sg_uploaded_movie")
                print "Done"
Пример #10
0
class studioShotgun(object):
    def __init__(self, path, name, key, project):
        self.SERVER_PATH = path
        self.SCRIPT_NAME = name     
        self.SCRIPT_KEY = key
        self.project_id = project
        self.sg = Shotgun(self.SERVER_PATH, self.SCRIPT_NAME, self.SCRIPT_KEY)

    #----------------------------------------------------------------------
    ## set Project id by ID
    def setProjectId(self, newId):
        self.project_id = newId

    #----------------------------------------------------------------------
    ## set Project id by ID
    def setProjectName(self, name):
        newId = 0
        projects = self.sg.find('Project', [], ['name'])
        for project in projects:
            if project['name'] == name:
                newId = project['id']

        self.project_id = newId

    #----------------------------------------------------------------------
    ## find asset by name
    def findAssetByName(self, name):
        fields = ['id', 'code', 'sg_asset_type', 'tasks']
        filters = [['project', 'is', {'type': 'Project', 'id': self.project_id}], ['code', 'is', name]]
        
        result = self.sg.find('Asset', filters, fields)
    
        return result
    
    #----------------------------------------------------------------------
    ## find shot by name
    def findShotByName(self, episode, shot):
        fields = ['id', 'code', 'sg_asset_type', 'tasks', 'sg_sequence']
        filters = [['project', 'is', {'type': 'Project', 'id': self.project_id}], ['code', 'is', shot]]
        
        result = self.sg.find('Shot', filters, fields)
    
        for x in result:
            name = x['sg_sequence']['name'].split('_')[0]
            if name == episode:
                return x
    
        return []

    #----------------------------------------------------------------------
    ## upload thumbnail to asset
    def uploadThumbnail(self, asset, thumbnail):
        upload = 0
        asset = self.findAssetByName(asset)
        if asset:
            upload = self.sg.upload_thumbnail("Asset", asset[0]['id'], thumbnail)
    
        return upload

    #----------------------------------------------------------------------
    ## create new asset
    def createAsset(self, asset, assetType, template, assetFile='', description=''):
        ## find asset
        asset = self.findAssetByName(asset)
        
        if not asset:
            ## create asset + task template
            filters = [['code', 'is', template]]
            template = self.sg.find_one('TaskTemplate', filters)
            
            data = {'project': {'type': 'Project', 'id': self.project_id}, 
                    'code': asset,
                    'description': description, 
                    'sg_asset_type': assetType, 
                    'sg_url_perforce': assetFile, 
                    'task_template': template}
    
            asset = self.sg.create('Asset', data)
    
        return asset

    #----------------------------------------------------------------------
    ## update file path in asset
    def updateAssetFilePath(self, asset, filename):
        asset = self.findAssetByName(asset)
    
        data = {'sg_url_perforce': filename}
        asset = self.sg.update("Asset", asset[0]['id'], data)
    
        return asset

    #----------------------------------------------------------------------
    ## create new version
    def createVersion(self, shotId, taskId, userId, filename, comment=''):
        curTime = datetime.now().strftime('%Y.%m.%d_%H.%M')
        fname = str(filename.split('/')[-1].split('.')[0]) + '_' + curTime
    
        data = {'project': {'type': 'Project', 'id': self.project_id},
                'code': fname,
                'description': comment,
                'sg_status_list': 'rev',
                'entity': {'type': 'Shot', 'id': shotId},
                'sg_task': {'type': 'Task', 'id': taskId},
                'user': {'type': 'HumanUser', 'id': userId}}
        
        result = self.sg.create('Version', data)
        
        upload = self.sg.upload('Version', result['id'], filename, 'sg_uploaded_movie')
    
        return [result, upload]

    #----------------------------------------------------------------------
    ## get user data from shotgum
    def getUserData(self, user):
        filters = [['login', 'is', user]]
        user = self.sg.find('HumanUser', filters)

        if user:
            return user[0]
        else:
            return []

    #----------------------------------------------------------------------
    ## get all user from project
    def getAllUsers(self):
        fields = ['id', 'login', 'name', 'projects', 'department']
        filters = [['projects', 'is', {'type': 'Project', 'id': self.project_id}]]
        users = self.sg.find('HumanUser', filters, fields)
    
        return users
__author__ = 'andrew.willis'

from shotgun_api3 import Shotgun

sg = Shotgun("http://andrewwillish.shotgunstudio.com", "scriptTest", "8b7db88321b7c296541580d1659872d2e63527c040b37b4a2ca0eb47f9da04cb")
proj = sg.find_one("Project",[['name','is','KIKO']])
print sg.create("shot",{'code':'SEQ01','project':proj})
#sg.update('Shot',shot['id'],{"sg_status_list":"ip"})
#sg.delete("Shot", 1160)
Пример #12
0
    class genericUtils:
        def __init__(self):
            self.sg = Shotgun('https://' + URL, name, API)

        def getFields(self, entity):
            '''get the fields for a type/entity as a list so we can pass it as an arg easily
            this is used all the time to make sure we get all the fields that we may ever need for a type/entity
            '''
            allFields = []
            fields = self.sg.schema_field_read(entity)
            for field in fields:
                allFields.append(field)
            return allFields

        def project(self, project):
            '''Gets the Shotgun project name and ID
            '''
            retFields = self.getFields('Project')
            project = project.replace('_', ' ')
            return self.sg.find_one("Project", [["name", "is", project]],
                                    retFields)

        def sequence(self, project, sequence):
            '''Returns the shotgun sequence name and ID 
            Parameters : (project, sequence)
            '''
            retFields = self.getFields('Sequence')
            return self.sg.find_one(
                "Sequence",
                [["code", "is", sequence], ['project', 'is', project]],
                retFields)

        def shot(self, project, shot):
            '''Returns the shotgun shot name and ID 
            Parameters : (project, shot)
            '''
            retFields = self.getFields('Shot')
            return self.sg.find_one(
                'Shot', [['code', 'is', shot], ['project', 'is', project]],
                retFields)

        def createProject(self, project):
            '''Creates a project in Shotgun given a project name
            Parameters : (project)
            '''
            filters = [['code', 'is', 'a']]
            template = self.sg.find_one('Project', [['name', 'is', 'a']],
                                        ['layout_project', 'id'])
            data = {'name': project, 'layout_project': template}
            return self.sg.create('Project', data)

        def createSequence(self, project, sequence):
            '''Creates a sequence in shotgun given 
            Parameters : (project, sequence)
            '''
            data = {
                'project': {
                    "type": "Project",
                    "id": project['id']
                },
                'code': sequence
            }
            return self.sg.create('Sequence', data)

        def createShot(self, project, shot, seq='', taskTemplateName=''):
            '''Creates a sequence in shotgun given 
            Parameters : (project, shot, seq='', taskTemplateName='Basic shot template'
            '''
            filters = [['code', 'is', taskTemplateName]]
            template = self.sg.find_one('TaskTemplate', filters)

            data = {
                'project': {
                    "type": "Project",
                    "id": project['id']
                },
                'code': shot,
                'task_template': template,
                'description': '',
                'self.sg_sequence': seq,
                'self.sg_status_list': 'wtg'
            }
            result = self.sg.create('Shot', data)
            return result

        def notesFind(self, shotID):
            '''Find all notes on a shot 
            Parameters : (shotID)
            Output : Note data :
            ['tasks', 'attachments', 'updated_at', 'replies', 'id', 'subject', 'playlist', '
            addressings_to', 'created_by', 'content', 'sg_status_list', 'reply_content', 
            'updated_by', 'addressings_cc', 'read_by_current_user', 'user', 'note_links', 
            'created_at', 'sg_note_from', 'project', 'sg_note_type', 'tag_list']        
            '''
            note = self.sg.find('Note', [['note_links', 'is', shotID]],
                                ['subject', 'content', 'created_at'],
                                [{
                                    'field_name': 'created_at',
                                    'direction': 'desc'
                                }])
            return note

        def notesFindLatest(self, shotID):
            '''Find the latest note on a shot
            Parameters : (shotID)
            Call with notesFindLatest(shot)['content'] for the note content only
            Output : Note data:
            ['tasks', 'attachments', 'updated_at', 'replies', 'id', 'subject', 'playlist', '
            addressings_to', 'created_by', 'content', 'sg_status_list', 'reply_content', 
            'updated_by', 'addressings_cc', 'read_by_current_user', 'user', 'note_links', 
            'created_at', 'sg_note_from', 'project', 'sg_note_type', 'tag_list']        
            '''
            note = self.notesFind(shotID)[0]
            return note

        def notesCreate(self, project, shotID, subject, content):
            '''Create a note for a shot given
            Parameters : (project, shotID, subject, content)
            Output : noteID
            '''
            # enter data here for a note to create
            data = {
                'subject': subject,
                'content': content,
                'note_links': [shotID],
                'project': project
            }
            # create the note
            noteID = self.sg.create('Note', data)
            return noteID

        def versionCreate(self,
                          project,
                          shot,
                          verName,
                          description,
                          framePath,
                          firstFrame,
                          lastFrame,
                          clientName=None,
                          sourceFile=None,
                          task=None,
                          user=None,
                          final=False,
                          makeThumb=False,
                          makeThumbShot=False):
            '''Create a version
            Parameters : (project, shotID, verName, description, framePath, firstFrame, lastFrame, clientName=None, sourceFile=None, task=None)
            Output : versionID
            '''

            data = {
                'project': project,
                'code': verName,
                'description': description,
                'sg_path_to_frames': framePath,
                #'sg_frame_range': str(firstFrame) + '-' + str(lastFrame),
                'sg_first_frame': int(firstFrame),
                'sg_last_frame': int(lastFrame),
                'sg_status_list': 'rev',
                'entity': shot
            }
            #if user != None:
            #data['user']
            if task != None:
                filters = [['content', 'is', task], ['entity', 'is', shot]]
                taskID = self.sg.find_one('Task', filters)
                data['sg_task'] = taskID
            #if final == True and 'send
            # in case we're putting a client version in here we need this code.
            # we are expecting a field called self.sg_client_name in the version table.
            # please make sure you create this in the shotgun setup
            # read the schema and if the client_name is not found, create it.
            '''
            versionFields = self.sg.schema_field_read('Version')
            if 'sg_client_name' not in versionFields and clientName != None:
                newField = self.sg.schema_field_create('Version','text','Client Name')
            if clientName != None :
                data['sg_client_name'] =  clientName
        
            #'user': {'type':'HumanUser', 'id':165} }
            # here we need to create a field for storing the source file that created this version.
            # if it's not there, create the field, and if it's there just update it.
            
            if 'sg_source_file' not in versionFields and sourceFile != None:
                newField = self.sg.schema_field_create('Version','text','Source File')
            if sourceFile != None:
                data['sg_source_file'] = sourceFile
            '''

            versionData = self.sg.create('Version', data)
            # handle the thumbnail grabbing here
            middleFrame = (int(firstFrame) + int(lastFrame)) / 2
            padding, padString = fxpipe.framePad(framePath)
            paddedFrame = padString % (middleFrame)
            if makeThumb == True:
                thumbData = self.sg.upload_thumbnail(
                    'Version', versionData['id'],
                    framePath.replace(padding, paddedFrame))
            if makeThumbShot == True:
                thumbData = self.sg.upload_thumbnail(
                    'Shot', shot['id'],
                    framePath.replace(padding, paddedFrame))
            return versionData

        #add a task version to the system
        def versionCreateTask(self,
                              project,
                              shot,
                              verName,
                              description,
                              framePath,
                              firstFrame,
                              lastFrame,
                              task,
                              sourceFile=''):
            '''
            DEPRECATED : USE versionCreate instead with the task='TASKNAME'
            Parameters : (project, shot, verName, description, framePath, firstFrame, lastFrame, task, sourceFile = '')
            Output : Version ID
            '''
            filters = [['content', 'is', task], ['entity', 'is', shot]]
            taskID = self.sg.find_one('Task', filters)
            data = {
                'project': project,
                'code': verName,
                'description': description,
                'self.sg_path_to_frames': framePath,
                'frame_range': str(firstFrame) + '-' + str(lastFrame),
                'self.sg_first_frame': firstFrame,
                'self.sg_last_frame': lastFrame,
                #'self.sg_uploaded_movie': '/Users/throb/Downloads/test.m4v',
                #'self.sg_first_frame': 1,
                #'self.sg_last_frame': 100,
                'self.sg_status_list': 'rev',
                'self.sg_task': taskID,
                'entity': shot
            }
            # here we need to create a field for storing the source file that created this version.
            # if it's not there, create the field, and if it's there just update it.
            try:
                tmp2 = {}
                tmp2 = tmp['self.sg_source_file']
            except:
                newField = self.sg.schema_field_create('Version', 'text',
                                                       'Source File')
            if sourceFile != '':
                data['self.sg_source_file'] = sourceFile

            return self.sg.create('Version', data)

        # look for specific version
        def versionFind(self, versionID):
            '''Find all versions in a shot with most recent first
            Parameters : (shotID)
            Output : Version data:
            ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
            'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
            'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
            'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
            'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
            'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
            'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
            'filmstrip_image', 'tag_list', 'frame_count', 'flagged']        
            '''
            retFields = self.getFields('Version')
            return self.sg.find('Version', [['id', 'is', versionID]],
                                retFields, [{
                                    'field_name': 'created_at',
                                    'direction': 'desc'
                                }])[0]

        # look for versions in a shot:
        def versionFindShot(self, shotID):
            '''Find all versions in a shot with most recent first
            Parameters : (shotID)
            Output : Version data:
            ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
            'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
            'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
            'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
            'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
            'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
            'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
            'filmstrip_image', 'tag_list', 'frame_count', 'flagged']        
            '''
            retFields = self.getFields('Version')
            return self.sg.find('Version', [['entity', 'is', shotID]],
                                retFields, [{
                                    'field_name': 'created_at',
                                    'direction': 'desc'
                                }])

        def versionFindLatest(self, shotID):
            '''Find only the most recent version
            Parameters : (shotID)
            Output : Version data:
            ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
            'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
            'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
            'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
            'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
            'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
            'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
            'filmstrip_image', 'tag_list', 'frame_count', 'flagged']         
            '''
            retFields = self.getFields('Version')
            return self.sg.find_one('Version', [['entity', 'is', shotID]],
                                    retFields, [{
                                        'field_name': 'created_at',
                                        'direction': 'desc'
                                    }])

        # search for the latest task given shotID and task info
        def versionFindLatestTask(self, shotID, task):
            retFields = self.getFields('Version')
            # first look for the task and get the ID
            filters = [['content', 'is', task], ['entity', 'is', shotID]]
            taskID = self.sg.find_one('Task', filters)
            # then look for the latest
            #version using the task ID.  note that we need to use the [0] or else we're sending the array versus the hash
            versionLatest = self.sg.find_one(
                'Version',
                [['entity', 'is', shotID], ['self.sg_task', 'is', taskID]],
                retFields, [{
                    'field_name': 'created_at',
                    'direction': 'desc'
                }])
            return versionLatest

        ## The following requires a field called "client_version" be added to shotgun
        def versionClientUpdate(self,
                                shotID,
                                version,
                                clientVersionName='Client Version'):
            '''This takes the shotID and version (int) and updates the shot with this client version number
            Sometimes the client wants to see different version numbers versus the internal ones.  This option allows for it.
            You will need to create a field.  Client Version is what I have used but you can specify what you want here.
            Parameters: (shotID, version, clientVersionName ='Client Version')
            Output : Version data
            '''
            sgFieldName = 'sg_' + clientVersionName.lower().replace(' ', '_')
            data = {sgFieldName: version}
            try:
                result = self.sg.update('Shot', shotID['id'], data)
            except:
                newField = self.sg.schema_field_create('Shot', 'number',
                                                       clientVersionName)
                result = self.sg.update('Shot', shotID['id'], data)
            return result

        def uploadQT(self, entityType, item, path):
            '''Upload a file to shotgun in the 'self.sg_qt' field.
            If you do this for a shot, you will need to add this to a field
            the field should be called 'qt' as shotgun will add the self.sg_ to it
            Shotgun provides the self.sg_qt for versions automatically
            Parameters: (entity,item,path)
            uploadQT ('Version',versionData, '/my/file.mov')
            '''
            # Make sure first letter is capitalized
            entity = entityType.capitalize()

            # upload that mother
            if entity.lower() == 'shot':
                try:
                    result = self.sg.upload(entity, item['id'], path, 'sg_qt')
                except:
                    newField = self.sg.schema_field_create('Shot', 'url', 'QT')
                    result = self.sg.upload(entity, item['id'], path, 'sg_qt')

            elif entity.lower() == 'version':
                result = self.sg.upload(entity, item['id'], path,
                                        'sg_uploaded_movie')
            return result

        def versionClientGet(self, shotID, clientVersion='Client Version'):
            '''Get latest client version number
            Parameters : (hotID, clientVersion='Client Version')
            Output : Version data
            '''
            sgFieldName = 'sg_' + clientVersionName.lower().replace(' ', '_')
            try:
                currentVersion = shotID[sgFieldName]
            except:
                currentVersion = 0
            if currentVersion == None:
                return 0
            return currentVersion

        def playlistFind(self, project, playlistName):
            '''Search for a playlist given a project and name
            Parameters : (project, playlistName)
            Output : playlist data:
            ['code', 'description', 'versions', 'created_at', 'sg_cinesync_session_url', 
            'updated_at', 'created_by', 'project', 'filmstrip_image', 'notes', 'image', 
            'updated_by', 'sg_cinesync_session_key', 'sg_status', 'tag_list', 'id', 
            'sg_date_and_time']        
            '''
            retFields = self.getFields('Playlist')
            return self.sg.find_one(
                'Playlist',
                [['code', 'is', playlistName], ['project', 'is', project]],
                retFields)

        def playlistCreate(self,
                           project,
                           playlistName,
                           playlistDescription=''):
            '''Create a playlist given a playlist name
            Parameters : (project, playlistName, playlistDescription='')
            Output : playlist data
            '''
            data = {
                'project': project,
                'code': playlistName,
                'description': playlistDescription
            }
            return self.sg.create('Playlist', data)

        # Add a version to a playlist
        def playlistAddVersion(self, project, playlistName, version):
            '''
            Description :\n
            This adds a version (existing version in the system) to a playlist.\n
            You need to give it: (in order)\r
            shotgun connection class\r
            project (dict of the project info including name and id)\r
            playlist name (string of the name of the playlist)\r
            version (dict of the version you wish to add\n
            It will return with a dict of the playlist
            '''

            my_playlist_list = self.sg.find_one(
                'Playlist',
                [['code', 'is', playlistName], ['project', 'is', project]],
                ['versions'])
            if len(my_playlist_list):
                ver_list = my_playlist_list['versions']
                ver_list.append({
                    'type': 'Version',
                    'name': version['code'],
                    'id': version['id']
                })
                result = self.sg.update('Playlist', my_playlist_list['id'],
                                        {'versions': ver_list})
                return result

        def playlistInfo(self, project, playlistName):
            '''Get playlist info (eg version name and description)
            Parameters : (project, playlistName)
            Output : version data
            '''
            data = []
            versionData = []
            retFields = self.getFields('Version')
            for versionInPlaylist in self.sg.find_one(
                    'Playlist',
                [['code', 'is', playlistName], ['project', 'is', project]],
                ['versions'])['versions']:
                data.append(
                    self.sg.find_one('Version',
                                     [['id', 'is', versionInPlaylist['id']]],
                                     retFields))
            #for items in data:
            #   versionData.append({'name':items['code'],'desc':items['description'],'first_frame':items['self.sg_first_frame})
            return data

        def getTimeShot(self, shot):
            '''Given shot (as dict) return total time on shot as [0] and other times for each task on shot
            '''
            outputData = []
            retFields = ['content', 'time_logs_sum']
            totalTime = 0
            for curTask in shot['tasks']:
                taskData = self.sg.find_one('Task',
                                            [['id', 'is', curTask['id']]],
                                            fields=retFields)
                totalTime += taskData['time_logs_sum']
                outputData.append({
                    'name': taskData['content'],
                    'time': taskData['time_logs_sum']
                })
            outputData.insert(0, {'name': shot['code'], 'time': totalTime})
            return outputData
Пример #13
0
from shotgun_api3 import Shotgun
from shotgun_api3 import __version__ as VERSION
from pprint import pprint
from faker import Faker
fake = Faker()
import sys
import os
import json

SERVER_PATH = 'https://bwillenbring1.shotgunstudio.com'
sg = Shotgun(SERVER_PATH, login='******', password='******')

user = {'type':'HumanUser','id':42}
proj = {'type':'Project','id':69}
page_id = sg.find_one('Page',[['page_type','is','project_overview'],['project','is', proj]])['id']
# Set the user's home page to the Cypress Test Projects shots page
data = {'custom_home_page':{'type':'Page','id':page_id}}
success = sg.update('HumanUser', user['id'], data=data)
pprint (success['custom_home_page']['id'] == page_id)
Пример #14
0
from docx import Document
from shotgun_api3 import Shotgun

# Setting up API for Shotgun
SERVER_PATH = ""
SCRIPT_NAME = ''
SCRIPT_KEY = ''
sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)

# Tools used to Query the project name to their ID
proj = sg.find_one("Project", [["name", "is", "Walt Denny"]])
print proj
query = sg.schema_read()['Asset'].keys()
print query
print sg.schema_read()['Asset'].get('sg_rpm_number')

# Function to format the text that gets read by Note_Thread_Read
def formatted(x):
    x.pop("type", None)
    x.pop("id", None)
    Name = x.get('created_by', {}).get('name')
    Name2 = x.get('user', {}).get('name')
    global thread
    if 'content' in x:
        if Name == None:
            thread += "\n"
            thread += str(Name2) + ":"
            thread += "\n"
        else:
            thread += "\n"
            thread += str(Name) + ":"
Пример #15
0
            shutil.copy(tmp_icon, icon_path)

        i['image'] = icon_path
        print '- Download thumbnail : ' + icon_path

    return entitys


# def sg_get_shot():

asset_entitys = sg_get_asset(project_name)

filters = [['project.Project.name', 'is', project_name],
           ['code', 'is', shot_name]]

shot_entity = sg.find_one('Shot', filters, fields=[])


def sg_set_assets_to_shot(asset_entitys, shot_entity):

    shot_id = shot_entity['id']
    data = {'assets': asset_entitys}

    return sg.update('Shot', shot_id, data)


print sg_set_assets_to_shot(asset_entitys, shot_entity)

# # first SG Lists
# sg_asset_lists()
# # respond with listWidgetItem selected
Пример #16
0
class Main(QtGui.QWidget, Ui_Form, ReferenceTab, CommentWidget, Lib, TaskManager, MyTasks, WhatsNew, Asset, LogEntry, Task, AssetLoader, Moodboard_Creator, PeopleTab, RenderTab):
    def __init__(self):
        super(Main, self).__init__()

        self.username = os.getenv('USERNAME')

        self.setWindowFlags(self.windowFlags() | QtCore.Qt.CustomizeWindowHint)

        self.ReferenceTab = ReferenceTab
        self.Lib = Lib
        self.TaskManager = TaskManager
        self.RenderTab = RenderTab
        self.MyTasks = MyTasks
        self.WhatsNew = WhatsNew
        self.CommentWidget = CommentWidget
        self.Task = Task
        self.Asset = Asset
        self.AssetLoader = AssetLoader
        self.LogEntry = LogEntry
        self.Moodboard_Creator = Moodboard_Creator
        self.PeopleTab = PeopleTab

        sg_url = "http://nad.shotgunstudio.com"
        sg_script_name = "ThibaultGenericScript"
        sg_key = "e014f12acda4074561022f165e8cd1913af2ba4903324a72edbb21430abbb2dc"
        self.sg_project_id = 146

        self.sg = Shotgun(sg_url, sg_script_name, sg_key)

        # Initialize the guis
        self.Form = self.setupUi(self)
        self.Form.center_window()

        self.setMinimumSize(1453, 923)
        self.setMaximumSize(1453, 923)

        self.db_to_load = ""
        self.db_path = "Z:\\Groupes-cours\\NAND999-A15-N01\\Nature\\_pipeline\\_utilities\\_database\\nature.sqlite"  # Database nature


        if QtGui.QApplication.keyboardModifiers() == QtCore.Qt.ShiftModifier:
            # Database Setup
            self.db_path = "H:\\01-NAD\\_pipeline\\_utilities\\_database\\db.sqlite"  # Copie de travail

        # Backup database
        if self.db_path not in ["H:\\01-NAD\\_pipeline\\_utilities\\_database\\db.sqlite", "Z:\\Groupes-cours\\NAND999-A15-N01\\Nature\\_pipeline\\_utilities\\_database\\rendering.sqlite"]:
            self.backup_database()

        self.db = sqlite3.connect(self.db_path, check_same_thread=False, timeout=30.0)
        self.cursor = self.db.cursor()

        # Global Variables
        self.projectList.hide()
        self.i = 0
        self.computer_id = socket.gethostname()
        self.ref_assets_instances = []
        self.selected_asset = None
        self.utf8_codec = QtCore.QTextCodec.codecForName("utf-8")
        self.today = time.strftime("%d/%m/%Y", time.gmtime())
        self.cur_path = os.path.dirname(os.path.realpath(__file__))  # H:\01-NAD\_pipeline\_utilities\_asset_manager
        self.cur_path_one_folder_up = self.cur_path.replace("\\_asset_manager", "")  # H:\01-NAD\_pipeline\_utilities
        self.NEF_folder = self.cur_path_one_folder_up + "\\_NEF"  # H:\01-NAD\_pipeline\_utilities\NEF
        self.screenshot_dir = self.cur_path_one_folder_up + "\\_database\\screenshots\\"
        self.no_img_found = self.cur_path + "\\media\\no_img_found.png"
        self.number_of_refreshes = 0
        self.members = {"acorbin":"Alexandre", "fpasquarelli":"Francis", "costiguy": "Chloe", "cgonnord": "Christopher",
                        "erodrigue": "Etienne", "jberger": "Jeremy", "lgregoire": "Laurence",
                        "lclavet": "Louis-Philippe", "mbeaudoin": "Mathieu",
                        "mroz": "Maxime", "obolduc": "Olivier", "slachapelle": "Simon", "thoudon": "Thibault",
                        "vdelbroucq": "Valentin", "yjobin": "Yann", "yshan": "Yi"}
        self.sg_members = {"acorbin": "3dalcor", "fpasquarelli": "francis.pasquarelli", "costiguy": "ostiguy.chloe", "cgonnord": "christopher.gonnord",
                           "erodrigue": "etienne.rodrigue89", "jberger": "jeremy.berger3d", "lgregoire": "lau-gregoire",
                           "lclavet": "clavet.lp", "mbeaudoin": "beaudoinmathieu",
                           "mroz": "maximeroz", "obolduc": "ol.bolduc", "slachapelle": "simonlachapelle", "thoudon": "houdon.thibault",
                           "vdelbroucq": "valentin.delbroucq", "yjobin": "yannjobinphoto", "yshan": "yishan3d"}
        self.departments_shortname = {"Script": "spt", "Storyboard": "stb", "References": "ref", "Concepts": "cpt",
                                      "Modeling": "mod", "Texturing": "tex", "Rigging": "rig", "Animation": "anm",
                                      "Simulation": "sim", "Shading": "shd", "Camera": "cam", "Lighting": "lgt", "Layout": "lay", "DMP": "dmp", "Rendering":"rdr",
                                      "Compositing": "cmp", "Editing": "edt", "RnD": "rnd"}
        self.departments_longname = {"spt": "Script", "stb": "Storyboard", "ref": "References", "cam": "Camera", "cpt": "Concepts", "lgt": "Lighting",
                                     "mod": "Modeling", "tex": "Texturing", "rig": "Rigging", "anm": "Animation",
                                     "sim": "Simulation", "shd": "Shading", "lay": "Layout", "dmp": "DMP", "rdr":"Rendering",
                                     "cmp": "Compositing", "edt": "Editing", "rnd": "RnD"}

        refresh_icon = QtGui.QIcon(self.cur_path + "\\media\\refresh.png")
        self.refreshAllBtn.setIcon(refresh_icon)
        self.refreshAllBtn.setIconSize(QtCore.QSize(24, 24))
        self.refreshAllBtn.clicked.connect(self.refresh_all)

        # Setup user session if it is not already setup
        is_setup = self.cursor.execute('''SELECT is_setup FROM preferences WHERE username=?''', (self.username,)).fetchone()[0]
        if is_setup == 0:
            self.Lib.setup_user_session(self)
            self.cursor.execute('''UPDATE preferences SET is_setup=1 WHERE username=?''', (self.username,))
            self.db.commit()

        # Clear temp folder
        if os.path.isdir("H:/tmp"):
            try:
                shutil.rmtree("H:/tmp")
            except:
                pass

        try:
            os.makedirs("H:/tmp")
        except:
            pass

        # Create Favicon
        self.app_icon = QtGui.QIcon()
        self.app_icon.addFile(self.cur_path + "\\media\\favicon_cube.png", QtCore.QSize(64, 64))
        self.Form.setWindowIcon(self.app_icon)

        # Set the StyleSheet
        self.themePrefComboBox.currentIndexChanged.connect(self.change_theme)
        self.theme = self.cursor.execute('''SELECT theme FROM preferences WHERE username=?''', (self.username,)).fetchone()[0]
        self.themePrefComboBox.setCurrentIndex(int(self.theme))
        self.change_theme()

        # Admin Setup
        self.remove_tabs_based_on_members()

        # Get remaining time and set deadline Progress Bar
        day_start = date(2015,6,28)
        day_end = date(2016,4,25)
        day_today = datetime.now().date()

        months_and_days_left = relativedelta.relativedelta(day_end, day_today)

        total_days = abs(day_end - day_start).days
        remaining_days = abs(day_end - date.today()).days
        remaining_days_percent = (remaining_days * 100) / total_days # Converts number of remaining day to a percentage

        self.deadlineProgressBar.setFormat("{0} months and {1} days left ({2}%)".format(months_and_days_left.months, months_and_days_left.days, remaining_days_percent))
        self.deadlineProgressBar.setMaximum(total_days)
        self.deadlineProgressBar.setValue(remaining_days)
        hue = self.fit_range(remaining_days, 0, total_days, 0, 76)
        self.deadlineProgressBar.setStyleSheet("QProgressBar::chunk {background-color: hsl(" + str(hue) + ", 255, 205);}")

        if self.username not in ["thoudon", "lclavet", "costiguy"]:
            self.deadlineFrame.hide()

        # Setup disk usage progress bar
        disk_usage = self.Lib.get_folder_space(self)
        disk_usage = int(float(disk_usage) * 1000) # Multiply disk usage by 1000. Ex: 1.819 to 1819
        disk_usage = (2000 * int(disk_usage)) / 1862 # 2TO in theory = 1.862GB in reality. Remapping real disk usage to the theoric one
        self.diskUsageProgressBar.setFormat('{0}/2000 GB'.format(str(disk_usage)))
        self.diskUsageProgressBar.setRange(0, 2000)
        self.diskUsageProgressBar.setValue(int(disk_usage))
        hue = self.fit_range(int(disk_usage), 0, 2000, 0, 76)
        self.diskUsageProgressBar.setStyleSheet("QProgressBar::chunk {background-color: hsl(" + str(hue) + ", 255, 205);}")

        # Thumbnail creation progress bar setup
        self.thumbnailProgressBar.setStyleSheet("QProgressBar::chunk {background-color: hsl(0, 100, 175);}")
        self.thumbnailProgressBar.setValue(0)
        self.thumbnailProgressBar.hide()

        # Get software paths from database and put them in preference
        self.photoshop_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Photoshop"''').fetchone()[0])
        self.maya_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Maya"''').fetchone()[0])
        self.maya_batch_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Maya Batch"''').fetchone()[0])
        self.softimage_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Softimage"''').fetchone()[0])
        self.softimage_batch_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Softimage Batch"''').fetchone()[0])
        self.houdini_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Houdini"''').fetchone()[0])
        self.houdini_batch_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Houdini Batch"''').fetchone()[0])
        self.cinema4d_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Cinema 4D"''').fetchone()[0])
        self.nuke_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Nuke"''').fetchone()[0])
        self.zbrush_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="ZBrush"''').fetchone()[0])
        if os.path.exists("C:/Program Files/Mari2.6v2/Bundle/bin/Mari2.6v2.exe"):
            self.mari_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Mari"''').fetchone()[0])
        else:
            self.mari_path = "C:/Program Files/Mari2.6v5/Bundle/bin/Mari2.6v5.exe"
        self.blender_path = str(self.cursor.execute('''SELECT software_path FROM software_paths WHERE software_name="Blender"''').fetchone()[0])

        self.cursor.execute('''UPDATE preferences SET is_online=1 WHERE username=?''', (self.username,))
        self.db.commit()

        # Preferences setup
        self.prefBckGroundColorSlider.sliderMoved.connect(self.change_pref_background_color_pixmap)
        self.prefBckGroundColorSlider.setStyleSheet("background-color; red;")

        # Set systray actions
        self.quitAction = QtGui.QAction("Quit", self, triggered=self.terminate_program)
        self.quitAction.setIcon(QtGui.QIcon(self.cur_path + "/media/turn_off.png"))

        # Systray icon
        self.trayIconMenu = QtGui.QMenu(self)
        self.trayIconMenu.addAction(self.quitAction)

        self.tray_icon = QtGui.QIcon(self.cur_path + "\\media\\favicon_cube.png")
        self.trayIcon = QtGui.QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.setIcon(self.tray_icon)

        self.tray_icon_log_id = ""
        self.tray_message = ""

        self.trayIcon.hide()

        #self.tray_icon.messageClicked.connect(self.tray_icon_message_clicked)
        self.trayIcon.activated.connect(self.tray_icon_clicked)

        # Initialize modules and connections
        AssetLoader.__init__(self)
        self.ReferenceTab.__init__(self)
        self.RenderTab.__init__(self)
        self.CommentWidget.__init__(self)
        self.WhatsNew.__init__(self)
        self.PeopleTab.__init__(self)
        self.WhatsNew.load_whats_new(self)
        self.check_last_active()

        #self.check_news_thread = CheckNews(self)
        #self.connect(self.check_news_thread, QtCore.SIGNAL("check_last_active"), self.check_last_active)
        #self.check_news_thread.daemon = True
        #self.check_news_thread.start()

        self.show()

        #self.check_shotgun_time_log()

    def check_shotgun_time_log(self):
        self.username = "******"
        peoples = {"acorbin":"Alexandre Corbin", "costiguy":"Chloé Ostiguy", "cgonnord":"Christopher Gonnord", "erodrigue":"Etienne Rodrigue", "fpasquarelli":"Francis Pasquarelli", "jberger":"Jérémy Berger", "lgregoire":"Laurence Grégoire", "lclavet":"Louis-Philippe Clavet", "mbeaudoin":"Mathieu Beaudoin", "mroz":"Maxime Roz", "thoudon":"Thibault Houdon", "vdelbroucq":"Valentin Delbroucq", "yjobin":"Yann Jobin", "yshan":"Yi Shan"}
        user = peoples[self.username]

        project = self.sg.find_one("Project", [["id", "is", self.sg_project_id]])
        time_log = self.sg.find("TimeLog", [["date", "in_calendar_day", -1], ["project", "is", project]], ["user"])
        people_logged = [log["user"]["name"] for log in time_log]
        people_logged = list(set(people_logged))

        if user not in people_logged:
            time_log_window = QtGui.QDialog(self)
            time_log_window.setWindowTitle("Add your time log entry")
            layout = QtGui.QVBoxLayout(time_log_window)
            descriptionLabel = QtGui.QLabel(time_log_window)
            durationLabel = QtGui.QLabel(time_log_window)
            descriptionLabel.setText("Description")
            durationLabel.setText("Duration")
            self.description = QtGui.QLineEdit(time_log_window)
            self.duration = QtGui.QLineEdit(time_log_window)

            addLogEntryBtn = QtGui.QPushButton(time_log_window)
            addLogEntryBtn.setText("Add Time Log Entry")
            addLogEntryBtn.clicked.connect(self.shotgun_add_time_log)

            didntWorkBtn = QtGui.QPushButton(time_log_window)
            didntWorkBtn.setText("I didn't work on this project yesterday.")

            layout.addWidget(durationLabel)
            layout.addWidget(self.duration)
            layout.addWidget(descriptionLabel)
            layout.addWidget(self.description)
            layout.addWidget(addLogEntryBtn)
            layout.addWidget(didntWorkBtn)

            time_log_window.exec_()

    def shotgun_add_empty_time_log(self):
        pass

    def shotgun_add_time_log(self):

        print(self.description.text())
        print(self.duration.text())

    def add_tag_to_tags_manager(self):
        # Check if a project is selected
        if len(self.projectList.currentText()) == 0:
            Lib.message_box(text="Please select a project first.")
            return

        tag_name = unicode(self.addTagLineEdit.text())
        tag_name = Lib.normalize_str(self, tag_name)

        if len(tag_name) == 0:
            Lib.message_box(text="Please enter a tag name.")
            return

        item = QtGui.QTreeWidgetItem(self.tagsTreeWidget)
        item.setText(0, tag_name)
        self.tagsTreeWidget.addTopLevelItem(item)

        self.addTagLineEdit.setText("")
        self.save_tags_list()

    def remove_selected_tags_from_tags_manager(self):
        root = self.tagsTreeWidget.invisibleRootItem()
        for item in self.tagsTreeWidget.selectedItems():
            (item.parent() or root).removeChild(item)
        self.save_tags_list()

    def save_tags_list(self):
        root = self.tagsTreeWidget.invisibleRootItem() # Fetch the root item
        child_count = root.childCount()
        for item in xrange(child_count):

            # Get the text of the first item in the tree widget
            parent_text = str(root.child(item).text(0))

            # Check if item already exists, if no, add it to the database, if yes, update its name and parent
            already_exist = self.cursor.execute('''SELECT tag_name FROM tags WHERE tag_name=?''', (parent_text,)).fetchone()
            if already_exist == None:
                self.cursor.execute('''INSERT INTO tags(project_name, tag_name, tag_parent) VALUES(?,?,?)''', (self.selected_project_name, parent_text, "",))
            else:
                self.cursor.execute('''UPDATE tags SET tag_name=?, tag_parent=? WHERE tag_name=? AND project_name=?''', (parent_text, "", parent_text, self.selected_project_name,))

            # Get all children of parent item
            nbr_of_children = root.child(item).childCount()
            for i in range(nbr_of_children):
                child_text = str(root.child(item).child(i).text(0))

                # Check if item already exists, if no, add it to the database, if yes, update its name and parent
                already_exist = self.cursor.execute('''SELECT tag_name FROM tags WHERE tag_name=?''', (child_text,)).fetchone()
                if already_exist == None:
                    self.cursor.execute('''INSERT INTO tags(project_name, tag_name, tag_parent) VALUES(?,?,?)''', (self.selected_project_name, child_text, parent_text,))
                else:
                    self.cursor.execute('''UPDATE tags SET tag_name=?, tag_parent=? WHERE tag_name=? AND project_name=?''', (child_text, parent_text, child_text, self.selected_project_name,))

        self.db.commit()

    def add_assets_to_asset_list(self, assets_list):
        """
        Add assets from assets_list to self.assetList

        """

        self.assetList.clear()
        for asset in assets_list:
            self.assetList.addItem(asset[4])

    def clear_filter(self, filter_type):
        """
        Clear the filter edit line
        """
        if filter_type == "seq":
            self.seqFilter.setText("")
        elif filter_type == "asset":
            self.assetFilter.setText("")

    def update_thumb(self):
        """
        Update selected asset thumbnail
        """
        self.Form.showMinimized()

        Lib.take_screenshot(self.screenshot_dir, self.selected_asset_name)

        pixmap = QtGui.QPixmap(self.screenshot_dir + self.selected_asset_name + ".jpg").scaled(1000, 200,
                                                                                               QtCore.Qt.KeepAspectRatio,
                                                                                               QtCore.Qt.SmoothTransformation)
        self.assetImg.setPixmap(pixmap)
        self.Form.showMaximized()
        self.Form.showNormal()

    def remove_tabs_based_on_members(self):

        if not (self.username == "thoudon" or self.username == "lclavet"):
            self.adminPrefFrame.hide()
            self.createAssetFromScratchBtn.hide()

        self.get_tabs_id_from_name()


        if self.members[self.username] == "Chloe":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])

        elif self.members[self.username] == "Francis":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])


        elif self.members[self.username] == "Alexandre":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])


        elif self.members[self.username] == "Christopher":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])


        elif self.members[self.username] == "Etienne":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])


        elif self.members[self.username] == "Jeremy":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])


        elif self.members[self.username] == "Laurence":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Louis-Philippe":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])

        elif self.members[self.username] == "Mathieu":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])


        elif self.members[self.username] == "Maxime":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])



        elif self.members[self.username] == "Olivier":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])


        elif self.members[self.username] == "Simon":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])


        elif self.members[self.username] == "Thibault":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()

        elif self.members[self.username] == "Yann":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Yi":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])


        elif self.members[self.username] == "Valentin":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

    def get_tabs_id_from_name(self):
        self.tabs_list = {}
        for i in xrange(self.Tabs.count()):
            self.tabs_list[str(self.Tabs.tabText(i))] = i

    def change_username(self):
        username = str(self.usernameAdminComboBox.currentText())
        self.username = username

    def backup_database(self):
        # Get creation_time of last database backup and compare it to current  time
        database_files = Lib.get_files_from_folder(self, path="Z:\\Groupes-cours\\NAND999-A15-N01\\Nature\\_pipeline\\_utilities\\_database\\_backup")
        if len(database_files) > 1000:
            self.Lib.message_box(self, type="error", text=u"Trop de backups détectés pour la base de donnée. Veuillez avertir Thibault, merci ;)")

        cur_db_name = os.path.split(self.db_path)[-1].replace(".sqlite", "")
        database_files = [i for i in database_files if cur_db_name in os.path.split(i)[-1]]
        database_files = sorted(database_files)
        last_database_file = database_files[-1]
        creation_time = time.ctime(os.path.getctime(last_database_file))
        creation_time = time.strptime(creation_time, "%a %b %d %H:%M:%S %Y")
        current_time = str(datetime.now())
        current_time = time.strptime(current_time, "%Y-%m-%d %H:%M:%S.%f")
        time_difference = (time.mktime(current_time) - time.mktime(creation_time)) / 60

        if time_difference > 180: # If last backup is older than 5 hours, do a backup
            fileName, fileExtension = os.path.splitext(last_database_file)
            last_database_file_version = int(fileName.split("_")[-1])
            new_version = str(last_database_file_version + 1).zfill(4)
            backup_database_filename = fileName.replace(str(last_database_file_version).zfill(4), new_version) + ".sqlite"
            shutil.copy(self.db_path, backup_database_filename)

    def refresh_all(self):
        self.blockSignals(True)

        #Default refreshes
        self.mt_item_added = True
        self.item_added = True
        self.setup_tags()

        #Get current tab text
        current_tab_text = self.Tabs.tabText(self.Tabs.currentIndex())

        if current_tab_text == "Asset Loader":
            self.statusLbl.setText("Status: Refreshing Asset Loader tab...")
            self.repaint()
            self.AssetLoader.load_all_assets_for_first_time(self)
            self.AssetLoader.load_assets_from_selected_seq_shot_dept(self)

        elif current_tab_text == "Task Manager":
            self.statusLbl.setText("Status: Refreshing Task Manager tab...")
            self.repaint()
            TaskManager.add_tasks_from_database(self)

        elif current_tab_text == "Tasks":
            self.statusLbl.setText("Status: Refreshing Tasks tab...")
            self.repaint()
            MyTasks.mt_add_tasks_from_database(self)

        elif current_tab_text == "Render":
            self.statusLbl.setText("Status: Refreshing Render tab...")
            self.repaint()
            RenderTab.add_computers_from_database(self)
            RenderTab.add_jobs_from_database(self)
            RenderTab.add_frames_from_database(self)

        elif current_tab_text == "People":
            self.statusLbl.setText("Status: Refreshing People tab...")
            self.repaint()
            self.PeopleTab.get_online_status(self)
            self.cursor.execute('''UPDATE preferences SET last_active=? WHERE username=?''', (datetime.now().strftime("%d/%m/%Y at %H:%M"), self.username,))
            self.db.commit()

        elif current_tab_text == "Images Manager":
            self.statusLbl.setText("Status: Refreshing Images Manager tab...")
            self.repaint()
            if len(self.ref_assets_instances) > 1:
                self.ReferenceTab.refresh_reference_list(self)

        elif "What's New" in current_tab_text:
            self.statusLbl.setText("Status: Refreshing What's New tab...")
            self.repaint()
            self.WhatsNew.load_whats_new(self)

        self.statusLbl.setText("Status: Idle...")
        self.blockSignals(False)

    def change_theme(self):
        if self.themePrefComboBox.currentIndex() == 0:
            self.theme = 0
            self.prefBckGroundColorSlider.setValue(114)
            self.Lib.apply_style(self, self)
            self.cursor.execute('''UPDATE preferences SET theme=? WHERE username=?''', (0, self.username,))
        elif self.themePrefComboBox.currentIndex() == 1:
            self.theme = 1
            self.prefBckGroundColorSlider.setValue(241)
            self.setStyleSheet("")
            app.setStyle(QtGui.QStyleFactory.create("cleanlooks"))
            self.cursor.execute('''UPDATE preferences SET theme=? WHERE username=?''', (1, self.username,))
            css = QtCore.QFile(self.cur_path + "\\media\\cleanlooks.css")
            css.open(QtCore.QIODevice.ReadOnly)
            if css.isOpen():
                self.Form.setStyleSheet(QtCore.QVariant(css.readAll()).toString().replace("checkbox|placeholder", self.cur_path.replace("\\", "/") + "/media/checkbox.png"))
        elif self.themePrefComboBox.currentIndex() == 2:
            self.prefBckGroundColorSlider.setValue(255)
            self.theme = 2
            self.setStyleSheet("")
            app.setStyle(QtGui.QStyleFactory.create("plastique"))
            self.cursor.execute('''UPDATE preferences SET theme=? WHERE username=?''', (2, self.username,))

        self.db.commit()

    def change_pref_background_color_pixmap(self):
        slider_value = self.prefBckGroundColorSlider.value()
        self.referenceThumbListWidget.setStyleSheet("background-color: rgb({0},{0},{0});".format(slider_value))

    def tray_icon_message_clicked(self):

        if self.tray_message == "Manager is in background mode.":
            return

        clicked_log_entry = self.cursor.execute('''SELECT log_value FROM log WHERE log_id=?''', (self.tray_icon_log_id,)).fetchone()[0]
        clicked_log_description = self.cursor.execute('''SELECT log_entry FROM log WHERE log_id=?''', (self.tray_icon_log_id,)).fetchone()[0]

        if len(clicked_log_entry) == 0:
            return

        asset = self.Asset(main=self, id=clicked_log_entry, get_infos_from_id=True)

        if "reference" in clicked_log_description:
            if "video" in clicked_log_description:
                subprocess.Popen(["C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", asset.dependency])
            else:
                if os.path.isfile(asset.full_path):
                    os.system(asset.full_path)
                else:
                    self.Lib.message_box(self, text="Can't find reference: it must have been deleted.")

        elif "comment" in clicked_log_description:
            self.CommentWidget(main=self, asset=asset)

    def tray_icon_clicked(self, reason):
        if reason == QtGui.QSystemTrayIcon.DoubleClick:
            if self.isHidden():
                self.setWindowFlags(QtCore.Qt.Widget)
                self.show()
                self.setWindowState(self.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
                self.trayIcon.hide()
            else:
                self.hide()
                self.trayIcon.show()

    def keyPressEvent(self, event):

        global_pos = self.mapFromGlobal(QtGui.QCursor.pos())
        widget_under_mouse = self.childAt(global_pos)

        key = event.key()
        if key == QtCore.Qt.Key_F11:
            if self.isFullScreen():
                self.showNormal()
            else:
                self.showFullScreen()
        elif key == QtCore.Qt.Key_Delete:
            current_tab_text = self.Tabs.tabText(self.Tabs.currentIndex())
            if current_tab_text == "Images Manager":
                ReferenceTab.remove_selected_references(self)
        elif key == QtCore.Qt.Key_F2:
            selected_reference = self.referenceThumbListWidget.selectedItems()[0]
            asset = selected_reference.data(QtCore.Qt.UserRole).toPyObject()
            ReferenceTab.rename_reference(self, asset)

        elif key == QtCore.Qt.Key_F1:
            self.show_wiki_help(widget_under_mouse)

        elif key == QtCore.Qt.Key_F5:
            self.refresh_all()

    def show_wiki_help(self, widget):
        if widget.objectName() == "publishBtn":
            subprocess.Popen(["C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe", "file:///Z:/Groupes-cours/NAND999-A15-N01/Nature/_info/wiki/wiki.html#Modeling"])

    def closeEvent(self, event):
        if not self.trayIcon.isVisible():
            self.setWindowFlags(QtCore.Qt.Tool)
            self.hide()
            self.trayIcon.show()
            self.tray_message = "Manager is in background mode."
            self.trayIcon.showMessage('Still running...', self.tray_message, QtGui.QSystemTrayIcon.Information, 1000)
            self.hide()
            event.ignore()
            self.trayIcon.show()

    def terminate_program(self):
        # tasks = subprocess.check_output(['tasklist'])
        # if "houdin" in tasks.lower():
        #     self.Lib.message_box(self, type="error", text="Please close Houdini layout scenes before closing the Manager!")
        #     return


        self.cursor.execute('''UPDATE preferences SET is_online=0 WHERE username=?''', (self.username,))
        self.db.commit()
        self.Lib.switch_mari_cache(self, "perso")
        self.close()
        app.exit()

        # self.quit_msg = "Are you sure you want to exit the program?"
        # reply = QtGui.QMessageBox.question(self, 'Are you leaving :(',
        #                  quit_msg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
        #
        # if reply == QtGui.QMessageBox.Yes:
        #
        #     event.accept()
        # else:
        #     event.ignore()

    def changeEvent(self, event):
        if event.type() == QtCore.QEvent.WindowStateChange:
            if self.windowState() & QtCore.Qt.WindowMinimized:
                self.setWindowFlags(QtCore.Qt.Tool)
                self.hide()
                self.trayIcon.show()
                self.tray_message = "Manager is in background mode."
                self.trayIcon.showMessage('Still running...', self.tray_message, QtGui.QSystemTrayIcon.Information, 1000)

    def check_last_active(self):
        for user in self.members.keys():
            last_active = datetime.now().strftime("%d/%m/%Y at %H:%M")
            last_active_datetime = datetime.strptime(last_active, '%d/%m/%Y at %H:%M')

            last_active_db = self.cursor.execute('''SELECT last_active FROM preferences WHERE username=?''', (user, )).fetchone()[0]
            last_active_db_datetime = datetime.strptime(last_active_db, '%d/%m/%Y at %H:%M')

            time_difference = last_active_datetime - last_active_db_datetime
            if time_difference.seconds > 600:
                self.cursor.execute('''UPDATE preferences SET is_online=0 WHERE username=?''', (user,))
            else:
                self.cursor.execute('''UPDATE preferences SET is_online=1 WHERE username=?''', (user,))

        last_active = datetime.now().strftime("%d/%m/%Y at %H:%M")
        self.cursor.execute('''UPDATE preferences SET last_active=? WHERE username=?''', (last_active, self.username,))
        self.db.commit()
Пример #17
0
class ShotgunUtils():
    '''
    a light version of the shotgun utils class to connect and update shotgun task for external artist
    '''
    def __init__(self):
        '''
        creates the connection to the shotgun site by api
        '''
        '''   shotgun conection '''
        SERVER_PATH = "https://hcpstudio.shotgunstudio.com"
        SCRIPT_NAME = 'Tracker'
        SCRIPT_KEY = '99b5c166044037cc2d04646b1dfd58b2f44e8a146b710b425b8f561f2a21e49d'

        self.sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
        self.userId = None
        self.userDic = {}
        self.tasks = None
        self.projectPath = None

    def getsgParameters(self, sgType, parameter=None):
        schema = self.sg.schema_field_read(sgType, parameter)
        print schema

    def getUserId(self, userName):

        filters = [['name', 'is', userName]]
        field = ['id', 'name', 'sg_projectpath', 'sg_keyword', 'login']

        user = self.sg.find_one('HumanUser', filters, field)

        if user:
            self.userId = user['id']
            self.projectPath = user['sg_projectpath']
            self.userDic = user

            return user['id']

        else:
            print "no {0} User found ".format(userName)
            return None

    def taskByUser(self):

        if not self.userId == None:

            filter = [[
                'task_assignees', 'is', {
                    'type': 'HumanUser',
                    'id': self.userId
                }
            ], ['sg_status_list', 'is_not', 'fin'],
                      ['sg_status_list', 'is_not', 'apr'],
                      ['sg_status_list', 'is_not', 'cmpt']]

            fields = [
                'id', 'content', 'sg_status_list', 'start_date', 'due_date',
                'sg_complexity', 'sg_priority_1', 'sg_note', 'project',
                'entity', 'sg_digitalmedia', 'sg_displayname'
            ]

            order = [{
                'field_name': 'due_date',
                'direction': 'asc'
            }, {
                'field_name': 'sg_priority_1',
                'direction': 'asc'
            }, {
                'field_name': 'sg_complexity',
                'direction': 'desc'
            }]

            taskList = self.sg.find('Task', filter, fields, order)

            if taskList:
                self.tasks = taskList
                return taskList

            else:

                self.tasks = []

                print "no task Asigned to: ", self.userId
                return taskList

        else:
            taskList = []

            print "no Id found"
            return taskList

    def getTaskById(self, taskId):

        filter = [['id', 'is', taskId]]

        fields = [
            'id', 'content', 'sg_status_list', 'start_date', 'due_date',
            'sg_complexity', 'sg_priority_1', 'sg_note', 'project', 'entity',
            'sg_digitalmedia', 'sg_displayname'
        ]

        task = self.sg.find_one('Task', filter, fields)

        if task:
            return task

        else:
            print 'no task found'
            return None

    def updateStatusFromUser(self, taskId, status):

        task = self.getTaskById(taskId)

        if task:

            project = task['project']
            sgStatus = status

            data = {'project': project, 'sg_status_list': sgStatus}

            self.sg.update('Task', taskId, data)
            return 1

        else:
            print 'No task by this id'
            return None

    def updateProjectPath(self, projectPath):

        data = {'sg_projectpath': projectPath}

        self.sg.update('HumanUser', self.userId, data)

    def getNotes(self, sgTaskId):

        task = self.getTaskById(sgTaskId)
        if task:
            filters = [['tasks', 'is', task]]
            fields = ['content', 'created_at', 'user', 'addressings_to']
            order = [{'field_name': 'created_at', 'direction': 'asc'}]

            notes = self.sg.find('Note', filters, fields, order)

            return notes

        else:
            print 'no Task'
            return None

    def createNote(self, taskId, content):

        task = self.getTaskById(taskId)

        if task:

            data = {
                'project': task['project'],
                'content': content,
                'tasks': [task],
                'user': self.userDic,
                'subject': 'Note'
            }

            note = self.sg.create('Note', data)
            return note['id']

        else:
            return None

    def uploadAttachment(self, taskId, filePath, tag):

        task = self.getTaskById(taskId)

        if task:

            entity = task['entity']
            if entity:

                entityType = entity['type']
                entityId = entity['id']

                uploadedfile = self.sg.upload(entityType, entityId, filePath)

                if uploadedfile:
                    data = {'sg_type': tag, 'sg_taskid': taskId}
                    self.sg.update('Attachment', uploadedfile, data)
                    return uploadedfile
                else:
                    return None
            else:
                print 'no entity set'
                return None

    def downloadAttachment(self, taskId, downloadPath, parent=None):

        filters = [['sg_taskid', 'is', taskId], ['sg_type', 'is', 'REFERENCE']]
        fields = ['id', 'attachment_links', 'filename', 'created_at']
        attachments = self.sg.find('Attachment', filters, fields)

        if attachments:
            progressBar = QtGui.QProgressBar(parent)
            progressBar.show()
            size = len(attachments)

            for x, attach in enumerate(attachments):

                extension = path.splitext(attach['filename'])
                dt = attach['created_at'].strftime("%Y_%m_%d_%H-%M-%S")
                name = attach['attachment_links'][0]['id']

                namePadded = '{0}_{3}.{1:04d}{2}'.format(
                    name, x, extension[-1], dt)

                fullPath = path.join(downloadPath, namePadded)

                dwFile = self.sg.download_attachment(attach, fullPath,
                                                     attach['id'])

                progressBar.setValue(((x + 1) / size) * 100)

            progressBar.close()
            return attachments
        else:
            return None

    def uploadReference(self, entityType, entityId, filePath, tag, taskId):

        uploadedfile = self.sg.upload(entityType, entityId, filePath)

        if uploadedfile:
            data = {
                'sg_type': tag,
                'sg_type': 'REFERENCE',
                'sg_taskid': taskId
            }
            self.sg.update('Attachment', uploadedfile, data)

            return uploadedfile

        else:
            return None
Пример #18
0
                                 stdout=subprocess.PIPE).communicate()[0]
    for line in raw_facts.split("\n"):
        try:
            line.index("=>")
        except:
            continue
        #print "facter: %s" % line
        (key, value) = line.split("=>")
        #print "fkey: %s fvalue: %s" % ( key, value )
        ret[key.strip()] = value.strip()
    return ret


hostname = gethostname().split('.', 1)[0]

asset = sg.find_one("Asset", [['code', 'is', hostname]], ['id'])
if not asset:
    print "couldn't find asset"
else:
    # if we find a valid asset, sync the facts for it
    fact_data = get_fact_data()

    for fact_name, fact_value in fact_data.items():
        if not fact_name in facts_to_sync: continue

        fact_data = {
            'code': fact_name,
            'sg_asset': {
                'type': 'Asset',
                'id': asset['id']
            },
def dropSG( mimeType, text ):
    '''
    Parse the received url for the ID, connect to shotgun and retrieve info for the particular ID.
    args:
       text  -  url of a shotgun version
    '''
    # DO SOME MORE CHECKING IF WE CARE ABOUT THIS PARTICULAR URL.
    # THIS PARTICULAR SCRIPT ONLY CARES ABOUT VERSIONS

    if not mimeType == 'text/plain' or not (text.startswith( 'http' ) and 'shotgunstudio' in text):
        return False
        
    def idCheck( url, sgType ):
        foundID = re.match( '.+%s/(\d+)' % sgType, url )
        foundIDinEmail = re.match( '.+entity_id=(\d+).+entity_type=%s' % sgType, url )
        foundIDinURL = re.match( r'.+#%s_(\d+)_' % sgType, url )
        if not foundID and not foundIDinEmail and not foundIDinURL:
            return
        try:
            if foundID:
                return int( foundID.group(1) )
            elif foundIDinEmail:
                return int( foundIDinEmail.group(1) )
            elif foundIDinURL:
                return int( foundIDinURL.group(1) )
        except ValueError:
            return

    SERVER_PATH = 'https://duckling.shotgunstudio.com' #  use your shotgun server name (i.e. "https://studioName.shotgunstudio.com")
    SCRIPT_NAME = 'assetOpenToShotgun' #  use the name of the shotgun api script that will do the query (needs to be set up in Shotgun's admin area)
    SCRIPT_KEY = 'e932e9c2864c9bcdc3f3ddf8b801cc3d565bf51f' #   use the script key as generated by Shotgun when the above script was created in Shotgun's admin area        
    
    #-------------------------------- VERSION
    if 'Version' in text:
        sgID = idCheck( text, 'Version' )
        print 'retrieving shotgun version %s' % sgID
        #DO THE SHOTGUN THING
        CONNECT = Shotgun( SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY )
        # QUERY SHOTGUN FOR THE FOUND ID
        columns = ['sg_path_to_frames', 'sg_first_frame', 'sg_last_frame']
        filters = [ [ 'id', 'is', sgID] ]
        v = CONNECT.find_one( 'Version', filters, columns )
        
        #DO THE NUKE THING
        nuke.createNode( 'Read', 'file %(sg_path_to_frames)s first %(sg_first_frame)s last %(sg_last_frame)s origfirst %(sg_first_frame)s origlast %(sg_last_frame)s' % v )
        return True
    #-------------------------------- PLAYLIST
    elif 'Playlist' in text:
        sgID = idCheck( text, 'Playlist' )
        print 'retrieving shotgun playlist %s' % sgID
        #DO THE SHOTGUN THING
        CONNECT = Shotgun( SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY )
        versions = getPlaylistVersionsByID( CONNECT, sgID )

        #DO THE NUKE THING
        for v in versions:
            nuke.createNode( 'Read', 'file %(sg_path_to_frames)s first %(sg_first_frame)s last %(sg_last_frame)s origfirst %(sg_first_frame)s origlast %(sg_last_frame)s' % v )
        return True        
    #-------------------------------- SHOT
    elif 'Shot' in text:
        sgID = idCheck( text, 'Shot' )        
        print 'retrieving shotgun shot %s' % sgID
        #DO THE SHOTGUN THING
        CONNECT = Shotgun( SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY )
        versions = getVersions( CONNECT, {'type':'Shot', 'id':int(sgID)}, ignore=['omt'] )
        # GET SHOT DESCRIPTION
        columns = ['description']
        filters = [ [ 'id', 'is', sgID] ]
        shot = CONNECT.find_one( 'Shot', filters, columns )
        desc = shot['description']
        #DO THE NUKE THING
        for v in versions:
            nuke.createNode( 'Read', 'file %(sg_path_to_frames)s first %(sg_first_frame)s last %(sg_last_frame)s origfirst %(sg_first_frame)s origlast %(sg_last_frame)s label %(sg_version_type)s' % v )
        

        if desc:
            nuke.createNode( 'StickyNote', 'label "%s"' % desc )

        return True
    
    else:
        return False
Пример #20
0
from urlparse import urlparse
import cookielib
from shotgun_api3 import Shotgun

blob = yaml.load(sys.stdin)
method = sys.argv[1]

config = blob['config']
payload = blob['data']

sg = Shotgun(config['shotgun_url'], config['script_name'], config['script_api_key'], 'api3_preview')

if method == 'find':
  result = sg.find(payload['entity'], payload['filters'], payload['fields'], payload['order'], payload['filter_operator'], payload['limit'], payload['retired_only'])
elif method == 'find_one':
  result = sg.find_one(payload['entity'], payload['filters'], payload['fields'], payload['order'], payload['filter_operator'])
elif method == 'create':
  result = sg.create(payload['entity'], payload['data'])
elif method == 'update':
  result = sg.update(payload['entity'], payload['id'], payload['data'])
elif method == 'delete':
  result = sg.delete(payload['entity'], payload['id'])
elif method == 'upload':
  result = sg.upload(payload['entity'], payload['id'], payload['path'], payload['field_name'], payload['display_name'])
elif method == 'upload_thumbnail':
  result = sg.upload_thumbnail(payload['entity'], payload['id'], payload['path'])
elif method == 'schema_field_read':
  result = sg.schema_field_read(payload['entity'])
elif method == 'schema_field_create':
  result = sg.schema_field_create(payload['entity'], payload['type'], payload['name'], payload['attrs'])
elif method == '_url_for_attachment_id':
Пример #21
0
             iw
         ) + ":height=" + str(
             fbh
         ) + ":t=max,drawtext=fontfile='" + wmfont + "': text=\'" + dstr + " | " + pn + " | SEQ=" + qn + " | SHOT=" + sn + " | " + imgn + " | " + "f %{eif\\:n+1\\:d}\': [email protected]: fontsize=" + ffs + ": x=10: y=(main_h-text_h)-10\" -pix_fmt yuv420p -vcodec h264 -g 30 -b:v 2000k -vprofile high -bf 0 -y \"" + rvid + "\""
 #print '\n'
 print "fcmd = %s" % fcmd
 fret = subprocess.call(fcmd, shell=True)
 fret = 1
 if fret == 0:
     # shotgun...
     # override username for offsite testing:
     #un = "cpb"
     filters = [
         ['name', 'is', pn],
     ]
     p = sg.find_one('Project', filters)
     if p != None:
         pid = p['id']
         #print "local login user is %s" % un
         filters = [
             ['name', 'is', un],
         ]
         u = sg.find_one('HumanUser', filters)
         if u != None:
             uid = u['id']
             #print "user = %s, sg_humanuser = %s, sg_uid = %s" % (un, u, uid)
             filters = [[
                 'project', 'is', {
                     'type': 'Project',
                     'id': pid
                 }
Пример #22
0
class DBase(object):
    """Wrapper for database, currently it's Shotgun"""



    def __init__(self):

        sgSite = 'https://chimneypot.shotgunstudio.com'
        scriptName = 'dBase'
        scriptKey = '729a76955455909c79f6d90262bb9fbe9186b92b'

        self.db = Shotgun(sgSite, scriptName, scriptKey)
        
        
    def getProjectsDict(self, status='Active', owner='kiev'):
        
        filters = [ ['sg_status', 'is', status],
                ['sg_project_owner', 'is', owner]
                ]
        fields = ['name', 'id']
        projectsListRaw = self.db.find("Project", filters, fields)
        projectDict = {x['name']:x['id'] for x in projectsListRaw}

        return projectDict

    def getSequencesDict(self, projId):

        filters = [['project','is',{'type':'Project','id':projId}]]
        fields = ['code', 'id']
        sequencesListRaw = self.db.find("Sequence", filters, fields)
        sequencesDict = {x['code']:x['id'] for x in sequencesListRaw}

        return sequencesDict
    
    def getShots(self, seqId):

        filters = [['sg_sequence','is',{'type':'Sequence','id':seqId}]]
        fields = ['code', 'id']
        sequencesListRaw = self.db.find("Shot", filters, fields)
        sequencesDict = {x['code']:x['id'] for x in sequencesListRaw}

        return sequencesDict    

    def addProject(self, projName, status='Active', owner='kiev'):

        data = {
            'name': projName,
            'sg_status': status,
            'sg_project_owner': owner
            }

        newProj = self.db.create('Project', data)

        return newProj

    def addSequence(self, seqName, projId):

        data = {
            'project': {'type': 'Project', 'id': projId},
            'code': seqName
            }

        newSeq = self.db.create('Sequence', data)

        return newSeq

    def addShot(self, shName, seqId, projId):

        data = {
            'project': {'type': 'Project', 'id': projId},
            'sg_sequence': {'type': 'Sequence', 'id': seqId},
            'code': shName
            }

        newSh = self.db.create('Shot', data)

        return newSh       



    def getProject(self, projId):
        
        filters = [['id', 'is', projId]]
        fields = ['name']
        proj = self.db.find_one("Project", filters, fields)

        return proj

    def getSequence(self, seqId):
        
        filters = [['id', 'is', seqId]]
        fields = ['code', 'project', 'shots']
        seq = self.db.find_one("Sequence", filters, fields)

        return seq

    def getShot(self, shId):

        filters = [['id', 'is', shId]]
        fields = ['code', 'project', 'sg_sequence', 'tasks']
        sh = self.db.find_one("Shot", filters, fields)

        return sh
class PublishMayaAudio(QWidget):
    def __init__(self, defaultSource = 'I:/lsapipeline/audios/', parent = None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('Audio Publishing Tool')
        self.parent = parent
        ## Connect to shotgun
    
        from shotgun_api3 import Shotgun

        ## Instance the api for talking directly to shotgun. 
        base_url    = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'audioUploader'
        api_key     = 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'
        
        self.sgsrv = Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii=True, connect=True)
        
        ## Get the user name
        self.user = getpass.getuser()

        ## Define the variable for the source folder and destination folder (local and remote as it were)
        self.sourceFolder = defaultSource or ''
        self.fileBoxes = {}
        
        ## Build the UI
        self.mainLayout = QVBoxLayout(self)
        
        self.epNumLayout = QHBoxLayout()
        self.epNumLabel = QLabel('EpNum:')
        self.epNumber = QLineEdit('', self)
        self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
        self.epNumber.textChanged.connect(self.epTextChange)   
        self.epNumber.setText('ep')
        
        self.epNumLayout.addWidget(self.epNumLabel)
        self.epNumLayout.addWidget(self.epNumber)

        ## Set the layout for the source text input and browse button        
        self.pathLayout = QHBoxLayout(self)
        self.sourceLabel = QLabel('Set Src Path:')
        ## Define the widgets for this layout
        self.sourceInput = QLineEdit(self)
        if self.sourceFolder:
            self.sourceInput.setText(self.sourceFolder)
        self.sourceInput.textChanged.connect(partial(self.doFileCheckboxes))
        self.browseButton = QPushButton('Browse')
        self.browseButton.released.connect(partial(self._browseDialog, dest = False))
        ## Add the widgets to the layout
        self.pathLayout.addWidget(self.sourceLabel)
        self.pathLayout.addWidget(self.sourceInput)       
        self.pathLayout.addWidget(self.browseButton)        
        
        self.optionsLayout = QHBoxLayout(self)
        self.makeSGEntries = QCheckBox(self)
        self.makeSGEntries.setChecked(True)
        self.makeSGEntries.setText('Make SGun Entries?')
        
        self.goButton = QPushButton('Publish Audio Files')
        self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')   
        self.goButton.clicked.connect(self._doit)
        
        self.optionsLayout.addWidget(self.makeSGEntries)
        self.optionsLayout.addWidget(self.goButton)
        
        self.split = HR.Widget_hr()
        self.mainLayout.addWidget(self.split)

        self.mainLayout.addLayout(self.epNumLayout)
        self.mainLayout.addLayout(self.pathLayout)
        self.mainLayout.addLayout(self.optionsLayout)
        
        ### Now do the check boxes for files....
        self.scrollLayout = QScrollArea(self)
        self.scrollLayout.setMinimumHeight(300)
        
        self.filesGroupBox = QGroupBox(self.scrollLayout)
        self.filesGroupBox.setFlat(True)
        
        self.scrollLayout.setWidget(self.filesGroupBox)
        self.scrollLayout.setWidgetResizable(True)
        
        self.fileLayout = QGridLayout(self.filesGroupBox)
        self.mainLayout.addWidget(self.scrollLayout)

    def epTextChange(self):
        if len(self.epNumber.text()) > 5:
            self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)
        elif self.epNumber.text() != 'ep' and len(self.epNumber.text()) == 5:
            self.epNumber.setStyleSheet('QLineEdit {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('Publish Audio Files')
            self.goButton.setEnabled(True)
        else:
            self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)

    def _toggleAll(self):
        """
        A quick toggle for all the type checkboxes to on or off
        """
        for eachType in self.fileBoxes:
            if eachType.text() == 'ALL':
                if eachType.isChecked():
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(True)
                else:
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(False)
                
    def doFileCheckboxes(self, myPath = ''):
        """
        Process all the folders/files found into check boxes for processing
        """ 
        ## try to get the epNumber from a file
        epNum = os.listdir(self.sourceInput.text())[0].split('_')[0]
        if epNum:
            self.epNumber.setText(epNum)
            
        if self.fileBoxes != {}:
            for key, var in self.fileBoxes.items():
                key.setParent(None)
                sip.delete(key)
                key = None
        
        self.repaint()
        self.files      = []
        self.fileBoxes  = {}
       
        ## First add the ALL checkbox
        self.ALL = QCheckBox(self)
        self.ALL.setChecked(False)
        self.ALL.setText('ALL') 
        self.ALL.toggled.connect(self._toggleAll)
        
        self.fileBoxes[self.ALL] =  None
        self.fileLayout.addWidget(self.ALL, 0, 0)
        
        self.colCount = 10
        r = 1
        c = 1
        
        ## Now process the folder and add the folders found as check boxes.
        try:
            ## Scan the entire folder structure for audio files to publish
            if self.isRootFolderThere(rootFolder = self.sourceFolder):
                print '%s found processing now...' % self.sourceFolder
                for dirname, dirnames, filenames in os.walk(self.sourceFolder):
                    if dirname.endswith('\\wav'):
                        print  'Scanning %s now..' % dirname
                        print 'Files: %s' % os.listdir(dirname)
                        getMaxFile = max(os.listdir(dirname))
                        if getMaxFile: ## we have a folder with files in it...
                            if getMaxFile.endswith(".wav"):
                                pathToWav = os.path.join(dirname, getMaxFile)
                                self.fileCheckBox = QCheckBox(self)
                                self.fileCheckBox.setChecked(False)
                                self.fileCheckBox.setText(getMaxFile)
                                self.fileBoxes[self.fileCheckBox] = pathToWav.replace('\\', '/')
                                 
                                if c == self.colCount:
                                    r = r + 1
                                    c = 1
                                self.fileLayout.addWidget(self.fileCheckBox, r, c)
                                c = c + 1
                                print 'Adding %s to layout now..' % pathToWav
                        else:
                            print '%s is emtpy...' % dirname
            else:
                self.files =  ['No root folder found...']
        except:
            self.files =  ['No wav files found...']

    def _browseDialog(self, dest = False):
        """
        This opens up a QFileDialog hard set to browse into the assets folder by default. 
        @param dest: To set if you are setting the destination input or the source input
        @type dest: Boolean 
        """

        if sys.platform == 'win32':
            print 'OPENING WIN BROWSE DIALOG NOW...'
            myPath = QFileDialog(self, 'rootDir', self.sourceFolder).getExistingDirectory().replace('\\', '/')
        else:
            print 'OPENING %s BROWSE DIALOG NOW...' % sys.platform
            myPath = QFileDialog(self, 'rootDir', self.sourceFolder).getExistingDirectory().replace('\\', '/')

        ## try to get the epNumber from a file
        epNum = os.listdir(myPath)[0].split('_')[0]
        
        if epNum:
            self.epNumber.setText(epNum)
        
        self.sourceFolder = str(myPath)

        os.system('echo epNum: %s' % self.epNumber)
        os.system('echo sourceFolder: %s' % self.sourceFolder)
        os.system('echo final myPath: %s' % myPath)
        self.sourceInput.setText(myPath)
        
        #self.doFileCheckboxes(myPath)
        
            
                 
    def _versionUp(self, path):
        return int(max(os.listdir(path)).split('.v')[-1].split('.wav')[0]) + 1 
    
    def _writeMaFile(self, fileName, pathToWav, wavName, publishPath):
        ## Check the folder exists, if not make one now.
        if not os.path.isdir(os.path.dirname(self.publishPath)):
            os.makedirs(os.path.dirname(self.publishPath))
        
        self.header = [
        r'//Maya ASCII 2013ff10 scene',
        r'//Name: %s' % fileName,
        r'//Last modified: Tue, Jun 17, 2014 10:41:32 AM',
        r'//Codeset: 1252',
        r'requires maya "2013ff10";',
        r'requires "Mayatomr" "2013.0 - 3.10.1.11 ";',
        r'currentUnit -l centimeter -a degree -t film;',
        r'fileInfo "application" "maya";',
        r'fileInfo "product" "Maya 2013";',
        r'fileInfo "version" "2013 x64";',
        r'fileInfo "cutIdentifier" "201301140020-856945";',
        r'fileInfo "osv" "Microsoft Windows 7 Ultimate Edition, 64-bit Windows 7 Service Pack 1 (Build 7601)\n";',
        ]
        
        self.audioNode = [
                        '\n%s' % r'createNode audio -n "%s";' % wavName.replace('.', '_'),
                            '\t%s' % r'setAttr ".ef" 1000;',
                            '\t%s' % r'setAttr ".se" 1000;',
                            '\t%s' % r'setAttr ".f" -type "string" "%s";' % pathToWav,
                          ]
        
        self.footer = [
                       '\n%s' % r'// End of %s.ma' % fileName]
        
        ## Now write the ma file
        ## Fail if the version already exists
        pathToTextFile = publishPath
        if not os.path.isfile(pathToTextFile):
            outfile = open(pathToTextFile, "w")
            for eachLine in self.header:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.audioNode:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.footer:
                outfile.write('%s\n' % eachLine)
            
            outfile.close()
        else:
            ## Remove it because we are republishing the same version again.
            os.remove(pathToTextFile)
            ## Note we can just delete this file already and move on if needed.
            outfile = open(pathToTextFile, "w")
            for eachLine in self.header:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.audioNode:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.footer:
                outfile.write('%s\n' % eachLine)
            
            outfile.close()
    
    def _createPublish(self, publishPath, fileName, pathToWav, wavName, version_number, localPath, localPathMac, wavSGName, ctx):
        self.pathToWav      = pathToWav
        self.publishPath    = publishPath
        self.localPath      = localPath
        self.localPathMac   = localPathMac
        self.fileName       = fileName
        self.wavName        = wavName
        self.wavSGName      = wavSGName
        self.version_number = version_number


        data = {
                "code"          : self.wavSGName,
                "description"   : None,
                "name"          : self.wavSGName,
                "project"       : ctx.project,
                "entity"        : {'id': self.exists['id'], 'name': self.wavSGName, 'type': 'CustomEntity03'},
                "version_number": self.version_number,
                'path_cache'    : self.publishPath.replace('/', '\\'),
                'published_file_type' : {'type' : 'PublishedFileType', 'id': 1},
                'updated_by'    : {
                               'type' : 'HumanUser', 'id' : 53
                               },
                'path'         : {
                              'content_type': None,
                              'link_type': 'local',
                              'url': 'file:///%s' % self.publishPath.replace('/', '\\'),
                              "local_path": self.publishPath.replace('/', '\\'),
                              'local_path_linux': '',
                              'local_path_mac': '%s' % self.localPathMac,
                              'local_path_windows': '%s' % self.publishPath.replace('/', '\\'),
                              'local_storage': {'id': 1, 'name': 'primary', 'type': 'LocalStorage'},
                              'name': self.fileName,
                                }
                }
        
        self.sgsrv.create('PublishedFile', data)
        print 'Publish file created for %s' % self.wavSGName
    
    def _publishAudio(self):
        """
        Function to add the publish a maya audio file both making a maya file with an audio node and publishing this to shotgun as a version
        """
        for key, var in self.fileBoxes.items():
            if var:
                if key.isChecked():
                    ## Work out what we need for the creation of the ma file 
                    ## and the publish for shotgun
                    self.pathToWav      = var
                    if sys.platform == 'win32':
                        self.publishPath = var.replace('/publish/wav', '/publish/maya').replace('.wav', '.ma').replace('/', '\\')
                    self.localPath      = self.publishPath.split('I:')[-1]
                    self.localPathMac   = self.publishPath.replace('I:', '/_projects')
                    self.fileName       = str(key.text()).replace('.wav', '.ma')
                    self.wavName        = str(key.text())
                    self.wavSGName      = str(key.text().replace('_AUD', '').split('.')[0])
                    self.version_number = int(str(key.text()).split('.')[-2].split('v')[-1])
                    
                    ## Now register the publish with Shotgun
                    ## First find the audio on shotgun for processing. 
                    self.exists         =  self.sgsrv.find_one('CustomEntity03',  filters = [["code", "is", self.wavSGName]], fields=['code', 'tasks', 'id'])

                    if not self.exists:
                        print '%s has no shotgun entry! You should make sure this has been processed correctly before proceeding!!' % self.wavName

                    else:
                        ## now publish
                        tk = sgtk.sgtk_from_path("I:/lsapipeline/")
                        ctx = tk.context_from_path(self.publishPath)
                        
                        ## For existing check
                        ## CHECK FOR EXISTING PUBLISH WITH THE SAME VERSION NUMBER!!!!
                        findExisting = self.sgsrv.find_one('PublishedFile', filters = [["code", "is", self.wavSGName]], fields=['code', 'id', 'version_number', 'created_at', 'entity'])
                        if findExisting:
                            if findExisting['version_number'] == self.version_number:
                                print 'A PUBLISHED FILE FOR THIS VERSION ALREADY EXISTS SKIPPING! VERSION UP OR DELETE EXISTING SHOTGUN PUBLISH ENTRIES IF YOU NEED TO YOU SHOULDNT BUT YOU MIGHT!'
                                ## WRITE THE MA
                                ## Now write the ma file we are going to publish with the audio node created.
                                ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                                self._writeMaFile(self.fileName, self.pathToWav, self.wavName, self.publishPath)
                            else:## This is a new version number
                                ## WRITE THE MA
                                ## Now write the ma file we are going to publish with the audio node created.
                                ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                                self._writeMaFile(self.fileName, self.pathToWav, self.wavName, self.publishPath)
                                self._createPublish(publishPath = self.publishPath, fileName = self.fileName, pathToWav = self.pathToWav, wavName = self.wavName, version_number = self.version_number,
                                               localPath = self.localPath, localPathMac = self.localPathMac, wavSGName = self.wavSGName, ctx = ctx)
                        else:## nothing already exists so build a fresh publish
                            ## WRITE THE MA
                            ## Now write the ma file we are going to publish with the audio node created.
                            ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                            self._writeMaFile(self.fileName, self.pathToWav, self.wavName, self.publishPath)
                            self._createPublish(publishPath = self.publishPath, fileName = self.fileName, pathToWav = self.pathToWav, wavName = self.wavName, version_number = self.version_number,
                                           localPath = self.localPath, localPathMac = self.localPathMac, wavSGName = self.wavSGName, ctx = ctx)
                        
        print 'Complete'
        self.goButton.setText('COMPLETE.. click to run again')
        self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')
        self.repaint()
        
    def _checkTypes(self):
        anythingChecked = False
        if self.fileBoxes:
            for each in self.fileBoxes:
                if each.isChecked():
                    anythingChecked = True
        return anythingChecked

    def _setINPROG(self):
        self.goButton.setText('IN PROGRESS...')
        self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
        self.repaint()
        return True
        
    def _doit(self):
        if self._setINPROG():
            if not self._checkTypes():
                self.goButton.setText('OOPS..')
                self.goButton.setStyleSheet('QPushButton {background-color: darkred; border: 2px solid 1 ; border-radius: 6px;}')
                self.reply = QMessageBox.question(self, 'Nope!', "Nothing to transfer. Try selecting something and try again", QMessageBox.Ok)
            else:
                self._publishAudio()

    def isRootFolderThere(self, rootFolder):
        """
        Method used to check if root folder is valid or not
        """
        if not os.path.isdir(rootFolder):
            print 'No such root folder found.'
            return -1
        else:
            return 1
Пример #24
0
sg = Shotgun(url, script_name, key)

filename = "Z:/Groupes-cours/NAND999-A15-N01/Nature/assets/mod/.thumb/banc_02_full.jpg"
result = sg.upload("Version",1048,filename,"sg_uploaded_movie")




my_local_file = {
    'attachment_links': [{'type':'Version','id':1048}],
    'project': {'type':'Project','id':146}
    }


asset = sg.find_one("Asset", [["code","is","afficheOeuvre"]], ["code"])

sg_user = sg.find_one('HumanUser', [['login', 'is', "houdon.thibault"]])
data = {
    'project': {'type':'Project','id':project_id},
    'note_links': [asset],
    'user': sg_user,
    'content':'Test',
    'subject':"Thibault's Note on afficheOeuvre"
    }

sg.create("Note", data)

#version = sg.create("Version", data)

Пример #25
0
class genericUtils:
    def __init__(self):
        self.sg = Shotgun('https://' + URL,name,API)

    def getFields (self, entity):
        '''get the fields for a type/entity as a list so we can pass it as an arg easily
        this is used all the time to make sure we get all the fields that we may ever need for a type/entity
        '''
        allFields = []
        fields = self.sg.schema_field_read(entity)
        for field in fields:
            allFields.append(field)
        return allFields  
    
    def project (self, project):
        '''Gets the Shotgun project name and ID
        '''
        retFields = self.getFields('Project')
        project = project.replace('_', ' ')
        return self.sg.find_one("Project", [["name", "is", project]], retFields )   

    def sequence (self, project, sequence):
        '''Returns the shotgun sequence name and ID 
        Parameters : (project, sequence)
        '''
        retFields = self.getFields('Sequence')
        return self.sg.find_one("Sequence", [["code", "is", sequence],['project','is',project]], retFields)
    
    def shot (self, project, shot):
        '''Returns the shotgun shot name and ID 
        Parameters : (project, shot)
        '''        
        retFields = self.getFields('Shot')
        return self.sg.find_one('Shot',[['code','is',shot],['project','is',project]],retFields)
    
    def createProject (self, project):
        '''Creates a project in Shotgun given a project name
        Parameters : (project)
        '''        
        filters = [['code','is','a']]
        template = self.sg.find_one('Project',[['name','is','a']],['layout_project','id'])
        data = {'name':project,
                'layout_project': template
                }
        return self.sg.create('Project',data)
    
    def createSequence (self, project, sequence):
        '''Creates a sequence in shotgun given 
        Parameters : (project, sequence)
        '''        
        data = {'project': {"type":"Project","id": project['id']},
                 'code': sequence}
        return self.sg.create('Sequence', data)
    
    def createShot (self, project, shot, seq='', taskTemplateName=''):
        '''Creates a sequence in shotgun given 
        Parameters : (project, shot, seq='', taskTemplateName='Basic shot template'
        '''          
        filters = [['code','is',taskTemplateName ]]
        template = self.sg.find_one('TaskTemplate',filters)
    
        data = { 'project': {"type":"Project","id": project['id']},
                 'code': shot,
                 'task_template' : template,
                 'description': '',
                 'self.sg_sequence': seq,
                 'self.sg_status_list': 'wtg' }
        result = self.sg.create('Shot', data)
        return result
    
    def notesFind (self, shotID):
        '''Find all notes on a shot 
        Parameters : (shotID)
        Output : Note data :
        ['tasks', 'attachments', 'updated_at', 'replies', 'id', 'subject', 'playlist', '
        addressings_to', 'created_by', 'content', 'sg_status_list', 'reply_content', 
        'updated_by', 'addressings_cc', 'read_by_current_user', 'user', 'note_links', 
        'created_at', 'sg_note_from', 'project', 'sg_note_type', 'tag_list']        
        '''
        note = self.sg.find('Note',[['note_links','is', shotID]],['subject','content', 'created_at'],[{'field_name':'created_at','direction':'desc'}])
        return note
    
    def notesFindLatest (self, shotID):
        '''Find the latest note on a shot
        Parameters : (shotID)
        Call with notesFindLatest(shot)['content'] for the note content only
        Output : Note data:
        ['tasks', 'attachments', 'updated_at', 'replies', 'id', 'subject', 'playlist', '
        addressings_to', 'created_by', 'content', 'sg_status_list', 'reply_content', 
        'updated_by', 'addressings_cc', 'read_by_current_user', 'user', 'note_links', 
        'created_at', 'sg_note_from', 'project', 'sg_note_type', 'tag_list']        
        '''
        note = self.notesFind(shotID)[0]
        return note
    
    
    def notesCreate(self, project, shotID, subject, content):
        '''Create a note for a shot given
        Parameters : (project, shotID, subject, content)
        Output : noteID
        '''
        # enter data here for a note to create
        data = {'subject':subject,'content':content,'note_links':[shotID],'project':project}
        # create the note
        noteID = self.sg.create('Note',data)
        return noteID
    
    def versionCreate(self, project, shot, verName, description, framePath, firstFrame, lastFrame, clientName=None, sourceFile=None, task=None, user=None, final=False, makeThumb=False, makeThumbShot=False):
        '''Create a version
        Parameters : (project, shotID, verName, description, framePath, firstFrame, lastFrame, clientName=None, sourceFile=None, task=None)
        Output : versionID
        '''
          
        data = {'project': project,
                'code': verName,
                'description': description,
                'sg_path_to_frames': framePath,
                #'sg_frame_range': str(firstFrame) + '-' + str(lastFrame),
                'sg_first_frame' : int(firstFrame),
                'sg_last_frame' : int(lastFrame),
                'sg_status_list': 'rev',
                'entity': shot}
        #if user != None:
            #data['user']
        if task != None:
            filters = [['content','is',task],['entity','is',shot]]
            taskID = self.sg.find_one('Task',filters)  
            data['sg_task']=taskID
        #if final == True and 'send
        # in case we're putting a client version in here we need this code.
        # we are expecting a field called self.sg_client_name in the version table.
        # please make sure you create this in the shotgun setup
        # read the schema and if the client_name is not found, create it.
        '''
        versionFields = self.sg.schema_field_read('Version')
        if 'sg_client_name' not in versionFields and clientName != None:
            newField = self.sg.schema_field_create('Version','text','Client Name')
        if clientName != None :
            data['sg_client_name'] =  clientName
    
        #'user': {'type':'HumanUser', 'id':165} }
        # here we need to create a field for storing the source file that created this version.
        # if it's not there, create the field, and if it's there just update it.
        
        if 'sg_source_file' not in versionFields and sourceFile != None:
            newField = self.sg.schema_field_create('Version','text','Source File')
        if sourceFile != None:
            data['sg_source_file'] = sourceFile
        '''
        
        versionData = self.sg.create('Version',data)
        # handle the thumbnail grabbing here
        middleFrame = (int(firstFrame) + int(lastFrame)) / 2
        padding, padString = fxpipe.framePad(framePath)
        paddedFrame = padString % (middleFrame)
        if makeThumb == True:
            thumbData = self.sg.upload_thumbnail('Version', versionData['id'], framePath.replace(padding,paddedFrame))
        if makeThumbShot == True:
            thumbData = self.sg.upload_thumbnail('Shot', shot['id'], framePath.replace(padding,paddedFrame))   
        return versionData      

   
    #add a task version to the system
    def versionCreateTask(self, project, shot, verName, description, framePath, firstFrame, lastFrame, task, sourceFile = ''):
        '''
        DEPRECATED : USE versionCreate instead with the task='TASKNAME'
        Parameters : (project, shot, verName, description, framePath, firstFrame, lastFrame, task, sourceFile = '')
        Output : Version ID
        '''
        filters = [['content','is',task],['entity','is',shot]]
        taskID = self.sg.find_one('Task',filters)
        data = {'project': project,
                'code': verName,
                'description': description,
                'self.sg_path_to_frames': framePath,
                'frame_range': str(firstFrame) + '-' + str(lastFrame),
                'self.sg_first_frame' : firstFrame,
                'self.sg_last_frame' : lastFrame,
                #'self.sg_uploaded_movie': '/Users/throb/Downloads/test.m4v',
                #'self.sg_first_frame': 1,
                #'self.sg_last_frame': 100,
                'self.sg_status_list': 'rev',
                'self.sg_task': taskID,
    
                'entity': shot}
        # here we need to create a field for storing the source file that created this version.
        # if it's not there, create the field, and if it's there just update it.
        try:
            tmp2 = {}
            tmp2 = tmp['self.sg_source_file']
        except:
            newField = self.sg.schema_field_create('Version','text','Source File')
        if sourceFile != '':
            data['self.sg_source_file'] = sourceFile
    
        return self.sg.create('Version',data)
    # look for specific version
    def versionFind(self, versionID):
        '''Find all versions in a shot with most recent first
        Parameters : (shotID)
        Output : Version data:
        ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
        'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
        'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
        'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
        'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
        'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
        'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
        'filmstrip_image', 'tag_list', 'frame_count', 'flagged']        
        '''        
        retFields = self.getFields('Version')
        return self.sg.find('Version',[['id','is',versionID]],retFields,[{'field_name':'created_at','direction':'desc'}])[0]
    
    # look for versions in a shot:
    def versionFindShot(self, shotID):
        '''Find all versions in a shot with most recent first
        Parameters : (shotID)
        Output : Version data:
        ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
        'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
        'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
        'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
        'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
        'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
        'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
        'filmstrip_image', 'tag_list', 'frame_count', 'flagged']        
        '''        
        retFields = self.getFields('Version')
        return self.sg.find('Version',[['entity','is',shotID]],retFields,[{'field_name':'created_at','direction':'desc'}])
    
    def versionFindLatest(self, shotID):
        '''Find only the most recent version
        Parameters : (shotID)
        Output : Version data:
        ['sg_version_type', 'open_notes_count', 'code', 'playlists', 'sg_task', 'image',
        'updated_at', 'sg_output', 'sg_path_to_frames', 'tasks', 'frame_range', 'id', 
        'description', 'sg_uploaded_movie_webm', 'open_notes', 'tank_published_file', 
        'task_template', 'created_by', 'sg_movie_type', 'sg_status_list', 'notes', 
        'sg_client_name', 'sg_uploaded_movie_mp4', 'updated_by', 'sg_send_for_final', 
        'user', 'sg_uploaded_movie_frame_rate', 'entity', 'step_0', 'sg_client_version', 
        'sg_uploaded_movie_transcoding_status', 'created_at', 'sg_qt', 'project', 
        'filmstrip_image', 'tag_list', 'frame_count', 'flagged']         
        '''
        retFields = self.getFields('Version')
        return self.sg.find_one('Version',[['entity','is',shotID]],retFields,[{'field_name':'created_at','direction':'desc'}])
    
    # search for the latest task given shotID and task info
    def versionFindLatestTask(self, shotID, task):
        retFields = self.getFields('Version')
        # first look for the task and get the ID
        filters = [['content','is',task],['entity','is',shotID]]
        taskID = self.sg.find_one('Task',filters)
        # then look for the latest
        #version using the task ID.  note that we need to use the [0] or else we're sending the array versus the hash
        versionLatest = self.sg.find_one('Version',[['entity','is',shotID],['self.sg_task','is',taskID]],retFields,[{'field_name':'created_at','direction':'desc'}])
        return versionLatest
    
    ## The following requires a field called "client_version" be added to shotgun
    def versionClientUpdate (self, shotID, version, clientVersionName ='Client Version'):
        '''This takes the shotID and version (int) and updates the shot with this client version number
        Sometimes the client wants to see different version numbers versus the internal ones.  This option allows for it.
        You will need to create a field.  Client Version is what I have used but you can specify what you want here.
        Parameters: (shotID, version, clientVersionName ='Client Version')
        Output : Version data
        '''
        sgFieldName = 'sg_' + clientVersionName.lower().replace(' ','_')
        data = { sgFieldName: version}
        try:
            result = self.sg.update('Shot', shotID['id'], data)
        except:
            newField = self.sg.schema_field_create('Shot', 'number', clientVersionName)
            result = self.sg.update('Shot', shotID['id'], data)
        return result
    

    def uploadQT (self, entityType, item, path):
        '''Upload a file to shotgun in the 'self.sg_qt' field.
        If you do this for a shot, you will need to add this to a field
        the field should be called 'qt' as shotgun will add the self.sg_ to it
        Shotgun provides the self.sg_qt for versions automatically
        Parameters: (entity,item,path)
        uploadQT ('Version',versionData, '/my/file.mov')
        '''
        # Make sure first letter is capitalized
        entity = entityType.capitalize()

        # upload that mother
        if entity.lower() == 'shot':
            try:
                result = self.sg.upload (entity, item['id'], path,'sg_qt')
            except:
                newField = self.sg.schema_field_create('Shot', 'url', 'QT')
                result = self.sg.upload (entity, item['id'], path,'sg_qt')
    
        elif entity.lower() == 'version':
            result = self.sg.upload (entity, item['id'], path,'sg_uploaded_movie')
        return result
    
 
    def versionClientGet (self, shotID, clientVersion='Client Version'):
        '''Get latest client version number
        Parameters : (hotID, clientVersion='Client Version')
        Output : Version data
        '''        
        sgFieldName = 'sg_' + clientVersionName.lower().replace(' ','_')
        try :
            currentVersion = shotID[sgFieldName]
        except :
            currentVersion = 0
        if currentVersion == None:
            return 0
        return currentVersion
    
    def playlistFind (self, project, playlistName):
        '''Search for a playlist given a project and name
        Parameters : (project, playlistName)
        Output : playlist data:
        ['code', 'description', 'versions', 'created_at', 'sg_cinesync_session_url', 
        'updated_at', 'created_by', 'project', 'filmstrip_image', 'notes', 'image', 
        'updated_by', 'sg_cinesync_session_key', 'sg_status', 'tag_list', 'id', 
        'sg_date_and_time']        
        '''        
        retFields = self.getFields('Playlist')
        return self.sg.find_one('Playlist',[['code','is',playlistName],['project','is',project]],retFields)
    
    def playlistCreate (self, project, playlistName, playlistDescription=''):
        '''Create a playlist given a playlist name
        Parameters : (project, playlistName, playlistDescription='')
        Output : playlist data
        '''        
        data = {'project':project,'code':playlistName, 'description':playlistDescription}
        return self.sg.create('Playlist',data)
    
    # Add a version to a playlist
    def playlistAddVersion (self, project, playlistName, version):
        '''
        Description :\n
        This adds a version (existing version in the system) to a playlist.\n
        You need to give it: (in order)\r
        shotgun connection class\r
        project (dict of the project info including name and id)\r
        playlist name (string of the name of the playlist)\r
        version (dict of the version you wish to add\n
        It will return with a dict of the playlist
        '''
    
        my_playlist_list = self.sg.find_one('Playlist',[['code','is',playlistName],['project','is',project]],['versions']);
        if len(my_playlist_list):
            ver_list = my_playlist_list['versions'];
            ver_list.append({'type':'Version','name':version['code'],'id':version['id']})
            result = self.sg.update('Playlist', my_playlist_list['id'], {'versions' : ver_list})
            return result
    
    def playlistInfo (self, project, playlistName):
        '''Get playlist info (eg version name and description)
        Parameters : (project, playlistName)
        Output : version data
        '''        
        data = []
        versionData = []
        retFields = self.getFields('Version')
        for versionInPlaylist in self.sg.find_one('Playlist',[['code','is',playlistName],['project','is',project]],['versions'])['versions']:
            data.append (self.sg.find_one('Version',[['id','is',versionInPlaylist['id']]],retFields))
        #for items in data:
         #   versionData.append({'name':items['code'],'desc':items['description'],'first_frame':items['self.sg_first_frame})
        return data        
    
    def getTimeShot(self, shot):
        '''Given shot (as dict) return total time on shot as [0] and other times for each task on shot
        '''
        outputData = []
        retFields = ['content','time_logs_sum']
        totalTime = 0
        for curTask in shot['tasks']:
            taskData = self.sg.find_one('Task',[['id','is',curTask['id']]],fields=retFields)
            totalTime += taskData['time_logs_sum']
            outputData.append({'name':taskData['content'],'time':taskData['time_logs_sum']})
        outputData.insert(0,{'name':shot['code'],'time':totalTime})
        return outputData
Пример #26
0
# filename = 'file:///Users/mmontagnino/Desktop/python-api-master/fullcalendar-2.8.0/demos/' + 'Calendar.html'
id = "d54c59d248f978ad103976c2b47875b06df5dc56c71afa774901d7791d9d9870"
name = "Test_Calendar"
srvr = "https://participant.shotgunstudio.com"

sg = Shotgun(srvr, name, id)

colors = {
    "Helen Ly": "red",
    "Rafiah Sessoms": "blue",
    "Nathaniel Bryan": "green",
    "Nick Kubinski": "purple",
    "Marian Montagnino": "cyan",
}

proj = sg.find_one("Project", [["name", "is", "Asset Pipeline"]])
print proj

filters = [["project", "is", proj], ["sg_status_list", "is", "wtg"]]
fields = [
    "entity.Shot.sg_sequence.Sequence.code",
    "entity.Shot.sg_air_date",
    "entity.Shot.code",
    "content",
    "task_assignees",
    "sg_task_order",
    "Id",
    # 	    'created_at',
    "entity.Shot.sg_status_list",
    # 	    'content',
    "start_date",
Пример #27
0
def get_fact_data():
    ret = {}
    raw_facts = subprocess.Popen(["facter"], stdout=subprocess.PIPE).communicate()[0]
    for line in raw_facts.split("\n"):
        try: line.index("=>")
        except: continue
        #print "facter: %s" % line
        (key, value) = line.split("=>")
        #print "fkey: %s fvalue: %s" % ( key, value )
        ret[key.strip()] = value.strip()
    return ret

hostname = gethostname().split('.', 1)[0]

asset = sg.find_one("Asset",[['code','is',hostname]],['id'])
if not asset:
    print "couldn't find asset"
else:
    # if we find a valid asset, sync the facts for it
    fact_data = get_fact_data()

    for fact_name,fact_value in fact_data.items():
        if not fact_name in facts_to_sync: continue

        fact_data = {
            'code': fact_name,
            'sg_asset': {'type':'Asset', 'id':asset['id']},
            'description': fact_value,
            'project': {'type':'Project', 'id':178},
        }
Пример #28
0
ID = raw_input("Type the id of the %s:\n" % typeToUpload)
while validRequest == False:
    #Number Validation
    while validId == False:
        try:
            ID = int(ID)
            validId = True
        except:
            print "Invalid input, the id must be a Number"
            ID = raw_input("Type the CORRECT id of the Asset:\n")
    #Shotgun Validation

    shoot = {'id': ID, 'type': typeToUpload}
    filters = [['entity', 'is', shoot]]
    fields = ['code']
    versions = sg.find_one(typeToUpload, [["id", "is", ID]],
                           ["id", "code", "sg_status_list"])

    if versions == None:
        print "The ID doesnt exist in Shotgun"
        ID = raw_input("Type the CORRECT id of the Asset:\n")
        validId = False
    else:
        print "%s name: %s" % (typeToUpload, versions['code'])
        try:
            versions = sg.find("Version", filters, fields)
        except Exception as e:
            print e
        if len(versions) > 0:
            print "The %s have this versions already:\n" % typeToUpload
            for version in versions:
                print "  -%s" % version["code"]
Пример #29
0
from shotgun_api3 import Shotgun

if True:
    sg = connect()
else:
    sg = Shotgun('http://127.0.0.1:8020', 'name', 'key')

print sg.server_info


proj =  sg.create('Project', {'name': 'Mock Project Test'})
seq = sg.create('Sequence', {'code': 'AA', 'project': proj})
shot = sg.create('Shot', {'code': 'AA_001', 'sg_sequence': seq})

print proj
print seq
print shot
#
# print sg.find('Project', [('id', 'is_not', 0)], ['name'], order=[
#     {'field_name': 'id', 'direction': 'asc'},
# ])

print sg._call_rpc('count', None)
exit()

print sg.create('Project', {'name': 'Test Project'})
print sg.count()
print sg.find_one('Project', [], order=[
    {'field_name': 'id', 'direction': 'asc'},
], fields=['task_assignees'])
class StoryboardFileManagement(QWidget):
    def __init__(self, defaultSource='', parent=None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('StoryBoard File Processing')
        self.parent = parent
        ## Connect to shotgun

        from shotgun_api3 import Shotgun

        ## Instance the api for talking directly to shotgun.
        base_url = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'audioUploader'
        api_key = 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'

        print 'Connecting to shotgun....'
        self.sgsrv = Shotgun(base_url=base_url,
                             script_name=script_name,
                             api_key=api_key,
                             ensure_ascii=True,
                             connect=True)

        ## Get the user name
        self.user = getpass.getuser()

        ## Define the variable for the source folder and destination folder (local and remote as it were)
        self.sourceFolder = defaultSource or ''
        self.fileBoxes = []

        ## Build the UI
        self.mainLayout = QVBoxLayout(self)

        self.epNumLayout = QHBoxLayout()
        self.epNumLabel = QLabel('EpNum:')
        self.epNumber = QLineEdit('', self)
        self.epNumber.setStyleSheet(
            'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.epNumber.textChanged.connect(self.epTextChange)
        self.epNumber.setText('ep')

        self.epNumLayout.addWidget(self.epNumLabel)
        self.epNumLayout.addWidget(self.epNumber)

        ## Set the layout for the source text input and browse button
        self.pathLayout = QHBoxLayout(self)
        self.sourceLabel = QLabel('Set Src Path:')
        ## Define the widgets for this layout
        self.sourceInput = QLineEdit(self)
        self.sourceInput.textChanged.connect(self.doFileCheckboxes)
        self.browseButton = QPushButton('Browse')
        self.browseButton.released.connect(
            partial(self._browseDialog, dest=False))
        ## Add the widgets to the layout
        self.pathLayout.addWidget(self.sourceLabel)
        self.pathLayout.addWidget(self.sourceInput)
        self.pathLayout.addWidget(self.browseButton)

        self.optionsLayout = QHBoxLayout(self)
        self.makeSGEntries = QCheckBox(self)
        self.makeSGEntries.setChecked(True)
        self.makeSGEntries.setText('Make SGun Entries?')

        self.goButton = QPushButton(
            'Transfer SBrd Files To Episode Version Folders')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.goButton.clicked.connect(self._doit)

        self.optionsLayout.addWidget(self.makeSGEntries)
        self.optionsLayout.addWidget(self.goButton)

        self.split = HR.Widget_hr()
        self.mainLayout.addWidget(self.split)

        self.mainLayout.addLayout(self.epNumLayout)
        self.mainLayout.addLayout(self.pathLayout)
        self.mainLayout.addLayout(self.optionsLayout)

        ### Now do the check boxes for files....
        self.scrollLayout = QScrollArea(self)
        self.scrollLayout.setMinimumHeight(300)

        self.filesGroupBox = QGroupBox(self.scrollLayout)
        self.filesGroupBox.setFlat(True)

        self.scrollLayout.setWidget(self.filesGroupBox)
        self.scrollLayout.setWidgetResizable(True)

        self.fileLayout = QGridLayout(self.filesGroupBox)

        self.mainLayout.addWidget(self.scrollLayout)

    def epTextChange(self):
        if len(self.epNumber.text()) > 5:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)
        elif self.epNumber.text() != 'ep' and len(self.epNumber.text()) == 5:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText(
                'Transfer SBrd Files To Episode Version Folders')
            self.goButton.setEnabled(True)
        else:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)

    def _toggleAll(self):
        """
        A quick toggle for all the type checkboxes to on or off
        """
        for eachType in self.fileBoxes:
            if eachType.text() == 'ALL':
                if eachType.isChecked():
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(True)
                else:
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(False)

    def doFileCheckboxes(self, myPath=''):
        """
        Process all the folders/files found into checkboxes for processing
        """
        ## try to get the epNumber from a file
        epNum = str(os.listdir(self.sourceInput.text())[0].split('_')[0])
        if epNum == '.DS' or epNum == '.DS_Store':
            getFiles = os.listdir(self.sourceInput.text())
            for each in getFiles:
                if ".mov" in each:
                    epNum = each.split('_')[0]
        #print 'I AM A BAD NAUGHTY VARIABLE!: %s' % epNum

        if epNum:
            self.epNumber.setText(epNum)

        if self.fileBoxes != []:
            for each in self.fileBoxes:
                each.setParent(None)
                sip.delete(each)
                each = None

        self.files = []
        self.fileBoxes = []

        ## First add the ALL checkbox
        self.ALL = QCheckBox(self)
        self.ALL.setChecked(False)
        self.ALL.setText('ALL')
        self.ALL.toggled.connect(self._toggleAll)

        self.fileBoxes.append(self.ALL)
        self.fileLayout.addWidget(self.ALL, 0, 0)

        ## Now process the folder and add the folders found as checkboxes.
        try:
            if myPath:
                if sys.platform == 'win32':
                    self.sourceFolder = myPath.replace('/', '\\')
                else:
                    self.sourceFolder = myPath
            else:
                self.sourceFolder = str(self.sourceInput.text())

            for eachFile in os.listdir(self.sourceFolder):
                if eachFile.endswith('.mov'):
                    self.files.append(eachFile)
        except:
            self.files = ['No mov files found...']

        self.colCount = 10
        r = 1
        c = 1
        for eachType in sorted(self.files):
            self.fileCheckBox = QCheckBox(self)
            self.fileCheckBox.setChecked(False)
            self.fileCheckBox.setText(eachType)
            self.fileBoxes.append(self.fileCheckBox)
            if c == self.colCount:
                r = r + 1
                c = 1
            self.fileLayout.addWidget(self.fileCheckBox, r, c)
            c = c + 1

    def _browseDialog(self, dest=False):
        """
        This opens up a QFileDialog hard set to browse into the assets folder by default. 
        @param dest: To set if you are setting the destination input or the source input
        @type dest: Boolean 
        """
        try:
            if sys.platform == 'win32':
                myPath = QFileDialog(
                    self, 'rootDir',
                    'O:/EPISODE DELIVERY').getExistingDirectory().replace(
                        '\\', '/')
            else:
                myPath = QFileDialog(
                    self, 'rootDir',
                    '/Volumes/LemonSky/OUT TO LEMONSKY/EPISODE DELIVERY'
                ).getExistingDirectory().replace('\\', '/')
        except:
            myPath = QFileDialog(self, 'rootDir',
                                 '').getExistingDirectory().replace('\\', '/')

        ## try to get the epNumber from a file
        epNum = os.listdir(myPath)[0].split('_')[0]
        if epNum:
            self.epNumber.setText(epNum)
        self.sourceInput.setText(myPath)
        self.sourceFolder = str(myPath)
        self.doFileCheckboxes(myPath)

    def _versionUp(self, path):
        return int(max(os.listdir(path)).split('.v')[-1].split('.mov')[0]) + 1

    def addStoryboardVersionToShotgun(self, path, epName, shotName, verNum,
                                      fullVersPublishName):
        """
        Function to add the audio asset to shotgun correctly for tasks etc and the pipeline to see it
        """
        #self.shotNum = each.text().split('.mov')[0]
        #self.addStoryboardVersionToShotgun(str(self.shotReviewDir), str(self.epName), self.shotNum, self.vNum, self.shotReviewFileName)
        ## Now start processing stuff..
        self.epName = epName.lower()
        self.shotName = shotName.lower()
        self.boardName = fullVersPublishName.lower()
        self.taskName = 'StoryBoard'
        self.sg_version = verNum

        self.pathToMovie = '%s%s' % (path, self.boardName)

        ## First find it the task exists
        self.getShotTasks = self.sgsrv.find_one(
            'Shot',
            filters=[["code", "is", self.shotName]],
            fields=['id', 'tasks'])

        ## Now check and see if the task we need is there...
        self.tasks = []
        self.taskList = []
        if self.getShotTasks:
            for eachTaskDict in self.getShotTasks['tasks']:
                self.tasks.append(eachTaskDict['name'])
                self.taskList.append(eachTaskDict)

            if self.taskName not in self.tasks:
                ## Create new task for the shot
                self.myNewTask = self.sgsrv.create(
                    'Task', {
                        'project': {
                            'type': 'Project',
                            'id': 66
                        },
                        'step': {
                            'type': 'Step',
                            'id': 72,
                            'name': 'StoryBoard'
                        },
                        'content': 'StoryBoard',
                        'sg_status_list': 'apr',
                        'template_task': {
                            'type': 'Task',
                            'id': 31333
                        }
                    })
                self.taskId = int(self.myNewTask['id'])
                ## Returns {'project': {'type': 'Project', 'id': 66, 'name': 'bubblebathbay'}, 'step': {'type': 'Step', 'id': 72, 'name': 'StoryBoard'}, 'type': 'Task', 'id': 32335}

                ## Add this dict to the list of dict for updating the shot task list with.
                self.taskList.append({
                    'type': 'Task',
                    'id': self.myNewTask['id'],
                    'name': 'StoryBoard'
                })

                ## Now update the shots task list.
                self.sgsrv.update(
                    'Shot', self.getShotTasks['id'], {
                        'project': {
                            'type': 'Project',
                            'id': 66
                        },
                        'tasks': self.taskList
                    })
                print 'Successfully updated shot %s with task %s' % (
                    self.shotName, self.taskId)

                ## Now create a version for this
                print 'Adding version %s to %s now' % (self.boardName,
                                                       self.shotName)
                data = {
                    'project': {
                        'type': 'Project',
                        'id': 66
                    },
                    'code': self.boardName,
                    'description': 'I am not a fluffy bunny!',
                    'sg_path_to_movie': self.pathToMovie,
                    'sg_status_list': 'rev',
                    'entity': {
                        'type': 'Shot',
                        'id': self.getShotTasks['id']
                    },
                    'sg_task': {
                        'type': 'Task',
                        'id': self.taskId
                    },
                    'sg_status_list': 'vwd',
                    'user': {
                        'type': 'HumanUser',
                        'id': 53
                    }
                }
                result = self.sgsrv.create('Version', data)

                ## Now upload to shotgun
                print 'Uploading version %s to %s now' % (self.boardName,
                                                          self.shotName)
                result2 = self.sgsrv.upload("Version", result['id'],
                                            self.pathToMovie,
                                            "sg_uploaded_movie")
                self._turnOffCheckBox('%s.mov' % self.shotName)
            else:
                ## Get the story board task id
                for eachTask in self.taskList:
                    if eachTask['name'] == 'StoryBoard':
                        self.taskId = eachTask['id']

                ## Now create a version for this
                print 'Adding version %s to %s now' % (self.boardName,
                                                       self.shotName)
                data = {
                    'project': {
                        'type': 'Project',
                        'id': 66
                    },
                    'code': self.boardName,
                    'description': 'I am not a fluffy bunny!',
                    'sg_path_to_movie': self.pathToMovie,
                    'sg_status_list': 'rev',
                    'entity': {
                        'type': 'Shot',
                        'id': self.getShotTasks['id']
                    },
                    'sg_task': {
                        'type': 'Task',
                        'id': self.taskId
                    },
                    'sg_status_list': 'vwd',
                    'user': {
                        'type': 'HumanUser',
                        'id': 53
                    }
                }
                result = self.sgsrv.create('Version', data)

                ## Now upload to shotgun
                print 'Uploading version %s to %s now' % (self.boardName,
                                                          self.shotName)
                result2 = self.sgsrv.upload("Version", result['id'],
                                            self.pathToMovie,
                                            "sg_uploaded_movie")
                self._turnOffCheckBox('%s.mov' % self.shotName)

        else:
            print 'NO TASKS EXIST FOR %s skipping...' % self.shotName
            self._turnOffCheckBox('%s.mov' % self.shotName)

    def _turnOffCheckBox(self, shotName):
        """
        Func for turning off the uploaded movies as we progress through them so if we error out we have 
        a way to see what has been processed already
        """
        for each in self.fileBoxes:
            if str(each.text()) == shotName:
                each.setChecked(False)
                self.repaint()

    def _checkTypes(self):
        anythingChecked = False
        if self.fileBoxes:
            for each in self.fileBoxes:
                if each.isChecked():
                    anythingChecked = True
        return anythingChecked

    def _setINPROG(self):
        self.goButton.setText('IN PROGRESS...')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.repaint()
        return True

    def _doit(self):
        if self._setINPROG():
            if not self._checkTypes():
                self.goButton.setText('OOPS..')
                self.goButton.setStyleSheet(
                    'QPushButton {background-color: darkred; border: 2px solid 1 ; border-radius: 6px;}'
                )
                self.reply = QMessageBox.question(
                    self, 'Nope!',
                    "Nothing to transfer. Try selecting something and try again",
                    QMessageBox.Ok)
            else:
                self.processStoryBoardFolder()

    def processStoryBoardFolder(self):
        """
        Function to copy over all the audio files from a single output folder into the correct locations for
        the bubblebathbay IDrive audios folders
        @param epNum: The episode name  
        @param pathToFolder: The path to the folder full of wav files you want to copy over.
        @type pathToFolder: String
        @type epNum: String
        NOTE: this tool has been written around the following audio output naming convention from TOONBOOM
        ep106_sh001.wav
        ep106_sh002.wav
        ep106_sh002_A.wav
        """

        if self.epNumber.text() != 'ep':
            for each in self.fileBoxes:
                if each.isChecked() and each.text() != 'ALL':
                    ## We will always start with a base version number of 0 as the audio files from Toonboom
                    ## Do NOT have any versioning...Therefore iteration folders from toonboom can be correctly versioned into
                    ## the publish wav folders without freaking out....
                    self.vNum = '000'
                    self.epName = str(self.epNumber.text()).lower()
                    self.shotNum = str(each.text()).split('.mov')[0].lower()

                    if sys.platform == 'win32':
                        self.shotReviewDir = 'I:/lsapipeline/episodes/%s/%s/SBoard/publish/review/' % (
                            self.epName, self.shotNum)
                    else:
                        self.shotReviewDir = '/Volumes/lsapipeline/episodes/%s/%s/SBoard/publish/review/' % (
                            self.epName, self.shotNum)

                    self.shotReviewFileName = '%s_BOARD.v%s.mov' % (
                        self.shotNum, self.vNum)
                    self.finalPath = '%s%s' % (self.shotReviewDir,
                                               self.shotReviewFileName)

                    ## Check for folder, if it doesn't exist make it
                    if not os.path.isdir(self.shotReviewDir):
                        os.makedirs(self.shotReviewDir)

                    ## Now check for existing file, if so version it up just in case so we don't even delete.
                    if os.path.isfile(self.finalPath):
                        newVersNum = self._versionUp(self.shotReviewDir)
                        if newVersNum <= 10:
                            self.vNum = '00%s' % newVersNum
                        elif newVersNum <= 100:
                            self.vNum = '0%s' % newVersNum
                        else:
                            self.vNum = '%s' % newVersNum
                        ## Now update the name and path vars as final.
                        self.shotReviewFileName = '%s_BOARD.v%s.mov' % (
                            self.shotNum, self.vNum)
                        self.finalPath = '%s%s' % (self.shotReviewDir,
                                                   self.shotReviewFileName)

                    ## Now get the original path for the audio file we are copying.
                    originalPath = '%s\\%s' % (self.sourceFolder, each.text())

                    ## Now perform the copy.
                    shutil.copyfile(originalPath, self.finalPath)
                    #p = subprocess.Popen(cmd, cwd=None, shell=True, bufsize=4096)
                    # Wait until process terminates
                    #while p.poll() is None:
                    #   time.sleep(0.5)
                    print 'Copied file: %s  to \t%s' % (each.text(),
                                                        self.finalPath)

                    if self.makeSGEntries.isChecked():
                        print 'Adding StoryBoard item to shotgun... %s: ' % self.shotReviewFileName
                        self.addStoryboardVersionToShotgun(
                            str(self.shotReviewDir), str(self.epName),
                            str(self.shotNum), str(self.vNum),
                            str(self.shotReviewFileName))

            print 'Finished processing files'
            self.goButton.setText('COMPLETED... click to do over...')
            self.goButton.setStyleSheet(
                'QPushButton {background-color: yellow; border: 2px solid 1 ; border-radius: 6px;}'
            )
        else:
            self.goButton.setText('Invalid Ep Number... click to do over...')
            self.goButton.setStyleSheet(
                'QPushButton {background-color: blue; border: 2px solid 1 ; border-radius: 6px;}'
            )
            print 'You must set a valid episode number!!!'
class DownloadPlaylist(QWidget):
    def __init__(self, parent = None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('Check Playlist local files...')
        
        ## Set base vars
        self.missingLocalFiles      = []
        self.missingLocalFilesDict  = {}
        self.onlineFilesDict        = {}
        self.tempSGFiles            = []
        self.badfiles               = []
        self.badfileBoxes           = []
        self.tempFileCheckBoxes     = []
        self.localFileCheckBoxes    = []
        self.playlist               = []
        
        ## Start the UI Build
        self.mainLayout = QVBoxLayout(self)
        
        self.allPlayLists = ''
        ## Instance the api for talking directly to shotgun. 
        base_url    = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'audioUploader'
        api_key     = 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'
        self.sgsrv  = Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii=True, connect=True)
        self.allPlayLists = []
        
        ### Now find the playlists from shotgun to use.
        self._populatePlaylists()

        self.playListLayout = QHBoxLayout(self)
        self.playListDropDown = QComboBox(self)
        self.playListDropDown.setMinimumWidth(200)
        self.playListDropDown.setMaximumHeight(25)
        
        self.playListSearchLabel = QLabel('Search')
        self.playListSearchInput = QLineEdit(self)
        self.playListSearchInput.textChanged.connect(self._searchDropDown)
        
        self.playListLayout.addWidget(self.playListDropDown)
        self.playListLayout.addWidget(self.playListSearchLabel)
        self.playListLayout.addWidget(self.playListSearchInput)
        
        self.checkForLocal = QPushButton('Check Local Files Exist...')
        self.checkForLocal.clicked.connect(self._checkFiles)
        self.checkForLocal.setStyleSheet("QPushButton {background-color: green}")
        
        self.downloadFilesButton = QPushButton('Click to download missing files...')
        self.downloadFilesButton.clicked.connect(self._processDownload)
        self.downloadFilesButton.setStyleSheet("QPushButton {background-color: green}")
        
        self.updateList()
        self.mainLayout.addLayout(self.playListLayout)
        self.mainLayout.addWidget(self.checkForLocal)
        self.mainLayout.addWidget(self.downloadFilesButton)

        self.downloadFilesButton.hide()

        
        ### Now do the check boxes for files....
        ### FILES TO LOCAL PROJECT FOLDER
        self.scrollLayout = QScrollArea(self)
        self.scrollLayout.setMinimumHeight(50)
        
        self.filesGroupBox = QGroupBox(self.scrollLayout)
        self.filesGroupBox.setTitle('Files to download to local drive')
        self.filesGroupBox.setFlat(True)
        
        self.scrollLayout.setWidget(self.filesGroupBox)
        self.scrollLayout.setWidgetResizable(True)
        
        self.fileLayout = QGridLayout(self.filesGroupBox)

        ### FILES TO LOCAL PROJECT FOLDER
        self.scrollLayout2 = QScrollArea(self)
        self.scrollLayout2.setMinimumHeight(50)
        
        self.filesGroupBox2 = QGroupBox(self.scrollLayout2)
        self.filesGroupBox2.setTitle('Files to download to temp folder')
        self.filesGroupBox2.setFlat(True)
        
        self.scrollLayout2.setWidget(self.filesGroupBox2)
        self.scrollLayout2.setWidgetResizable(True)
        
        self.tempFilesLayout = QGridLayout(self.filesGroupBox2)

        ### FILES TO LOCAL PROJECT FOLDER
        self.scrollLayout3 = QScrollArea(self)
        self.scrollLayout3.setMinimumHeight(50)
        
        self.filesGroupBox3 = QGroupBox(self.scrollLayout3)
        self.filesGroupBox3.setTitle('BAD FILES! Contact Co-Ord to fix.')
        self.filesGroupBox3.setFlat(True)
        
        self.scrollLayout3.setWidget(self.filesGroupBox3)
        self.scrollLayout3.setWidgetResizable(True)
        
        self.badFileCheckBoxLayout = QGridLayout(self.filesGroupBox3)

        self.mainLayout.addWidget(self.scrollLayout)
        self.mainLayout.addWidget(self.scrollLayout2)
        self.mainLayout.addWidget(self.scrollLayout3)

    def _populatePlaylists(self):
        self.pendingReview = self.sgsrv.find('Playlist', filters = [["sg_status", "is", 'rev']], fields=['code', 'created_at', 'versions'])
        self.delivered = self.sgsrv.find('Playlist', filters = [["sg_status", "is", 'dlvr']], fields=['code', 'created_at', 'versions'])
        
        if self.pendingReview:
            for eachPL in self.pendingReview:
                self.allPlayLists.append(eachPL)
        if self.delivered:
            for eachPL in self.delivered:
                self.allPlayLists.append(eachPL)

    def _clearLists(self):
        #os.system('echo clearing lists now...')
        if self.localFileCheckBoxes != []:
            for each in self.localFileCheckBoxes:
                try:
                    each.setParent(None)
                    sip.delete(each)
                    each = None
                except RuntimeError:
                    pass

        if self.tempFileCheckBoxes != []:
            for each in self.tempFileCheckBoxes:
                try:
                    each.setParent(None)
                    sip.delete(each)
                    each = None
                except RuntimeError:
                    pass
                
        if self.badfileBoxes != []:
            for each in self.badfileBoxes:
                try:
                    each.setParent(None)
                    sip.delete(each)
                    each = None
                except RuntimeError:
                    pass

    def _doFileCheckboxes(self):
        """
        Process all the files found into check boxes for processing
        """ 
        self._clearLists()
        self.badfileBoxes           = []
        self.tempFileCheckBoxes     = []
        self.localFileCheckBoxes    = []

        ## LOCAL DOWNLOAD
        ## First add the ALL checkbox
        self.ALL_Local = QCheckBox(self)
        self.ALL_Local.setChecked(False)
        self.ALL_Local.setText('Toggle All') 
        self.ALL_Local.toggled.connect(self._toggleAllLocal)
        self.fileLayout.addWidget(self.ALL_Local, 0, 0)
        
        self.colCount = 5
        r = 1
        c = 1
        for eachType in sorted(self.missingLocalFiles):
            self.fileCheckBox = QCheckBox(self)
            self.fileCheckBox.setChecked(True)
            self.fileCheckBox.setText(eachType)
            self.localFileCheckBoxes.append(self.fileCheckBox)
            if c == self.colCount:
                r = r + 1
                c = 1
            self.fileLayout.addWidget(self.fileCheckBox, r, c)
            c = c + 1

        ## TEMP FILES
        ## First add the ALL checkbox
        self.ALL_Temp = QCheckBox(self)
        self.ALL_Temp.setChecked(False)
        self.ALL_Temp.setText('Toggle All') 
        self.ALL_Temp.toggled.connect(self._toggleAllTemp)
        self.tempFilesLayout.addWidget(self.ALL_Temp, 0, 0)
        
        self.colCount = 5
        r = 1
        c = 1
        for eachType in sorted(self.tempSGFiles):
            self.fileCheckBox = QCheckBox(self)
            self.fileCheckBox.setChecked(True)
            self.fileCheckBox.setText(eachType)
            self.tempFileCheckBoxes.append(self.fileCheckBox)
            if c == self.colCount:
                r = r + 1
                c = 1
            self.tempFilesLayout.addWidget(self.fileCheckBox, r, c)
            c = c + 1
        
        ## BAD FILES
        self.colCount = 5
        r = 1
        c = 1
        for eachType in sorted(self.badfiles):
            self.fileCheckBox = QLabel(self)
            self.fileCheckBox.setText(eachType)
            self.fileCheckBox.setStyleSheet("QLabel {background-color:red; text-align:center;}")
            self.badfileBoxes.append(self.fileCheckBox)
            if c == self.colCount:
                r = r + 1
                c = 1
            self.badFileCheckBoxLayout.addWidget(self.fileCheckBox, r, c)
            c = c + 1
            
        self.repaint()

    def _toggleAllTemp(self):
        for eachBox in self.tempFileCheckBoxes:
            if self.ALL_Temp.isChecked():
                eachBox.setChecked(True)
            else:
                eachBox.setChecked(False)

    def _toggleAllLocal(self):
        for eachBox in self.localFileCheckBoxes:
            if self.ALL_Local.isChecked():
                eachBox.setChecked(True)
            else:
                eachBox.setChecked(False)       

    def _searchDropDown(self):
        self.playListDropDown.clear() 
        for eachPlayList in sorted(self.allPlayLists):
            if str(self.playListSearchInput.text()) in eachPlayList['code']:
                self.playListDropDown.addItem(eachPlayList['code'])

    def updateList(self):
        self.playListDropDown.clear()        

        for eachPlayList in sorted(self.allPlayLists):
            self.playListDropDown.addItem(eachPlayList['code'])

    def _setPlaylist(self):
        """
        Set the playlist from the current pulldown
        """
        for eachPlayList in self.allPlayLists:
            if eachPlayList['code'] == self.playListDropDown.currentText():
                print 'Fetching versions for %s now..' % eachPlayList['code']
                self.playlist       = eachPlayList
            else:
                pass

    def _getVersionInfo(self, versionData):
        """
        Function to process the version data from shotgun
        If we are under darwin osx change the path to local to match our project drives so the path to local is correct for osx
        """
        getVersInfo = self.sgsrv.find_one('Version', filters = [["id", "is", versionData['id']]], fields = ['code', 'sg_path_to_movie', 'sg_uploaded_movie'])
        pathToLocal = getVersInfo['sg_path_to_movie']    
        
        ## Process the osx pathToLocal
        if sys.platform == 'darwin':
            if pathToLocal:
                pathToLocal = pathToLocal.replace('I:', '/_projects').replace("\\", "/")
                getVersInfo['sg_path_to_movie'] = pathToLocal 
        
        ## Now process the URL
        try:
            url = getVersInfo['sg_uploaded_movie']['url']
        except TypeError:
            url = None

        return getVersInfo['code'], pathToLocal, url, getVersInfo

    def _checkFiles(self):
        self._clearLists()
        os.system('cls')
        #os.system('echo Checking Playlist: %s \n' % self.playListDropDown.currentText())
        os.system('echo Looking for files on local drive....\n')
        self.tempSGFiles            = []
        self.missingLocalFiles      = []
        
        self.missingLocalFilesDict  = {}
        self.onlineFilesDict        = {}

        self.badfiles               = []
        self.getVersions            = []
        self.playList               = []
        self.missingUploadedMoveMsg = 'MISSING UPLOADED MOVIE. THIS NEEDS TO BE FIXED. PLEASE CONTACT CO-ORD ABOUT THIS!'
        ######################################################
        ## Set the state for the UI into checking for files...
        self.checkForLocal.setText('Checking files...')
        self.checkForLocal.setStyleSheet("QPushButton {background-color: yellow}")
        self.downloadFilesButton.hide()
        self.repaint()
        ######################################################
        
        ######################################################
        ## Scan each path to local and then check for existing files.
        self._setPlaylist()
        self.getVersions    = self.playlist['versions']
        
        if self.getVersions:
            for eachVer in self.playlist['versions']:
                ######################################################
                ## Fetch the version information from shotgun
                versionName, pathToLocal, url, getVersInfo = self._getVersionInfo(eachVer)
                print 'Checking \t%s now...' % versionName
                
                ######################################################
                ## If we have a valid path to local in shotgun....
                if pathToLocal and 'B:' not in pathToLocal and 'Shotgun' not in pathToLocal:
                    print 'Path: \t\t%s' % pathToLocal
                    
                    ## Now check to see if the path to the file is true or not. 
                    pathExists = os.path.isfile(pathToLocal)
                    os.system('echo EXISTS?: \t%s' % pathExists)
                    
                    ## If it doesn't exist mark this file for download to local path
                    if not pathExists:
                        ## Check if we can download this file from an uploaded movie!?!
                        if url:
                            os.system('echo DL: \t\t%s\n' % versionName)
                            os.system('echo .')
                            
                            ## Add the file to the list for the check-boxes, and the dictionary used for download info
                            if eachVer['name'] not in self.missingLocalFiles:
                                self.missingLocalFiles.append(versionName)## For the check-boxes
                            self.missingLocalFilesDict[versionName] = getVersInfo ## For the down loader
                        else:
                            os.system('echo %s %s' % (versionName, self.missingUploadedMoveMsg))
                            os.system('echo .')
                            
                            ## Add the file to the bad list of files as we are missing an online uploaded file to download.
                            if eachVer['name'] not in self.badfiles:
                                self.badfiles.append(eachVer['name'])
                        
                    ## If the file does exist on the local HD, check to see if we have to resume it or not.
                    ## Check the file sizes match if they don't add to missing files..
                    else: 
                        if url:
                            ## Find the online file size and compare it against the local file size on disk
                            u               = urllib2.urlopen(url)
                            meta            = u.info()
                            onlinefileSize  = int(meta.getheaders("Content-Length")[0])
                            localmeta       = os.stat('%s' % pathToLocal)
                            
                            if not localmeta.st_size == onlinefileSize:
                                os.system('echo Filesize mismatch for %s marking for download again..\n' % pathToLocal.split(os.sep)[-1])
                                os.system('echo Size On Disk: %.8f \tSize On SGun: %.8f' % (float(localmeta.st_size)/1000000, float(onlinefileSize)/1000000))
                                #print localmeta.st_size #17,892,757 bytes
                                os.system('echo .')
                                
                                ## Add the file to the list for the check-boxes, and the dictionary used for download info
                                if eachVer['name'] not in self.missingLocalFiles:
                                    self.missingLocalFiles.append(versionName)## For the check-boxes
                                
                                self.missingLocalFilesDict[versionName] = getVersInfo ## For the down loader
                        
                        else:
                            os.system('echo %s %s' % (versionName, self.missingUploadedMoveMsg))
                            os.system('echo .')
                            if eachVer['name'] not in self.badfiles:
                                self.badfiles.append(eachVer['name'])
                else:
                    ## We don't have a valid path in shotgun to a local file!
                    if url:
                        ## But we do have a url to an uploaded movie...
                        os.system('echo No local path found in shotgun field for %s. File will be saved to Temp folder...' % versionName)
                        os.system('echo .')
                        
                        ## Add the file to the list for the check-boxes, and the dictionary used for download info
                        
                        if eachVer['name'] not in self.tempSGFiles:
                            self.tempSGFiles.append(getVersInfo['code']) ## for the check-boxes
                        self.onlineFilesDict[getVersInfo['code']] = getVersInfo ## For the down loader
                    else:
                        ## OOPS this is missing both a local path and uploaded movie in shotgun :( :( :( 
                        os.system('echo %s MISSING UPLOADED MOVIE AND LOCAL PATH!!!! THIS NEEDS TO BE FIXED. PLEASE CONTACT CO-ORD ABOUT THIS!' % versionName)
                        os.system('echo .')
                        
                        ## Add the file to the list of bad files.
                        self.badfiles.append(eachVer['name'])
        else:
            print '%s has NO versions! This playlist is empty! PLEASE CONTACT CO-ORD ABOUT THIS!' % self.playlist['code']
        
        ########################################
        ## NOW CHECK THE FINAL LISTS AND SET THE UI INTO THE CORRECT STATE
        ## EITHER READY FOR DOWNLOAD OR START A NEW CHECK                                         
        if self.missingLocalFiles or self.tempSGFiles or self.badfiles:
           self.downloadFilesButton.show()
           self.checkForLocal.setText('Check Complete...click to check again...')
           self.checkForLocal.setStyleSheet("QPushButton {background-color: orange}")
           
           ## Now process the check box lists...
           self._doFileCheckboxes()
                       
        else:
            os.system('echo CHECKS OUT OKAY!! ALL FILES EXIST FOR THIS PLAYLIST.....\n')
            self.checkForLocal.setText('Check Local File Exist...')
            self.checkForLocal.setStyleSheet("QPushButton {background-color: green}")
           
            ## Now clear out all the checkboxes.           
            self._clearLists()       

    def _downloadFile(self, pathToLocal, url):
        """
        Main download function
        """
        fileName    = pathToLocal.split(os.sep)[-1]
        u           = urllib2.urlopen(url)
        meta        = u.info()
        file_size   = int(meta.getheaders("Content-Length")[0])

        #os.system('cls')
        os.system('echo Downloading: %s \tSize: %.2f MB\n' % (fileName, float(file_size)/1000000))
        
        f               = open(pathToLocal, 'wb')
        file_size_dl    = 0
        block_sz        = 8192
        while True:
            buffer = u.read(block_sz)
            if not buffer:
                break                                 
            file_size_dl += len(buffer)
            f.write(buffer)
            status = r".........%20s: %34.2f MB [%3.2f%%]" % (fileName, float(file_size_dl)/1000000, file_size_dl * 100. / file_size)
            status = status + chr(8)*(len(status)+1)
            print status,
        f.close()
        os.system('echo \n')
        os.system('echo Download Complete....')

    def _resumeDownload(self, pathToLocal, url, localSize, totalSGFileSize):
        """
        Resume download function
        """
        fileName    = pathToLocal.split(os.sep)[-1]
        req         = urllib2.Request(url)
        remainingB  = totalSGFileSize - localSize
                
        ## Now set the header for the range
        req.headers["Range"] = "bytes=%s-%s" % (localSize, totalSGFileSize)
        
        u           = urllib2.urlopen(req) #create the connection
        meta        = u.info()
        file_size   = int(meta.getheaders("Content-Length")[0])

        #os.system('cls')
        os.system('echo Resuming: %s \tSize: %.2f MB \tRemaining: %.2f MB\n' % (fileName, float(totalSGFileSize)/1000000, float(remainingB)/1000000))
        
        f               = open(pathToLocal, 'ab')
        file_size_dl    = 0
        block_sz        = 8192
        while True:
            buffer = u.read(block_sz)
            if not buffer:
                break                                 
            file_size_dl += len(buffer)
            ## Now write to the file..
            f.write(buffer)
            
            ## Now print the satus
            status = r".........%20s: %34.2f Mb [%3.2f%%]" % (fileName, float(file_size_dl)/1000000, file_size_dl * 100. / totalSGFileSize)
            status = status + chr(8)*(len(status)+1)
            print status,
        f.close()
        os.system('echo \n')
        os.system('echo Download Complete....')         
        
    def _preDownload(self, pathToLocal, url):
        """
        Function to check if the file exists on the local hd
        if it doesn't match that of the online file
        """
        
        ## First check to see if the file exists!
        if not os.path.isfile(pathToLocal):
            ## Do a full download of the file now.
            self._makeDirectories(pathToLocal)
            self._downloadFile(pathToLocal, url)
        else:
            ## The file exists, lets check to resume or skip it.
            u               = urllib2.urlopen(url)
            meta            = u.info()
            onlinefileSize  = int(meta.getheaders("Content-Length")[0])
            localmeta       = os.stat(pathToLocal)
            
            if localmeta.st_size == onlinefileSize:                           
                os.system('echo %s already down-loaded skipping...\n' % pathToLocal)
                return
            elif localmeta.st_size > onlinefileSize:
                ## Delete it, it's a bad download....
                print 'Removing %s ...' % pathToLocal.split(os.sep)[-1]
                os.remove(pathToLocal)                
                try:
                    self._downloadFile(pathToLocal, url)
                except IOError, e:
                    os.system('echo OH NO!: %s' % e)
                    os.system('echo Try a restart of the application and check the files again to solve this problem...')
            else:
Пример #32
0
sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)

project = 'TBD'

dir = "//home/crystal/Desktop/project_test/" + project.lower()

assetALL = sg.find('Asset', [['project.Project.name', 'is', project]], ['image', 'code'])



for asset in assetALL:
    asset_name = asset['code']
    asset_thum = asset['image']

    lookdevALL = sg.find_one('Version', [['project.Project.name', 'is', project],
                                                                    ['entity.Asset.code', 'is', asset_name],
                                                                    ['sg_task.Task.step.Step.id', 'is', 18]],
                                                        ['image', 'sg_path_to_movie'])
    lookdev_mov = lookdevALL['sg_path_to_movie']
    print lookdev_mov
    # lookdev_mov = str(lookdev_mov).replace("\\", "/")

    # print lookdev_mov
    # thum = "%s_" % (datetime.today().strftime('%Y%m%d')) + str(uuid.uuid4())[:8] + ".jpg"
    # thum_path = "/home/crystal/MG/asset/thumnail/small_thum/%s" % thum
    #
    # cate_arr = os.listdir(dir)
    # for cate in cate_arr:
    #     dir_cate = dir + "/" + cate
    #     asset_arr = os.listdir(dir_cate)
    #
    #     for asset2 in asset_arr:
Пример #33
0
    p.product_rmk,
    p.prod_cls_n
FROM item i
JOIN product p ON i.product_id = p.product_id
WHERE product_n not like 'Unknown %'
ORDER BY item_sc DESC
''')

row = cur.fetchone()
while row:
    if not row['item_sc']:
        row = cur.fetchone()
        continue
    asset_data = transform_asset(row)

    existing_asset = sg.find_one('Asset', [['code', 'is', asset_data['code']]])

    if existing_asset:
        print "asset %s exists" % (asset_data['code'])
        sg.update('Asset', existing_asset['id'], asset_data)
    else:
        print "asset %s creating" % (asset_data['code'])
        try:
            sg.create('Asset', asset_data, return_fields=['id'])
            pass
        except Exception:
            pprint.pprint(row)
            pprint.pprint(asset_data)
    row = cur.fetchone()

conn.close()
class StoryboardFileManagement(QWidget):
    def __init__(self, defaultSource = '', parent = None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('StoryBoard File Processing')
        self.parent = parent
        ## Connect to shotgun
    
        from shotgun_api3 import Shotgun

        ## Instance the api for talking directly to shotgun. 
        base_url    = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'audioUploader'
        api_key     = 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'
        
        print 'Connecting to shotgun....'
        self.sgsrv = Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii=True, connect=True)
        
        ## Get the user name
        self.user = getpass.getuser()

        ## Define the variable for the source folder and destination folder (local and remote as it were)
        self.sourceFolder = defaultSource or ''
        self.fileBoxes = []
        
        ## Build the UI
        self.mainLayout = QVBoxLayout(self)
        
        self.epNumLayout = QHBoxLayout()
        self.epNumLabel = QLabel('EpNum:')
        self.epNumber = QLineEdit('', self)
        self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
        self.epNumber.textChanged.connect(self.epTextChange)   
        self.epNumber.setText('ep')
        
        self.epNumLayout.addWidget(self.epNumLabel)
        self.epNumLayout.addWidget(self.epNumber)

        ## Set the layout for the source text input and browse button        
        self.pathLayout = QHBoxLayout(self)
        self.sourceLabel = QLabel('Set Src Path:')
        ## Define the widgets for this layout
        self.sourceInput = QLineEdit(self)
        self.sourceInput.textChanged.connect(self.doFileCheckboxes)
        self.browseButton = QPushButton('Browse')
        self.browseButton.released.connect(partial(self._browseDialog, dest = False))
        ## Add the widgets to the layout
        self.pathLayout.addWidget(self.sourceLabel)
        self.pathLayout.addWidget(self.sourceInput)       
        self.pathLayout.addWidget(self.browseButton)        
        
        self.optionsLayout = QHBoxLayout(self)
        self.makeSGEntries = QCheckBox(self)
        self.makeSGEntries.setChecked(True)
        self.makeSGEntries.setText('Make SGun Entries?')
        
        self.goButton = QPushButton('Transfer SBrd Files To Episode Version Folders')
        self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')   
        self.goButton.clicked.connect(self._doit)
        
        self.optionsLayout.addWidget(self.makeSGEntries)
        self.optionsLayout.addWidget(self.goButton)
        
        self.split = HR.Widget_hr()
        self.mainLayout.addWidget(self.split)

        self.mainLayout.addLayout(self.epNumLayout)
        self.mainLayout.addLayout(self.pathLayout)
        self.mainLayout.addLayout(self.optionsLayout)
        
        ### Now do the check boxes for files....
        self.scrollLayout = QScrollArea(self)
        self.scrollLayout.setMinimumHeight(300)
        
        self.filesGroupBox = QGroupBox(self.scrollLayout)
        self.filesGroupBox.setFlat(True)
        
        self.scrollLayout.setWidget(self.filesGroupBox)
        self.scrollLayout.setWidgetResizable(True)
        
        self.fileLayout = QGridLayout(self.filesGroupBox)
        
        self.mainLayout.addWidget(self.scrollLayout)

    def epTextChange(self):
        if len(self.epNumber.text()) > 5:
            self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)
        elif self.epNumber.text() != 'ep' and len(self.epNumber.text()) == 5:
            self.epNumber.setStyleSheet('QLineEdit {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('Transfer SBrd Files To Episode Version Folders')
            self.goButton.setEnabled(True)
        else:
            self.epNumber.setStyleSheet('QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
            self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')   
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)

    def _toggleAll(self):
        """
        A quick toggle for all the type checkboxes to on or off
        """
        for eachType in self.fileBoxes:
            if eachType.text() == 'ALL':
                if eachType.isChecked():
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(True)
                else:
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(False)
                
    def doFileCheckboxes(self, myPath = ''):
        """
        Process all the folders/files found into checkboxes for processing
        """ 
        ## try to get the epNumber from a file
        epNum = str(os.listdir(self.sourceInput.text())[0].split('_')[0])
        if epNum == '.DS' or epNum == '.DS_Store':
            getFiles = os.listdir(self.sourceInput.text())
            for each in getFiles:
                if ".mov" in each:
                    epNum = each.split('_')[0]
        #print 'I AM A BAD NAUGHTY VARIABLE!: %s' % epNum

        if epNum:
            self.epNumber.setText(epNum)
            
        if self.fileBoxes != []:
            for each in self.fileBoxes:
                each.setParent(None)
                sip.delete(each)
                each = None

        self.files = []
        self.fileBoxes = []
       
        ## First add the ALL checkbox
        self.ALL = QCheckBox(self)
        self.ALL.setChecked(False)
        self.ALL.setText('ALL') 
        self.ALL.toggled.connect(self._toggleAll)
        
        self.fileBoxes.append(self.ALL)
        self.fileLayout.addWidget(self.ALL, 0, 0)
        
        ## Now process the folder and add the folders found as checkboxes.
        try:
            if myPath:
                if sys.platform == 'win32':
                    self.sourceFolder = myPath.replace('/', '\\')
                else:
                    self.sourceFolder = myPath
            else:
                self.sourceFolder = str(self.sourceInput.text())

            for eachFile in os.listdir(self.sourceFolder):
                if eachFile.endswith('.mov'):
                    self.files.append(eachFile)
        except:
            self.files =  ['No mov files found...']

        self.colCount = 10
        r = 1
        c = 1
        for eachType in sorted(self.files):
            self.fileCheckBox = QCheckBox(self)
            self.fileCheckBox.setChecked(False)
            self.fileCheckBox.setText(eachType)
            self.fileBoxes.append(self.fileCheckBox)
            if c == self.colCount:
                r = r + 1
                c = 1
            self.fileLayout.addWidget(self.fileCheckBox, r, c)
            c = c + 1

    def _browseDialog(self, dest = False):
        """
        This opens up a QFileDialog hard set to browse into the assets folder by default. 
        @param dest: To set if you are setting the destination input or the source input
        @type dest: Boolean 
        """
        try:
            if sys.platform == 'win32':
                myPath = QFileDialog(self, 'rootDir', 'O:/EPISODE DELIVERY').getExistingDirectory().replace('\\', '/')
            else:
                myPath = QFileDialog(self, 'rootDir', '/Volumes/LemonSky/OUT TO LEMONSKY/EPISODE DELIVERY').getExistingDirectory().replace('\\', '/')
        except :
            myPath = QFileDialog(self, 'rootDir', '').getExistingDirectory().replace('\\', '/')

        ## try to get the epNumber from a file
        epNum = os.listdir(myPath)[0].split('_')[0]
        if epNum:
            self.epNumber.setText(epNum)
        self.sourceInput.setText(myPath)
        self.sourceFolder = str(myPath)
        self.doFileCheckboxes(myPath)
                 
    def _versionUp(self, path):
        return int(max(os.listdir(path)).split('.v')[-1].split('.mov')[0]) + 1 
    
    def addStoryboardVersionToShotgun(self, path, epName, shotName, verNum, fullVersPublishName):
        """
        Function to add the audio asset to shotgun correctly for tasks etc and the pipeline to see it
        """
        #self.shotNum = each.text().split('.mov')[0]
        #self.addStoryboardVersionToShotgun(str(self.shotReviewDir), str(self.epName), self.shotNum, self.vNum, self.shotReviewFileName)
        ## Now start processing stuff..
        self.epName     = epName.lower()
        self.shotName   = shotName.lower()
        self.boardName  = fullVersPublishName.lower()
        self.taskName   = 'StoryBoard'
        self.sg_version = verNum
               
        self.pathToMovie = '%s%s' % (path, self.boardName)
        
        ## First find it the task exists
        self.getShotTasks =  self.sgsrv.find_one('Shot',  filters = [["code", "is", self.shotName]], fields=['id', 'tasks'])
        
        ## Now check and see if the task we need is there...
        self.tasks = []
        self.taskList = []
        if self.getShotTasks:
            for eachTaskDict in self.getShotTasks['tasks']:
                self.tasks.append(eachTaskDict['name'])
                self.taskList.append(eachTaskDict)

            if self.taskName not in self.tasks:
                ## Create new task for the shot
                self.myNewTask = self.sgsrv.create(
                                                   'Task', 
                                                   {
                                                    'project': 
                                                            {
                                                             'type': 'Project',
                                                             'id': 66
                                                             }, 
                                                    'step': {
                                                             'type': 'Step', 
                                                             'id': 72, 
                                                             'name': 'StoryBoard'
                                                            }, 
                                                    'content': 'StoryBoard',
                                                    'sg_status_list': 'apr',
                                                    'template_task': {
                                                                      'type': 'Task', 
                                                                      'id': 31333
                                                                      }
                                                    }
                                                   )
                self.taskId = int(self.myNewTask['id'])
                ## Returns {'project': {'type': 'Project', 'id': 66, 'name': 'bubblebathbay'}, 'step': {'type': 'Step', 'id': 72, 'name': 'StoryBoard'}, 'type': 'Task', 'id': 32335}
                 
                ## Add this dict to the list of dict for updating the shot task list with.
                self.taskList.append({'type': 'Task', 'id': self.myNewTask['id'], 'name': 'StoryBoard'})
    
                ## Now update the shots task list.
                self.sgsrv.update(
                                  'Shot', 
                                  self.getShotTasks['id'], 
                                  {
                                   'project': {
                                               'type':'Project',
                                               'id':66
                                               }, 
                                   'tasks': self.taskList
                                   }
                                  )
                print 'Successfully updated shot %s with task %s' % (self.shotName, self.taskId)
    
                ## Now create a version for this
                print 'Adding version %s to %s now' % (self.boardName, self.shotName)
                data = { 'project': {'type':'Project','id': 66},
                         'code': self.boardName,
                         'description': 'I am not a fluffy bunny!',
                         'sg_path_to_movie': self.pathToMovie,
                         'sg_status_list': 'rev',
                         'entity': {'type':'Shot', 'id':self.getShotTasks['id']},
                         'sg_task': {'type':'Task', 'id':self.taskId},
                         'sg_status_list': 'vwd',
                         'user': {'type':'HumanUser', 'id':53} }
                result = self.sgsrv.create('Version', data)
                
                ## Now upload to shotgun
                print 'Uploading version %s to %s now' % (self.boardName, self.shotName)
                result2 = self.sgsrv.upload("Version", result['id'], self.pathToMovie, "sg_uploaded_movie")
                self._turnOffCheckBox('%s.mov' % self.shotName)
            else:
                ## Get the story board task id
                for eachTask in self.taskList:
                    if eachTask['name'] == 'StoryBoard':
                        self.taskId = eachTask['id']
                
                ## Now create a version for this
                print 'Adding version %s to %s now' % (self.boardName, self.shotName)
                data = { 'project': {'type':'Project','id': 66},
                         'code': self.boardName,
                         'description': 'I am not a fluffy bunny!',
                         'sg_path_to_movie': self.pathToMovie,
                         'sg_status_list': 'rev',
                         'entity': {'type':'Shot', 'id':self.getShotTasks['id']},
                         'sg_task': {'type':'Task', 'id':self.taskId},
                         'sg_status_list': 'vwd',
                         'user': {'type':'HumanUser', 'id': 53} }
                result = self.sgsrv.create('Version', data)
                
                ## Now upload to shotgun
                print 'Uploading version %s to %s now' % (self.boardName, self.shotName)
                result2 = self.sgsrv.upload("Version", result['id'], self.pathToMovie, "sg_uploaded_movie")
                self._turnOffCheckBox('%s.mov' % self.shotName)

        else:
            print 'NO TASKS EXIST FOR %s skipping...' % self.shotName 
            self._turnOffCheckBox('%s.mov' % self.shotName)
        
    def _turnOffCheckBox(self, shotName):
        """
        Func for turning off the uploaded movies as we progress through them so if we error out we have 
        a way to see what has been processed already
        """
        for each in self.fileBoxes:
            if str(each.text()) == shotName:
                each.setChecked(False)
                self.repaint()    

    def _checkTypes(self):
        anythingChecked = False
        if self.fileBoxes:
            for each in self.fileBoxes:
                if each.isChecked():
                    anythingChecked = True
        return anythingChecked

    def _setINPROG(self):
        self.goButton.setText('IN PROGRESS...')
        self.goButton.setStyleSheet('QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}')
        self.repaint()
        return True
        
    def _doit(self):
        if self._setINPROG():
            if not self._checkTypes():
                self.goButton.setText('OOPS..')
                self.goButton.setStyleSheet('QPushButton {background-color: darkred; border: 2px solid 1 ; border-radius: 6px;}')
                self.reply = QMessageBox.question(self, 'Nope!', "Nothing to transfer. Try selecting something and try again", QMessageBox.Ok)
            else:
                self.processStoryBoardFolder()
    
    def processStoryBoardFolder(self):
        """
        Function to copy over all the audio files from a single output folder into the correct locations for
        the bubblebathbay IDrive audios folders
        @param epNum: The episode name  
        @param pathToFolder: The path to the folder full of wav files you want to copy over.
        @type pathToFolder: String
        @type epNum: String
        NOTE: this tool has been written around the following audio output naming convention from TOONBOOM
        ep106_sh001.wav
        ep106_sh002.wav
        ep106_sh002_A.wav
        """

        if self.epNumber.text() !=  'ep':
            for each in self.fileBoxes:
                if each.isChecked() and each.text() != 'ALL':
                    ## We will always start with a base version number of 0 as the audio files from Toonboom
                    ## Do NOT have any versioning...Therefore iteration folders from toonboom can be correctly versioned into
                    ## the publish wav folders without freaking out....
                    self.vNum = '000'
                    self.epName = str(self.epNumber.text()).lower()
                    self.shotNum = str(each.text()).split('.mov')[0].lower()
                                       
                    if sys.platform == 'win32':
                        self.shotReviewDir = 'I:/lsapipeline/episodes/%s/%s/SBoard/publish/review/' % ( self.epName, self.shotNum)
                    else:
                        self.shotReviewDir = '/Volumes/lsapipeline/episodes/%s/%s/SBoard/publish/review/' % ( self.epName, self.shotNum)
                        
                    self.shotReviewFileName = '%s_BOARD.v%s.mov'  %  (self.shotNum, self.vNum)
                    self.finalPath          = '%s%s' % (self.shotReviewDir, self.shotReviewFileName)       
                    
                    ## Check for folder, if it doesn't exist make it
                    if not os.path.isdir(self.shotReviewDir):
                        os.makedirs(self.shotReviewDir)
                                       
                    ## Now check for existing file, if so version it up just in case so we don't even delete.
                    if os.path.isfile(self.finalPath):
                        newVersNum =  self._versionUp(self.shotReviewDir)
                        if newVersNum <= 10:
                            self.vNum = '00%s' %newVersNum
                        elif newVersNum <= 100:
                            self.vNum = '0%s' %newVersNum
                        else:
                            self.vNum = '%s' %newVersNum
                        ## Now update the name and path vars as final.
                        self.shotReviewFileName = '%s_BOARD.v%s.mov'  %  (self.shotNum, self.vNum)
                        self.finalPath          = '%s%s' % (self.shotReviewDir, self.shotReviewFileName)
                    
                    ## Now get the original path for the audio file we are copying.
                    originalPath = '%s\\%s' % (self.sourceFolder, each.text())
                
                    ## Now perform the copy.
                    shutil.copyfile(originalPath, self.finalPath)
                    #p = subprocess.Popen(cmd, cwd=None, shell=True, bufsize=4096)
                    # Wait until process terminates
                    #while p.poll() is None:
                     #   time.sleep(0.5)
                    print 'Copied file: %s  to \t%s' % (each.text(), self.finalPath)
                    
                    if self.makeSGEntries.isChecked():
                        print 'Adding StoryBoard item to shotgun... %s: ' % self.shotReviewFileName
                        self.addStoryboardVersionToShotgun(str(self.shotReviewDir), str(self.epName), str(self.shotNum), str(self.vNum), str(self.shotReviewFileName))
            
            print 'Finished processing files'
            self.goButton.setText('COMPLETED... click to do over...')
            self.goButton.setStyleSheet('QPushButton {background-color: yellow; border: 2px solid 1 ; border-radius: 6px;}')
        else:
            self.goButton.setText('Invalid Ep Number... click to do over...')
            self.goButton.setStyleSheet('QPushButton {background-color: blue; border: 2px solid 1 ; border-radius: 6px;}')
            print 'You must set a valid episode number!!!'
Пример #35
0
class studioShotgun(object):
    def __init__(self, path, name, key, project):
        self.SERVER_PATH = path
        self.SCRIPT_NAME = name
        self.SCRIPT_KEY = key
        self.project_id = project
        self.sg = Shotgun(self.SERVER_PATH, self.SCRIPT_NAME, self.SCRIPT_KEY)

    #----------------------------------------------------------------------
    ## set Project id by ID
    def setProjectId(self, newId):
        self.project_id = newId

    #----------------------------------------------------------------------
    ## set Project id by ID
    def setProjectName(self, name):
        newId = 0
        projects = self.sg.find('Project', [], ['name'])
        for project in projects:
            if project['name'] == name:
                newId = project['id']

        self.project_id = newId

    #----------------------------------------------------------------------
    ## find asset by name
    def findAssetByName(self, name):
        fields = ['id', 'code', 'sg_asset_type', 'tasks']
        filters = [[
            'project', 'is', {
                'type': 'Project',
                'id': self.project_id
            }
        ], ['code', 'is', name]]

        result = self.sg.find('Asset', filters, fields)

        return result

    #----------------------------------------------------------------------
    ## find shot by name
    def findShotByName(self, episode, shot):
        fields = ['id', 'code', 'sg_asset_type', 'tasks', 'sg_sequence']
        filters = [[
            'project', 'is', {
                'type': 'Project',
                'id': self.project_id
            }
        ], ['code', 'is', shot]]

        result = self.sg.find('Shot', filters, fields)

        for x in result:
            name = x['sg_sequence']['name'].split('_')[0]
            if name == episode:
                return x

        return []

    #----------------------------------------------------------------------
    ## upload thumbnail to asset
    def uploadThumbnail(self, asset, thumbnail):
        upload = 0
        asset = self.findAssetByName(asset)
        if asset:
            upload = self.sg.upload_thumbnail("Asset", asset[0]['id'],
                                              thumbnail)

        return upload

    #----------------------------------------------------------------------
    ## create new asset
    def createAsset(self,
                    asset,
                    assetType,
                    template,
                    assetFile='',
                    description=''):
        ## find asset
        asset = self.findAssetByName(asset)

        if not asset:
            ## create asset + task template
            filters = [['code', 'is', template]]
            template = self.sg.find_one('TaskTemplate', filters)

            data = {
                'project': {
                    'type': 'Project',
                    'id': self.project_id
                },
                'code': asset,
                'description': description,
                'sg_asset_type': assetType,
                'sg_url_perforce': assetFile,
                'task_template': template
            }

            asset = self.sg.create('Asset', data)

        return asset

    #----------------------------------------------------------------------
    ## update file path in asset
    def updateAssetFilePath(self, asset, filename):
        asset = self.findAssetByName(asset)

        data = {'sg_url_perforce': filename}
        asset = self.sg.update("Asset", asset[0]['id'], data)

        return asset

    #----------------------------------------------------------------------
    ## create new version
    def createVersion(self, shotId, taskId, userId, filename, comment=''):
        curTime = datetime.now().strftime('%Y.%m.%d_%H.%M')
        fname = str(filename.split('/')[-1].split('.')[0]) + '_' + curTime

        data = {
            'project': {
                'type': 'Project',
                'id': self.project_id
            },
            'code': fname,
            'description': comment,
            'sg_status_list': 'rev',
            'entity': {
                'type': 'Shot',
                'id': shotId
            },
            'sg_task': {
                'type': 'Task',
                'id': taskId
            },
            'user': {
                'type': 'HumanUser',
                'id': userId
            }
        }

        result = self.sg.create('Version', data)

        upload = self.sg.upload('Version', result['id'], filename,
                                'sg_uploaded_movie')

        return [result, upload]

    #----------------------------------------------------------------------
    ## get user data from shotgum
    def getUserData(self, user):
        filters = [['login', 'is', user]]
        user = self.sg.find('HumanUser', filters)

        if user:
            return user[0]
        else:
            return []

    #----------------------------------------------------------------------
    ## get all user from project
    def getAllUsers(self):
        fields = ['id', 'login', 'name', 'projects', 'department']
        filters = [[
            'projects', 'is', {
                'type': 'Project',
                'id': self.project_id
            }
        ]]
        users = self.sg.find('HumanUser', filters, fields)

        return users
Пример #36
0
    p.product_rmk,
    p.prod_cls_n
FROM item i
JOIN product p ON i.product_id = p.product_id
WHERE product_n not like 'Unknown %'
ORDER BY item_sc DESC
''')

row = cur.fetchone()
while row:
    if not row['item_sc']:
        row = cur.fetchone()
        continue
    asset_data = transform_asset( row )

    existing_asset = sg.find_one('Asset', [['code','is',asset_data['code']]])

    if existing_asset:
        print "asset %s exists" % ( asset_data['code'] )
        sg.update('Asset', existing_asset['id'], asset_data)
    else:
        print "asset %s creating" % ( asset_data['code'] )
        try:
            sg.create('Asset', asset_data, return_fields=['id'])
            pass
        except Exception:
            pprint.pprint(row)
            pprint.pprint(asset_data)
    row = cur.fetchone()

conn.close()
Пример #37
0
sh.col(1).width = 0x0ff0
sh.col(2).width = 0x0ff0
sh.col(3).width = 0x0ff0
sh.col(4).width = 0x0ff0
sh.col(5).width = 0x0ff0
sh.col(6).width = 0x0ff0
sh.col(7).width = 0x0ff0
sh.col(8).width = 0x0ff0
sh.col(9).width = 0x0ff0
sh.col(10).width = 0x0ff0

#sh.row(0).write(col_0, 'Issue', HEADER_CELL)
for cont in sg.find('HumanUser', filters, fields):
    maxTaskinaWeek = get_maxTask(
        cont['id'])  # get max task for each artist for a week
    AtrName = sg.find_one('HumanUser', [["id", "is", cont['id']]],
                          ['name'])['name']

    sh.write(row, 0, AtrName, ARTIST_CELL)
    MaxTaskFirstPointer = row
    #if (AtrName == "Gyaneshwar Reddy") :
    rowRegister = row  # save row initial value
    columnRegister = column  # save column initial value

    for idx, val in enumerate(
            get_week(datetime.datetime.now().date() - datetime.timedelta(
                days=7))):  #for d in get_week(datetime.datetime.now().date()):
        total = 0
        column = column + 1
        if (val.isoformat() <= datetime.date.today().strftime("%Y-%m-%d")):
            ret = sg.find('TimeLog',[['user','is',{"type":"HumanUser","id":cont['id']}],\
            ["date","is",val.isoformat()]], ["duration","entity"])
class PublishMayaAudio(QWidget):
    def __init__(self, defaultSource='I:/lsapipeline/audios/', parent=None):
        QWidget.__init__(self, parent)
        self.setWindowTitle('Audio Publishing Tool')
        self.parent = parent
        ## Connect to shotgun

        from shotgun_api3 import Shotgun

        ## Instance the api for talking directly to shotgun.
        base_url = "http://bubblebathbay.shotgunstudio.com"
        script_name = 'audioUploader'
        api_key = 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'

        self.sgsrv = Shotgun(base_url=base_url,
                             script_name=script_name,
                             api_key=api_key,
                             ensure_ascii=True,
                             connect=True)

        ## Get the user name
        self.user = getpass.getuser()

        ## Define the variable for the source folder and destination folder (local and remote as it were)
        self.sourceFolder = defaultSource or ''
        self.fileBoxes = {}

        ## Build the UI
        self.mainLayout = QVBoxLayout(self)

        self.epNumLayout = QHBoxLayout()
        self.epNumLabel = QLabel('EpNum:')
        self.epNumber = QLineEdit('', self)
        self.epNumber.setStyleSheet(
            'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.epNumber.textChanged.connect(self.epTextChange)
        self.epNumber.setText('ep')

        self.epNumLayout.addWidget(self.epNumLabel)
        self.epNumLayout.addWidget(self.epNumber)

        ## Set the layout for the source text input and browse button
        self.pathLayout = QHBoxLayout(self)
        self.sourceLabel = QLabel('Set Src Path:')
        ## Define the widgets for this layout
        self.sourceInput = QLineEdit(self)
        if self.sourceFolder:
            self.sourceInput.setText(self.sourceFolder)
        self.sourceInput.textChanged.connect(partial(self.doFileCheckboxes))
        self.browseButton = QPushButton('Browse')
        self.browseButton.released.connect(
            partial(self._browseDialog, dest=False))
        ## Add the widgets to the layout
        self.pathLayout.addWidget(self.sourceLabel)
        self.pathLayout.addWidget(self.sourceInput)
        self.pathLayout.addWidget(self.browseButton)

        self.optionsLayout = QHBoxLayout(self)
        self.makeSGEntries = QCheckBox(self)
        self.makeSGEntries.setChecked(True)
        self.makeSGEntries.setText('Make SGun Entries?')

        self.goButton = QPushButton('Publish Audio Files')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.goButton.clicked.connect(self._doit)

        self.optionsLayout.addWidget(self.makeSGEntries)
        self.optionsLayout.addWidget(self.goButton)

        self.split = HR.Widget_hr()
        self.mainLayout.addWidget(self.split)

        self.mainLayout.addLayout(self.epNumLayout)
        self.mainLayout.addLayout(self.pathLayout)
        self.mainLayout.addLayout(self.optionsLayout)

        ### Now do the check boxes for files....
        self.scrollLayout = QScrollArea(self)
        self.scrollLayout.setMinimumHeight(300)

        self.filesGroupBox = QGroupBox(self.scrollLayout)
        self.filesGroupBox.setFlat(True)

        self.scrollLayout.setWidget(self.filesGroupBox)
        self.scrollLayout.setWidgetResizable(True)

        self.fileLayout = QGridLayout(self.filesGroupBox)
        self.mainLayout.addWidget(self.scrollLayout)

    def epTextChange(self):
        if len(self.epNumber.text()) > 5:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)
        elif self.epNumber.text() != 'ep' and len(self.epNumber.text()) == 5:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('Publish Audio Files')
            self.goButton.setEnabled(True)
        else:
            self.epNumber.setStyleSheet(
                'QLineEdit {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setStyleSheet(
                'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
            )
            self.goButton.setText('BAD EP NUMBER')
            self.goButton.setEnabled(False)

    def _toggleAll(self):
        """
        A quick toggle for all the type checkboxes to on or off
        """
        for eachType in self.fileBoxes:
            if eachType.text() == 'ALL':
                if eachType.isChecked():
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(True)
                else:
                    for eachSubType in self.fileBoxes:
                        if eachSubType.text() != 'ALL':
                            eachSubType.setChecked(False)

    def doFileCheckboxes(self, myPath=''):
        """
        Process all the folders/files found into check boxes for processing
        """
        ## try to get the epNumber from a file
        epNum = os.listdir(self.sourceInput.text())[0].split('_')[0]
        if epNum:
            self.epNumber.setText(epNum)

        if self.fileBoxes != {}:
            for key, var in self.fileBoxes.items():
                key.setParent(None)
                sip.delete(key)
                key = None

        self.repaint()
        self.files = []
        self.fileBoxes = {}

        ## First add the ALL checkbox
        self.ALL = QCheckBox(self)
        self.ALL.setChecked(False)
        self.ALL.setText('ALL')
        self.ALL.toggled.connect(self._toggleAll)

        self.fileBoxes[self.ALL] = None
        self.fileLayout.addWidget(self.ALL, 0, 0)

        self.colCount = 10
        r = 1
        c = 1

        ## Now process the folder and add the folders found as check boxes.
        try:
            ## Scan the entire folder structure for audio files to publish
            if self.isRootFolderThere(rootFolder=self.sourceFolder):
                print '%s found processing now...' % self.sourceFolder
                for dirname, dirnames, filenames in os.walk(self.sourceFolder):
                    if dirname.endswith('\\wav'):
                        print 'Scanning %s now..' % dirname
                        print 'Files: %s' % os.listdir(dirname)
                        getMaxFile = max(os.listdir(dirname))
                        if getMaxFile:  ## we have a folder with files in it...
                            if getMaxFile.endswith(".wav"):
                                pathToWav = os.path.join(dirname, getMaxFile)
                                self.fileCheckBox = QCheckBox(self)
                                self.fileCheckBox.setChecked(False)
                                self.fileCheckBox.setText(getMaxFile)
                                self.fileBoxes[
                                    self.fileCheckBox] = pathToWav.replace(
                                        '\\', '/')

                                if c == self.colCount:
                                    r = r + 1
                                    c = 1
                                self.fileLayout.addWidget(
                                    self.fileCheckBox, r, c)
                                c = c + 1
                                print 'Adding %s to layout now..' % pathToWav
                        else:
                            print '%s is emtpy...' % dirname
            else:
                self.files = ['No root folder found...']
        except:
            self.files = ['No wav files found...']

    def _browseDialog(self, dest=False):
        """
        This opens up a QFileDialog hard set to browse into the assets folder by default. 
        @param dest: To set if you are setting the destination input or the source input
        @type dest: Boolean 
        """

        if sys.platform == 'win32':
            print 'OPENING WIN BROWSE DIALOG NOW...'
            myPath = QFileDialog(
                self, 'rootDir',
                self.sourceFolder).getExistingDirectory().replace('\\', '/')
        else:
            print 'OPENING %s BROWSE DIALOG NOW...' % sys.platform
            myPath = QFileDialog(
                self, 'rootDir',
                self.sourceFolder).getExistingDirectory().replace('\\', '/')

        ## try to get the epNumber from a file
        epNum = os.listdir(myPath)[0].split('_')[0]

        if epNum:
            self.epNumber.setText(epNum)

        self.sourceFolder = str(myPath)

        os.system('echo epNum: %s' % self.epNumber)
        os.system('echo sourceFolder: %s' % self.sourceFolder)
        os.system('echo final myPath: %s' % myPath)
        self.sourceInput.setText(myPath)

        #self.doFileCheckboxes(myPath)

    def _versionUp(self, path):
        return int(max(os.listdir(path)).split('.v')[-1].split('.wav')[0]) + 1

    def _writeMaFile(self, fileName, pathToWav, wavName, publishPath):
        ## Check the folder exists, if not make one now.
        if not os.path.isdir(os.path.dirname(self.publishPath)):
            os.makedirs(os.path.dirname(self.publishPath))

        self.header = [
            r'//Maya ASCII 2013ff10 scene',
            r'//Name: %s' % fileName,
            r'//Last modified: Tue, Jun 17, 2014 10:41:32 AM',
            r'//Codeset: 1252',
            r'requires maya "2013ff10";',
            r'requires "Mayatomr" "2013.0 - 3.10.1.11 ";',
            r'currentUnit -l centimeter -a degree -t film;',
            r'fileInfo "application" "maya";',
            r'fileInfo "product" "Maya 2013";',
            r'fileInfo "version" "2013 x64";',
            r'fileInfo "cutIdentifier" "201301140020-856945";',
            r'fileInfo "osv" "Microsoft Windows 7 Ultimate Edition, 64-bit Windows 7 Service Pack 1 (Build 7601)\n";',
        ]

        self.audioNode = [
            '\n%s' % r'createNode audio -n "%s";' % wavName.replace('.', '_'),
            '\t%s' % r'setAttr ".ef" 1000;',
            '\t%s' % r'setAttr ".se" 1000;',
            '\t%s' % r'setAttr ".f" -type "string" "%s";' % pathToWav,
        ]

        self.footer = ['\n%s' % r'// End of %s.ma' % fileName]

        ## Now write the ma file
        ## Fail if the version already exists
        pathToTextFile = publishPath
        if not os.path.isfile(pathToTextFile):
            outfile = open(pathToTextFile, "w")
            for eachLine in self.header:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.audioNode:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.footer:
                outfile.write('%s\n' % eachLine)

            outfile.close()
        else:
            ## Remove it because we are republishing the same version again.
            os.remove(pathToTextFile)
            ## Note we can just delete this file already and move on if needed.
            outfile = open(pathToTextFile, "w")
            for eachLine in self.header:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.audioNode:
                outfile.write('%s\n' % eachLine)
            for eachLine in self.footer:
                outfile.write('%s\n' % eachLine)

            outfile.close()

    def _createPublish(self, publishPath, fileName, pathToWav, wavName,
                       version_number, localPath, localPathMac, wavSGName,
                       ctx):
        self.pathToWav = pathToWav
        self.publishPath = publishPath
        self.localPath = localPath
        self.localPathMac = localPathMac
        self.fileName = fileName
        self.wavName = wavName
        self.wavSGName = wavSGName
        self.version_number = version_number

        data = {
            "code": self.wavSGName,
            "description": None,
            "name": self.wavSGName,
            "project": ctx.project,
            "entity": {
                'id': self.exists['id'],
                'name': self.wavSGName,
                'type': 'CustomEntity03'
            },
            "version_number": self.version_number,
            'path_cache': self.publishPath.replace('/', '\\'),
            'published_file_type': {
                'type': 'PublishedFileType',
                'id': 1
            },
            'updated_by': {
                'type': 'HumanUser',
                'id': 53
            },
            'path': {
                'content_type': None,
                'link_type': 'local',
                'url': 'file:///%s' % self.publishPath.replace('/', '\\'),
                "local_path": self.publishPath.replace('/', '\\'),
                'local_path_linux': '',
                'local_path_mac': '%s' % self.localPathMac,
                'local_path_windows':
                '%s' % self.publishPath.replace('/', '\\'),
                'local_storage': {
                    'id': 1,
                    'name': 'primary',
                    'type': 'LocalStorage'
                },
                'name': self.fileName,
            }
        }

        self.sgsrv.create('PublishedFile', data)
        print 'Publish file created for %s' % self.wavSGName

    def _publishAudio(self):
        """
        Function to add the publish a maya audio file both making a maya file with an audio node and publishing this to shotgun as a version
        """
        for key, var in self.fileBoxes.items():
            if var:
                if key.isChecked():
                    ## Work out what we need for the creation of the ma file
                    ## and the publish for shotgun
                    self.pathToWav = var
                    if sys.platform == 'win32':
                        self.publishPath = var.replace(
                            '/publish/wav',
                            '/publish/maya').replace('.wav',
                                                     '.ma').replace('/', '\\')
                    self.localPath = self.publishPath.split('I:')[-1]
                    self.localPathMac = self.publishPath.replace(
                        'I:', '/_projects')
                    self.fileName = str(key.text()).replace('.wav', '.ma')
                    self.wavName = str(key.text())
                    self.wavSGName = str(key.text().replace('_AUD',
                                                            '').split('.')[0])
                    self.version_number = int(
                        str(key.text()).split('.')[-2].split('v')[-1])

                    ## Now register the publish with Shotgun
                    ## First find the audio on shotgun for processing.
                    self.exists = self.sgsrv.find_one(
                        'CustomEntity03',
                        filters=[["code", "is", self.wavSGName]],
                        fields=['code', 'tasks', 'id'])

                    if not self.exists:
                        print '%s has no shotgun entry! You should make sure this has been processed correctly before proceeding!!' % self.wavName

                    else:
                        ## now publish
                        tk = sgtk.sgtk_from_path("I:/lsapipeline/")
                        ctx = tk.context_from_path(self.publishPath)

                        ## For existing check
                        ## CHECK FOR EXISTING PUBLISH WITH THE SAME VERSION NUMBER!!!!
                        findExisting = self.sgsrv.find_one(
                            'PublishedFile',
                            filters=[["code", "is", self.wavSGName]],
                            fields=[
                                'code', 'id', 'version_number', 'created_at',
                                'entity'
                            ])
                        if findExisting:
                            if findExisting[
                                    'version_number'] == self.version_number:
                                print 'A PUBLISHED FILE FOR THIS VERSION ALREADY EXISTS SKIPPING! VERSION UP OR DELETE EXISTING SHOTGUN PUBLISH ENTRIES IF YOU NEED TO YOU SHOULDNT BUT YOU MIGHT!'
                                ## WRITE THE MA
                                ## Now write the ma file we are going to publish with the audio node created.
                                ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                                self._writeMaFile(self.fileName,
                                                  self.pathToWav, self.wavName,
                                                  self.publishPath)
                            else:  ## This is a new version number
                                ## WRITE THE MA
                                ## Now write the ma file we are going to publish with the audio node created.
                                ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                                self._writeMaFile(self.fileName,
                                                  self.pathToWav, self.wavName,
                                                  self.publishPath)
                                self._createPublish(
                                    publishPath=self.publishPath,
                                    fileName=self.fileName,
                                    pathToWav=self.pathToWav,
                                    wavName=self.wavName,
                                    version_number=self.version_number,
                                    localPath=self.localPath,
                                    localPathMac=self.localPathMac,
                                    wavSGName=self.wavSGName,
                                    ctx=ctx)
                        else:  ## nothing already exists so build a fresh publish
                            ## WRITE THE MA
                            ## Now write the ma file we are going to publish with the audio node created.
                            ## Note this will delete and re-make any ma files with the same name in the folder if they exist
                            self._writeMaFile(self.fileName, self.pathToWav,
                                              self.wavName, self.publishPath)
                            self._createPublish(
                                publishPath=self.publishPath,
                                fileName=self.fileName,
                                pathToWav=self.pathToWav,
                                wavName=self.wavName,
                                version_number=self.version_number,
                                localPath=self.localPath,
                                localPathMac=self.localPathMac,
                                wavSGName=self.wavSGName,
                                ctx=ctx)

        print 'Complete'
        self.goButton.setText('COMPLETE.. click to run again')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: green; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.repaint()

    def _checkTypes(self):
        anythingChecked = False
        if self.fileBoxes:
            for each in self.fileBoxes:
                if each.isChecked():
                    anythingChecked = True
        return anythingChecked

    def _setINPROG(self):
        self.goButton.setText('IN PROGRESS...')
        self.goButton.setStyleSheet(
            'QPushButton {background-color: red; border: 2px solid 1 ; border-radius: 6px;}'
        )
        self.repaint()
        return True

    def _doit(self):
        if self._setINPROG():
            if not self._checkTypes():
                self.goButton.setText('OOPS..')
                self.goButton.setStyleSheet(
                    'QPushButton {background-color: darkred; border: 2px solid 1 ; border-radius: 6px;}'
                )
                self.reply = QMessageBox.question(
                    self, 'Nope!',
                    "Nothing to transfer. Try selecting something and try again",
                    QMessageBox.Ok)
            else:
                self._publishAudio()

    def isRootFolderThere(self, rootFolder):
        """
        Method used to check if root folder is valid or not
        """
        if not os.path.isdir(rootFolder):
            print 'No such root folder found.'
            return -1
        else:
            return 1
Пример #39
0
class ShotgunUtils():
    '''
    this module is a collection of functions to conect the Asset manager to shogun studio website, to update, create
    and manages all attributes and parameters from the different entities.
    '''
    def __init__(self):
        '''
        creates the connection to the server and connects to database.
        creates list of Ids form the  database collections that needs to convert to shotgun collections

        '''
        '''   shotgun conection '''
        SERVER_PATH = "https://hcpstudio.shotgunstudio.com"
        SCRIPT_NAME = 'sgApi'
        SCRIPT_KEY = '3899a8466f2cea694c2ba5341d871da845509d18d96a4feb7fb8d147de0fa819'

        self.sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
        '''Shotgun Dictionaries for  status and Piepeline Step and Entity'''

        self.sgStatusList = {
            'CBB': 'cbb',
            'CURRENT': 'crnt',
            'DEPRECATED': 'dep',
            'FINAL': 'fin',
            'HOLD': 'hld',
            'IN PROGRESS': 'ip',
            'OMIT': 'omt',
            'OUTDATED': 'outd',
            'READY TO START': 'rdy',
            'APPROVED': 'apr',
            'REJECTED': 'rej',
            'RETAKE': 'rtk',
            'SUBMIT FOR APPROVAL': 'app',
            'VARIANT': 'vari'
        }

        self.amStatusList = dict(map(reversed, self.sgStatusList.iteritems()))

        self.sgEntityDic = {
            'ITEM': 'Asset',
            'DIGITALMEDIA': 'Version',
            'SHOT': 'shot',
            'SEQUENCE': 'Sequence'
        }
        self.amEntityDic = dict(map(reversed, self.sgEntityDic.iteritems()))
        ''' DAO master conection    '''

        config = ConfigParser.ConfigParser()
        config.read("__database_config.ini")

        master = DaoMaster(instance=config.get('database_connection',
                                               'instance'),
                           db=config.get('database_connection', 'db'))
        session = master.getSession()
        storedFunctions = master.getStoredFunctions()

        self.ItemStatusConvert = storedFunctions.getCatalogItemStatusStoredFunctions(
        )
        self.ShotStatusConvert = storedFunctions.getCatalogShotStatusStoredFunctions(
        )
        self.SequenceStatusConvert = storedFunctions.getCatalogSequenceStatusStoredFunctions(
        )
        self.DMStatusConvert = storedFunctions.getCatalogDigitalMediaStatusStoredFunctions(
        )
        self.TaskStatusConvert = storedFunctions.getCatalogTaskStatusStoredFunctions(
        )
        self.TaskStepConvert = storedFunctions.getCatalogTaskPipelineStepStoredFunctions(
        )
        ''' instance entities from database '''
        self.itemInstance = session.getItemDao()
        self.projectInstance = session.getProjectDao()
        self.sequenceInstance = session.getSequenceDao()
        self.shotInstance = session.getShotDao()
        self.taskInstance = session.getTaskDao()
        self.dmInstance = session.getDigitalMediaDao()
        self.userInstance = session.getUserDao()
        ''' Catalog instance '''
        self.catalogDepartment = session.getCatalogDepartmentDao()
        self.catalogDMType = session.getCatalogDigitalMediaStatusDao()
        self.catalogDMStatus = session.getCatalogDigitalMediaStatusDao()
        self.catalogItemClass = session.getCatalogItemClassDao()
        self.catalogItemComplex = session.getCatalogItemComplexDao()
        self.catalogItemFormat = session.getCatalogItemFormatDao()
        self.catalogItemStatus = session.getCatalogItemStatusDao()
        self.catalogItemType = session.getCatalogItemTypeDao()
        self.catalogSequenceComplex = session.getCatalogSequenceComplexityDao()
        self.catalogSequenceStatus = session.getCatalogSequenceStatusDao()
        self.catalogShotComplex = session.getCatalogShotComplexityDao()
        self.catalogShotPriority = session.getCatalogShotPriorityDao()
        self.catalogShotStatus = session.getCatalogShotStatusDao()
        self.catalogTaskComplex = session.getCatalogTaskComplexityDao()
        self.catalogTaskEntity = session.getCatalogTaskEntityDao()
        self.catalogTaskName = session.getCatalogTaskNameDao()
        self.catalogTaskPipelineStep = session.getCatalogTaskPipelineStepDao()
        self.catalogTaskPriority = session.getCatalogTaskPriorityDao()
        self.catalogTaskStatus = session.getCatalogTaskStatusDao()

        self.ItemStatusList = self.getCatalogItemStatus()
        self.ItemType = self.getCatalogItemType()
        self.ItemClass = self.getCatalogItemCalss()
        self.ItemComplexity = self.getCatalogItemComplex()

        self.Department = self.getCatalogDepartment()

        self.DMStatus = self.getCatalogDMStatus()
        self.DMType = self.getCatalogDMType()

        self.SequenceComplex = self.getCatalogSequenceComplex()
        self.SequenceStatus = self.getCatalogSequenceStatus()

        self.ShotComplex = self.getCatalogShotComplex()
        self.ShotPriority = self.getCatalogShotPriority()
        self.ShotStatus = self.getCatalogShotStatus()

        self.TaskEntity = self.getCatalogTaskEntity()
        self.TaskName = self.getCatalogTaskName()
        self.TaskStep = self.getCatalogTaskPipelineStep()
        self.TaskPriority = self.getCatalogTaskPriority()
        self.TaskStatus = self.getCatalogTaskStatus()
        self.TaskComplex = self.getCatalogTaskComplex()

        self.sgPiepelineStepTag2IdDic = self.getSgStepsDic()
        self.sgPiepelineStepId2TagDic = dict(
            map(reversed, self.sgPiepelineStepTag2IdDic.iteritems()))

    def getParameterSchema(self, fieldType, fieldName=None):
        '''
         utility function to search fields in a given entity.
        :param fieldType: entity to search parameters 'Project', 'Sequence', 'Shot', 'Asset', 'Version', etc.
        :param fieldName: name of the field to search 'id', 'name', 'coce', etc.
        :return: retruns a dictionary with the properties of given parameter
        '''

        squemaDic = self.sg.schema_field_read(fieldType, fieldName)
        print squemaDic
        for field in squemaDic:
            print field
        return squemaDic

    def getEntities(self):
        '''
        utility function to find all the Entities in shotgun for developing
        :return: renturn a list of all entities
        '''
        squemaDic = self.sg.schema_entity_read()
        for entity in squemaDic:
            print entity
        return squemaDic

    def sgDicListFromDaoItemSubscription(self, itemSubscription):

        sgItemDictionaryList = []

        if itemSubscription == []:

            return sgItemDictionaryList

        else:

            for item in itemSubscription:

                subscription = self.itemInstance.readOneByProperties(
                    self.itemInstance.Properties.Id, item)

                if self.sg.find_one(
                        'Asset',
                    [['id', 'is', subscription.getShotgunID()]]):

                    sgDic = {
                        'type': 'Asset',
                        'id': subscription.getShotgunID()
                    }
                    sgItemDictionaryList.append(sgDic)
                else:
                    pass

            return sgItemDictionaryList

    def sgDicListFromDaoShotSubscription(self, shotSubscription):

        sgShotDictionaryList = []

        if shotSubscription == []:

            return sgShotDictionaryList

        else:

            for shot in shotSubscription:
                subscription = self.shotInstance.readOneByProperties(
                    self.shotInstance.Properties.Id, shot)

                if self.sg.find_one(
                        'Shot',
                    [['id', 'is', subscription.getShotgunID()]]):

                    sgDic = {'type': 'Shot', 'id': subscription.getShotgunID()}
                    sgShotDictionaryList.append(sgDic)

                else:
                    pass

            return sgShotDictionaryList

    def sgDicListFromDaoSequenceSubscription(self, sequenceSubscription):

        sgSequenceDictionaryList = []

        if sequenceSubscription == []:

            return sgSequenceDictionaryList

        else:

            for sequence in sequenceSubscription:

                subscription = self.sequenceInstance.readOneByProperties(
                    self.sequenceInstance.Properties.Id, sequence)

                if self.sg.find_one(
                        'Sequence',
                    [['id', 'is', subscription.getShotgunID()]]):

                    sgDic = {
                        'type': 'Sequence',
                        'id': subscription.getShotgunID()
                    }
                    sgSequenceDictionaryList.append(sgDic)

                else:
                    pass

            return sgSequenceDictionaryList

    def sgDicListFromDaoDMSubscription(self, dmSubscription):

        sgDMDictionaryList = []

        if dmSubscription == []:

            return sgDMDictionaryList

        else:

            for dm in dmSubscription:
                subscription = self.dmInstance.readOneByProperties(
                    self.dmInstance.Properties.Id, dm)
                if self.sg.find_one(
                        'Version',
                    [['id', 'is', subscription.getShotgunID()]]):

                    sgDic = {
                        'type': 'Version',
                        'id': subscription.getShotgunID()
                    }
                    sgDMDictionaryList.append(sgDic)

                else:
                    pass

            return sgDMDictionaryList

    def sgDicListFromDaoUserSubscription(self, userSubscription):

        sgUserDictionaryList = []

        if userSubscription == []:

            return sgUserDictionaryList

        else:

            for user in userSubscription:
                subscription = self.userInstance.readOneByProperties(
                    self.userInstance.Properties.Id, user)

                if not subscription.getShotgunID() == 0:
                    if self.sg.find_one(
                            'HumanUser',
                        [['id', 'is', subscription.getShotgunID()]]):
                        sgDic = {
                            'type': 'HumanUser',
                            'id': subscription.getShotgunID()
                        }
                        sgUserDictionaryList.append(sgDic)

                else:
                    pass

            return sgUserDictionaryList

    def sgDicListFromDaoTaskSubscription(self, taskSubscription):

        sgUserDictionaryList = []

        if taskSubscription == []:

            return sgUserDictionaryList

        else:

            for task in taskSubscription:
                subscription = self.taskInstance.readOneByProperties(
                    self.taskInstance.Properties.Id, task)

                if not subscription.getShotgunID() == 0:
                    if self.sg.find_one(
                            'Task',
                        [['id', 'is', subscription.getShotgunID()]]):
                        sgDic = {
                            'type': 'Task',
                            'id': subscription.getShotgunID()
                        }
                        sgUserDictionaryList.append(sgDic)

                else:
                    pass

            return sgUserDictionaryList

    def amItemIdListFromSgItemSubscriptionDicList(self, sgDicList):

        amSubscriptionList = []

        if sgDicList == []:
            return amSubscriptionList

        else:
            for sgDic in sgDicList:
                item = self.itemInstance.readOneByProperties(
                    self.itemInstance.Properties.Id, sgDic['id'])

                if item:
                    amSubscriptionList.append(item.getId())

                else:
                    pass

            return amSubscriptionList

    def amShotIdListFromSgShotSubscriptionDicList(self, sgDicList):

        amSubscriptionList = []

        if sgDicList == []:
            return amSubscriptionList

        else:
            for sgDic in sgDicList:
                entity = self.shotInstance.readOneByProperties(
                    self.shotInstance.Properties.Id, sgDic['id'])

                if entity:
                    amSubscriptionList.append(entity.getId())

                else:
                    pass

            return amSubscriptionList

    def amSequenceIdListFromSgSequenceSubscriptionDicList(self, sgDicList):

        amSubscriptionList = []

        if sgDicList == []:
            return amSubscriptionList

        else:
            for sgDic in sgDicList:
                entity = self.sequenceInstance.readOneByProperties(
                    self.sequenceInstance.Properties.Id, sgDic['id'])

                if entity:
                    amSubscriptionList.append(entity.getId())

                else:
                    pass

            return amSubscriptionList

    def amDMIdListFromSgDMSubscriptionDicList(self, sgDicList):

        amSubscriptionList = []

        if sgDicList == []:
            return amSubscriptionList

        else:
            for sgDic in sgDicList:
                entity = self.dmInstance.readOneByProperties(
                    self.dmInstance.Properties.Id, sgDic['id'])

                if entity:
                    amSubscriptionList.append(entity.getId())

                else:
                    pass

            return amSubscriptionList

    def amTaskIdListFromSgTaskSubscriptionDicList(self, sgDicList):

        amSubscriptionList = []

        if sgDicList == []:
            return amSubscriptionList

        else:
            for sgDic in sgDicList:
                entity = self.dmInstance.readOneByProperties(
                    self.dmInstance.Properties.Id, sgDic['id'])

                if entity:
                    amSubscriptionList.append(entity.getId())

                else:
                    pass

            return amSubscriptionList

    def sgIdFromItemId(self, itemId):
        if not itemId == 0:
            entity = self.itemInstance.readOneByProperties(
                self.itemInstance.Properties.Id, itemId)
            return entity.getShotgunID()
        else:
            return 0

    def sgIdFromShotId(self, shotId):

        if not shotId == 0:
            entity = self.shotInstance.readOneByProperties(
                self.shotInstance.Properties.Id, shotId)
            return entity.getShotgunID()
        else:
            return 0

    def sgIdFromSquenceId(self, sequenceId):

        if not sequenceId == 0:
            entity = self.sequenceInstance.readOneByProperties(
                self.sequenceInstance.Properties.Id, sequenceId)
            return entity.getShotgunID()
        else:
            return 0

    def sgIdFromProjectId(self, projectId):

        if not projectId == 0:
            entity = self.projectInstance.readOneByProperties(
                self.projectInstance.Properties.Id, projectId)
            return entity.getShotgunID()
        else:
            return 0

    def sgIdFromDmId(self, dmId):

        if not dmId == 0:
            entity = self.dmInstance.readOneByProperties(
                self.dmInstance.Properties.Id, dmId)
            return entity.getShotgunID()

        else:
            return 0

    def sgIdFromTaskId(self, taskId):

        if not taskId == 0:
            entity = self.taskInstance.readOneByProperties(
                self.taskInstance.Properties.Id, taskId)
            return entity.getShotgunID()

        else:
            return 0

    def getCatalogDepartment(self):

        listFromCatalog = []

        catalogAll = self.catalogDepartment.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogDMStatus(self):

        listFromCatalog = []

        catalogAll = self.catalogDMStatus.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogDMType(self):

        listFromCatalog = []

        catalogAll = self.catalogDMType.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogItemCalss(self):

        listFromCatalog = []

        catalogAll = self.catalogItemClass.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogItemComplex(self):

        listFromCatalog = []

        catalogAll = self.catalogItemComplex.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def itemStatus2Dao(self, status):

        return self.ItemStatusConvert.getIdFromTag(status)

    def shotStatus2Dao(self, status):

        return self.ShotStatusConvert.getIdFromTag(status)

    def sequenceStatus2Dao(self, status):

        return self.SequenceStatusConvert.getIdFromTag(status)

    def dmStatus2Dao(self, status):

        return self.SequenceStatusConvert.getIdFromTag(status)

    def taskStatus2Dao(self, status):

        return self.TaskStatusConvert.getIdFromTag(status)

    def getCatalogItemStatus(self):

        listFromCatalog = []

        catalogAll = self.catalogItemStatus.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogItemType(self):

        listFromCatalog = []

        catalogAll = self.catalogItemType.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogSequenceComplex(self):

        listFromCatalog = []

        catalogAll = self.catalogSequenceComplex.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogSequenceStatus(self):

        listFromCatalog = []

        catalogAll = self.catalogSequenceStatus.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogShotComplex(self):

        listFromCatalog = []

        catalogAll = self.catalogShotComplex.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogShotPriority(self):

        listFromCatalog = []

        catalogAll = self.catalogShotPriority.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogShotStatus(self):

        listFromCatalog = []

        catalogAll = self.catalogShotStatus.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogTaskComplex(self):

        listFromCatalog = []

        catalogAll = self.catalogTaskComplex.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogTaskEntity(self):

        listFromCatalog = []

        catalogAll = self.catalogTaskEntity.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogTaskName(self):

        listFromCatalog = []

        catalogAll = self.catalogTaskName.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogTaskPipelineStep(self):

        listFromCatalog = []

        catalogAll = self.catalogTaskPipelineStep.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogTaskPriority(self):

        listFromCatalog = []

        catalogAll = self.catalogTaskPriority.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getCatalogTaskStatus(self):

        listFromCatalog = []

        catalogAll = self.catalogTaskStatus.readAll()

        for catalog in catalogAll:
            listFromCatalog.append(catalog.getTag())

        return listFromCatalog

    def getSgStepsDic(self):

        sgFields = ['id', 'code']
        dictionaryList = self.sg.find('Step', [], sgFields)

        stepDic = {}

        for dictionary in dictionaryList:
            stepDic.update({dictionary['code']: dictionary['id']})

        return stepDic

    def daoitem2sgDic(self, itemId):

        entity = self.itemInstance.readOneByProperties(
            self.itemInstance.Properties.Id, itemId)
        sgDic = {}

        if entity:
            if not entity.getShotgunID() == 0:

                sgDic = {'type': 'Asset', 'id': entity.getShotgunID()}

                return sgDic

            else:
                return None

        else:
            return None

    def daoShot2sgDic(self, itemId):

        entity = self.shotInstance.readOneByProperties(
            self.shotInstance.Properties.Id, itemId)
        sgDic = {}

        if entity:
            if not entity.getShotgunID() == 0:

                sgDic = {'type': 'Shot', 'id': entity.getShotgunID()}

                return sgDic

            else:
                return None

        else:
            return None

    def daoSequence2sgDic(self, itemId):

        entity = self.sequenceInstance.readOneByProperties(
            self.sequenceInstance.Properties.Id, itemId)
        sgDic = {}

        if entity:
            if not entity.getShotgunID() == 0:

                sgDic = {'type': 'Sequence', 'id': entity.getShotgunID()}

                return sgDic

            else:
                return None

        else:
            return None

    def daoDM2sgDic(self, itemId):

        entity = self.dmInstance.readOneByProperties(
            self.dmInstance.Properties.Id, itemId)
        sgDic = {}

        if entity:
            if not entity.getShotgunID() == 0:

                sgDic = {'type': 'Version', 'id': entity.getShotgunID()}

                return sgDic

            else:
                return None

        else:
            return None

    def daoHumanUser2sgDic(self, itemId):

        entity = self.userInstance.readOneByProperties(
            self.userInstance.Properties.Id, itemId)
        sgDic = {}

        if entity:
            if not entity.getShotgunID() == 0:

                sgDic = {'type': 'Asset', 'id': entity.getShotgunID()}

                return sgDic

            else:
                return None

        else:
            return None

    def daoTask2sgDic(self, itemId):

        entity = self.taskInstance.readOneByProperties(
            self.taskInstance.Properties.Id, itemId)
        sgDic = {}

        if entity:
            if not entity.getShotgunID() == 0:

                sgDic = {'type': 'Task', 'id': entity.getShotgunID()}

                return sgDic

            else:
                return None

        else:
            return None
sh.col(0).width = 0x0ff0
sh.col(1).width = 0x0ff0
sh.col(2).width = 0x0ff0
sh.col(3).width = 0x0ff0
sh.col(4).width = 0x0ff0
sh.col(5).width = 0x0ff0
sh.col(6).width = 0x0ff0
sh.col(7).width = 0x0ff0
sh.col(8).width = 0x0ff0
sh.col(9).width = 0x0ff0
sh.col(10).width = 0x0ff0

#sh.row(0).write(col_0, 'Issue', HEADER_CELL)
for cont in sg.find('HumanUser',filters , fields):
	maxTaskinaWeek = get_maxTask(cont['id'])										# get max task for each artist for a week
	AtrName = sg.find_one('HumanUser',[["id","is",cont['id']]],['name'])['name']

	sh.write(row, 0, AtrName,ARTIST_CELL)
	MaxTaskFirstPointer = row
	#if (AtrName == "Gyaneshwar Reddy") :
	rowRegister = row						# save row initial value
	columnRegister = column 				# save column initial value

	for idx, val in enumerate(get_week(datetime.datetime.now().date() - datetime.timedelta(days=7))):				#for d in get_week(datetime.datetime.now().date()):
		total = 0
		column = column + 1
		if (val.isoformat() <= datetime.date.today().strftime("%Y-%m-%d")):
			ret = sg.find('TimeLog',[['user','is',{"type":"HumanUser","id":cont['id']}],\
			["date","is",val.isoformat()]], ["duration","entity"])
			if (ret != []):
				switchForTask = 1
Пример #41
0
class Main(QtGui.QWidget, Ui_Form, ReferenceTab, CommentWidget, Lib,
           TaskManager, MyTasks, WhatsNew, Asset, LogEntry, Task, AssetLoader,
           Moodboard_Creator, PeopleTab, RenderTab):
    def __init__(self):
        super(Main, self).__init__()

        self.username = os.getenv('USERNAME')

        self.setWindowFlags(self.windowFlags() | QtCore.Qt.CustomizeWindowHint)

        self.ReferenceTab = ReferenceTab
        self.Lib = Lib
        self.TaskManager = TaskManager
        self.RenderTab = RenderTab
        self.MyTasks = MyTasks
        self.WhatsNew = WhatsNew
        self.CommentWidget = CommentWidget
        self.Task = Task
        self.Asset = Asset
        self.AssetLoader = AssetLoader
        self.LogEntry = LogEntry
        self.Moodboard_Creator = Moodboard_Creator
        self.PeopleTab = PeopleTab

        sg_url = "http://nad.shotgunstudio.com"
        sg_script_name = "ThibaultGenericScript"
        sg_key = "e014f12acda4074561022f165e8cd1913af2ba4903324a72edbb21430abbb2dc"
        self.sg_project_id = 146

        self.sg = Shotgun(sg_url, sg_script_name, sg_key)

        # Initialize the guis
        self.Form = self.setupUi(self)
        self.Form.center_window()

        self.setMinimumSize(1453, 923)
        self.setMaximumSize(1453, 923)

        self.db_to_load = ""
        self.db_path = "Z:\\Groupes-cours\\NAND999-A15-N01\\Nature\\_pipeline\\_utilities\\_database\\nature.sqlite"  # Database nature

        if QtGui.QApplication.keyboardModifiers() == QtCore.Qt.ShiftModifier:
            # Database Setup
            self.db_path = "H:\\01-NAD\\_pipeline\\_utilities\\_database\\db.sqlite"  # Copie de travail

        # Backup database
        if self.db_path not in [
                "H:\\01-NAD\\_pipeline\\_utilities\\_database\\db.sqlite",
                "Z:\\Groupes-cours\\NAND999-A15-N01\\Nature\\_pipeline\\_utilities\\_database\\rendering.sqlite"
        ]:
            self.backup_database()

        self.db = sqlite3.connect(self.db_path,
                                  check_same_thread=False,
                                  timeout=30.0)
        self.cursor = self.db.cursor()

        # Global Variables
        self.projectList.hide()
        self.i = 0
        self.computer_id = socket.gethostname()
        self.ref_assets_instances = []
        self.selected_asset = None
        self.utf8_codec = QtCore.QTextCodec.codecForName("utf-8")
        self.today = time.strftime("%d/%m/%Y", time.gmtime())
        self.cur_path = os.path.dirname(os.path.realpath(
            __file__))  # H:\01-NAD\_pipeline\_utilities\_asset_manager
        self.cur_path_one_folder_up = self.cur_path.replace(
            "\\_asset_manager", "")  # H:\01-NAD\_pipeline\_utilities
        self.NEF_folder = self.cur_path_one_folder_up + "\\_NEF"  # H:\01-NAD\_pipeline\_utilities\NEF
        self.screenshot_dir = self.cur_path_one_folder_up + "\\_database\\screenshots\\"
        self.no_img_found = self.cur_path + "\\media\\no_img_found.png"
        self.number_of_refreshes = 0
        self.members = {
            "acorbin": "Alexandre",
            "fpasquarelli": "Francis",
            "costiguy": "Chloe",
            "cgonnord": "Christopher",
            "erodrigue": "Etienne",
            "jberger": "Jeremy",
            "lgregoire": "Laurence",
            "lclavet": "Louis-Philippe",
            "mbeaudoin": "Mathieu",
            "mroz": "Maxime",
            "obolduc": "Olivier",
            "slachapelle": "Simon",
            "thoudon": "Thibault",
            "vdelbroucq": "Valentin",
            "yjobin": "Yann",
            "yshan": "Yi"
        }
        self.sg_members = {
            "acorbin": "3dalcor",
            "fpasquarelli": "francis.pasquarelli",
            "costiguy": "ostiguy.chloe",
            "cgonnord": "christopher.gonnord",
            "erodrigue": "etienne.rodrigue89",
            "jberger": "jeremy.berger3d",
            "lgregoire": "lau-gregoire",
            "lclavet": "clavet.lp",
            "mbeaudoin": "beaudoinmathieu",
            "mroz": "maximeroz",
            "obolduc": "ol.bolduc",
            "slachapelle": "simonlachapelle",
            "thoudon": "houdon.thibault",
            "vdelbroucq": "valentin.delbroucq",
            "yjobin": "yannjobinphoto",
            "yshan": "yishan3d"
        }
        self.departments_shortname = {
            "Script": "spt",
            "Storyboard": "stb",
            "References": "ref",
            "Concepts": "cpt",
            "Modeling": "mod",
            "Texturing": "tex",
            "Rigging": "rig",
            "Animation": "anm",
            "Simulation": "sim",
            "Shading": "shd",
            "Camera": "cam",
            "Lighting": "lgt",
            "Layout": "lay",
            "DMP": "dmp",
            "Rendering": "rdr",
            "Compositing": "cmp",
            "Editing": "edt",
            "RnD": "rnd"
        }
        self.departments_longname = {
            "spt": "Script",
            "stb": "Storyboard",
            "ref": "References",
            "cam": "Camera",
            "cpt": "Concepts",
            "lgt": "Lighting",
            "mod": "Modeling",
            "tex": "Texturing",
            "rig": "Rigging",
            "anm": "Animation",
            "sim": "Simulation",
            "shd": "Shading",
            "lay": "Layout",
            "dmp": "DMP",
            "rdr": "Rendering",
            "cmp": "Compositing",
            "edt": "Editing",
            "rnd": "RnD"
        }

        refresh_icon = QtGui.QIcon(self.cur_path + "\\media\\refresh.png")
        self.refreshAllBtn.setIcon(refresh_icon)
        self.refreshAllBtn.setIconSize(QtCore.QSize(24, 24))
        self.refreshAllBtn.clicked.connect(self.refresh_all)

        # Setup user session if it is not already setup
        is_setup = self.cursor.execute(
            '''SELECT is_setup FROM preferences WHERE username=?''',
            (self.username, )).fetchone()[0]
        if is_setup == 0:
            self.Lib.setup_user_session(self)
            self.cursor.execute(
                '''UPDATE preferences SET is_setup=1 WHERE username=?''',
                (self.username, ))
            self.db.commit()

        # Clear temp folder
        if os.path.isdir("H:/tmp"):
            try:
                shutil.rmtree("H:/tmp")
            except:
                pass

        try:
            os.makedirs("H:/tmp")
        except:
            pass

        # Create Favicon
        self.app_icon = QtGui.QIcon()
        self.app_icon.addFile(self.cur_path + "\\media\\favicon_cube.png",
                              QtCore.QSize(64, 64))
        self.Form.setWindowIcon(self.app_icon)

        # Set the StyleSheet
        self.themePrefComboBox.currentIndexChanged.connect(self.change_theme)
        self.theme = self.cursor.execute(
            '''SELECT theme FROM preferences WHERE username=?''',
            (self.username, )).fetchone()[0]
        self.themePrefComboBox.setCurrentIndex(int(self.theme))
        self.change_theme()

        # Admin Setup
        self.remove_tabs_based_on_members()

        # Get remaining time and set deadline Progress Bar
        day_start = date(2015, 6, 28)
        day_end = date(2016, 4, 25)
        day_today = datetime.now().date()

        months_and_days_left = relativedelta.relativedelta(day_end, day_today)

        total_days = abs(day_end - day_start).days
        remaining_days = abs(day_end - date.today()).days
        remaining_days_percent = (
            remaining_days * 100
        ) / total_days  # Converts number of remaining day to a percentage

        self.deadlineProgressBar.setFormat(
            "{0} months and {1} days left ({2}%)".format(
                months_and_days_left.months, months_and_days_left.days,
                remaining_days_percent))
        self.deadlineProgressBar.setMaximum(total_days)
        self.deadlineProgressBar.setValue(remaining_days)
        hue = self.fit_range(remaining_days, 0, total_days, 0, 76)
        self.deadlineProgressBar.setStyleSheet(
            "QProgressBar::chunk {background-color: hsl(" + str(hue) +
            ", 255, 205);}")

        if self.username not in ["thoudon", "lclavet", "costiguy"]:
            self.deadlineFrame.hide()

        # Setup disk usage progress bar
        disk_usage = self.Lib.get_folder_space(self)
        disk_usage = int(
            float(disk_usage) *
            1000)  # Multiply disk usage by 1000. Ex: 1.819 to 1819
        disk_usage = (
            2000 * int(disk_usage)
        ) / 1862  # 2TO in theory = 1.862GB in reality. Remapping real disk usage to the theoric one
        self.diskUsageProgressBar.setFormat('{0}/2000 GB'.format(
            str(disk_usage)))
        self.diskUsageProgressBar.setRange(0, 2000)
        self.diskUsageProgressBar.setValue(int(disk_usage))
        hue = self.fit_range(int(disk_usage), 0, 2000, 0, 76)
        self.diskUsageProgressBar.setStyleSheet(
            "QProgressBar::chunk {background-color: hsl(" + str(hue) +
            ", 255, 205);}")

        # Thumbnail creation progress bar setup
        self.thumbnailProgressBar.setStyleSheet(
            "QProgressBar::chunk {background-color: hsl(0, 100, 175);}")
        self.thumbnailProgressBar.setValue(0)
        self.thumbnailProgressBar.hide()

        # Get software paths from database and put them in preference
        self.photoshop_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Photoshop"'''
            ).fetchone()[0])
        self.maya_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Maya"'''
            ).fetchone()[0])
        self.maya_batch_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Maya Batch"'''
            ).fetchone()[0])
        self.softimage_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Softimage"'''
            ).fetchone()[0])
        self.softimage_batch_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Softimage Batch"'''
            ).fetchone()[0])
        self.houdini_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Houdini"'''
            ).fetchone()[0])
        self.houdini_batch_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Houdini Batch"'''
            ).fetchone()[0])
        self.cinema4d_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Cinema 4D"'''
            ).fetchone()[0])
        self.nuke_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Nuke"'''
            ).fetchone()[0])
        self.zbrush_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="ZBrush"'''
            ).fetchone()[0])
        if os.path.exists(
                "C:/Program Files/Mari2.6v2/Bundle/bin/Mari2.6v2.exe"):
            self.mari_path = str(
                self.cursor.execute(
                    '''SELECT software_path FROM software_paths WHERE software_name="Mari"'''
                ).fetchone()[0])
        else:
            self.mari_path = "C:/Program Files/Mari2.6v5/Bundle/bin/Mari2.6v5.exe"
        self.blender_path = str(
            self.cursor.execute(
                '''SELECT software_path FROM software_paths WHERE software_name="Blender"'''
            ).fetchone()[0])

        self.cursor.execute(
            '''UPDATE preferences SET is_online=1 WHERE username=?''',
            (self.username, ))
        self.db.commit()

        # Preferences setup
        self.prefBckGroundColorSlider.sliderMoved.connect(
            self.change_pref_background_color_pixmap)
        self.prefBckGroundColorSlider.setStyleSheet("background-color; red;")

        # Set systray actions
        self.quitAction = QtGui.QAction("Quit",
                                        self,
                                        triggered=self.terminate_program)
        self.quitAction.setIcon(
            QtGui.QIcon(self.cur_path + "/media/turn_off.png"))

        # Systray icon
        self.trayIconMenu = QtGui.QMenu(self)
        self.trayIconMenu.addAction(self.quitAction)

        self.tray_icon = QtGui.QIcon(self.cur_path +
                                     "\\media\\favicon_cube.png")
        self.trayIcon = QtGui.QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.setIcon(self.tray_icon)

        self.tray_icon_log_id = ""
        self.tray_message = ""

        self.trayIcon.hide()

        #self.tray_icon.messageClicked.connect(self.tray_icon_message_clicked)
        self.trayIcon.activated.connect(self.tray_icon_clicked)

        # Initialize modules and connections
        AssetLoader.__init__(self)
        self.ReferenceTab.__init__(self)
        self.RenderTab.__init__(self)
        self.CommentWidget.__init__(self)
        self.WhatsNew.__init__(self)
        self.PeopleTab.__init__(self)
        self.WhatsNew.load_whats_new(self)
        self.check_last_active()

        #self.check_news_thread = CheckNews(self)
        #self.connect(self.check_news_thread, QtCore.SIGNAL("check_last_active"), self.check_last_active)
        #self.check_news_thread.daemon = True
        #self.check_news_thread.start()

        self.show()

        #self.check_shotgun_time_log()

    def check_shotgun_time_log(self):
        self.username = "******"
        peoples = {
            "acorbin": "Alexandre Corbin",
            "costiguy": "Chloé Ostiguy",
            "cgonnord": "Christopher Gonnord",
            "erodrigue": "Etienne Rodrigue",
            "fpasquarelli": "Francis Pasquarelli",
            "jberger": "Jérémy Berger",
            "lgregoire": "Laurence Grégoire",
            "lclavet": "Louis-Philippe Clavet",
            "mbeaudoin": "Mathieu Beaudoin",
            "mroz": "Maxime Roz",
            "thoudon": "Thibault Houdon",
            "vdelbroucq": "Valentin Delbroucq",
            "yjobin": "Yann Jobin",
            "yshan": "Yi Shan"
        }
        user = peoples[self.username]

        project = self.sg.find_one("Project",
                                   [["id", "is", self.sg_project_id]])
        time_log = self.sg.find(
            "TimeLog",
            [["date", "in_calendar_day", -1], ["project", "is", project]],
            ["user"])
        people_logged = [log["user"]["name"] for log in time_log]
        people_logged = list(set(people_logged))

        if user not in people_logged:
            time_log_window = QtGui.QDialog(self)
            time_log_window.setWindowTitle("Add your time log entry")
            layout = QtGui.QVBoxLayout(time_log_window)
            descriptionLabel = QtGui.QLabel(time_log_window)
            durationLabel = QtGui.QLabel(time_log_window)
            descriptionLabel.setText("Description")
            durationLabel.setText("Duration")
            self.description = QtGui.QLineEdit(time_log_window)
            self.duration = QtGui.QLineEdit(time_log_window)

            addLogEntryBtn = QtGui.QPushButton(time_log_window)
            addLogEntryBtn.setText("Add Time Log Entry")
            addLogEntryBtn.clicked.connect(self.shotgun_add_time_log)

            didntWorkBtn = QtGui.QPushButton(time_log_window)
            didntWorkBtn.setText("I didn't work on this project yesterday.")

            layout.addWidget(durationLabel)
            layout.addWidget(self.duration)
            layout.addWidget(descriptionLabel)
            layout.addWidget(self.description)
            layout.addWidget(addLogEntryBtn)
            layout.addWidget(didntWorkBtn)

            time_log_window.exec_()

    def shotgun_add_empty_time_log(self):
        pass

    def shotgun_add_time_log(self):

        print(self.description.text())
        print(self.duration.text())

    def add_tag_to_tags_manager(self):
        # Check if a project is selected
        if len(self.projectList.currentText()) == 0:
            Lib.message_box(text="Please select a project first.")
            return

        tag_name = unicode(self.addTagLineEdit.text())
        tag_name = Lib.normalize_str(self, tag_name)

        if len(tag_name) == 0:
            Lib.message_box(text="Please enter a tag name.")
            return

        item = QtGui.QTreeWidgetItem(self.tagsTreeWidget)
        item.setText(0, tag_name)
        self.tagsTreeWidget.addTopLevelItem(item)

        self.addTagLineEdit.setText("")
        self.save_tags_list()

    def remove_selected_tags_from_tags_manager(self):
        root = self.tagsTreeWidget.invisibleRootItem()
        for item in self.tagsTreeWidget.selectedItems():
            (item.parent() or root).removeChild(item)
        self.save_tags_list()

    def save_tags_list(self):
        root = self.tagsTreeWidget.invisibleRootItem()  # Fetch the root item
        child_count = root.childCount()
        for item in xrange(child_count):

            # Get the text of the first item in the tree widget
            parent_text = str(root.child(item).text(0))

            # Check if item already exists, if no, add it to the database, if yes, update its name and parent
            already_exist = self.cursor.execute(
                '''SELECT tag_name FROM tags WHERE tag_name=?''',
                (parent_text, )).fetchone()
            if already_exist == None:
                self.cursor.execute(
                    '''INSERT INTO tags(project_name, tag_name, tag_parent) VALUES(?,?,?)''',
                    (
                        self.selected_project_name,
                        parent_text,
                        "",
                    ))
            else:
                self.cursor.execute(
                    '''UPDATE tags SET tag_name=?, tag_parent=? WHERE tag_name=? AND project_name=?''',
                    (
                        parent_text,
                        "",
                        parent_text,
                        self.selected_project_name,
                    ))

            # Get all children of parent item
            nbr_of_children = root.child(item).childCount()
            for i in range(nbr_of_children):
                child_text = str(root.child(item).child(i).text(0))

                # Check if item already exists, if no, add it to the database, if yes, update its name and parent
                already_exist = self.cursor.execute(
                    '''SELECT tag_name FROM tags WHERE tag_name=?''',
                    (child_text, )).fetchone()
                if already_exist == None:
                    self.cursor.execute(
                        '''INSERT INTO tags(project_name, tag_name, tag_parent) VALUES(?,?,?)''',
                        (
                            self.selected_project_name,
                            child_text,
                            parent_text,
                        ))
                else:
                    self.cursor.execute(
                        '''UPDATE tags SET tag_name=?, tag_parent=? WHERE tag_name=? AND project_name=?''',
                        (
                            child_text,
                            parent_text,
                            child_text,
                            self.selected_project_name,
                        ))

        self.db.commit()

    def add_assets_to_asset_list(self, assets_list):
        """
        Add assets from assets_list to self.assetList

        """

        self.assetList.clear()
        for asset in assets_list:
            self.assetList.addItem(asset[4])

    def clear_filter(self, filter_type):
        """
        Clear the filter edit line
        """
        if filter_type == "seq":
            self.seqFilter.setText("")
        elif filter_type == "asset":
            self.assetFilter.setText("")

    def update_thumb(self):
        """
        Update selected asset thumbnail
        """
        self.Form.showMinimized()

        Lib.take_screenshot(self.screenshot_dir, self.selected_asset_name)

        pixmap = QtGui.QPixmap(self.screenshot_dir + self.selected_asset_name +
                               ".jpg").scaled(1000, 200,
                                              QtCore.Qt.KeepAspectRatio,
                                              QtCore.Qt.SmoothTransformation)
        self.assetImg.setPixmap(pixmap)
        self.Form.showMaximized()
        self.Form.showNormal()

    def remove_tabs_based_on_members(self):

        if not (self.username == "thoudon" or self.username == "lclavet"):
            self.adminPrefFrame.hide()
            self.createAssetFromScratchBtn.hide()

        self.get_tabs_id_from_name()

        if self.members[self.username] == "Chloe":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])

        elif self.members[self.username] == "Francis":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Alexandre":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Christopher":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])

        elif self.members[self.username] == "Etienne":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Jeremy":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Laurence":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Louis-Philippe":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])

        elif self.members[self.username] == "Mathieu":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Maxime":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])

        elif self.members[self.username] == "Olivier":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Simon":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Thibault":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()

        elif self.members[self.username] == "Yann":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Yi":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

        elif self.members[self.username] == "Valentin":
            self.Tabs.removeTab(self.tabs_list["Tasks"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Task Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Tags Manager"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Misc"])
            self.get_tabs_id_from_name()
            self.Tabs.removeTab(self.tabs_list["Render"])

    def get_tabs_id_from_name(self):
        self.tabs_list = {}
        for i in xrange(self.Tabs.count()):
            self.tabs_list[str(self.Tabs.tabText(i))] = i

    def change_username(self):
        username = str(self.usernameAdminComboBox.currentText())
        self.username = username

    def backup_database(self):
        # Get creation_time of last database backup and compare it to current  time
        database_files = Lib.get_files_from_folder(
            self,
            path=
            "Z:\\Groupes-cours\\NAND999-A15-N01\\Nature\\_pipeline\\_utilities\\_database\\_backup"
        )
        if len(database_files) > 1000:
            self.Lib.message_box(
                self,
                type="error",
                text=
                u"Trop de backups détectés pour la base de donnée. Veuillez avertir Thibault, merci ;)"
            )

        cur_db_name = os.path.split(self.db_path)[-1].replace(".sqlite", "")
        database_files = [
            i for i in database_files if cur_db_name in os.path.split(i)[-1]
        ]
        database_files = sorted(database_files)
        last_database_file = database_files[-1]
        creation_time = time.ctime(os.path.getctime(last_database_file))
        creation_time = time.strptime(creation_time, "%a %b %d %H:%M:%S %Y")
        current_time = str(datetime.now())
        current_time = time.strptime(current_time, "%Y-%m-%d %H:%M:%S.%f")
        time_difference = (time.mktime(current_time) -
                           time.mktime(creation_time)) / 60

        if time_difference > 180:  # If last backup is older than 5 hours, do a backup
            fileName, fileExtension = os.path.splitext(last_database_file)
            last_database_file_version = int(fileName.split("_")[-1])
            new_version = str(last_database_file_version + 1).zfill(4)
            backup_database_filename = fileName.replace(
                str(last_database_file_version).zfill(4),
                new_version) + ".sqlite"
            shutil.copy(self.db_path, backup_database_filename)

    def refresh_all(self):
        self.blockSignals(True)

        #Default refreshes
        self.mt_item_added = True
        self.item_added = True
        self.setup_tags()

        #Get current tab text
        current_tab_text = self.Tabs.tabText(self.Tabs.currentIndex())

        if current_tab_text == "Asset Loader":
            self.statusLbl.setText("Status: Refreshing Asset Loader tab...")
            self.repaint()
            self.AssetLoader.load_all_assets_for_first_time(self)
            self.AssetLoader.load_assets_from_selected_seq_shot_dept(self)

        elif current_tab_text == "Task Manager":
            self.statusLbl.setText("Status: Refreshing Task Manager tab...")
            self.repaint()
            TaskManager.add_tasks_from_database(self)

        elif current_tab_text == "Tasks":
            self.statusLbl.setText("Status: Refreshing Tasks tab...")
            self.repaint()
            MyTasks.mt_add_tasks_from_database(self)

        elif current_tab_text == "Render":
            self.statusLbl.setText("Status: Refreshing Render tab...")
            self.repaint()
            RenderTab.add_computers_from_database(self)
            RenderTab.add_jobs_from_database(self)
            RenderTab.add_frames_from_database(self)

        elif current_tab_text == "People":
            self.statusLbl.setText("Status: Refreshing People tab...")
            self.repaint()
            self.PeopleTab.get_online_status(self)
            self.cursor.execute(
                '''UPDATE preferences SET last_active=? WHERE username=?''', (
                    datetime.now().strftime("%d/%m/%Y at %H:%M"),
                    self.username,
                ))
            self.db.commit()

        elif current_tab_text == "Images Manager":
            self.statusLbl.setText("Status: Refreshing Images Manager tab...")
            self.repaint()
            if len(self.ref_assets_instances) > 1:
                self.ReferenceTab.refresh_reference_list(self)

        elif "What's New" in current_tab_text:
            self.statusLbl.setText("Status: Refreshing What's New tab...")
            self.repaint()
            self.WhatsNew.load_whats_new(self)

        self.statusLbl.setText("Status: Idle...")
        self.blockSignals(False)

    def change_theme(self):
        if self.themePrefComboBox.currentIndex() == 0:
            self.theme = 0
            self.prefBckGroundColorSlider.setValue(114)
            self.Lib.apply_style(self, self)
            self.cursor.execute(
                '''UPDATE preferences SET theme=? WHERE username=?''', (
                    0,
                    self.username,
                ))
        elif self.themePrefComboBox.currentIndex() == 1:
            self.theme = 1
            self.prefBckGroundColorSlider.setValue(241)
            self.setStyleSheet("")
            app.setStyle(QtGui.QStyleFactory.create("cleanlooks"))
            self.cursor.execute(
                '''UPDATE preferences SET theme=? WHERE username=?''', (
                    1,
                    self.username,
                ))
            css = QtCore.QFile(self.cur_path + "\\media\\cleanlooks.css")
            css.open(QtCore.QIODevice.ReadOnly)
            if css.isOpen():
                self.Form.setStyleSheet(
                    QtCore.QVariant(css.readAll()).toString().replace(
                        "checkbox|placeholder",
                        self.cur_path.replace("\\", "/") +
                        "/media/checkbox.png"))
        elif self.themePrefComboBox.currentIndex() == 2:
            self.prefBckGroundColorSlider.setValue(255)
            self.theme = 2
            self.setStyleSheet("")
            app.setStyle(QtGui.QStyleFactory.create("plastique"))
            self.cursor.execute(
                '''UPDATE preferences SET theme=? WHERE username=?''', (
                    2,
                    self.username,
                ))

        self.db.commit()

    def change_pref_background_color_pixmap(self):
        slider_value = self.prefBckGroundColorSlider.value()
        self.referenceThumbListWidget.setStyleSheet(
            "background-color: rgb({0},{0},{0});".format(slider_value))

    def tray_icon_message_clicked(self):

        if self.tray_message == "Manager is in background mode.":
            return

        clicked_log_entry = self.cursor.execute(
            '''SELECT log_value FROM log WHERE log_id=?''',
            (self.tray_icon_log_id, )).fetchone()[0]
        clicked_log_description = self.cursor.execute(
            '''SELECT log_entry FROM log WHERE log_id=?''',
            (self.tray_icon_log_id, )).fetchone()[0]

        if len(clicked_log_entry) == 0:
            return

        asset = self.Asset(main=self,
                           id=clicked_log_entry,
                           get_infos_from_id=True)

        if "reference" in clicked_log_description:
            if "video" in clicked_log_description:
                subprocess.Popen([
                    "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
                    asset.dependency
                ])
            else:
                if os.path.isfile(asset.full_path):
                    os.system(asset.full_path)
                else:
                    self.Lib.message_box(
                        self,
                        text="Can't find reference: it must have been deleted."
                    )

        elif "comment" in clicked_log_description:
            self.CommentWidget(main=self, asset=asset)

    def tray_icon_clicked(self, reason):
        if reason == QtGui.QSystemTrayIcon.DoubleClick:
            if self.isHidden():
                self.setWindowFlags(QtCore.Qt.Widget)
                self.show()
                self.setWindowState(self.windowState()
                                    & ~QtCore.Qt.WindowMinimized
                                    | QtCore.Qt.WindowActive)
                self.trayIcon.hide()
            else:
                self.hide()
                self.trayIcon.show()

    def keyPressEvent(self, event):

        global_pos = self.mapFromGlobal(QtGui.QCursor.pos())
        widget_under_mouse = self.childAt(global_pos)

        key = event.key()
        if key == QtCore.Qt.Key_F11:
            if self.isFullScreen():
                self.showNormal()
            else:
                self.showFullScreen()
        elif key == QtCore.Qt.Key_Delete:
            current_tab_text = self.Tabs.tabText(self.Tabs.currentIndex())
            if current_tab_text == "Images Manager":
                ReferenceTab.remove_selected_references(self)
        elif key == QtCore.Qt.Key_F2:
            selected_reference = self.referenceThumbListWidget.selectedItems(
            )[0]
            asset = selected_reference.data(QtCore.Qt.UserRole).toPyObject()
            ReferenceTab.rename_reference(self, asset)

        elif key == QtCore.Qt.Key_F1:
            self.show_wiki_help(widget_under_mouse)

        elif key == QtCore.Qt.Key_F5:
            self.refresh_all()

    def show_wiki_help(self, widget):
        if widget.objectName() == "publishBtn":
            subprocess.Popen([
                "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
                "file:///Z:/Groupes-cours/NAND999-A15-N01/Nature/_info/wiki/wiki.html#Modeling"
            ])

    def closeEvent(self, event):
        if not self.trayIcon.isVisible():
            self.setWindowFlags(QtCore.Qt.Tool)
            self.hide()
            self.trayIcon.show()
            self.tray_message = "Manager is in background mode."
            self.trayIcon.showMessage('Still running...', self.tray_message,
                                      QtGui.QSystemTrayIcon.Information, 1000)
            self.hide()
            event.ignore()
            self.trayIcon.show()

    def terminate_program(self):
        # tasks = subprocess.check_output(['tasklist'])
        # if "houdin" in tasks.lower():
        #     self.Lib.message_box(self, type="error", text="Please close Houdini layout scenes before closing the Manager!")
        #     return

        self.cursor.execute(
            '''UPDATE preferences SET is_online=0 WHERE username=?''',
            (self.username, ))
        self.db.commit()
        self.Lib.switch_mari_cache(self, "perso")
        self.close()
        app.exit()

        # self.quit_msg = "Are you sure you want to exit the program?"
        # reply = QtGui.QMessageBox.question(self, 'Are you leaving :(',
        #                  quit_msg, QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
        #
        # if reply == QtGui.QMessageBox.Yes:
        #
        #     event.accept()
        # else:
        #     event.ignore()

    def changeEvent(self, event):
        if event.type() == QtCore.QEvent.WindowStateChange:
            if self.windowState() & QtCore.Qt.WindowMinimized:
                self.setWindowFlags(QtCore.Qt.Tool)
                self.hide()
                self.trayIcon.show()
                self.tray_message = "Manager is in background mode."
                self.trayIcon.showMessage('Still running...',
                                          self.tray_message,
                                          QtGui.QSystemTrayIcon.Information,
                                          1000)

    def check_last_active(self):
        for user in self.members.keys():
            last_active = datetime.now().strftime("%d/%m/%Y at %H:%M")
            last_active_datetime = datetime.strptime(last_active,
                                                     '%d/%m/%Y at %H:%M')

            last_active_db = self.cursor.execute(
                '''SELECT last_active FROM preferences WHERE username=?''',
                (user, )).fetchone()[0]
            last_active_db_datetime = datetime.strptime(
                last_active_db, '%d/%m/%Y at %H:%M')

            time_difference = last_active_datetime - last_active_db_datetime
            if time_difference.seconds > 600:
                self.cursor.execute(
                    '''UPDATE preferences SET is_online=0 WHERE username=?''',
                    (user, ))
            else:
                self.cursor.execute(
                    '''UPDATE preferences SET is_online=1 WHERE username=?''',
                    (user, ))

        last_active = datetime.now().strftime("%d/%m/%Y at %H:%M")
        self.cursor.execute(
            '''UPDATE preferences SET last_active=? WHERE username=?''', (
                last_active,
                self.username,
            ))
        self.db.commit()
Пример #42
0
else:
    sg = Shotgun('http://127.0.0.1:8020', 'name', 'key')

print sg.server_info

proj = sg.create('Project', {'name': 'Mock Project Test'})
seq = sg.create('Sequence', {'code': 'AA', 'project': proj})
shot = sg.create('Shot', {'code': 'AA_001', 'sg_sequence': seq})

print proj
print seq
print shot
#
# print sg.find('Project', [('id', 'is_not', 0)], ['name'], order=[
#     {'field_name': 'id', 'direction': 'asc'},
# ])

print sg._call_rpc('count', None)
exit()

print sg.create('Project', {'name': 'Test Project'})
print sg.count()
print sg.find_one('Project', [],
                  order=[
                      {
                          'field_name': 'id',
                          'direction': 'asc'
                      },
                  ],
                  fields=['task_assignees'])