mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #861 from pypeclub/feature/settings_shadow_widget
Settings shadow widget when working
This commit is contained in:
commit
4a952d0225
7 changed files with 204 additions and 14 deletions
|
|
@ -45,8 +45,16 @@ class SettingsAction(PypeModule, ITrayAction):
|
|||
if not self.settings_window:
|
||||
raise AssertionError("Window is not initialized.")
|
||||
|
||||
# Store if was visible
|
||||
was_visible = self.settings_window.isVisible()
|
||||
|
||||
# Show settings gui
|
||||
self.settings_window.show()
|
||||
|
||||
# Pull window to the front.
|
||||
self.settings_window.raise_()
|
||||
self.settings_window.activateWindow()
|
||||
|
||||
# Reset content if was not visible
|
||||
if not was_visible:
|
||||
self.settings_window.reset()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ def main(user_role=None):
|
|||
|
||||
widget = MainWidget(user_role)
|
||||
widget.show()
|
||||
widget.reset()
|
||||
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
|
|
|||
|
|
@ -193,6 +193,9 @@ QPushButton[btn-type="expand-toggle"] {
|
|||
background-color: #21252B;
|
||||
}
|
||||
|
||||
#ShadowWidget {
|
||||
font-size: 36pt;
|
||||
}
|
||||
QTabWidget::pane {
|
||||
border-top-style: none;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
import copy
|
||||
import json
|
||||
from enum import Enum
|
||||
from Qt import QtWidgets, QtCore, QtGui
|
||||
from pype.settings.constants import (
|
||||
SYSTEM_SETTINGS_KEY,
|
||||
|
|
@ -26,27 +27,60 @@ from pype.settings.lib import (
|
|||
save_project_anatomy,
|
||||
|
||||
apply_overrides,
|
||||
get_system_settings,
|
||||
find_environments,
|
||||
DuplicatedEnvGroups
|
||||
)
|
||||
from .widgets import UnsavedChangesDialog
|
||||
from . import lib
|
||||
from avalon import io
|
||||
from avalon.mongodb import (
|
||||
AvalonMongoConnection,
|
||||
AvalonMongoDB
|
||||
)
|
||||
from avalon.vendor import qtawesome
|
||||
|
||||
|
||||
class CategoryState(Enum):
|
||||
Idle = object()
|
||||
Working = object()
|
||||
|
||||
|
||||
class SettingsCategoryWidget(QtWidgets.QWidget):
|
||||
schema_category = None
|
||||
initial_schema_name = None
|
||||
|
||||
state_changed = QtCore.Signal()
|
||||
saved = QtCore.Signal(QtWidgets.QWidget)
|
||||
|
||||
def __init__(self, user_role, parent=None):
|
||||
super(SettingsCategoryWidget, self).__init__(parent)
|
||||
|
||||
self.user_role = user_role
|
||||
|
||||
self._state = CategoryState.Idle
|
||||
|
||||
self.initialize_attributes()
|
||||
self.create_ui()
|
||||
self.reset()
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
return self._state
|
||||
|
||||
@state.setter
|
||||
def state(self, value):
|
||||
self.set_state(value)
|
||||
|
||||
def set_state(self, state):
|
||||
if self._state == state:
|
||||
return
|
||||
|
||||
self._state = state
|
||||
self.state_changed.emit()
|
||||
|
||||
# Process events so emitted signal is processed
|
||||
app = QtWidgets.QApplication.instance()
|
||||
if app:
|
||||
app.processEvents()
|
||||
|
||||
def initialize_attributes(self):
|
||||
self._hide_studio_overrides = False
|
||||
|
|
@ -84,7 +118,9 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
|
|||
scroll_widget.setWidgetResizable(True)
|
||||
scroll_widget.setWidget(content_widget)
|
||||
|
||||
footer_widget = QtWidgets.QWidget()
|
||||
configurations_widget = QtWidgets.QWidget(self)
|
||||
|
||||
footer_widget = QtWidgets.QWidget(configurations_widget)
|
||||
footer_layout = QtWidgets.QHBoxLayout(footer_widget)
|
||||
|
||||
if self.user_role == "developer":
|
||||
|
|
@ -95,7 +131,6 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
|
|||
footer_layout.addWidget(spacer_widget, 1)
|
||||
footer_layout.addWidget(save_btn, 0)
|
||||
|
||||
configurations_widget = QtWidgets.QWidget()
|
||||
configurations_layout = QtWidgets.QVBoxLayout(configurations_widget)
|
||||
configurations_layout.setContentsMargins(0, 0, 0, 0)
|
||||
configurations_layout.setSpacing(0)
|
||||
|
|
@ -186,12 +221,15 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
|
|||
input_field.hierarchical_style_update()
|
||||
|
||||
def reset(self):
|
||||
self.set_state(CategoryState.Working)
|
||||
|
||||
reset_default_settings()
|
||||
|
||||
self.keys.clear()
|
||||
self.input_fields.clear()
|
||||
while self.content_layout.count() != 0:
|
||||
widget = self.content_layout.itemAt(0).widget()
|
||||
widget.setVisible(False)
|
||||
self.content_layout.removeWidget(widget)
|
||||
widget.deleteLater()
|
||||
|
||||
|
|
@ -203,8 +241,11 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
|
|||
|
||||
self.add_children_gui(self.schema)
|
||||
self._update_values()
|
||||
|
||||
self.hierarchical_style_update()
|
||||
|
||||
self.set_state(CategoryState.Idle)
|
||||
|
||||
def items_are_valid(self):
|
||||
has_invalid = False
|
||||
for item in self.input_fields:
|
||||
|
|
@ -232,13 +273,21 @@ class SettingsCategoryWidget(QtWidgets.QWidget):
|
|||
first_invalid_item.setFocus(True)
|
||||
return False
|
||||
|
||||
def on_saved(self, saved_tab_widget):
|
||||
"""Callback on any tab widget save."""
|
||||
return
|
||||
|
||||
def _save(self):
|
||||
if not self.items_are_valid():
|
||||
return
|
||||
self.set_state(CategoryState.Working)
|
||||
|
||||
self.save()
|
||||
if self.items_are_valid():
|
||||
self.save()
|
||||
|
||||
self._update_values()
|
||||
self._update_values()
|
||||
|
||||
self.set_state(CategoryState.Idle)
|
||||
|
||||
self.saved.emit(self)
|
||||
|
||||
def _on_refresh(self):
|
||||
self.reset()
|
||||
|
|
@ -433,7 +482,7 @@ class ProjectListWidget(QtWidgets.QWidget):
|
|||
|
||||
self.project_list = project_list
|
||||
|
||||
self.refresh()
|
||||
self.dbcon = None
|
||||
|
||||
def on_item_clicked(self, new_index):
|
||||
new_project_name = new_index.data(QtCore.Qt.DisplayRole)
|
||||
|
|
@ -501,10 +550,32 @@ class ProjectListWidget(QtWidgets.QWidget):
|
|||
|
||||
model = self.project_list.model()
|
||||
model.clear()
|
||||
|
||||
items = [self.default]
|
||||
io.install()
|
||||
for project_doc in tuple(io.projects()):
|
||||
items.append(project_doc["name"])
|
||||
|
||||
system_settings = get_system_settings()
|
||||
mongo_url = system_settings["modules"]["avalon"]["AVALON_MONGO"]
|
||||
if not mongo_url:
|
||||
mongo_url = os.environ["PYPE_MONGO"]
|
||||
|
||||
# Force uninstall of whole avalon connection if url does not match
|
||||
# to current environment and set it as environment
|
||||
if mongo_url != os.environ["AVALON_MONGO"]:
|
||||
AvalonMongoConnection.uninstall(self.dbcon, force=True)
|
||||
os.environ["AVALON_MONGO"] = mongo_url
|
||||
self.dbcon = None
|
||||
|
||||
if not self.dbcon:
|
||||
try:
|
||||
self.dbcon = AvalonMongoDB()
|
||||
self.dbcon.install()
|
||||
except Exception:
|
||||
self.dbcon = None
|
||||
self.current_project = None
|
||||
|
||||
if self.dbcon:
|
||||
for project_doc in tuple(self.dbcon.projects()):
|
||||
items.append(project_doc["name"])
|
||||
|
||||
for item in items:
|
||||
model.appendRow(QtGui.QStandardItem(item))
|
||||
|
|
@ -527,6 +598,7 @@ class ProjectWidget(SettingsCategoryWidget):
|
|||
|
||||
def ui_tweaks(self):
|
||||
project_list_widget = ProjectListWidget(self)
|
||||
project_list_widget.refresh()
|
||||
|
||||
self.main_layout.insertWidget(0, project_list_widget, 0)
|
||||
|
||||
|
|
@ -541,7 +613,26 @@ class ProjectWidget(SettingsCategoryWidget):
|
|||
# Projects does not have any specific validations
|
||||
return True
|
||||
|
||||
def on_saved(self, saved_tab_widget):
|
||||
"""Callback on any tab widget save.
|
||||
|
||||
Check if AVALON_MONGO is still same.
|
||||
"""
|
||||
if self is saved_tab_widget:
|
||||
return
|
||||
|
||||
system_settings = get_system_settings()
|
||||
mongo_url = system_settings["modules"]["avalon"]["AVALON_MONGO"]
|
||||
if not mongo_url:
|
||||
mongo_url = os.environ["PYPE_MONGO"]
|
||||
|
||||
# If mongo url is not the same as was then refresh projects
|
||||
if mongo_url != os.environ["AVALON_MONGO"]:
|
||||
self.project_list_widget.refresh()
|
||||
|
||||
def _on_project_change(self):
|
||||
self.set_state(CategoryState.Working)
|
||||
|
||||
project_name = self.project_list_widget.project_name()
|
||||
if project_name is None:
|
||||
_project_overrides = lib.NOT_SET
|
||||
|
|
@ -566,6 +657,8 @@ class ProjectWidget(SettingsCategoryWidget):
|
|||
item.apply_overrides(overrides)
|
||||
self.ignore_value_changes = False
|
||||
|
||||
self.set_state(CategoryState.Idle)
|
||||
|
||||
def save(self):
|
||||
data = {}
|
||||
studio_overrides = bool(self.project_name is None)
|
||||
|
|
|
|||
|
|
@ -430,7 +430,7 @@ class SettingObject:
|
|||
return self.mouseReleaseEvent(event)
|
||||
return
|
||||
|
||||
menu = QtWidgets.QMenu()
|
||||
menu = QtWidgets.QMenu(self)
|
||||
|
||||
actions_mapping = {}
|
||||
if self.child_modified:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,48 @@ from Qt import QtWidgets, QtCore, QtGui
|
|||
from avalon.vendor import qtawesome
|
||||
|
||||
|
||||
class ShadowWidget(QtWidgets.QWidget):
|
||||
def __init__(self, message, parent):
|
||||
super(ShadowWidget, self).__init__(parent)
|
||||
self.setObjectName("ShadowWidget")
|
||||
|
||||
self.parent_widget = parent
|
||||
self.message = message
|
||||
|
||||
def wrapper(func):
|
||||
def wrapped(*args, **kwarg):
|
||||
result = func(*args, **kwarg)
|
||||
self._update_geometry()
|
||||
return result
|
||||
return wrapped
|
||||
|
||||
parent.resizeEvent = wrapper(parent.resizeEvent)
|
||||
parent.moveEvent = wrapper(parent.moveEvent)
|
||||
parent.showEvent = wrapper(parent.showEvent)
|
||||
|
||||
def set_message(self, message):
|
||||
self.message = message
|
||||
if self.isVisible():
|
||||
self.repaint()
|
||||
|
||||
def _update_geometry(self):
|
||||
self.setGeometry(self.parent_widget.rect())
|
||||
|
||||
def paintEvent(self, event):
|
||||
painter = QtGui.QPainter(self)
|
||||
painter.setRenderHint(QtGui.QPainter.Antialiasing)
|
||||
painter.fillRect(
|
||||
event.rect(), QtGui.QBrush(QtGui.QColor(0, 0, 0, 127))
|
||||
)
|
||||
if self.message:
|
||||
painter.drawText(
|
||||
event.rect(),
|
||||
QtCore.Qt.AlignCenter | QtCore.Qt.AlignCenter,
|
||||
self.message
|
||||
)
|
||||
painter.end()
|
||||
|
||||
|
||||
class IconButton(QtWidgets.QPushButton):
|
||||
def __init__(self, icon_name, color, hover_color, *args, **kwargs):
|
||||
super(IconButton, self).__init__(*args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from Qt import QtWidgets, QtGui
|
||||
from .base import SystemWidget, ProjectWidget
|
||||
from .base import CategoryState, SystemWidget, ProjectWidget
|
||||
from .widgets import ShadowWidget
|
||||
from .. import style
|
||||
|
||||
|
||||
|
|
@ -22,6 +23,12 @@ class MainWidget(QtWidgets.QWidget):
|
|||
|
||||
studio_widget = SystemWidget(user_role, header_tab_widget)
|
||||
project_widget = ProjectWidget(user_role, header_tab_widget)
|
||||
|
||||
tab_widgets = [
|
||||
studio_widget,
|
||||
project_widget
|
||||
]
|
||||
|
||||
header_tab_widget.addTab(studio_widget, "System")
|
||||
header_tab_widget.addTab(project_widget, "Project")
|
||||
|
||||
|
|
@ -31,3 +38,39 @@ class MainWidget(QtWidgets.QWidget):
|
|||
layout.addWidget(header_tab_widget)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
self._shadow_widget = ShadowWidget("Working...", self)
|
||||
|
||||
for tab_widget in tab_widgets:
|
||||
tab_widget.saved.connect(self._on_tab_save)
|
||||
tab_widget.state_changed.connect(self._on_state_change)
|
||||
|
||||
self.tab_widgets = tab_widgets
|
||||
|
||||
def _on_tab_save(self, source_widget):
|
||||
for tab_widget in self.tab_widgets:
|
||||
tab_widget.on_saved(source_widget)
|
||||
|
||||
def _on_state_change(self):
|
||||
any_working = False
|
||||
for widget in self.tab_widgets:
|
||||
if widget.state is CategoryState.Working:
|
||||
any_working = True
|
||||
break
|
||||
|
||||
if (
|
||||
(any_working and self._shadow_widget.isVisible())
|
||||
or (not any_working and not self._shadow_widget.isVisible())
|
||||
):
|
||||
return
|
||||
|
||||
self._shadow_widget.setVisible(any_working)
|
||||
|
||||
# Process events to apply shadow widget visibility
|
||||
app = QtWidgets.QApplication.instance()
|
||||
if app:
|
||||
app.processEvents()
|
||||
|
||||
def reset(self):
|
||||
for tab_widget in self.tab_widgets:
|
||||
tab_widget.reset()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue