Skip to content
258 changes: 253 additions & 5 deletions python/context_selector/context_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from sgtk.platform.qt import QtCore, QtGui
from .ui.context_editor_widget import Ui_ContextWidget

from collections import OrderedDict

# framework imports
shotgun_globals = sgtk.platform.import_framework(
"tk-framework-shotgunutils", "shotgun_globals"
Expand Down Expand Up @@ -97,12 +99,43 @@ def __init__(self, parent):
self.ui = Ui_ContextWidget()
self.ui.setupUi(self)


self._initialize_task_statuses = True
self._status_permissions = {}
#self._complex_populate_status_display()

# Todo: read all availabvle 'sg_status_list' fields from shotgrid
self._status_dict = {
"wtg": "Waiting to Start",
"rdy": "Ready to Start",
"ip": "In Progress",
"hld": "On Hold",
"rev": "Ready For Review",
"apr": "Approved",
"fin": "Final",
"na": "N/A"
}

self._tasks = {}
# Loads the style sheet for the widget
qss_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "style.qss")
with open(qss_file, "rt") as f:
# apply to widget (and all its children)
self.setStyleSheet(f.read())

def display_publish_name(self):
"""
Display the publish name widget
"""
self.ui.publish_name_label.show()
self.ui.publish_name_display.show()
self.ui.publish_token_label.show()
self.ui.publish_token_display.show()

def set_publish_name(self, publish_name):
self.ui.publish_name_display.setText(publish_name)
self.ui.publish_name_display.setCursorPosition(0)

def eventFilter(self, widget, event):
"""
Filter out and handle some key/click events on the search widgets.
Expand Down Expand Up @@ -226,7 +259,7 @@ def set_context(
task_display_override=task_display_override,
link_display_override=link_display_override,
)

self._show_status(context)
# ensure the new context is added to the list of recents.
if context:
self._add_to_recents(context)
Expand All @@ -251,6 +284,11 @@ def set_up(self, task_manager):
self.ui.task_search_btn.toggled.connect(self._on_task_search_toggled)
self.ui.task_search.hide()

#self.ui.task_display.textchanged.connect(self._task_display_update)

# Update task status
self.ui.status_display.currentIndexChanged.connect(self._save_task_status)

# setup the search toggle
self.ui.link_search_btn.toggled.connect(self._on_link_search_toggled)
self.ui.link_search.hide()
Expand Down Expand Up @@ -296,6 +334,85 @@ def set_up(self, task_manager):
# get recent contexts from user settings
self._get_recent_contexts()

def _complex_populate_status_display(self, context):
"""
Populate status display
"""
self.ui.status_display.blockSignals(True)
if self._initialize_task_statuses:
# self._check_status_permissions(context)
self._initialize_task_statuses = False

self.ui.status_display.clear()

for status_short_code, status_name in self._status_dict.items():
self.ui.status_display.addItem(status_name)

for index, status_short_code in enumerate(self._status_dict.keys()):
if status_short_code == "na":
self.ui.status_display.model().item(index).setEnabled(False)
try:
if self._context and self._context.task:
task_id = self._context.task["id"]
if task_id in self._tasks:
status_name = self._tasks[task_id]["new_status_name"]
self.ui.status_display.setCurrentText(status_name)
else:
self.ui.status_display.setCurrentText("N/A")
except:
_log("Unable to set current task status")
pass
self.ui.status_display.blockSignals(False)

def _simple_populate_status_display(self):
"""
Populate status display
"""
self.ui.status_display.blockSignals(True)

self.ui.status_display.clear()
#self.ui.status_display.addItem("testing")

for status_short_code, status_name in self._status_dict.items():
self.ui.status_display.addItem(status_name)
self.ui.status_display.setCurrentText("N/A")
self.ui.status_display.blockSignals(False)

def _check_status_permissions(self, context):
"""
Check if current user have permission to change each status
Todo: find a better way to do this
"""
sg = sgtk.platform.current_bundle().shotgun
if context and context.task:
task_status_short_code = _get_task_status(context)

for status_short_code in self._status_dict.keys():
try:
result = sg.update('Task', context.task['id'], {'sg_status_list': status_short_code})
if result['sg_status_list'] == status_short_code:
self._status_permissions[status_short_code] = True
else:
self._status_permissions[status_short_code] = False
except:
self._status_permissions[status_short_code] = False
pass
# reset task status
sg.update('Task', context.task['id'], {'sg_status_list': task_status_short_code})

def _get_status_name(self, short_code):
if not short_code:
return "N/A"
return self._status_dict[short_code]

def _get_status_short_code(self, name):
if not name:
return "na"
if name:
for key, value in self._status_dict.items():
if value == name:
return key

def restrict_entity_types_by_link(self, entity_type, field_name):
"""
Specify what entries should show up in the list of links when
Expand Down Expand Up @@ -615,14 +732,17 @@ def _on_context_activated(self, context):
"""
Called when a new context is set via the menu or one of the completers.
"""

logger.debug("Context changed to: %s" % (context,))

msg = "Context changed to: %s" % (context,)
logger.debug(msg)
_log(msg)
self._context = context
# update the widget to display the new context and alert listeners that
# a new context was selected
self._show_context(context)
self._show_status(context)
self.context_changed.emit(context)


def _on_entity_activated(self, entity_type, entity_id, entity_name):
"""
Slot called when an entity is selected via one of the search completers.
Expand Down Expand Up @@ -666,6 +786,61 @@ def _on_task_search_toggled(self, checked):
self.ui.task_menu_btn.show()
self.ui.task_search.hide()

def _save_task_status(self):
"""
Update task status
"""
self.ui.status_display.blockSignals(True)
try:
if self._context and self._context.task:
task_id = self._context.task["id"]
if task_id not in self._tasks:
self._tasks[task_id] = {}
task_name = self._context.task["name"]
original_status_code = _get_task_status(self._context)
new_status_name = self.ui.status_display.currentText()
new_status_code = self._get_status_short_code(new_status_name)
self._tasks[task_id]["task_name"] = task_name
self._tasks[task_id]["original_status_code"] = original_status_code
self._tasks[task_id]["new_status_name"] = new_status_name
self._tasks[task_id]["new_status_code"] = new_status_code
# _log("self._context is: %s" % self._context)
# _log("self._context.entity is: %s" % self._context.entity["name"])
_log("task name is: %s" % self._context.task["name"])
_log("Task are: %s" % self._tasks)
except:
_log("Unable to get task or task status" )
pass
self.ui.status_display.blockSignals(False)

def update_task_status(self):
"""
Update task status
"""
try:
sg = sgtk.platform.current_bundle().shotgun
for task_id in self._tasks.keys():

try:
# _log("----------------------------------------")
task_name = self._tasks[task_id]["task_name"]
original_status_code = self._tasks[task_id]["original_status_code"]
new_status_code = self._tasks[task_id]["new_status_code"]
if original_status_code != new_status_code:
result = sg.update('Task', task_id, {'sg_status_list': new_status_code})

_log("Updating status of task \'%s\' from %s to %s ..." % (task_name, original_status_code, new_status_code))
if result['sg_status_list'] == new_status_code:
_log("Task status updated successfully")
else:
_log("Task status update was not successful")
except:
_log("Error when updating status of task %s", task_name)
pass
except:
_log("Error when updating task statuses ")
pass

def _on_link_search_toggled(self, checked):
"""
Slot called when the user clicks the link display or the link search
Expand Down Expand Up @@ -828,7 +1003,6 @@ def _show_context(
"""
Show the supplied context in the UI.
"""

if task_display_override:
task_display = task_display_override
else:
Expand All @@ -841,6 +1015,7 @@ def _show_context(

# update the task display/state
self.ui.task_display.setText(task_display)

self.ui.task_search_btn.setChecked(False)
self.ui.task_search_btn.setDown(False)

Expand All @@ -855,6 +1030,48 @@ def _show_context(
self._query_related_tasks, task_args=[context]
)

def _show_status(self, context):
"""
Show task status.
"""
self.ui.status_display.blockSignals(True)
try:
if context and context.task:
self._complex_populate_status_display(context)

_log("Get task status ...")
task_id = context.task["id"]
if task_id in self._tasks.keys():
task_status_name = self._tasks[task_id]["new_status_name"]
else:
task_status_short_code = _get_task_status(context)
task_status_name = self._get_status_name(task_status_short_code)


try:
self.ui.status_display.setCurrentText(task_status_name)
except:
_log("Unable to update show task status")
pass

else:
self.ui.status_display.setCurrentText("N/A")
except:
_log("Unable to update show task status")
pass
self.ui.status_display.blockSignals(False)

def _update_task_display(self, context, task_display_override=None):
"""
Update the task display
"""
if task_display_override:
task_display = task_display_override
else:
task_display = _get_task_display(context)

# update the task display/state
self.ui.task_display.setText(task_display)

def _get_task_display(context, plain_text=False):
"""
Expand Down Expand Up @@ -883,6 +1100,28 @@ def _get_task_display(context, plain_text=False):
return display_name


def _get_task_status(context):
"""
Gat task status
"""

sg = sgtk.platform.current_bundle().shotgun

if not context or not context.task:
return ""
task_id = context.task["id"]

entity = 'Task'
filters = [['id', 'is', task_id]]
fields = ['entity', 'sg_status_list']
item = sg.find_one(entity, filters, fields)
_log("item is: %s" % item)
task_status = item['sg_status_list']
_log("task_status is: %s" % task_status)

return task_status


def _get_link_display(context, plain_text=False):
"""
Build a display string for the link of the supplied context.
Expand Down Expand Up @@ -1016,3 +1255,12 @@ def _query_entity_schema(entity_type, field_name):
return bundle.shotgun.schema_field_read(
entity_type, field_name=field_name, project_entity=project
)


def _log(msg, error=0):
if logger:
if error:
logger.warn(msg)
else:
logger.info(msg)
print(msg)
Loading