Merge pull request #2296 from pypeclub/feature/OP-1775_Settings-UI-use-openpype-styles

Settings UI use OpenPype styles
This commit is contained in:
Jakub Trllo 2021-11-30 10:58:01 +01:00 committed by GitHub
commit ba285533e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 563 additions and 899 deletions

View file

@ -59,7 +59,12 @@
"color-selected": "#F0F2F5",
"color-hover": "#F0F2F5"
},
"nice-checkbox": {
"bg-checked": "#56a06f",
"bg-unchecked": "#434b56",
"bg-checker": "#D3D8DE",
"bg-checker-hover": "#F0F2F5"
},
"loader": {
"asset-view": {
"selected": "rgba(168, 175, 189, 0.6)",
@ -79,6 +84,34 @@
"bg-expander-hover": "#2d6c9f",
"bg-expander-selected-hover": "#3784c5"
}
},
"settings": {
"invalid-light": "#C93636",
"invalid-dark": "#AD2E2E",
"modified-light": "#46b1f3",
"modified-mid": "#189AEA",
"modified-dark": "#106AA2",
"studio-light": "#73C990",
"studio-dark": "#56a06f",
"studio-label-hover": "#FFFFFF",
"project-light": "#FFA64D",
"project-mid": "#FF8C1A",
"project-dark": "#E67300",
"label-fg": "#969b9e",
"label-fg-hover": "#b8c1c5",
"breadcrumbs-btn-bg": "rgba(127, 127, 127, 60)",
"breadcrumbs-btn-bg-hover": "rgba(127, 127, 127, 90)",
"content-hightlighted": "rgba(19, 26, 32, 15)",
"focus-border": "#839caf",
"image-btn": "#bfccd6",
"image-btn-hover": "#189aea",
"image-btn-disabled": "#bfccd6"
}
}
}

View file

@ -660,15 +660,6 @@ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
background: none;
}
/* Globally used names */
#Separator {
background: {color:bg-menu-separator};
}
#IconButton {
padding: 4px 4px 4px 4px;
}
/* Password dialog*/
#PasswordBtn {
border: none;
@ -971,7 +962,235 @@ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
background: transparent;
}
/* Settings - NOT USED YET
- we need to define font family for settings UI */
#SettingsMainWidget {
background: #141a1f;
}
/* Change focus borders. */
#SettingsMainWidget QAbstractSpinBox:focus, #SettingsMainWidget QLineEdit:focus, #SettingsMainWidget QPlainTextEdit:focus, #SettingsMainWidget QTextEdit:focus {
border-color: {color:settings:focus-border};
}
/* Modify tab widget for settings */
#SettingsMainWidget QTabWidget::pane {
border-top-style: none;
}
#SettingsMainWidget QTabBar {
background: transparent;
}
#SettingsMainWidget QTabBar::tab {
border: none;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
padding: 5px;
}
#SettingsMainWidget QTabBar::tab:selected {
background: {color:bg};
border-color: #9B9B9B;
border-bottom-color: #C2C7CB;
}
#SettingsMainWidget QTabBar::tab:!selected {
margin-top: 2px;
background: #21252B;
}
#SettingsMainWidget QTabBar::tab:!selected:hover {
background: #333840;
}
#SettingsMainWidget QTabBar::tab:first:selected {
margin-left: 0;
}
#SettingsMainWidget QTabBar::tab:last:selected {
margin-right: 0;
}
#SettingsMainWidget QTabBar::tab:only-one {
margin: 0;
}
#SettingsToolIconBtn {
border: 0px solid #bfccd6;
background-color: transparent;
}
#SettingsToolBtn {
border: 1px solid #bfccd6;
border-radius: 10px;
background-color: transparent;
}
#SettingsToolBtn:hover {
border-color: #189aea;
color: {color:settings:modified-light};
background-color: transparent;
}
#SettingsToolBtn:disabled {
background-color: #464b54;
}
#ExpandToggleBtn {
background: transparent;
}
#SettingsLabel {
background: transparent;
color: {color:settings:label-fg};
}
#SettingsLabel:hover {color: {color:settings:label-fg-hover};}
#SettingsLabel[state="studio"] {color: {color:settings:studio-light};}
#SettingsLabel[state="studio"]:hover {color: {color:settings:studio-label-hover};}
#SettingsLabel[state="modified"] {color: {color:settings:modified-mid};}
#SettingsLabel[state="modified"]:hover {color: {color:settings:modified-light};}
#SettingsLabel[state="overriden-modified"] {color: {color:settings:modified-mid};}
#SettingsLabel[state="overriden-modified"]:hover {color: {color:settings:modified-light};}
#SettingsLabel[state="overriden"] {color: {color:settings:project-mid};}
#SettingsLabel[state="overriden"]:hover {color: {color:settings:project-light};}
#SettingsLabel[state="invalid"] {color:{color:settings:invalid-dark};}
#SettingsLabel[state="invalid"]:hover {color: {color:settings:invalid-dark};}
/* TODO Replace these with explicit widget types if possible */
#SettingsMainWidget QWidget[input-state="modified"] {
border-color: {color:settings:modified-mid};
}
#SettingsMainWidget QWidget[input-state="overriden-modified"] {
border-color: {color:settings:modified-mid};
}
#SettingsMainWidget QWidget[input-state="overriden"] {
border-color: {color:settings:project-mid};
}
#SettingsMainWidget QWidget[input-state="invalid"] {
border-color: {color:settings:invalid-dark};
}
#GroupWidget {
border-bottom: 1px solid #21252B;
}
#ProjectListWidget QLabel {
background: transparent;
font-weight: bold;
}
#MultiSelectionComboBox {
font-size: 12px;
}
#DictKey[state="modified"] {border-color: {color:settings:modified-mid};}
#DictKey[state="invalid"] {border-color: {color:settings:invalid-dark};}
#ExpandLabel {
font-weight: bold;
color: {color:settings:label-fg};
}
#ExpandLabel:hover {
color: {color:settings:label-fg-hover};
}
#ContentWidget {
background-color: transparent;
}
#ContentWidget[content_state="hightlighted"] {
background-color: {color:settings:content-hightlighted};
}
#SideLineWidget {
background-color: #333942;
border-style: solid;
border-color: #4e5254;
border-left-width: 3px;
border-bottom-width: 0px;
border-right-width: 0px;
border-top-width: 0px;
}
#SideLineWidget:hover {
border-color: #7d8386;
}
#SideLineWidget[state="child-studio"] {border-color: {color:settings:studio-dark};}
#SideLineWidget[state="child-studio"]:hover {border-color: {color:settings:studio-light};}
#SideLineWidget[state="child-modified"] {border-color: {color:settings:modified-dark};}
#SideLineWidget[state="child-modified"]:hover {border-color: {color:settings:modified-mid};}
#SideLineWidget[state="child-invalid"] {border-color: {color:settings:invalid-dark};}
#SideLineWidget[state="child-invalid"]:hover {border-color: {color:settings:invalid-light};}
#SideLineWidget[state="child-overriden"] {border-color: {color:settings:project-dark};}
#SideLineWidget[state="child-overriden"]:hover {border-color: {color:settings:project-mid};}
#SideLineWidget[state="child-overriden-modified"] {border-color: {color:settings:modified-dark};}
#SideLineWidget[state="child-overriden-modified"]:hover {border-color: {color:settings:modified-mid};}
#DictAsWidgetBody {
background: transparent;
}
#DictAsWidgetBody[show_borders="1"] {
border: 1px solid #4e5254;
border-radius: 5px;
}
#ShadowWidget {
font-size: 36pt;
}
#BreadcrumbsPathInput {
padding: 2px;
font-size: 9pt;
}
#BreadcrumbsButton {
padding-right: 12px;
font-size: 9pt;
background: transparent;
}
#BreadcrumbsButton[empty="1"] {
padding-right: 0px;
}
#BreadcrumbsButton::menu-button {
border: none;
width: 12px;
background: {color:settings:breadcrumbs-btn-bg};
}
#BreadcrumbsButton::menu-button:hover {
background: {color:settings:breadcrumbs-btn-bg-hover};
}
#BreadcrumbsPanel {
border: 1px solid #4e5254;
border-radius: 5px;
background: #21252B;
}
/* Globally used names */
#Separator {
background: {color:bg-menu-separator};
}
#IconButton {
padding: 4px 4px 4px 4px;
}
#NiceCheckbox {
/* Default size hint of NiceCheckbox is defined by font size. */
font-size: 7pt;
}
#ImageButton {
padding: 0;
background: transparent;
font-size: 11pt;
}
#ImageButton:disabled {
background: {color:bg-buttons-disabled};
}

View file

@ -1,12 +1,13 @@
import sys
from Qt import QtWidgets, QtGui
from openpype import style
from .lib import (
BTN_FIXED_SIZE,
CHILD_OFFSET
)
from .local_settings import LocalSettingsWindow
from .settings import (
style,
MainWidget,
ProjectListWidget
)
@ -36,8 +37,6 @@ __all__ = (
"BTN_FIXED_SIZE",
"CHILD_OFFSET",
"style",
"MainWidget",
"ProjectListWidget",
"LocalSettingsWindow",

View file

@ -172,7 +172,9 @@ class LocalApplicationsWidgets(QtWidgets.QWidget):
def _reset_app_widgets(self):
while self.content_layout.count() > 0:
item = self.content_layout.itemAt(0)
item.widget().hide()
widget = item.widget()
if widget is not None:
widget.setVisible(False)
self.content_layout.removeItem(item)
self.widgets_by_group_name.clear()

View file

@ -6,10 +6,7 @@ from openpype.settings.constants import (
PROJECT_ANATOMY_KEY,
DEFAULT_PROJECT_KEY
)
from .widgets import (
SpacerWidget,
ProxyLabelWidget
)
from .widgets import ProxyLabelWidget
from .constants import (
LABEL_REMOVE_DEFAULT,
LABEL_ADD_DEFAULT,
@ -238,9 +235,9 @@ class SitesWidget(QtWidgets.QWidget):
comboboxes_layout = QtWidgets.QHBoxLayout(comboboxes_widget)
comboboxes_layout.setContentsMargins(0, 0, 0, 0)
comboboxes_layout.addWidget(active_site_widget)
comboboxes_layout.addWidget(remote_site_widget)
comboboxes_layout.addWidget(SpacerWidget(comboboxes_widget), 1)
comboboxes_layout.addWidget(active_site_widget, 0)
comboboxes_layout.addWidget(remote_site_widget, 0)
comboboxes_layout.addStretch(1)
content_widget = QtWidgets.QWidget(self)
content_layout = QtWidgets.QVBoxLayout(content_widget)
@ -259,7 +256,9 @@ class SitesWidget(QtWidgets.QWidget):
def _clear_widgets(self):
while self.content_layout.count():
item = self.content_layout.itemAt(0)
item.widget().hide()
widget = item.widget()
if widget is not None:
widget.setVisible(False)
self.content_layout.removeItem(item)
self.input_objects = {}
@ -383,7 +382,7 @@ class SitesWidget(QtWidgets.QWidget):
self.input_objects[site_name] = site_input_objects
# Add spacer so other widgets are squeezed to top
self.content_layout.addWidget(SpacerWidget(self), 1)
self.content_layout.addStretch(1)
def _on_input_value_change(self, site_name, key):
if (
@ -456,6 +455,8 @@ class _SiteCombobox(QtWidgets.QWidget):
self
)
combobox_input = QtWidgets.QComboBox(self)
combobox_delegate = QtWidgets.QStyledItemDelegate()
combobox_input.setItemDelegate(combobox_delegate)
main_layout = QtWidgets.QHBoxLayout(self)
main_layout.addWidget(label_widget)
@ -464,6 +465,7 @@ class _SiteCombobox(QtWidgets.QWidget):
combobox_input.currentIndexChanged.connect(self._on_index_change)
self.label_widget = label_widget
self.combobox_input = combobox_input
self._combobox_delegate = combobox_delegate
def _set_current_text(self, text):
index = None
@ -777,7 +779,7 @@ class RootSiteWidget(QtWidgets.QWidget):
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.addWidget(sites_widget)
main_layout.addWidget(SpacerWidget(self), 1)
main_layout.addStretch(1)
self.sites_widget = sites_widget

View file

@ -1,7 +1,6 @@
from Qt import QtWidgets, QtCore
from openpype.tools.settings.settings.widgets import (
ExpandingWidget,
SpacerWidget
ExpandingWidget
)
@ -56,7 +55,5 @@ class ProxyLabelWidget(QtWidgets.QWidget):
__all__ = (
"ExpandingWidget",
"SpacerWidget",
"Separator",
"SpacerWidget"
)

View file

@ -1,7 +1,7 @@
import logging
from Qt import QtWidgets, QtGui
from ..settings import style
from openpype import style
from openpype.settings.lib import (
get_local_settings,
@ -15,7 +15,6 @@ from openpype.api import (
from openpype.modules import ModulesManager
from .widgets import (
SpacerWidget,
ExpandingWidget
)
from .mongo_widget import OpenPypeMongoWidget
@ -58,8 +57,7 @@ class LocalSettingsWidget(QtWidgets.QWidget):
self._create_app_ui()
self._create_project_ui()
# Add spacer to main layout
self.main_layout.addWidget(SpacerWidget(self), 1)
self.main_layout.addStretch(1)
def _create_pype_mongo_ui(self):
pype_mongo_expand_widget = ExpandingWidget("OpenPype Mongo URL", self)
@ -210,7 +208,7 @@ class LocalSettingsWindow(QtWidgets.QWidget):
footer_layout = QtWidgets.QHBoxLayout(footer)
footer_layout.addWidget(reset_btn, 0)
footer_layout.addWidget(SpacerWidget(footer), 1)
footer_layout.addStretch(1)
footer_layout.addWidget(save_btn, 0)
main_layout = QtWidgets.QVBoxLayout(self)

View file

@ -1,10 +1,8 @@
from . import style
from .window import MainWidget
from .widgets import ProjectListWidget
__all__ = (
"style",
"MainWidget",
"ProjectListWidget"
)

View file

@ -470,10 +470,9 @@ class GUIWidget(BaseWidget):
self.entity_widget.add_widget_to_layout(self)
def _create_label_ui(self):
self.setObjectName("LabelWidget")
label = self.entity["label"]
label_widget = QtWidgets.QLabel(label, self)
label_widget.setObjectName("SettingsLabel")
layout = QtWidgets.QHBoxLayout(self)
layout.setContentsMargins(0, 5, 0, 5)
@ -481,7 +480,7 @@ class GUIWidget(BaseWidget):
def _create_separator_ui(self):
splitter_item = QtWidgets.QWidget(self)
splitter_item.setObjectName("SplitterItem")
splitter_item.setObjectName("Separator")
splitter_item.setMinimumHeight(self.separator_height)
splitter_item.setMaximumHeight(self.separator_height)
@ -513,10 +512,9 @@ class MockUpWidget(BaseWidget):
child_invalid = False
def create_ui(self):
self.setObjectName("LabelWidget")
label = "Mockup widget for entity {}".format(self.entity.path)
label_widget = QtWidgets.QLabel(label, self)
label_widget.setObjectName("SettingsLabel")
layout = QtWidgets.QHBoxLayout(self)
layout.setContentsMargins(0, 5, 0, 5)

View file

@ -391,7 +391,9 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
while self.content_layout.count() != 0:
widget = self.content_layout.itemAt(0).widget()
widget.hide()
if widget is not None:
widget.setVisible(False)
self.content_layout.removeWidget(widget)
widget.deleteLater()

View file

@ -164,6 +164,7 @@ class DictConditionalWidget(BaseWidget):
content_widget.setProperty("show_borders", show_borders)
label_widget = QtWidgets.QLabel(self.entity.label)
label_widget.setObjectName("SettingsLabel")
content_layout = QtWidgets.QGridLayout(content_widget)
content_layout.setContentsMargins(5, 5, 5, 5)

View file

@ -3,7 +3,12 @@ from uuid import uuid4
from Qt import QtWidgets, QtCore, QtGui
from .base import BaseWidget
from .lib import create_deffered_value_change_timer
from .lib import (
create_deffered_value_change_timer,
create_add_btn,
create_remove_btn,
create_confirm_btn
)
from .widgets import (
ExpandingWidget,
IconButton
@ -21,92 +26,6 @@ KEY_INPUT_TOOLTIP = (
)
class PaintHelper:
cached_icons = {}
@classmethod
def _draw_image(cls, width, height, brush):
image = QtGui.QPixmap(width, height)
image.fill(QtCore.Qt.transparent)
icon_path_stroker = QtGui.QPainterPathStroker()
icon_path_stroker.setCapStyle(QtCore.Qt.RoundCap)
icon_path_stroker.setJoinStyle(QtCore.Qt.RoundJoin)
icon_path_stroker.setWidth(height / 5)
painter = QtGui.QPainter(image)
painter.setPen(QtCore.Qt.transparent)
painter.setBrush(brush)
rect = QtCore.QRect(0, 0, image.width(), image.height())
fifteenth = rect.height() / 15
# Left point
p1 = QtCore.QPoint(
rect.x() + (5 * fifteenth),
rect.y() + (9 * fifteenth)
)
# Middle bottom point
p2 = QtCore.QPoint(
rect.center().x(),
rect.y() + (11 * fifteenth)
)
# Top right point
p3 = QtCore.QPoint(
rect.x() + (10 * fifteenth),
rect.y() + (5 * fifteenth)
)
path = QtGui.QPainterPath(p1)
path.lineTo(p2)
path.lineTo(p3)
stroked_path = icon_path_stroker.createStroke(path)
painter.drawPath(stroked_path)
painter.end()
return image
@classmethod
def get_confirm_icon(cls, width, height):
key = "{}x{}-confirm_image".format(width, height)
icon = cls.cached_icons.get(key)
if icon is None:
image = cls._draw_image(width, height, QtCore.Qt.white)
icon = QtGui.QIcon(image)
cls.cached_icons[key] = icon
return icon
def create_add_btn(parent):
add_btn = QtWidgets.QPushButton("+", parent)
add_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
add_btn.setProperty("btn-type", "tool-item")
add_btn.setFixedSize(BTN_FIXED_SIZE, BTN_FIXED_SIZE)
return add_btn
def create_remove_btn(parent):
remove_btn = QtWidgets.QPushButton("-", parent)
remove_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
remove_btn.setProperty("btn-type", "tool-item")
remove_btn.setFixedSize(BTN_FIXED_SIZE, BTN_FIXED_SIZE)
return remove_btn
def create_confirm_btn(parent):
confirm_btn = QtWidgets.QPushButton(parent)
icon = PaintHelper.get_confirm_icon(
BTN_FIXED_SIZE, BTN_FIXED_SIZE
)
confirm_btn.setIcon(icon)
confirm_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
confirm_btn.setProperty("btn-type", "tool-item")
confirm_btn.setFixedSize(BTN_FIXED_SIZE, BTN_FIXED_SIZE)
return confirm_btn
class ModifiableDictEmptyItem(QtWidgets.QWidget):
def __init__(self, entity_widget, store_as_list, parent):
super(ModifiableDictEmptyItem, self).__init__(parent)
@ -375,7 +294,7 @@ class ModifiableDictItem(QtWidgets.QWidget):
"fa.edit", QtCore.Qt.lightGray, QtCore.Qt.white
)
edit_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
edit_btn.setProperty("btn-type", "tool-item-icon")
edit_btn.setObjectName("SettingsToolIconBtn")
edit_btn.setFixedHeight(BTN_FIXED_SIZE)
confirm_btn = create_confirm_btn(self)

View file

@ -0,0 +1,19 @@
import os
from Qt import QtGui
def get_image_path(image_filename):
return os.path.join(
os.path.dirname(os.path.abspath(__file__)),
image_filename
)
def get_image(image_filename):
image_path = get_image_path(image_filename)
return QtGui.QImage(image_path)
def get_pixmap(image_filename):
image_path = get_image_path(image_filename)
return QtGui.QPixmap(image_path)

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 820 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

View file

@ -7,8 +7,8 @@ from .widgets import (
NumberSpinBox,
GridLabelWidget,
SettingsComboBox,
NiceCheckbox,
SettingsPlainTextEdit,
SettingsNiceCheckbox,
SettingsLineEdit
)
from .multiselection_combobox import MultiSelectionComboBox
@ -21,6 +21,7 @@ from .base import (
BaseWidget,
InputWidget
)
from openpype.widgets.sliders import NiceSlider
from openpype.tools.settings import CHILD_OFFSET
@ -129,6 +130,7 @@ class DictImmutableKeysWidget(BaseWidget):
content_widget.setProperty("show_borders", show_borders)
label_widget = QtWidgets.QLabel(self.entity.label)
label_widget.setObjectName("SettingsLabel")
content_layout = QtWidgets.QGridLayout(content_widget)
content_layout.setContentsMargins(5, 5, 5, 5)
@ -324,12 +326,7 @@ class DictImmutableKeysWidget(BaseWidget):
class BoolWidget(InputWidget):
def _add_inputs_to_layout(self):
checkbox_height = self.style().pixelMetric(
QtWidgets.QStyle.PM_IndicatorHeight
)
self.input_field = NiceCheckbox(
height=checkbox_height, parent=self.content_widget
)
self.input_field = SettingsNiceCheckbox(parent=self.content_widget)
self.content_layout.addWidget(self.input_field, 0)
self.content_layout.addStretch(1)
@ -352,6 +349,9 @@ class BoolWidget(InputWidget):
def _on_value_change(self):
if self.ignore_input_changes:
return
self.start_value_timer()
def _on_value_change_timer(self):
self.entity.set(self.input_field.isChecked())

View file

@ -1,5 +1,7 @@
from Qt import QtCore
from .widgets import SettingsToolBtn
# Offset of value change trigger in ms
VALUE_CHANGE_OFFSET_MS = 300
@ -16,3 +18,33 @@ def create_deffered_value_change_timer(callback):
timer.setInterval(VALUE_CHANGE_OFFSET_MS)
timer.timeout.connect(callback)
return timer
def create_add_btn(parent):
add_btn = SettingsToolBtn("add", parent)
add_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
return add_btn
def create_remove_btn(parent):
remove_btn = SettingsToolBtn("remove", parent)
remove_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
return remove_btn
def create_up_btn(parent):
remove_btn = SettingsToolBtn("up", parent)
remove_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
return remove_btn
def create_down_btn(parent):
add_btn = SettingsToolBtn("down", parent)
add_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
return add_btn
def create_confirm_btn(parent):
remove_btn = SettingsToolBtn("confirm", parent)
remove_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
return remove_btn

View file

@ -1,13 +1,17 @@
from Qt import QtWidgets, QtCore
from .base import InputWidget
from .widgets import ExpandingWidget
from openpype.tools.settings import (
BTN_FIXED_SIZE,
CHILD_OFFSET
)
from avalon.vendor import qtawesome
from .base import InputWidget
from .widgets import ExpandingWidget
from .lib import (
create_add_btn,
create_remove_btn,
create_up_btn,
create_down_btn
)
class EmptyListItem(QtWidgets.QWidget):
@ -16,18 +20,11 @@ class EmptyListItem(QtWidgets.QWidget):
self.entity_widget = entity_widget
add_btn = QtWidgets.QPushButton("+", self)
remove_btn = QtWidgets.QPushButton("-", self)
add_btn = create_add_btn(self)
remove_btn = create_remove_btn(self)
add_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
remove_btn.setEnabled(False)
add_btn.setFixedSize(BTN_FIXED_SIZE, BTN_FIXED_SIZE)
remove_btn.setFixedSize(BTN_FIXED_SIZE, BTN_FIXED_SIZE)
add_btn.setProperty("btn-type", "tool-item")
remove_btn.setProperty("btn-type", "tool-item")
layout = QtWidgets.QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(3)
@ -52,32 +49,10 @@ class ListItem(QtWidgets.QWidget):
self.ignore_input_changes = entity_widget.ignore_input_changes
char_up = qtawesome.charmap("fa.angle-up")
char_down = qtawesome.charmap("fa.angle-down")
add_btn = QtWidgets.QPushButton("+")
remove_btn = QtWidgets.QPushButton("-")
up_btn = QtWidgets.QPushButton(char_up)
down_btn = QtWidgets.QPushButton(char_down)
font_up_down = qtawesome.font("fa", 13)
up_btn.setFont(font_up_down)
down_btn.setFont(font_up_down)
add_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
remove_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
up_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
down_btn.setFocusPolicy(QtCore.Qt.ClickFocus)
add_btn.setFixedSize(BTN_FIXED_SIZE, BTN_FIXED_SIZE)
remove_btn.setFixedSize(BTN_FIXED_SIZE, BTN_FIXED_SIZE)
up_btn.setFixedSize(BTN_FIXED_SIZE, BTN_FIXED_SIZE)
down_btn.setFixedSize(BTN_FIXED_SIZE, BTN_FIXED_SIZE)
add_btn.setProperty("btn-type", "tool-item")
remove_btn.setProperty("btn-type", "tool-item")
up_btn.setProperty("btn-type", "tool-item")
down_btn.setProperty("btn-type", "tool-item")
add_btn = create_add_btn(self)
remove_btn = create_remove_btn(self)
up_btn = create_up_btn(self)
down_btn = create_down_btn(self)
add_btn.clicked.connect(self._on_add_clicked)
remove_btn.clicked.connect(self._on_remove_clicked)

View file

@ -1,13 +0,0 @@
import os
from openpype import resources
def load_stylesheet():
style_path = os.path.join(os.path.dirname(__file__), "style.css")
with open(style_path, "r") as style_file:
stylesheet = style_file.read()
return stylesheet
def app_icon_path():
return resources.get_openpype_icon_filepath()

View file

@ -1,453 +0,0 @@
/* :root {
--border-color-: #464b54;
}
*/
QWidget {
color: #bfccd6;
background-color: #282C34;
font-size: 12px;
border-radius: 0px;
}
QMenu {
border: 1px solid #555555;
background-color: #21252B;
}
QMenu::item {
padding: 5px 10px 5px 10px;
border-left: 5px solid #313131;
}
QMenu::item:selected {
border-left-color: #61839e;
background-color: #222d37;
}
QCheckBox {
spacing: 0px;
}
QCheckBox::indicator {}
QCheckBox::indicator:focus {}
QLineEdit, QSpinBox, QDoubleSpinBox, QPlainTextEdit, QTextEdit {
border: 1px solid #464b54;
border-radius: 3px;
background-color: #21252B;
}
QLineEdit:disabled, QSpinBox:disabled, QDoubleSpinBox:disabled, QPlainTextEdit:disabled, QTextEdit:disabled, QPushButton:disabled {
background-color: #464b54;
}
QLineEdit:focus, QSpinBox:focus, QDoubleSpinBox:focus, QPlainTextEdit:focus, QTextEdit:focus {
border: 1px solid #839caf;
}
QComboBox {
border: 1px solid #464b54;
border-radius: 3px;
padding: 2px 2px 4px 4px;
background: #21252B;
}
QComboBox QAbstractItemView::item {
padding: 3px;
}
QToolButton {
background: transparent;
}
QLabel {
background: transparent;
color: #969b9e;
}
QLabel:hover {color: #b8c1c5;}
QLabel[state="studio"] {color: #73C990;}
QLabel[state="studio"]:hover {color: #ffffff;}
QLabel[state="modified"] {color: #189aea;}
QLabel[state="modified"]:hover {color: #46b1f3;}
QLabel[state="overriden-modified"] {color: #189aea;}
QLabel[state="overriden-modified"]:hover {color: #46b1f3;}
QLabel[state="overriden"] {color: #ff8c1a;}
QLabel[state="overriden"]:hover {color: #ffa64d;}
QLabel[state="invalid"] {color: #ad2e2e;}
QLabel[state="invalid"]:hover {color: #ad2e2e;}
QWidget[input-state="studio"] {border-color: #858a94;}
QWidget[input-state="modified"] {border-color: #189aea;}
QWidget[input-state="overriden-modified"] {border-color: #189aea;}
QWidget[input-state="overriden"] {border-color: #ff8c1a;}
QWidget[input-state="invalid"] {border-color: #ad2e2e;}
QPushButton {
border: 1px solid #aaaaaa;
border-radius: 3px;
padding: 5px;
}
QPushButton:hover {
background-color: #333840;
border: 1px solid #fff;
color: #fff;
}
QPushButton[btn-type="tool-item"] {
border: 1px solid #bfccd6;
border-radius: 10px;
}
QPushButton[btn-type="tool-item"]:hover {
border-color: #189aea;
color: #46b1f3;
background-color: transparent;
}
QPushButton[btn-type="tool-item-icon"] {
border: 0px solid #bfccd6;
background-color: transparent;
}
QPushButton[btn-type="expand-toggle"] {
background: #21252B;
}
/* SLider */
QSlider::groove {
border: 1px solid #464b54;
border-radius: 0.3em;
}
QSlider::groove:horizontal {
height: 8px;
}
QSlider::groove:vertical {
width: 8px;
}
QSlider::handle {
width: 10px;
height: 10px;
border-radius: 5px;
}
QSlider::handle:horizontal {
margin: -2px 0;
}
QSlider::handle:vertical {
margin: 0 -2px;
}
#GroupWidget {
border-bottom: 1px solid #21252B;
}
#ProjectListWidget QListView {
border: 1px solid #464b54;
background: #21252B;
}
#ProjectListWidget QListView:disabled {
background: #282C34;
}
#ProjectListWidget QListView::item:disabled {
color: #4e5254;
}
#ProjectListWidget QLabel {
background: transparent;
font-weight: bold;
}
#MultiSelectionComboBox {
font-size: 12px;
}
#DictKey[state="studio"] {border-color: #464b54;}
#DictKey[state="modified"] {border-color: #189aea;}
#DictKey[state="overriden"] {border-color: #00f;}
#DictKey[state="overriden-modified"] {border-color: #0f0;}
#DictKey[state="invalid"] {border-color: #ad2e2e;}
#DictLabel {
font-weight: bold;
}
#ContentWidget {
background-color: transparent;
}
#ContentWidget[content_state="hightlighted"] {
background-color: rgba(19, 26, 32, 15%);
}
#SideLineWidget {
background-color: #333942;
border-style: solid;
border-color: #4e5254;
border-left-width: 3px;
border-bottom-width: 0px;
border-right-width: 0px;
border-top-width: 0px;
}
#SideLineWidget:hover {
border-color: #7d8386;
}
#SideLineWidget[state="child-studio"] {border-color: #56a06f;}
#SideLineWidget[state="child-studio"]:hover {border-color: #73C990;}
#SideLineWidget[state="child-modified"] {border-color: #106aa2;}
#SideLineWidget[state="child-modified"]:hover {border-color: #189aea;}
#SideLineWidget[state="child-invalid"] {border-color: #ad2e2e;}
#SideLineWidget[state="child-invalid"]:hover {border-color: #c93636;}
#SideLineWidget[state="child-overriden"] {border-color: #e67300;}
#SideLineWidget[state="child-overriden"]:hover {border-color: #ff8c1a;}
#SideLineWidget[state="child-overriden-modified"] {border-color: #106aa2;}
#SideLineWidget[state="child-overriden-modified"]:hover {border-color: #189aea;}
#MainWidget {
background: #141a1f;
}
#DictAsWidgetBody {
background: transparent;
}
#DictAsWidgetBody[show_borders="1"] {
border: 1px solid #4e5254;
border-radius: 5px;
}
#SplitterItem {
background-color: #21252B;
}
#ShadowWidget {
font-size: 36pt;
}
QTabWidget::pane {
border-top-style: none;
}
QTabBar {
background: transparent;
}
QTabBar::tab {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
padding: 5px;
}
QTabBar::tab:selected {
background: #282C34;
border-color: #9B9B9B;
border-bottom-color: #C2C7CB;
}
QTabBar::tab:!selected {
margin-top: 2px;
background: #21252B;
}
QTabBar::tab:!selected:hover {
background: #333840;
}
QTabBar::tab:first:selected {
margin-left: 0;
}
QTabBar::tab:last:selected {
margin-right: 0;
}
QTabBar::tab:only-one {
margin: 0;
}
QScrollBar:horizontal {
height: 15px;
margin: 3px 15px 3px 15px;
border: 1px transparent #21252B;
border-radius: 4px;
background-color: #21252B;
}
QScrollBar::handle:horizontal {
background-color: #4B5362;
min-width: 5px;
border-radius: 4px;
}
QScrollBar::add-line:horizontal {
margin: 0px 3px 0px 3px;
border-image: url(:/qss_icons/rc/right_arrow_disabled.png);
width: 10px;
height: 10px;
subcontrol-position: right;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal {
margin: 0px 3px 0px 3px;
border-image: url(:/qss_icons/rc/left_arrow_disabled.png);
height: 10px;
width: 10px;
subcontrol-position: left;
subcontrol-origin: margin;
}
QScrollBar::add-line:horizontal:hover,QScrollBar::add-line:horizontal:on {
border-image: url(:/qss_icons/rc/right_arrow.png);
height: 10px;
width: 10px;
subcontrol-position: right;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on {
border-image: url(:/qss_icons/rc/left_arrow.png);
height: 10px;
width: 10px;
subcontrol-position: left;
subcontrol-origin: margin;
}
QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal {
background: none;
}
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
background: none;
}
QScrollBar:vertical {
background-color: #21252B;
width: 15px;
margin: 15px 3px 15px 3px;
border: 1px transparent #21252B;
border-radius: 4px;
}
QScrollBar::handle:vertical {
background-color: #4B5362;
min-height: 5px;
border-radius: 4px;
}
QScrollBar::sub-line:vertical {
margin: 3px 0px 3px 0px;
border-image: url(:/qss_icons/rc/up_arrow_disabled.png);
height: 10px;
width: 10px;
subcontrol-position: top;
subcontrol-origin: margin;
}
QScrollBar::add-line:vertical {
margin: 3px 0px 3px 0px;
border-image: url(:/qss_icons/rc/down_arrow_disabled.png);
height: 10px;
width: 10px;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on {
border-image: url(:/qss_icons/rc/up_arrow.png);
height: 10px;
width: 10px;
subcontrol-position: top;
subcontrol-origin: margin;
}
QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on {
border-image: url(:/qss_icons/rc/down_arrow.png);
height: 10px;
width: 10px;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical {
background: none;
}
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
background: none;
}
QTableView
{
border: 1px solid #444;
gridline-color: #6c6c6c;
background-color: #201F1F;
alternate-background-color:#21252B;
}
QHeaderView
{
border: 1px transparent;
border-radius: 2px;
margin: 0px;
padding: 0px;
}
QHeaderView::section {
background-color: #21252B;
/*color: silver;*/
padding: 4px;
border: 1px solid #6c6c6c;
border-radius: 0px;
text-align: center;
color: #969b9e;
font-weight: bold;
}
QAbstractItemView::item:pressed {
background: #78879b;
color: #FFFFFF;
}
QAbstractItemView::item:selected:active {
background: #3d8ec9;
}
QAbstractItemView::item:selected:!active {
background: #3d8ec9;
}
#BreadcrumbsPathInput {
padding: 2px;
font-size: 9pt;
}
#BreadcrumbsButton {
padding-right: 12px;
font-size: 9pt;
}
#BreadcrumbsButton[empty="1"] {
padding-right: 0px;
}
#BreadcrumbsButton::menu-button {
width: 12px;
background: rgba(127, 127, 127, 60);
}
#BreadcrumbsButton::menu-button:hover {
background: rgba(127, 127, 127, 90);
}
#BreadcrumbsPanel {
border: 1px solid #4e5254;
border-radius: 5px;
background: #21252B;;
}

View file

@ -6,7 +6,16 @@ from avalon.mongodb import (
AvalonMongoDB
)
from openpype.style import get_objected_colors
from openpype.tools.utils.widgets import ImageButton
from openpype.tools.utils.lib import paint_image_with_color
from openpype.widgets.nice_checkbox import NiceCheckbox
from openpype.settings.lib import get_system_settings
from .images import (
get_pixmap,
get_image
)
from .constants import (
DEFAULT_PROJECT_LABEL,
PROJECT_NAME_ROLE,
@ -31,6 +40,78 @@ class SettingsPlainTextEdit(QtWidgets.QPlainTextEdit):
self.focused_in.emit()
class SettingsToolBtn(ImageButton):
_mask_pixmap = None
_cached_icons = {}
def __init__(self, btn_type, parent):
super(SettingsToolBtn, self).__init__(parent)
icon, hover_icon = self._get_icon_type(btn_type)
self.setIcon(icon)
self._icon = icon
self._hover_icon = hover_icon
@classmethod
def _get_icon_type(cls, btn_type):
if btn_type not in cls._cached_icons:
settings_colors = get_objected_colors()["settings"]
normal_color = settings_colors["image-btn"].get_qcolor()
hover_color = settings_colors["image-btn-hover"].get_qcolor()
disabled_color = settings_colors["image-btn-disabled"].get_qcolor()
image = get_image("{}.png".format(btn_type))
pixmap = paint_image_with_color(image, normal_color)
hover_pixmap = paint_image_with_color(image, hover_color)
disabled_pixmap = paint_image_with_color(image, disabled_color)
icon = QtGui.QIcon(pixmap)
hover_icon = QtGui.QIcon(hover_pixmap)
icon.addPixmap(
disabled_pixmap, QtGui.QIcon.Disabled, QtGui.QIcon.On
)
icon.addPixmap(
disabled_pixmap, QtGui.QIcon.Disabled, QtGui.QIcon.Off
)
hover_icon.addPixmap(
disabled_pixmap, QtGui.QIcon.Disabled, QtGui.QIcon.On
)
hover_icon.addPixmap(
disabled_pixmap, QtGui.QIcon.Disabled, QtGui.QIcon.Off
)
cls._cached_icons[btn_type] = icon, hover_icon
return cls._cached_icons[btn_type]
def enterEvent(self, event):
self.setIcon(self._hover_icon)
super(SettingsToolBtn, self).enterEvent(event)
def leaveEvent(self, event):
self.setIcon(self._icon)
super(SettingsToolBtn, self).leaveEvent(event)
@classmethod
def _get_mask_pixmap(cls):
if cls._mask_pixmap is None:
mask_pixmap = get_pixmap("mask.png")
cls._mask_pixmap = mask_pixmap
return cls._mask_pixmap
def _change_size(self):
super(SettingsToolBtn, self)._change_size()
size = self.iconSize()
scaled = self._get_mask_pixmap().scaled(
size.width(),
size.height(),
QtCore.Qt.IgnoreAspectRatio,
QtCore.Qt.SmoothTransformation
)
self.setMask(scaled.mask())
class ShadowWidget(QtWidgets.QWidget):
def __init__(self, message, parent):
super(ShadowWidget, self).__init__(parent)
@ -132,9 +213,14 @@ class SettingsComboBox(QtWidgets.QComboBox):
def __init__(self, *args, **kwargs):
super(SettingsComboBox, self).__init__(*args, **kwargs)
delegate = QtWidgets.QStyledItemDelegate()
self.setItemDelegate(delegate)
self.currentIndexChanged.connect(self._on_change)
self.setFocusPolicy(QtCore.Qt.StrongFocus)
self._delegate = delegate
def wheelEvent(self, event):
if self.hasFocus():
return super(SettingsComboBox, self).wheelEvent(event)
@ -180,14 +266,14 @@ class ExpandingWidget(QtWidgets.QWidget):
button_size = QtCore.QSize(5, 5)
button_toggle = QtWidgets.QToolButton(parent=side_line_widget)
button_toggle.setProperty("btn-type", "expand-toggle")
button_toggle.setObjectName("ExpandToggleBtn")
button_toggle.setIconSize(button_size)
button_toggle.setArrowType(QtCore.Qt.RightArrow)
button_toggle.setCheckable(True)
button_toggle.setChecked(False)
label_widget = QtWidgets.QLabel(label, parent=side_line_widget)
label_widget.setObjectName("DictLabel")
label_widget.setObjectName("ExpandLabel")
before_label_widget = QtWidgets.QWidget(side_line_widget)
before_label_layout = QtWidgets.QHBoxLayout(before_label_widget)
@ -381,6 +467,7 @@ class GridLabelWidget(QtWidgets.QWidget):
self.properties = {}
label_widget = QtWidgets.QLabel(label, self)
label_widget.setObjectName("SettingsLabel")
label_proxy_layout = QtWidgets.QHBoxLayout()
label_proxy_layout.setContentsMargins(0, 0, 0, 0)
@ -415,197 +502,12 @@ class GridLabelWidget(QtWidgets.QWidget):
return super(GridLabelWidget, self).mouseReleaseEvent(event)
class NiceCheckboxMoveWidget(QtWidgets.QFrame):
def __init__(self, height, border_width, parent):
super(NiceCheckboxMoveWidget, self).__init__(parent=parent)
self.checkstate = False
self.half_size = int(height / 2)
self.full_size = self.half_size * 2
self.border_width = border_width
self.setFixedHeight(self.full_size)
self.setFixedWidth(self.full_size)
self.setStyleSheet((
"background: #444444;border-style: none;"
"border-radius: {};border-width:{}px;"
).format(self.half_size, self.border_width))
def update_position(self):
parent_rect = self.parent().rect()
if self.checkstate is True:
pos_x = (
parent_rect.x()
+ parent_rect.width()
- self.full_size
- self.border_width
)
else:
pos_x = parent_rect.x() + self.border_width
pos_y = parent_rect.y() + int(
parent_rect.height() / 2 - self.half_size
)
self.setGeometry(pos_x, pos_y, self.width(), self.height())
def state_offset(self):
diff_x = (
self.parent().rect().width()
- self.full_size
- (2 * self.border_width)
)
return QtCore.QPoint(diff_x, 0)
def change_position(self, checkstate):
self.checkstate = checkstate
self.update_position()
def resizeEvent(self, event):
super().resizeEvent(event)
self.update_position()
class NiceCheckbox(QtWidgets.QFrame):
stateChanged = QtCore.Signal(int)
checked_bg_color = QtGui.QColor(69, 128, 86)
unchecked_bg_color = QtGui.QColor(170, 80, 80)
class SettingsNiceCheckbox(NiceCheckbox):
focused_in = QtCore.Signal()
def set_bg_color(self, color):
self._bg_color = color
self.setStyleSheet(self._stylesheet_template.format(
color.red(), color.green(), color.blue()
))
def bg_color(self):
return self._bg_color
bgcolor = QtCore.Property(QtGui.QColor, bg_color, set_bg_color)
def __init__(self, checked=True, height=30, *args, **kwargs):
super(NiceCheckbox, self).__init__(*args, **kwargs)
self._checkstate = checked
if checked:
bg_color = self.checked_bg_color
else:
bg_color = self.unchecked_bg_color
self.half_height = int(height / 2)
height = self.half_height * 2
tenth_height = int(height / 10)
self.setFixedHeight(height)
self.setFixedWidth((height - tenth_height) * 2)
move_item_size = height - (2 * tenth_height)
self.move_item = NiceCheckboxMoveWidget(
move_item_size, tenth_height, self
)
self.move_item.change_position(self._checkstate)
self._stylesheet_template = (
"border-radius: {}px;"
"border-width: {}px;"
"background: #333333;"
"border-style: solid;"
"border-color: #555555;"
).format(self.half_height, tenth_height)
self._stylesheet_template += "background: rgb({},{},{});"
self.set_bg_color(bg_color)
def resizeEvent(self, event):
super(NiceCheckbox, self).resizeEvent(event)
self.move_item.update_position()
def show(self, *args, **kwargs):
super(NiceCheckbox, self).show(*args, **kwargs)
self.move_item.update_position()
def checkState(self):
if self._checkstate:
return QtCore.Qt.Checked
else:
return QtCore.Qt.Unchecked
def _on_checkstate_change(self):
self.stateChanged.emit(self.checkState())
move_start_value = self.move_item.pos()
offset = self.move_item.state_offset()
if self._checkstate is True:
move_end_value = move_start_value + offset
else:
move_end_value = move_start_value - offset
move_animation = QtCore.QPropertyAnimation(
self.move_item, b"pos", self
)
move_animation.setDuration(150)
move_animation.setEasingCurve(QtCore.QEasingCurve.OutQuad)
move_animation.setStartValue(move_start_value)
move_animation.setEndValue(move_end_value)
color_animation = QtCore.QPropertyAnimation(
self, b"bgcolor"
)
color_animation.setDuration(150)
if self._checkstate is True:
color_animation.setStartValue(self.unchecked_bg_color)
color_animation.setEndValue(self.checked_bg_color)
else:
color_animation.setStartValue(self.checked_bg_color)
color_animation.setEndValue(self.unchecked_bg_color)
anim_group = QtCore.QParallelAnimationGroup(self)
anim_group.addAnimation(move_animation)
anim_group.addAnimation(color_animation)
def _finished():
self.move_item.change_position(self._checkstate)
anim_group.finished.connect(_finished)
anim_group.start()
def isChecked(self):
return self._checkstate
def setChecked(self, checked):
if checked == self._checkstate:
return
self._checkstate = checked
self._on_checkstate_change()
def setCheckState(self, state=None):
if state is None:
checkstate = not self._checkstate
elif state == QtCore.Qt.Checked:
checkstate = True
elif state == QtCore.Qt.Unchecked:
checkstate = False
else:
return
if checkstate == self._checkstate:
return
self._checkstate = checkstate
self._on_checkstate_change()
def mousePressEvent(self, event):
self.focused_in.emit()
super(NiceCheckbox, self).mousePressEvent(event)
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.setCheckState()
event.accept()
return
return super(NiceCheckbox, self).mouseReleaseEvent(event)
super(SettingsNiceCheckbox, self).mousePressEvent(event)
class ProjectModel(QtGui.QStandardItemModel):

View file

@ -5,7 +5,7 @@ from .categories import (
ProjectWidget
)
from .widgets import ShadowWidget, RestartDialog
from . import style
from openpype import style
from openpype.lib import is_admin_password_required
from openpype.widgets import PasswordDialog
@ -25,7 +25,7 @@ class MainWidget(QtWidgets.QWidget):
self._password_dialog = None
self.setObjectName("MainWidget")
self.setObjectName("SettingsMainWidget")
self.setWindowTitle("OpenPype Settings")
self.resize(self.widget_width, self.widget_height)

View file

@ -25,6 +25,34 @@ def center_window(window):
window.move(geo.topLeft())
def paint_image_with_color(image, color):
"""Redraw image with single color using it's alpha.
It is expected that input image is singlecolor image with alpha.
Args:
image (QImage): Loaded image with alpha.
color (QColor): Color that will be used to paint image.
"""
width = image.width()
height = image.height()
alpha_mask = image.createAlphaMask()
alpha_region = QtGui.QRegion(QtGui.QBitmap.fromImage(alpha_mask))
pixmap = QtGui.QPixmap(width, height)
pixmap.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(pixmap)
painter.setClipRegion(alpha_region)
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(color)
painter.drawRect(QtCore.QRect(0, 0, width, height))
painter.end()
return pixmap
def format_version(value, hero_version=False):
"""Formats integer to displayable version name"""
label = "v{0:03d}".format(value)

View file

@ -30,6 +30,32 @@ class PlaceholderLineEdit(QtWidgets.QLineEdit):
self.setPalette(filter_palette)
class ImageButton(QtWidgets.QPushButton):
"""PushButton with icon and size of font.
Using font metrics height as icon size reference.
TODO:
- handle changes of screen (different resolution)
"""
def __init__(self, *args, **kwargs):
super(ImageButton, self).__init__(*args, **kwargs)
self.setObjectName("ImageButton")
def _change_size(self):
font_height = self.fontMetrics().height()
self.setIconSize(QtCore.QSize(font_height, font_height))
def showEvent(self, event):
super(ImageButton, self).showEvent(event)
self._change_size()
def sizeHint(self):
return self.iconSize()
class OptionalMenu(QtWidgets.QMenu):
"""A subclass of `QtWidgets.QMenu` to work with `OptionalAction`

View file

@ -1,11 +1,18 @@
from math import floor, sqrt, ceil
from Qt import QtWidgets, QtCore, QtGui
from openpype.style import get_objected_colors
class NiceCheckbox(QtWidgets.QFrame):
stateChanged = QtCore.Signal(int)
clicked = QtCore.Signal()
_checked_bg_color = None
_unchecked_bg_color = None
_checker_color = None
_checker_hover_color = None
def __init__(self, checked=False, draw_icons=False, parent=None):
super(NiceCheckbox, self).__init__(parent)
@ -41,12 +48,6 @@ class NiceCheckbox(QtWidgets.QFrame):
self._pressed = False
self._under_mouse = False
self.checked_bg_color = QtGui.QColor(67, 181, 129)
self.unchecked_bg_color = QtGui.QColor(79, 79, 79)
self.checker_checked_color = QtGui.QColor(255, 255, 255)
self.checker_unchecked_color = self.checker_checked_color
self.icon_scale_factor = sqrt(2) / 2
icon_path_stroker = QtGui.QPainterPathStroker()
@ -58,6 +59,37 @@ class NiceCheckbox(QtWidgets.QFrame):
self._animation_timer.timeout.connect(self._on_animation_timeout)
self._base_size = QtCore.QSize(90, 50)
self._load_colors()
@classmethod
def _load_colors(cls):
if cls._checked_bg_color is not None:
return
colors_data = get_objected_colors()
colors_info = colors_data["nice-checkbox"]
cls._checked_bg_color = colors_info["bg-checked"].get_qcolor()
cls._unchecked_bg_color = colors_info["bg-unchecked"].get_qcolor()
cls._checker_color = colors_info["bg-checker"].get_qcolor()
cls._checker_hover_color = colors_info["bg-checker-hover"].get_qcolor()
@property
def checked_bg_color(self):
return self._checked_bg_color
@property
def unchecked_bg_color(self):
return self._unchecked_bg_color
@property
def checker_color(self):
return self._checker_color
@property
def checker_hover_color(self):
return self._checker_hover_color
def setTristate(self, tristate=True):
if self._is_tristate != tristate:
@ -73,15 +105,6 @@ class NiceCheckbox(QtWidgets.QFrame):
self._draw_icons = draw_icons
self.repaint()
def _checkbox_size_hint(self):
checkbox_height = self.style().pixelMetric(
QtWidgets.QStyle.PM_IndicatorHeight
)
checkbox_height += checkbox_height % 2
width = (2 * checkbox_height) - (checkbox_height / 5)
new_size = QtCore.QSize(width, checkbox_height)
return new_size
def sizeHint(self):
height = self.fontMetrics().height()
width = self.get_width_hint_by_height(height)
@ -159,7 +182,7 @@ class NiceCheckbox(QtWidgets.QFrame):
if self._animation_timer.isActive():
self._animation_timer.stop()
if self.isEnabled():
if self.isVisible() and self.isEnabled():
# Start animation
self._animation_timer.start(self._animation_timeout)
else:
@ -235,14 +258,16 @@ class NiceCheckbox(QtWidgets.QFrame):
def _on_animation_timeout(self):
if self._checkstate == QtCore.Qt.Checked:
self._current_step += 1
if self._current_step == self._steps:
self._animation_timer.stop()
return
self._current_step += 1
elif self._checkstate == QtCore.Qt.Unchecked:
self._current_step -= 1
if self._current_step == 0:
self._animation_timer.stop()
return
self._current_step -= 1
else:
if self._current_step < self._middle_step:
@ -291,11 +316,9 @@ class NiceCheckbox(QtWidgets.QFrame):
# Draw inner background
if self._current_step == self._steps:
bg_color = self.checked_bg_color
checker_color = self.checker_checked_color
elif self._current_step == 0:
bg_color = self.unchecked_bg_color
checker_color = self.checker_unchecked_color
else:
offset_ratio = self._current_step / self._steps
@ -305,11 +328,6 @@ class NiceCheckbox(QtWidgets.QFrame):
self.unchecked_bg_color,
offset_ratio
)
checker_color = self.steped_color(
self.checker_checked_color,
self.checker_unchecked_color,
offset_ratio
)
margins_ratio = self._checker_margins_divider
if margins_ratio > 0:
@ -359,52 +377,14 @@ class NiceCheckbox(QtWidgets.QFrame):
checker_rect = QtCore.QRect(pos_x, pos_y, checker_size, checker_size)
under_mouse = self.isEnabled() and self._under_mouse
shadow_x = checker_rect.x()
shadow_y = checker_rect.y() + margin_size_c
shadow_size = min(
frame_rect.right() - shadow_x,
frame_rect.bottom() - shadow_y,
checker_size + (2 * margin_size_c)
)
shadow_rect = QtCore.QRect(
checker_rect.x(),
shadow_y,
shadow_size,
shadow_size
)
shadow_brush = QtGui.QRadialGradient(
shadow_rect.center(),
shadow_rect.height() / 2
)
shadow_brush.setColorAt(0.6, QtCore.Qt.black)
shadow_brush.setColorAt(1, QtCore.Qt.transparent)
painter.setPen(QtCore.Qt.transparent)
painter.setBrush(shadow_brush)
painter.drawEllipse(shadow_rect)
if under_mouse:
checker_color = self.checker_hover_color
else:
checker_color = self.checker_color
painter.setBrush(checker_color)
painter.drawEllipse(checker_rect)
if under_mouse:
adjust = margin_size_c
if adjust < 1 and checker_rect.height() > 4:
adjust = 1
smaller_checker_rect = checker_rect.adjusted(
adjust, adjust, -adjust, -adjust
)
gradient = QtGui.QLinearGradient(
smaller_checker_rect.bottomRight(),
smaller_checker_rect.topLeft()
)
gradient.setColorAt(0, checker_color)
gradient.setColorAt(1, checker_color.darker(155))
painter.setBrush(gradient)
painter.drawEllipse(smaller_checker_rect)
if self._draw_icons:
painter.setBrush(bg_color)
icon_path = self._get_icon_path(painter, checker_rect)