1
0
Fork 0
mirror of synced 2024-06-03 03:04:42 +12:00

Merge pull request #72 from loathingKernel/dialogs

Re-implement LoginDialog.
This commit is contained in:
Dummerle 2021-08-16 21:01:03 +02:00 committed by GitHub
commit c289fae292
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 1429 additions and 621 deletions

View file

@ -1,5 +1,5 @@
include README.md
include rare/languages/*.qm
include rare/styles/*
include rare/styles/qss/*
include rare/styles/colors/*
include rare/resources/images/*
recursive-include rare/resources/stylesheets/* *
include rare/resources/colors/*

View file

@ -46,7 +46,7 @@ else:
src_files += [
'LICENSE',
'README.md',
'rare/styles/Logo.ico',
'rare/resources/images/Rare.ico',
]
# Dependencies are automatically detected, but it might need fine tuning.
@ -65,7 +65,7 @@ setup(name='Rare',
executables=[
Executable('rare/__main__.py',
targetName=name,
icon='rare/styles/Logo.ico',
icon='rare/resources/images/Rare.ico',
base=base,
shortcutName=shortcutName,
shortcutDir=shortcutDir,

View file

@ -1,5 +1,5 @@
import os
__version__ = "1.4.1"
style_path = os.path.join(os.path.dirname(__file__), "styles/")
lang_path = os.path.join(os.path.dirname(__file__), "languages/")
resources_path = os.path.join(os.path.dirname(__file__), "resources")
languages_path = os.path.join(os.path.dirname(__file__), "languages")

View file

@ -3,13 +3,14 @@ import logging
import os
import sys
import time
import importlib
from PyQt5.QtCore import QSettings, QTranslator
from PyQt5.QtCore import QSettings, QTranslator, Qt, QFile, QIODevice, QTextStream
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QStyleFactory
from custom_legendary.core import LegendaryCore
from rare import lang_path, style_path
from rare import languages_path, resources_path
from rare.components.dialogs.launch_dialog import LaunchDialog
from rare.components.main_window import MainWindow
from rare.components.tray_icon import TrayIcon
@ -48,13 +49,21 @@ class App(QApplication):
self.core.lgd.config.add_section("Legendary")
self.core.lgd.save_config()
# workaround if egl sync enabled, but no programdata path
if self.core.egl_sync_enabled and not os.path.exists(self.core.egl.programdata_path):
self.core.lgd.config.remove_option("Legendary", "egl-sync")
self.core.lgd.save_config()
# workaround if egl sync enabled, but no programdata_path
# programdata_path might be unset if logging in through the browser
if self.core.egl_sync_enabled:
if self.core.egl.programdata_path is None:
self.core.lgd.config.remove_option("Legendary", "egl_sync")
self.core.lgd.save_config()
else:
if not os.path.exists(self.core.egl.programdata_path):
self.core.lgd.config.remove_option("Legendary", "egl_sync")
self.core.lgd.save_config()
# set Application name for settings
self.mainwindow = None
self.tray_icon = None
self.launch_dialog = None
self.setApplicationName("Rare")
self.setOrganizationName("Rare")
settings = QSettings()
@ -67,8 +76,8 @@ class App(QApplication):
# Translator
self.translator = QTranslator()
lang = settings.value("language", get_lang(), type=str)
if os.path.exists(lang_path + lang + ".qm"):
self.translator.load(lang_path + lang + ".qm")
if os.path.exists(languages_path + lang + ".qm"):
self.translator.load(languages_path + lang + ".qm")
logger.info("Your language is supported: " + lang)
elif not lang == "en":
logger.info("Your language is not supported")
@ -81,27 +90,40 @@ class App(QApplication):
settings.setValue("style_sheet", "RareStyle")
if color := settings.value("color_scheme", False):
settings.setValue("style_sheet", "")
custom_palette = load_color_scheme(os.path.join(style_path, "colors", color + ".scheme"))
custom_palette = load_color_scheme(os.path.join(resources_path, "colors", color + ".scheme"))
if custom_palette is not None:
self.setPalette(custom_palette)
elif style := settings.value("style_sheet", False):
settings.setValue("color_scheme", "")
self.setStyleSheet(open(os.path.join(style_path, "qss", style + ".qss")).read())
self.setWindowIcon(QIcon(os.path.join(style_path, "Logo.png")))
stylesheet = open(os.path.join(resources_path, "stylesheets", style, "stylesheet.qss")).read()
style_resource_path = os.path.join(resources_path, "stylesheets", style, "")
if os.name == "nt":
style_resource_path = style_resource_path.replace('\\', '/')
self.setStyleSheet(stylesheet.replace("@path@", style_resource_path))
# lk: for qresources stylesheets, not an ideal solution for modability,
# lk: too many extra steps and I don't like binary files in git, even as strings.
# importlib.import_module("rare.resources.stylesheets." + style)
# resource = QFile(f":/{style}/stylesheet.qss")
# resource.open(QIODevice.ReadOnly)
# self.setStyleSheet(QTextStream(resource).readAll())
self.setWindowIcon(QIcon(os.path.join(resources_path, "images", "Rare.png")))
# launch app
self.launch_dialog = LaunchDialog(self.core, args.offline)
self.launch_dialog.quit_app.connect(self.launch_dialog.close)
self.launch_dialog.quit_app.connect(lambda ec: exit(ec))
self.launch_dialog.start_app.connect(self.start_app)
self.launch_dialog.start_app.connect(self.launch_dialog.close)
if not args.silent or args.subparser == "launch":
self.launch_dialog.show()
self.launch_dialog.login()
def start_app(self, offline=False):
self.args.offline = offline
self.mainwindow = MainWindow(self.core, self.args)
self.launch_dialog.close()
self.mainwindow.quit_app.connect(self.exit_app)
self.tray_icon = TrayIcon(self)
self.tray_icon.exit_action.triggered.connect(lambda: exit(0))
self.tray_icon.exit_action.triggered.connect(self.exit_app)
self.tray_icon.start_rare.triggered.connect(self.mainwindow.show)
self.tray_icon.activated.connect(self.tray)
if not offline:
@ -117,13 +139,21 @@ class App(QApplication):
self.mainwindow.show()
logger.info("Show App")
def exit_app(self, exit_code=0):
if self.tray_icon is not None:
self.tray_icon.deleteLater()
if self.mainwindow is not None:
self.mainwindow.close()
self.processEvents()
self.exit(exit_code)
def start(args):
while True:
app = App(args)
exit_code = app.exec_()
# if not restart
if exit_code != -133742:
break
# restart app
del app
if exit_code != -133742:
break

View file

@ -171,7 +171,7 @@ class InstallDialog(QDialog, Ui_InstallDialog):
self.close()
def on_worker_failed(self, message: str):
error_text = self.tr("Error")
error_text = self.tr("Error, check selected options.")
self.download_size_info_label.setText(error_text)
self.install_size_info_label.setText(error_text)
QMessageBox.critical(self, self.windowTitle(), message)
@ -241,7 +241,7 @@ class InstallInfoWorker(QRunnable):
sdl_prompt=lambda app_name, title: self.dl_item.options.sdl_list
))
self.signals.result.emit(download)
except RuntimeError as e:
except Exception as e:
self.signals.failed.emit(str(e))
self.signals.finished.emit()

View file

@ -2,7 +2,7 @@ import json
import os
from logging import getLogger
from PyQt5.QtCore import QThread, pyqtSignal, QSettings
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QSettings
from PyQt5.QtWidgets import QDialog
from requests.exceptions import ConnectionError
@ -66,81 +66,73 @@ class SteamThread(QThread):
self.progress.emit(100)
class LoginThread(QThread):
login = pyqtSignal()
start_app = pyqtSignal(bool) # offline
def __init__(self, core: LegendaryCore):
super(LoginThread, self).__init__()
self.core = core
def run(self):
logger.info("Try if you are logged in")
try:
if self.core.login():
logger.info("You are logged in")
self.start_app.emit(False)
else:
self.run()
except ValueError:
logger.info("You are not logged in. Open Login Window")
self.login.emit()
except ConnectionError as e:
logger.warning(e)
self.start_app.emit(True)
class LaunchDialog(QDialog, Ui_LaunchDialog):
quit_app = pyqtSignal(int)
start_app = pyqtSignal(bool)
finished = False
completed = False
def __init__(self, core: LegendaryCore, offline):
super(LaunchDialog, self).__init__()
def __init__(self, core: LegendaryCore, offline=False, parent=None):
super(LaunchDialog, self).__init__(parent=parent)
self.setupUi(self)
self.setAttribute(Qt.WA_DeleteOnClose, True)
self.core = core
self.offline = offline
self.image_thread = None
self.steam_thread = None
if os.name == "nt":
self.finished = True
self.completed = True
self.steam_info.setVisible(False)
self.steam_prog_bar.setVisible(False)
self.core = core
if not offline:
self.login_thread = LoginThread(core)
self.login_thread.login.connect(self.login)
self.login_thread.start_app.connect(self.launch)
self.login_thread.start()
else:
self.launch(offline)
def login(self):
self.hide()
if LoginDialog(core=self.core).login():
self.show()
self.login_thread.start()
else:
exit(0)
do_launch = True
try:
if self.offline:
pass
else:
if self.core.login():
logger.info("You are logged in")
else:
raise ValueError("You are not logged in. Open Login Window")
except ValueError as e:
logger.info(str(e))
do_launch = LoginDialog(core=self.core, parent=self).login()
except ConnectionError as e:
logger.warning(e)
self.offline = True
finally:
if do_launch:
self.show()
self.launch()
else:
self.quit_app.emit(0)
def launch(self, offline=False):
def launch(self):
# self.core = core
if not os.path.exists(p := os.path.expanduser("~/.cache/rare/images")):
os.makedirs(p)
self.offline = offline
if not offline:
if not self.offline:
self.image_info.setText(self.tr("Downloading Images"))
self.img_thread = ImageThread(self.core, self)
self.img_thread.download_progess.connect(self.update_image_progbar)
self.img_thread.finished.connect(self.finish)
self.img_thread.start()
self.image_thread = ImageThread(self.core, self)
self.image_thread.download_progess.connect(self.update_image_progbar)
self.image_thread.finished.connect(self.finish)
self.image_thread.finished.connect(lambda: self.image_info.setText(self.tr("Ready")))
self.image_thread.finished.connect(self.image_thread.quit)
self.image_thread.finished.connect(self.image_thread.deleteLater)
self.image_thread.start()
# not disabled and not windows
if (not QSettings().value("disable_protondb", False, bool)) and (not os.name == "nt"):
self.steam_thread = SteamThread(self.core, self)
self.steam_thread.progress.connect(self.update_steam_prog_bar)
self.steam_thread.action.connect(lambda x: self.steam_info.setText(x))
self.steam_thread.finished.connect(self.finish)
self.steam_thread.finished.connect(lambda: self.steam_info.setText(self.tr("Ready")))
self.steam_thread.finished.connect(self.steam_thread.quit)
self.steam_thread.finished.connect(self.steam_thread.deleteLater)
self.steam_thread.start()
else:
self.finished = True
self.completed = True
self.steam_info.setVisible(False)
self.steam_prog_bar.setVisible(False)
@ -151,10 +143,10 @@ class LaunchDialog(QDialog, Ui_LaunchDialog):
self.image_prog_bar.setValue(i)
def finish(self):
if self.finished:
if self.completed:
self.image_info.setText(self.tr("Starting..."))
self.image_prog_bar.setValue(100)
self.steam_prog_bar.setValue(100)
self.start_app.emit(self.offline)
else:
self.finished = True
self.completed = True

View file

@ -1,96 +1,103 @@
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QStackedLayout, QWidget, QPushButton
from dataclasses import dataclass
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog
from custom_legendary.core import LegendaryCore
# Login Opportunities: Browser, Import
from logging import getLogger
from rare.components.dialogs.login.browser_login import BrowserLogin
from rare.components.dialogs.login.import_widget import ImportWidget
from rare.components.dialogs.login.import_login import ImportLogin
# Login Opportunities: Browser, Import
from rare.ui.components.dialogs.login.login_dialog import Ui_LoginDialog
logger = getLogger("Login")
class LoginDialog(QDialog):
@dataclass
class LoginPages:
landing: int
browser: int
import_egl: int
success: int
class LoginDialog(QDialog, Ui_LoginDialog):
logged_in: bool = False
pages = LoginPages(landing=0, browser=1, import_egl=2, success=3)
def __init__(self, core: LegendaryCore):
super(LoginDialog, self).__init__()
def __init__(self, core: LegendaryCore, parent=None):
super(LoginDialog, self).__init__(parent=parent)
self.setupUi(self)
self.setAttribute(Qt.WA_DeleteOnClose, True)
self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint)
self.core = core
self.setWindowTitle("Rare - Login")
self.setFixedWidth(350)
self.setFixedHeight(450)
self.init_ui()
self.browser_page = BrowserLogin(self.core, self.login_stack)
self.login_stack.insertWidget(self.pages.browser, self.browser_page)
self.browser_page.success.connect(self.login_successful)
self.browser_page.changed.connect(
lambda: self.next_button.setEnabled(self.browser_page.is_valid())
)
self.import_page = ImportLogin(self.core, self.login_stack)
self.login_stack.insertWidget(self.pages.import_egl, self.import_page)
self.import_page.success.connect(self.login_successful)
self.import_page.changed.connect(
lambda: self.next_button.setEnabled(self.import_page.is_valid())
)
def init_ui(self):
self.layout = QStackedLayout()
self.next_button.setEnabled(False)
self.back_button.setEnabled(False)
self.landing_widget = QWidget()
self.landing_layout = QVBoxLayout()
self.login_browser_radio.clicked.connect(lambda: self.next_button.setEnabled(True))
self.login_import_radio.clicked.connect(lambda: self.next_button.setEnabled(True))
self.exit_button.clicked.connect(self.close)
self.back_button.clicked.connect(self.back_clicked)
self.next_button.clicked.connect(self.next_clicked)
self.title = QLabel(f"<h1>{self.tr('Welcome to Rare')}</h1>")
self.landing_layout.addWidget(self.title)
self.info_text = QLabel(self.tr("Select one option to Login"))
self.landing_layout.addWidget(self.info_text)
self.login_stack.setCurrentIndex(self.pages.landing)
self.browser_login = OptionWidget(self.tr("Use Browser"),
self.tr("This opens your default browser. Login and copy the text"))
self.resize(self.minimumSizeHint())
self.setFixedSize(self.size())
self.landing_layout.addWidget(self.browser_login)
self.browser_login.button.clicked.connect(lambda: self.layout.setCurrentIndex(1))
def back_clicked(self):
self.back_button.setEnabled(False)
self.next_button.setEnabled(True)
self.login_stack.setCurrentIndex(self.pages.landing)
self.import_login = OptionWidget("Import from existing installation",
"Import an existing login session from an Epic Games Launcher installation. You will get logged out there")
self.import_login.button.clicked.connect(lambda: self.layout.setCurrentIndex(2))
self.landing_layout.addWidget(self.import_login)
self.close_button = QPushButton("Exit App")
self.close_button.clicked.connect(self.close)
self.landing_layout.addWidget(self.close_button)
self.landing_widget.setLayout(self.landing_layout)
self.layout.addWidget(self.landing_widget)
self.browser_widget = BrowserLogin(self.core)
self.browser_widget.success.connect(self.success)
self.browser_widget.back.clicked.connect(lambda: self.layout.setCurrentIndex(0))
self.layout.addWidget(self.browser_widget)
self.import_widget = ImportWidget(self.core)
self.import_widget.back.clicked.connect(lambda: self.layout.setCurrentIndex(0))
self.import_widget.success.connect(self.success)
self.layout.addWidget(self.import_widget)
self.layout.addWidget(LoginSuccessfulWidget())
self.setLayout(self.layout)
def next_clicked(self):
if self.login_stack.currentIndex() == self.pages.landing:
if self.login_browser_radio.isChecked():
self.login_stack.setCurrentIndex(self.pages.browser)
self.next_button.setEnabled(False)
if self.login_import_radio.isChecked():
self.login_stack.setCurrentIndex(self.pages.import_egl)
self.next_button.setEnabled(self.import_page.is_valid())
self.back_button.setEnabled(True)
elif self.login_stack.currentIndex() == self.pages.browser:
self.browser_page.do_login()
elif self.login_stack.currentIndex() == self.pages.import_egl:
self.import_page.do_login()
else:
self.close()
def login(self):
self.exec_()
return self.logged_in
def success(self):
if self.core.login():
self.logged_in = True
self.layout.setCurrentIndex(3)
# time.sleep(1)
self.close()
class OptionWidget(QWidget):
def __init__(self, btn_text: str, info_text: str):
super(OptionWidget, self).__init__()
self.layout = QVBoxLayout()
self.text = QLabel(info_text)
self.text.setWordWrap(True)
self.button = QPushButton(btn_text)
self.layout.addWidget(self.button)
self.layout.addWidget(self.text)
self.setLayout(self.layout)
class LoginSuccessfulWidget(QWidget):
def __init__(self):
super(LoginSuccessfulWidget, self).__init__()
self.layout = QVBoxLayout()
self.layout.addWidget(QLabel("Login Successful"))
self.setLayout(self.layout)
def login_successful(self):
try:
if self.core.login():
self.logged_in = True
self.welcome_label.setText(
self.welcome_label.text().replace("</h1>", f", {self.core.lgd.userdata['displayName']}</h1>")
)
self.exit_button.setVisible(False)
self.back_button.setVisible(False)
self.login_stack.setCurrentIndex(self.pages.success)
else:
raise ValueError("Login failed.")
except ValueError as e:
logger.error(str(e))
self.next_button.setEnabled(False)
self.logged_in = False

View file

@ -1,54 +1,49 @@
import json
from logging import getLogger
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel, QLineEdit
from PyQt5.QtCore import pyqtSignal, QUrl
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QWidget
from custom_legendary.core import LegendaryCore
from rare.ui.components.dialogs.login.browser_login import Ui_BrowserLogin
logger = getLogger("BrowserLogin")
class BrowserLogin(QWidget):
class BrowserLogin(QWidget, Ui_BrowserLogin):
success = pyqtSignal()
url: str = "https://www.epicgames.com/id/login?redirectUrl=https%3A%2F%2Fwww.epicgames.com%2Fid%2Fapi%2Fredirect"
changed = pyqtSignal()
login_url = "https://www.epicgames.com/id/login?redirectUrl=https%3A%2F%2Fwww.epicgames.com%2Fid%2Fapi%2Fredirect"
def __init__(self, core: LegendaryCore, parent=None):
super(BrowserLogin, self).__init__(parent=parent)
self.setupUi(self)
def __init__(self, core: LegendaryCore):
super(BrowserLogin, self).__init__()
self.layout = QVBoxLayout()
self.core = core
self.back = QPushButton("Back") # TODO Icon
self.layout.addWidget(self.back)
self.open_button.clicked.connect(self.open_browser)
self.sid_edit.textChanged.connect(self.changed.emit)
self.info_text = QLabel(self.tr(
"Opens a browser. You login and copy the json code in the field below. Click <a href='{}'>here</a> to open Browser").format(
self.url))
self.info_text.setWordWrap(True)
self.info_text.setOpenExternalLinks(True)
self.layout.addWidget(self.info_text)
def is_valid(self):
return len(self.sid_edit.text()) == 32
self.input_field = QLineEdit()
self.input_field.setPlaceholderText(self.tr("Insert SID here"))
self.layout.addWidget(self.input_field)
self.mini_info = QLabel("")
self.login_btn = QPushButton(self.tr("Login"))
self.login_btn.clicked.connect(self.login)
self.layout.addWidget(self.login_btn)
self.setLayout(self.layout)
def login(self):
self.mini_info.setText(self.tr("Loading..."))
sid = self.input_field.text()
def do_login(self):
self.status_label.setText(self.tr("Logging in..."))
sid = self.sid_edit.text()
# when the text copied
if sid.startswith("{") and sid.endswith("}"):
sid = json.loads(sid)["sid"]
token = self.core.auth_sid(sid)
if self.core.auth_code(token):
logger.info(f"Successfully logged in as {self.core.lgd.userdata['displayName']}")
self.success.emit()
else:
self.mini_info.setText("Login failed")
try:
token = self.core.auth_sid(sid)
if self.core.auth_code(token):
logger.info(f"Successfully logged in as {self.core.lgd.userdata['displayName']}")
self.success.emit()
else:
self.status_label.setText(self.tr("Login failed."))
logger.warning("Failed to login through browser")
except Exception as e:
logger.warning(e)
def open_browser(self):
QDesktopServices.openUrl(QUrl(self.login_url))

View file

@ -0,0 +1,95 @@
import os
from getpass import getuser
from logging import getLogger
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QFileDialog
from custom_legendary.core import LegendaryCore
from rare.ui.components.dialogs.login.import_login import Ui_ImportLogin
logger = getLogger("ImportLogin")
class ImportLogin(QWidget, Ui_ImportLogin):
success = pyqtSignal()
changed = pyqtSignal()
if os.name == "nt":
localappdata = os.path.expandvars("%LOCALAPPDATA%")
else:
localappdata = os.path.join("drive_c/users", getuser(), "Local Settings/Application Data")
appdata_path = os.path.join(localappdata, "EpicGamesLauncher/Saved/Config/Windows")
found = False
def __init__(self, core: LegendaryCore, parent=None):
super(ImportLogin, self).__init__(parent=parent)
self.setupUi(self)
self.core = core
self.text_egl_found = self.tr("Found EGL Program Data. Click 'Next' to import them.")
self.text_egl_notfound = self.tr("Could not find EGL Program Data. ")
if os.name == "nt":
if not self.core.egl.appdata_path and os.path.exists(self.egl_data_path):
self.core.egl.appdata_path = self.appdata_path
if not self.core.egl.appdata_path:
self.status_label.setText(self.text_egl_notfound)
else:
self.status_label.setText(self.text_egl_found)
self.found = True
else:
self.info_label.setText(self.tr(
"Please select the Wine prefix"
" where Epic Games Launcher is installed. ") + self.info_label.text()
)
prefixes = self.get_wine_prefixes()
if len(prefixes):
self.prefix_combo.addItems(prefixes)
self.status_label.setText(self.tr("Select the Wine prefix you want to import."))
else:
self.status_label.setText(self.text_egl_notfound)
self.prefix_tool.clicked.connect(self.prefix_path)
self.prefix_combo.editTextChanged.connect(self.changed.emit)
def get_wine_prefixes(self):
possible_prefixes = [
os.path.expanduser("~/.wine"),
os.path.expanduser("~/Games/epic-games-store"),
]
prefixes = []
for prefix in possible_prefixes:
if os.path.exists(os.path.join(prefix, self.appdata_path)):
prefixes.append(prefix)
return prefixes
def prefix_path(self):
prefix_dialog = QFileDialog(self, self.tr("Choose path"), os.path.expanduser("~/"))
prefix_dialog.setFileMode(QFileDialog.DirectoryOnly)
if prefix_dialog.exec_():
names = prefix_dialog.selectedFiles()
self.prefix_combo.setCurrentText(names[0])
def is_valid(self):
if os.name == "nt":
return self.found
else:
return os.path.exists(os.path.join(self.prefix_combo.currentText(), self.appdata_path))
def do_login(self):
self.status_label.setText(self.tr("Loading..."))
if os.name == "nt":
pass
else:
self.core.egl.appdata_path = os.path.join(self.prefix_combo.currentText(), self.appdata_path)
try:
if self.core.auth_import():
logger.info(f"Logged in as {self.core.lgd.userdata['displayName']}")
self.success.emit()
else:
self.status_label.setText(self.tr("Login failed."))
logger.warning("Failed to import existing session.")
except Exception as e:
self.status_label.setText(self.tr("Login failed. ") + str(e))
logger.warning("Failed to import existing session: " + str(e))

View file

@ -1,103 +0,0 @@
import os
from getpass import getuser
from logging import getLogger
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel, QButtonGroup, QRadioButton
from custom_legendary.core import LegendaryCore
logger = getLogger("Import")
class ImportWidget(QWidget):
success = pyqtSignal()
def __init__(self, core: LegendaryCore):
super(ImportWidget, self).__init__()
self.layout = QVBoxLayout()
self.core = core
self.back = QPushButton("Back")
self.layout.addWidget(self.back)
self.title = QLabel("<h3>Import existing Login session</h3>")
self.title.setWordWrap(True)
self.layout.addWidget(self.title)
self.infoText = QLabel(
"Found Installations here. \nPlease select prefix, where Epic Games Launcher is installed\nNote: You will get logged out there")
self.infoText.setWordWrap(True)
self.layout.addWidget(self.infoText)
self.import_button = QPushButton(self.tr("Import"))
self.data_path = ""
if os.name == "nt":
if not self.core.egl.appdata_path and os.path.exists(
os.path.expandvars("%LOCALAPPDATA%/EpicGamesLauncher/Saved/Config/Windows")):
self.core.egl.appdata_path = os.path.expandvars("%LOCALAPPDATA%/EpicGamesLauncher/Saved/Config/Windows")
if not self.core.egl.appdata_path:
self.text = QLabel(self.tr("Could not find EGL program data"))
else:
self.text = QLabel(self.tr("Found EGL program Data. Do you want to import them?"))
self.layout.addWidget(self.text)
# Linux
else:
self.radio_buttons = []
prefixes = self.get_wine_prefixes()
if len(prefixes) == 0:
self.infoText.setText(self.tr("Could not find any Epic Games login data"))
self.import_button.setDisabled(True)
else:
self.btn_group = QButtonGroup()
for i in prefixes:
radio_button = QRadioButton(i)
self.radio_buttons.append(radio_button)
self.btn_group.addButton(radio_button)
self.layout.addWidget(radio_button)
radio_button.toggled.connect(self.toggle_radiobutton)
self.login_text = QLabel("")
self.layout.addWidget(self.login_text)
self.layout.addWidget(self.import_button)
self.import_button.clicked.connect(self.import_login_data)
self.setLayout(self.layout)
def toggle_radiobutton(self):
if self.sender().isChecked():
self.data_path = self.sender().text()
def get_wine_prefixes(self):
possible_prefixes = [
os.path.expanduser("~/.wine"),
os.path.expanduser("~/Games/epic-games-store")
]
prefixes = []
for i in possible_prefixes:
if os.path.exists(os.path.join(i, "drive_c/users", getuser(),
"Local Settings/Application Data/EpicGamesLauncher/Saved/Config/Windows")):
prefixes.append(i)
return prefixes
def import_login_data(self):
self.import_button.setText(self.tr("Loading..."))
self.import_button.setDisabled(True)
if os.name != "nt":
self.core.egl.appdata_path = os.path.join(self.data_path,
f"drive_c/users/{getuser()}/Local Settings/Application Data/EpicGamesLauncher/Saved/Config/Windows")
try:
if self.core.auth_import():
logger.info(f"Logged in as {self.core.lgd.userdata['displayName']}")
self.success.emit()
else:
logger.warning("Failed to import existing session")
except Exception as e:
logger.warning(e)
logger.warning("Error: No valid session found")
self.login_text.setText(self.tr("Error: No valid session found"))
self.import_button.setText(self.tr("Import"))
self.import_button.setDisabled(False)

View file

@ -1,11 +1,11 @@
import os
from logging import getLogger
from PyQt5.QtCore import QSettings, QTimer
from PyQt5.QtCore import Qt, QSettings, QTimer, pyqtSignal
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtWidgets import QMainWindow, QMessageBox, QApplication
from custom_legendary.core import LegendaryCore
from rare.components.tab_widget import TabWidget
from rare.utils.rpc import DiscordRPC
@ -13,9 +13,11 @@ logger = getLogger("Window")
class MainWindow(QMainWindow):
quit_app = pyqtSignal(int)
def __init__(self, core: LegendaryCore, args):
super(MainWindow, self).__init__()
self.setAttribute(Qt.WA_DeleteOnClose)
self.settings = QSettings()
self.core = core
self.offline = args.offline
@ -28,6 +30,7 @@ class MainWindow(QMainWindow):
self.setWindowTitle("Rare - GUI for legendary")
self.tab_widget = TabWidget(core, self, args.offline)
self.tab_widget.quit_app.connect(self.quit_app.emit)
self.setCentralWidget(self.tab_widget)
if not args.offline:
self.rpc = DiscordRPC(core)

View file

@ -18,6 +18,7 @@ from rare.utils.models import InstallQueueItemModel, InstallOptionsModel
class TabWidget(QTabWidget):
quit_app = pyqtSignal(int)
delete_presence = pyqtSignal()
def __init__(self, core: LegendaryCore, parent, offline):
@ -52,8 +53,10 @@ class TabWidget(QTabWidget):
self.addTab(self.account, "")
self.setTabEnabled(disabled_tab + 1, False)
self.mini_widget = MiniWidget(core)
self.mini_widget.quit_app.connect(self.quit_app.emit)
account_action = QWidgetAction(self)
account_action.setDefaultWidget(MiniWidget(core))
account_action.setDefaultWidget(self.mini_widget)
account_button = TabButtonWidget(core, 'mdi.account-circle', 'Account')
account_button.setMenu(QMenu())
account_button.menu().addAction(account_action)
@ -78,13 +81,22 @@ class TabWidget(QTabWidget):
# show uninstalled info
self.games_tab.default_widget.game_list.show_uninstalled_info.connect(self.games_tab.show_uninstalled)
# install dlc
self.games_tab.game_info.dlc_tab.install_dlc.connect(self.install_game)
self.games_tab.game_info.dlc_tab.install_dlc.connect(
lambda app_name, update: self.install_game(
InstallOptionsModel(app_name=app_name),
update=update))
# install game
self.games_tab.uninstalled_info_widget.info.install_game.connect(self.install_game)
self.games_tab.uninstalled_info_widget.info.install_game.connect(
lambda app_name: self.install_game(
InstallOptionsModel(app_name=app_name)))
# repair game
self.games_tab.game_info.info.verify_game.connect(lambda app_name: self.start_download(
InstallOptionsModel(app_name, core.get_installed_game(app_name).install_path, repair=True)))
self.games_tab.game_info.info.verify_game.connect(
lambda app_name: self.install_game(
InstallOptionsModel(app_name=app_name,
base_path=core.get_installed_game(app_name).install_path,
repair=True),
silent=True))
# Finished sync
self.cloud_saves.finished.connect(self.finished_sync)
@ -95,10 +107,11 @@ class TabWidget(QTabWidget):
self.tabBarClicked.connect(lambda x: self.games_tab.layout.setCurrentIndex(0) if x == 0 else None)
self.setIconSize(QSize(25, 25))
def install_game(self, app_name, disable_path=False):
# TODO; maybe pass InstallOptionsModel only, not split arguments
def install_game(self, options: InstallOptionsModel, update=False, silent=False):
install_dialog = InstallDialog(self.core,
InstallQueueItemModel(options=InstallOptionsModel(app_name=app_name)),
update=disable_path, parent=self)
InstallQueueItemModel(options=options),
update=update, silent=silent, parent=self)
install_dialog.result_ready.connect(self.on_install_dialog_closed)
install_dialog.execute()
@ -107,11 +120,11 @@ class TabWidget(QTabWidget):
self.setCurrentIndex(1)
self.start_download(download_item)
def start_download(self, options):
def start_download(self, download_item: InstallQueueItemModel):
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) + 1
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
self.setCurrentIndex(1)
self.downloadTab.install_game(options)
self.downloadTab.install_game(download_item)
def game_imported(self, app_name: str):
igame = self.core.get_installed_game(app_name)

View file

@ -1,12 +1,14 @@
import webbrowser
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QMessageBox, QLabel, QPushButton
from custom_legendary.core import LegendaryCore
class MiniWidget(QWidget):
quit_app = pyqtSignal(int)
def __init__(self, core: LegendaryCore):
super(MiniWidget, self).__init__()
self.layout = QVBoxLayout()
@ -39,5 +41,4 @@ class MiniWidget(QWidget):
if reply == QMessageBox.Yes:
self.core.lgd.invalidate_userdata()
# restart app
QCoreApplication.instance().exit(-133742) # restart exit code
self.quit_app.emit(-133742) # restart exit code

View file

@ -115,9 +115,6 @@ class GameSettings(QWidget, Ui_GameSettings):
if self.change:
# Dont use Proton
if i == 0:
self.proton_prefix.setEnabled(False)
self.wrapper_widget.setEnabled(True)
self.linux_settings.wine_groupbox.setEnabled(True)
if f"{self.game.app_name}" in self.core.lgd.config.sections():
if self.core.lgd.config.get(f"{self.game.app_name}", "wrapper", fallback=False):
self.core.lgd.config.remove_option(self.game.app_name, "wrapper")
@ -130,6 +127,13 @@ class GameSettings(QWidget, Ui_GameSettings):
self.core.lgd.config.remove_option(f"{self.game.app_name}.env", "STEAM_COMPAT_DATA_PATH")
if not self.core.lgd.config[self.game.app_name + ".env"]:
self.core.lgd.config.remove_section(self.game.app_name + ".env")
self.proton_prefix.setEnabled(False)
# lk: TODO: This has to be fixed properly.
# lk: It happens because of the widget update. Mask it for now behind disabling the save button
self.wrapper.setText(self.core.lgd.config.get(f"{self.game.app_name}", "wrapper", fallback=""))
self.wrapper_button.setDisabled(True)
self.wrapper_widget.setEnabled(True)
self.linux_settings.wine_groupbox.setEnabled(True)
else:
self.proton_prefix.setEnabled(True)
self.wrapper_widget.setEnabled(False)

View file

@ -1,13 +1,15 @@
import os
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QSystemTrayIcon, QMenu, QAction
from rare import style_path
from rare import resources_path
class TrayIcon(QSystemTrayIcon):
def __init__(self, parent):
super(TrayIcon, self).__init__(parent)
self.setIcon(QIcon(style_path + "Logo.png"))
self.setIcon(QIcon(os.path.join(resources_path, "images", "Rare.png")))
self.setVisible(True)
self.setToolTip("Rare")

View file

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1 @@
<svg height="736" viewBox="0 0 736 736" width="736" xmlns="http://www.w3.org/2000/svg"><path d="m368 120c-137 0-248 111-248 248s111 248 248 248 248-111 248-248-111-248-248-248z" fill="#43474d"/></svg>

After

Width:  |  Height:  |  Size: 200 B

View file

@ -0,0 +1 @@
<svg height="736" viewBox="0 0 736 736" width="736" xmlns="http://www.w3.org/2000/svg"><path d="m368 120c-137 0-248 111-248 248s111 248 248 248 248-111 248-248-111-248-248-248z" fill="#483d8b"/></svg>

After

Width:  |  Height:  |  Size: 200 B

View file

@ -0,0 +1 @@
<svg height="640" viewBox="0 0 320 640" width="320" xmlns="http://www.w3.org/2000/svg"><path d="m41 236.475h238c21.4 0 32.1 25.9 17 41l-119 119c-9.4 9.4-24.6 9.4-33.9 0l-119.1-119c-15.1-15.1-4.4-41 17-41z" fill="#eee"/></svg>

After

Width:  |  Height:  |  Size: 225 B

View file

@ -0,0 +1 @@
<svg height="320" viewBox="0 0 320 320" width="320" xmlns="http://www.w3.org/2000/svg"><path d="m41 76.475h238c21.4 0 32.1 25.9 17 41l-119 119c-9.4 9.4-24.6 9.4-33.9 0l-119.1-119c-15.1-15.1-4.4-41 17-41z" fill="#eee"/></svg>

After

Width:  |  Height:  |  Size: 224 B

View file

@ -0,0 +1 @@
<svg height="320" viewBox="0 0 320 320" width="320" xmlns="http://www.w3.org/2000/svg"><path d="m279.01546 243.525h-237.999997c-21.4 0-32.1000001-25.9-17-41l118.999997-119c9.4-9.4 24.6-9.4 33.9 0l119 119c15.2 15.1 4.5 41-16.9 41z" fill="#eee"/></svg>

After

Width:  |  Height:  |  Size: 250 B

View file

@ -0,0 +1 @@
<svg height="688" viewBox="0 0 688 688" width="688" xmlns="http://www.w3.org/2000/svg"><path d="m520 120h-352c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-352c0-26.5-21.5-48-48-48z" fill="#43474d"/></svg>

After

Width:  |  Height:  |  Size: 232 B

View file

@ -0,0 +1 @@
<svg height="688" viewBox="0 0 688 688" width="688" xmlns="http://www.w3.org/2000/svg"><path d="m520 120h-352c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-352c0-26.5-21.5-48-48-48z" fill="#483d8b"/></svg>

After

Width:  |  Height:  |  Size: 232 B

View file

@ -0,0 +1,355 @@
/*
$active_base = #202225;
$active_text = #eeeeee;
$widget_base = #333344;
$primary_border = #42474E;
$secondary_border = darkslategrey;
*/
* { background-color: #202225; }
* { color: #eeeeee; }
* { border-color: #483d8b; }
*::disabled,
*::drop-down:disabled {
color: #43474d;
border-color: #43474d;
background-color: #202225;
}
QLabel {
border-width: 0px;
background-color: transparent;
padding: 0px;
}
QMenu,
QListView,
QListWidget,
QFrame[frameShape="6"],
QLineEdit,
QTextEdit,
QTimeEdit,
QDateEdit,
QDateTimeEdit,
QComboBox,
QComboBox:editable,
QComboBox QAbstractItemView,
QSpinBox,
QDoubleSpinBox,
QProgressBar,
QScrollBar {
border-width: 1px;
border-style: solid;
border-radius: 2px;
padding: 2px;
}
QListView,
QListWidget,
QLineEdit,
QTextEdit,
QTimeEdit,
QDateEdit,
QDateTimeEdit,
QComboBox:editable,
QComboBox QAbstractItemView,
QSpinBox,
QDoubleSpinBox,
QProgressBar,
QScrollBar {
border-color: #2f4f4f;
background-color: #333344;
selection-background-color: #2f4f4f;
}
QLineEdit,
QTextEdit,
QTimeEdit,
QDateEdit,
QDateTimeEdit,
QComboBox
QSpinBox,
QDoubleSpinBox,
QProgressBar,
QPushButton {
height: 17px;
}
QToolButton {
height: 14px;
}
QFrame[frameShape="6"] {
border-radius: 4px;
}
QComboBox {
background-color: #3c3f41;
}
*::item:selected,
QComboBox QAbstractItemView {
selection-background-color: #2f4f4f;
}
*::drop-down,
*::drop-down:editable,
*::up-button,
*::down-button {
subcontrol-origin: border;
border-width: 1px;
border-style: solid;
border-radius: 2px;
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
*::drop-down {
subcontrol-position: top right;
border-color: #483d8b;
border-left-color: #5246a0; /* #483d8b lighter */
}
*::drop-down:editable,
*::up-button ,
*::down-button {
border-color: #2f4f4f;
background-color: #3c3f41;
}
*::drop-down,
*::drop-down:editable {
width: 14px;
image: url(@path@drop-down.svg);
}
*::up-button ,
*::down-button {
width: 14px; /* 16 + 2*1px border-width = 15px padding + 3px parent border */
}
*::up-button {
subcontrol-position: top right; /* position at the top right corner */
border-bottom-width: 1;
image: url(@path@sort-up.svg);
}
*::down-button {
subcontrol-position: bottom right; /* position at bottom right corner */
border-top-width: 1;
image: url(@path@sort-down.svg);
}
QProgressBar {
text-align: center;
}
QProgressBar::chunk {
width: 9.5%;
margin: 0.5%;
background-color: #2f4f4f;
}
QScrollBar {
border-radius: 6px;
padding: 1px;
}
QScrollBar::add-line:vertical,
QScrollBar::sub-line:vertical,
QScrollBar::add-line:horizontal,
QScrollBar::sub-line:horizontal {
border: none;
height: 0px;
background: transparent;
}
QScrollBar::add-line:vertical {
subcontrol-position: top;
subcontrol-origin: margin;
}
QScrollBar::sub-line:vertical {
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::add-line:horizontal {
subcontrol-position: right;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal {
subcontrol-position: left;
subcontrol-origin: margin;
}
QScrollBar::handle {
border-width: 1px;
border-style: solid;
border-color: lightgray;
background-color: gray;
border-radius: 4px;
min-height: 20px;
min-width: 20px;
}
QPushButton,
QToolButton {
background-color: #3c3f41;
}
QPushButton::hover,
QToolButton::hover {
background-color: #222233;
}
QPushButton,
QToolButton {
border-width: 1px;
border-style: solid;
border-radius: 2px;
padding: 2px;
padding-left: 6px;
padding-right: 6px
}
QPushButton::menu-indicator {
subcontrol-position: right center;
subcontrol-origin: padding;
left: -2px;
border-style: none;
}
QPushButton#menu {
padding: 0px;
margin: 0px;
border-style: none;
}
QPushButton#menu_button {
background-color: transparent;
border: none;
}
QPushButton:hover#menu_button {
background-color: #334;
}
QPushButton#install_button {
background-color: #090;
}
QPushButton::hover#install_button {
background-color: #060;
}
QPushButton::disabled#install_button {
background-color: #020;
}
QPushButton#uninstall_button {
background-color: #900;
}
QPushButton::hover#uninstall_button {
background-color: #600;
}
QPushButton::disabled#uninstall_button {
background-color: #200;
}
QPushButton#success{
background-color: lime;
}
QGroupBox,
QCheckBox,
QRadioButton {
background-color: none;
}
QGroupBox::indicator,
QCheckBox::indicator,
QRadioButton::indicator {
border-color: #2f4f4f;
border-width: 1px;
border-style: solid;
}
QCheckBox::indicator,
QRadioButton::indicator {
width: 11px;
height: 11px;
}
QGroupBox::indicator:disabled,
QCheckBox::indicator:disabled,
QRadioButton::indicator:disabled {
border-color: #43474d;
}
QRadioButton::indicator {
border-radius: 5%;
}
QGroupBox::indicator,
QCheckBox::indicator {
border-radius: 2px;
}
QGroupBox::indicator:checked,
QCheckBox::indicator:checked {
border-radius: 2px;
image: url(@path@square.svg);
}
QRadioButton::indicator:checked {
border-radius: 5%;
image: url(@path@circle.svg);
}
QGroupBox::indicator:checked:disabled,
QCheckBox::indicator:checked:disabled {
image: url(@path@square-disabled.svg);
}
QRadioButton::indicator:checked:disabled {
image: url(@path@circle-disabled.svg);
}
QGroupBox,
QGroupBox#group,
QGroupBox#settings_widget {
border-width: 1px;
border-style: solid;
border-radius: 4px;
font-size: 11px;
font-weight: bold;
margin-top: 3ex;
padding: 1px;
}
QGroupBox#game_widget_icon {
border: none;
padding: 0px;
margin: 0px;
}
QSizeGrip {
image: none;
width: 4px;
height: 4px;
}
#list_widget {
border-top-width: 2px;
}
#search_bar {
padding: 3px;
border-radius: 5px;
background-color: #334;
}
QPushButton:hover#installed_menu_button {
background-color: green;
}
QTabBar#main_tab_bar {
border-bottom: none;
background-color: #2b2b2c;
}
QTabBar::tab#main_tab_bar {
border-top: 2px solid transparent;
border-bottom: none;
}
QTabBar::tab#main_tab_bar {
border-bottom: none;
padding: 5px;
}
QTabBar::tab:selected#main_tab_bar {
background-color: #202225;
border-top: 2px solid #483d8b;
}
QTabBar::tab:hover#main_tab_bar {
border-top: 2px solid #483d8b;
}
QTabBar::tab#settings_bar {
border-radius: 0;
}
QTabBar::tab:hover#settings_bar {
border-left: 2px solid white;
}
QTabBar::tab::selected#settings_bar {
background-color: #2f4f4f;
}
QTabBar::tab:disabled#settings_bar {
color: transparent;
background-color: transparent;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -1,266 +0,0 @@
QWidget {
background-color: #202225;
color: #eee;
}
QLabel {
background-color: transparent;
padding: 4px;
}
QLineEdit {
border: 1px solid darkslategrey;
border-radius: 2px;
background-color: #334;
padding: 2px;
}
QScrollBar {
border: 1px solid darkslategrey;
border-radius: 4px;
background-color: #334;
padding: 1px;
}
QScrollBar::add-line:vertical {
border: none;
background: transparent;
height: 0px;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::sub-line:vertical {
border: none;
background: transparent;
height: 0px;
subcontrol-position: top;
subcontrol-origin: margin;
}
QScrollBar::add-line:horizontal {
border: none;
background: transparent;
height: 0px;
subcontrol-position: right;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal {
border: none;
background: green;
height: 0px;
subcontrol-position: left;
subcontrol-origin: margin;
}
QScrollBar::handle {
border: 1px solid darkslategrey;
background-color: gray;
border-radius: 4px;
min-height: 20px;
min-width: 20px;
}
QTabBar#main_tab_bar {
border-bottom: none;
background-color: #2b2b2c;
}
QTabBar::tab#main_tab_bar {
border-bottom: none;
}
QTabBar::tab#main_tab_bar {
border-bottom: none;
padding: 5px
}
QTabBar::tab:selected#main_tab_bar {
background-color: gray;
}
QTabBar::tab:hover#main_tab_bar {
border-bottom: 2px solid black;
}
QGroupBox {
border: 1px solid gray;
font-size: 13px;
font-weight: bold;
border-radius: 6px;
margin-top: 3ex;
padding-top: 0px;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
}
QGroupBox#settings_widget {
border: 1px solid gray;
font-size: 13px;
font-weight: bold;
border-radius: 6px;
margin-top: 3ex;
padding-top: 0px;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
}
QGroupBox#game_widget_icon {
border: none;
padding: 0;
margin: 0;
}
QGroupBox#group {
border: 1px solid gray;
font-size: 13px;
font-weight: bold;
border-radius: 6px;
margin-top: 3ex;
padding-top: 0px;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
}
QToolButton {
border: 1px solid gray;
border-radius: 2px;
background-color: #3c3f41;
padding: 4px;
}
QToolButton:hover {
background-color: #223;
}
QPushButton {
border: 1px solid gray;
border-radius: 2px;
background-color: #3c3f41;
padding: 5px;
}
QPushButton:hover {
background-color: #223;
}
QPushButton::menu-indicator {
subcontrol-position: right center;
subcontrol-origin: padding;
left: -2px;
border-style: none;
}
QPushButton#menu {
padding: 0px;
margin: 0px;
border-style: none;
}
QPushButton#menu_button {
background-color: transparent;
border: none;
}
QPushButton:hover#menu_button {
background-color: #334;
}
QPushButton#success{
background-color: lime;
}
QRadioButton {
background-color: none;
border-radius: 50%;
}
QRadioButton::indicator {
border: 1px solid gray;
border-radius: 5%;
}
QCheckBox {
background-color: none;
}
QCheckBox::indicator {
border: 1px solid gray;
border-radius: 2px;
}
QCheckBox::indicator:checked {
width: -20ex;
height: -20ex;
background: #5F5F80;
border-radius: 10px;
}
QSpinBox {
border: 1px solid darkslategrey;
border-radius: 2px;
background-color: #334;
padding: 2px;
}
/*
QCheckBox::indicator {
border: 1px solid gray;
}
*/
QComboBox {
border: 1px solid gray;
border-radius: 2px;
background-color: #3c3f41;
padding: 5px;
}
QComboBox::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
/*
border-left-width: 1px;
border-left-color: darkgray;
border-left-style: solid;
*/
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
#list_widget {
border-top: 2px solid white;
}
QPushButton:hover#installed_menu_button {
background-color: green;
}
QTabBar::tab#settings_bar {
border-radius: 0;
}
QTabBar::tab:hover#settings_bar {
border-left: 2px solid white;
}
QTabBar::tab::selected#settings_bar {
background-color: darkslategrey;
}
#search_bar {
padding: 3px;
border-radius: 5px;
background-color: #334;
}
QTabBar::tab:disabled#settings_bar {
color: transparent;
background-color: transparent;
}

View file

@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'browser_login.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_BrowserLogin(object):
def setupUi(self, BrowserLogin):
BrowserLogin.setObjectName("BrowserLogin")
BrowserLogin.resize(246, 130)
BrowserLogin.setWindowTitle("BrowserLogin")
self.browser_layout = QtWidgets.QGridLayout(BrowserLogin)
self.browser_layout.setObjectName("browser_layout")
self.open_button = QtWidgets.QPushButton(BrowserLogin)
self.open_button.setObjectName("open_button")
self.browser_layout.addWidget(self.open_button, 1, 0, 1, 1)
self.title_label = QtWidgets.QLabel(BrowserLogin)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.title_label.setFont(font)
self.title_label.setObjectName("title_label")
self.browser_layout.addWidget(self.title_label, 0, 0, 1, 2, QtCore.Qt.AlignTop)
self.sid_edit = QtWidgets.QLineEdit(BrowserLogin)
self.sid_edit.setObjectName("sid_edit")
self.browser_layout.addWidget(self.sid_edit, 1, 1, 1, 1)
self.info_label = QtWidgets.QLabel(BrowserLogin)
font = QtGui.QFont()
font.setItalic(True)
self.info_label.setFont(font)
self.info_label.setWordWrap(True)
self.info_label.setObjectName("info_label")
self.browser_layout.addWidget(self.info_label, 3, 0, 1, 2, QtCore.Qt.AlignBottom)
self.status_label = QtWidgets.QLabel(BrowserLogin)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.status_label.sizePolicy().hasHeightForWidth())
self.status_label.setSizePolicy(sizePolicy)
self.status_label.setText("")
self.status_label.setObjectName("status_label")
self.browser_layout.addWidget(self.status_label, 2, 1, 1, 1)
self.retranslateUi(BrowserLogin)
QtCore.QMetaObject.connectSlotsByName(BrowserLogin)
def retranslateUi(self, BrowserLogin):
_translate = QtCore.QCoreApplication.translate
self.open_button.setText(_translate("BrowserLogin", "Open Browser"))
self.title_label.setText(_translate("BrowserLogin", "Login through browser"))
self.sid_edit.setPlaceholderText(_translate("BrowserLogin", "Insert SID here"))
self.info_label.setText(_translate("BrowserLogin", "Click the button to open the login page in a browser. After logging in, copy the SID code in the input above."))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
BrowserLogin = QtWidgets.QWidget()
ui = Ui_BrowserLogin()
ui.setupUi(BrowserLogin)
BrowserLogin.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BrowserLogin</class>
<widget class="QWidget" name="BrowserLogin">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>246</width>
<height>130</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">BrowserLogin</string>
</property>
<layout class="QGridLayout" name="browser_layout">
<item row="1" column="0">
<widget class="QPushButton" name="open_button">
<property name="text">
<string>Open Browser</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2" alignment="Qt::AlignTop">
<widget class="QLabel" name="title_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Login through browser</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="sid_edit">
<property name="placeholderText">
<string>Insert SID here</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2" alignment="Qt::AlignBottom">
<widget class="QLabel" name="info_label">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Click the button to open the login page in a browser. After logging in, copy the SID code in the input above.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="status_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'import_login.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_ImportLogin(object):
def setupUi(self, ImportLogin):
ImportLogin.setObjectName("ImportLogin")
ImportLogin.resize(503, 173)
ImportLogin.setWindowTitle("ImportLogin")
self.import_layout = QtWidgets.QGridLayout(ImportLogin)
self.import_layout.setObjectName("import_layout")
self.info_label = QtWidgets.QLabel(ImportLogin)
font = QtGui.QFont()
font.setItalic(True)
self.info_label.setFont(font)
self.info_label.setWordWrap(True)
self.info_label.setObjectName("info_label")
self.import_layout.addWidget(self.info_label, 3, 0, 1, 3, QtCore.Qt.AlignBottom)
self.title_label = QtWidgets.QLabel(ImportLogin)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.title_label.setFont(font)
self.title_label.setObjectName("title_label")
self.import_layout.addWidget(self.title_label, 0, 0, 1, 3, QtCore.Qt.AlignTop)
self.prefix_combo = QtWidgets.QComboBox(ImportLogin)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.prefix_combo.sizePolicy().hasHeightForWidth())
self.prefix_combo.setSizePolicy(sizePolicy)
self.prefix_combo.setEditable(True)
self.prefix_combo.setObjectName("prefix_combo")
self.import_layout.addWidget(self.prefix_combo, 1, 1, 1, 1)
self.prefix_label = QtWidgets.QLabel(ImportLogin)
self.prefix_label.setObjectName("prefix_label")
self.import_layout.addWidget(self.prefix_label, 1, 0, 1, 1)
self.prefix_tool = QtWidgets.QToolButton(ImportLogin)
self.prefix_tool.setObjectName("prefix_tool")
self.import_layout.addWidget(self.prefix_tool, 1, 2, 1, 1)
self.status_label = QtWidgets.QLabel(ImportLogin)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.status_label.sizePolicy().hasHeightForWidth())
self.status_label.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setItalic(True)
self.status_label.setFont(font)
self.status_label.setText("")
self.status_label.setObjectName("status_label")
self.import_layout.addWidget(self.status_label, 2, 1, 1, 2)
self.retranslateUi(ImportLogin)
QtCore.QMetaObject.connectSlotsByName(ImportLogin)
def retranslateUi(self, ImportLogin):
_translate = QtCore.QCoreApplication.translate
self.info_label.setText(_translate("ImportLogin", "You will get logged out from EGL in the process."))
self.title_label.setText(_translate("ImportLogin", "Import existing session from EGL"))
self.prefix_label.setText(_translate("ImportLogin", "Select path"))
self.prefix_tool.setText(_translate("ImportLogin", "Browse"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ImportLogin = QtWidgets.QWidget()
ui = Ui_ImportLogin()
ui.setupUi(ImportLogin)
ImportLogin.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ImportLogin</class>
<widget class="QWidget" name="ImportLogin">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>503</width>
<height>173</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">ImportLogin</string>
</property>
<layout class="QGridLayout" name="import_layout">
<item row="3" column="0" colspan="3" alignment="Qt::AlignBottom">
<widget class="QLabel" name="info_label">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>You will get logged out from EGL in the process.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3" alignment="Qt::AlignTop">
<widget class="QLabel" name="title_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Import existing session from EGL</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="prefix_combo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="prefix_label">
<property name="text">
<string>Select path</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="prefix_tool">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QLabel" name="status_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,131 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'login_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_LoginDialog(object):
def setupUi(self, LoginDialog):
LoginDialog.setObjectName("LoginDialog")
LoginDialog.resize(492, 311)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(LoginDialog.sizePolicy().hasHeightForWidth())
LoginDialog.setSizePolicy(sizePolicy)
self.dialog_layout = QtWidgets.QVBoxLayout(LoginDialog)
self.dialog_layout.setObjectName("dialog_layout")
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.dialog_layout.addItem(spacerItem)
self.welcome_label = QtWidgets.QLabel(LoginDialog)
self.welcome_label.setObjectName("welcome_label")
self.dialog_layout.addWidget(self.welcome_label)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
self.dialog_layout.addItem(spacerItem1)
self.login_stack = QtWidgets.QStackedWidget(LoginDialog)
self.login_stack.setEnabled(True)
self.login_stack.setMinimumSize(QtCore.QSize(480, 135))
self.login_stack.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.login_stack.setFrameShadow(QtWidgets.QFrame.Raised)
self.login_stack.setObjectName("login_stack")
self.login_page = QtWidgets.QWidget()
self.login_page.setEnabled(True)
self.login_page.setObjectName("login_page")
self.login_page_layout = QtWidgets.QGridLayout(self.login_page)
self.login_page_layout.setObjectName("login_page_layout")
self.login_browser_label = QtWidgets.QLabel(self.login_page)
font = QtGui.QFont()
font.setItalic(True)
self.login_browser_label.setFont(font)
self.login_browser_label.setObjectName("login_browser_label")
self.login_page_layout.addWidget(self.login_browser_label, 1, 1, 1, 1)
self.login_label = QtWidgets.QLabel(self.login_page)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.login_label.setFont(font)
self.login_label.setObjectName("login_label")
self.login_page_layout.addWidget(self.login_label, 0, 0, 1, 3, QtCore.Qt.AlignTop)
self.login_import_label = QtWidgets.QLabel(self.login_page)
font = QtGui.QFont()
font.setItalic(True)
self.login_import_label.setFont(font)
self.login_import_label.setObjectName("login_import_label")
self.login_page_layout.addWidget(self.login_import_label, 2, 1, 1, 1)
self.login_import_radio = QtWidgets.QRadioButton(self.login_page)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.login_import_radio.sizePolicy().hasHeightForWidth())
self.login_import_radio.setSizePolicy(sizePolicy)
self.login_import_radio.setObjectName("login_import_radio")
self.login_page_layout.addWidget(self.login_import_radio, 2, 0, 1, 1)
self.login_browser_radio = QtWidgets.QRadioButton(self.login_page)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.login_browser_radio.sizePolicy().hasHeightForWidth())
self.login_browser_radio.setSizePolicy(sizePolicy)
self.login_browser_radio.setObjectName("login_browser_radio")
self.login_page_layout.addWidget(self.login_browser_radio, 1, 0, 1, 1)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.login_page_layout.addItem(spacerItem2, 1, 2, 2, 1)
self.login_stack.addWidget(self.login_page)
self.success_page = QtWidgets.QWidget()
self.success_page.setObjectName("success_page")
self.success_page_layout = QtWidgets.QHBoxLayout(self.success_page)
self.success_page_layout.setObjectName("success_page_layout")
self.success_label = QtWidgets.QLabel(self.success_page)
self.success_label.setObjectName("success_label")
self.success_page_layout.addWidget(self.success_label)
self.login_stack.addWidget(self.success_page)
self.dialog_layout.addWidget(self.login_stack)
self.button_layout = QtWidgets.QHBoxLayout()
self.button_layout.setObjectName("button_layout")
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.button_layout.addItem(spacerItem3)
self.exit_button = QtWidgets.QPushButton(LoginDialog)
self.exit_button.setObjectName("exit_button")
self.button_layout.addWidget(self.exit_button)
self.back_button = QtWidgets.QPushButton(LoginDialog)
self.back_button.setObjectName("back_button")
self.button_layout.addWidget(self.back_button)
self.next_button = QtWidgets.QPushButton(LoginDialog)
self.next_button.setObjectName("next_button")
self.button_layout.addWidget(self.next_button)
self.dialog_layout.addLayout(self.button_layout)
self.retranslateUi(LoginDialog)
self.login_stack.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(LoginDialog)
def retranslateUi(self, LoginDialog):
_translate = QtCore.QCoreApplication.translate
LoginDialog.setWindowTitle(_translate("LoginDialog", "Welcome to Rare"))
self.welcome_label.setText(_translate("LoginDialog", "<h1>Welcome to Rare</h1>"))
self.login_browser_label.setText(_translate("LoginDialog", "Login using a browser."))
self.login_label.setText(_translate("LoginDialog", "Select login method"))
self.login_import_label.setText(_translate("LoginDialog", "Import from Epic Games Launcher"))
self.login_import_radio.setText(_translate("LoginDialog", "Import"))
self.login_browser_radio.setText(_translate("LoginDialog", "Browser"))
self.success_label.setText(_translate("LoginDialog", "<h2>Login Succeful!</h2>"))
self.exit_button.setText(_translate("LoginDialog", "Exit"))
self.back_button.setText(_translate("LoginDialog", "Back"))
self.next_button.setText(_translate("LoginDialog", "Next"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
LoginDialog = QtWidgets.QDialog()
ui = Ui_LoginDialog()
ui.setupUi(LoginDialog)
LoginDialog.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,220 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LoginDialog</class>
<widget class="QDialog" name="LoginDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>492</width>
<height>311</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Welcome to Rare</string>
</property>
<layout class="QVBoxLayout" name="dialog_layout">
<item>
<spacer name="login_vspacer_top">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="welcome_label">
<property name="text">
<string>&lt;h1&gt;Welcome to Rare&lt;/h1&gt;</string>
</property>
</widget>
</item>
<item>
<spacer name="login_vspacer_bottom">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QStackedWidget" name="login_stack">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>135</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="login_page">
<property name="enabled">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="login_page_layout">
<item row="1" column="1">
<widget class="QLabel" name="login_browser_label">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Login using a browser.</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3" alignment="Qt::AlignTop">
<widget class="QLabel" name="login_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Select login method</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="login_import_label">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Import from Epic Games Launcher</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="login_import_radio">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Import</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="login_browser_radio">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Browser</string>
</property>
</widget>
</item>
<item row="1" column="2" rowspan="2">
<spacer name="login_hspacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="success_page">
<layout class="QHBoxLayout" name="success_page_layout">
<item>
<widget class="QLabel" name="success_label">
<property name="text">
<string>&lt;h2&gt;Login Succeful!&lt;/h2&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="button_layout">
<item>
<spacer name="button_hspacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="exit_button">
<property name="text">
<string>Exit</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="back_button">
<property name="text">
<string>Back</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="next_button">
<property name="text">
<string>Next</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -170,7 +170,7 @@ class Ui_GameInfo(object):
self.repair_button.setObjectName("repair_button")
self.installed_layout.addWidget(self.repair_button)
self.uninstall_button = QtWidgets.QPushButton(self.installed_page)
self.uninstall_button.setStyleSheet("background-color: #900")
self.uninstall_button.setStyleSheet("")
self.uninstall_button.setObjectName("uninstall_button")
self.installed_layout.addWidget(self.uninstall_button)
self.game_actions_stack.addWidget(self.installed_page)
@ -179,7 +179,7 @@ class Ui_GameInfo(object):
self.uninstalled_layout = QtWidgets.QVBoxLayout(self.uninstalled_page)
self.uninstalled_layout.setObjectName("uninstalled_layout")
self.install_button = QtWidgets.QPushButton(self.uninstalled_page)
self.install_button.setStyleSheet("background-color: #090")
self.install_button.setStyleSheet("")
self.install_button.setObjectName("install_button")
self.uninstalled_layout.addWidget(self.install_button)
self.game_actions_stack.addWidget(self.uninstalled_page)

View file

@ -250,7 +250,7 @@
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="installed_page" native="true">
<widget class="QWidget" name="installed_page">
<layout class="QVBoxLayout" name="installed_layout">
<property name="leftMargin">
<number>0</number>
@ -333,7 +333,7 @@
<item>
<widget class="QPushButton" name="uninstall_button">
<property name="styleSheet">
<string notr="true">background-color: #900</string>
<string notr="true"/>
</property>
<property name="text">
<string>Uninstall Game</string>
@ -347,7 +347,7 @@
<item>
<widget class="QPushButton" name="install_button">
<property name="styleSheet">
<string notr="true">background-color: #090</string>
<string notr="true"/>
</property>
<property name="text">
<string>Install Game</string>

View file

@ -6,7 +6,7 @@ from PyQt5.QtWidgets import QLayout, QStyle, QSizePolicy, QLabel, QFileDialog, Q
QStyleOptionTab, QStylePainter, QTabBar
from qtawesome import icon
from rare import style_path
from rare import resources_path
from rare.ui.utils.pathedit import Ui_PathEdit
@ -163,7 +163,7 @@ class PathEdit(QWidget, Ui_PathEdit):
dlg_path = self.text_edit.text()
if not dlg_path:
dlg_path = os.path.expanduser("~/")
dlg = QFileDialog(self, self.tr("Choose Path"), dlg_path)
dlg = QFileDialog(self, self.tr("Choose path"), dlg_path)
dlg.setFileMode(self.file_type)
if self.type_filter:
dlg.setFilter([self.type_filter])
@ -213,7 +213,7 @@ class WaitingSpinner(QLabel):
margin-left: auto;
margin-right: auto;
""")
self.movie = QMovie(os.path.join(style_path, "loader.gif"))
self.movie = QMovie(os.path.join(resources_path, "images", "loader.gif"))
self.setMovie(self.movie)
self.movie.start()

View file

@ -1,36 +1,38 @@
import os
from dataclasses import field, dataclass
from custom_legendary.models.game import Game, InstalledGame
from custom_legendary.models.downloading import AnalysisResult
from custom_legendary.downloader.manager import DLManager
from multiprocessing import Queue
@dataclass
class InstallOptionsModel:
def __init__(self, app_name: str, base_path: str = os.path.expanduser("~/legendary"),
max_workers: int = os.cpu_count() * 2, repair: bool = False, no_install: bool = False,
ignore_space_req: bool = False, force: bool = False, sdl_list: list = ['']
):
self.app_name = app_name
self.base_path = base_path
self.max_workers = max_workers
self.repair = repair
self.no_install = no_install
self.ignore_space_req = ignore_space_req
self.force = force
self.sdl_list = sdl_list
app_name: str
base_path: str = os.path.expanduser("~/legendary")
max_workers: int = os.cpu_count() * 2
repair: bool = False
no_install: bool = False
ignore_space_req: bool = False
force: bool = False
sdl_list: list[str] = field(default_factory=lambda: [''])
@dataclass
class InstallDownloadModel:
def __init__(self, dlmanager, analysis, game, igame, repair: bool, repair_file: str):
self.dlmanager = dlmanager
self.analysis = analysis
self.game = game
self.igame = igame
self.repair = repair
self.repair_file = repair_file
dlmanager: DLManager
analysis: AnalysisResult
game: Game
igame: InstalledGame
repair: bool
repair_file: str
@dataclass
class InstallQueueItemModel:
def __init__(self, status_q=None, download: InstallDownloadModel = None, options: InstallOptionsModel = None):
self.status_q = status_q
self.download = download
self.options = options
status_q: Queue = None
download: InstallDownloadModel = None
options: InstallOptionsModel = None
def __bool__(self):
return (self.status_q is not None) and (self.download is not None) and (self.options is not None)

View file

@ -13,7 +13,7 @@ from PyQt5.QtGui import QPalette, QColor
if os.name == "nt":
from win32com.client import Dispatch
from rare import lang_path, style_path
from rare import languages_path, resources_path
# Mac not supported
from custom_legendary.core import LegendaryCore
@ -180,23 +180,23 @@ def load_color_scheme(path: str):
def get_color_schemes():
colors = []
for file in os.listdir(os.path.join(style_path, "colors")):
if file.endswith(".scheme") and os.path.isfile(os.path.join(style_path, "colors", file)):
for file in os.listdir(os.path.join(resources_path, "colors")):
if file.endswith(".scheme") and os.path.isfile(os.path.join(resources_path, "colors", file)):
colors.append(file.replace(".scheme", ""))
return colors
def get_style_sheets():
styles = []
for file in os.listdir(os.path.join(style_path, "qss")):
if file.endswith(".qss") and os.path.isfile(os.path.join(style_path, "qss", file)):
styles.append(file.replace(".qss", ""))
for folder in os.listdir(os.path.join(resources_path, "stylesheets")):
if os.path.isfile(os.path.join(resources_path, "stylesheets", folder, "stylesheet.qss")):
styles.append(folder)
return styles
def get_possible_langs():
langs = ["en"]
for i in os.listdir(lang_path):
for i in os.listdir(languages_path):
if i.endswith(".qm"):
langs.append(i.split(".")[0])
return langs
@ -232,7 +232,7 @@ def create_rare_desktop_link(type_of_link):
desktop_file.write("[Desktop Entry]\n"
f"Name=Rare\n"
f"Type=Application\n"
f"Icon={os.path.join(style_path, 'Logo.png')}\n"
f"Icon={os.path.join(resources_path, 'images', 'Rare.png')}\n"
f"Exec={os.path.abspath(sys.argv[0])}\n"
"Terminal=false\n"
"StartupWMClass=rare\n"
@ -262,7 +262,7 @@ def create_rare_desktop_link(type_of_link):
shortcut.WorkingDirectory = os.getcwd()
# Icon
shortcut.IconLocation = os.path.join(style_path, "Logo.ico")
shortcut.IconLocation = os.path.join(resources_path, "images", "Rare.ico")
shortcut.save()