Source code for shotgun_fields.footage_widget

# Copyright (c) 2016 Shotgun Software Inc.
#
# CONFIDENTIAL AND PROPRIETARY
#
# This work is provided "AS IS" and subject to the Shotgun Pipeline Toolkit
# Source Code License included in this distribution package. See LICENSE.
# By accessing, using, copying or modifying this work you indicate your
# agreement to the Shotgun Pipeline Toolkit Source Code License. All rights
# not expressly granted therein are reserved by Shotgun Software Inc.

import re

from .label_base_widget import LabelBaseWidget
from .shotgun_field_meta import ShotgunFieldMeta

from sgtk.platform.qt import QtCore, QtGui
from tank_vendor import six


[docs]@six.add_metaclass(ShotgunFieldMeta) class FootageWidget(LabelBaseWidget): """ Display a ``footage`` field value as returned by the Shotgun API. """ _DISPLAY_TYPE = "footage"
[docs]@six.add_metaclass(ShotgunFieldMeta) class FootageEditorWidget(QtGui.QLineEdit): """ Allows editing of a ``footage`` field value as returned by the Shotgun API. Pressing ``Enter`` or ``Return`` when the widget has focus will cause the value to be applied and the ``value_changed`` signal to be emitted. """ _EDITOR_TYPE = "footage"
[docs] def get_value(self): """ :return: The internal value being displayed by the widget. """ return self.validator().fixup(self.text())
def keyPressEvent(self, event): """ Provides shortcuts for applying modified values. :param event: The key press event object :type event: :class:`~PySide.QtGui.QKeyEvent` """ if event.key() in [QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return]: self.value_changed.emit() else: super(FootageEditorWidget, self).keyPressEvent(event) def setup_widget(self): """ Prepare the widget for display. Called by the metaclass during initialization. """ self.setMinimumWidth(100) self.setValidator(_FootageInputValidator()) self.textChanged.connect(self._on_text_changed) self.returnPressed.connect(self.value_changed.emit) def _display_default(self): """ Display the default value of the widget. """ self.clear() def _display_value(self, value): """ Set the value displayed by the widget. :param value: The value returned by the Shotgun API to be displayed """ self.setText(self._string_value(value)) def _on_text_changed(self): """ Keep the internal value updated as the user types """ self._value = str(self.text()) def _string_value(self, value): """ Ensure the value to be displayed is a string. :param value: The value from Shotgun """ return str(value)
class _FootageInputValidator(QtGui.QValidator): """ A validator for the {feet}-{frames} footage spec. """ def fixup(self, input_str): """ Translate the input string into a valid string if possible. :param str input_str: The input value to translate. :return: The translated value or the original input string if translation is not possible. """ try: # translate the input into feet & frames (feet, frames) = self._get_feet_frames(input_str) input_str = "%d-%02d" % (feet, frames) except ValueError: pass return input_str def validate(self, input_str, pos): """ Validate the input_str string if it is possible to infer feet and frames. :param input_str: The input string :param pos: The cursor position within the widget :return: :class:`~PySide.QtGui.QValidator` enum ``Invalid`` or ``Acceptable`` depending on if the input string is valid. :rtype: int """ try: (feet, frames) = self._get_feet_frames(input_str) except ValueError: return QtGui.QValidator.Invalid return QtGui.QValidator.Acceptable def _get_feet_frames(self, input_str): """ Convert the input string into a tuple representing ``feet`` and ``frames``. :param str input_str: A string representing a footage spec. :return: A tuple of the form ``(feet, frames)`` inferred from the input string. :rtype tuple: :raises: ``ValueError`` if feet and frames cannot be inferred. """ input_str = str(input_str) input_str = input_str.strip() input_str = input_str.rstrip("-") if str.isdigit(input_str): # if the value is simply an integer, we can calculate the number of # feet (16 frames per foot) and the remaining frames using ``divmod``. return divmod(int(input_str), 16) match = re.match(r"^(\d+)-(\d+)$", input_str) if match: # the input value is of the form ``{feet}-{frames}``. ensure the # frames value is reduced, then compute the total feet and frames. feet = match.group(1) frames = match.group(2) (extra_feet, frames) = divmod(int(frames), 16) return (int(feet) + extra_feet, frames) raise ValueError