def update_context(self, context): '''Update based on *context*.''' logging.info('Building context from: {0}'.format( pprint.pformat(context))) if context['version']: contributors = session.query( 'select user_id from AssetVersion where id ' 'in ({0})'.format(','.join(context['version']))).all() for contributor in contributors: self._lookup[contributor['user_id']] = 'contributors' if context['task']: other_assignees = session.query( 'select id from User where assignments.context_id ' 'in ({0})'.format(','.join(context['task']))).all() for assignee in other_assignees: self._lookup[assignee['id']] = 'assigned' for task_id in context['task']: try: managers = ftrack.Task(task_id).getManagers() for manager in managers: self._lookup[manager.get('userid')] = 'supervisors' except Exception: logging.warning( 'Failed to get managers for task with id "{0}"'.format( task_id)) logging.info('_lookup contains "{0}"'.format(str(self._lookup)))
def __init__(self): '''Initialise classifier.''' super(UserClassifier, self).__init__() logging.info('Initialise classifier') self._lookup = dict()
def register(registry, **kw): '''Register hook.''' # Validate that registry is instance of ftrack.Registry, if not # return early since the register method probably is called # from the new API. if not isinstance(registry, ftrack.Registry): return logging.info('Register assignment notification hook') ftrack.EVENT_HUB.subscribe('topic=ftrack.crew.notification.assignment', callback)
def publish_script_panel(self): task = self.current_task asset_name = self.asset_name thumbnail = self.asset_thumbnail comment = self.comment asset_type = self.current_asset_type import tempfile tmp_script = tempfile.NamedTemporaryFile(suffix='.nk', delete=False).name nuke.scriptSaveAs(tmp_script) task = ftrack.Task(task.getId()) parent = task.getParent() if isinstance(parent, ftrack.Project): msg = 'Cannot publish asset "%s" under project "%s"' self.header.setMessage(msg % (task.getName(), parent.getName()), 'error') asset_id = parent.createAsset(name=asset_name, assetType=asset_type).getId() asset = ftrack.Asset(asset_id) version = asset.createVersion(comment=comment, taskid=task.getId()) version.createComponent(name='nukescript', path=tmp_script) logging.info(thumbnail) if thumbnail: version.createThumbnail(thumbnail) scene_metas = SceneNodeAnalyser() version.setMeta('mft.node_numbers', json.dumps(scene_metas.node_number_meta)) dependencies = get_dependencies() logging.info(dependencies.values()) version.addUsesVersions(versions=dependencies.values()) result = version.publish() if result: self.header.setMessage('Asset %s correctly published' % asset.getName()) if self.current_shot_status_changed(): task.shot.ftrack_object.setStatus(self.current_shot_status) if self.current_task_status_changed(): task.setStatus(self.current_task_status)
def callback(event): '''Handle version notification call to action. The callback will find the Node in the graph matching the parent asset of the version specified in `event['data']['version_id']`. When found it will try to match the Component used and replace it with a Component from the new version. ''' logging.info('Changing version of asset based on data:\n{0}'.format( pprint.pformat(event['data']))) location = ftrack.Location('ftrack.connect') session = ftrack_api.Session() # TODO: Update this to pick which Component to use in a more sophisticated # way. result = session.query('select components, id, asset.name from ' 'AssetVersion where id is "{0}"'.format( event['data']['version_id'])).all()[0] # TODO: See if this can be done by using the Locations API in the new # API. componentInLocation = location.getComponent(result['components'][0]['id']) accessPath = componentInLocation.getFilesystemPath() importObj = FTAssetObject(componentId=result['components'][0]['id'], filePath=accessPath, componentName=result['components'][0]['name'], assetVersionId=result['id']) Connector.changeVersion(iAObj=importObj, applicationObject=_getNodeName( result['asset']['id']))
def callback(event): '''Handle assignment notification call to action. This hook will reset the environment variables TASK_ID and SHOT_ID to match the *event* and will try to load any nukescript published on the task. ''' logging.info('Open nukescript published on task based on:\n{0}'.format( pprint.pformat(event['data']))) _session = ftrack_api.Session() task_id = event['data']['task_id'] task = _session.get('Task', task_id) logging.info('Setting FTRACK_TASKID to: {0}'.format(task_id)) os.environ['FTRACK_TASKID'] = task_id logging.info('Setting FTRACK_SHOTID to: {0}'.format(task_id)) os.environ['FTRACK_SHOTID'] = task['parent_id'] # Find the component and open it in Nuke. components = _session.query( 'select id, version.version from Component where ' 'name is "nukescript" and version.task_id is "{task_id}"'.format( task_id=task_id)).all() components = sorted(components, key=lambda component: component['version']['version']) if components: component = components[0] entity_reference = 'ftrack://{component_id}?entityType=component'.format( component_id=component['id']) open_published_script(entity_reference) else: FnAssetAPI.logging.warning('No valid component found.')
def __init__(self, parent=None): '''Initialise widget with *parent*.''' super(NukeCrew, self).__init__(parent=parent) ftrack_connect.ui.theme.applyTheme(self, 'integration') self.setMinimumWidth(400) self.setSizePolicy( QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)) self.vertical_layout = QtWidgets.QVBoxLayout(self) self.horizontal_layout = QtWidgets.QHBoxLayout() self.header = Header(username=getpass.getuser(), parent=self) self.vertical_layout.addWidget(self.header) self.notification_list = _notification_list.Notification(self) self._hub = ftrack_connect_nuke.crew_hub.crew_hub self._classifier = UserClassifier() self._classifier.update_context(self._read_context_from_environment()) current_user = ftrack.getUser(getpass.getuser()) groups = ['Assigned', 'Contributors', 'Supervisors'] self.chat = _crew.Crew(groups, current_user, hub=self._hub, classifier=self._classifier, parent=self) self.chat.chat.busyOverlay.setStyleSheet(NUKE_OVERLAY_STYLE) added_user_ids = [] for _user in session.query('select id, username, first_name, last_name' ' from User where is_active is True'): if _user['id'] != current_user.getId(): self.chat.addUser( u'{0} {1}'.format(_user['first_name'], _user['last_name']), _user['id']) added_user_ids.append(_user['id']) self.tab_panel = QtWidgets.QTabWidget(parent=self) self.tab_panel.addTab(self.chat, 'Chat') self.tab_panel.addTab(self.notification_list, 'Notifications') self.horizontal_layout.addWidget(self.tab_panel) # TODO: This styling should probably be done in a global stylesheet # for the entire Nuke plugin. self.notification_list.overlay.setStyleSheet(NUKE_OVERLAY_STYLE) self.vertical_layout.setContentsMargins(0, 0, 0, 0) self.vertical_layout.addLayout(self.horizontal_layout) self.setObjectName('Crew') self.setWindowTitle('Crew') # Import inline to avoid mysterious segfault in nuke 9.1dev build. from ftrack_connect.connector.panelcom import (PanelComInstance as _PanelComInstance) panel_communication_singleton = _PanelComInstance.instance() panel_communication_singleton.addRefreshListener(self.on_refresh_event) self.on_refresh_event() if not self._hub.compatibleServerVersion: logging.info('Incompatible server version.') self.blockingOverlay = ftrack_connect.ui.widget.overlay.BlockingOverlay( self, message='Incompatible server version.') self.blockingOverlay.setStyleSheet(NUKE_OVERLAY_STYLE) self.blockingOverlay.show() else: self._hub.populateUnreadConversations(current_user.getId(), added_user_ids)