1
0
Fork 0
mirror of synced 2024-06-29 11:40:37 +12:00
Rare/rare/components/dialogs/login/__init__.py
loathingKernel 400625975d Dialogs: Re-implement Launch and Login dialogs on top of a few common super-classes
To keep dialogs in a common format and allow them to share the same
properties, three classes of dialogs have been implemented inheriting from
each other.

The classes are `BaseDialog` -> `ButtonDialog` -> `ActionDialog`

* Basedialog: is the basis of all dialogs and is responsible for
rejecting close requests from the window manager and the keyboard.
It also restricts access to `exec()` and `exec_()` because they are harmful.
It serves as the basis of Launch and Login dialogs

* ButtonDialog: is offering buttons for accepting or rejecting the presented
option. It implements its own buttons and exposes abstract methods to
implement handling in them. It restricts access to `close()` because these
dialogs should always product a result.
It is the basis of Uninstall, Selective dialogs.

* ActionDialog: in addition to the ButtonDialog, it offers an action buttom
with to validate the form or to make the dialog unable to close. It serves
as the basis of Install and Move dialogs.
2023-12-24 21:08:26 +02:00

158 lines
6.3 KiB
Python

from logging import getLogger
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QLayout, QMessageBox, QFrame
from legendary.core import LegendaryCore
from rare.shared import ArgumentsSingleton
from rare.ui.components.dialogs.login.landing_page import Ui_LandingPage
from rare.ui.components.dialogs.login.login_dialog import Ui_LoginDialog
from rare.utils.misc import icon
from rare.widgets.dialogs import BaseDialog
from rare.widgets.sliding_stack import SlidingStackedWidget
from .browser_login import BrowserLogin
from .import_login import ImportLogin
logger = getLogger("LoginDialog")
class LandingPage(QFrame):
def __init__(self, parent=None):
super(LandingPage, self).__init__(parent=parent)
self.setFrameStyle(self.StyledPanel)
self.ui = Ui_LandingPage()
self.ui.setupUi(self)
class LoginDialog(BaseDialog):
def __init__(self, core: LegendaryCore, parent=None):
super(LoginDialog, self).__init__(parent=parent)
self.setWindowFlags(
Qt.Window
| Qt.Dialog
| Qt.CustomizeWindowHint
| Qt.WindowSystemMenuHint
| Qt.WindowTitleHint
| Qt.WindowMinimizeButtonHint
| Qt.WindowCloseButtonHint
| Qt.MSWindowsFixedSizeDialogHint
)
self.ui = Ui_LoginDialog()
self.ui.setupUi(self)
self.logged_in: bool = False
self.core = core
self.args = ArgumentsSingleton()
self.login_stack = SlidingStackedWidget(parent=self)
self.login_stack.setMinimumWidth(480)
self.ui.login_stack_layout.addWidget(self.login_stack)
self.landing_page = LandingPage(self.login_stack)
self.login_stack.insertWidget(0, self.landing_page)
self.browser_page = BrowserLogin(self.core, self.login_stack)
self.login_stack.insertWidget(1, self.browser_page)
self.browser_page.success.connect(self.login_successful)
self.browser_page.changed.connect(
lambda: self.ui.next_button.setEnabled(self.browser_page.is_valid())
)
self.import_page = ImportLogin(self.core, self.login_stack)
self.login_stack.insertWidget(2, self.import_page)
self.import_page.success.connect(self.login_successful)
self.import_page.changed.connect(lambda: self.ui.next_button.setEnabled(self.import_page.is_valid()))
# # NOTE: The real problem is that the BrowserLogin page has a huge QLabel with word-wrapping enabled.
# # That forces the whole form to vertically expand instead of horizontally. Since the form is not shown
# # on the first page, the internal Qt calculation for the size of that form calculates it by expanding it
# # vertically. Once the form becomes visible, the correct calculation takes place and that is why the
# # dialog reduces in height. To avoid that, calculate the bounding size of all forms and set it as the
# # minumum size
# self.login_stack.setMinimumSize(
# self.landing_page.sizeHint().expandedTo(
# self.browser_page.sizeHint().expandedTo(self.import_page.sizeHint())
# )
# )
self.login_stack.setFixedHeight(
max(
self.landing_page.heightForWidth(self.login_stack.minimumWidth()),
self.browser_page.heightForWidth(self.login_stack.minimumWidth()),
self.import_page.heightForWidth(self.login_stack.minimumWidth()),
)
)
self.ui.next_button.setEnabled(False)
self.ui.back_button.setEnabled(False)
self.landing_page.ui.login_browser_radio.clicked.connect(lambda: self.ui.next_button.setEnabled(True))
self.landing_page.ui.login_browser_radio.clicked.connect(self.browser_radio_clicked)
self.landing_page.ui.login_import_radio.clicked.connect(lambda: self.ui.next_button.setEnabled(True))
self.landing_page.ui.login_import_radio.clicked.connect(self.import_radio_clicked)
self.ui.exit_button.clicked.connect(self.reject)
self.ui.back_button.clicked.connect(self.back_clicked)
self.ui.next_button.clicked.connect(self.next_clicked)
self.login_stack.setCurrentWidget(self.landing_page)
self.ui.exit_button.setIcon(icon("fa.remove"))
self.ui.back_button.setIcon(icon("fa.chevron-left"))
self.ui.next_button.setIcon(icon("fa.chevron-right"))
# lk: Set next as the default button only to stop closing the dialog when pressing enter
self.ui.exit_button.setAutoDefault(False)
self.ui.back_button.setAutoDefault(False)
self.ui.next_button.setAutoDefault(True)
self.ui.main_layout.setSizeConstraint(QLayout.SetFixedSize)
def back_clicked(self):
self.ui.back_button.setEnabled(False)
self.ui.next_button.setEnabled(True)
self.login_stack.slideInWidget(self.landing_page)
def browser_radio_clicked(self):
self.login_stack.slideInWidget(self.browser_page)
self.ui.back_button.setEnabled(True)
self.ui.next_button.setEnabled(False)
def import_radio_clicked(self):
self.login_stack.slideInWidget(self.import_page)
self.ui.back_button.setEnabled(True)
self.ui.next_button.setEnabled(self.import_page.is_valid())
def next_clicked(self):
if self.login_stack.currentWidget() is self.landing_page:
if self.landing_page.ui.login_browser_radio.isChecked():
self.browser_radio_clicked()
if self.landing_page.ui.login_import_radio.isChecked():
self.import_radio_clicked()
elif self.login_stack.currentWidget() is self.browser_page:
self.browser_page.do_login()
elif self.login_stack.currentWidget() is self.import_page:
self.import_page.do_login()
def login(self):
if self.args.test_start:
self.reject()
self.open()
def login_successful(self):
try:
if self.core.login():
self.logged_in = True
self.accept()
else:
raise ValueError("Login failed.")
except Exception as e:
logger.error(str(e))
self.core.lgd.invalidate_userdata()
self.ui.next_button.setEnabled(False)
self.logged_in = False
QMessageBox.warning(None, self.tr("Login error"), str(e))