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)
示例#5
0
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)