diff --git a/openpype/tools/settings/settings/window.py b/openpype/tools/settings/settings/window.py
index 22778e4a5b..96f11f3932 100644
--- a/openpype/tools/settings/settings/window.py
+++ b/openpype/tools/settings/settings/window.py
@@ -1,4 +1,16 @@
from Qt import QtWidgets, QtGui, QtCore
+
+from openpype import style
+
+from openpype.lib import is_admin_password_required
+from openpype.widgets import PasswordDialog
+
+from openpype.settings.lib import (
+ get_last_opened_info,
+ opened_settings_ui,
+ closed_settings_ui,
+)
+
from .categories import (
CategoryState,
SystemWidget,
@@ -10,10 +22,6 @@ from .widgets import (
SettingsTabWidget
)
from .search_dialog import SearchEntitiesDialog
-from openpype import style
-
-from openpype.lib import is_admin_password_required
-from openpype.widgets import PasswordDialog
class MainWidget(QtWidgets.QWidget):
@@ -25,6 +33,10 @@ class MainWidget(QtWidgets.QWidget):
def __init__(self, user_role, parent=None, reset_on_show=True):
super(MainWidget, self).__init__(parent)
+ # Object referencing to this machine and time when UI was opened
+ # - is used on close event
+ self._last_opened_info = None
+
self._user_passed = False
self._reset_on_show = reset_on_show
@@ -74,7 +86,7 @@ class MainWidget(QtWidgets.QWidget):
self._on_restart_required
)
tab_widget.reset_started.connect(self._on_reset_started)
- tab_widget.reset_started.connect(self._on_reset_finished)
+ tab_widget.reset_finished.connect(self._on_reset_finished)
tab_widget.full_path_requested.connect(self._on_full_path_request)
header_tab_widget.context_menu_requested.connect(
@@ -131,11 +143,38 @@ class MainWidget(QtWidgets.QWidget):
def showEvent(self, event):
super(MainWidget, self).showEvent(event)
+
if self._reset_on_show:
self._reset_on_show = False
# Trigger reset with 100ms delay
QtCore.QTimer.singleShot(100, self.reset)
+ elif not self._last_opened_info:
+ self._check_on_ui_open()
+
+ def _check_on_ui_open(self):
+ last_opened_info = get_last_opened_info()
+ if last_opened_info is not None:
+ if self._last_opened_info != last_opened_info:
+ self._last_opened_info = None
+ else:
+ self._last_opened_info = opened_settings_ui()
+
+ if self._last_opened_info is not None:
+ return
+
+ dialog = SettingsUIOpenedElsewhere(last_opened_info, self)
+ dialog.exec_()
+ if dialog.result() == 1:
+ self._last_opened_info = opened_settings_ui()
+ return
+
+ def closeEvent(self, event):
+ if self._last_opened_info:
+ closed_settings_ui(self._last_opened_info)
+ self._last_opened_info = None
+ super(MainWidget, self).closeEvent(event)
+
def _show_password_dialog(self):
if self._password_dialog:
self._password_dialog.open()
@@ -221,6 +260,8 @@ class MainWidget(QtWidgets.QWidget):
if current_widget is widget:
self._update_search_dialog()
+ self._check_on_ui_open()
+
def keyPressEvent(self, event):
if event.matches(QtGui.QKeySequence.Find):
# todo: search in all widgets (or in active)?
@@ -231,3 +272,88 @@ class MainWidget(QtWidgets.QWidget):
return
return super(MainWidget, self).keyPressEvent(event)
+
+
+class SettingsUIOpenedElsewhere(QtWidgets.QDialog):
+ def __init__(self, info_obj, parent=None):
+ super(SettingsUIOpenedElsewhere, self).__init__(parent)
+
+ self._result = 0
+
+ self.setWindowTitle("Someone else has opened Settings UI")
+
+ message_label = QtWidgets.QLabel((
+ "Someone else has opened Settings UI. That may cause data loss."
+ " Please contact the person on the other side."
+ "
You can open the UI in view-only mode or take"
+ " the control which will cause the other settings won't be able"
+ " to save changes.
"
+ ), self)
+ message_label.setWordWrap(True)
+
+ separator_widget_1 = QtWidgets.QFrame(self)
+ separator_widget_2 = QtWidgets.QFrame(self)
+ for separator_widget in (
+ separator_widget_1,
+ separator_widget_2
+ ):
+ separator_widget.setObjectName("Separator")
+ separator_widget.setMinimumHeight(1)
+ separator_widget.setMaximumHeight(1)
+
+ other_information = QtWidgets.QWidget(self)
+ other_information_layout = QtWidgets.QFormLayout(other_information)
+ other_information_layout.setContentsMargins(0, 0, 0, 0)
+ for label, value in (
+ ("Username", info_obj.username),
+ ("Host name", info_obj.hostname),
+ ("Host IP", info_obj.hostip),
+ ("System name", info_obj.system_name),
+ ("Local ID", info_obj.local_id),
+ ("Time Stamp", info_obj.timestamp),
+ ):
+ other_information_layout.addRow(
+ label,
+ QtWidgets.QLabel(value, other_information)
+ )
+
+ footer_widget = QtWidgets.QWidget(self)
+ buttons_widget = QtWidgets.QWidget(footer_widget)
+
+ take_control_btn = QtWidgets.QPushButton(
+ "Take control", buttons_widget
+ )
+ view_mode_btn = QtWidgets.QPushButton(
+ "View only", buttons_widget
+ )
+
+ buttons_layout = QtWidgets.QHBoxLayout(buttons_widget)
+ buttons_layout.setContentsMargins(0, 0, 0, 0)
+ buttons_layout.addWidget(take_control_btn, 1)
+ buttons_layout.addWidget(view_mode_btn, 1)
+
+ footer_layout = QtWidgets.QHBoxLayout(footer_widget)
+ footer_layout.setContentsMargins(0, 0, 0, 0)
+ footer_layout.addStretch(1)
+ footer_layout.addWidget(buttons_widget, 0)
+
+ layout = QtWidgets.QVBoxLayout(self)
+ layout.addWidget(message_label, 0)
+ layout.addWidget(separator_widget_1, 0)
+ layout.addWidget(other_information, 1, QtCore.Qt.AlignHCenter)
+ layout.addWidget(separator_widget_2, 0)
+ layout.addWidget(footer_widget, 0)
+
+ take_control_btn.clicked.connect(self._on_take_control)
+ view_mode_btn.clicked.connect(self._on_view_mode)
+
+ def result(self):
+ return self._result
+
+ def _on_take_control(self):
+ self._result = 1
+ self.close()
+
+ def _on_view_mode(self):
+ self._result = 0
+ self.close()