ayon-core/openpype/modules/ftrack/tray/login_dialog.py
Jakub Trllo 6843ae8532
General: Small code cleanups (#5034)
* make sure the message type is set and unset correctly

* Update dummy data in readme

* remove debug message from main thread callbacks

* removed unused import

* cleanup code in muster addon

* simplified 'get_publish_instance_label' function

* even better json file handling

Co-authored-by: Roy Nieterau <roy_nieterau@hotmail.com>

---------

Co-authored-by: Roy Nieterau <roy_nieterau@hotmail.com>
2023-05-26 14:44:47 +02:00

344 lines
11 KiB
Python

import requests
from qtpy import QtCore, QtGui, QtWidgets
from openpype import style
from openpype_modules.ftrack.lib import credentials
from openpype import resources
from . import login_tools
class CredentialsDialog(QtWidgets.QDialog):
SIZE_W = 300
SIZE_H = 230
login_changed = QtCore.Signal()
logout_signal = QtCore.Signal()
def __init__(self, module, parent=None):
super(CredentialsDialog, self).__init__(parent)
self.setWindowTitle("OpenPype - Ftrack Login")
self._module = module
self._login_server_thread = None
self._is_logged = False
self._in_advance_mode = False
icon = QtGui.QIcon(resources.get_openpype_icon_filepath())
self.setWindowIcon(icon)
self.setWindowFlags(
QtCore.Qt.WindowCloseButtonHint |
QtCore.Qt.WindowMinimizeButtonHint
)
self.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H))
self.setMaximumSize(QtCore.QSize(self.SIZE_W + 100, self.SIZE_H + 100))
self.setStyleSheet(style.load_stylesheet())
self.login_changed.connect(self._on_login)
self.ui_init()
def ui_init(self):
self.ftsite_label = QtWidgets.QLabel("Ftrack URL:")
self.user_label = QtWidgets.QLabel("Username:")
self.api_label = QtWidgets.QLabel("API Key:")
self.ftsite_input = QtWidgets.QLabel()
self.ftsite_input.setTextInteractionFlags(
QtCore.Qt.TextBrowserInteraction
)
# self.ftsite_input.setReadOnly(True)
self.ftsite_input.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
self.user_input = QtWidgets.QLineEdit()
self.user_input.setPlaceholderText("user.name")
self.user_input.textChanged.connect(self._user_changed)
self.api_input = QtWidgets.QLineEdit()
self.api_input.setPlaceholderText(
"e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
)
self.api_input.textChanged.connect(self._api_changed)
input_layout = QtWidgets.QFormLayout()
input_layout.setContentsMargins(10, 15, 10, 5)
input_layout.addRow(self.ftsite_label, self.ftsite_input)
input_layout.addRow(self.user_label, self.user_input)
input_layout.addRow(self.api_label, self.api_input)
self.btn_advanced = QtWidgets.QPushButton("Advanced")
self.btn_advanced.clicked.connect(self._on_advanced_clicked)
self.btn_simple = QtWidgets.QPushButton("Simple")
self.btn_simple.clicked.connect(self._on_simple_clicked)
self.btn_login = QtWidgets.QPushButton("Login")
self.btn_login.setToolTip(
"Set Username and API Key with entered values"
)
self.btn_login.clicked.connect(self._on_login_clicked)
self.btn_ftrack_login = QtWidgets.QPushButton("Ftrack login")
self.btn_ftrack_login.setToolTip("Open browser for Login to Ftrack")
self.btn_ftrack_login.clicked.connect(self._on_ftrack_login_clicked)
self.btn_logout = QtWidgets.QPushButton("Logout")
self.btn_logout.clicked.connect(self._on_logout_clicked)
self.btn_close = QtWidgets.QPushButton("Close")
self.btn_close.setToolTip("Close this window")
self.btn_close.clicked.connect(self._close_widget)
btns_layout = QtWidgets.QHBoxLayout()
btns_layout.addWidget(self.btn_advanced)
btns_layout.addWidget(self.btn_simple)
btns_layout.addStretch(1)
btns_layout.addWidget(self.btn_ftrack_login)
btns_layout.addWidget(self.btn_login)
btns_layout.addWidget(self.btn_logout)
btns_layout.addWidget(self.btn_close)
self.note_label = QtWidgets.QLabel((
"NOTE: Click on \"{}\" button to log with your default browser"
" or click on \"{}\" button to enter API key manually."
).format(self.btn_ftrack_login.text(), self.btn_advanced.text()))
self.note_label.setWordWrap(True)
self.note_label.hide()
self.error_label = QtWidgets.QLabel("")
self.error_label.setWordWrap(True)
self.error_label.hide()
label_layout = QtWidgets.QVBoxLayout()
label_layout.setContentsMargins(10, 5, 10, 5)
label_layout.addWidget(self.note_label)
label_layout.addWidget(self.error_label)
main = QtWidgets.QVBoxLayout(self)
main.addLayout(input_layout)
main.addLayout(label_layout)
main.addStretch(1)
main.addLayout(btns_layout)
self.fill_ftrack_url()
self.set_is_logged(self._is_logged)
self.setLayout(main)
def show(self, *args, **kwargs):
super(CredentialsDialog, self).show(*args, **kwargs)
self.fill_ftrack_url()
def fill_ftrack_url(self):
checked_url = self.check_url()
if checked_url == self.ftsite_input.text():
return
self.ftsite_input.setText(checked_url or "< Not set >")
enabled = bool(checked_url)
self.btn_login.setEnabled(enabled)
self.btn_ftrack_login.setEnabled(enabled)
self.api_input.setEnabled(enabled)
self.user_input.setEnabled(enabled)
if not checked_url:
self.btn_advanced.hide()
self.btn_simple.hide()
self.btn_ftrack_login.hide()
self.btn_login.hide()
self.note_label.hide()
self.api_input.hide()
self.user_input.hide()
def set_advanced_mode(self, is_advanced):
self._in_advance_mode = is_advanced
self.error_label.setVisible(False)
is_logged = self._is_logged
self.note_label.setVisible(not is_logged and not is_advanced)
self.btn_ftrack_login.setVisible(not is_logged and not is_advanced)
self.btn_advanced.setVisible(not is_logged and not is_advanced)
self.btn_login.setVisible(not is_logged and is_advanced)
self.btn_simple.setVisible(not is_logged and is_advanced)
self.user_label.setVisible(is_logged or is_advanced)
self.user_input.setVisible(is_logged or is_advanced)
self.api_label.setVisible(is_logged or is_advanced)
self.api_input.setVisible(is_logged or is_advanced)
if is_advanced:
self.user_input.setFocus()
else:
self.btn_ftrack_login.setFocus()
def set_is_logged(self, is_logged):
self._is_logged = is_logged
self.user_input.setReadOnly(is_logged)
self.api_input.setReadOnly(is_logged)
self.user_input.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
self.api_input.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
self.btn_logout.setVisible(is_logged)
self.set_advanced_mode(self._in_advance_mode)
def set_error(self, msg):
self.error_label.setText(msg)
self.error_label.show()
def _on_logout_clicked(self):
self.user_input.setText("")
self.api_input.setText("")
self.set_is_logged(False)
self.logout_signal.emit()
def _on_simple_clicked(self):
self.set_advanced_mode(False)
def _on_advanced_clicked(self):
self.set_advanced_mode(True)
def _user_changed(self):
self._not_invalid_input(self.user_input)
def _api_changed(self):
self._not_invalid_input(self.api_input)
def _not_invalid_input(self, input_widget):
input_widget.setStyleSheet("")
def _invalid_input(self, input_widget):
input_widget.setStyleSheet("border: 1px solid red;")
def _on_login(self):
self.set_is_logged(True)
self._close_widget()
def _on_login_clicked(self):
username = self.user_input.text().strip()
api_key = self.api_input.text().strip()
missing = []
if username == "":
missing.append("Username")
self._invalid_input(self.user_input)
if api_key == "":
missing.append("API Key")
self._invalid_input(self.api_input)
if len(missing) > 0:
self.set_error("You didn't enter {}".format(" and ".join(missing)))
return
if not self.login_with_credentials(username, api_key):
self._invalid_input(self.user_input)
self._invalid_input(self.api_input)
self.set_error(
"We're unable to sign in to Ftrack with these credentials"
)
def _on_ftrack_login_clicked(self):
url = self.check_url()
if not url:
return
# If there is an existing server thread running we need to stop it.
if self._login_server_thread:
if self._login_server_thread.is_alive():
self._login_server_thread.stop()
self._login_server_thread.join()
self._login_server_thread = None
# If credentials are not properly set, try to get them using a http
# server.
self._login_server_thread = login_tools.LoginServerThread(
url, self._result_of_ftrack_thread
)
self._login_server_thread.start()
def _result_of_ftrack_thread(self, username, api_key):
if not self.login_with_credentials(username, api_key):
self._invalid_input(self.api_input)
self.set_error((
"Somthing happened with Ftrack login."
" Try enter Username and API key manually."
))
def login_with_credentials(self, username, api_key):
verification = credentials.check_credentials(username, api_key)
if verification:
credentials.save_credentials(username, api_key, False)
self._module.set_credentials_to_env(username, api_key)
self.set_credentials(username, api_key)
self.login_changed.emit()
return verification
def set_credentials(self, username, api_key, is_logged=True):
self.user_input.setText(username)
self.api_input.setText(api_key)
self.error_label.hide()
self._not_invalid_input(self.ftsite_input)
self._not_invalid_input(self.user_input)
self._not_invalid_input(self.api_input)
if is_logged is not None:
self.set_is_logged(is_logged)
def check_url(self):
settings_url = self._module.settings_ftrack_url
url = self._module.ftrack_url
if not settings_url:
self.set_error(
"Ftrack URL is not defined in settings!"
)
return
if url is None:
self.set_error(
"Specified URL does not lead to a valid Ftrack server."
)
return
try:
result = requests.get(
url,
# Old python API will not work with redirect.
allow_redirects=False
)
except requests.exceptions.RequestException:
self.set_error(
"Specified URL could not be reached."
)
return
if (
result.status_code != 200
or "FTRACK_VERSION" not in result.headers
):
self.set_error(
"Specified URL does not lead to a valid Ftrack server."
)
return
return url
def closeEvent(self, event):
event.ignore()
self._close_widget()
def _close_widget(self):
self.hide()