diff --git a/openpype/style/style.css b/openpype/style/style.css index 54e217f3622..c96e87aa022 100644 --- a/openpype/style/style.css +++ b/openpype/style/style.css @@ -1117,19 +1117,19 @@ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { #ExpandLabel[state="invalid"]:hover, #SettingsLabel[state="invalid"]:hover { color: {color:settings:invalid-dark}; } +#SettingsOutdatedSourceVersion { + color: {color:settings:source-version-outdated}; +} #SourceVersionLabel { - border-radius: 0.48em; - padding-left: 3px; - padding-right: 3px; + padding-left: 3px; + padding-right: 3px; } #SourceVersionLabel[state="same"] { - border: 1px solid {color:settings:source-version}; - color: {color:settings:source-version}; + color: {color:settings:source-version}; } #SourceVersionLabel[state="different"] { - border: 1px solid {color:settings:source-version-outdated}; - color: {color:settings:source-version-outdated}; + color: {color:settings:source-version-outdated}; } /* TODO Replace these with explicit widget types if possible */ @@ -1146,8 +1146,8 @@ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { border-color: {color:settings:invalid-dark}; } -#GroupWidget { - border-bottom: 1px solid #21252B; +#SettingsFooter { + border-top: 1px solid #21252B; } #ProjectListWidget QLabel { @@ -1155,6 +1155,10 @@ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { font-weight: bold; } +#ProjectListContentWidget { + background: {color:bg-view}; +} + #MultiSelectionComboBox { font-size: 12px; } diff --git a/openpype/tools/settings/settings/categories.py b/openpype/tools/settings/settings/categories.py index 74f29133f6f..18a9764b34a 100644 --- a/openpype/tools/settings/settings/categories.py +++ b/openpype/tools/settings/settings/categories.py @@ -93,6 +93,20 @@ class SettingsCategoryWidget(QtWidgets.QWidget): restart_required_trigger = QtCore.Signal() full_path_requested = QtCore.Signal(str, str) + require_restart_label_text = ( + "Your changes require restart of" + " all running OpenPype processes to take affect." + ) + outdated_version_label_text = ( + "Your settings are loaded from an older version." + ) + source_version_tooltip = "Using settings of current OpenPype version" + source_version_tooltip_outdated = ( + "Please check that all settings are still correct (blue colour\n" + "indicates potential changes in the new version) and save your\n" + "settings to update them to you current running OpenPype version." + ) + def __init__(self, user_role, parent=None): super(SettingsCategoryWidget, self).__init__(parent) @@ -204,6 +218,7 @@ def create_ui(self): conf_wrapper_widget = QtWidgets.QWidget(self) configurations_widget = QtWidgets.QWidget(conf_wrapper_widget) + # Breadcrumbs/Path widget breadcrumbs_widget = QtWidgets.QWidget(self) breadcrumbs_label = QtWidgets.QLabel("Path:", breadcrumbs_widget) breadcrumbs_bar = BreadcrumbsAddressBar(breadcrumbs_widget) @@ -219,8 +234,8 @@ def create_ui(self): breadcrumbs_layout.addWidget(breadcrumbs_bar, 1) breadcrumbs_layout.addWidget(refresh_btn, 0) + # Widgets representing settings entities scroll_widget = QtWidgets.QScrollArea(configurations_widget) - scroll_widget.setObjectName("GroupWidget") content_widget = QtWidgets.QWidget(scroll_widget) scroll_widget.setWidgetResizable(True) scroll_widget.setWidget(content_widget) @@ -230,28 +245,46 @@ def create_ui(self): content_layout.setSpacing(5) content_layout.setAlignment(QtCore.Qt.AlignTop) - footer_widget = QtWidgets.QWidget(configurations_widget) + # Footer widget + footer_widget = QtWidgets.QWidget(self) + footer_widget.setObjectName("SettingsFooter") + + # Info labels + # TODO dynamic labels + labels_alignment = QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter + empty_label = QtWidgets.QLabel(footer_widget) + + outdated_version_label = QtWidgets.QLabel( + self.outdated_version_label_text, footer_widget + ) + outdated_version_label.setToolTip(self.source_version_tooltip_outdated) + outdated_version_label.setAlignment(labels_alignment) + outdated_version_label.setVisible(False) + outdated_version_label.setObjectName("SettingsOutdatedSourceVersion") + require_restart_label = QtWidgets.QLabel( + self.require_restart_label_text, footer_widget + ) + require_restart_label.setAlignment(labels_alignment) + require_restart_label.setVisible(False) + + # Label showing source version of loaded settings source_version_label = QtWidgets.QLabel("", footer_widget) source_version_label.setObjectName("SourceVersionLabel") set_style_property(source_version_label, "state", "") - source_version_label.setToolTip( - "Version of OpenPype from which are settings loaded." - "\nThe 'legacy' are settings that were not stored per version." - ) + source_version_label.setToolTip(self.source_version_tooltip) save_btn = QtWidgets.QPushButton("Save", footer_widget) - require_restart_label = QtWidgets.QLabel(footer_widget) - require_restart_label.setAlignment(QtCore.Qt.AlignCenter) footer_layout = QtWidgets.QHBoxLayout(footer_widget) footer_layout.setContentsMargins(5, 5, 5, 5) - footer_layout.setSpacing(10) if self.user_role == "developer": self._add_developer_ui(footer_layout, footer_widget) - footer_layout.addWidget(source_version_label, 0) + footer_layout.addWidget(empty_label, 1) + footer_layout.addWidget(outdated_version_label, 1) footer_layout.addWidget(require_restart_label, 1) + footer_layout.addWidget(source_version_label, 0) footer_layout.addWidget(save_btn, 0) configurations_layout = QtWidgets.QVBoxLayout(configurations_widget) @@ -259,7 +292,6 @@ def create_ui(self): configurations_layout.setSpacing(0) configurations_layout.addWidget(scroll_widget, 1) - configurations_layout.addWidget(footer_widget, 0) conf_wrapper_layout = QtWidgets.QHBoxLayout(conf_wrapper_widget) conf_wrapper_layout.setContentsMargins(0, 0, 0, 0) @@ -271,20 +303,29 @@ def create_ui(self): main_layout.setSpacing(0) main_layout.addWidget(breadcrumbs_widget, 0) main_layout.addWidget(conf_wrapper_widget, 1) + main_layout.addWidget(footer_widget, 0) save_btn.clicked.connect(self._save) refresh_btn.clicked.connect(self._on_refresh) breadcrumbs_bar.path_edited.connect(self._on_path_edit) + self._require_restart_label = require_restart_label + self._outdated_version_label = outdated_version_label + self._empty_label = empty_label + + self._is_loaded_version_outdated = False + self.save_btn = save_btn self._source_version_label = source_version_label - self.refresh_btn = refresh_btn - self.require_restart_label = require_restart_label + self.scroll_widget = scroll_widget self.content_layout = content_layout self.content_widget = content_widget self.breadcrumbs_bar = breadcrumbs_bar + self.breadcrumbs_model = None + self.refresh_btn = refresh_btn + self.conf_wrapper_layout = conf_wrapper_layout self.main_layout = main_layout @@ -448,13 +489,7 @@ def _on_reset_start(self): return def _on_require_restart_change(self): - value = "" - if self.entity.require_restart: - value = ( - "Your changes require restart of" - " all running OpenPype processes to take affect." - ) - self.require_restart_label.setText(value) + self._update_labels_visibility() def reset(self): self.set_state(CategoryState.Working) @@ -537,13 +572,22 @@ def reset(self): # Update source version label state_value = "" + tooltip = "" + outdated = False if source_version: if source_version != self._current_version: state_value = "different" + tooltip = self.source_version_tooltip_outdated + outdated = True else: state_value = "same" + tooltip = self.source_version_tooltip + + self._is_loaded_version_outdated = outdated self._source_version_label.setText(source_version) + self._source_version_label.setToolTip(tooltip) set_style_property(self._source_version_label, "state", state_value) + self._update_labels_visibility() self.set_state(CategoryState.Idle) @@ -654,7 +698,29 @@ def _save(self): if require_restart: self.restart_required_trigger.emit() - self.require_restart_label.setText("") + + def _update_labels_visibility(self): + visible_label = None + labels = { + self._empty_label, + self._outdated_version_label, + self._require_restart_label, + } + if self.entity.require_restart: + visible_label = self._require_restart_label + elif self._is_loaded_version_outdated: + visible_label = self._outdated_version_label + else: + visible_label = self._empty_label + + if visible_label.isVisible(): + return + + for label in labels: + if label is visible_label: + visible_label.setVisible(True) + else: + label.setVisible(False) def _on_refresh(self): self.reset() diff --git a/openpype/tools/settings/settings/widgets.py b/openpype/tools/settings/settings/widgets.py index 45b4afe616f..f793aab057c 100644 --- a/openpype/tools/settings/settings/widgets.py +++ b/openpype/tools/settings/settings/widgets.py @@ -1011,7 +1011,10 @@ def __init__(self, parent, only_active=False): super(ProjectListWidget, self).__init__(parent) self.setObjectName("ProjectListWidget") - project_list = ProjectView(self) + content_frame = QtWidgets.QFrame(self) + content_frame.setObjectName("ProjectListContentWidget") + + project_list = ProjectView(content_frame) project_model = ProjectModel(only_active) project_proxy = ProjectSortFilterProxy() @@ -1019,22 +1022,33 @@ def __init__(self, parent, only_active=False): project_proxy.setSourceModel(project_model) project_list.setModel(project_proxy) - layout = QtWidgets.QVBoxLayout(self) - layout.setSpacing(3) - layout.addWidget(project_list, 1) + content_layout = QtWidgets.QVBoxLayout(content_frame) + content_layout.setContentsMargins(0, 0, 0, 0) + content_layout.setSpacing(0) + content_layout.addWidget(project_list, 1) - if only_active: - inactive_chk = None - else: - inactive_chk = QtWidgets.QCheckBox(" Show Inactive Projects ") + inactive_chk = None + if not only_active: + checkbox_wrapper = QtWidgets.QWidget(content_frame) + checkbox_wrapper.setAttribute(QtCore.Qt.WA_TranslucentBackground) + + inactive_chk = QtWidgets.QCheckBox( + "Show Inactive Projects", checkbox_wrapper + ) inactive_chk.setChecked(not project_proxy.is_filter_enabled()) - layout.addSpacing(5) - layout.addWidget(inactive_chk, 0) - layout.addSpacing(5) + wrapper_layout = QtWidgets.QHBoxLayout(checkbox_wrapper) + wrapper_layout.addWidget(inactive_chk, 1) + + content_layout.addWidget(checkbox_wrapper, 0) inactive_chk.stateChanged.connect(self.on_inactive_vis_changed) + layout = QtWidgets.QVBoxLayout(self) + # Margins '3' are matching to configurables widget scroll area on right + layout.setContentsMargins(5, 3, 3, 3) + layout.addWidget(content_frame, 1) + project_list.left_mouse_released_at.connect(self.on_item_clicked) project_list.right_mouse_released_at.connect( self._on_item_right_clicked