diff --git a/openpype/tools/creator/constants.py b/openpype/tools/creator/constants.py new file mode 100644 index 0000000000..9096224ac1 --- /dev/null +++ b/openpype/tools/creator/constants.py @@ -0,0 +1,11 @@ +from Qt import QtCore + + +FamilyRole = QtCore.Qt.UserRole + 3 +ExistsRole = QtCore.Qt.UserRole + 4 +PluginRole = QtCore.Qt.UserRole + 5 + +Separator = "---separator---" + +# TODO regex should be defined by schema +SubsetAllowedSymbols = "a-zA-Z0-9_." diff --git a/openpype/tools/creator/widgets.py b/openpype/tools/creator/widgets.py index 7a370d8700..f9a104e237 100644 --- a/openpype/tools/creator/widgets.py +++ b/openpype/tools/creator/widgets.py @@ -1,4 +1,7 @@ -from Qt import QtWidgets, QtCore +import re +from Qt import QtWidgets, QtCore, QtGui + +from .constants import SubsetAllowedSymbols class CreateErrorMessageBox(QtWidgets.QDialog): @@ -74,3 +77,92 @@ class CreateErrorMessageBox(QtWidgets.QDialog): line.setFrameShape(QtWidgets.QFrame.HLine) line.setFrameShadow(QtWidgets.QFrame.Sunken) return line + + +class SubsetNameValidator(QtGui.QRegExpValidator): + invalid = QtCore.Signal(set) + pattern = "^[{}]*$".format(SubsetAllowedSymbols) + + def __init__(self): + reg = QtCore.QRegExp(self.pattern) + super(SubsetNameValidator, self).__init__(reg) + + def validate(self, input, pos): + results = super(SubsetNameValidator, self).validate(input, pos) + if results[0] == self.Invalid: + self.invalid.emit(self.invalid_chars(input)) + return results + + def invalid_chars(self, input): + invalid = set() + re_valid = re.compile(self.pattern) + for char in input: + if char == " ": + invalid.add("' '") + continue + if not re_valid.match(char): + invalid.add(char) + return invalid + + +class SubsetNameLineEdit(QtWidgets.QLineEdit): + report = QtCore.Signal(str) + colors = { + "empty": (QtGui.QColor("#78879b"), ""), + "exists": (QtGui.QColor("#4E76BB"), "border-color: #4E76BB;"), + "new": (QtGui.QColor("#7AAB8F"), "border-color: #7AAB8F;"), + } + + def __init__(self, *args, **kwargs): + super(SubsetNameLineEdit, self).__init__(*args, **kwargs) + + validator = SubsetNameValidator() + self.setValidator(validator) + self.setToolTip("Only alphanumeric characters (A-Z a-z 0-9), " + "'_' and '.' are allowed.") + + self._status_color = self.colors["empty"][0] + + anim = QtCore.QPropertyAnimation() + anim.setTargetObject(self) + anim.setPropertyName(b"status_color") + anim.setEasingCurve(QtCore.QEasingCurve.InCubic) + anim.setDuration(300) + anim.setStartValue(QtGui.QColor("#C84747")) # `Invalid` status color + self.animation = anim + + validator.invalid.connect(self.on_invalid) + + def on_invalid(self, invalid): + message = "Invalid character: %s" % ", ".join(invalid) + self.report.emit(message) + self.animation.stop() + self.animation.start() + + def as_empty(self): + self._set_border("empty") + self.report.emit("Empty subset name ..") + + def as_exists(self): + self._set_border("exists") + self.report.emit("Existing subset, appending next version.") + + def as_new(self): + self._set_border("new") + self.report.emit("New subset, creating first version.") + + def _set_border(self, status): + qcolor, style = self.colors[status] + self.animation.setEndValue(qcolor) + self.setStyleSheet(style) + + def _get_status_color(self): + return self._status_color + + def _set_status_color(self, color): + self._status_color = color + self.setStyleSheet("border-color: %s;" % color.name()) + + status_color = QtCore.Property( + QtGui.QColor, _get_status_color, _set_status_color + ) diff --git a/openpype/tools/creator/window.py b/openpype/tools/creator/window.py index 501cb66bb8..8ce0dbff54 100644 --- a/openpype/tools/creator/window.py +++ b/openpype/tools/creator/window.py @@ -4,126 +4,34 @@ import traceback import re from Qt import QtWidgets, QtCore, QtGui -from avalon.vendor import qtawesome -import six -from avalon import api, io, style -from .widgets import CreateErrorMessageBox +from avalon.vendor import qtawesome +from avalon import api, io, style from avalon.tools import lib + from openpype.api import get_current_project_settings +from .widgets import ( + CreateErrorMessageBox, + SubsetNameLineEdit +) +from .constants import ( + FamilyRole, + ExistsRole, + PluginRole, + SubsetAllowedSymbols, + Separator +) + module = sys.modules[__name__] module.window = None -module.root = api.registered_root() - -HelpRole = QtCore.Qt.UserRole + 2 -FamilyRole = QtCore.Qt.UserRole + 3 -ExistsRole = QtCore.Qt.UserRole + 4 -PluginRole = QtCore.Qt.UserRole + 5 - -Separator = "---separator---" - -# TODO regex should be defined by schema -SubsetAllowedSymbols = "a-zA-Z0-9_." -class SubsetNameValidator(QtGui.QRegExpValidator): - - invalid = QtCore.Signal(set) - pattern = "^[{}]*$".format(SubsetAllowedSymbols) - - def __init__(self): - reg = QtCore.QRegExp(self.pattern) - super(SubsetNameValidator, self).__init__(reg) - - def validate(self, input, pos): - results = super(SubsetNameValidator, self).validate(input, pos) - if results[0] == self.Invalid: - self.invalid.emit(self.invalid_chars(input)) - return results - - def invalid_chars(self, input): - invalid = set() - re_valid = re.compile(self.pattern) - for char in input: - if char == " ": - invalid.add("' '") - continue - if not re_valid.match(char): - invalid.add(char) - return invalid - - -class SubsetNameLineEdit(QtWidgets.QLineEdit): - - report = QtCore.Signal(str) - colors = { - "empty": (QtGui.QColor("#78879b"), ""), - "exists": (QtGui.QColor("#4E76BB"), "border-color: #4E76BB;"), - "new": (QtGui.QColor("#7AAB8F"), "border-color: #7AAB8F;"), - } - - def __init__(self, *args, **kwargs): - super(SubsetNameLineEdit, self).__init__(*args, **kwargs) - - validator = SubsetNameValidator() - self.setValidator(validator) - self.setToolTip("Only alphanumeric characters (A-Z a-z 0-9), " - "'_' and '.' are allowed.") - - self._status_color = self.colors["empty"][0] - - anim = QtCore.QPropertyAnimation() - anim.setTargetObject(self) - anim.setPropertyName(b"status_color") - anim.setEasingCurve(QtCore.QEasingCurve.InCubic) - anim.setDuration(300) - anim.setStartValue(QtGui.QColor("#C84747")) # `Invalid` status color - self.animation = anim - - validator.invalid.connect(self.on_invalid) - - def on_invalid(self, invalid): - message = "Invalid character: %s" % ", ".join(invalid) - self.report.emit(message) - self.animation.stop() - self.animation.start() - - def as_empty(self): - self._set_border("empty") - self.report.emit("Empty subset name ..") - - def as_exists(self): - self._set_border("exists") - self.report.emit("Existing subset, appending next version.") - - def as_new(self): - self._set_border("new") - self.report.emit("New subset, creating first version.") - - def _set_border(self, status): - qcolor, style = self.colors[status] - self.animation.setEndValue(qcolor) - self.setStyleSheet(style) - - def _get_status_color(self): - return self._status_color - - def _set_status_color(self, color): - self._status_color = color - self.setStyleSheet("border-color: %s;" % color.name()) - - status_color = QtCore.Property(QtGui.QColor, - _get_status_color, - _set_status_color) - - -class Window(QtWidgets.QDialog): - +class CreatorWindow(QtWidgets.QDialog): stateChanged = QtCore.Signal(bool) def __init__(self, parent=None): - super(Window, self).__init__(parent) + super(CreatorWindow, self).__init__(parent) self.setWindowTitle("Instance Creator") self.setFocusPolicy(QtCore.Qt.StrongFocus) if not parent: @@ -131,9 +39,6 @@ class Window(QtWidgets.QDialog): self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint ) - # Store the widgets for lookup in here - self.data = dict() - # Store internal states in here self.state = { "valid": False @@ -459,7 +364,6 @@ class Window(QtWidgets.QDialog): """ def refresh(self): - listing = self.data["Listing"] asset = self.data["Asset"] asset.setText(api.Session["AVALON_ASSET"]) @@ -474,7 +378,6 @@ class Window(QtWidgets.QDialog): label = creator.label or creator.family item = QtWidgets.QListWidgetItem(label) item.setData(QtCore.Qt.ItemIsEnabled, True) - item.setData(HelpRole, creator.__doc__) item.setData(FamilyRole, creator.family) item.setData(PluginRole, creator) item.setData(ExistsRole, False) @@ -708,8 +611,7 @@ def show(debug=False, parent=None): module.project = any_project["name"] with lib.application(): - window = Window(parent) - window.setStyleSheet(style.load_stylesheet()) + window = CreatorWindow(parent) window.refresh() window.show()