mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-02 00:44:52 +01:00
Merge branch '2.0/develop' into develop
This commit is contained in:
commit
2460cd1fdc
236 changed files with 13976 additions and 1252 deletions
|
|
@ -1,2 +1,7 @@
|
|||
from .lib import *
|
||||
from .ftrack_server import *
|
||||
from .ftrack_module import FtrackModule
|
||||
|
||||
|
||||
def tray_init(tray_widget, main_widget):
|
||||
return FtrackModule(main_widget, tray_widget)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import os
|
||||
import toml
|
||||
import time
|
||||
from pype.ftrack import AppAction
|
||||
from avalon import lib
|
||||
from app.api import Logger
|
||||
from pypeapp import Logger
|
||||
from pype import lib as pypelib
|
||||
|
||||
log = Logger.getLogger(__name__)
|
||||
log = Logger().get_logger(__name__)
|
||||
|
||||
|
||||
def registerApp(app, session):
|
||||
|
|
@ -37,6 +38,9 @@ def registerApp(app, session):
|
|||
description = apptoml.get('description', None)
|
||||
preactions = apptoml.get('preactions', [])
|
||||
|
||||
if icon:
|
||||
icon = icon.format(os.environ.get('PYPE_STATICS_SERVER', ''))
|
||||
|
||||
# register action
|
||||
AppAction(
|
||||
session, label, name, executable, variant,
|
||||
|
|
@ -65,4 +69,4 @@ def register(session):
|
|||
time.sleep(0.1)
|
||||
app_counter += 1
|
||||
except Exception as e:
|
||||
log.warning("'{0}' - not proper App ({1})".format(app['name'], e))
|
||||
log.exception("'{0}' - not proper App ({1})".format(app['name'], e))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import sys
|
|||
import argparse
|
||||
import logging
|
||||
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
from pype.clockify import ClockifyAPI
|
||||
|
||||
|
||||
class StartClockify(BaseAction):
|
||||
'''Starts timer on clockify.'''
|
||||
|
||||
#: Action identifier.
|
||||
identifier = 'clockify.start.timer'
|
||||
#: Action label.
|
||||
label = 'Start timer'
|
||||
#: Action description.
|
||||
description = 'Starts timer on clockify'
|
||||
#: roles that are allowed to register this action
|
||||
icon = 'https://clockify.me/assets/images/clockify-logo.png'
|
||||
#: Clockify api
|
||||
clockapi = ClockifyAPI()
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
if len(entities) != 1:
|
||||
return False
|
||||
if entities[0].entity_type.lower() != 'task':
|
||||
return False
|
||||
if self.clockapi.workspace_id is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
def launch(self, session, entities, event):
|
||||
task = entities[0]
|
||||
task_name = task['type']['name']
|
||||
project_name = task['project']['full_name']
|
||||
|
||||
def get_parents(entity):
|
||||
output = []
|
||||
if entity.entity_type.lower() == 'project':
|
||||
return output
|
||||
output.extend(get_parents(entity['parent']))
|
||||
output.append(entity['name'])
|
||||
|
||||
return output
|
||||
|
||||
desc_items = get_parents(task['parent'])
|
||||
desc_items.append(task['name'])
|
||||
description = '/'.join(desc_items)
|
||||
project_id = self.clockapi.get_project_id(project_name)
|
||||
tag_ids = []
|
||||
tag_ids.append(self.clockapi.get_tag_id(task_name))
|
||||
self.clockapi.start_time_entry(
|
||||
description, project_id, tag_ids=tag_ids
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def register(session, **kw):
|
||||
'''Register plugin. Called when used as an plugin.'''
|
||||
|
||||
if not isinstance(session, ftrack_api.session.Session):
|
||||
return
|
||||
|
||||
StartClockify(session).register()
|
||||
|
||||
|
||||
def main(arguments=None):
|
||||
'''Set up logging and register action.'''
|
||||
if arguments is None:
|
||||
arguments = []
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
# Allow setting of logging level from arguments.
|
||||
loggingLevels = {}
|
||||
for level in (
|
||||
logging.NOTSET, logging.DEBUG, logging.INFO, logging.WARNING,
|
||||
logging.ERROR, logging.CRITICAL
|
||||
):
|
||||
loggingLevels[logging.getLevelName(level).lower()] = level
|
||||
|
||||
parser.add_argument(
|
||||
'-v', '--verbosity',
|
||||
help='Set the logging output verbosity.',
|
||||
choices=loggingLevels.keys(),
|
||||
default='info'
|
||||
)
|
||||
namespace = parser.parse_args(arguments)
|
||||
|
||||
# Set up basic logging
|
||||
logging.basicConfig(level=loggingLevels[namespace.verbosity])
|
||||
|
||||
session = ftrack_api.Session()
|
||||
register(session)
|
||||
|
||||
# Wait for events
|
||||
logging.info(
|
||||
'Registered actions and listening for events. Use Ctrl-C to abort.'
|
||||
)
|
||||
session.event_hub.wait()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import json
|
||||
import ftrack_api
|
||||
from pype.ftrack import BaseAction, MissingPermision
|
||||
from pype.clockify import ClockifyAPI
|
||||
|
||||
|
||||
class SyncClocify(BaseAction):
|
||||
'''Synchronise project names and task types.'''
|
||||
|
||||
#: Action identifier.
|
||||
identifier = 'clockify.sync'
|
||||
#: Action label.
|
||||
label = 'Sync To Clockify'
|
||||
#: Action description.
|
||||
description = 'Synchronise data to Clockify workspace'
|
||||
#: priority
|
||||
priority = 100
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub', 'Administrator']
|
||||
#: icon
|
||||
icon = 'https://clockify.me/assets/images/clockify-logo-white.svg'
|
||||
#: CLockifyApi
|
||||
clockapi = ClockifyAPI()
|
||||
|
||||
def register(self):
|
||||
if self.clockapi.workspace_id is None:
|
||||
raise ValueError('Clockify Workspace or API key are not set!')
|
||||
|
||||
if self.clockapi.validate_workspace_perm() is False:
|
||||
raise MissingPermision('Clockify')
|
||||
super().register()
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
''' Validation '''
|
||||
return True
|
||||
|
||||
def launch(self, session, entities, event):
|
||||
# JOB SETTINGS
|
||||
userId = event['source']['user']['id']
|
||||
user = session.query('User where id is ' + userId).one()
|
||||
|
||||
job = session.create('Job', {
|
||||
'user': user,
|
||||
'status': 'running',
|
||||
'data': json.dumps({
|
||||
'description': 'Sync Ftrack to Clockify'
|
||||
})
|
||||
})
|
||||
session.commit()
|
||||
try:
|
||||
entity = entities[0]
|
||||
|
||||
if entity.entity_type.lower() == 'project':
|
||||
project = entity
|
||||
else:
|
||||
project = entity['project']
|
||||
project_name = project['full_name']
|
||||
|
||||
task_types = []
|
||||
for task_type in project['project_schema']['_task_type_schema'][
|
||||
'types'
|
||||
]:
|
||||
task_types.append(task_type['name'])
|
||||
|
||||
clockify_projects = self.clockapi.get_projects()
|
||||
|
||||
if project_name not in clockify_projects:
|
||||
response = self.clockapi.add_project(project_name)
|
||||
if 'id' not in response:
|
||||
self.log.error('Project {} can\'t be created'.format(
|
||||
project_name
|
||||
))
|
||||
return {
|
||||
'success': False,
|
||||
'message': 'Can\'t create project, unexpected error'
|
||||
}
|
||||
project_id = response['id']
|
||||
else:
|
||||
project_id = clockify_projects[project_name]
|
||||
|
||||
clockify_workspace_tags = self.clockapi.get_tags()
|
||||
for task_type in task_types:
|
||||
if task_type not in clockify_workspace_tags:
|
||||
response = self.clockapi.add_tag(task_type)
|
||||
if 'id' not in response:
|
||||
self.log.error('Task {} can\'t be created'.format(
|
||||
task_type
|
||||
))
|
||||
continue
|
||||
except Exception:
|
||||
job['status'] = 'failed'
|
||||
session.commit()
|
||||
return False
|
||||
|
||||
job['status'] = 'done'
|
||||
session.commit()
|
||||
return True
|
||||
|
||||
|
||||
def register(session, **kw):
|
||||
'''Register plugin. Called when used as an plugin.'''
|
||||
|
||||
if not isinstance(session, ftrack_api.session.Session):
|
||||
return
|
||||
|
||||
SyncClocify(session).register()
|
||||
|
||||
|
||||
def main(arguments=None):
|
||||
'''Set up logging and register action.'''
|
||||
if arguments is None:
|
||||
arguments = []
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
# Allow setting of logging level from arguments.
|
||||
loggingLevels = {}
|
||||
for level in (
|
||||
logging.NOTSET, logging.DEBUG, logging.INFO, logging.WARNING,
|
||||
logging.ERROR, logging.CRITICAL
|
||||
):
|
||||
loggingLevels[logging.getLevelName(level).lower()] = level
|
||||
|
||||
parser.add_argument(
|
||||
'-v', '--verbosity',
|
||||
help='Set the logging output verbosity.',
|
||||
choices=loggingLevels.keys(),
|
||||
default='info'
|
||||
)
|
||||
namespace = parser.parse_args(arguments)
|
||||
|
||||
# Set up basic logging
|
||||
logging.basicConfig(level=loggingLevels[namespace.verbosity])
|
||||
|
||||
session = ftrack_api.Session()
|
||||
register(session)
|
||||
|
||||
# Wait for events
|
||||
logging.info(
|
||||
'Registered actions and listening for events. Use Ctrl-C to abort.'
|
||||
)
|
||||
session.event_hub.wait()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import subprocess
|
||||
import os
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
||||
|
|
@ -15,9 +15,8 @@ class ComponentOpen(BaseAction):
|
|||
# Action label
|
||||
label = 'Open File'
|
||||
# Action icon
|
||||
icon = (
|
||||
'https://cdn4.iconfinder.com/data/icons/rcons-application/32/'
|
||||
'application_go_run-256.png'
|
||||
icon = '{}/ftrack/action_icons/ComponentOpen.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ import os
|
|||
import sys
|
||||
import argparse
|
||||
import json
|
||||
import ftrack_api
|
||||
import arrow
|
||||
import logging
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction, get_ca_mongoid
|
||||
from pypeapp import config
|
||||
|
||||
"""
|
||||
This action creates/updates custom attributes.
|
||||
|
|
@ -113,20 +114,13 @@ class CustomAttributes(BaseAction):
|
|||
description = 'Creates Avalon/Mongo ID for double check'
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub', 'Administrator']
|
||||
icon = (
|
||||
'https://cdn4.iconfinder.com/data/icons/'
|
||||
'ios-web-user-interface-multi-circle-flat-vol-4/512/'
|
||||
'Bullet_list_menu_lines_points_items_options-512.png'
|
||||
icon = '{}/ftrack/action_icons/CustomAttributes.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
def __init__(self, session):
|
||||
super().__init__(session)
|
||||
|
||||
templates = os.environ['PYPE_STUDIO_TEMPLATES']
|
||||
path_items = [
|
||||
templates, 'presets', 'ftrack', 'ftrack_custom_attributes.json'
|
||||
]
|
||||
self.filepath = os.path.sep.join(path_items)
|
||||
self.types = {}
|
||||
self.object_type_ids = {}
|
||||
self.groups = {}
|
||||
|
|
@ -230,22 +224,12 @@ class CustomAttributes(BaseAction):
|
|||
self.process_attribute(data)
|
||||
|
||||
def custom_attributes_from_file(self, session, event):
|
||||
try:
|
||||
with open(self.filepath) as data_file:
|
||||
json_dict = json.load(data_file)
|
||||
except Exception as e:
|
||||
msg = (
|
||||
'Loading "Custom attribute file" Failed.'
|
||||
' Please check log for more information'
|
||||
)
|
||||
self.log.warning("{} - {}".format(msg, str(e)))
|
||||
self.show_message(event, msg)
|
||||
return
|
||||
presets = config.get_presets()['ftrack']['ftrack_custom_attributes']
|
||||
|
||||
for cust_attr_name in json_dict:
|
||||
for cust_attr_name in presets:
|
||||
try:
|
||||
data = {}
|
||||
cust_attr = json_dict[cust_attr_name]
|
||||
cust_attr = presets[cust_attr_name]
|
||||
# Get key, label, type
|
||||
data.update(self.get_required(cust_attr))
|
||||
# Get hierachical/ entity_type/ object_id
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@ import sys
|
|||
import logging
|
||||
import argparse
|
||||
import re
|
||||
import json
|
||||
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
from pype import api as pype, lib as pypelib
|
||||
from avalon import lib as avalonlib
|
||||
from avalon.tools.libraryloader.io_nonsingleton import DbConnector
|
||||
from pypeapp import config, Anatomy
|
||||
|
||||
|
||||
class CreateFolders(BaseAction):
|
||||
|
|
@ -23,10 +22,10 @@ class CreateFolders(BaseAction):
|
|||
label = 'Create Folders'
|
||||
|
||||
#: Action Icon.
|
||||
icon = (
|
||||
'https://cdn1.iconfinder.com/data/icons/hawcons/32/'
|
||||
'698620-icon-105-folder-add-512.png'
|
||||
icon = '{}/ftrack/action_icons/CreateFolders.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
db = DbConnector()
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
|
|
@ -130,12 +129,12 @@ class CreateFolders(BaseAction):
|
|||
template_publish = av_project['config']['template']['publish']
|
||||
self.db.uninstall()
|
||||
except Exception:
|
||||
anatomy = pype.Anatomy
|
||||
template_work = anatomy.avalon.work
|
||||
template_publish = anatomy.avalon.publish
|
||||
templates = Anatomy().templates
|
||||
template_work = templates["avalon"]["work"]
|
||||
template_publish = templates["avalon"]["publish"]
|
||||
|
||||
collected_paths = []
|
||||
presets = self.get_presets()
|
||||
presets = config.get_presets()['tools']['sw_folders']
|
||||
for entity in all_entities:
|
||||
if entity.entity_type.lower() == 'project':
|
||||
continue
|
||||
|
|
@ -238,17 +237,6 @@ class CreateFolders(BaseAction):
|
|||
output.extend(self.get_notask_children(child))
|
||||
return output
|
||||
|
||||
def get_presets(self):
|
||||
fpath_items = [pypelib.get_presets_path(), 'tools', 'sw_folders.json']
|
||||
filepath = os.path.normpath(os.path.sep.join(fpath_items))
|
||||
presets = dict()
|
||||
try:
|
||||
with open(filepath) as data_file:
|
||||
presets = json.load(data_file)
|
||||
except Exception as e:
|
||||
self.log.warning('Wasn\'t able to load presets')
|
||||
return dict(presets)
|
||||
|
||||
def template_format(self, template, data):
|
||||
|
||||
partial_data = PartialDict(data)
|
||||
|
|
|
|||
|
|
@ -3,11 +3,10 @@ import sys
|
|||
import re
|
||||
import argparse
|
||||
import logging
|
||||
import json
|
||||
|
||||
import ftrack_api
|
||||
from pype import lib as pypelib
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
from pypeapp import config
|
||||
|
||||
|
||||
class CreateProjectFolders(BaseAction):
|
||||
|
|
@ -21,9 +20,8 @@ class CreateProjectFolders(BaseAction):
|
|||
description = 'Creates folder structure'
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub', 'Administrator']
|
||||
icon = (
|
||||
'https://cdn2.iconfinder.com/data/icons/'
|
||||
'buttons-9/512/Button_Add-01.png'
|
||||
icon = '{}/ftrack/action_icons/CreateProjectFolders.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
pattern_array = re.compile('\[.*\]')
|
||||
|
|
@ -43,7 +41,7 @@ class CreateProjectFolders(BaseAction):
|
|||
else:
|
||||
project = entity['project']
|
||||
|
||||
presets = self.load_presets()
|
||||
presets = config.get_presets()['tools']['project_folder_structure']
|
||||
try:
|
||||
# Get paths based on presets
|
||||
basic_paths = self.get_path_items(presets)
|
||||
|
|
@ -143,28 +141,6 @@ class CreateProjectFolders(BaseAction):
|
|||
self.session.commit()
|
||||
return new_ent
|
||||
|
||||
def load_presets(self):
|
||||
preset_items = [
|
||||
pypelib.get_presets_path(),
|
||||
'tools',
|
||||
'project_folder_structure.json'
|
||||
]
|
||||
filepath = os.path.sep.join(preset_items)
|
||||
|
||||
# Load folder structure template from presets
|
||||
presets = dict()
|
||||
try:
|
||||
with open(filepath) as data_file:
|
||||
presets = json.load(data_file)
|
||||
except Exception as e:
|
||||
msg = 'Unable to load Folder structure preset'
|
||||
self.log.warning(msg)
|
||||
return {
|
||||
'success': False,
|
||||
'message': msg
|
||||
}
|
||||
return presets
|
||||
|
||||
def get_path_items(self, in_dict):
|
||||
output = []
|
||||
for key, value in in_dict.items():
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import os
|
||||
import sys
|
||||
import logging
|
||||
from bson.objectid import ObjectId
|
||||
import argparse
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
from avalon.tools.libraryloader.io_nonsingleton import DbConnector
|
||||
|
||||
|
|
@ -16,10 +17,8 @@ class DeleteAsset(BaseAction):
|
|||
label = 'Delete Asset/Subsets'
|
||||
#: Action description.
|
||||
description = 'Removes from Avalon with all childs and asset from Ftrack'
|
||||
icon = (
|
||||
'https://cdn4.iconfinder.com/data/icons/'
|
||||
'ios-web-user-interface-multi-circle-flat-vol-5/512/'
|
||||
'Delete_dustbin_empty_recycle_recycling_remove_trash-512.png'
|
||||
icon = '{}/ftrack/action_icons/DeleteAsset.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub', 'Administrator']
|
||||
|
|
@ -86,6 +85,12 @@ class DeleteAsset(BaseAction):
|
|||
'type': 'asset',
|
||||
'name': entity['name']
|
||||
})
|
||||
|
||||
if av_entity is None:
|
||||
return {
|
||||
'success': False,
|
||||
'message': 'Didn\'t found assets in avalon'
|
||||
}
|
||||
|
||||
asset_label = {
|
||||
'type': 'label',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import os
|
||||
import sys
|
||||
import logging
|
||||
import argparse
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
from avalon.tools.libraryloader.io_nonsingleton import DbConnector
|
||||
|
||||
|
|
@ -17,10 +18,8 @@ class AssetsRemover(BaseAction):
|
|||
description = 'Removes assets from Ftrack and Avalon db with all childs'
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub', 'Administrator']
|
||||
icon = (
|
||||
'https://cdn4.iconfinder.com/data/icons/'
|
||||
'ios-web-user-interface-multi-circle-flat-vol-5/512/'
|
||||
'Clipboard_copy_delete_minus_paste_remove-512.png'
|
||||
icon = '{}/ftrack/action_icons/AssetsRemover.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
#: Db
|
||||
db = DbConnector()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,14 @@
|
|||
import os
|
||||
import sys
|
||||
import re
|
||||
import json
|
||||
import logging
|
||||
import subprocess
|
||||
from operator import itemgetter
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
from app.api import Logger
|
||||
from pype import lib as pypelib
|
||||
from pypeapp import Logger, config
|
||||
|
||||
|
||||
log = Logger.getLogger(__name__)
|
||||
log = Logger().get_logger(__name__)
|
||||
|
||||
|
||||
class DJVViewAction(BaseAction):
|
||||
|
|
@ -19,16 +16,17 @@ class DJVViewAction(BaseAction):
|
|||
identifier = "djvview-launch-action"
|
||||
label = "DJV View"
|
||||
description = "DJV View Launcher"
|
||||
icon = "http://a.fsdn.com/allura/p/djv/icon"
|
||||
icon = '{}/app_icons/djvView.png'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
type = 'Application'
|
||||
|
||||
def __init__(self, session):
|
||||
'''Expects a ftrack_api.Session instance'''
|
||||
super().__init__(session)
|
||||
self.djv_path = None
|
||||
self.config_data = None
|
||||
|
||||
self.load_config_data()
|
||||
self.config_data = config.get_presets()['djv_view']['config']
|
||||
self.set_djv_path()
|
||||
|
||||
if self.djv_path is None:
|
||||
|
|
@ -56,21 +54,6 @@ class DJVViewAction(BaseAction):
|
|||
return True
|
||||
return False
|
||||
|
||||
def load_config_data(self):
|
||||
path_items = [pypelib.get_presets_path(), 'djv_view', 'config.json']
|
||||
filepath = os.path.sep.join(path_items)
|
||||
|
||||
data = dict()
|
||||
try:
|
||||
with open(filepath) as data_file:
|
||||
data = json.load(data_file)
|
||||
except Exception as e:
|
||||
log.warning(
|
||||
'Failed to load data from DJV presets file ({})'.format(e)
|
||||
)
|
||||
|
||||
self.config_data = data
|
||||
|
||||
def set_djv_path(self):
|
||||
for path in self.config_data.get("djv_paths", []):
|
||||
if os.path.exists(path):
|
||||
|
|
@ -234,6 +217,7 @@ class DJVViewAction(BaseAction):
|
|||
|
||||
return True
|
||||
|
||||
|
||||
def register(session):
|
||||
"""Register hooks."""
|
||||
if not isinstance(session, ftrack_api.session.Session):
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import json
|
||||
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
||||
|
|
@ -18,9 +19,8 @@ class JobKiller(BaseAction):
|
|||
description = 'Killing selected running jobs'
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub', 'Administrator']
|
||||
icon = (
|
||||
'https://cdn2.iconfinder.com/data/icons/new-year-resolutions/64/'
|
||||
'resolutions-23-512.png'
|
||||
icon = '{}/ftrack/action_icons/JobKiller.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
|
|
@ -46,10 +46,7 @@ class JobKiller(BaseAction):
|
|||
desctiption = data['description']
|
||||
except Exception:
|
||||
desctiption = '*No description*'
|
||||
try:
|
||||
user = job['user']['username']
|
||||
except Exception:
|
||||
user = '*No user'
|
||||
user = job['user']['username']
|
||||
created = job['created_at'].strftime('%d.%m.%Y %H:%M:%S')
|
||||
label = '{} - {} - {}'.format(
|
||||
desctiption, created, user
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import os
|
|||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import json
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
|
@ -17,9 +16,8 @@ class MultipleNotes(BaseAction):
|
|||
label = 'Multiple Notes'
|
||||
#: Action description.
|
||||
description = 'Add same note to multiple Asset Versions'
|
||||
icon = (
|
||||
'https://cdn2.iconfinder.com/data/icons/'
|
||||
'mixed-rounded-flat-icon/512/note_1-512.png'
|
||||
icon = '{}/ftrack/action_icons/MultipleNotes.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@ import os
|
|||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
import logging
|
||||
import operator
|
||||
import re
|
||||
from pype import lib as pypelib
|
||||
from app.api import Logger
|
||||
from pypeapp import Logger, config
|
||||
|
||||
log = Logger.getLogger(__name__)
|
||||
log = Logger().get_logger(__name__)
|
||||
|
||||
|
||||
class RVAction(BaseAction):
|
||||
|
|
@ -18,7 +17,9 @@ class RVAction(BaseAction):
|
|||
identifier = "rv.launch.action"
|
||||
label = "rv"
|
||||
description = "rv Launcher"
|
||||
icon = "https://img.icons8.com/color/48/000000/circled-play.png"
|
||||
icon = '{}/ftrack/action_icons/RV.png'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
type = 'Application'
|
||||
|
||||
def __init__(self, session):
|
||||
|
|
@ -40,7 +41,7 @@ class RVAction(BaseAction):
|
|||
)
|
||||
else:
|
||||
# if not, fallback to config file location
|
||||
self.load_config_data()
|
||||
self.config_data = config.get_presets()['djv_view']['config']
|
||||
self.set_rv_path()
|
||||
|
||||
if self.rv_path is None:
|
||||
|
|
@ -61,21 +62,6 @@ class RVAction(BaseAction):
|
|||
return True
|
||||
return False
|
||||
|
||||
def load_config_data(self):
|
||||
path_items = [pypelib.get_presets_path(), 'rv', 'config.json']
|
||||
filepath = os.path.sep.join(path_items)
|
||||
|
||||
data = dict()
|
||||
try:
|
||||
with open(filepath) as data_file:
|
||||
data = json.load(data_file)
|
||||
except Exception as e:
|
||||
log.warning(
|
||||
'Failed to load data from RV presets file ({})'.format(e)
|
||||
)
|
||||
|
||||
self.config_data = data
|
||||
|
||||
def set_rv_path(self):
|
||||
self.rv_path = self.config_data.get("rv_path")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import argparse
|
|||
import logging
|
||||
import json
|
||||
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction, lib as ftracklib
|
||||
|
||||
|
||||
|
|
@ -50,9 +50,8 @@ class SyncToAvalon(BaseAction):
|
|||
#: Action description.
|
||||
description = 'Send data from Ftrack to Avalon'
|
||||
#: Action icon.
|
||||
icon = (
|
||||
'https://cdn1.iconfinder.com/data/icons/hawcons/32/'
|
||||
'699650-icon-92-inbox-download-512.png'
|
||||
icon = '{}/ftrack/action_icons/SyncToAvalon-local.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub']
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import collections
|
||||
import os
|
||||
import json
|
||||
import re
|
||||
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
from avalon import io, inventory, schema
|
||||
|
||||
|
|
@ -27,9 +27,8 @@ class TestAction(BaseAction):
|
|||
priority = 10000
|
||||
#: roles that are allowed to register this action
|
||||
role_list = ['Pypeclub']
|
||||
icon = (
|
||||
'https://cdn4.iconfinder.com/data/icons/hospital-19/512/'
|
||||
'8_hospital-512.png'
|
||||
icon = '{}/ftrack/action_icons/TestAction.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import json
|
||||
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
||||
|
|
@ -15,9 +16,8 @@ class ThumbToChildren(BaseAction):
|
|||
# Action label
|
||||
label = 'Thumbnail to Children'
|
||||
# Action icon
|
||||
icon = (
|
||||
'https://cdn3.iconfinder.com/data/icons/transfers/100/'
|
||||
'239322-download_transfer-128.png'
|
||||
icon = '{}/ftrack/action_icons/thumbToChildren.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import json
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction
|
||||
|
||||
|
||||
|
|
@ -14,9 +15,8 @@ class ThumbToParent(BaseAction):
|
|||
# Action label
|
||||
label = 'Thumbnail to Parent'
|
||||
# Action icon
|
||||
icon = (
|
||||
"https://cdn3.iconfinder.com/data/icons/transfers/100/"
|
||||
"239419-upload_transfer-512.png"
|
||||
icon = '{}/ftrack/action_icons/thumbToParent.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
def discover(self, session, entities, event):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import os
|
||||
import json
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
import appdirs
|
||||
|
||||
|
||||
|
|
@ -77,7 +77,6 @@ def _check_credentials(username=None, apiKey=None):
|
|||
session = ftrack_api.Session()
|
||||
session.close()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import os
|
|||
import sys
|
||||
import argparse
|
||||
import logging
|
||||
import ftrack_api
|
||||
import json
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseAction, lib
|
||||
|
||||
|
||||
|
|
@ -49,9 +49,8 @@ class Sync_To_Avalon(BaseAction):
|
|||
#: Action description.
|
||||
description = 'Send data from Ftrack to Avalon'
|
||||
#: Action icon.
|
||||
icon = (
|
||||
'https://cdn1.iconfinder.com/data/icons/hawcons/32/'
|
||||
'699650-icon-92-inbox-download-512.png'
|
||||
icon = '{}/ftrack/action_icons/SyncToAvalon.svg'.format(
|
||||
os.environ.get('PYPE_STATICS_SERVER', '')
|
||||
)
|
||||
|
||||
def register(self):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseEvent, get_ca_mongoid
|
||||
from pype.ftrack.events.event_sync_to_avalon import Sync_to_Avalon
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseEvent
|
||||
import operator
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseEvent
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseEvent, lib
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import os
|
||||
import sys
|
||||
import re
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseEvent
|
||||
from app import api
|
||||
|
||||
|
||||
ignore_me = True
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseEvent
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.ftrack import BaseEvent
|
||||
|
||||
|
||||
|
|
|
|||
329
pype/ftrack/ftrack_module.py
Normal file
329
pype/ftrack/ftrack_module.py
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
import os
|
||||
import json
|
||||
import threading
|
||||
import time
|
||||
from Qt import QtCore, QtGui, QtWidgets
|
||||
|
||||
from pype.vendor import ftrack_api
|
||||
from pypeapp import style
|
||||
from pype.ftrack import FtrackServer, credentials, login_dialog as login_dialog
|
||||
|
||||
from pype import api as pype
|
||||
|
||||
|
||||
log = pype.Logger().get_logger("FtrackModule", "ftrack")
|
||||
|
||||
|
||||
class FtrackModule:
|
||||
def __init__(self, main_parent=None, parent=None):
|
||||
|
||||
self.parent = parent
|
||||
self.widget_login = login_dialog.Login_Dialog_ui(self)
|
||||
self.action_server = FtrackServer('action')
|
||||
self.thread_action_server = None
|
||||
self.thread_timer = None
|
||||
|
||||
self.bool_logged = False
|
||||
self.bool_action_server = False
|
||||
self.bool_timer_event = False
|
||||
|
||||
def show_login_widget(self):
|
||||
self.widget_login.show()
|
||||
|
||||
def validate(self):
|
||||
validation = False
|
||||
cred = credentials._get_credentials()
|
||||
try:
|
||||
if 'username' in cred and 'apiKey' in cred:
|
||||
validation = credentials._check_credentials(
|
||||
cred['username'],
|
||||
cred['apiKey']
|
||||
)
|
||||
if validation is False:
|
||||
self.show_login_widget()
|
||||
else:
|
||||
self.show_login_widget()
|
||||
|
||||
except Exception as e:
|
||||
log.error("We are unable to connect to Ftrack: {0}".format(e))
|
||||
|
||||
validation = credentials._check_credentials()
|
||||
if validation is True:
|
||||
log.info("Connected to Ftrack successfully")
|
||||
self.loginChange()
|
||||
else:
|
||||
log.warning("Please sign in to Ftrack")
|
||||
self.bool_logged = False
|
||||
self.set_menu_visibility()
|
||||
|
||||
return validation
|
||||
|
||||
# Necessary - login_dialog works with this method after logging in
|
||||
def loginChange(self):
|
||||
self.bool_logged = True
|
||||
self.set_menu_visibility()
|
||||
self.start_action_server()
|
||||
|
||||
def logout(self):
|
||||
credentials._clear_credentials()
|
||||
self.stop_action_server()
|
||||
|
||||
log.info("Logged out of Ftrack")
|
||||
self.bool_logged = False
|
||||
self.set_menu_visibility()
|
||||
|
||||
# Actions part
|
||||
def start_action_server(self):
|
||||
if self.thread_action_server is None:
|
||||
self.thread_action_server = threading.Thread(
|
||||
target=self.set_action_server
|
||||
)
|
||||
self.thread_action_server.daemon = True
|
||||
self.thread_action_server.start()
|
||||
|
||||
log.info("Ftrack action server launched")
|
||||
self.bool_action_server = True
|
||||
self.set_menu_visibility()
|
||||
|
||||
def set_action_server(self):
|
||||
try:
|
||||
self.action_server.run_server()
|
||||
except Exception:
|
||||
msg = 'Ftrack Action server crashed! Please try to start again.'
|
||||
log.error(msg)
|
||||
# TODO show message to user
|
||||
self.bool_action_server = False
|
||||
self.set_menu_visibility()
|
||||
|
||||
def reset_action_server(self):
|
||||
self.stop_action_server()
|
||||
self.start_action_server()
|
||||
|
||||
def stop_action_server(self):
|
||||
try:
|
||||
self.action_server.stop_session()
|
||||
if self.thread_action_server is not None:
|
||||
self.thread_action_server.join()
|
||||
self.thread_action_server = None
|
||||
|
||||
log.info("Ftrack action server stopped")
|
||||
self.bool_action_server = False
|
||||
self.set_menu_visibility()
|
||||
except Exception as e:
|
||||
log.error("During Killing action server: {0}".format(e))
|
||||
|
||||
# Definition of Tray menu
|
||||
def tray_menu(self, parent_menu):
|
||||
# Menu for Tray App
|
||||
self.menu = QtWidgets.QMenu('Ftrack', parent_menu)
|
||||
self.menu.setProperty('submenu', 'on')
|
||||
|
||||
# Actions - server
|
||||
self.smActionS = self.menu.addMenu("Action server")
|
||||
|
||||
self.aRunActionS = QtWidgets.QAction(
|
||||
"Run action server", self.smActionS
|
||||
)
|
||||
self.aResetActionS = QtWidgets.QAction(
|
||||
"Reset action server", self.smActionS
|
||||
)
|
||||
self.aStopActionS = QtWidgets.QAction(
|
||||
"Stop action server", self.smActionS
|
||||
)
|
||||
|
||||
self.aRunActionS.triggered.connect(self.start_action_server)
|
||||
self.aResetActionS.triggered.connect(self.reset_action_server)
|
||||
self.aStopActionS.triggered.connect(self.stop_action_server)
|
||||
|
||||
self.smActionS.addAction(self.aRunActionS)
|
||||
self.smActionS.addAction(self.aResetActionS)
|
||||
self.smActionS.addAction(self.aStopActionS)
|
||||
|
||||
# Actions - basic
|
||||
self.aLogin = QtWidgets.QAction("Login", self.menu)
|
||||
self.aLogin.triggered.connect(self.validate)
|
||||
self.aLogout = QtWidgets.QAction("Logout", self.menu)
|
||||
self.aLogout.triggered.connect(self.logout)
|
||||
|
||||
self.menu.addAction(self.aLogin)
|
||||
self.menu.addAction(self.aLogout)
|
||||
|
||||
self.bool_logged = False
|
||||
self.set_menu_visibility()
|
||||
|
||||
parent_menu.addMenu(self.menu)
|
||||
|
||||
def tray_start(self):
|
||||
self.validate()
|
||||
|
||||
# Definition of visibility of each menu actions
|
||||
def set_menu_visibility(self):
|
||||
|
||||
self.smActionS.menuAction().setVisible(self.bool_logged)
|
||||
self.aLogin.setVisible(not self.bool_logged)
|
||||
self.aLogout.setVisible(self.bool_logged)
|
||||
|
||||
if self.bool_logged is False:
|
||||
if self.bool_timer_event is True:
|
||||
self.stop_timer_thread()
|
||||
return
|
||||
|
||||
self.aRunActionS.setVisible(not self.bool_action_server)
|
||||
self.aResetActionS.setVisible(self.bool_action_server)
|
||||
self.aStopActionS.setVisible(self.bool_action_server)
|
||||
|
||||
if self.bool_timer_event is False:
|
||||
self.start_timer_thread()
|
||||
|
||||
def start_timer_thread(self):
|
||||
try:
|
||||
if self.thread_timer is None:
|
||||
self.thread_timer = FtrackEventsThread(self)
|
||||
self.bool_timer_event = True
|
||||
self.thread_timer.signal_timer_started.connect(
|
||||
self.timer_started
|
||||
)
|
||||
self.thread_timer.signal_timer_stopped.connect(
|
||||
self.timer_stopped
|
||||
)
|
||||
self.thread_timer.start()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def stop_timer_thread(self):
|
||||
try:
|
||||
if self.thread_timer is not None:
|
||||
self.thread_timer.terminate()
|
||||
self.thread_timer.wait()
|
||||
self.thread_timer = None
|
||||
|
||||
except Exception as e:
|
||||
log.error("During Killing Timer event server: {0}".format(e))
|
||||
|
||||
def process_modules(self, modules):
|
||||
if 'TimersManager' in modules:
|
||||
self.timer_manager = modules['TimersManager']
|
||||
self.timer_manager.add_module(self)
|
||||
|
||||
def start_timer_manager(self, data):
|
||||
if self.thread_timer is not None:
|
||||
self.thread_timer.ftrack_start_timer(data)
|
||||
|
||||
def stop_timer_manager(self):
|
||||
if self.thread_timer is not None:
|
||||
self.thread_timer.ftrack_stop_timer()
|
||||
|
||||
def timer_started(self, data):
|
||||
if hasattr(self, 'timer_manager'):
|
||||
self.timer_manager.start_timers(data)
|
||||
|
||||
def timer_stopped(self):
|
||||
if hasattr(self, 'timer_manager'):
|
||||
self.timer_manager.stop_timers()
|
||||
|
||||
|
||||
class FtrackEventsThread(QtCore.QThread):
|
||||
# Senders
|
||||
signal_timer_started = QtCore.Signal(object)
|
||||
signal_timer_stopped = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(FtrackEventsThread, self).__init__()
|
||||
cred = credentials._get_credentials()
|
||||
self.username = cred['username']
|
||||
self.user = None
|
||||
self.last_task = None
|
||||
|
||||
def run(self):
|
||||
self.timer_session = ftrack_api.Session(auto_connect_event_hub=True)
|
||||
self.timer_session.event_hub.subscribe(
|
||||
'topic=ftrack.update and source.user.username={}'.format(
|
||||
self.username
|
||||
),
|
||||
self.event_handler)
|
||||
|
||||
user_query = 'User where username is "{}"'.format(self.username)
|
||||
self.user = self.timer_session.query(user_query).one()
|
||||
|
||||
timer_query = 'Timer where user.username is "{}"'.format(self.username)
|
||||
timer = self.timer_session.query(timer_query).first()
|
||||
if timer is not None:
|
||||
self.last_task = timer['context']
|
||||
self.signal_timer_started.emit(
|
||||
self.get_data_from_task(self.last_task)
|
||||
)
|
||||
|
||||
self.timer_session.event_hub.wait()
|
||||
|
||||
def get_data_from_task(self, task_entity):
|
||||
data = {}
|
||||
data['task_name'] = task_entity['name']
|
||||
data['task_type'] = task_entity['type']['name']
|
||||
data['project_name'] = task_entity['project']['full_name']
|
||||
data['hierarchy'] = self.get_parents(task_entity['parent'])
|
||||
|
||||
return data
|
||||
|
||||
def get_parents(self, entity):
|
||||
output = []
|
||||
if entity.entity_type.lower() == 'project':
|
||||
return output
|
||||
output.extend(self.get_parents(entity['parent']))
|
||||
output.append(entity['name'])
|
||||
|
||||
return output
|
||||
|
||||
def event_handler(self, event):
|
||||
try:
|
||||
if event['data']['entities'][0]['objectTypeId'] != 'timer':
|
||||
return
|
||||
except Exception:
|
||||
return
|
||||
|
||||
new = event['data']['entities'][0]['changes']['start']['new']
|
||||
old = event['data']['entities'][0]['changes']['start']['old']
|
||||
|
||||
if old is None and new is None:
|
||||
return
|
||||
|
||||
timer_query = 'Timer where user.username is "{}"'.format(self.username)
|
||||
timer = self.timer_session.query(timer_query).first()
|
||||
if timer is not None:
|
||||
self.last_task = timer['context']
|
||||
|
||||
if old is None:
|
||||
self.signal_timer_started.emit(
|
||||
self.get_data_from_task(self.last_task)
|
||||
)
|
||||
elif new is None:
|
||||
self.signal_timer_stopped.emit()
|
||||
|
||||
def ftrack_stop_timer(self):
|
||||
try:
|
||||
self.user.stop_timer()
|
||||
self.timer_session.commit()
|
||||
self.signal_timer_stopped.emit()
|
||||
except Exception as e:
|
||||
log.debug("Timer stop had issues: {}".format(e))
|
||||
|
||||
def ftrack_start_timer(self, input_data):
|
||||
if self.user is None:
|
||||
return
|
||||
if (
|
||||
input_data['task_name'] == self.last_task['name'] and
|
||||
input_data['hierarchy'][-1] == self.last_task['parent']['name']
|
||||
):
|
||||
return
|
||||
task_query = (
|
||||
'Task where name is "{task_name}"'
|
||||
' and parent.name is "{entity_name}"'
|
||||
' and project.full_name is "{project_name}"'
|
||||
).format(**input_data)
|
||||
|
||||
task = self.timer_session.query(task_query).one()
|
||||
self.last_task = task
|
||||
self.user.start_timer(task)
|
||||
self.timer_session.commit()
|
||||
self.signal_timer_started.emit(
|
||||
self.get_data_from_task(self.last_task)
|
||||
)
|
||||
|
|
@ -1,624 +0,0 @@
|
|||
import os
|
||||
import json
|
||||
import threading
|
||||
import time
|
||||
import ftrack_api
|
||||
from app import style
|
||||
from app.vendor.Qt import QtCore, QtGui, QtWidgets
|
||||
|
||||
from pype.ftrack import credentials, login_dialog as login_dialog
|
||||
|
||||
from pype.vendor.pynput import mouse, keyboard
|
||||
from . import FtrackServer
|
||||
|
||||
from pype import api as pype
|
||||
|
||||
|
||||
# load data from templates
|
||||
pype.load_data_from_templates()
|
||||
|
||||
log = pype.Logger.getLogger(__name__, "ftrack")
|
||||
|
||||
|
||||
class FtrackRunner:
|
||||
def __init__(self, main_parent=None, parent=None):
|
||||
|
||||
self.parent = parent
|
||||
self.widget_login = login_dialog.Login_Dialog_ui(self)
|
||||
self.widget_timer = StopTimer(self)
|
||||
self.action_server = FtrackServer('action')
|
||||
self.thread_action_server = None
|
||||
self.thread_timer = None
|
||||
self.thread_timer_coundown = None
|
||||
|
||||
# self.signal_start_timer.connect(self.timerStart)
|
||||
|
||||
self.bool_logged = False
|
||||
self.bool_action_server = False
|
||||
self.bool_timer_event = False
|
||||
|
||||
def show_login_widget(self):
|
||||
self.widget_login.show()
|
||||
|
||||
def validate(self):
|
||||
validation = False
|
||||
cred = credentials._get_credentials()
|
||||
try:
|
||||
if 'username' in cred and 'apiKey' in cred:
|
||||
validation = credentials._check_credentials(
|
||||
cred['username'],
|
||||
cred['apiKey']
|
||||
)
|
||||
if validation is False:
|
||||
self.show_login_widget()
|
||||
else:
|
||||
self.show_login_widget()
|
||||
|
||||
except Exception as e:
|
||||
log.error("We are unable to connect to Ftrack: {0}".format(e))
|
||||
|
||||
validation = credentials._check_credentials()
|
||||
if validation is True:
|
||||
log.info("Connected to Ftrack successfully")
|
||||
self.loginChange()
|
||||
else:
|
||||
log.warning("Please sign in to Ftrack")
|
||||
self.bool_logged = False
|
||||
self.set_menu_visibility()
|
||||
|
||||
return validation
|
||||
|
||||
# Necessary - login_dialog works with this method after logging in
|
||||
def loginChange(self):
|
||||
self.bool_logged = True
|
||||
self.set_menu_visibility()
|
||||
self.start_action_server()
|
||||
|
||||
def logout(self):
|
||||
credentials._clear_credentials()
|
||||
self.stop_action_server()
|
||||
|
||||
log.info("Logged out of Ftrack")
|
||||
self.bool_logged = False
|
||||
self.set_menu_visibility()
|
||||
|
||||
# Actions part
|
||||
def start_action_server(self):
|
||||
if self.thread_action_server is None:
|
||||
self.thread_action_server = threading.Thread(
|
||||
target=self.set_action_server
|
||||
)
|
||||
self.thread_action_server.daemon = True
|
||||
self.thread_action_server.start()
|
||||
|
||||
log.info("Ftrack action server launched")
|
||||
self.bool_action_server = True
|
||||
self.set_menu_visibility()
|
||||
|
||||
def set_action_server(self):
|
||||
try:
|
||||
self.action_server.run_server()
|
||||
except Exception:
|
||||
msg = 'Ftrack Action server crashed! Please try to start again.'
|
||||
log.error(msg)
|
||||
# TODO show message to user
|
||||
self.bool_action_server = False
|
||||
self.set_menu_visibility()
|
||||
|
||||
def reset_action_server(self):
|
||||
self.stop_action_server()
|
||||
self.start_action_server()
|
||||
|
||||
def stop_action_server(self):
|
||||
try:
|
||||
self.action_server.stop_session()
|
||||
if self.thread_action_server is not None:
|
||||
self.thread_action_server.join()
|
||||
self.thread_action_server = None
|
||||
|
||||
log.info("Ftrack action server stopped")
|
||||
self.bool_action_server = False
|
||||
self.set_menu_visibility()
|
||||
except Exception as e:
|
||||
log.error("During Killing action server: {0}".format(e))
|
||||
|
||||
# Definition of Tray menu
|
||||
def trayMenu(self, parent):
|
||||
# Menu for Tray App
|
||||
self.menu = QtWidgets.QMenu('Ftrack', parent)
|
||||
self.menu.setProperty('submenu', 'on')
|
||||
self.menu.setStyleSheet(style.load_stylesheet())
|
||||
|
||||
# Actions - server
|
||||
self.smActionS = self.menu.addMenu("Action server")
|
||||
|
||||
self.aRunActionS = QtWidgets.QAction(
|
||||
"Run action server", self.smActionS
|
||||
)
|
||||
self.aResetActionS = QtWidgets.QAction(
|
||||
"Reset action server", self.smActionS
|
||||
)
|
||||
self.aStopActionS = QtWidgets.QAction(
|
||||
"Stop action server", self.smActionS
|
||||
)
|
||||
|
||||
self.aRunActionS.triggered.connect(self.start_action_server)
|
||||
self.aResetActionS.triggered.connect(self.reset_action_server)
|
||||
self.aStopActionS.triggered.connect(self.stop_action_server)
|
||||
|
||||
self.smActionS.addAction(self.aRunActionS)
|
||||
self.smActionS.addAction(self.aResetActionS)
|
||||
self.smActionS.addAction(self.aStopActionS)
|
||||
|
||||
# Actions - basic
|
||||
self.aLogin = QtWidgets.QAction("Login", self.menu)
|
||||
self.aLogin.triggered.connect(self.validate)
|
||||
self.aLogout = QtWidgets.QAction("Logout", self.menu)
|
||||
self.aLogout.triggered.connect(self.logout)
|
||||
|
||||
self.menu.addAction(self.aLogin)
|
||||
self.menu.addAction(self.aLogout)
|
||||
|
||||
self.bool_logged = False
|
||||
self.set_menu_visibility()
|
||||
|
||||
return self.menu
|
||||
|
||||
# Definition of visibility of each menu actions
|
||||
def set_menu_visibility(self):
|
||||
|
||||
self.smActionS.menuAction().setVisible(self.bool_logged)
|
||||
self.aLogin.setVisible(not self.bool_logged)
|
||||
self.aLogout.setVisible(self.bool_logged)
|
||||
|
||||
if self.bool_logged is False:
|
||||
if self.bool_timer_event is True:
|
||||
self.stop_timer_thread()
|
||||
return
|
||||
|
||||
self.aRunActionS.setVisible(not self.bool_action_server)
|
||||
self.aResetActionS.setVisible(self.bool_action_server)
|
||||
self.aStopActionS.setVisible(self.bool_action_server)
|
||||
|
||||
if self.bool_timer_event is False:
|
||||
self.start_timer_thread()
|
||||
|
||||
def start_timer_thread(self):
|
||||
try:
|
||||
if self.thread_timer is None:
|
||||
self.thread_timer = FtrackEventsThread(self)
|
||||
self.bool_timer_event = True
|
||||
self.thread_timer.signal_timer_started.connect(
|
||||
self.timer_started
|
||||
)
|
||||
self.thread_timer.signal_timer_stopped.connect(
|
||||
self.timer_stopped
|
||||
)
|
||||
self.thread_timer.start()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def stop_timer_thread(self):
|
||||
try:
|
||||
if self.thread_timer is not None:
|
||||
self.thread_timer.terminate()
|
||||
self.thread_timer.wait()
|
||||
self.thread_timer = None
|
||||
|
||||
except Exception as e:
|
||||
log.error("During Killing Timer event server: {0}".format(e))
|
||||
|
||||
def start_countdown_thread(self):
|
||||
if self.thread_timer_coundown is None:
|
||||
self.thread_timer_coundown = CountdownThread(self)
|
||||
self.thread_timer_coundown.signal_show_question.connect(
|
||||
self.show_widget_timer
|
||||
)
|
||||
self.thread_timer_coundown.signal_send_time.connect(
|
||||
self.change_count_widget
|
||||
)
|
||||
self.thread_timer_coundown.signal_stop_timer.connect(
|
||||
self.timer_stop
|
||||
)
|
||||
self.thread_timer_coundown.start()
|
||||
|
||||
def stop_countdown_thread(self):
|
||||
if self.thread_timer_coundown is not None:
|
||||
self.thread_timer_coundown.runs = False
|
||||
self.thread_timer_coundown.terminate()
|
||||
self.thread_timer_coundown.wait()
|
||||
self.thread_timer_coundown = None
|
||||
|
||||
def show_widget_timer(self):
|
||||
self.widget_timer.show()
|
||||
self.widget_timer.setWindowState(QtCore.Qt.WindowMinimized)
|
||||
self.widget_timer.setWindowState(QtCore.Qt.WindowActive)
|
||||
# self.widget_timer.activateWindow()
|
||||
|
||||
def change_count_widget(self, time):
|
||||
str_time = str(time).replace(".0", "")
|
||||
self.widget_timer.lbl_rest_time.setText(str_time)
|
||||
|
||||
def timer_started(self):
|
||||
self.start_countdown_thread()
|
||||
|
||||
def timer_stopped(self):
|
||||
self.stop_countdown_thread()
|
||||
|
||||
def timer_stop(self):
|
||||
if self.thread_timer is not None:
|
||||
self.widget_timer.main_context = False
|
||||
self.widget_timer.refresh_context()
|
||||
self.thread_timer.signal_stop_timer.emit()
|
||||
if self.thread_timer_coundown is not None:
|
||||
self.stop_countdown_thread()
|
||||
|
||||
def timer_restart(self):
|
||||
if self.thread_timer is not None:
|
||||
self.thread_timer.signal_restart_timer.emit()
|
||||
|
||||
self.timer_started()
|
||||
|
||||
def timer_continue(self):
|
||||
if self.thread_timer_coundown is not None:
|
||||
self.thread_timer_coundown.signal_continue_timer.emit()
|
||||
|
||||
|
||||
class FtrackEventsThread(QtCore.QThread):
|
||||
# Senders
|
||||
signal_timer_started = QtCore.Signal()
|
||||
signal_timer_stopped = QtCore.Signal()
|
||||
# Listeners
|
||||
signal_stop_timer = QtCore.Signal()
|
||||
signal_restart_timer = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(FtrackEventsThread, self).__init__()
|
||||
cred = credentials._get_credentials()
|
||||
self.username = cred['username']
|
||||
self.signal_stop_timer.connect(self.ftrack_stop_timer)
|
||||
self.signal_restart_timer.connect(self.ftrack_restart_timer)
|
||||
self.user = None
|
||||
self.last_task = None
|
||||
|
||||
def run(self):
|
||||
self.timer_session = ftrack_api.Session(auto_connect_event_hub=True)
|
||||
self.timer_session.event_hub.subscribe(
|
||||
'topic=ftrack.update and source.user.username={}'.format(
|
||||
self.username
|
||||
),
|
||||
self.event_handler)
|
||||
|
||||
user_query = 'User where username is "{}"'.format(self.username)
|
||||
self.user = self.timer_session.query(user_query).one()
|
||||
|
||||
timer_query = 'Timer where user.username is "{}"'.format(self.username)
|
||||
timer = self.timer_session.query(timer_query).first()
|
||||
if timer is not None:
|
||||
self.last_task = timer['context']
|
||||
self.signal_timer_started.emit()
|
||||
|
||||
self.timer_session.event_hub.wait()
|
||||
|
||||
def event_handler(self, event):
|
||||
try:
|
||||
if event['data']['entities'][0]['objectTypeId'] != 'timer':
|
||||
return
|
||||
except Exception:
|
||||
return
|
||||
|
||||
new = event['data']['entities'][0]['changes']['start']['new']
|
||||
old = event['data']['entities'][0]['changes']['start']['old']
|
||||
|
||||
if old is None and new is None:
|
||||
return
|
||||
|
||||
timer_query = 'Timer where user.username is "{}"'.format(self.username)
|
||||
timer = self.timer_session.query(timer_query).first()
|
||||
if timer is not None:
|
||||
self.last_task = timer['context']
|
||||
|
||||
if old is None:
|
||||
self.signal_timer_started.emit()
|
||||
elif new is None:
|
||||
self.signal_timer_stopped.emit()
|
||||
|
||||
def ftrack_stop_timer(self):
|
||||
try:
|
||||
self.user.stop_timer()
|
||||
self.timer_session.commit()
|
||||
except Exception as e:
|
||||
log.debug("Timer stop had issues: {}".format(e))
|
||||
|
||||
def ftrack_restart_timer(self):
|
||||
try:
|
||||
if (self.last_task is not None) and (self.user is not None):
|
||||
self.user.start_timer(self.last_task)
|
||||
self.timer_session.commit()
|
||||
except Exception as e:
|
||||
log.debug("Timer stop had issues: {}".format(e))
|
||||
|
||||
|
||||
class CountdownThread(QtCore.QThread):
|
||||
# Senders
|
||||
signal_show_question = QtCore.Signal()
|
||||
signal_send_time = QtCore.Signal(object)
|
||||
signal_stop_timer = QtCore.Signal()
|
||||
signal_stop_countdown = QtCore.Signal()
|
||||
# Listeners
|
||||
signal_reset_timer = QtCore.Signal()
|
||||
signal_continue_timer = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(CountdownThread, self).__init__()
|
||||
|
||||
self.runs = True
|
||||
self.over_line = False
|
||||
config_data = self.load_timer_values()
|
||||
self.count_length = config_data['full_time']*60
|
||||
self.border_line = config_data['message_time']*60 + 1
|
||||
self.reset_count()
|
||||
self.signal_reset_timer.connect(self.reset_count)
|
||||
self.signal_continue_timer.connect(self.continue_timer)
|
||||
|
||||
def continue_timer(self):
|
||||
self.over_line = False
|
||||
self.reset_count()
|
||||
|
||||
def reset_count(self):
|
||||
if self.over_line is True:
|
||||
self.actual = self.border_line
|
||||
else:
|
||||
self.actual = self.count_length
|
||||
|
||||
def stop(self):
|
||||
self.runs = False
|
||||
|
||||
def run(self):
|
||||
thread_mouse = MouseThread(self)
|
||||
thread_mouse.start()
|
||||
thread_keyboard = KeyboardThread(self)
|
||||
thread_keyboard.start()
|
||||
while self.runs:
|
||||
if self.actual == self.border_line:
|
||||
self.signal_show_question.emit()
|
||||
self.over_line = True
|
||||
|
||||
if self.actual <= self.border_line:
|
||||
self.signal_send_time.emit(self.actual)
|
||||
|
||||
time.sleep(1)
|
||||
self.actual -= 1
|
||||
|
||||
if self.actual == 0:
|
||||
self.runs = False
|
||||
self.signal_stop_timer.emit()
|
||||
|
||||
thread_mouse.signal_stop.emit()
|
||||
thread_mouse.terminate()
|
||||
thread_mouse.wait()
|
||||
thread_keyboard.signal_stop.emit()
|
||||
thread_keyboard.terminate()
|
||||
thread_keyboard.wait()
|
||||
|
||||
def load_timer_values(self):
|
||||
templates = os.environ['PYPE_STUDIO_TEMPLATES']
|
||||
path_items = [templates, 'presets', 'ftrack', 'ftrack_config.json']
|
||||
filepath = os.path.sep.join(path_items)
|
||||
data = dict()
|
||||
try:
|
||||
with open(filepath) as data_file:
|
||||
json_dict = json.load(data_file)
|
||||
data = json_dict['timer']
|
||||
except Exception as e:
|
||||
msg = (
|
||||
'Loading "Ftrack Config file" Failed.'
|
||||
' Please check log for more information.'
|
||||
' Times are set to default.'
|
||||
)
|
||||
log.warning("{} - {}".format(msg, str(e)))
|
||||
|
||||
data = self.validate_timer_values(data)
|
||||
|
||||
return data
|
||||
|
||||
def validate_timer_values(self, data):
|
||||
# default values
|
||||
if 'full_time' not in data:
|
||||
data['full_time'] = 15
|
||||
if 'message_time' not in data:
|
||||
data['message_time'] = 0.5
|
||||
|
||||
# minimum values
|
||||
if data['full_time'] < 2:
|
||||
data['full_time'] = 2
|
||||
# message time is earlier that full time
|
||||
if data['message_time'] > data['full_time']:
|
||||
data['message_time'] = data['full_time'] - 0.5
|
||||
return data
|
||||
|
||||
|
||||
class MouseThread(QtCore.QThread):
|
||||
signal_stop = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(MouseThread, self).__init__()
|
||||
self.parent = parent
|
||||
self.signal_stop.connect(self.stop)
|
||||
self.m_listener = None
|
||||
|
||||
def stop(self):
|
||||
if self.m_listener is not None:
|
||||
self.m_listener.stop()
|
||||
|
||||
def on_move(self, posx, posy):
|
||||
self.parent.signal_reset_timer.emit()
|
||||
|
||||
def run(self):
|
||||
self.m_listener = mouse.Listener(on_move=self.on_move)
|
||||
self.m_listener.start()
|
||||
|
||||
|
||||
class KeyboardThread(QtCore.QThread):
|
||||
signal_stop = QtCore.Signal()
|
||||
|
||||
def __init__(self, parent):
|
||||
super(KeyboardThread, self).__init__()
|
||||
self.parent = parent
|
||||
self.signal_stop.connect(self.stop)
|
||||
self.k_listener = None
|
||||
|
||||
def stop(self):
|
||||
if self.k_listener is not None:
|
||||
self.k_listener.stop()
|
||||
|
||||
def on_press(self, key):
|
||||
self.parent.signal_reset_timer.emit()
|
||||
|
||||
def run(self):
|
||||
self.k_listener = keyboard.Listener(on_press=self.on_press)
|
||||
self.k_listener.start()
|
||||
|
||||
|
||||
class StopTimer(QtWidgets.QWidget):
|
||||
|
||||
SIZE_W = 300
|
||||
SIZE_H = 160
|
||||
|
||||
def __init__(self, parent=None):
|
||||
|
||||
super(StopTimer, self).__init__()
|
||||
|
||||
self.main_context = True
|
||||
self.parent = parent
|
||||
self.setWindowIcon(self.parent.parent.icon)
|
||||
self.setWindowFlags(
|
||||
QtCore.Qt.WindowCloseButtonHint |
|
||||
QtCore.Qt.WindowMinimizeButtonHint
|
||||
)
|
||||
|
||||
self._translate = QtCore.QCoreApplication.translate
|
||||
|
||||
self.font = QtGui.QFont()
|
||||
self.font.setFamily("DejaVu Sans Condensed")
|
||||
self.font.setPointSize(9)
|
||||
self.font.setBold(True)
|
||||
self.font.setWeight(50)
|
||||
self.font.setKerning(True)
|
||||
|
||||
self.resize(self.SIZE_W, self.SIZE_H)
|
||||
self.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H))
|
||||
self.setMaximumSize(QtCore.QSize(self.SIZE_W+100, self.SIZE_H+100))
|
||||
self.setStyleSheet(style.load_stylesheet())
|
||||
|
||||
self.setLayout(self._main())
|
||||
self.refresh_context()
|
||||
self.setWindowTitle('Pype - Stop Ftrack timer')
|
||||
|
||||
def _main(self):
|
||||
self.main = QtWidgets.QVBoxLayout()
|
||||
self.main.setObjectName('main')
|
||||
|
||||
self.form = QtWidgets.QFormLayout()
|
||||
self.form.setContentsMargins(10, 15, 10, 5)
|
||||
self.form.setObjectName('form')
|
||||
|
||||
msg_info = 'You didn\'t work for a long time.'
|
||||
msg_question = 'Would you like to stop Ftrack timer?'
|
||||
msg_stopped = (
|
||||
'Your Ftrack timer was stopped. Do you want to start again?'
|
||||
)
|
||||
|
||||
self.lbl_info = QtWidgets.QLabel(msg_info)
|
||||
self.lbl_info.setFont(self.font)
|
||||
self.lbl_info.setTextFormat(QtCore.Qt.RichText)
|
||||
self.lbl_info.setObjectName("lbl_info")
|
||||
self.lbl_info.setWordWrap(True)
|
||||
|
||||
self.lbl_question = QtWidgets.QLabel(msg_question)
|
||||
self.lbl_question.setFont(self.font)
|
||||
self.lbl_question.setTextFormat(QtCore.Qt.RichText)
|
||||
self.lbl_question.setObjectName("lbl_question")
|
||||
self.lbl_question.setWordWrap(True)
|
||||
|
||||
self.lbl_stopped = QtWidgets.QLabel(msg_stopped)
|
||||
self.lbl_stopped.setFont(self.font)
|
||||
self.lbl_stopped.setTextFormat(QtCore.Qt.RichText)
|
||||
self.lbl_stopped.setObjectName("lbl_stopped")
|
||||
self.lbl_stopped.setWordWrap(True)
|
||||
|
||||
self.lbl_rest_time = QtWidgets.QLabel("")
|
||||
self.lbl_rest_time.setFont(self.font)
|
||||
self.lbl_rest_time.setTextFormat(QtCore.Qt.RichText)
|
||||
self.lbl_rest_time.setObjectName("lbl_rest_time")
|
||||
self.lbl_rest_time.setWordWrap(True)
|
||||
self.lbl_rest_time.setAlignment(QtCore.Qt.AlignCenter)
|
||||
|
||||
self.form.addRow(self.lbl_info)
|
||||
self.form.addRow(self.lbl_question)
|
||||
self.form.addRow(self.lbl_stopped)
|
||||
self.form.addRow(self.lbl_rest_time)
|
||||
|
||||
self.group_btn = QtWidgets.QHBoxLayout()
|
||||
self.group_btn.addStretch(1)
|
||||
self.group_btn.setObjectName("group_btn")
|
||||
|
||||
self.btn_stop = QtWidgets.QPushButton("Stop timer")
|
||||
self.btn_stop.setToolTip('Stop\'s Ftrack timer')
|
||||
self.btn_stop.clicked.connect(self.stop_timer)
|
||||
|
||||
self.btn_continue = QtWidgets.QPushButton("Continue")
|
||||
self.btn_continue.setToolTip('Timer will continue')
|
||||
self.btn_continue.clicked.connect(self.continue_timer)
|
||||
|
||||
self.btn_close = QtWidgets.QPushButton("Close")
|
||||
self.btn_close.setToolTip('Close window')
|
||||
self.btn_close.clicked.connect(self.close_widget)
|
||||
|
||||
self.btn_restart = QtWidgets.QPushButton("Start timer")
|
||||
self.btn_restart.setToolTip('Timer will be started again')
|
||||
self.btn_restart.clicked.connect(self.restart_timer)
|
||||
|
||||
self.group_btn.addWidget(self.btn_continue)
|
||||
self.group_btn.addWidget(self.btn_stop)
|
||||
self.group_btn.addWidget(self.btn_restart)
|
||||
self.group_btn.addWidget(self.btn_close)
|
||||
|
||||
self.main.addLayout(self.form)
|
||||
self.main.addLayout(self.group_btn)
|
||||
|
||||
return self.main
|
||||
|
||||
def refresh_context(self):
|
||||
self.lbl_question.setVisible(self.main_context)
|
||||
self.lbl_rest_time.setVisible(self.main_context)
|
||||
self.lbl_stopped.setVisible(not self.main_context)
|
||||
|
||||
self.btn_continue.setVisible(self.main_context)
|
||||
self.btn_stop.setVisible(self.main_context)
|
||||
self.btn_restart.setVisible(not self.main_context)
|
||||
self.btn_close.setVisible(not self.main_context)
|
||||
|
||||
def stop_timer(self):
|
||||
self.parent.timer_stop()
|
||||
self.close_widget()
|
||||
|
||||
def restart_timer(self):
|
||||
self.parent.timer_restart()
|
||||
self.close_widget()
|
||||
|
||||
def continue_timer(self):
|
||||
self.parent.timer_continue()
|
||||
self.close_widget()
|
||||
|
||||
def closeEvent(self, event):
|
||||
event.ignore()
|
||||
if self.main_context is True:
|
||||
self.continue_timer()
|
||||
else:
|
||||
self.close_widget()
|
||||
|
||||
def close_widget(self):
|
||||
self.main_context = True
|
||||
self.refresh_context()
|
||||
self.hide()
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import sys
|
||||
from pype.ftrack import credentials, login_dialog as login_dialog
|
||||
from pype.ftrack.ftrack_server import FtrackServer
|
||||
from app.vendor.Qt import QtWidgets
|
||||
from Qt import QtWidgets
|
||||
from pype import api
|
||||
|
||||
log = api.Logger.getLogger(__name__, "ftrack-event-server")
|
||||
log = api.Logger().get_logger(__name__, "ftrack-event-server")
|
||||
|
||||
|
||||
class EventServer:
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import sys
|
||||
from pype.ftrack import credentials
|
||||
from pype.ftrack.ftrack_server import FtrackServer
|
||||
from app import api
|
||||
from pypeapp import Logger
|
||||
|
||||
log = api.Logger.getLogger(__name__, "ftrack-event-server-cli")
|
||||
log = Logger().get_logger(__name__, "ftrack-event-server-cli")
|
||||
|
||||
possible_yes = ['y', 'yes']
|
||||
possible_no = ['n', 'no']
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ import os
|
|||
import sys
|
||||
import types
|
||||
import importlib
|
||||
import ftrack_api
|
||||
from pype.vendor import ftrack_api
|
||||
import time
|
||||
import logging
|
||||
from app.api import Logger
|
||||
from pypeapp import Logger
|
||||
|
||||
log = Logger.getLogger(__name__)
|
||||
log = Logger().get_logger(__name__)
|
||||
|
||||
"""
|
||||
# Required - Needed for connection to Ftrack
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import avalon
|
|||
import avalon.api
|
||||
from avalon import schema
|
||||
from avalon.vendor import toml, jsonschema
|
||||
from app.api import Logger
|
||||
from pypeapp import Logger
|
||||
|
||||
ValidationError = jsonschema.ValidationError
|
||||
|
||||
log = Logger.getLogger(__name__)
|
||||
log = Logger().get_logger(__name__)
|
||||
|
||||
|
||||
def get_ca_mongoid():
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ from pype import lib as pypelib
|
|||
from .avalon_sync import get_config_data
|
||||
from .ftrack_base_handler import BaseHandler
|
||||
|
||||
from pypeapp import Anatomy
|
||||
|
||||
|
||||
class AppAction(BaseHandler):
|
||||
'''Custom Action base class
|
||||
|
|
@ -177,7 +179,8 @@ class AppAction(BaseHandler):
|
|||
os.environ["AVALON_APP"] = self.identifier.split("_")[0]
|
||||
os.environ["AVALON_APP_NAME"] = self.identifier
|
||||
|
||||
anatomy = pype.Anatomy
|
||||
anatomy = Anatomy()
|
||||
|
||||
hierarchy = ""
|
||||
parents = database[project_name].find_one({
|
||||
"type": 'asset',
|
||||
|
|
@ -190,7 +193,7 @@ class AppAction(BaseHandler):
|
|||
application = avalonlib.get_application(os.environ["AVALON_APP_NAME"])
|
||||
|
||||
data = {
|
||||
"root": os.environ["AVALON_PROJECTS"],
|
||||
"root": os.environ.get("PYPE_STUDIO_PROJECTS_MOUNT"),
|
||||
"project": {
|
||||
"name": entity['project']['full_name'],
|
||||
"code": entity['project']['name']
|
||||
|
|
@ -213,12 +216,10 @@ class AppAction(BaseHandler):
|
|||
except Exception:
|
||||
try:
|
||||
anatomy = anatomy.format(data)
|
||||
work_template = os.path.join(
|
||||
anatomy.work.root,
|
||||
anatomy.work.folder
|
||||
)
|
||||
work_template = anatomy["work"]["folder"]
|
||||
|
||||
except Exception as e:
|
||||
self.log.error(
|
||||
self.log.exception(
|
||||
"{0} Error in anatomy.format: {1}".format(__name__, e)
|
||||
)
|
||||
os.environ["AVALON_WORKDIR"] = os.path.normpath(work_template)
|
||||
|
|
@ -239,13 +240,22 @@ class AppAction(BaseHandler):
|
|||
tools_env = acre.get_tools(tools_attr)
|
||||
env = acre.compute(tools_env)
|
||||
env = acre.merge(env, current_env=dict(os.environ))
|
||||
env = acre.append(dict(os.environ), env)
|
||||
|
||||
|
||||
#
|
||||
# tools_env = acre.get_tools(tools)
|
||||
# env = acre.compute(dict(tools_env))
|
||||
# env = acre.merge(env, dict(os.environ))
|
||||
# os.environ = acre.append(dict(os.environ), env)
|
||||
# os.environ = acre.compute(os.environ)
|
||||
|
||||
# Get path to execute
|
||||
st_temp_path = os.environ['PYPE_STUDIO_TEMPLATES']
|
||||
st_temp_path = os.environ['PYPE_CONFIG']
|
||||
os_plat = platform.system().lower()
|
||||
|
||||
# Path to folder with launchers
|
||||
path = os.path.join(st_temp_path, 'bin', os_plat)
|
||||
path = os.path.join(st_temp_path, 'launchers', os_plat)
|
||||
# Full path to executable launcher
|
||||
execfile = None
|
||||
|
||||
|
|
@ -275,7 +285,7 @@ class AppAction(BaseHandler):
|
|||
try:
|
||||
fp = open(execfile)
|
||||
except PermissionError as p:
|
||||
self.log.error('Access denied on {0} - {1}'.format(
|
||||
self.log.exception('Access denied on {0} - {1}'.format(
|
||||
execfile, p))
|
||||
return {
|
||||
'success': False,
|
||||
|
|
@ -344,6 +354,8 @@ class AppAction(BaseHandler):
|
|||
|
||||
# Set origin avalon environments
|
||||
for key, value in env_origin.items():
|
||||
if value == None:
|
||||
value = ""
|
||||
os.environ[key] = value
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import ftrack_api
|
||||
import functools
|
||||
import time
|
||||
from pype import api as pype
|
||||
from pype.vendor import ftrack_api
|
||||
from pype.vendor.ftrack_api import session as fa_session
|
||||
|
||||
|
||||
class MissingPermision(Exception):
|
||||
|
|
@ -30,7 +31,7 @@ class BaseHandler(object):
|
|||
def __init__(self, session):
|
||||
'''Expects a ftrack_api.Session instance'''
|
||||
self._session = session
|
||||
self.log = pype.Logger.getLogger(self.__class__.__name__)
|
||||
self.log = pype.Logger().get_logger(self.__class__.__name__)
|
||||
|
||||
# Using decorator
|
||||
self.register = self.register_decorator(self.register)
|
||||
|
|
@ -71,7 +72,7 @@ class BaseHandler(object):
|
|||
self.type, label)
|
||||
)
|
||||
except Exception as e:
|
||||
self.log.error('{} "{}" - Registration failed ({})'.format(
|
||||
self.log.exception('{} "{}" - Registration failed ({})'.format(
|
||||
self.type, label, str(e))
|
||||
)
|
||||
return wrapper_register
|
||||
|
|
@ -94,7 +95,7 @@ class BaseHandler(object):
|
|||
return result
|
||||
except Exception as e:
|
||||
msg = '{} "{}": Failed ({})'.format(self.type, label, str(e))
|
||||
self.log.error(msg)
|
||||
self.log.exception(msg)
|
||||
return {
|
||||
'success': False,
|
||||
'message': msg
|
||||
|
|
@ -110,7 +111,6 @@ class BaseHandler(object):
|
|||
self.session.reset()
|
||||
|
||||
def _preregister(self):
|
||||
# Rolecheck
|
||||
if hasattr(self, "role_list") and len(self.role_list) > 0:
|
||||
username = self.session.api_user
|
||||
user = self.session.query(
|
||||
|
|
@ -197,7 +197,9 @@ class BaseHandler(object):
|
|||
_entities = event['data'].get('entities_object', None)
|
||||
if (
|
||||
_entities is None or
|
||||
_entities[0].get('link', None) == ftrack_api.symbol.NOT_SET
|
||||
_entities[0].get(
|
||||
'link', None
|
||||
) == fa_session.ftrack_api.symbol.NOT_SET
|
||||
):
|
||||
_entities = self._get_entities(event)
|
||||
|
||||
|
|
@ -302,7 +304,7 @@ class BaseHandler(object):
|
|||
|
||||
# Launch preactions
|
||||
for preaction in self.preactions:
|
||||
event = ftrack_api.event.base.Event(
|
||||
event = fa_session.ftrack_api.event.base.Event(
|
||||
topic='ftrack.action.launch',
|
||||
data=dict(
|
||||
actionIdentifier=preaction,
|
||||
|
|
@ -314,7 +316,7 @@ class BaseHandler(object):
|
|||
)
|
||||
session.event_hub.publish(event, on_error='ignore')
|
||||
# Relaunch this action
|
||||
event = ftrack_api.event.base.Event(
|
||||
event = fa_session.ftrack_api.event.base.Event(
|
||||
topic='ftrack.action.launch',
|
||||
data=dict(
|
||||
actionIdentifier=self.identifier,
|
||||
|
|
@ -415,7 +417,7 @@ class BaseHandler(object):
|
|||
'applicationId=ftrack.client.web and user.id="{0}"'
|
||||
).format(user_id)
|
||||
self.session.event_hub.publish(
|
||||
ftrack_api.event.base.Event(
|
||||
fa_session.ftrack_api.event.base.Event(
|
||||
topic='ftrack.action.trigger-user-interface',
|
||||
data=dict(
|
||||
type='message',
|
||||
|
|
@ -438,7 +440,7 @@ class BaseHandler(object):
|
|||
).format(user_id)
|
||||
|
||||
self.session.event_hub.publish(
|
||||
ftrack_api.event.base.Event(
|
||||
fa_session.ftrack_api.event.base.Event(
|
||||
topic='ftrack.action.trigger-user-interface',
|
||||
data=dict(
|
||||
type='widget',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import os
|
||||
import requests
|
||||
from app.vendor.Qt import QtCore, QtGui, QtWidgets
|
||||
from app import style
|
||||
from Qt import QtCore, QtGui, QtWidgets
|
||||
from pypeapp import style
|
||||
from . import credentials, login_tools
|
||||
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ class Login_Dialog_ui(QtWidgets.QWidget):
|
|||
elif hasattr(parent, 'parent') and hasattr(parent.parent, 'icon'):
|
||||
self.setWindowIcon(self.parent.parent.icon)
|
||||
else:
|
||||
pype_setup = os.getenv('PYPE_SETUP_ROOT')
|
||||
pype_setup = os.getenv('PYPE_ROOT')
|
||||
items = [pype_setup, "app", "resources", "icon.png"]
|
||||
fname = os.path.sep.join(items)
|
||||
icon = QtGui.QIcon(fname)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import webbrowser
|
|||
import functools
|
||||
import pype
|
||||
import inspect
|
||||
from app.vendor.Qt import QtCore
|
||||
from Qt import QtCore
|
||||
|
||||
|
||||
class LoginServerHandler(BaseHTTPRequestHandler):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue