Пример #1
0
class AppServerSvc(win32serviceutil.ServiceFramework):
    _svc_name_ = "timelog"
    _svc_display_name_ = "shotgun time log"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        SetConsoleCtrlHandler(lambda x: True, True)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)

        self.count = 0
        self.estinmins = 0
        self.isAlive = True
        self.envv = ''
        self.prlist = []

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.run = False

    def SvcDoRun(self):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_, ''))
        self.sg = Shotgun('https://xxxxxxxxxxxxxxxx.shotgunstudio.com',
                          'timelogservice',
                          'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
        self.main()

    def updateProject(self, projectid):
        servicemanager.LogWarningMsg(unicode(projectid))
        filters = [["project.Project.id", "is", projectid]]
        fields = ["time_logs_sum", "est_in_mins"]
        for eventTimeLog in self.sg.find('Task', filters, fields):
            self.count = self.count + eventTimeLog['time_logs_sum']
            if eventTimeLog['est_in_mins'] is not None:
                self.estinmins = self.estinmins + eventTimeLog['est_in_mins']

        data = {'sg_artisttimelog': self.count / 600}
        asset = self.sg.update("Project", projectid, data)
        data = {'sg_total_bid': self.estinmins / 600}
        asset = self.sg.update("Project", projectid, data)

    def main(self):
        while self.isAlive:
            filters = [["sg_status", "is", "active"]]
            fields = ['id']
            for f in self.sg.find('Project', filters, fields):
                self.prlist.append(f['id'])

            for prid in self.prlist:
                self.updateProject(prid)
                self.count = 0
                self.estinmins = 0
                if win32event.WaitForSingleObject(
                        self.hWaitStop, 3000) == win32event.WAIT_OBJECT_0:
                    break
Пример #2
0
class AppServerSvc(win32serviceutil.ServiceFramework):
    _svc_name_ = "timelog"
    _svc_display_name_ = "shotgun time log"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        SetConsoleCtrlHandler(lambda x: True, True)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)

        self.count = 0
        self.estinmins = 0
        self.isAlive = True
        self.envv = ""
        self.prlist = []

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.run = False

    def SvcDoRun(self):
        servicemanager.LogMsg(
            servicemanager.EVENTLOG_INFORMATION_TYPE, servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, "")
        )
        self.sg = Shotgun(
            "https://xxxxxxxxxxxxxxxx.shotgunstudio.com", "timelogservice", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        )
        self.main()

    def updateProject(self, projectid):
        servicemanager.LogWarningMsg(unicode(projectid))
        filters = [["project.Project.id", "is", projectid]]
        fields = ["time_logs_sum", "est_in_mins"]
        for eventTimeLog in self.sg.find("Task", filters, fields):
            self.count = self.count + eventTimeLog["time_logs_sum"]
            if eventTimeLog["est_in_mins"] is not None:
                self.estinmins = self.estinmins + eventTimeLog["est_in_mins"]

        data = {"sg_artisttimelog": self.count / 600}
        asset = self.sg.update("Project", projectid, data)
        data = {"sg_total_bid": self.estinmins / 600}
        asset = self.sg.update("Project", projectid, data)

    def main(self):
        while self.isAlive:
            filters = [["sg_status", "is", "active"]]
            fields = ["id"]
            for f in self.sg.find("Project", filters, fields):
                self.prlist.append(f["id"])

            for prid in self.prlist:
                self.updateProject(prid)
                self.count = 0
                self.estinmins = 0
                if win32event.WaitForSingleObject(self.hWaitStop, 3000) == win32event.WAIT_OBJECT_0:
                    break
Пример #3
0
def submitShotgunTicket(output, jobList):

	currentuser = str(User.currentUser().name())
	title = "AtS - %s"%currentuser

	desc = []
	desc.append(output+"\n")
	desc.append("JOBLIST:") 

	for job in jobList:
	    desc.append(str(job.key())+" - "+str(job.name())) 
			
	sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
	
        id = sg.find("HumanUser",[['login','is',currentuser]],['id'])
        userid = id[0]

        ticket_data = {
            'created_by': {'type':'HumanUser','id':userid['id']},
            'title': title,
            'description': "\n".join(desc),
            'addressings_to':[{'type':'Group', 'id':19}, {'type':'HumanUser','id':userid['id']}],
            'project': {'type':'Project', 'id':178},
            'sg_service': {'type':'CustomNonProjectEntity01', 'id':27},
        }
        sg_ticket = sg.create('Ticket', ticket_data, ['id'])
        new_ticket_url = SERVER_PATH + "/detail/Ticket/" + str(sg_ticket['id'])
        QDesktopServices.openUrl( QUrl(new_ticket_url) )
Пример #4
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)
Пример #5
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)
Пример #6
0
def getentitiesfromshotgun(name):
    sg = Shotgun(const.SHOTGUN_URL, const.API_NAME, const.API_KEY)
    sgname = name
    if name in const.ENTITY_MAP:
        sgname = const.ENTITY_MAP[name]
    fields = sg.schema_field_read(sgname)
    rawents = sg.find(sgname,
                      [['project', 'is', {
                          'type': 'Project',
                          'id': 70
                      }]], list(fields.keys()))
    pp(rawents)
    clean = []
    for ent in rawents:

        if 'image' in ent and ent['image']:
            directory = "data/filestorage/%s/%s/%s" % (name, ent['id'],
                                                       "image")
            if not os.path.exists(os.path.dirname(directory)):
                os.makedirs(os.path.dirname(directory))
            sg.download_attachment({'url': ent['image']}, directory)
            ent['image'] = directory
        for field in fields:
            if fields[field]['data_type']['value'] == 'url' and ent[field]:
                pp(ent)
                directory = "data/filestorage/%s/%s/%s" % (name, ent['id'],
                                                           ent[field]['name'])
                if not isinstance(ent['id'], int):
                    directory = "data/filestorage/%s/%s/%s" % (
                        name, ent['id']['value'], ent[field]['name'])
                if not os.path.exists(os.path.dirname(directory)):
                    os.makedirs(os.path.dirname(directory))
                sg.download_attachment(ent[field], directory)
                ent[field] = directory

            ent[field] = {
                "value": ent[field],
                "type": fields[field]['data_type']['value']
            }

        ent.pop("created_at", None)
        ent.pop("created_by", None)
        ent.pop("updated_at", None)
        ent.pop("updated_by", None)
        ent.pop("filmstrip_image", None)
        ent.pop("cached_display_name", None)

        dic = {}
        dic['type'] = {'type': 'text', 'value': ent.pop('type')}
        for f in ent:
            dic[fields[f]['name']['value']] = ent[f]

        clean.append(dic)

    return clean
def _get_projects_list():
    sg = Shotgun('http://yoursite.com', 'your_api', '123456')

    filters = [['sg_status', 'is', 'Active'], ['tank_name', 'is_not', '']]
    fields = ['name']
    order = [{'field_name': 'name', 'direction': 'asc'}]
    projectsDic = sg.find('Project', filters, fields, order)

    newProjectsDic = []

    for project in projectsDic:
        newProjectsDic.append(project['name'].replace(' ', ''))

    return newProjectsDic
def _get_projects_list():
	sg = Shotgun('http://yoursite.com', 'your_api', '123456')

	filters = [['sg_status', 'is', 'Active'], ['tank_name', 'is_not', '']]
	fields = ['name']
	order = [{'field_name': 'name', 'direction': 'asc'}]
	projectsDic = sg.find('Project', filters, fields, order)

	newProjectsDic = []

	for project in projectsDic:
		newProjectsDic.append(project['name'].replace(' ', ''))

	return newProjectsDic
class MyWidgetHolder(QtGui.QWidget):
    def __init__(self, parent = None):
        QtGui.QWidget.__init__(self, parent)

        notificationList = []
        # sender, receiver, date, message, noteDict )
        notificationList.append( notification("Cyrilc", "john", datetime.datetime.now(), "Wait for approval ! rhooooooo lr lr bon y va oui ou non il est l'heure d'ylller j'ai faim. et de toute facon il est l'heure", "pas") )
        notificationList.append( notification("Donat", "john", datetime.datetime.now(), "Peu continuer !", "pas") )
        notificationList.append( notification("MikeB", "john", datetime.datetime.now(), "Oui c'est sympas", "pas") )
        notificationList.append( notification("Aurelien", "john", datetime.datetime.now(), "Launch Time", "pas") )
        notificationList.append( notification("Thomas", "john", datetime.datetime.now(), "Wait for appoval", "pas") )
        notificationList.append( notification("James", "john", datetime.datetime.now(), "Approved", "pas") )
        notificationList.append( notification("Mike", "john", datetime.datetime.now(), "Aurevoir John !", "pas") )
        notificationList.append( notification("Tristan", "john", datetime.datetime.now(), "Bonjour John !", "pas") )
        notificationList.append( notification("Eric", "john", datetime.datetime.now(), "Bonjour John !", "pas") )
        notificationList.append( notification("Francois", "john", datetime.datetime.now(), "Bonjour John !", "pas") )


        path_to_shotgunApi = getPathToShotgunApi()
        sys.path.append(path_to_shotgunApi)

        from shotgun_api3 import Shotgun
        self.SERVER_PATH = "https://nozon.shotgunstudio.com"
        self.SCRIPT_NAME = 'noteManager'     
        self.SCRIPT_KEY = '30b93ec002ce2e22ecd6fb31fdda6063797deed1d612b4f6ca39e8030104707c'
        self.sg = Shotgun(self.SERVER_PATH, self.SCRIPT_NAME, self.SCRIPT_KEY)
        sg_spawnedNotes = self.sg.find("CustomEntity04", [ ['sg_note','is_not', None] ] ,   ["project"] )
        for a in sg_spawnedNotes :
            print a


        self.setMinimumWidth(1000)
        self.setMinimumHeight(50)

        self.noteBarW = NotificationBar(notificationList, ["jack","popeye","james","conan le barbare"])
        button = QtGui.QPushButton("pafpaf")
        #button.clicked.connect(self.noteBarW.addNotification)

        lay = QtGui.QVBoxLayout()
        lay.addWidget(button)
        lay.addWidget(self.noteBarW)
        lay.addWidget(QtGui.QPushButton("pafpaf"))
        self.setLayout(lay)
        lay.setSpacing(0)
        lay.setContentsMargins(0,0,0,0)
        self.show()
Пример #10
0
def submitShotgunTicket(output, jobList):

    currentuser = str(User.currentUser().name())
    title = "AtS - %s" % currentuser

    desc = []
    desc.append(output + "\n")
    desc.append("JOBLIST:")

    for job in jobList:
        desc.append(str(job.key()) + " - " + str(job.name()))

    sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)

    id = sg.find("HumanUser", [['login', 'is', currentuser]], ['id'])
    userid = id[0]

    ticket_data = {
        'created_by': {
            'type': 'HumanUser',
            'id': userid['id']
        },
        'title':
        title,
        'description':
        "\n".join(desc),
        'addressings_to': [{
            'type': 'Group',
            'id': 19
        }, {
            'type': 'HumanUser',
            'id': userid['id']
        }],
        'project': {
            'type': 'Project',
            'id': 178
        },
        'sg_service': {
            'type': 'CustomNonProjectEntity01',
            'id': 27
        },
    }
    sg_ticket = sg.create('Ticket', ticket_data, ['id'])
    new_ticket_url = SERVER_PATH + "/detail/Ticket/" + str(sg_ticket['id'])
    QDesktopServices.openUrl(QUrl(new_ticket_url))
Пример #11
0
def getAllProjects():
    
    site = 'https://chimneypot.shotgunstudio.com'    
    scriptName = 'AssetBrowser'
    scriptKey = 'c35ab5f5322d4b1e8b6488bb315c03e5f38881ea'    
    
    sg = Shotgun(site, scriptName, scriptKey)    

    fields = ['id','name','type']
    projects= sg.find("Project",[],fields)
    
    if len(projects) < 1:
        print "couldn't find any projects"
        #exit(0)
    else:
        print "Found "+str(len(projects))+" projects"
#        pprint (projects)
    
    return projects 
Пример #12
0
def getShotsBySeqId(seq_id):

    site = 'https://chimneypot.shotgunstudio.com'
    scriptName = 'AssetBrowser'
    scriptKey = 'c35ab5f5322d4b1e8b6488bb315c03e5f38881ea'

    sg = Shotgun(site, scriptName, scriptKey)

    fields = ['id', 'type', 'code']
    filters = [['sg_sequence', 'is', {'type': 'Sequence', 'id': seq_id}]]
    shots = sg.find("Shot", filters, fields)

    if len(shots) < 1:
        print "couldn't find any shots"
        #exit(0)
    else:
        None

    return shots
Пример #13
0
def getShotsBySeqId(seq_id):
    
    site = 'https://chimneypot.shotgunstudio.com'    
    scriptName = 'AssetBrowser'
    scriptKey = 'c35ab5f5322d4b1e8b6488bb315c03e5f38881ea'    
    
    sg = Shotgun(site, scriptName, scriptKey)

    fields = ['id','type','code']
    filters = [['sg_sequence','is',{'type':'Sequence','id':seq_id}]]
    shots= sg.find("Shot",filters,fields)
    
    if len(shots) < 1:
        print "couldn't find any shots"
        #exit(0)
    else:
        None   

    return shots
Пример #14
0
def getAllProjects():

    site = 'https://chimneypot.shotgunstudio.com'
    scriptName = 'AssetBrowser'
    scriptKey = 'c35ab5f5322d4b1e8b6488bb315c03e5f38881ea'

    sg = Shotgun(site, scriptName, scriptKey)

    fields = ['id', 'name', 'type']
    projects = sg.find("Project", [], fields)

    if len(projects) < 1:
        print "couldn't find any projects"
        #exit(0)
    else:
        print "Found " + str(len(projects)) + " projects"


#        pprint (projects)

    return projects
Пример #15
0
def setupLightFiles(cb010 = True, cb020 = True, cb030 = True, cb040 = True, cb050 = True, cb060 = True, optimizeEnv = True, rippleLyr = True, bgHillLyr = True, directory = 'I:/bubblebathbay/episodes', episode = 152, shots = 1):
	## Initialize Shotgun API
	base_url	= "http://bubblebathbay.shotgunstudio.com"
	script_name	= 'audioUploader'
	api_key		= 'bbfc5a7f42364edd915656d7a48d436dc864ae7b48caeb69423a912b930bc76a'
	sgsrv		= Shotgun(base_url = base_url , script_name = script_name, api_key = api_key, ensure_ascii = True, connect = True)

	## Query data from Shotgun
	data = sgsrv.find('Shot', filters = [["code", "contains", 'ep%s_sh' % episode]], fields = ['code', 'sg_cut_in', 'sg_cut_out', 'sg_tod', 'sg_ocean_type'])
	if data:
		if episode:
			if shots:

				for each in data:
					if each['code'].split('_')[-1].strip('sh') in shots:
						try:
							cmds.refresh(suspend = True)
							get_data_from_shotgun(cb010 = cb010, cb020 = cb020, cb030 = cb030, cb040 = cb040, cb050 = cb050, cb060 = cb060, optimizeEnv = optimizeEnv, rippleLyr = rippleLyr, bgHillLyr = bgHillLyr, directory = directory, **each)
						except:
							pass
						finally:
							cmds.refresh(suspend = False)
Пример #16
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
Пример #17
0
class dMFXsubmitterDialog(QDialog, Ui_dMFXsubmitter):
    def __init__(self, parent=None):
        # set up the UI and variable here - don't forget to call updateUI at end
        super(dMFXsubmitterDialog, self).__init__(parent)
        self.acceptDrops()
        self.setupUi(self)  # generic call to setup the Ui provided by Qt
        self.password = ''
        self.version_file_path = ''
        self.user = ''
        self.user_id = ''
        self.user_name = ''
        self.user_initials = ''
        self.submit_movie = False
        self.movie_file_path = ''
        self.description = ''
        self.login_status = False
        self.allOK = True
        self.submit_call_track = True
        self.version_type = 'Shot'
        self.created_version_id = None
        self.sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
        self.sgu = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
        self.users_with_initals = INITIALS_LIST
        self.user_list = []
        self.lineEdit_versionFile.dragEnterEvent = types.MethodType(
            dragEnterEvent, self.lineEdit_versionFile)
        self.lineEdit_versionFile.dropEvent = types.MethodType(
            dropEvent, self.lineEdit_versionFile)
        self.lineEdit_versionFile.setAcceptDrops(True)
        self.lineEdit_versionFile.setDragEnabled(True)
        self.lineEdit_forReview.dragEnterEvent = types.MethodType(
            dragEnterEvent, self.lineEdit_forReview)
        self.lineEdit_forReview.dropEvent = types.MethodType(
            dropEvent, self.lineEdit_forReview)
        self.lineEdit_forReview.setAcceptDrops(True)
        self.lineEdit_forReview.setDragEnabled(True)

        # start things happening... get the users from sg and populate them into the drop-down
        self.update_user_list()
        self.connect(self, SIGNAL('update'), self.updateUI)

        self.new_value = 'this is not a new value'
        #self.emit(SIGNAL("update"))
        self.updateUI()

    def update_user_list(self):
        filters = [
            ['sg_status_list', 'is', 'act'],
        ]
        fields = ['name', 'login']
        users = self.sg.find('HumanUser', filters, fields)
        user_list = [(user['name'], user['login'], user['id'])
                     for user in users if user['name'] != 'Template User']
        user_list.sort()
        self.user_list = user_list
        self.comboBox_artistSelect.addItem('Please Select...')
        self.user = '******'
        for user in user_list:
            self.comboBox_artistSelect.addItem(user[0])
        self.updateUI()

    def reset_to_go_again(self):
        # todo set all fields to blank, not just update the values...
        self.version_file_path = ''
        self.submit_movie = False
        self.movie_file_path = ''
        self.description = ''
        self.allOK = True
        self.created_version_id = None
        self.plainTextEdit_description.setPlainText('')
        self.lineEdit_versionFile.setText('')
        self.lineEdit_forReview.setText('')
        self.updateUI()

    def updateUI(self):
        # make sure that the UI is updated to match input
        self.activateWindow()  # window gets keyboard focus after redraw
        self.allOK = True
        self.description = str(self.plainTextEdit_description.toPlainText())

        # check user and if it needs initials, activate the text box
        if self.user in self.users_with_initals:
            self.lineEdit_initials.setEnabled(True)
        else:
            self.lineEdit_initials.setEnabled(False)

        # check user to see if one has been selected... set login to default if it has and there is no login set
        if self.user == STARTING_USER_LIST_TEXT:
            self.pushButton_login.setEnabled(False)
        else:
            self.pushButton_login.setEnabled(True)
            if not self.login_status:
                self.pushButton_login.setDefault(True)

        # check to see if logged in - if not, disable everything below login
        if self.login_status:
            self.label_password.setText("** Logged In **")
            self.pushButton_login.setEnabled(False)
            self.comboBox_artistSelect.setEnabled(False)
        else:
            self.label_password.setText("Shotgun Password")
            self.pushButton_login.setEnabled(True)

        # check the submit checkbox and enable fields if set
        if self.checkBox_forReview.isChecked():
            self.lineEdit_forReview.setEnabled(True)
            self.pushButton_getForReview.setEnabled(True)
            self.submit_movie = True

        # check for movie submit check-box
        if self.submit_movie:
            self.lineEdit_forReview.setEnabled(True)
            self.pushButton_getForReview.setEnabled(True)
        else:
            self.lineEdit_forReview.setEnabled(False)
            self.pushButton_getForReview.setEnabled(False)

        # check for a need for initals
        if self.user in INITIALS_LIST:
            self.label_initials.setText('Add Your Initials')
            self.lineEdit_initials.show()
        else:
            self.label_initials.setText('')
            self.lineEdit_initials.hide()
            self.user_initials = ''
            self.lineEdit_initials.setText('')

        # check to see if the version file is a movie and, if so and the movie line is empty, fill that in
        if self.version_file_path and os.path.splitext(
                str(self.version_file_path).lower()
        )[1] in MOVIE_FILE_EXTENSION_LIST and not self.movie_file_path:
            self.movie_file_path = str(self.version_file_path)
            self.lineEdit_forReview.setText(self.movie_file_path)

        # check for conditions that allow an update to happen
        conditions = True  # start by assuming we can go and switch if we can't
        if self.user in INITIALS_LIST and not self.user_initials:
            conditions = False
        if conditions and not self.login_status:
            conditions = False
        if conditions and self.version_file_path and not os.path.exists(
                self.version_file_path):
            conditions = False
        if conditions and self.submit_movie:
            if self.movie_file_path and not os.path.exists(
                    self.movie_file_path):
                conditions = False
            if not self.movie_file_path:
                conditions = False

        #enable the submit button if appropriate
        if conditions:
            self.pushButton_submit.setEnabled(True)
            self.pushButton_submit.setDefault(True)
        else:
            self.pushButton_submit.setEnabled(False)

    # self.pushButton_login
    @pyqtSignature("")
    def on_pushButton_login_clicked(self):
        result = self.sgu.authenticate_human_user(
            self.user_name, self.lineEdit_password.text())
        if result:
            self.login_status = True
        else:
            # user tried to log in and failed - let them know
            QMessageBox.about(
                self, "Log In Error",
                "Unable to login to Shotgun using your user/pass combination, please try again"
            )
        self.updateUI()

    # self.pushButton_getVersionFile
    @pyqtSignature("")
    def on_pushButton_getVersionFile_clicked(self):
        self.version_file_path = str(
            QFileDialog.getOpenFileName(
                self, "Select the file to submit as a Version"))
        if self.version_file_path:
            self.lineEdit_versionFile.setText(self.version_file_path)
        self.updateUI()

    # self.pushButton_getForReview
    @pyqtSignature("")
    def on_pushButton_getForReview_clicked(self):
        self.movie_file_path = str(
            QFileDialog.getOpenFileNameAndFilter(
                self,
                "Select a movie file to submit for screening",
                filter="Movies ( *.mp4 *.mov)")
            [0])  # the getopenfile returns a tuple of length 2
        if self.movie_file_path:
            self.lineEdit_forReview.setText(self.movie_file_path)
        self.updateUI()

    # self.pushButton_quit
    @pyqtSignature("")
    def on_pushButton_quit_clicked(self):
        QApplication.quit()

    # self.checkBox_forReview
    @pyqtSignature("bool")
    def on_checkBox_forReview_clicked(self):
        #lcheckBox_forReview boolean toggle code here
        self.submit_movie = self.checkBox_forReview.isChecked()
        self.updateUI()

    # self.comboBox_artistSelect
    @pyqtSignature("QString")
    def on_comboBox_artistSelect_currentIndexChanged(self):
        if self.user:
            self.user = self.comboBox_artistSelect.currentText()
            self.user_name = [
                user[1] for user in self.user_list if user[0] == self.user
            ][0]
            self.user_id = [
                user[2] for user in self.user_list if user[0] == self.user
            ][0]
        self.updateUI()

    # self.comboBox_version_type
    @pyqtSignature("QString")
    def on_comboBox_version_type_currentIndexChanged(self):
        self.version_type = str(self.comboBox_version_type.currentText())
        self.updateUI()

    # self.lineEdit_forReview
    @pyqtSignature("QString")
    def on_lineEdit_forReview_textEdited(self):
        self.movie_file_path = str(self.lineEdit_forReview.text())
        self.emit(SIGNAL("update"))

    # self.lineEdit_initials
    @pyqtSignature("QString")
    def on_lineEdit_initials_textEdited(self):
        self.user_initials = str(self.lineEdit_initials.text())
        self.updateUI()

    # self.lineEdit_versionFile
    @pyqtSignature("QString")
    def on_lineEdit_versionFile_textEdited(self):
        self.version_file_path = str(self.lineEdit_versionFile.text())
        self.updateUI()

    # self.lineEdit_versionFile
    @pyqtSignature("QString")
    def on_lineEdit_versionFile_textChanged(self):
        self.version_file_path = str(self.lineEdit_versionFile.text())
        self.updateUI()

    # self.plainTextEdit_description
    @pyqtSignature("")
    def on_plainTextEdit_description_textEdited(self):
        self.updateUI()

    # self.pushButton_submit
    @pyqtSignature("")
    def on_pushButton_submit_clicked(self):
        if not self.submit_call_track:
            self.submit_call_track = True
            return
        else:
            self.submit_call_track = False

        sgerrmsg = "There were no matching {0}s, make sure that you have selected the right kind of entity and try again"
        if not self.allOK:
            return
        try:
            self.created_version_id = update_shotgun(
                self.sg, self.version_file_path, self.description,
                self.user_id, self.version_type, self.user_initials, self)
            if not self.created_version_id:  # sg did not find anything! Tell the user and let them try again or quit
                self.allOK = False
                sub_dialog = dMFXsubmitterSubDialog("No Matches",
                                                    "Reset",
                                                    "QUIT!",
                                                    sgerrmsg.format(
                                                        self.version_type),
                                                    boxeditable=False,
                                                    parent=self)
                button, text, pick = sub_dialog.getValues()
                if sub_dialog.exec_():
                    sub_dialog.close()
                    button, text, pick = sub_dialog.getValues()
                    if button == 'No':
                        QApplication.quit()
                    else:
                        return  # return if they click on Retry
                else:
                    return  # return if they close the window

            mainlabel = "Success!"
            yeslabel = 'Go Again'
            nolabel = 'QUIT!'
            boxtext = 'Your version was successfully created'

            if self.allOK and self.submit_movie:
                if not do_submit_for_review(self.sg, self.movie_file_path,
                                            self.created_version_id):
                    # the sym-link failed for some reason after 2 tries...
                    mainlabel = "Partial Success..."
                    boxtext = "Your version was created but the movie was NOT put into today's Review Folder. Please add it manually, or resubmit the Version"

        except Exception, e:
            mainlabel = "ERROR!"
            yeslabel = 'Reset'
            nolabel = 'QUIT!'
            boxtext = 'Something Went Horribly Wrong! -\nError: {0}\n{1}'.format(
                e, traceback.format_exc())

        #QMessageBox.about(self, "updateUI", output_string)
        sub_dialog = dMFXsubmitterSubDialog(mainlabel, yeslabel, nolabel,
                                            boxtext)
        if sub_dialog.exec_():
            sub_dialog.close()
            button, text, pick = sub_dialog.getValues()
            if button == 'No':
                QApplication.quit()
            else:
                self.reset_to_go_again()
Пример #18
0
class MainUI(QtGui.QWidget):
    def __init__(self, app):
        """
		main UI for STATIC ENV handling

		I always build my UI in __init__ so suck it up..

		"""
        QtGui.QWidget.__init__(self)
        self.app = app
        context = self.app.context
        self.fileBoxes = []
        ## 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.shotNum = self._getShotNum()[0]
        self.currentENV = self._getShotNum()[1]

        debug(self.app,
              method='MainUI',
              message='self.shotNum: %s' % self.shotNum,
              verbose=False)
        debug(self.app,
              method='MainUI',
              message='self.currentENV: %s' % self.currentENV,
              verbose=False)
        self.lightAlembicFolder = 'I:/lsapipeline/episodes/ep000/%s/Light/publish/alembic_anim' % self.shotNum

        ## Now build the UI
        self.mainLayout = QtGui.QHBoxLayout(self)
        self.leftSideLayout = QtGui.QVBoxLayout(self)
        debug(self.app,
              method='MainUI',
              message='self.mainLayout built...',
              verbose=False)

        ##########################
        ### ENV SELECTION PULLDOWN
        self.envLayout = QtGui.QVBoxLayout(self)
        self.envPulldown = QtGui.QComboBox()

        getENVS = self.sgsrv.find(
            'Asset',
            filters=[["code", "contains", 'ENV_'],
                     ["code", "not_contains", '_ENV_'],
                     ["code", "not_contains", 'WORLDMAP'],
                     ["code", "not_contains", 'TSETbuild']],
            fields=['code'])
        debug(self.app,
              method='MainUI',
              message='getENVS: %s' % getENVS,
              verbose=False)

        if self.shotNum:
            for each in getENVS:
                if each['code'] == self.currentENV:
                    self.envPulldown.addItem(each['code'])
                    self.lightAlembicFolder = 'I:/lsapipeline/episodes/ep000/%s/Light/publish/alembic_anim' % self.shotNum

            self.envPulldown.setCurrentIndex(
                self.envPulldown.findText(self.currentENV))
            debug(self.app,
                  method='MainUI',
                  message='self.envPulldown setCurrentIndex...',
                  verbose=False)
        else:
            for each in getENVS:
                if 'ANIM' in each['code']:
                    self.envPulldown.addItem(each['code'])

        self.fetchAssetListButton = QtGui.QPushButton(Icon('refresh.png'),
                                                      'Fetch Asset List')
        self.fetchAssetListButton.setStyleSheet(
            "QPushButton {text-align : left}")
        self.fetchAssetListButton.released.connect(self._fetchAssetList)
        debug(self.app,
              method='MainUI',
              message='self.fetchAssetListButton built...',
              verbose=False)

        self.importAssetButton = QtGui.QPushButton(Icon('alembic.png'),
                                                   'Import latest Pub ABC')
        self.importAssetButton.setStyleSheet("QPushButton {text-align : left}")
        self.importAssetButton.released.connect(self._fetchMDLAlembicPublish)
        debug(self.app,
              method='MainUI',
              message='self.importAssetButton built...',
              verbose=False)

        self.checkMDLButton = QtGui.QPushButton(Icon('refresh.png'),
                                                'Check For RIG Publishes')
        self.checkMDLButton.setStyleSheet("QPushButton {text-align : left}")
        self.checkMDLButton.released.connect(
            self._checkVersionsAgainstPublishes)
        debug(self.app,
              method='MainUI',
              message='self.checkMDLButton built...',
              verbose=False)

        self.checkSRFXMLButton = QtGui.QPushButton(Icon('refresh.png'),
                                                   'Check For SRF Publishes')
        self.checkSRFXMLButton.setStyleSheet("QPushButton {text-align : left}")
        self.checkSRFXMLButton.released.connect(
            self._checkSRFVersionsAgainstPublishes)

        self.lambert1Button = QtGui.QPushButton(Icon('refresh.png'),
                                                'Check lambert1 objects')
        self.lambert1Button.setStyleSheet("QPushButton {text-align : left}")
        self.lambert1Button.released.connect(self._lambert1Object)

        self.checkFileInPathButton = QtGui.QPushButton(
            Icon('refresh.png'), 'Check Invalid FileIn Path')
        self.checkFileInPathButton.setStyleSheet(
            "QPushButton {text-align : left}")
        self.checkFileInPathButton.released.connect(self.checkFileInPath)

        self.checkNonManifoldButton = QtGui.QPushButton(
            Icon('refresh.png'), 'Check Non-Manifold Geometry')
        self.checkNonManifoldButton.setStyleSheet(
            "QPushButton {text-align : left}")
        self.checkNonManifoldButton.released.connect(
            self.cleanupNonManifoldGeometry)

        if context.step['name'] == 'Anm':
            self.creaseXMLButton = QtGui.QPushButton('Create crease XML')
            self.creaseXMLButton.released.connect(self._writeCreaseToXML)
            self.creaseXMLButton.setEnabled(True)

        if context.step['name'] == 'Light':
            self.fetchCreaseXMLButton = QtGui.QPushButton(
                'Fetch latest published crease XML')
            self.fetchCreaseXMLButton.released.connect(
                partial(self._getCreaseFromXML,
                        rootPrefix='ENV_DOCKS_STATICANIM_ABC_ANIM_CACHES_hrc'))
            self.fetchCreaseXMLButton.setEnabled(True)

        self.republishALL = QtGui.QPushButton('Publish ABC from ANM')
        self.republishALL.released.connect(self._republishAllAlembicsForENV)
        self.republishALL.setEnabled(True)

        ## Add stuff to the env layout
        self.envLayout.addWidget(self.envPulldown)
        self.envLayout.addWidget(self.fetchAssetListButton)
        self.envLayout.addWidget(self.importAssetButton)
        self.envLayout.addWidget(self.checkMDLButton)
        self.envLayout.addWidget(self.checkSRFXMLButton)
        self.envLayout.addWidget(self.lambert1Button)
        self.envLayout.addWidget(self.checkFileInPathButton)
        self.envLayout.addWidget(self.checkNonManifoldButton)
        self.envLayout.addWidget(self.republishALL)
        if context.step['name'] == 'Anm':
            self.envLayout.addWidget(self.creaseXMLButton)
        if context.step['name'] == 'Light':
            self.envLayout.addWidget(self.fetchCreaseXMLButton)

        ######################
        ### ENV RELATED ASSETS
        self.assetLayout = QtGui.QVBoxLayout(self)

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

        self.envAssetsGroupBox = QtGui.QGroupBox(self.scrollLayout)
        self.envAssetsGroupBox.setFlat(True)

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

        self.envAssetsLayout = QtGui.QGridLayout(self.envAssetsGroupBox)

        self.assetLayout.addWidget(self.scrollLayout)

        self.mainLayout.addLayout(self.leftSideLayout)
        ## Add stuff to leftSideLayout
        self.leftSideLayout.addLayout(self.envLayout)
        self.leftSideLayout.addStretch(1)

        ## Add anything else to the HBox
        self.mainLayout.addLayout(self.assetLayout)
        self.resize(1000, 500)
        debug(self.app,
              method='MainUI',
              message='ui built successfully fetching assets now...',
              verbose=False)
        debug(self.app,
              method='MainUI',
              message='self.envPulldown.currentText(): %s' %
              self.envPulldown.currentText(),
              verbose=False)

        self._fetchAssetList()
        self.envPulldown.currentIndexChanged.connect(
            partial(self._getShotNumFromMenuName))
        self.envPulldown.currentIndexChanged.connect(
            partial(self._fetchAssetList))

    def _prettyPrintXML(self, elem, level=0):
        i = '\n' + level * '	'
        if len(elem):
            if not elem.text or not elem.text.strip():
                elem.text = i + '	'
            if not elem.tail or not elem.tail.strip():
                elem.tail = i
            for elem in elem:
                self._prettyPrintXML(elem, level + 1)
            if not elem.tail or not elem.tail.strip():
                elem.tail = i
        else:
            if level and (not elem.tail or not elem.tail.strip()):
                elem.tail = i

    def _getCreaseFromXML(self, rootPrefix=''):
        scene_path = os.path.abspath(cmds.file(query=True, sn=True))
        xmlPath = '%s/Anm/publish/crease_xml/ep000_Docks_Addon.xml' % '/'.join(
            os.path.abspath(cmds.file(query=True, sn=True)).replace(
                '\\', '/').split('/')[:5]) if scene_path else ''

        print xmlPath

        if os.path.isfile(xmlPath):
            tree = ET.parse(xmlPath)
            root = tree.getroot()
            if root.tag == 'CreaseXML':

                for mesh in root.getchildren():
                    mesh_name = mesh.attrib.get('name')
                    mesh_name = '|'.join(
                        [x.split(':')[-1] for x in mesh_name.split('|')])
                    mesh_name = '%s%s' % (
                        rootPrefix, mesh_name) if rootPrefix else mesh_name

                    if cmds.objExists(mesh_name):
                        for edge in mesh.getchildren():
                            vertexA = int(edge.attrib.get('vertexA'))
                            vertexB = int(edge.attrib.get('vertexB'))
                            creaseValue = edge.attrib.get('creaseValue')
                            edgeID = cmds.polyListComponentConversion(
                                '%s.vtx[%d]' % (mesh_name, vertexA),
                                '%s.vtx[%d]' % (mesh_name, vertexB),
                                fromVertex=1,
                                toEdge=1,
                                internal=1)[0].split('.')[-1]

                            if '-inf' not in creaseValue:
                                cmds.polyCrease('%s.%s' % (mesh_name, edgeID),
                                                value=float(creaseValue))
                    else:
                        cmds.warning('%s doesn\'t exist, skipping...' %
                                     mesh_name)
            else:
                cmds.warning('Not a valid xml...')
        else:
            cmds.warning('Not a valid crease xml path...')

    def _writeCreaseToXML(self):
        scene_path = os.path.abspath(
            cmds.file(query=True, sn=True)
        )  # I:\bubblebathbay\episodes\ep106\ep106_sh030\FX\work\maya\ep106sh030.v025.ma
        xmlPath = '%s/publish/crease_xml/ep000_Docks_Addon.xml' % '/'.join(
            os.path.abspath(cmds.file(query=True, sn=True)).replace(
                '\\', '/').split('/')[:6]) if scene_path else ''

        if os.path.isdir(os.path.dirname(xmlPath)):
            ## Get all mesh in scene with all their edges intact i.e. |pCube1|pCubeShape1.e[0:11] (Filter out intermediate object as well as they don't get cache out)
            meshes = [
                '%s.e[0:%s]' % (mesh, cmds.polyEvaluate(mesh, edge=True) - 1)
                for mesh in cmds.ls(type='mesh', long=True)
                if not cmds.getAttr('%s.intermediateObject' % mesh)
                if cmds.polyEvaluate(mesh, edge=True)
            ]
            if meshes:
                edge_creases = []

                for mesh in meshes:
                    mesh_name = mesh.split('.')[0]
                    edges = cmds.polyCrease(mesh, value=True, q=True)

                    if edges:
                        crease_edges = []
                        for edge, value in enumerate(edges, start=0):
                            if value > 0:  ## 0 means no crease, more than 0 means crease...

                                ## 2 vertices = 1 edge. Therefore, get edge's vertices id...
                                crease_edges.append((
                                    filter(
                                        None,
                                        cmds.polyInfo(
                                            '%s.e[%s]' % (mesh_name, edge),
                                            edgeToVertex=True)[0].split(':')
                                        [-1].replace('Hard', '').replace(
                                            '\n',
                                            '').split(' '))[0],  ## Vertex A
                                    filter(
                                        None,
                                        cmds.polyInfo(
                                            '%s.e[%s]' % (mesh_name, edge),
                                            edgeToVertex=True)[0].split(':')
                                        [-1].replace('Hard', '').replace(
                                            '\n',
                                            '').split(' '))[1],  ## Vertex B
                                    str(
                                        value
                                    ),  ## Crease value (Reason why we put it as string is because somehow maya sometimes return value "-inf" which's going to be troublesome when applying crease to poly later...
                                ))
                        edge_creases.append(
                            (mesh_name,
                             crease_edges)) if crease_edges else None

                if edge_creases:
                    ## Process root
                    root = ET.Element('CreaseXML')

                    for each in edge_creases:
                        mesh = '|'.join(
                            [x.split(':')[-1] for x in each[0].split('|')]
                        )  ## Get rid of object names that has ":" in it as it will be stripped out during alembic cache anyways...
                        if 'geo_hrc' in mesh:
                            mesh = '|%s' % '|'.join(
                                mesh.split('|')[([
                                    i for
                                    (i,
                                     x) in enumerate(mesh.split('|'), start=0)
                                    if x == 'geo_hrc'
                                ][0] - 1):]
                            )  ## Get full name until root of geo_hrc

                        meshElem = ET.SubElement(root, 'Mesh')
                        meshElem.set('name', mesh)

                        for child in each[1]:
                            vertexA = child[0]
                            vertexB = child[1]
                            creaseValue = child[2]

                            edgeElem = ET.SubElement(meshElem, 'Edge')
                            edgeElem.set('vertexA', vertexA)
                            edgeElem.set('vertexB', vertexB)
                            edgeElem.set('creaseValue', creaseValue)

                    ## Make directory if it doesn't exist
                    if not os.path.exists(os.path.dirname(xmlPath)):
                        os.makedirs(os.path.dirname(xmlPath))

                    ## Process XML to output nicely so it's human readable i.e. not everything in 1 line
                    self._prettyPrintXML(root)
                    tree = ET.ElementTree(root)

                    ## Output .xml into directory
                    tree.write(xmlPath, encoding='utf-8')

    def arraysMatch(self, a, b):
        '''
		Utility to compare two string list
		'''
        return True if a == b else False

    def cleanupNonManifoldGeometry(self, normals=True):
        ## Get all the mesh that has mentalraySubdivApprox connected and has non-manifold problem
        # subdiv_mesh = [cmds.listRelatives(mesh, parent = True, fullPath = True)[0] for mesh in cmds.ls(type = 'mesh') if cmds.listConnections(mesh, type = 'mentalraySubdivApprox') if cmds.polyInfo(mesh, nme = True) or cmds.polyInfo(nmv = True)]
        subdiv_mesh = [
            cmds.listRelatives(mesh, parent=True, fullPath=True)[0]
            for mesh in cmds.ls(type='mesh')
            if cmds.polyInfo(mesh, nme=True) or cmds.polyInfo(nmv=True)
        ]
        subdiv_mesh = list(set(subdiv_mesh))

        if subdiv_mesh:
            for each in subdiv_mesh:
                ## Make sure we do indeed have nonmanifold geometry
                ##
                nonManifold = cmds.polyInfo(each, nmv=True, nme=True)
                if nonManifold:

                    proceed = cmds.confirmDialog(
                        title='Non-Manifold Geometry!',
                        message='Geo Name:\n%s' % each,
                        button=['Cleanup!', 'Skip...'],
                        defaultButton='Skip...',
                        cancelButton='Skip...',
                        dismissString='Skip...')
                    if proceed == 'Cleanup!':

                        ## Conform the geo and see if that gets rid of all the nonmanifold bits
                        ##
                        if normals:
                            cmds.polyNormal('%s.f[*]' % each,
                                            normalMode=2,
                                            constructionHistory=True)

                        edges = cmds.polyInfo(each, nme=True) if cmds.polyInfo(
                            each, nme=True) else []
                        vertices = [] if edges else cmds.polyInfo(each,
                                                                  nmv=True)
                        lastEdges = []
                        lastVertices = []

                        while (not self.arraysMatch(lastEdges, edges)
                               or not self.arraysMatch(lastVertices, vertices)
                               ) and (edges or vertices):
                            ## Remember what was nonmanifold last time
                            ##
                            lastEdges = edges
                            lastVertices = vertices
                            ## Split any nonmanifold edges
                            ##
                            if edges:
                                cmds.polySplitEdge(edges,
                                                   constructionHistory=True)
                                vertices = cmds.polyInfo(each, nmv=True)
                                edges = []

                            ## Split any remaining nonmanifold vertices
                            ##
                            if vertices:
                                cmds.polySplitVertex(vertices,
                                                     constructionHistory=True)
                                vertices = []

                            ## Now check to see if the object is still nonmanifold
                            ##
                            nonManifold = cmds.polyInfo(each,
                                                        nmv=True,
                                                        nme=True)
                            if nonManifold:
                                ## Chip off the faces
                                ##
                                nonManifoldFaces = cmds.polyListComponentConversion(
                                    nonManifold, toFace=True)
                                cmds.polyChipOff(nonManifoldFaces,
                                                 kft=0,
                                                 dup=0,
                                                 constructionHistory=True)
                                ## And then check for nonmanifold bits again
                                ##
                                edges = cmds.polyInfo(each, nme=True)
                                if not edges:
                                    vertices = cmds.polyInfo(each, nmv=True)

                        ## Check to see if we failed to cleanup
                        if edges or vertices:
                            cmds.warning(
                                'Failed to cleanup non-manifold geometry of %s...'
                                % each)

    def _lambert1Object(self):
        ## Delete sets first
        if cmds.objExists('lambert1_object_set'):
            cmds.delete('lambert1_object_set')

        lambert1 = cmds.ls(cmds.sets('initialShadingGroup', q=True), long=True)
        if lambert1:
            lambert1 = [
                x.split('.f')[0] for x in lambert1
                if cmds.objectType(x) == 'mesh' and 'CArch' not in x
            ]

        ## Create sets if bad stuffs detected
        if lambert1:
            cmds.sets(lambert1, name='lambert1_object_set')

    def checkFileInPath(self):
        ## Delete sets first
        if cmds.objExists('invalid_fileIn_path_set'):
            cmds.delete('invalid_fileIn_path_set')

        fileIn = cmds.ls(type='file')
        fileIn.extend(cmds.ls(type='mentalrayTexture'))
        if fileIn:
            badFileInPath = [
                x for x in fileIn
                if not os.path.exists(cmds.getAttr('%s.fileTextureName' % x))
            ]

            ## Create sets if bad stuffs detected
            if badFileInPath:
                cmds.sets(badFileInPath, name='invalid_fileIn_path_set')

    def _toggleCBx(self, chbx='', wtfami=''):
        """
		Function to select on checkbox toggle
		@param chbx: the QCheckbox
		@param wtfami: WHO THE HELL KNOWS!!????!!!!!!!!
		@type chbox: PyQt Object
		:return:
		"""
        if chbx.isChecked():
            cmds.select('%s_hrc' % chbx.text(), add=True)
        else:
            cmds.select('%s_hrc' % chbx.text(), d=True)

    def _getShotNum(self):
        self.workSpace = cmds.workspace(q=True, fn=True)
        debug(self.app,
              method='_getShotNum',
              message='self.workSpace: %s' % self.workSpace,
              verbose=False)
        envName = ''
        shotNum = ''

        if 'ep000_Docks_Addon' in self.workSpace:
            envName = 'ENV_DOCKS_STATICANIM'
            shotNum = 'ep000_Docks_Addon'
        else:
            envName = None
            shotNum = None

        return shotNum, envName

    def _getShotNumFromMenuName(self, index=''):
        self.workSpace = cmds.workspace(q=True, fn=True)
        envName = ''
        shotNum = ''

        if self.envPulldown.currentText() == 'ENV_DOCKS_STATICANIM':
            shotNum = 'ep000_Docks_Addon'
        else:
            shotNum = None

        return shotNum

    def _addVersionTag(self, assetName, versionNumber):
        if cmds.objExists('%s.rigVersion' % assetName):
            cmds.deleteAttr('%s.rigVersion' % assetName)
        try:
            cmds.addAttr(assetName, ln='rigVersion', at='long', dv=0)
        except:
            pass

        cmds.setAttr('%s.rigVersion' % assetName, int(versionNumber))

    def _checkVersionsAgainstPublishes(self):
        ## Path to the assets folder
        pathToAssets = "I:/lsapipeline/assets"
        character_rootdirs = [
            os.path.join(pathToAssets, dir).replace('\\', '/')
            for dir in os.listdir(pathToAssets)
            if 'Character' in dir or 'Building' in dir
        ]
        character_subdirs = [
            os.path.join(rootDir, subDir).replace('\\', '/')
            for rootDir in character_rootdirs for subDir in os.listdir(rootDir)
            if 'CHAR_' in subDir or '_BLD' in subDir
        ]
        RIGVersNum = ''

        ## Fetch the subAssets for the ENV
        getData = self.sgsrv.find(
            'Asset',
            filters=[["code", "is",
                      self.envPulldown.currentText()]],
            fields=['code', 'id', 'assets'])

        ## Now can the checkboxes and see which assets arechecked
        if self.fileBoxes:
            for eachAsset in self.fileBoxes:
                if eachAsset.isChecked():
                    for eachSGAsset in getData[0]['assets']:
                        if eachSGAsset['name'] == eachAsset.text():

                            assetFolder = [
                                subDir for subDir in character_subdirs if
                                os.path.basename(subDir) in eachSGAsset['name']
                            ][0]
                            assetPublishFolder = '%s/RIG/publish/maya' % assetFolder if assetFolder else None

                            if os.path.isdir(assetPublishFolder):
                                try:
                                    getLatestPublish = max(
                                        os.listdir(assetPublishFolder))
                                except:
                                    getLatestPublish = []

                                if getLatestPublish and getLatestPublish.endswith(
                                        '.mb'):
                                    RIGVersNum = int(
                                        getLatestPublish.split('.')[-2].split(
                                            'v')[-1])

                            try:
                                getAssetVersion = cmds.getAttr(
                                    '%s_hrc.rigVersion' % eachAsset.text())
                            except ValueError:
                                getAssetVersion = None

                            if getAssetVersion:
                                if not getAssetVersion == RIGVersNum:
                                    print '!!HIGHER VER EXISTS: %s_hrc:%s \t %s' % (
                                        eachAsset.text(), getAssetVersion,
                                        getLatestPublish)
                                    eachAsset.setStyleSheet(
                                        "QCheckBox{background-color: red}")
                                else:
                                    eachAsset.setStyleSheet(
                                        "QCheckBox{background-color: green}")
                                    eachAsset.setChecked(False)
                                    print 'PASSED: version match %s' % (
                                        getLatestPublish)
                            else:
                                eachAsset.setStyleSheet(
                                    "QCheckBox{background-color: red}")
                                cmds.warning(
                                    '%s IS MISSING VERSION INFORMATION! PLEASE FIX!!!'
                                    % eachAsset.text())

            for eachAsset in self.fileBoxes:
                if eachAsset.isChecked() and eachAsset.text() == 'ALL':
                    eachAsset.setChecked(False)
                    eachAsset.setStyleSheet(
                        "QCheckBox{background-color: green}")

    def _checkSRFVersionsAgainstPublishes(self):
        ## Path to the assets folder
        pathToAssets = "I:/lsapipeline/assets"
        character_rootdirs = [
            os.path.join(pathToAssets, dir).replace('\\', '/')
            for dir in os.listdir(pathToAssets)
            if 'Character' in dir or 'Building' in dir
        ]
        character_subdirs = [
            os.path.join(rootDir, subDir).replace('\\', '/')
            for rootDir in character_rootdirs for subDir in os.listdir(rootDir)
            if 'CHAR_' in subDir or '_BLD' in subDir
        ]
        XMLVersNum = ''

        ## Fetch the subAssets for the ENV
        getData = self.sgsrv.find(
            'Asset',
            filters=[["code", "is",
                      self.envPulldown.currentText()]],
            fields=['code', 'id', 'assets'])

        ## Now can the checkboxes and see which assets are checked
        if self.fileBoxes:
            for eachAsset in self.fileBoxes:
                if eachAsset.isChecked():
                    #print 'Checking %s ...' % eachAsset.text()
                    for eachSGAsset in getData[0]['assets']:
                        if eachSGAsset['name'] == eachAsset.text():

                            assetFolder = [
                                subDir for subDir in character_subdirs if
                                os.path.basename(subDir) in eachSGAsset['name']
                            ][0]
                            assetPublishFolder = '%s/SRF/publish/xml' % assetFolder if assetFolder else None

                            if os.path.isdir(assetPublishFolder):
                                try:
                                    getLatestPublish = max(
                                        os.listdir(assetPublishFolder))
                                except:
                                    getLatestPublish = []

                                if getLatestPublish and getLatestPublish.endswith(
                                        '.xml'):
                                    XMLVersNum = int(
                                        getLatestPublish.split('.')[-2].split(
                                            'v')[-1])

                            try:
                                getAssetSRFVersion = cmds.getAttr(
                                    '%s_hrc.SRFversion' % eachAsset.text())
                            except ValueError:
                                getAssetSRFVersion = None

                            if getAssetSRFVersion:
                                if not getAssetSRFVersion == XMLVersNum:
                                    print '!!HIGHER VER EXISTS: %s_hrc:%s \t %s' % (
                                        eachAsset.text(), getAssetSRFVersion,
                                        getLatestPublish)
                                    eachAsset.setStyleSheet(
                                        "QCheckBox{background-color: red}")
                                else:
                                    eachAsset.setStyleSheet(
                                        "QCheckBox{background-color: green}")
                                    eachAsset.setChecked(False)
                                    print 'PASSED: version match %s' % (
                                        getLatestPublish)
                            else:
                                eachAsset.setStyleSheet(
                                    "QCheckBox{background-color: red}")
                                cmds.warning(
                                    '%s IS MISSING VERSION INFORMATION! PLEASE FIX!!!'
                                    % eachAsset.text())

            for eachAsset in self.fileBoxes:
                if eachAsset.isChecked() and eachAsset.text() == 'ALL':
                    eachAsset.setChecked(False)
                    eachAsset.setStyleSheet(
                        "QCheckBox{background-color: green}")

    def _checkVersionNumber(self, assetName, versionNumber, attrType):
        """
		Returns if the version number for an asset in the scene matches that of the asset in the static_folder
		"""
        foundVersion = False

        ## Path to the assets folder
        pathToAssets = "I:/lsapipeline/assets"
        character_rootdirs = [
            os.path.join(pathToAssets, dir).replace('\\', '/')
            for dir in os.listdir(pathToAssets)
            if 'Character' in dir or 'Building' in dir
        ]
        character_subdirs = [
            os.path.join(rootDir, subDir).replace('\\', '/')
            for rootDir in character_rootdirs for subDir in os.listdir(rootDir)
            if 'CHAR_' in subDir or '_BLD' in subDir
        ]

        assetFolder = [
            subDir for subDir in character_subdirs
            if os.path.basename(subDir) in assetName
        ][0]
        assetPublishFolder = ''
        if attrType == 'RIG':
            assetPublishFolder = '%s/RIG/publish/maya' % assetFolder if assetFolder else None
        elif attrType == 'SRF':
            assetPublishFolder = '%s/SRF/publish/xml' % assetFolder if assetFolder else None

        if os.path.isdir(assetPublishFolder):
            try:
                getLatestPublish = max(os.listdir(assetPublishFolder))
            except:
                getLatestPublish = []

            if getLatestPublish:
                getlatestVersionNum = int(
                    getLatestPublish.split('.')[-2].split('v')[-1])
                if int(versionNumber) == int(getlatestVersionNum):
                    foundVersion = True
            else:
                cmds.warning(
                    'There is no asset for %s found in the lighting anim alembic folder.'
                    % assetName)

        return foundVersion

    def _fetchAssetList(self, index=''):
        getData = self.sgsrv.find(
            'Asset',
            filters=[["code", "is",
                      self.envPulldown.currentText()]],
            fields=['code', 'id', 'assets'])
        debug(self.app,
              method='_fetchAssetList',
              message='getData: %s' % getData,
              verbose=False)

        if self.fileBoxes:
            for each in self.fileBoxes:
                each.setParent(None)
                each = None

        self.fileBoxes = []

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

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

        self.colCount = 5
        r = 1
        c = 1

        if getData:
            for eachAsset in getData[0]['assets']:
                self.assetCheckBox = QtGui.QCheckBox(self)
                self.assetCheckBox.setChecked(False)
                self.assetCheckBox.setText(eachAsset['name'])
                self.assetCheckBox.toggled.connect(
                    partial(self._toggleCBx, self.assetCheckBox))
                self.fileBoxes.append(self.assetCheckBox)

                if cmds.objExists('%s_hrc' % eachAsset['name']):
                    self.assetCheckBox.setStyleSheet(
                        "QCheckBox{background-color: #0066CC}")

                    ## Now check the version of RIG and SRF
                    if cmds.objExists('%s_hrc.rigVersion' % eachAsset['name']):
                        if not self._checkVersionNumber(
                                eachAsset['name'],
                                cmds.getAttr(
                                    '%s_hrc.rigVersion' % eachAsset['name']),
                                attrType='RIG'):
                            self.assetCheckBox.setStyleSheet(
                                "QCheckBox{background-color: red}")
                    else:
                        self.assetCheckBox.setStyleSheet(
                            "QCheckBox{background-color: #990000}")
                        cmds.warning('Asset version attr not found on %s_hrc' %
                                     eachAsset['name'])
                else:
                    self.assetCheckBox.setStyleSheet(
                        "QCheckBox{background-color: red}")

                if c == self.colCount:
                    r = r + 1
                    c = 1

                self.envAssetsLayout.addWidget(self.assetCheckBox, r, c)
                c = c + 1

    def _toggleAll(self):
        """
		A quick toggle for all the type checkboxes to on or off
		"""
        for each in self.fileBoxes:
            if each.text() == 'ALL':
                each.setStyleSheet("QCheckBox{background-color: grey}")
                if each.isChecked():
                    for eachAsset in self.fileBoxes:
                        if eachAsset.text() != 'ALL':
                            eachAsset.setChecked(True)
                            eachAsset.setStyleSheet(
                                "QCheckBox{background-color: grey}")

                else:
                    for eachAsset in self.fileBoxes:
                        if eachAsset.text() != 'ALL':
                            eachAsset.setChecked(False)

    def _cleanupShit(self):
        try:
            cmds.delete(cmds.ls('rig_hrc'))
        except:
            pass
        try:
            cmds.delete(cmds.ls('parts_hrc'))
        except:
            pass
        try:
            cmds.delete(cmds.ls('collisionNurbsHulls'))
        except:
            pass

        for each in cmds.ls(type='transform'):
            if 'Constraint' in each:
                cmds.delete(each)

    def _fetchMDLAlembicPublish(self):
        """
		This function will find the checked assets, and then go off and get the latest published alembic asset from the asset folder
		None of this is done off the database btw..
		"""
        pathToAssets = 'I:/lsapipeline/assets'
        if self.shotNum:
            moveTo = 'I:/lsapipeline/episodes/ep000/%s/Light/publish/alembic_anim' % self.shotNum
        elif self._getShotNumFromMenuName():
            moveTo = 'I:/lsapipeline/episodes/ep000/%s/Light/publish/alembic_anim' % self._getShotNumFromMenuName(
            )
        else:
            cmds.warning(
                'This ENV is not a valid for processing using this tool!')
            return -1

        if os.path.isdir(moveTo):
            getData = self.sgsrv.find(
                'Asset',
                filters=[["code", "is",
                          self.envPulldown.currentText()]],
                fields=['code', 'id', 'assets'])
            subAssets = [
                '%s_hrc' % eachAsset['name']
                for eachAsset in getData[0]['assets']
                if cmds.objExists('%s_hrc' % eachAsset['name'])
            ]

            reimport_cache = True

            ## Prompt to continue here
            if subAssets:
                self.reply = cmds.confirmDialog(
                    title='Remove all sub assets?',
                    message=
                    'Warning you are about to remove all the sub assets!',
                    button=['Continue...', 'Skip Import'])
                if self.reply == 'Continue...':
                    ## Go through all the _hrc asset and delete the f**k off the scene ya go...
                    [cmds.delete(subAsset) for subAsset in subAssets]
                elif self.reply == 'Skip Import':
                    reimport_cache = False

            ## Find latest .abc alembic anim cache in ENV's published directory...
            if reimport_cache:
                try:
                    findLatest = max(os.listdir(moveTo))
                except:
                    findLatest = []
                if findLatest:
                    ## Create base group name template according to ENV's name...
                    if self.currentENV:
                        groupName = '%s_ABC_ANIM_CACHES_hrc' % self.currentENV
                    else:
                        groupName = '%s_ABC_ANIM_CACHES_hrc' % self.envPulldown.currentText(
                        )
                    ## Create the group if it doesn't exist...
                    if not cmds.objExists(groupName):
                        cmds.group(n=groupName, em=True)

                    try:
                        cmds.AbcImport('%s/%s' % (moveTo, findLatest),
                                       reparent=groupName,
                                       setToStartFrame=True)
                        self._cleanupShit()
                        self._fetchAssetList()
                    except RuntimeError:
                        cmds.warning('Failed to import cache! %s/%s' %
                                     (moveTo, findLatest))
                else:
                    cmds.warning('Nothing published for %s !' % self.shotNum)

    def _isRootFolderThere(self, rootFolder):
        """
		Method used to check if root folder is valid or not eg: I:/lsapipeline/assets
		@param rootFolder: The path to the root folder to check for
		@type rootFolder: String
		"""
        if not os.path.isdir(rootFolder):
            print 'No such root folder found: %s' % rootFolder
            return -1
        else:
            return 1

    def _importSingleCache(self, folderPath, parentGrp, cacheName):
        """
		Function to import the alembics and parent them to the right group
		@param folderPath: Path to the folder for the caches to import
		@param parentGrp: The name of the group to parent the alembics to.
		@type folderPath: String
		@type parentGrp: String
		"""
        try:
            findLatest = max(os.listdir(folderPath))
        except:
            findLatest = []

        if findLatest:
            try:
                cmds.AbcImport('%s/%s' % (folderPath, findLatest),
                               reparent=parentGrp,
                               setToStartFrame=True)
            except RuntimeError:
                cmds.warning('Failed to import cache! %s/%s' %
                             (folderPath, findLatest))
        else:
            cmds.warning('Nothing published for %s !' % cacheName)

    def _importCaches(self, folderPath, parentGrp):
        """
		Function to import the alembics and parent them to the right group
		@param folderPath: Path to the folder for the caches to import
		@param parentGrp: The name of the group to parent the alembics to.
		@type folderPath: String
		@type parentGrp: String
		"""
        for eachCache in os.listdir(folderPath):
            try:
                cmds.AbcImport('%s/%s' % (folderPath, eachCache),
                               reparent=parentGrp,
                               setToStartFrame=True)
            except RuntimeError:
                cmds.warning('Failed to import cache! %s/%s' %
                             (folderPath, eachCache))

    def _republishAllAlembicsForENV(self):
        """
		This helper will republish all the MDL alembic files from the most recently published mb files found in the assets folders
		for every asset associated to the ENV.

		getData = self.sgsrv.find('Asset',  filters = [["code", "is", eachENV]], fields=['code', 'id', 'assets'])
		Finds the ENV name and then gets a list of Sub Assets associated with it from the assets field.

		This is why we want every ENV to be the parent of an asset in the system appropriately.
		"""
        ## Path to the assets folder
        assetWorkFolder = 'I:/lsapipeline/episodes/ep000/%s/Anm/work/maya' % self.shotNum

        if os.path.isdir(assetWorkFolder):
            getLatestScene = [
                each for each in os.listdir(assetWorkFolder)
                if each.endswith('.ma')
            ]
            getLatestScene = max(getLatestScene)
            if getLatestScene:
                latestScene = '%s/%s' % (assetWorkFolder, getLatestScene)
                latestScene.replace("/", os.sep)
                alembicPath = latestScene.replace('Anm', 'Light').replace(
                    'work', 'publish').replace('.ma', '.abc').replace(
                        'maya', 'alembic_anim').replace('.v', '_ABC.v')
                ## Remove current alembic
                if os.path.isfile(alembicPath):
                    os.remove(alembicPath)

                ## Import the file so we don't have to display anything due to the files prob being saved with textures on etc
                sceneName = cmds.file(sceneName=True, q=True)
                if not sceneName == latestScene:
                    try:
                        cmds.file(latestScene, o=True, f=True)
                    except:
                        cmds.warning('Failed to open %s...' % latestScene)
                    cleanup.removeAllNS()

                ## Now export back out a new alembic with the version name that should exist in the assembly reference.
                roots = cmds.ls(type='transform')
                rootHrc = [
                    root for root in roots
                    if cmds.referenceQuery(root, isNodeReferenced=True)
                    if cmds.objExists('%s.type' % root)
                    if str(cmds.getAttr('%s.type' % root)).startswith('anim')
                ] if roots else None
                rootName = ' -root '.join(rootHrc) if rootHrc else None

                if rootName:
                    ## Change uv set map1 if the mesh has multiple uv sets for alembic cache
                    [
                        cmds.polyUVSet(each, currentUVSet=True, uvSet='map1')
                        for each in cmds.ls(type='mesh')
                    ]

                    ## Now scan the geo in the scene and preserve the crease information
                    for each in cmds.ls(type='mesh', l=True):
                        if not cmds.objExists('%s.SubDivisionMesh' % each):
                            try:
                                cmds.addAttr('%s' % each,
                                             ln='SubDivisionMesh',
                                             at='bool')
                                cmds.setAttr("%s.SubDivisionMesh" % each, 1)
                            except:
                                pass

                    ## Add custom attribute tag to check rig version if it doesn't exist...
                    for root in rootHrc:
                        rigVersion = int(
                            os.path.basename(
                                cmds.referenceQuery(root,
                                                    filename=True)).split('.')
                            [1].split('v')[-1])

                        if not cmds.objExists('%s.rigVersion' % root):
                            cmds.addAttr(root,
                                         longName='rigVersion',
                                         attributeType='long',
                                         dv=0)

                        cmds.setAttr('%s.rigVersion' % root, rigVersion)

                    minTime = cmds.playbackOptions(min=True, q=True)
                    maxTime = cmds.playbackOptions(max=True, q=True)
                    abc_export_cmd = "-attr smoothed -attr SubDivisionMesh -attr rigVersion -ro -uvWrite -wholeFrameGeo -worldSpace -writeVisibility -fr %d %d -root %s -file %s" % (
                        minTime, maxTime, rootName, alembicPath)
                    try:
                        [cmds.currentTime(minTime) for i in range(2)]
                        cmds.AbcExport(verbose=False, j=abc_export_cmd)
                        # cmds.file(new = True, force = True)
                    except:
                        cmds.warning("Failed to export Alembic Cache!!")
                else:
                    cmds.warning(
                        'Cannot find any proper _hrc with anim tag in this scene...'
                    )
Пример #19
0
def launch(progressBar, logLabel, filterDataList , app, projectContext = None, sg= None ) :
    
    


    SERVER_PATH = "https://nozon.shotgunstudio.com"
    SCRIPT_NAME = 'noteManager'     
    SCRIPT_KEY = '3fbb2a5f180457af709fcad231c96ac8a916711427af5a06c47eb1758690f6e4'

    if not sg :
        try :
            
            from shotgun_api3 import Shotgun
            sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)

        except :
            sg = app.engine.tank.shotgun
    
    projectId = None
    if projectContext :
        projectId = projectContext
    else :
        projectId = app.context.project

    today = datetime.datetime.utcnow().strftime("%Y%m%d")

    import os
    try :
        os.makedirs("c:/temp/EVENTLOG")
    except :
        pass

    if not progressBar :
        import glob
        test = outputLogFileName =  "c:/temp/EVENTLOG/eventManager_"+projectId["name"]+"_"+ "*" +".html"
        outputLogFileName =  "c:/temp/EVENTLOG/eventManager_"+projectId["name"]+"_"+ today +".html"
        if len(glob.glob(test)) :
            print "skiped"
            return 
    f = open(outputLogFileName, 'w')
    f.write("<!DOCTYPE html><html><head><title>Page Title</title></head><body><dir>")


    def cout(text) :
        
        text = text.replace(" ","&nbsp;")
        text = text.replace("\n","<br>")
        text = text.replace("<font&nbsp;color=","<font color=")
        f.write(str(text)+"<br>\n")






    eventFilter_List=[]
    if not filterDataList :
        filterEvent = event_filter()
        filterEvent.massTest = 60.0
        eventFilter_List.append(  filterEvent  )

    for filterData in filterDataList :
        eventFilter_List.append( event_filter(*filterData))

    if progressBar :
        progressBar.setFormat("Querying database")
    textLineList=["<font color='#000000'>Results : </font>"]
    




    cout("Retrieving project workstation list : " + str(projectId) )


    eventFilterList = ['version_up','save_file_as', 'open_file', 'file_publish', 'new_file','open_file','open_file_snapshot' ]
    filters = [ ["project", "is", projectId],  ["event_type", "in", eventFilterList ]  ]


    wsDictList=[] 
    firstEventLog = None 
    lastEventLog = None

    eventLogList =  sg.find("EventLogEntry", filters, [ "meta" , "created_at"] )

    cout("got It ! ")

    for eventLog in eventLogList :
        if eventLog["meta"].has_key("ws") :
            if not eventLog["meta"]["ws"] in wsDictList :
                wsDictList.append(eventLog["meta"]["ws"])

        
            if not firstEventLog : 
                firstEventLog = eventLog
            elif firstEventLog["id"] > eventLog["id"] :
                firstId = eventLog


            if not lastEventLog :
                lastEventLog = eventLog
            elif lastEventLog["id"] < eventLog["id"] :
                lastEventLog = eventLog




    if not firstEventLog :
        print "there's no event for this project "
        f.close()
        return


    textLineList.append("&nbsp; &nbsp; &nbsp;->&nbsp;" +   " + ".join(wsDictList))

    cout("First event " + str(firstEventLog["created_at"]) )


    cout("Retrieving every event list since " + str(firstEventLog["created_at"])   )
    

    {
        "filter_operator": "all",
        "filters": [
            ["created_at", "greater_than", firstEventLog["created_at"]] ,
            ["created_at", "smaller_than", lastEventLog["created_at"]]
        ]
    }



    filters = [ ["created_at", "between",  [ firstEventLog["created_at"], lastEventLog["created_at"]  ]     ] ,
                ["entity", 'is_not', None],
                ["event_type", "in", eventFilterList ]  ]




    wsDict = {}
    eventLogList = sg.find("EventLogEntry", filters, [ "meta", "entity", "project", "event_type", "created_at"  ] )

    cout("got It ! ")
    for eventLog in eventLogList : 
        thisProject = False
        if eventLog['project']['id'] ==  projectId['id'] :
            thisProject = True

       
        dataEvent = sg_Event( eventLog["created_at"],  eventLog["entity"],  eventLog["event_type"],  thisProject, eventLog["id"])
        # event_datetime, event_context, event_type, thisProject = True  

        if not wsDict.has_key(eventLog["meta"]["ws"]) :
            wsDict[eventLog["meta"]["ws"]] = [dataEvent]
        else :
            wsDict[eventLog["meta"]["ws"]].append(dataEvent)

    stepProgressBar = 0 
    if progressBar :
        progressBar.setFormat("Computing events")
        progressBar.setValue(stepProgressBar)
    
    ev = 0
    
    workstationDict = {}
    for workstation,dailyEventQueue in wsDict.iteritems():

        contextList = get_contextList(dailyEventQueue)
        array_2D    = makeArray( dailyEventQueue, contextList ) 
        

        cout("&nbsp; &nbsp; &nbsp;->&nbsp;" + str(workstation)  )

        dayContext_timeTree = calculateArray(array_2D, contextList, eventFilter_List, cout)
        drawArray(array_2D, eventFilter_List,  cout)

        workstationDict[workstation]=dayContext_timeTree

   
        ev+= len(array_2D)
        
        stepProgressBar+= 100/len(wsDict.keys())
        if progressBar :
            progressBar.setValue(stepProgressBar)





    outputText = displayDataContext(workstationDict, cout )
    outputText +="<br><br> See full log file :<br>"
    outputText += str(outputLogFileName)


    if progressBar :
        progressBar.setValue(100)
        progressBar.setFormat("Computing done")
        logLabel.setText(outputText.replace(" ","&nbsp;"))

    cout("done :  " +  str (ev) )
    
    f.write("</dir></body></html>")
    f.close()


    datafileName =  "c:/temp/EVENTLOG/eventManager_"+projectId["name"]+"_"+ today +".pkl"
    displayDataContext_perDay( workstationDict, projectId["name"], datafileName  )
Пример #20
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
Пример #21
0
 
 # first do the studio location tank.bat
 studio_tank_bat = os.path.abspath(os.path.join(tank_install_root, "..", "tank.bat"))
 if os.path.exists(studio_tank_bat):
     log.info("Updating %s..." % studio_tank_bat)         
     try:
         this_folder = os.path.abspath(os.path.join( os.path.dirname(__file__)))
         new_tank_bat = os.path.join(this_folder, "setup", "root_binaries", "tank.bat")
         log.debug("copying %s -> %s" % (new_tank_bat, studio_tank_bat))
         shutil.copy(new_tank_bat, studio_tank_bat)
         os.chmod(studio_tank_bat, 0775)
     except Exception, e:
         log.error("\n\nCould not upgrade core! Please contact support! \nError: %s" % e)
 
 
 pcs = sg.find("PipelineConfiguration", [], ["code", "project", "windows_path", "mac_path", "linux_path"])
 
 for pc in pcs:
     
     try:
         log.info("Processing Pipeline Config %s (Project %s)..." % (pc.get("code"), 
                                                                     pc.get("project").get("name")))
     
         local_os_path = pc.get(SG_LOCAL_STORAGE_OS_MAP[sys.platform])
         
         if local_os_path is None:
             log.info("No pipeline configurations registered for this OS. Skipping...")
             continue
     
         if not os.path.exists(local_os_path):
             log.info("Pipeline Config does not exist on disk (%s) - skipping..." % local_os_path)
Пример #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
Пример #23
0
import maya.cmds as cmds
import maya.mel as mel
import os, sys,threading

sys.path.append('//vfx-data-server/dsGlobal/globalResources/Shotgun')
from shotgun_api3 import Shotgun
try:
    server = "https://duckling.shotgunstudio.com"
    scriptName = "assetOpenToShotgun"
    scriptId = "e932e9c2864c9bcdc3f3ddf8b801cc3d565bf51f"
    sg = Shotgun(server, scriptName, scriptId)
    myPeople = sg.find("HumanUser", ["name"])
except:
    print "could not connect to SG Server"

print "THIS IS RUNNING A USERSETUP.PY FILE"

try:
  import vxmaya_setup
  import vxmaya_file
  import vxmaya_core
except:
  pass

mel.eval("evalDeferred dsMenu;")
#mel.eval("evalDeferred overwriteProc;")

if sys.platform == "win32":
    cmds.dirmap( en=True )
    cmds.dirmap( m=('/dsPipe/', '//vfx-data-server/dsPipe/') )
Пример #24
0
contact_template = MyTemplate(
    '''<script type="text/javascript" src="http://download.skype.com/share/skypebuttons/js/skypeCheck.js"></script>
<a href="skype:{{skype_id}}?add"><img src="http://download.skype.com/share/skypebuttons/buttons/add_green_transparent_118x23.png" style="border: none;" width="118" height="23" alt="Add me to Skype" /></a>'''
)

#create a shotgun instance
sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)

#set up the data that we need for each user and look for non-blank skype id's
fields = ['id', SKYPE_ID_FIELD, SKYPE_BUTTON_FIELD, SKYPE_ADD_CONTACT_FIELD]
filters = [
    [SKYPE_ID_FIELD, 'is_not', None],
]

#find all the users that have skype-id's
users = sg.find("HumanUser", filters, fields)

#initialize an empty list to contain shotgun update requests
batch_data = []

#process all users checking to see if button data is correct for the user name
# (this is in case a skype user name changes) or if there is not a button
for user in users:
    # put skype user name into template to create button html code
    skype_button_text = button_template.safe_substitute(
        skype_id=user[SKYPE_ID_FIELD])
    skype_contact_text = contact_template.safe_substitute(
        skype_id=user[SKYPE_ID_FIELD])

    if user[SKYPE_BUTTON_FIELD] <> skype_button_text:
        #set the skype button html into the user container
Пример #25
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
Пример #26
0
    "sg_task_order",
    "Id",
    # 	    'created_at',
    "entity.Shot.sg_status_list",
    # 	    'content',
    "start_date",
    "due_date",
    "entity.Shot.sg_title",
    "entity.Shot.sg_title_name",
    # 	'upstream_tasks',
    # 	'downstream_tasks',
    # 	'dependency_violation',
    # 	'pinned'
]

results = sg.find("Task", filters, fields)

print "Due Date\tShot Code\tTitle\tTitle Name\tContent\tAssigned To"
for r in results:
    s = str(r["due_date"])
    if s == "None":
        print "None\t" + str(r["entity.Shot.code"]) + "\t" + str(r["entity.Shot.sg_title"]) + "\t" + str(
            r["entity.Shot.sg_title_name"]
        ) + "\t" + str(r["content"])
    else:
        dueDate = datetime.strptime(s, "%Y-%m-%d")
        for u in r["task_assignees"]:
            print str(dueDate) + "\t" + str(r["entity.Shot.code"]) + "\t" + str(r["entity.Shot.sg_title"]) + "\t" + str(
                r["entity.Shot.sg_title_name"]
            ) + "\t" + str(r["content"]) + "\t" + str(u["name"])
Пример #27
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()
Пример #28
0
import yaml
import urllib2
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':
Пример #29
0
        log.info("Updating %s..." % studio_tank_bat)
        try:
            this_folder = os.path.abspath(
                os.path.join(os.path.dirname(__file__)))
            new_tank_bat = os.path.join(this_folder, "setup", "root_binaries",
                                        "tank.bat")
            log.debug("copying %s -> %s" % (new_tank_bat, studio_tank_bat))
            shutil.copy(new_tank_bat, studio_tank_bat)
            os.chmod(studio_tank_bat, 0775)
        except Exception, e:
            log.error(
                "\n\nCould not upgrade core! Please contact support! \nError: %s"
                % e)

    pcs = sg.find(
        "PipelineConfiguration", [],
        ["code", "project", "windows_path", "mac_path", "linux_path"])

    for pc in pcs:

        try:
            log.info("Processing Pipeline Config %s (Project %s)..." %
                     (pc.get("code"), pc.get("project").get("name")))

            local_os_path = pc.get(SG_LOCAL_STORAGE_OS_MAP[sys.platform])

            if local_os_path is None:
                log.info(
                    "No pipeline configurations registered for this OS. Skipping..."
                )
                continue
Пример #30
0
SCRIPT_USER = '******'
SCRIPT_KEY = '987fd62624610c1580c070441f1ae208653541f9'

sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)

M = imaplib.IMAP4_SSL('imap.gmail.com', 993)
M.login('*****@*****.**', 'PASSWORD')
M.select("eng-support")  # mailbox/tag name
typ, data = M.search(None, 'ALL')
for num in data[0].split():
    typ, msgdata = M.fetch(num, '(RFC822)')
    #print 'Message %s\n%s\n' % (num, data[0][1])
    msg_dict = parse.parse(msgdata[0][1])
    print "message from %s" % msg_dict["from"]

    people = sg.find("HumanUser", [['email', 'is', msg_dict["from"]]],
                     ['id', 'name'])
    if len(people) < 1:
        print "couldn't find user"
    else:
        # if we find a valid user, create a ticket for them
        user = people[0]
        ticket_data = {
            'created_by': {
                'type': 'HumanUser',
                'id': user['id']
            },
            'addressings_to': [{
                'type': 'Group',
                'id': 5
            }],
            'title': msg_dict['subject'],
Пример #31
0
##shotgun
try:
    from shotgun_api3 import Shotgun
except:
    print "no module named Shotgun"

SERVER_PATH = "http://show.macrograph.co.kr"
SCRIPT_NAME = "testapi"
SCRIPT_KEY = "b4332cb2077957915585fafdf27f252bdaf8a3ada1450970d0c69743253de823"

sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)

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

print assetALL
Пример #32
0
from shotgun_api3 import Shotgun
import os

SCRIPT_NAME = 'Samuel - API'
SCRIPT_KEY = '2b3f3b6e442242c067501a9e17503bac1d27b6ea244a4e4b5987e26d5f6520e2'
sg = Shotgun("https://objeus.shotgunstudio.com", SCRIPT_NAME, SCRIPT_KEY)

echars = sg.find('Attachment',
                 [['attachment_links', 'type_is', 'CustomEntity06']],
                 ['attachment_links'])
for echar in echars:
    sg.download_attachment(
        echar,
        os.path.abspath(
            os.path.expanduser("importdata/" +
                               echar['attachment_links'][0]['name'] +
                               ".json")))
# set up templates for the skype button    
button_template = MyTemplate('''<script type="text/javascript" src="http://download.skype.com/share/skypebuttons/js/skypeCheck.js"></script>
<a href="skype:{{skype_id}}?call"><img src="http://download.skype.com/share/skypebuttons/buttons/call_blue_white_124x52.png" style="border: none;" width="124" height="52" alt="Skype Me!" />''')
contact_template = MyTemplate('''<script type="text/javascript" src="http://download.skype.com/share/skypebuttons/js/skypeCheck.js"></script>
<a href="skype:{{skype_id}}?add"><img src="http://download.skype.com/share/skypebuttons/buttons/add_green_transparent_118x23.png" style="border: none;" width="118" height="23" alt="Add me to Skype" /></a>''')


#create a shotgun instance
sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)

#set up the data that we need for each user and look for non-blank skype id's
fields = ['id', SKYPE_ID_FIELD  , SKYPE_BUTTON_FIELD , SKYPE_ADD_CONTACT_FIELD] 
filters = [[SKYPE_ID_FIELD , 'is_not',  None ],]

#find all the users that have skype-id's
users= sg.find("HumanUser",filters,fields)

#initialize an empty list to contain shotgun update requests
batch_data = []

#process all users checking to see if button data is correct for the user name
# (this is in case a skype user name changes) or if there is not a button
for user in users:
    # put skype user name into template to create button html code
    skype_button_text = button_template.safe_substitute(skype_id=user[SKYPE_ID_FIELD])
    skype_contact_text = contact_template.safe_substitute(skype_id=user[SKYPE_ID_FIELD])
    
    if user[SKYPE_BUTTON_FIELD] <> skype_button_text:
        #set the skype button html into the user container
        user[SKYPE_BUTTON_FIELD] = skype_button_text
        user[SKYPE_ADD_CONTACT_FIELD] = skype_contact_text
Пример #34
0
db.query("set character_set_connection=utf8;")
db.query("set character_set_server=utf8;")
db.query("set character_set_client=utf8;")

db.query("set character_set_results=utf8;")


SERVER_PATH = "http://show.macrograph.co.kr"
SCRIPT_NAME = "testapi"
SCRIPT_KEY = "b4332cb2077957915585fafdf27f252bdaf8a3ada1450970d0c69743253de823"

sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)

field = ['name','sg_status','sg_description','image','start_date','end_date']
projectsALL = sg.find('Project',[],field)


for project in projectsALL:
    project_name = project['name']
    status = project['sg_status']
    description = project['sg_description']
    thumbnail = project['image']
    start_date = project['start_date']
    end_date = project['end_date']

    if thumbnail == None:
        thum = "noimage.jpg"
    else:
        thum = "%s_" % (datetime.today().strftime('%Y%m%d')) + str(uuid.uuid4())[:8] + ".jpg"
    thum_path = "/home/crystal/MG/asset/thumnail/small_thum/%s" % thum
Пример #35
0
from shotgun_api3 import Shotgun
from glob import glob
import json

SCRIPT_NAME = 'Samuel - API'
SCRIPT_KEY = '2b3f3b6e442242c067501a9e17503bac1d27b6ea244a4e4b5987e26d5f6520e2'
sg = Shotgun("https://objeus.shotgunstudio.com", SCRIPT_NAME, SCRIPT_KEY)

epers = sg.find('CustomEntity07', [], ['code'])
efiles = sg.find('Attachment',
                 [['attachment_links', 'type_is', 'CustomEntity07']],
                 ['attachment_links'])
efilenames = {}
for efile in efiles:
    efilenames[efile['attachment_links'][0]['name']] = efile['id']
print efilenames
enames = {}
for eper in epers:
    enames[eper['code']] = eper
print enames

pers = glob('pers/*.json')
for per in pers:
    with open(per) as json_data:
        temp = json.load(json_data)
    json_data.close()
    data = {
        'code': temp['name'],
        'description': temp['desc'],
        'sg_arcana': temp['arcana'],
        'sg_level': (int)(temp['level']),
Пример #36
0
        progressBar.setValue(100)
        progressBar.setFormat("Computing done")
        logLabel.setText(outputText.replace(" ","&nbsp;"))

    cout("done :  " +  str (ev) )
    
    f.write("</dir></body></html>")
    f.close()


    datafileName =  "c:/temp/EVENTLOG/eventManager_"+projectId["name"]+"_"+ today +".pkl"
    displayDataContext_perDay( workstationDict, projectId["name"], datafileName  )



if __name__ == '__main__':

    SERVER_PATH = "https://nozon.shotgunstudio.com"
    SCRIPT_NAME = 'noteManager'     
    SCRIPT_KEY = '3fbb2a5f180457af709fcad231c96ac8a916711427af5a06c47eb1758690f6e4'


    import sys
    sys.path.append("Z:/Dev/cyril/python/PACKAGES")
    from shotgun_api3 import Shotgun

    sg = Shotgun(SERVER_PATH, SCRIPT_NAME, SCRIPT_KEY)
    projetcLit = sg.find("Project", [], ["name"])
    for projectContext in projetcLit :
        print "\n\n###########\tPROJECT\t############\n\t\t" , projectContext["name"], projectContext["id"]
        launch(None, None, [] , None, projectContext, sg )
Пример #37
0
# Make the jobs directory
makeDir(root)


# Change directory
os.chdir(root)


# Start Shotgun calls
fields 						= ['id', 'code', 'name', 'sg_status']
filters						= [
								['sg_status', 'is', 'Active'],
								#['id', 'is_not', 4] # Add project ids to ignore
							]
projects 					= sg.find("Project",filters,fields)
print projects
print


for p in projects:
	print p

	projectName 			= p['name']

	makeDir(projectName)


	filters 				= [
								['project', 'is', {'type':'Project', 'id':p['id']}]
	]
Пример #38
0
SCRIPT_USER = '******'
SCRIPT_KEY = '987fd62624610c1580c070441f1ae208653541f9'

sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)

M = imaplib.IMAP4_SSL('imap.gmail.com', 993)
M.login('*****@*****.**', 'PASSWORD')
M.select("eng-support") # mailbox/tag name
typ, data = M.search(None, 'ALL')
for num in data[0].split():
    typ, msgdata = M.fetch(num, '(RFC822)')
    #print 'Message %s\n%s\n' % (num, data[0][1])
    msg_dict = parse.parse(msgdata[0][1])
    print "message from %s" % msg_dict["from"]

    people = sg.find("HumanUser",[['email','is',msg_dict["from"]]],['id','name'])
    if len(people) < 1:
        print "couldn't find user"
    else:
        # if we find a valid user, create a ticket for them
        user = people[0]
        ticket_data = {
            'created_by': {'type':'HumanUser','id':user['id']},
            'addressings_to': [{'type':'Group','id':5}],
            'title': msg_dict['subject'],
            'description': msg_dict['body'],
            'project': {'type':'Project', 'id':178},
        }
        sg.create('Ticket', ticket_data, return_fields=['id'])

        # if we made it this far the e-mail was processed, now delete it
Пример #39
0
CURRENT_VERSION_FIELD = '********'  # get this from the "Configure Field" dialog in shotgun
sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
fields = ['id', 'entity', 'sg_asset_type']  # version id, shot info, "version"

# sg_current_version field to upate

#TEST VALUES TO BE SET BY POST FROM ACTION MENU
version_ids = [19, 20, 93]  # replace with result from the post
project_id = 64  # Replace this with the result from the post

for a_version_id in version_ids:
    filters = [['project', 'is', {
        'type': 'Project',
        'id': project_id
    }], ['id', 'is', a_version_id]]
    assets = sg.find("Version", filters, fields)
    if len(assets) < 1:
        print "couldn't find any assets"
        exit(0)
    else:
        for an_asset in assets:
            entity_type = an_asset['entity'][
                'type']  # should always be 'Shot'!
            if entity_type == 'Shot':  # we always expect a shot but OK to test
                shot_id = an_asset['entity']['id']
                linked_version = {'type': 'Version', 'id': a_version_id}
                data = {CURRENT_VERSION_FIELD: linked_version}

                changed_asset = sg.update("Shot", shot_id, data)
                pprint(changed_asset)
            else:
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:
Пример #41
0
import datetime
import logging
import logging.config
import gluon.contrib.simplejson

# shotgun
sys.path.append('/X/tools/pythonlib')
from shotgun_api3 import Shotgun

SG = Shotgun(sg_server, sg_script_name, sg_script_key)


session.departments = []
if not session.departments:
        session.departments = SG.find('Department', [['sg_status_list', 'is', 'act']],
                                      fields=['code', 'name', 'color'],
                                      order=[{'field_name':'name', 'direction':'asc'}]
                                      )
session.dept_to = []
session.dept_ny = []
for d in session.departments:
    if d['code'].upper().startswith('NY'):
        session.dept_ny.append(d['id'])
    else:
        session.dept_to.append(d['id'])

PROJECT_STATUS = ['Active', 'Bidding', 'Demo/Test', 'Delivered']

if not session.projects:
    result = SG.find('Project', [['sg_status', 'in', PROJECT_STATUS]],
                     fields=['code','name', 'color', 'sg_status'],
                     order=[{'field_name':'name', 'direction':'asc'}]
Пример #42
0
#from dBase import *
from shotgun_api3 import Shotgun
import os


site = 'https://chimneypot.shotgunstudio.com'    
scriptName = 'dBase'
scriptKey = '729a76955455909c79f6d90262bb9fbe9186b92b'
pName = 'kievPipelineTest'
sg = Shotgun(site, scriptName, scriptKey)

lst = sg.find('HumanUser', [['updated_at', 'not_in_last', 1, 'MONTH'],['sg_status_list', 'is', 'act']], ['name', 'updated_at', 'sg_status_list'])
for i in lst:
	print "%s: %s, %s, %s"%(i['name'],i['updated_at'], i['sg_status_list'], i['id'])

killEric = sg.update('HumanUser', 62, {'sg_status_list':'dis'})


def test():
	print 'huy'    
    return sg

Пример #43
0
    form_project_id = form.getvalue('project_id')

    # and convert to values that can be used by Shotgun API (list and ints)
    version_ids = [int(x) for x in selected_ids_str.split(',')
                   ]  # list of ints from a string
    project_id = int(form_project_id)  # integer from string

    success = True  # keep track of errors so that true success for all requests can be reported to the user
    filters = [
        ['project', 'is', {
            'type': 'Project',
            'id': project_id
        }],
        ['id', 'in'] + version_ids,
    ]
    versions = sg.find("Version", filters, fields)
    found_shots = set(
    )  # a set to hold all of the found shots so we can error if we need to...

    for a_version in versions:  #pre-process all shots looking for duplicates
        print "</br>"
        if a_version['entity']['name'] in found_shots:
            raise MultiShotError(
                'There is more than one version of shot %s in your request' %
                a_version['entity']['name'])
        else:
            found_shots.add(a_version['entity']['name'])

    for a_version in versions:  # re-process all shots to set the current version field correctly
        entity_type = a_version['entity']['type']  # should always be 'Shot'!
        if entity_type == 'Shot':  # we always expect a shot but OK to test
#sh.write(1, 10, "not filled \n# @ # ")
sh.write(1, 10, "blank\nno data filled",BLANK_TASK_CELL)
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"])
Пример #45
0
class dMFXsubmitterDialog(QDialog, Ui_dMFXsubmitter):

    def __init__(self, parent = None):
        # set up the UI and variable here - don't forget to call updateUI at end
        super(dMFXsubmitterDialog,self).__init__(parent)
        self.acceptDrops()
        self.setupUi(self) # generic call to setup the Ui provided by Qt
        self.password = ''
        self.version_file_path = ''
        self.user = ''
        self.user_id = ''
        self.user_name = ''
        self.user_initials = ''
        self.submit_movie = False
        self.movie_file_path = ''
        self.description = ''
        self.login_status = False
        self.allOK = True
        self.submit_call_track = True
        self.version_type = 'Shot'
        self.created_version_id = None
        self.sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
        self.sgu = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
        self.users_with_initals = INITIALS_LIST
        self.user_list = []
        self.lineEdit_versionFile.dragEnterEvent = types.MethodType(dragEnterEvent,self.lineEdit_versionFile)
        self.lineEdit_versionFile.dropEvent = types.MethodType(dropEvent,self.lineEdit_versionFile)
        self.lineEdit_versionFile.setAcceptDrops(True)
        self.lineEdit_versionFile.setDragEnabled(True)
        self.lineEdit_forReview.dragEnterEvent = types.MethodType(dragEnterEvent,self.lineEdit_forReview)
        self.lineEdit_forReview.dropEvent = types.MethodType(dropEvent,self.lineEdit_forReview)
        self.lineEdit_forReview.setAcceptDrops(True)
        self.lineEdit_forReview.setDragEnabled(True)

        # start things happening... get the users from sg and populate them into the drop-down
        self.update_user_list()
        self.connect(self,SIGNAL('update'),self.updateUI)

        self.new_value = 'this is not a new value'
        #self.emit(SIGNAL("update"))
        self.updateUI()

    def update_user_list(self):
        filters = [ ['sg_status_list', 'is', 'act' ],]
        fields = ['name', 'login']
        users = self.sg.find('HumanUser', filters, fields)
        user_list = [ (user['name'],user['login'],user['id']) for user in users if user['name'] != 'Template User']
        user_list.sort()
        self.user_list = user_list
        self.comboBox_artistSelect.addItem('Please Select...')
        self.user = '******'
        for user in user_list:
           self.comboBox_artistSelect.addItem(user[0])
        self.updateUI()

    def reset_to_go_again(self):
        # todo set all fields to blank, not just update the values...
        self.version_file_path = ''
        self.submit_movie = False
        self.movie_file_path = ''
        self.description = ''
        self.allOK = True
        self.created_version_id = None
        self.plainTextEdit_description.setPlainText('')
        self.lineEdit_versionFile.setText('')
        self.lineEdit_forReview.setText('')
        self.updateUI()

    def updateUI(self):
        # make sure that the UI is updated to match input
        self.activateWindow() # window gets keyboard focus after redraw
        self.allOK = True
        self.description = str(self.plainTextEdit_description.toPlainText())

        # check user and if it needs initials, activate the text box
        if self.user in self.users_with_initals:
            self.lineEdit_initials.setEnabled(True)
        else:
            self.lineEdit_initials.setEnabled(False)

        # check user to see if one has been selected... set login to default if it has and there is no login set
        if self.user == STARTING_USER_LIST_TEXT:
            self.pushButton_login.setEnabled(False)
        else:
            self.pushButton_login.setEnabled(True)
            if not self.login_status:
                self.pushButton_login.setDefault(True)

        # check to see if logged in - if not, disable everything below login
        if self.login_status:
            self.label_password.setText("** Logged In **")
            self.pushButton_login.setEnabled(False)
            self.comboBox_artistSelect.setEnabled(False)
        else:
            self.label_password.setText("Shotgun Password")
            self.pushButton_login.setEnabled(True)

        # check the submit checkbox and enable fields if set
        if self.checkBox_forReview.isChecked():
            self.lineEdit_forReview.setEnabled(True)
            self.pushButton_getForReview.setEnabled(True)
            self.submit_movie=True

        # check for movie submit check-box
        if self.submit_movie:
            self.lineEdit_forReview.setEnabled(True)
            self.pushButton_getForReview.setEnabled(True)
        else:
            self.lineEdit_forReview.setEnabled(False)
            self.pushButton_getForReview.setEnabled(False)

        # check for a need for initals
        if self.user in INITIALS_LIST:
            self.label_initials.setText('Add Your Initials')
            self.lineEdit_initials.show()
        else:
            self.label_initials.setText('')
            self.lineEdit_initials.hide()
            self.user_initials = ''
            self.lineEdit_initials.setText('')

        # check to see if the version file is a movie and, if so and the movie line is empty, fill that in
        if self.version_file_path and os.path.splitext(str(self.version_file_path).lower())[1] in MOVIE_FILE_EXTENSION_LIST and not self.movie_file_path:
            self.movie_file_path = str(self.version_file_path)
            self.lineEdit_forReview.setText(self.movie_file_path)

        # check for conditions that allow an update to happen
        conditions = True # start by assuming we can go and switch if we can't
        if self.user in INITIALS_LIST and not self.user_initials:
            conditions = False
        if conditions and not self.login_status:
            conditions = False
        if conditions and self.version_file_path and not os.path.exists(self.version_file_path):
            conditions = False
        if conditions and self.submit_movie:
            if self.movie_file_path and not os.path.exists(self.movie_file_path):
                conditions = False
            if not self.movie_file_path:
                conditions = False

        #enable the submit button if appropriate
        if conditions:
            self.pushButton_submit.setEnabled(True)
            self.pushButton_submit.setDefault(True)
        else:
            self.pushButton_submit.setEnabled(False)


    # self.pushButton_login
    @pyqtSignature("") 
    def on_pushButton_login_clicked(self):
        result = self.sgu.authenticate_human_user(self.user_name, self.lineEdit_password.text())
        if result:
            self.login_status = True
        else:
            # user tried to log in and failed - let them know
            QMessageBox.about(self, "Log In Error", "Unable to login to Shotgun using your user/pass combination, please try again")
        self.updateUI()

    # self.pushButton_getVersionFile
    @pyqtSignature("")
    def on_pushButton_getVersionFile_clicked(self):
        self.version_file_path = str(QFileDialog.getOpenFileName(self, "Select the file to submit as a Version"   ))
        if self.version_file_path:
            self.lineEdit_versionFile.setText(self.version_file_path)
        self.updateUI()

    # self.pushButton_getForReview
    @pyqtSignature("") 
    def on_pushButton_getForReview_clicked(self):
        self.movie_file_path = str(QFileDialog.getOpenFileNameAndFilter(self, "Select a movie file to submit for screening",
                                   filter= "Movies ( *.mp4 *.mov)")[0]) # the getopenfile returns a tuple of length 2
        if self.movie_file_path:
            self.lineEdit_forReview.setText(self.movie_file_path)
        self.updateUI()

    # self.pushButton_quit
    @pyqtSignature("")
    def on_pushButton_quit_clicked(self):
        QApplication.quit()

    # self.checkBox_forReview
    @pyqtSignature("bool")
    def on_checkBox_forReview_clicked(self):
        #lcheckBox_forReview boolean toggle code here
        self.submit_movie = self.checkBox_forReview.isChecked()
        self.updateUI()

    # self.comboBox_artistSelect
    @pyqtSignature("QString")
    def on_comboBox_artistSelect_currentIndexChanged(self):
        if self.user:
            self.user = self.comboBox_artistSelect.currentText()
            self.user_name = [ user[1] for user in self.user_list if user[0] == self.user][0]
            self.user_id = [ user[2] for user in self.user_list if user[0] == self.user][0]
        self.updateUI()

    # self.comboBox_version_type
    @pyqtSignature("QString")
    def on_comboBox_version_type_currentIndexChanged(self):
        self.version_type = str(self.comboBox_version_type.currentText())
        self.updateUI()

    # self.lineEdit_forReview
    @pyqtSignature("QString")
    def on_lineEdit_forReview_textEdited(self):
        self.movie_file_path = str(self.lineEdit_forReview.text())
        self.emit(SIGNAL("update"))

    # self.lineEdit_initials
    @pyqtSignature("QString")
    def on_lineEdit_initials_textEdited(self):
        self.user_initials = str(self.lineEdit_initials.text())
        self.updateUI()

    # self.lineEdit_versionFile
    @pyqtSignature("QString")
    def on_lineEdit_versionFile_textEdited(self):
        self.version_file_path = str(self.lineEdit_versionFile.text())
        self.updateUI()

    # self.lineEdit_versionFile
    @pyqtSignature("QString")
    def on_lineEdit_versionFile_textChanged(self):
        self.version_file_path = str(self.lineEdit_versionFile.text())
        self.updateUI()

    # self.plainTextEdit_description
    @pyqtSignature("")
    def on_plainTextEdit_description_textEdited(self):
        self.updateUI()

    # self.pushButton_submit   
    @pyqtSignature("")
    def on_pushButton_submit_clicked(self):
        if not self.submit_call_track:
            self.submit_call_track = True
            return
        else:
            self.submit_call_track = False

        sgerrmsg = "There were no matching {0}s, make sure that you have selected the right kind of entity and try again"
        if not self.allOK:
            return
        try:
            self.created_version_id = update_shotgun(self.sg, self.version_file_path, self.description, self.user_id, self.version_type, self.user_initials, self )
            if not self.created_version_id: # sg did not find anything! Tell the user and let them try again or quit
                self.allOK = False
                sub_dialog = dMFXsubmitterSubDialog(
                    "No Matches", "Reset", "QUIT!", sgerrmsg.format(self.version_type), boxeditable = False, parent=self )
                button, text, pick = sub_dialog.getValues()
                if sub_dialog.exec_():
                    sub_dialog.close()
                    button, text, pick = sub_dialog.getValues()
                    if button == 'No' :
                        QApplication.quit()
                    else:
                        return # return if they click on Retry
                else: return # return if they close the window

            mainlabel = "Success!"
            yeslabel = 'Go Again'
            nolabel = 'QUIT!'
            boxtext =  'Your version was successfully created'

            if self.allOK and self.submit_movie:
                if not do_submit_for_review(self.sg,self.movie_file_path,self.created_version_id):
                    # the sym-link failed for some reason after 2 tries...
                    mainlabel = "Partial Success..."
                    boxtext = "Your version was created but the movie was NOT put into today's Review Folder. Please add it manually, or resubmit the Version"

        except Exception,e:
            mainlabel = "ERROR!"
            yeslabel = 'Reset'
            nolabel = 'QUIT!'
            boxtext =  'Something Went Horribly Wrong! -\nError: {0}\n{1}'.format(e,traceback.format_exc())

        #QMessageBox.about(self, "updateUI", output_string)
        sub_dialog = dMFXsubmitterSubDialog(mainlabel,yeslabel,nolabel, boxtext )
        if sub_dialog.exec_():
            sub_dialog.close()
            button, text, pick = sub_dialog.getValues()
            if button == 'No' :
                QApplication.quit()
            else:
                self.reset_to_go_again()
    form = cgi.FieldStorage() 
    
    # Get data from fields 
    selected_ids_str = form.getvalue('selected_ids')
    form_project_id = form.getvalue('project_id')
    
    # and convert to values that can be used by Shotgun API (list and ints)
    version_ids=[int(x) for x in selected_ids_str.split(',')] # list of ints from a string
    project_id =int(form_project_id)  # integer from string

    success = True # keep track of errors so that true success for all requests can be reported to the user
    filters = [
        ['project','is',{'type':'Project','id':project_id}],
        ['id', 'in' ] + version_ids ,
        ]
    versions= sg.find("Version",filters,fields)
    found_shots = set() # a set to hold all of the found shots so we can error if we need to...

    for a_version in versions: #pre-process all shots looking for duplicates
        print "</br>"
        if a_version['entity']['name'] in found_shots:
            raise MultiShotError(
                'There is more than one version of shot %s in your request' % a_version['entity']['name'] )
        else:
            found_shots.add( a_version['entity']['name'] )

    for a_version in versions: # re-process all shots to set the current version field correctly           
        entity_type = a_version['entity']['type'] # should always be 'Shot'!
        if entity_type == 'Shot': # we always expect a shot but OK to test
            shot_id = a_version['entity']['id']
            linked_version = { 'type' : 'Version' , 'id' : a_version['id'] } 
SCRIPT_USER = "******"  # your script name
SCRIPT_KEY = "********"  # your key here
CURRENT_VERSION_FIELD = "********"  # get this from the "Configure Field" dialog in shotgun
sg = Shotgun(SERVER_PATH, SCRIPT_USER, SCRIPT_KEY)
fields = ["id", "entity", "sg_asset_type"]  # version id, shot info, "version"

# sg_current_version field to upate

# TEST VALUES TO BE SET BY POST FROM ACTION MENU
version_ids = [19, 20, 93]  # replace with result from the post
project_id = 64  # Replace this with the result from the post


for a_version_id in version_ids:
    filters = [["project", "is", {"type": "Project", "id": project_id}], ["id", "is", a_version_id]]
    assets = sg.find("Version", filters, fields)
    if len(assets) < 1:
        print "couldn't find any assets"
        exit(0)
    else:
        for an_asset in assets:
            entity_type = an_asset["entity"]["type"]  # should always be 'Shot'!
            if entity_type == "Shot":  # we always expect a shot but OK to test
                shot_id = an_asset["entity"]["id"]
                linked_version = {"type": "Version", "id": a_version_id}
                data = {CURRENT_VERSION_FIELD: linked_version}

                changed_asset = sg.update("Shot", shot_id, data)
                pprint(changed_asset)
            else:
                print ("version %s is linked to something other than a shot?" % a_version_id)
Пример #48
0
    print '</br>'
    success = True  # keep track of errors so that true success for all requests can be reported to the user

    # first, look to see if there is a current version in the shot
    # if not, then find all the versions that link to that shot and return the most recent

    shot_filters = [['project', 'is', {
        'type': 'Project',
        'id': PROJECT_ID
    }], [
        'id',
        'in',
    ] + shot_ids]

    # #mark First get the version so that the linked shot can then be accessed.
    assets = sg.find("Shot", shot_filters, shot_fields)

    # did anything get returned? if not then error out...
    if len(assets) < 1:
        print '</br>'
        print "<b>Shotgun Server Did Not Return Any Shots! </b>"
        print '</br>'
        print '</br>'
        success = False

    else:  # something was returned, process it!

        for an_asset in assets:  # get the appropriate version and append it to the version list
            if an_asset[
                    CURRENT_VERSION_FIELD]:  # there is a valid version in the field, append it to the list:
                version_ids.append(
Пример #49
0
class MainUI(QtGui.QWidget):
	def __init__(self, app):
		"""
		main UI for STATIC ENV handling

		I always build my UI in __init__ so suck it up..

		"""
		QtGui.QWidget.__init__(self)
		self.app = app
		self.fileBoxes  = []
		## 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.shotNum    = self._getShotNum()[0]
		self.currentENV = self._getShotNum()[1]
		debug(self.app, method = 'MainUI', message = 'self.shotNum: %s' % self.shotNum, verbose = False)
		debug(self.app, method = 'MainUI', message = 'self.currentENV: %s' % self.currentENV, verbose = False)
		self.lightAlembicFolder = 'I:/lsapipeline/episodes/ep000/%s/Light/publish/alembic_static' % self.shotNum

		## Now build the UI
		self.mainLayout     = QtGui.QHBoxLayout(self)
		self.leftSideLayout = QtGui.QVBoxLayout(self)
		debug(self.app, method = 'MainUI', message = 'self.mainLayout built...', verbose = False)

		##########################
		### ENV SELECTION PULLDOWN
		self.envLayout      = QtGui.QVBoxLayout(self)
		self.envPulldown    = QtGui.QComboBox()

		getENVS             = self.sgsrv.find('Asset',  filters = [["code", "contains", 'ENV_'], ["code", "not_contains", '_ENV_'], ["code", "not_contains", 'WORLDMAP'], ["code", "not_contains", 'TSETbuild']], fields=['code'])
		debug(self.app, method = 'MainUI', message = 'getENVS: %s' % getENVS, verbose = False)

		if self.shotNum:
			for each in getENVS:
				if each['code'] == self.currentENV:
					self.envPulldown.addItem(each['code'])
					self.lightAlembicFolder = 'I:/lsapipeline/episodes/ep000/%s/Light/publish/alembic_static' % self.shotNum
			self.envPulldown.setCurrentIndex(self.envPulldown.findText(self.currentENV))
			debug(self.app, method = 'MainUI', message = 'self.envPulldown setCurrentIndex...', verbose = False)
		else:
			for each in getENVS:
				if 'STATIC' in each['code']:
					self.envPulldown.addItem(each['code'])


		self.fetchAssetListButton = QtGui.QPushButton(Icon('refresh.png'), 'Fetch Asset List')
		self.fetchAssetListButton.setStyleSheet("QPushButton {text-align : left}")
		self.fetchAssetListButton.released.connect(self._fetchAssetList)
		debug(self.app, method = 'MainUI', message = 'self.fetchAssetListButton built...', verbose = False)

		self.importAssetButton = QtGui.QPushButton(Icon('alembic.png'), 'Import latest Pub ABC for Sel')
		self.importAssetButton.setStyleSheet("QPushButton {text-align : left}")
		self.importAssetButton.released.connect(self._fetchMDLAlembicPublish)
		debug(self.app, method = 'MainUI', message = 'self.importAssetButton built...', verbose = False)

		self.checkMDLButton = QtGui.QPushButton(Icon('refresh.png'), 'Check For MDL ABC Publishes')
		self.checkMDLButton.setStyleSheet("QPushButton {text-align : left}")
		self.checkMDLButton.released.connect(self._checkVersionsAgainstPublishes)
		debug(self.app, method = 'MainUI', message = 'self.checkMDLButton built...', verbose = False)

		self.redoSetsButton = QtGui.QPushButton(Icon('plus.png'), 'ReDo Set Assignments')
		self.redoSetsButton.setStyleSheet("QPushButton {text-align : left}")
		self.redoSetsButton.released.connect(self._createSets)
		debug(self.app, method = 'MainUI', message = 'self.redoSetsButton built...', verbose = False)

		self.checkSRFXMLButton = QtGui.QPushButton(Icon('refresh.png'), 'Check For SRF Publishes')
		self.checkSRFXMLButton.setStyleSheet("QPushButton {text-align : left}")
		self.checkSRFXMLButton.released.connect(self._checkSRFVersionsAgainstPublishes)

		self.cleanDuplicateCoresButton = QtGui.QPushButton(Icon('AssignedFileIt.png'), 'Clean Duplicate Cores')
		self.cleanDuplicateCoresButton.setStyleSheet("QPushButton {text-align : left}")
		self.cleanDuplicateCoresButton.released.connect(self._fixTheFuckingCores)
		self.cleanDuplicateCoresButton.setToolTip('This is performed on every import of an static env via the multiloader.\n Exposed just in case you need to run this manually.\n This will go through a scene with multiple static ENVs in it \nand try to make sure duplicate cores are renering correctly.')

		self.removeCoreGrpsButton = QtGui.QPushButton(Icon('skull.png'), 'Remove old Core Grps under geo_hrc')
		self.removeCoreGrpsButton.setStyleSheet("QPushButton {text-align : left}")
		self.removeCoreGrpsButton.released.connect(self._removeCoreGrps)
		self.removeCoreGrpsButton.setToolTip('You can use this to clean up any old core grps under the geo_hrc grps in a scene\nafer you have done a core archive rebuild from xml...')
		## THIS IS UP TO YOU TO ENABLE. IT SHOULDNT BE REQUIRED AS THE MDL PUBLISH SHOULD NOW BE EXPORTING THE CORRECT ATTRS FOR ALEMBIC
		self.republishALL = QtGui.QPushButton('Republish ALL MDL Alembics for %s' % self.currentENV)
		self.republishALL.released.connect(self._republishAllAlembicsForENV)
		self.republishALL.setEnabled(True)

		self.lambert1Button = QtGui.QPushButton(Icon('refresh.png'), 'Check lambert1 objects')
		self.lambert1Button.setStyleSheet("QPushButton {text-align : left}")
		self.lambert1Button.released.connect(self._lambert1Object)

		self.caNSclashCheckButton = QtGui.QPushButton(Icon('refresh.png'), 'Check Core Archive Namespace')
		self.caNSclashCheckButton.setStyleSheet("QPushButton {text-align : left}")
		self.caNSclashCheckButton.released.connect(self.coreArchiveNSclashCheck)

		self.checkFileInPathButton = QtGui.QPushButton(Icon('refresh.png'), 'Check Invalid FileIn Path')
		self.checkFileInPathButton.setStyleSheet("QPushButton {text-align : left}")
		self.checkFileInPathButton.released.connect(self.checkFileInPath)

		self.checkNonManifoldButton = QtGui.QPushButton(Icon('refresh.png'), 'Check Non-Manifold Geometry')
		self.checkNonManifoldButton.setStyleSheet("QPushButton {text-align : left}")
		self.checkNonManifoldButton.released.connect(self.cleanupNonManifoldGeometry)

		## Add stuff to the env layout
		self.envLayout.addWidget(self.envPulldown)
		self.envLayout.addWidget(self.fetchAssetListButton)
		self.envLayout.addWidget(self.importAssetButton)
		self.envLayout.addWidget(self.checkMDLButton)
		self.envLayout.addWidget(self.checkSRFXMLButton)
		self.envLayout.addWidget(self.redoSetsButton)
		self.envLayout.addWidget(self.cleanDuplicateCoresButton)
		self.envLayout.addWidget(self.removeCoreGrpsButton)
		self.envLayout.addWidget(self.republishALL)
		self.envLayout.addWidget(self.lambert1Button)
		self.envLayout.addWidget(self.caNSclashCheckButton)
		self.envLayout.addWidget(self.checkFileInPathButton)
		self.envLayout.addWidget(self.checkNonManifoldButton)

		######################
		### ENV RELATED ASSETS
		self.assetLayout  = QtGui.QVBoxLayout(self)

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

		self.envAssetsGroupBox = QtGui.QGroupBox(self.scrollLayout)
		self.envAssetsGroupBox.setFlat(True)

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

		self.envAssetsLayout = QtGui.QGridLayout(self.envAssetsGroupBox)

		self.assetLayout.addWidget(self.scrollLayout)

		self.mainLayout.addLayout(self.leftSideLayout)
		## Add stuff to leftSideLayout
		self.leftSideLayout.addLayout(self.envLayout)
		self.leftSideLayout.addStretch(1)

		## Add anything else to the HBox
		self.mainLayout.addLayout(self.assetLayout)
		self.resize(1000, 500)
		debug(self.app, method = 'MainUI', message = 'ui built successfully fetching assets now...', verbose = False)
		debug(self.app, method = 'MainUI', message = 'self.envPulldown.currentText(): %s' % self.envPulldown.currentText(), verbose = False)

		self._fetchAssetList()
		self.envPulldown.currentIndexChanged.connect(partial(self._getShotNumFromMenuName))
		self.envPulldown.currentIndexChanged.connect(partial(self._fetchAssetList))

	def arraysMatch(self, a, b):
		'''
		Utility to compare two string list
		'''
		return True if a == b else False

	def cleanupNonManifoldGeometry(self, normals = True):
		## Get all the mesh that has mentalraySubdivApprox connected and has non-manifold problem
        # subdiv_mesh = [cmds.listRelatives(mesh, parent = True, fullPath = True)[0] for mesh in cmds.ls(type = 'mesh') if cmds.listConnections(mesh, type = 'mentalraySubdivApprox') if cmds.polyInfo(mesh, nme = True) or cmds.polyInfo(nmv = True)]
		subdiv_mesh = [cmds.listRelatives(mesh, parent = True, fullPath = True)[0] for mesh in cmds.ls(type = 'mesh') if cmds.polyInfo(mesh, nme = True) or cmds.polyInfo(nmv = True)]
		subdiv_mesh = list( set( subdiv_mesh ) )

		if subdiv_mesh:
			for each in subdiv_mesh:
				## Make sure we do indeed have nonmanifold geometry
				##
				nonManifold = cmds.polyInfo(each, nmv = True, nme = True)
				if nonManifold:

					proceed = cmds.confirmDialog(title = 'Non-Manifold Geometry!', message = 'Geo Name:\n%s' % each, button = ['Cleanup!', 'Skip...'], defaultButton = 'Skip...', cancelButton = 'Skip...', dismissString = 'Skip...')
					if proceed == 'Cleanup!':

						## Conform the geo and see if that gets rid of all the nonmanifold bits
						##
						if normals:
							cmds.polyNormal('%s.f[*]' % each, normalMode = 2, constructionHistory = True)

						edges			= cmds.polyInfo(each, nme = True) if cmds.polyInfo(each, nme = True) else []
						vertices 		= [] if edges else cmds.polyInfo(each, nmv = True)
						lastEdges		= []
						lastVertices	= []

						while ( not self.arraysMatch(lastEdges, edges) or not self.arraysMatch(lastVertices, vertices) ) and ( edges or vertices ):
							## Remember what was nonmanifold last time
							##
							lastEdges		= edges
							lastVertices	= vertices
							## Split any nonmanifold edges
							##
							if edges:
								cmds.polySplitEdge(edges, constructionHistory = True)
								vertices = cmds.polyInfo(each, nmv = True)
								edges = []

							## Split any remaining nonmanifold vertices
							##
							if vertices:
								cmds.polySplitVertex(vertices, constructionHistory = True)
								vertices = []

							## Now check to see if the object is still nonmanifold
							##
							nonManifold = cmds.polyInfo(each, nmv = True, nme = True)
							if nonManifold:
								## Chip off the faces
								##
								nonManifoldFaces = cmds.polyListComponentConversion(nonManifold, toFace = True)
								cmds.polyChipOff(nonManifoldFaces, kft = 0, dup = 0, constructionHistory = True)
								## And then check for nonmanifold bits again
								##
								edges = cmds.polyInfo(each, nme = True)
								if not edges:
									vertices = cmds.polyInfo(each, nmv = True)

						## Check to see if we failed to cleanup
						if edges or vertices:
							cmds.warning('Failed to cleanup non-manifold geometry of %s...' % each)

	def _lambert1Object(self):
		## Delete sets first
		if cmds.objExists('lambert1_object_set'):
			cmds.delete('lambert1_object_set')

		lambert1 = cmds.ls( cmds.sets('initialShadingGroup', q = True), long = True )
		if lambert1:
			lambert1 = [x.split('.f')[0] for x in lambert1 if cmds.objectType(x) == 'mesh' and 'CArch' not in x]

		## Create sets if bad stuffs detected
		if lambert1:
			cmds.sets(lambert1, name = 'lambert1_object_set')

	def coreArchiveNSclashCheck(self):
		coreArchive_NS = [ns for ns in cmds.namespaceInfo(listOnlyNamespaces = True) if 'CORE' in ns.split('_')[-1]]
		if coreArchive_NS:
			dup_coreArchive_NS = [ns for ns in coreArchive_NS if not ns.endswith('_CORE')]
			if dup_coreArchive_NS:
				cmds.confirmDialog(title = 'Core Archive Namespace', message = 'Core Archive namespace clashes detected, please check the namespace editor!', button = 'OK!')

	def checkFileInPath(self):
		## Delete sets first
		if cmds.objExists('invalid_fileIn_path_set'):
			cmds.delete('invalid_fileIn_path_set')

		fileIn = cmds.ls(type = 'file')
		fileIn.extend( cmds.ls(type = 'mentalrayTexture') )
		if fileIn:
			badFileInPath = [x for x in fileIn if not os.path.exists( cmds.getAttr('%s.fileTextureName' % x) )]

			## Create sets if bad stuffs detected
			if badFileInPath:
				cmds.sets(badFileInPath, name = 'invalid_fileIn_path_set')

	def _removeCoreGrps(self):
		"""
		Exposing function for operator to cleanup after a rebuild
		"""
		## Step one after import
		## Clean the f*****g left over grps first if they exist
		ENVLIST = ['ENV_MIDDLEHARBOUR_STATIC_ABC_STATIC_CACHES_hrc', 'ENV_MIDDLEHARBOUR_EAST_STATIC_ABC_STATIC_CACHES_hrc', 'ENV_WESTHARBOUR_STATIC_ABC_STATIC_CACHES_hrc',
					'ENV_THEHEADS_STATIC_ABC_STATIC_CACHES_hrc', 'ENV_BIGTOWN_STATIC_ABC_STATIC_CACHES_hrc']
		getHRCS = [[eachGrp for eachGrp in cmds.listRelatives(eachENV)] for eachENV in ENVLIST if cmds.objExists(eachENV)]
		[[cmds.delete(eachChild) for eachChild in cmds.listRelatives(eachHrc, ad = True, f = True) if '_CORE_' in eachChild] for eachHrc in getHRCS]

	def _toggleCBx(self, chbx = '', wtfami = ''):
		"""
		Function to select on checkbox toggle
		@param chbx: the QCheckbox
		@param wtfami: WHO THE HELL KNOWS!!????!!!!!!!!
		@type chbox: PyQt Object
		:return:
		"""
		if chbx.isChecked():
			cmds.select('%s_hrc' % chbx.text(), add = True)
		else:
			cmds.select('%s_hrc' % chbx.text(), d = True)

	def _getShotNum(self):
		self.workSpace = cmds.workspace(q = True, fn = True)
		debug(self.app, method = '_getShotNum', message = 'self.workSpace: %s' % self.workSpace, verbose = False)
		envName = ''
		shotNum = ''

		if 'ep000_sh010' in self.workSpace:
			envName = 'ENV_MIDDLEHARBOUR_STATIC'
			shotNum = 'ep000_sh010'
		elif 'ep000_sh020' in self.workSpace:
			envName = 'ENV_WESTHARBOUR_STATIC'
			shotNum = 'ep000_sh020'
		elif 'ep000_sh030' in self.workSpace:
			envName = 'ENV_BIGTOWN_STATIC'
			shotNum = 'ep000_sh030'
		elif 'ep000_sh040' in self.workSpace:
			envName = 'ENV_THEHEADS_STATIC'
			shotNum = 'ep000_sh040'
		elif 'ep000_sh050' in self.workSpace:
			envName = 'ENV_MIDDLEHARBOUR_EAST_STATIC'
			shotNum = 'ep000_sh050'
		else:
			envName = None
			shotNum = None

		return shotNum, envName

	def _getShotNumFromMenuName(self, index = ''):
		self.workSpace = cmds.workspace(q = True, fn = True)
		envName = ''
		shotNum = ''

		if self.envPulldown.currentText() == 'ENV_MIDDLEHARBOUR_STATIC':
			shotNum = 'ep000_sh010'
		elif self.envPulldown.currentText() == 'ENV_WESTHARBOUR_STATIC':
			shotNum = 'ep000_sh020'
		elif self.envPulldown.currentText() == 'ENV_BIGTOWN_STATIC':
			shotNum = 'ep000_sh030'
		elif self.envPulldown.currentText() == 'ENV_THEHEADS_STATIC':
			shotNum = 'ep000_sh040'
		elif self.envPulldown.currentText() == 'ENV_MIDDLEHARBOUR_EAST_STATIC':
			shotNum = 'ep000_sh050'
		else:
			shotNum = None

		return shotNum

	def _addVersionTag(self, assetName, versionNumber):
		if cmds.objExists('%s.version' % assetName):
			cmds.deleteAttr('%s.version' % assetName)
		try:
			cmds.addAttr(assetName, ln = 'version', at = 'long', min = 0, max  = 50000, dv = 0)
		except:
			pass
		cmds.setAttr('%s.version' % assetName, int(versionNumber))

	def _checkVersionsAgainstPublishes(self):
		## Path to the assets folder
		pathToAssets = "I:/lsapipeline/assets" ##Hardcoded yuckiness..
		MDLVersNum = ''

		## Fetch the subAssets for the ENV
		getData = self.sgsrv.find('Asset',  filters = [["code", "is", self.envPulldown.currentText()]], fields=['code', 'id', 'assets'])

		## Now can the checkboxes and see which assets arechecked
		if self.fileBoxes:
			for eachAsset in self.fileBoxes:
				if eachAsset.isChecked():
					#print 'Checking %s ...' % eachAsset.text()
					for eachSGAsset in getData[0]['assets']:

						if eachSGAsset['name'] == eachAsset.text():
							## BLD
							if 'BLD' in eachSGAsset['name']:
								assetPublishFolder = "%s/Building/%s/MDL/publish/alembic" % (pathToAssets, eachSGAsset['name'])
							## LND
							elif 'LND' in eachSGAsset['name']:
								assetPublishFolder = "%s/Environment/%s/MDL/publish/alembic" % (pathToAssets, eachSGAsset['name'])

							assetPublishFolder.replace("/", os.sep)
							if os.path.isdir(assetPublishFolder):
								try:
									getLatestPublish = max(os.listdir(assetPublishFolder))
								except:
									getLatestPublish = []

								if getLatestPublish and getLatestPublish.endswith('.abc'):
									MDLVersNum = int(getLatestPublish.split('.')[-2].split('v')[-1])

							try:
								getAssetVersion = cmds.getAttr('%s_hrc.version' % eachAsset.text())
							except ValueError:
								getAssetVersion = None

							if getAssetVersion:
								if not getAssetVersion == MDLVersNum:
									#self.envPulldown.setCurrentIndex(self.envPulldown.findText(self.currentENV))
									print '!!HIGHER VER EXISTS: %s_hrc:%s \t %s' % (eachAsset.text(), getAssetVersion, getLatestPublish)
									eachAsset.setStyleSheet("QCheckBox{background-color: red}")
								else:
									eachAsset.setStyleSheet("QCheckBox{background-color: green}")
									eachAsset.setChecked(False)
									print 'PASSED: version match %s' % (getLatestPublish)
							else:
								eachAsset.setStyleSheet("QCheckBox{background-color: red}")
								cmds.warning('%s IS MISSING VERSION INFORMATION! PLEASE FIX!!!' % eachAsset.text())
			for eachAsset in self.fileBoxes:
				if eachAsset.isChecked() and eachAsset.text() == 'ALL':
					eachAsset.setChecked(False)
					eachAsset.setStyleSheet("QCheckBox{background-color: green}")

	def _checkSRFVersionsAgainstPublishes(self):
		## Path to the assets folder
		pathToAssets = "I:/lsapipeline/assets" ##Hardcoded yuckiness..
		MDLVersNum = ''

		## Fetch the subAssets for the ENV
		getData = self.sgsrv.find('Asset',  filters = [["code", "is", self.envPulldown.currentText()]], fields=['code', 'id', 'assets'])

		## Now can the checkboxes and see which assets are checked
		if self.fileBoxes:
			for eachAsset in self.fileBoxes:
				if eachAsset.isChecked():
					#print 'Checking %s ...' % eachAsset.text()
					for eachSGAsset in getData[0]['assets']:

						if eachSGAsset['name'] == eachAsset.text():
							## BLD
							if 'BLD' in eachSGAsset['name']:
								assetPublishFolder = "%s/Building/%s/SRF/publish/xml" % (pathToAssets, eachSGAsset['name'])
							## LND
							elif 'LND' in eachSGAsset['name']:
								assetPublishFolder = "%s/Environment/%s/SRF/publish/xml" % (pathToAssets, eachSGAsset['name'])

							assetPublishFolder.replace("/", os.sep)
							if os.path.isdir(assetPublishFolder):
								try:
									getLatestPublish = max(os.listdir(assetPublishFolder))
								except:
									getLatestPublish = []

								if getLatestPublish and getLatestPublish.endswith('.xml'):
									XMLVersNum = int(getLatestPublish.split('.')[-2].split('v')[-1])

							try:
								getAssetSRFVersion = cmds.getAttr('%s_hrc.SRFversion' % eachAsset.text())
							except ValueError:
								getAssetSRFVersion = None

							if getAssetSRFVersion:
								if not getAssetSRFVersion == XMLVersNum:
									#self.envPulldown.setCurrentIndex(self.envPulldown.findText(self.currentENV))
									print '!!HIGHER VER EXISTS: %s_hrc:%s \t %s' % (eachAsset.text(), getAssetSRFVersion, getLatestPublish)
									eachAsset.setStyleSheet("QCheckBox{background-color: red}")
								else:
									eachAsset.setStyleSheet("QCheckBox{background-color: green}")
									eachAsset.setChecked(False)
									print 'PASSED: version match %s' % (getLatestPublish)
							else:
								eachAsset.setStyleSheet("QCheckBox{background-color: red}")
								cmds.warning('%s IS MISSING VERSION INFORMATION! PLEASE FIX!!!' % eachAsset.text())
			for eachAsset in self.fileBoxes:
				if eachAsset.isChecked() and eachAsset.text() == 'ALL':
					eachAsset.setChecked(False)
					eachAsset.setStyleSheet("QCheckBox{background-color: green}")

	def _checkVersionNumber(self, assetName, versionNumber):
		"""
		Returns if the version number for an asset in the scene matches that of the asset in the static_folder
		"""

		foundVersion = False
		assetList = []
		for eachAlembic in os.listdir(self.lightAlembicFolder):
			if assetName.replace('_', '') in eachAlembic:
				assetList.append(eachAlembic)

		try:
			getlatest = max(assetList)
		except:
			getlatest = []

		if getlatest:
			getlatestVersionNum = getlatest.split('.')[-2].split('v')[-1]
			if int(versionNumber) == int(getlatestVersionNum):
				foundVersion = True
		else:
			cmds.warning('There is no asset for %s found in the lighting static alembic folder.' % assetName)

		return foundVersion

	def _fetchAssetList(self, index = ''):
		getData = self.sgsrv.find('Asset',  filters = [["code", "is", self.envPulldown.currentText()]], fields=['code', 'id', 'assets'])
		debug(self.app, method = '_fetchAssetList', message = 'getData: %s' % getData, verbose = False)

		if self.fileBoxes:
			for each in self.fileBoxes:
				each.setParent(None)
				each = None

		self.fileBoxes  = []

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

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

		self.colCount = 5
		r = 1
		c = 1

		if getData:
			for eachAsset in getData[0]['assets']:
				self.assetCheckBox = QtGui.QCheckBox(self)
				self.assetCheckBox.setChecked(False)
				self.assetCheckBox.setText(eachAsset['name'])
				self.assetCheckBox.toggled.connect(partial(self._toggleCBx, self.assetCheckBox))
				self.fileBoxes.append(self.assetCheckBox)
				if cmds.objExists('%s_hrc' % eachAsset['name']):
					self.assetCheckBox.setStyleSheet("QCheckBox{background-color: #0066CC}")
					## Now check the version
					if cmds.objExists('%s_hrc.version' % eachAsset['name']):
						self.lightAlembicFolder = 'I:/lsapipeline/episodes/ep000/%s/Light/publish/alembic_static' % self._getShotNumFromMenuName()
						if not self._checkVersionNumber(eachAsset['name'], cmds.getAttr('%s_hrc.version' % eachAsset['name'])):
							self.assetCheckBox.setStyleSheet("QCheckBox{background-color: red}")
					else:
						self.assetCheckBox.setStyleSheet("QCheckBox{background-color: #990000}")
						cmds.warning('Asset version attr not found on %s_hrc' % eachAsset['name'])
				else:
					self.assetCheckBox.setStyleSheet("QCheckBox{background-color: red}")


				if c == self.colCount:
					r = r + 1
					c = 1
				self.envAssetsLayout.addWidget(self.assetCheckBox, r, c)
				c = c + 1

	def _toggleAll(self):
		"""
		A quick toggle for all the type checkboxes to on or off
		"""
		for each in self.fileBoxes:
			if each.text() == 'ALL':
				each.setStyleSheet("QCheckBox{background-color: grey}")
				if each.isChecked():
					for eachAsset in self.fileBoxes:
						if eachAsset.text() != 'ALL':
							eachAsset.setChecked(True)
							eachAsset.setStyleSheet("QCheckBox{background-color: grey}")

				else:
					for eachAsset in self.fileBoxes:
						if eachAsset.text() != 'ALL':
							eachAsset.setChecked(False)

	def _fetchMDLAlembicPublish(self):
		"""
		This function will find the checked assets, and then go off and get the latest published alembic asset from the asset folder
		None of this is done off the database btw..
		"""
		pathToAssets        = 'I:/lsapipeline/assets'
		if self.shotNum:
			moveTo          = 'I:/lsapipeline/episodes/ep000/%s/Light/publish/alembic_static' % self.shotNum
		elif self._getShotNumFromMenuName():
			moveTo          = 'I:/lsapipeline/episodes/ep000/%s/Light/publish/alembic_static' % self._getShotNumFromMenuName()
		else:
			cmds.warning('This ENV is not a valid for processing using this tool!')
			return -1

		pathTo = ''

		toProcess = []

		for eachAsset in self.fileBoxes:
			if eachAsset.text() != 'ALL':
				if eachAsset.isChecked():
					toProcess.append(eachAsset.text())
		if toProcess:
			for eachAsset in toProcess:
				if cmds.objExists('%s_hrc' % eachAsset):
					###Prompt to continue here
					self.reply = cmds.confirmDialog(title = "Remove Asset? %s" % eachAsset, message = "Warning you are about to remove %s" % eachAsset, button = ['Continue...','Skip Import'])
					if self.reply == 'Continue...':
						cmds.delete('%s_hrc' % eachAsset)
						self._doIt(eachAsset, pathToAssets, moveTo)
					else:
						pass
				else:
					self._doIt(eachAsset, pathToAssets, moveTo)
		else:
			cmds.warning('No assets selected for importing!!')

	def _doIt(self, eachAsset, pathToAssets, moveTo):
		"""
		Func to process eachAsset from the _fetchMDLAlembicPublish function
		"""
		if 'BLD' in eachAsset:
			pathTo = "%s/Building/%s/MDL/publish/alembic" % (pathToAssets, eachAsset)
		## LND
		elif 'LND' in eachAsset:
			pathTo = "%s/Environment/%s/MDL/publish/alembic" % (pathToAssets, eachAsset)

		if self._isRootFolderThere(rootFolder = pathTo):
			if os.path.isdir(pathTo):
				try:
					maxFile = max(os.listdir(pathTo))
				except ValueError:
					maxFile = []
				if maxFile:
					finalPath = '%s/%s' %(pathTo, maxFile)
					moveIT = '%s\\%s' % (moveTo.replace('/', '\\'), maxFile)
					if os.path.isfile(moveIT):
						os.remove(moveIT)
					print 'Copy in progress for %s' % maxFile
					shutil.copyfile(finalPath, '%s/%s' % (moveTo, maxFile))
				else:
					cmds.warning('FAILED!: Nothing has been published for this asset! Talk to the modelling dept.')

		self._createBaseGroups()
		self._importSingleCache(pathTo, '%s_ABC_STATIC_CACHES_hrc' % self.currentENV, '%s_hrc' % eachAsset)
		for eachAssetCBx in self.fileBoxes:
			if eachAssetCBx.text() == eachAsset:
				eachAssetCBx.setChecked(False)
				eachAssetCBx.setStyleSheet("QCheckBox{background-color: green}")

	def _republishAllAlembicsForENV(self):
		"""
		This helper will republish all the MDL alembic files from the most recently published mb files found in the assets folders
		for every asset associated to the ENV.

		getData = self.sgsrv.find('Asset',  filters = [["code", "is", eachENV]], fields=['code', 'id', 'assets'])
		Finds the ENV name and then gets a list of Sub Assets associated with it from the assets field.

		This is why we want every ENV to be the parent of an asset in the system appropriately.
		"""
		start = time.time()

		## Empty the scene first, or BAD THINGS HAPPEN!!!
		cmds.file(new = True, f = True)

		## Path to the assets folder
		pathToAssets = "I:/lsapipeline/assets" ##Hardcoded yuckiness..

		## Fetch the subAssets for the ENV
		getData = self.sgsrv.find('Asset',  filters = [["code", "is", self.envPulldown.currentText()]], fields=['code', 'id', 'assets'])

		for eachAsset in getData[0]['assets']:
			## BLD
			if 'BLD' in eachAsset['name']:
				assetPublishFolder = "%s/Building/%s/MDL/publish/maya" % (pathToAssets, eachAsset['name'])
			## LND
			elif 'LND' in eachAsset['name']:
				assetPublishFolder = "%s/Environment/%s/MDL/publish/maya" % (pathToAssets, eachAsset['name'])

			assetPublishFolder.replace("/", os.sep)
			if os.path.isdir(assetPublishFolder):
				getLatestPublish = max(os.listdir(assetPublishFolder))
				if getLatestPublish and getLatestPublish.endswith('.mb'):
					latestPublish = '%s/%s' % (assetPublishFolder, getLatestPublish)
					latestPublish.replace("/", os.sep)
					alembicPath = latestPublish.replace('.mb', '.abc').replace('maya', 'alembic').replace('.v', '_ABC.v')
					## Remove current alembic
					if os.path.isfile(alembicPath):
						os.remove(alembicPath)
					## Import the file so we don't have to display anything due to the files prob being saved with tesxtures on etc
					print '====================='
					print 'Importing %s now...' % latestPublish
					try:    cmds.file(latestPublish, i = True, f = True)
					except: cmds.warning('Failed to import %s...' % latestPublish)
					cleanup.removeAllNS()
					print 'Import complete'
					print '====================='

					## Change uv set map1 if the mesh has multiple uv sets for alembic cache
					[cmds.polyUVSet(each, currentUVSet = True, uvSet = 'map1') for each in cmds.ls(type = 'mesh')]

					## Now scan the geo in the scene and preserve the crease information
					print '====================='
					print 'Adding crease SubDivisionMesh attr'
					for each in cmds.ls(type = 'mesh', l = True):
						if not cmds.objExists('%s.SubDivisionMesh' % each):
							try:
								cmds.addAttr('%s' % each, ln = 'SubDivisionMesh', at = 'bool')
								cmds.setAttr("%s.SubDivisionMesh" % each, 1)
							except:
								pass
					print 'Complete..'
					print '====================='

					## Now export back out a new alembic with the version name that should exist in the assembly reference.
					rootName = '%s_hrc' % eachAsset['name']
					# abc_export_cmd = "-attr smoothed -attr SubDivisionMesh -ro -uvWrite -wholeFrameGeo -worldSpace -writeVisibility -fr 1 1 -root %s -file %s" % (rootName, alembicPath)
					abc_export_cmd = "-attr smoothed -attr SubDivisionMesh -ro -uvWrite -wholeFrameGeo -worldSpace -writeVisibility -fr %d %d -root %s -file %s" % (1, 1, rootName, alembicPath)
					try:
						print '====================='
						print 'Exporting %s to alembic cache now to %s' % (rootName, alembicPath)
						cmds.AbcExport(verbose = False, j = abc_export_cmd)
						print 'Export Complete...'
						print '====================='
					except:
						print "Failed to export Alembic Cache!!"
			## Now do a new scene with no save
			cmds.file(new = True, f = True)
		# print 'FINISHED FIXING ALL ALEMBIC PUBLISHES FOR ASSETS FOR ENV: %s'  % eachENV
		print 'TIME: %s' % (time.time()-start)

	def _isRootFolderThere(self, rootFolder):
		"""
		Method used to check if root folder is valid or not eg: I:/lsapipeline/assets
		@param rootFolder: The path to the root folder to check for
		@type rootFolder: String
		"""
		if not os.path.isdir(rootFolder):
			print 'No such root folder found: %s' % rootFolder
			return -1
		else:
			return 1

	def findAlembicPublishes(self, envName = '', rootFolder = 'I:/lsapipeline/assets', moveTo = 'I:/lsapipeline/episodes/ep000/ep000_sh010/Light/publish/alembic_static'):
		"""
		Function to find all the LND asset published alembic MDL publishes and move them into the lighting base shot folder.
		Note this will grab every asset parented to the ENV asset in shotgun. If they are missing from this field they won't be pulled in correctly.
		Also note it was originally intended to process the entire world, so the envList is kinda old now as we're just doing the one ENV at a time.

		@param envName: The name of the ENV we're looking for subAssets of
		@param rootFolder: The path of the rootFolder for the assets to scan for
		@param moveTo: The path of the master shot folders alembic_static we are going to copy the files to
		@type envName: String
		@type rootFolder: String
		@type moveTo: String
		"""
		start = time.time()
		pathToAssets = "I:/lsapipeline/assets"

		getData = self.sgsrv.find('Asset',  filters = [["code", "is", envName]], fields=['code', 'id', 'assets'])
		for eachAsset in getData[0]['assets']:
			## BLD
			if 'BLD' in eachAsset['name']:
				pathTo = "%s/Building/%s/MDL/publish/alembic" % (rootFolder, eachAsset['name'])
			## LND
			elif 'LND' in eachAsset['name']:
				pathTo = "%s/Environment/%s/MDL/publish/alembic" % (rootFolder, eachAsset['name'])

			if self._isRootFolderThere(rootFolder = pathTo):
				if os.path.isdir(pathTo):
					try:
						maxFile = max(os.listdir(pathTo))
					except ValueError:
						maxFile = []
					if maxFile:
						finalPath = '%s/%s' %(pathTo, maxFile)
						moveIT = '%s\\%s' % (moveTo.replace('/', '\\'), maxFile)
						if os.path.isfile(moveIT):
							os.remove(moveIT)
						print 'Copy in progress for %s' % maxFile
						shutil.copyfile(finalPath, '%s/%s' % (moveTo, maxFile))

		self._createBaseGroups(envs[0])
		self._importCaches(moveTo, '%s_ABC_STATIC_CACHES_hrc' % self.currentENV)
		self._createSets()

	def _importSingleCache(self, folderPath, parentGrp, cacheName):
		"""
		Function to import the alembics and parent them to the right group
		@param folderPath: Path to the folder for the caches to import
		@param parentGrp: The name of the group to parent the alembics to.
		@type folderPath: String
		@type parentGrp: String
		"""
		try:
			findLatest = max(os.listdir(folderPath))
		except:
			findLatest = []

		if findLatest:
			try:
				cmds.AbcImport('%s/%s' % (folderPath, findLatest), reparent  = parentGrp, setToStartFrame = True)
				self._createSets()
			except RuntimeError:
				cmds.warning('Failed to import cache! %s/%s' % (folderPath, findLatest))

			## Now add the version number to the grp
			versionNumber = findLatest.split('.')[-2].split('v')[-1]
			self._addVersionTag('%s' % cacheName, versionNumber)
		else:
			cmds.warning('Nothing published for %s !' % cacheName)

	def _importCaches(self, folderPath, parentGrp):
		"""
		Function to import the alembics and parent them to the right group
		@param folderPath: Path to the folder for the caches to import
		@param parentGrp: The name of the group to parent the alembics to.
		@type folderPath: String
		@type parentGrp: String
		"""
		for eachCache in os.listdir(folderPath):
			try:
				cmds.AbcImport('%s/%s' % (folderPath, eachCache), reparent  = parentGrp, setToStartFrame = True)
			except RuntimeError:
				cmds.warning('Failed to import cache! %s/%s' % (folderPath, eachCache))
		self._createSets()

	def _createBaseGroups(self):
		"""
		Function to create the base grps for the caches to be parented to.
		@param envName: The name of the enviroment we are importing into.
		@type envName: String
		"""
		envName = self.currentENV
		if envName:
			grps = ['%s_ABC_STATIC_CACHES_hrc' % self.currentENV, '%s_Core_Archives_hrc' % self.currentENV]
		else:
			grps = ['%s_ABC_STATIC_CACHES_hrc' % self.envPulldown.currentText(), '%s_Core_Archives_hrc' % self.envPulldown.currentText()]

		for eachGrp in grps:
			if not cmds.objExists(eachGrp):
				cmds.group(n = eachGrp, em = True)

	def _createSets(self):
		"""
		Function used to put the alembic caches into the right sets for use witht ehlayout tool deved in house at LSky
		The lists were built from the base ENV scenes pre the cleanup. If new buildings are added to the sets they should be added to the lists
		below
		"""

		## Now check for the sets

		## Sets for MIDDLE HARBOUR
		if self.envPulldown.currentText() == 'ENV_MIDDLEHARBOUR_STATIC':
			animBuildList = ['BBB_CanoeBoatHouse_BLD', 'AI_Jetty_Dock_BLD_hrc', 'BBB_BowserBoatHouse_Dock_BLD_hrc','BBB_DockyardPier_Dock_BLD_hrc','BBB_Jetty_Dock_BLD_hrc','BBB_MainStorage_Dock_BLD_hrc','BBB_Office_Dock_BLD_hrc','BBB_TheMarina_Dock_BLD_hrc','BBB_DryDockInterior_BLD_hrc','BBB_Int_TerrysStorageshed_BLD_hrc','BBB_ZipBoatHouse_BLD_hrc', 'BBB_ZipBoathouseInterior_BLD_hrc','BBB_SydneyBoatHouse_BLD_hrc', 'BBB_SydneyBoathouseInterior_BLD_hrc']
			setList = {
					   "BBBEastPointLND"    : ["BBB_Silo_BLD_hrc", "BBB_StorageShed02_BLD_hrc", "BBB_TerrysBoatHouse_BLD_hrc", "BBB_TerrysStorageShed_BLD_hrc", "BBB_DockyardPier_BLD_hrc", "BBB_EastPoint_LND_hrc"],
					   "BBBMidPointLND"     : ["BBB_Storage001_BLD_hrc", "BBB_Storage002_BLD_hrc", "BBB_StorageShed_BLD_hrc", "BBB_TheMarina_BLD_hrc", "BBB_Gen011_BLD_hrc", "BBB_Jetty_BLD_hrc", "BBB_MainStorage_BLD_hrc", "BBB_Office_BLD_hrc", "BBB_PirateShip_BLD_hrc", "BBB_MidPoint_LND_hrc", "BBB_DryDockMainBuilding_BLD_hrc", "BBB_DryDockInterior_BLD_hrc"],
					   "BBBWestPointLND"    : ["BBB_BowserBoatHouse_BLD_hrc", "BBB_Gen002_BLD_hrc", "BBB_Gen008_BLD_hrc", "BBB_Gen009_BLD_hrc", "BBB_Gen010_BLD_hrc", "BBB_Gen007_BLD_hrc", "BBB_Gen003_BLD_hrc", "BBB_Gen004_BLD_hrc", "BBB_Gen001_BLD_hrc", "BBB_Gen005_BLD_hrc", "BBB_Gen006_BLD_hrc", "BBB_WestPoint_LND_hrc", "BBB_ZipBoatHouse_BLD_hrc", "BBB_SydneyBoatHouse_BLD_hrc"],
					   "TWRLND"             : ["TWR_LND_hrc"],
					   }
		## Sets for MIDDLE HARBOUR EAST
		if self.envPulldown.currentText() == 'ENV_MIDDLEHARBOUR_EAST_STATIC':
			animBuildList = []
			setList = {
					   "AILND"              : ["AI_LightHouse_BLD_hrc", "AI_LND_hrc", "AI_Jetty_BLD_hrc"],
					   "FWBSandbarLND"      : ["FWB_Rock001_LND_hrc", "FWB_Rock002_LND_hrc", "FWB_Rock003_LND_hrc", "FWB_Rock004_LND_hrc", "FWB_Rock005_LND_hrc", "FWB_Rock006_LND_hrc", "FWB_Rock007_LND_hrc", "FWB_Rock008_LND_hrc", "FWB_BeachHouse_LND_hrc", "FWB_Sandbar_LND_hrc", "FWB_Fingers_LND_hrc", ],
					   "HCEastLND"          : ["HC_ExtraBlockingRock_LND_hrc", "HC_East_LND_hrc", "HC_Island010_E_LND_hrc", "HC_Island010_F_LND_hrc", "HC_Waterfall001_LND_hrc", "HC_Bridge001_A_LND_hrc", "HC_Bridge001_B_LND_hrc", "HC_Bridge001_C_LND_hrc", "HC_Cave001_LND_hrc", "HC_Island006_A_LND_hrc", "HC_Island006_B_LND_hrc", "HC_Island007_LND_hrc", "HC_Island010_A_LND_hrc", "HC_Island010_B_LND_hrc", "HC_Island010_C_LND_hrc", "HC_Island010_D_LND_hrc"],
					   "HCNorthLND"         : ["HC_North_LND_hrc", "HC_Entrance002_LND_hrc", "HC_Island001_A_LND_hrc", "HC_Island001_B_LND_hrc", "HC_Island001_C_LND_hrc", "HC_Island001_D_LND_hrc", "HC_Island001_E_LND_hrc", "HC_Island001_F_LND_hrc", "HC_Island001_G_LND_hrc", "HC_Island001_H_LND_hrc", "HC_Island001_I_LND_hrc", "HC_Island001_J_LND_hrc", "HC_Island002_A_LND_hrc", "HC_Island002_B_LND_hrc", "HC_Island003_A_LND_hrc", "HC_Island003_B_LND_hrc", "HC_Island004_LND_hrc"],
					   "HCSouthLND"         : ["HC_South_LND_hrc"],
					   "HCWestLND"          : ["HC_Entrance001_LND_hrc", "HC_West_LND_hrc", "HC_ShipWreck_BLD_hrc", "HC_Island008_LND_hrc", "HC_Island009_LND_hrc"],
					   }

		## Sets for WEST HARBOUR
		elif self.envPulldown.currentText() == 'ENV_WESTHARBOUR_STATIC':
			animBuildList = ['BB_PP_JettyDock_01_BLD', 'BB_PP_JettyDock_02_BLD', 'DingleIsland_JettyDock_BLD', 'LittleTown_Dock001_BLD', 'LittleTown_Dock002_BLD', 'MulliganTown_JettyDock_01_BLD', 'MulliganTown_JettyDock_02_BLD', 'BB_OF_Lease_BLD']
			setList = {
					   'AdmiralBridgeLND'       : ["AdmiralBridge_LND_hrc"],
					   'BBOysterFarmLND'        : ["BB_OysterFarm_LND_hrc", "BB_OF_Hut005_BLD_hrc", "BB_OF_Lease_BLD_hrc", "BB_OF_Hut004_BLD_hrc", "BB_OF_Hut003_BLD_hrc", "BB_OF_Hut002_BLD_hrc", "BB_OF_Hut001_BLD_hrc"],
					   'BBPointPeriwinkleLND'   : ["BB_PointPeriwinkle_LND_hrc", "BB_PP_Jetty_BLD_hrc", "BB_PP_Huts_BLD_hrc", "BB_PP_JettyDock_01_BLD_hrc", "BB_PP_JettyDock_02_BLD_hrc"],
					   'DingleIslandLND'        : ["DingleIsland_JettyDock_BLD_hrc", "DingleIsland_LND_hrc"],
					   'LittleTownLND'          : ["LittleTown_EastBuilding_BLD_hrc", "LittleTown_MidBuilding_BLD_hrc", "LittleTown_MidGenBuilding_BLD_hrc", "LittleTown_WestBuilding_BLD_hrc", "LittleTown_East_LND_hrc", "LittleTown_Mid_LND_hrc", "LittleTown_West_LND_hrc"],
					   'MuliganTownLND'         : ["MulliganTown_JettyBuilding_BLD_hrc", "MulliganTown_EastBuilding_BLD_hrc", "MulliganTown_WestBuilding_BLD_hrc", "MulliganTown_EastGenBuilding_BLD_hrc", "MulliganTown_WestGenBuilding_BLD_hrc", "MulliganTown_SateliteHouse_BLD_hrc", "MulliganTown_JettyDock_01_BLD_hrc", "MulliganTown_JettyDock_02_BLD_hrc", "MulliganTown_East_LND_hrc", "MulliganTown_West_LND_hrc"]
					   }

		## Sets for BIG TOWN
		elif self.envPulldown.currentText() == 'ENV_BIGTOWN_STATIC':
			animBuildList = ['BigPort_Shipyard_Dock_BLD']
			setList = {
					   'BigNorthPortLND'        : ["BigNorthPort_LND_hrc", "BigNorthPort_Building_BLD_hrc"],
					   'BigPortLND'             : ["BigPort_LND_hrc", "BigPort_Shipyard_BLD_hrc"],
					   'BigTown01LND'           : ["BigTown_01_LND_hrc", "BigTown_01_Building_BLD_hrc"],
					   'BigTown02LND'           : ["BigTown_02_LND_hrc", "BigTown_02_Building_BLD_hrc"],
					   'BigTownLND'             : ["BigTown_LND_hrc", "BigTown_Building_BLD_hrc"],
					   }

		## Sets for THEHEADS
		elif self.envPulldown.currentText() == 'ENV_THEHEADS_STATIC':
			animBuildList = []
			setList = {
					   'THIrisleLND'        : ['TH_IrisIsle_LND_hrc'],
					   'THMangoShore01LND'  : ["TH_MangoShore01_LND_hrc", "TH_MangoShore02_LND_hrc"],
					   'THRainbowShoreLND'  : ["TH_RainbowCliffs_LND_hrc", "TH_RainbowShore01_LND_hrc", "TH_RainbowShore02_LND_hrc"]
					   }
		cmds.select(clear = True)
		for setName, itemList in setList.items():
			if not cmds.objExists(setName):
				cmds.sets(n = setName)

			for eachHRC in itemList:
				if eachHRC not in animBuildList:
					try:
						cmds.sets(eachHRC, e = True, forceElement = setName)
						print 'Successfully added %s to %s' % (eachHRC, setName)
					except ValueError:
						print 'Failed to add %s' % eachHRC

	def _reconnectDuplicates(self, eachGeo = '', core_archive = ''):
		"""
		Stuff...
		"""
		## Fetch the Geo Shaders
		## Now reconnect
		getCoreConnections = cmds.listConnections('%s.message' % core_archive, plugs = True)
		if not cmds.objExists(core_archive):
			cmds.warning('_reconnectDuplicates needs a valid core_archive to work!!\n\t%s is invalid!' % core_archive)
		else:
			if '%s.miGeoShader' % eachGeo not in getCoreConnections:
				#print 'Reconnected %s to %s' % (eachGeo, core_archive)
				cmds.connectAttr('%s.message' % core_archive, '%s.miGeoShader' % eachGeo, force = True)

	def _fixTheFuckingCores(self):
		"""
		This is used to clean sweep the static scenes and remove the duplicate Namespaces and reconnect the bases to the duplicates
		"""

		removedNameSpaces = []
		## Remove duplicate root core namespaces
		getAllNameSpaces = cmds.namespaceInfo(listOnlyNamespaces = True)
		for eachNS in getAllNameSpaces:
			if eachNS.endswith('1'):
				print 'Removing %s' % eachNS
				cmds.namespace(removeNamespace = eachNS, mergeNamespaceWithRoot = True)
				removedNameSpaces.append(eachNS.replace('1', '').replace('_CORE', ''))

		## Remove duplicate base cores
		for each in cmds.ls(type = 'core_archive'):
			if '1'in each:
				print 'Cleaned rootCore %s from scene...' % each
				cmds.delete(each)

		## Now find all geo with the core name in it and proceess it for reconnection
		for eachCore in removedNameSpaces:
			#print eachCore
			## Check child _hrc grps for processing
			getAllGeo = [eachGeo for eachGeo in cmds.ls('*%s*' % eachCore) if cmds.nodeType(eachGeo) == 'transform']
			for eachGeo in getAllGeo:
				self._reconnectDuplicates(eachGeo, '%s_CORE_Geoshader' % eachCore)

		coreLib.cleanupDeadCoreArchives()

	def _rebuildCoresForSelected(self):
		"""
		Function to help delete all cores and rebuild for selected LND
		"""
		pass
Пример #50
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
Пример #51
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

try:
    print '<h3>Processing request to create playlist from current version of these shots...</h3>'
    print '</br>'
    print '</br>'
    success = True # keep track of errors so that true success for all requests can be reported to the user
    
       
    shot_filters = [
    ['project','is',{'type':'Project','id':PROJECT_ID}],
    ['id', 'in', ] + shot_ids
    ]
    
    # #mark First get the version so that the linked shot can then be accessed.
    assets= sg.find("Shot", shot_filters, shot_fields)

    # did anything get returned? if not then error out...
    if len(assets) < 1:
        print '</br>'
        print "<b>Shotgun Server Did Not Return Any Shots! </b>"
        print '</br>'
        print '</br>'            
        success = False


    else: # something was returned, process it!
                        
        for an_asset in assets: # get the appropriate version and append it to the version list
            
             # first, look to see if there is a current version in the shot data
Пример #53
0
    document.add_heading(fileName, 0)

    # Writing it out
    document.add_paragraph(unicode(feed, 'utf-8'))
    try :
        document.save('I:\dev_JC\_Python\Data_Pull\WD\\' + fileName + '.docx')
    except IOError:
        document.save('I:\dev_JC\_Python\Data_Pull\WD\\' + "Bad_Name" + '.docx')

# Pulls a shotgun Thread based on the id
formatting ={}
filters = [ ['id', 'is', 123]]  ##This is the controller, place whatever project ID you need docs for
project = sg.find_one('Project', filters, fields=['id'])
filters = [ ['project', 'is', {'type':'Project', 'id':project['id']}], ]
#result = sg.find('Asset', filters, fields=['sg_rpm_number', 'notes', 'id', 'sg_rpm_number'])
result = sg.find('Asset', filters, fields=['sg_rpm_number', 'cached_display_name','notes', 'id', 'sg_rpm_number'])
print result


for i in result:
    thread = ""
    dict = i['notes']
    excludeRPM = []
    excludeID = []

    # Filter out array elements that are not threads in list/bad job numbers
    if not dict:
        continue
    if i['sg_rpm_number'] in excludeRPM:
        continue
Пример #54
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()
Пример #55
0
import logging
import logging.config
import gluon.contrib.simplejson

# shotgun
sys.path.append('/X/tools/pythonlib')
from shotgun_api3 import Shotgun

SG = Shotgun(sg_server, sg_script_name, sg_script_key)

session.departments = []
if not session.departments:
    session.departments = SG.find('Department',
                                  [['sg_status_list', 'is', 'act']],
                                  fields=['code', 'name', 'color'],
                                  order=[{
                                      'field_name': 'name',
                                      'direction': 'asc'
                                  }])
session.dept_to = []
session.dept_ny = []
for d in session.departments:
    if d['code'].upper().startswith('NY'):
        session.dept_ny.append(d['id'])
    else:
        session.dept_to.append(d['id'])

PROJECT_STATUS = ['Active', 'Bidding', 'Demo/Test', 'Delivered']

if not session.projects:
    result = SG.find('Project', [['sg_status', 'in', PROJECT_STATUS]],