AccountWidget: Add a Quit button in the widget in case the system tray
is unavailable (for example running in a gamescope session) * Do not show the launch window while instantiating the application. This probably was causing numerous issues because it was running outside of the applications event loop. This also fixes the exit button on the login dialog requiring `sys.exit()` to quit Rare. Now it goes through the proper cleanup procedures. * Make slot and signal names more uniform * Fix a problem with RareCore connecting RareGames to the same signals multiple times when the library was refreshed.
This commit is contained in:
parent
8d46a3e353
commit
c3c9b0f059
|
@ -55,14 +55,9 @@ class Rare(RareApp):
|
||||||
self.launch_dialog: Optional[LaunchDialog] = None
|
self.launch_dialog: Optional[LaunchDialog] = None
|
||||||
self.timer: Optional[QTimer] = None
|
self.timer: Optional[QTimer] = None
|
||||||
|
|
||||||
# launch app
|
# This launches the application after it has been instantiated.
|
||||||
self.launch_dialog = LaunchDialog(parent=None)
|
# The timer's signal will be serviced once we call `exec()` on the application
|
||||||
self.launch_dialog.quit_app.connect(self.launch_dialog.close)
|
QTimer.singleShot(0, self.launch_app)
|
||||||
self.launch_dialog.quit_app.connect(lambda x: sys.exit(x))
|
|
||||||
self.launch_dialog.start_app.connect(self.start_app)
|
|
||||||
self.launch_dialog.start_app.connect(self.launch_dialog.close)
|
|
||||||
|
|
||||||
self.launch_dialog.login()
|
|
||||||
|
|
||||||
def poke_timer(self):
|
def poke_timer(self):
|
||||||
dt_exp = datetime.fromisoformat(self.core.lgd.userdata['expires_at'][:-1]).replace(tzinfo=timezone.utc)
|
dt_exp = datetime.fromisoformat(self.core.lgd.userdata['expires_at'][:-1]).replace(tzinfo=timezone.utc)
|
||||||
|
@ -80,13 +75,23 @@ class Rare(RareApp):
|
||||||
return
|
return
|
||||||
self.poke_timer()
|
self.poke_timer()
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def launch_app(self):
|
||||||
|
self.launch_dialog = LaunchDialog(parent=None)
|
||||||
|
self.launch_dialog.exit_app.connect(self.launch_dialog.close)
|
||||||
|
self.launch_dialog.exit_app.connect(self.__on_exit_app)
|
||||||
|
self.launch_dialog.start_app.connect(self.start_app)
|
||||||
|
self.launch_dialog.start_app.connect(self.launch_dialog.close)
|
||||||
|
self.launch_dialog.login()
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
def start_app(self):
|
def start_app(self):
|
||||||
self.timer = QTimer()
|
self.timer = QTimer()
|
||||||
self.timer.timeout.connect(self.re_login)
|
self.timer.timeout.connect(self.re_login)
|
||||||
self.poke_timer()
|
self.poke_timer()
|
||||||
|
|
||||||
self.main_window = MainWindow()
|
self.main_window = MainWindow()
|
||||||
self.main_window.exit_app.connect(self.on_exit_app)
|
self.main_window.exit_app.connect(self.__on_exit_app)
|
||||||
|
|
||||||
if not self.args.silent:
|
if not self.args.silent:
|
||||||
self.main_window.show()
|
self.main_window.show()
|
||||||
|
@ -94,11 +99,11 @@ class Rare(RareApp):
|
||||||
if self.args.test_start:
|
if self.args.test_start:
|
||||||
self.main_window.close()
|
self.main_window.close()
|
||||||
self.main_window = None
|
self.main_window = None
|
||||||
self.on_exit_app(0)
|
self.__on_exit_app(0)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def on_exit_app(self, exit_code=0):
|
def __on_exit_app(self, exit_code=0):
|
||||||
threadpool = QThreadPool.globalInstance()
|
threadpool = QThreadPool.globalInstance()
|
||||||
threadpool.waitForDone()
|
threadpool.waitForDone()
|
||||||
if self.timer is not None:
|
if self.timer is not None:
|
||||||
|
@ -119,9 +124,7 @@ def start(args) -> int:
|
||||||
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
|
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
|
||||||
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
|
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
|
||||||
app = Rare(args)
|
app = Rare(args)
|
||||||
exit_code = app.exec_()
|
exit_code = app.exec()
|
||||||
# if not restart
|
|
||||||
# restart app
|
|
||||||
del app
|
del app
|
||||||
if exit_code != -133742:
|
if exit_code != -133742:
|
||||||
break
|
break
|
||||||
|
|
|
@ -14,7 +14,7 @@ logger = getLogger("LaunchDialog")
|
||||||
|
|
||||||
|
|
||||||
class LaunchDialog(QDialog):
|
class LaunchDialog(QDialog):
|
||||||
quit_app = pyqtSignal(int)
|
exit_app = pyqtSignal(int)
|
||||||
start_app = pyqtSignal()
|
start_app = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
|
@ -74,7 +74,7 @@ class LaunchDialog(QDialog):
|
||||||
self.show()
|
self.show()
|
||||||
self.launch()
|
self.launch()
|
||||||
else:
|
else:
|
||||||
self.quit_app.emit(0)
|
self.exit_app.emit(0)
|
||||||
|
|
||||||
def launch(self):
|
def launch(self):
|
||||||
self.progress_info.setText(self.tr("Preparing Rare"))
|
self.progress_info.setText(self.tr("Preparing Rare"))
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from dataclasses import dataclass
|
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import QLayout, QDialog, QMessageBox, QFrame
|
from PyQt5.QtWidgets import QLayout, QDialog, QMessageBox, QFrame
|
||||||
from legendary.core import LegendaryCore
|
from legendary.core import LegendaryCore
|
||||||
|
|
||||||
|
@ -15,13 +14,6 @@ from .import_login import ImportLogin
|
||||||
logger = getLogger("LoginDialog")
|
logger = getLogger("LoginDialog")
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class LoginPages:
|
|
||||||
landing: int
|
|
||||||
browser: int
|
|
||||||
import_egl: int
|
|
||||||
|
|
||||||
|
|
||||||
class LandingPage(QFrame):
|
class LandingPage(QFrame):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(LandingPage, self).__init__(parent=parent)
|
super(LandingPage, self).__init__(parent=parent)
|
||||||
|
@ -31,8 +23,7 @@ class LandingPage(QFrame):
|
||||||
|
|
||||||
|
|
||||||
class LoginDialog(QDialog):
|
class LoginDialog(QDialog):
|
||||||
logged_in: bool = False
|
exit_app: pyqtSignal = pyqtSignal(int)
|
||||||
pages = LoginPages(landing=0, browser=1, import_egl=2)
|
|
||||||
|
|
||||||
def __init__(self, core: LegendaryCore, parent=None):
|
def __init__(self, core: LegendaryCore, parent=None):
|
||||||
super(LoginDialog, self).__init__(parent=parent)
|
super(LoginDialog, self).__init__(parent=parent)
|
||||||
|
@ -51,6 +42,8 @@ class LoginDialog(QDialog):
|
||||||
self.ui = Ui_LoginDialog()
|
self.ui = Ui_LoginDialog()
|
||||||
self.ui.setupUi(self)
|
self.ui.setupUi(self)
|
||||||
|
|
||||||
|
self.logged_in: bool = False
|
||||||
|
|
||||||
self.core = core
|
self.core = core
|
||||||
self.args = ArgumentsSingleton()
|
self.args = ArgumentsSingleton()
|
||||||
|
|
||||||
|
@ -59,16 +52,16 @@ class LoginDialog(QDialog):
|
||||||
self.ui.login_stack_layout.addWidget(self.login_stack)
|
self.ui.login_stack_layout.addWidget(self.login_stack)
|
||||||
|
|
||||||
self.landing_page = LandingPage(self.login_stack)
|
self.landing_page = LandingPage(self.login_stack)
|
||||||
self.login_stack.insertWidget(self.pages.landing, self.landing_page)
|
self.login_stack.insertWidget(0, self.landing_page)
|
||||||
|
|
||||||
self.browser_page = BrowserLogin(self.core, self.login_stack)
|
self.browser_page = BrowserLogin(self.core, self.login_stack)
|
||||||
self.login_stack.insertWidget(self.pages.browser, self.browser_page)
|
self.login_stack.insertWidget(1, self.browser_page)
|
||||||
self.browser_page.success.connect(self.login_successful)
|
self.browser_page.success.connect(self.login_successful)
|
||||||
self.browser_page.changed.connect(
|
self.browser_page.changed.connect(
|
||||||
lambda: self.ui.next_button.setEnabled(self.browser_page.is_valid())
|
lambda: self.ui.next_button.setEnabled(self.browser_page.is_valid())
|
||||||
)
|
)
|
||||||
self.import_page = ImportLogin(self.core, self.login_stack)
|
self.import_page = ImportLogin(self.core, self.login_stack)
|
||||||
self.login_stack.insertWidget(self.pages.import_egl, self.import_page)
|
self.login_stack.insertWidget(2, self.import_page)
|
||||||
self.import_page.success.connect(self.login_successful)
|
self.import_page.success.connect(self.login_successful)
|
||||||
self.import_page.changed.connect(lambda: self.ui.next_button.setEnabled(self.import_page.is_valid()))
|
self.import_page.changed.connect(lambda: self.ui.next_button.setEnabled(self.import_page.is_valid()))
|
||||||
|
|
||||||
|
@ -84,34 +77,34 @@ class LoginDialog(QDialog):
|
||||||
self.ui.back_button.clicked.connect(self.back_clicked)
|
self.ui.back_button.clicked.connect(self.back_clicked)
|
||||||
self.ui.next_button.clicked.connect(self.next_clicked)
|
self.ui.next_button.clicked.connect(self.next_clicked)
|
||||||
|
|
||||||
self.login_stack.setCurrentIndex(self.pages.landing)
|
self.login_stack.setCurrentWidget(self.landing_page)
|
||||||
|
|
||||||
self.layout().setSizeConstraint(QLayout.SetFixedSize)
|
self.layout().setSizeConstraint(QLayout.SetFixedSize)
|
||||||
|
|
||||||
def back_clicked(self):
|
def back_clicked(self):
|
||||||
self.ui.back_button.setEnabled(False)
|
self.ui.back_button.setEnabled(False)
|
||||||
self.ui.next_button.setEnabled(True)
|
self.ui.next_button.setEnabled(True)
|
||||||
self.login_stack.slideInIndex(self.pages.landing)
|
self.login_stack.slideInWidget(self.landing_page)
|
||||||
|
|
||||||
def browser_radio_clicked(self):
|
def browser_radio_clicked(self):
|
||||||
self.login_stack.slideInIndex(self.pages.browser)
|
self.login_stack.slideInWidget(self.browser_page)
|
||||||
self.ui.back_button.setEnabled(True)
|
self.ui.back_button.setEnabled(True)
|
||||||
self.ui.next_button.setEnabled(False)
|
self.ui.next_button.setEnabled(False)
|
||||||
|
|
||||||
def import_radio_clicked(self):
|
def import_radio_clicked(self):
|
||||||
self.login_stack.slideInIndex(self.pages.import_egl)
|
self.login_stack.slideInWidget(self.import_page)
|
||||||
self.ui.back_button.setEnabled(True)
|
self.ui.back_button.setEnabled(True)
|
||||||
self.ui.next_button.setEnabled(self.import_page.is_valid())
|
self.ui.next_button.setEnabled(self.import_page.is_valid())
|
||||||
|
|
||||||
def next_clicked(self):
|
def next_clicked(self):
|
||||||
if self.login_stack.currentIndex() == self.pages.landing:
|
if self.login_stack.currentWidget() is self.landing_page:
|
||||||
if self.landing_page.ui.login_browser_radio.isChecked():
|
if self.landing_page.ui.login_browser_radio.isChecked():
|
||||||
self.browser_radio_clicked()
|
self.browser_radio_clicked()
|
||||||
if self.landing_page.ui.login_import_radio.isChecked():
|
if self.landing_page.ui.login_import_radio.isChecked():
|
||||||
self.import_radio_clicked()
|
self.import_radio_clicked()
|
||||||
elif self.login_stack.currentIndex() == self.pages.browser:
|
elif self.login_stack.currentWidget() is self.browser_page:
|
||||||
self.browser_page.do_login()
|
self.browser_page.do_login()
|
||||||
elif self.login_stack.currentIndex() == self.pages.import_egl:
|
elif self.login_stack.currentWidget() is self.import_page:
|
||||||
self.import_page.do_login()
|
self.import_page.do_login()
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
|
|
|
@ -44,7 +44,7 @@ class MainWindow(QMainWindow):
|
||||||
|
|
||||||
self.setWindowTitle("Rare - GUI for legendary")
|
self.setWindowTitle("Rare - GUI for legendary")
|
||||||
self.tab_widget = MainTabWidget(self)
|
self.tab_widget = MainTabWidget(self)
|
||||||
self.tab_widget.exit_app.connect(self.on_exit_app)
|
self.tab_widget.exit_app.connect(self.__on_exit_app)
|
||||||
self.setCentralWidget(self.tab_widget)
|
self.setCentralWidget(self.tab_widget)
|
||||||
|
|
||||||
# Set up status bar stuff (jumping through a lot of hoops)
|
# Set up status bar stuff (jumping through a lot of hoops)
|
||||||
|
@ -112,7 +112,7 @@ class MainWindow(QMainWindow):
|
||||||
self.timer.start()
|
self.timer.start()
|
||||||
|
|
||||||
self.tray_icon: TrayIcon = TrayIcon(self)
|
self.tray_icon: TrayIcon = TrayIcon(self)
|
||||||
self.tray_icon.exit_app.connect(self.on_exit_app)
|
self.tray_icon.exit_app.connect(self.__on_exit_app)
|
||||||
self.tray_icon.show_app.connect(self.show)
|
self.tray_icon.show_app.connect(self.show)
|
||||||
self.tray_icon.activated.connect(lambda r: self.toggle() if r == self.tray_icon.DoubleClick else None)
|
self.tray_icon.activated.connect(lambda r: self.toggle() if r == self.tray_icon.DoubleClick else None)
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ class MainWindow(QMainWindow):
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def on_exit_app(self, exit_code=0) -> None:
|
def __on_exit_app(self, exit_code=0) -> None:
|
||||||
self.__exit_code = exit_code
|
self.__exit_code = exit_code
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ class MainTabWidget(QTabWidget):
|
||||||
self.setTabEnabled(button_index, False)
|
self.setTabEnabled(button_index, False)
|
||||||
|
|
||||||
self.account_widget = AccountWidget(self)
|
self.account_widget = AccountWidget(self)
|
||||||
self.account_widget.logout.connect(self.logout)
|
self.account_widget.exit_app.connect(self.__on_exit_app)
|
||||||
account_action = QWidgetAction(self)
|
account_action = QWidgetAction(self)
|
||||||
account_action.setDefaultWidget(self.account_widget)
|
account_action.setDefaultWidget(self.account_widget)
|
||||||
account_button = TabButtonWidget("mdi.account-circle", "Account", fallback_icon="fa.user")
|
account_button = TabButtonWidget("mdi.account-circle", "Account", fallback_icon="fa.user")
|
||||||
|
@ -93,17 +93,18 @@ class MainTabWidget(QTabWidget):
|
||||||
self.tab_bar.setMinimumWidth(self.width())
|
self.tab_bar.setMinimumWidth(self.width())
|
||||||
super(MainTabWidget, self).resizeEvent(event)
|
super(MainTabWidget, self).resizeEvent(event)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot(int)
|
||||||
def logout(self):
|
def __on_exit_app(self, exit_code: int):
|
||||||
# FIXME: Don't allow logging out if there are active downloads
|
# FIXME: Don't allow logging out if there are active downloads
|
||||||
if self.downloads_tab.is_download_active:
|
if self.downloads_tab.is_download_active:
|
||||||
QMessageBox.warning(
|
QMessageBox.warning(
|
||||||
self,
|
self,
|
||||||
self.tr("Logout"),
|
self.tr("Quit") if exit_code == self.account_widget.ExitCodes.EXIT else self.tr("Logout"),
|
||||||
self.tr("There are active downloads. Stop them before logging out."),
|
self.tr("There are active downloads. Stop them before trying to quit."),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
# FIXME: End of FIXME
|
# FIXME: End of FIXME
|
||||||
|
if exit_code == self.account_widget.ExitCodes.LOGOUT:
|
||||||
reply = QMessageBox.question(
|
reply = QMessageBox.question(
|
||||||
self,
|
self,
|
||||||
self.tr("Logout"),
|
self.tr("Logout"),
|
||||||
|
@ -114,4 +115,6 @@ class MainTabWidget(QTabWidget):
|
||||||
|
|
||||||
if reply == QMessageBox.Yes:
|
if reply == QMessageBox.Yes:
|
||||||
self.core.lgd.invalidate_userdata()
|
self.core.lgd.invalidate_userdata()
|
||||||
self.exit_app.emit(-133742) # restart exit code
|
else:
|
||||||
|
return
|
||||||
|
self.exit_app.emit(exit_code) # restart exit code
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
from enum import IntEnum
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QMessageBox, QLabel, QPushButton
|
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QPushButton
|
||||||
|
|
||||||
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
|
from rare.shared import LegendaryCoreSingleton, GlobalSignalsSingleton
|
||||||
from rare.utils.misc import icon
|
from rare.utils.misc import icon
|
||||||
|
|
||||||
|
|
||||||
class AccountWidget(QWidget):
|
class AccountWidget(QWidget):
|
||||||
|
exit_app: pyqtSignal = pyqtSignal(int)
|
||||||
logout: pyqtSignal = pyqtSignal()
|
logout: pyqtSignal = pyqtSignal()
|
||||||
|
|
||||||
|
class ExitCodes(IntEnum):
|
||||||
|
EXIT = 0
|
||||||
|
LOGOUT = -133742
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
super(AccountWidget, self).__init__(parent=parent)
|
super(AccountWidget, self).__init__(parent=parent)
|
||||||
self.core = LegendaryCoreSingleton()
|
self.core = LegendaryCoreSingleton()
|
||||||
|
@ -25,11 +31,22 @@ class AccountWidget(QWidget):
|
||||||
"https://www.epicgames.com/account/personal?productName=epicgames"
|
"https://www.epicgames.com/account/personal?productName=epicgames"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.logout_button = QPushButton(self.tr("Logout"))
|
self.logout_button = QPushButton(self.tr("Logout"), parent=self)
|
||||||
self.logout_button.clicked.connect(self.logout)
|
self.logout_button.clicked.connect(self.__on_logout)
|
||||||
|
self.quit_button = QPushButton(self.tr("Quit"), parent=self)
|
||||||
|
self.quit_button.clicked.connect(self.__on_quit)
|
||||||
|
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
layout.addWidget(QLabel(self.tr("Account")))
|
layout.addWidget(QLabel(self.tr("Account")))
|
||||||
layout.addWidget(QLabel(self.tr("Logged in as <b>{}</b>").format(username)))
|
layout.addWidget(QLabel(self.tr("Logged in as <b>{}</b>").format(username)))
|
||||||
layout.addWidget(self.open_browser)
|
layout.addWidget(self.open_browser)
|
||||||
layout.addWidget(self.logout_button)
|
layout.addWidget(self.logout_button)
|
||||||
|
layout.addWidget(self.quit_button)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def __on_quit(self):
|
||||||
|
self.exit_app.emit(AccountWidget.ExitCodes.EXIT)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def __on_logout(self):
|
||||||
|
self.exit_app.emit(AccountWidget.ExitCodes.LOGOUT)
|
||||||
|
|
|
@ -179,8 +179,8 @@ class RareCore(QObject):
|
||||||
del self.__args
|
del self.__args
|
||||||
self.__args = None
|
self.__args = None
|
||||||
|
|
||||||
|
del self.__eos_overlay
|
||||||
RareCore.__instance = None
|
RareCore.__instance = None
|
||||||
|
|
||||||
super(RareCore, self).deleteLater()
|
super(RareCore, self).deleteLater()
|
||||||
|
|
||||||
def __validate_install(self, rgame: RareGame):
|
def __validate_install(self, rgame: RareGame):
|
||||||
|
|
Loading…
Reference in a new issue