Merge pull request #335 from loathingKernel/next
Improve the login dialog
This commit is contained in:
commit
d36582bf6c
|
@ -6,7 +6,7 @@ from typing import Tuple, List, Union, Optional
|
|||
from PyQt5.QtCore import Qt, QThreadPool, QSettings, QCoreApplication
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtGui import QCloseEvent, QKeyEvent, QShowEvent
|
||||
from PyQt5.QtWidgets import QDialog, QFileDialog, QCheckBox, QLayout, QWidget, QVBoxLayout
|
||||
from PyQt5.QtWidgets import QDialog, QFileDialog, QCheckBox, QLayout, QWidget, QVBoxLayout, QFormLayout
|
||||
from legendary.utils.selective_dl import get_sdl_appname
|
||||
|
||||
from rare.models.game import RareGame
|
||||
|
@ -85,7 +85,10 @@ class InstallDialog(QDialog):
|
|||
save_func=self.save_install_edit,
|
||||
parent=self,
|
||||
)
|
||||
self.ui.install_dir_layout.addWidget(self.install_dir_edit)
|
||||
self.ui.install_dialog_layout.setWidget(
|
||||
self.ui.install_dialog_layout.getWidgetPosition(self.ui.install_dir_label)[0],
|
||||
QFormLayout.FieldRole, self.install_dir_edit
|
||||
)
|
||||
|
||||
if self.options.update:
|
||||
self.ui.install_dir_label.setEnabled(False)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtCore import Qt, pyqtSignal
|
||||
from PyQt5.QtWidgets import QLayout, QDialog, QMessageBox, QFrame
|
||||
from legendary.core import LegendaryCore
|
||||
|
||||
|
@ -48,7 +48,7 @@ class LoginDialog(QDialog):
|
|||
self.args = ArgumentsSingleton()
|
||||
|
||||
self.login_stack = SlidingStackedWidget(parent=self)
|
||||
self.login_stack.setMinimumSize(480, 180)
|
||||
self.login_stack.setMinimumWidth(480)
|
||||
self.ui.login_stack_layout.addWidget(self.login_stack)
|
||||
|
||||
self.landing_page = LandingPage(self.login_stack)
|
||||
|
@ -65,6 +65,26 @@ class LoginDialog(QDialog):
|
|||
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)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ from typing import Tuple
|
|||
|
||||
from PyQt5.QtCore import pyqtSignal, QUrl
|
||||
from PyQt5.QtGui import QDesktopServices
|
||||
from PyQt5.QtWidgets import QFrame, qApp
|
||||
from PyQt5.QtWidgets import QFrame, qApp, QFormLayout, QLineEdit
|
||||
from legendary.core import LegendaryCore
|
||||
from legendary.utils import webview_login
|
||||
|
||||
|
@ -31,11 +31,14 @@ class BrowserLogin(QFrame):
|
|||
self.sid_edit = IndicatorLineEdit(
|
||||
placeholder=self.tr("Insert authorizationCode here"), edit_func=self.text_changed, parent=self
|
||||
)
|
||||
self.sid_edit.line_edit.setEchoMode(QLineEdit.Password)
|
||||
self.ui.link_text.setText(self.login_url)
|
||||
self.ui.copy_button.setIcon(icon("mdi.content-copy", "fa.copy"))
|
||||
self.ui.copy_button.clicked.connect(self.copy_link)
|
||||
|
||||
self.ui.sid_layout.addWidget(self.sid_edit)
|
||||
self.ui.form_layout.setWidget(
|
||||
self.ui.form_layout.getWidgetPosition(self.ui.sid_label)[0],
|
||||
QFormLayout.FieldRole, self.sid_edit
|
||||
)
|
||||
|
||||
self.ui.open_button.clicked.connect(self.open_browser)
|
||||
self.sid_edit.textChanged.connect(self.changed.emit)
|
||||
|
@ -68,7 +71,7 @@ class BrowserLogin(QFrame):
|
|||
auth_code = self.sid_edit.text()
|
||||
try:
|
||||
if self.core.auth_code(auth_code):
|
||||
logger.info(f"Successfully logged in as {self.core.lgd.userdata['displayName']}")
|
||||
logger.info("Successfully logged in as %s", self.core.lgd.userdata['displayName'])
|
||||
self.success.emit()
|
||||
else:
|
||||
self.ui.status_label.setText(self.tr("Login failed."))
|
||||
|
@ -82,7 +85,7 @@ class BrowserLogin(QFrame):
|
|||
QDesktopServices.openUrl(QUrl(self.login_url))
|
||||
else:
|
||||
if webview_login.do_webview_login(callback_code=self.core.auth_ex_token):
|
||||
logger.info("Successfully logged in as " f"{self.core.lgd.userdata['displayName']}")
|
||||
logger.info("Successfully logged in as %s", {self.core.lgd.userdata['displayName']})
|
||||
self.success.emit()
|
||||
else:
|
||||
logger.warning("Failed to login through browser.")
|
||||
|
|
|
@ -15,6 +15,8 @@ logger = getLogger("ImportLogin")
|
|||
class ImportLogin(QFrame):
|
||||
success = pyqtSignal()
|
||||
changed = pyqtSignal()
|
||||
|
||||
# FIXME: Use pathspec instead of duplicated code
|
||||
if os.name == "nt":
|
||||
localappdata = os.path.expandvars("%LOCALAPPDATA%")
|
||||
else:
|
||||
|
@ -45,10 +47,6 @@ class ImportLogin(QFrame):
|
|||
if programdata_path := self.core.egl.programdata_path:
|
||||
if wine_pfx := programdata_path.split("drive_c")[0]:
|
||||
self.ui.prefix_combo.addItem(wine_pfx)
|
||||
self.ui.info_label.setText(
|
||||
self.tr("Please select the Wine prefix where Epic Games Launcher is installed. ")
|
||||
+ self.ui.info_label.text()
|
||||
)
|
||||
prefixes = self.get_wine_prefixes()
|
||||
if len(prefixes):
|
||||
self.ui.prefix_combo.addItems(prefixes)
|
||||
|
@ -97,15 +95,15 @@ class ImportLogin(QFrame):
|
|||
if os.name == "nt":
|
||||
pass
|
||||
else:
|
||||
logger.info(f'Using EGL appdata path at "{self.egl_appdata}"')
|
||||
logger.info("Using EGL appdata path at %s", {self.egl_appdata})
|
||||
self.core.egl.appdata_path = self.egl_appdata
|
||||
try:
|
||||
if self.core.auth_import():
|
||||
logger.info(f"Logged in as {self.core.lgd.userdata['displayName']}")
|
||||
logger.info("Logged in as %s", {self.core.lgd.userdata['displayName']})
|
||||
self.success.emit()
|
||||
else:
|
||||
self.ui.status_label.setText(self.tr("Login failed."))
|
||||
logger.warning("Failed to import existing session.")
|
||||
except Exception as e:
|
||||
self.ui.status_label.setText(self.tr("Login failed. {}").format(str(e)))
|
||||
logger.warning(f"Failed to import existing session: {e}")
|
||||
logger.warning("Failed to import existing session: %s", e)
|
||||
|
|
|
@ -8,7 +8,7 @@ from .downloads import DownloadsTab
|
|||
from .games import GamesTab
|
||||
from .settings import SettingsTab
|
||||
from .settings.debug import DebugSettings
|
||||
from .shop import Shop
|
||||
from .store import Shop
|
||||
from .tab_widgets import MainTabBar, TabButtonWidget
|
||||
|
||||
|
||||
|
@ -86,9 +86,6 @@ class MainTabWidget(QTabWidget):
|
|||
if index == self.games_index:
|
||||
self.games_tab.setCurrentWidget(self.games_tab.games_page)
|
||||
|
||||
if not self.args.offline and index == self.store_index:
|
||||
self.store_tab.load()
|
||||
|
||||
def resizeEvent(self, event):
|
||||
self.tab_bar.setMinimumWidth(self.width())
|
||||
super(MainTabWidget, self).resizeEvent(event)
|
||||
|
|
|
@ -72,6 +72,7 @@ class GameInfoTabs(SideTabWidget):
|
|||
class GameMetadataView(QTreeView, SideTabContents):
|
||||
def __init__(self, parent=None):
|
||||
super(GameMetadataView, self).__init__(parent=parent)
|
||||
self.implements_scrollarea = True
|
||||
self.setColumnWidth(0, 300)
|
||||
self.setWordWrap(True)
|
||||
self.model = QJsonModel()
|
||||
|
|
|
@ -44,9 +44,8 @@ class GameSettings(DefaultGameSettings, SideTabContents):
|
|||
parent=self
|
||||
)
|
||||
self.ui.launch_settings_layout.insertRow(
|
||||
int(self.ui.launch_settings_layout.indexOf(self.ui.launch_params)/2) + 1,
|
||||
QLabel(self.tr("Override executable"), self),
|
||||
self.override_exe_edit
|
||||
self.ui.launch_settings_layout.getWidgetPosition(self.ui.launch_params)[0] + 1,
|
||||
QLabel(self.tr("Override executable"), self), self.override_exe_edit
|
||||
)
|
||||
|
||||
self.ui.game_settings_layout.setAlignment(Qt.AlignTop)
|
||||
|
|
|
@ -6,7 +6,7 @@ from typing import Tuple, Iterable, List, Union
|
|||
|
||||
from PyQt5.QtCore import Qt, QThreadPool, QRunnable, pyqtSlot, pyqtSignal
|
||||
from PyQt5.QtGui import QShowEvent
|
||||
from PyQt5.QtWidgets import QGroupBox, QListWidgetItem, QFileDialog, QMessageBox, QFrame, QLabel
|
||||
from PyQt5.QtWidgets import QGroupBox, QListWidgetItem, QFileDialog, QMessageBox, QFrame, QFormLayout
|
||||
from legendary.models.egl import EGLManifest
|
||||
from legendary.models.game import InstalledGame
|
||||
|
||||
|
@ -39,25 +39,27 @@ class EGLSyncGroup(QGroupBox):
|
|||
save_func=self.egl_path_edit_save_cb,
|
||||
parent=self,
|
||||
)
|
||||
self.ui.egl_path_edit_layout.addWidget(self.egl_path_edit)
|
||||
self.ui.egl_sync_layout.setWidget(
|
||||
self.ui.egl_sync_layout.getWidgetPosition(self.ui.egl_path_edit_label)[0],
|
||||
QFormLayout.FieldRole, self.egl_path_edit
|
||||
)
|
||||
|
||||
self.egl_path_info_label = QLabel(self.tr("Estimated path"), self)
|
||||
self.egl_path_info = ElideLabel(parent=self)
|
||||
self.egl_path_info.setProperty("infoLabel", 1)
|
||||
self.ui.egl_sync_layout.insertRow(
|
||||
self.ui.egl_sync_layout.indexOf(self.ui.egl_path_edit_label) + 1,
|
||||
self.egl_path_info_label, self.egl_path_info
|
||||
self.ui.egl_sync_layout.setWidget(
|
||||
self.ui.egl_sync_layout.getWidgetPosition(self.ui.egl_path_info_label)[0],
|
||||
QFormLayout.FieldRole, self.egl_path_info
|
||||
)
|
||||
|
||||
if platform.system() == "Windows":
|
||||
self.ui.egl_path_edit_label.setEnabled(False)
|
||||
self.egl_path_edit.setEnabled(False)
|
||||
self.egl_path_info_label.setEnabled(False)
|
||||
self.ui.egl_path_info_label.setEnabled(False)
|
||||
self.egl_path_info.setEnabled(False)
|
||||
else:
|
||||
self.egl_path_edit.textChanged.connect(self.egl_path_changed)
|
||||
if self.core.egl.programdata_path:
|
||||
self.egl_path_info_label.setEnabled(True)
|
||||
self.ui.egl_path_info_label.setEnabled(True)
|
||||
self.egl_path_info.setEnabled(True)
|
||||
|
||||
self.ui.egl_sync_check.setChecked(self.core.egl_sync_enabled)
|
||||
|
|
|
@ -199,7 +199,8 @@ class ImportGroup(QGroupBox):
|
|||
)
|
||||
self.path_edit.textChanged.connect(self.path_changed)
|
||||
self.ui.import_layout.setWidget(
|
||||
self.ui.import_layout.indexOf(self.ui.path_edit_label), QFormLayout.FieldRole, self.path_edit
|
||||
self.ui.import_layout.getWidgetPosition(self.ui.path_edit_label)[0],
|
||||
QFormLayout.FieldRole, self.path_edit
|
||||
)
|
||||
|
||||
self.app_name_edit = IndicatorLineEdit(
|
||||
|
@ -209,7 +210,8 @@ class ImportGroup(QGroupBox):
|
|||
)
|
||||
self.app_name_edit.textChanged.connect(self.app_name_changed)
|
||||
self.ui.import_layout.setWidget(
|
||||
self.ui.import_layout.indexOf(self.ui.app_name_label), QFormLayout.FieldRole, self.app_name_edit
|
||||
self.ui.import_layout.getWidgetPosition(self.ui.app_name_label)[0],
|
||||
QFormLayout.FieldRole, self.app_name_edit
|
||||
)
|
||||
|
||||
self.ui.import_folder_check.stateChanged.connect(self.import_folder_changed)
|
||||
|
|
|
@ -7,7 +7,7 @@ from PyQt5.QtWidgets import QWidget
|
|||
|
||||
from rare import __version__, __codename__
|
||||
from rare.ui.components.tabs.settings.about import Ui_About
|
||||
from rare.utils.qt_requests import QtRequestManager
|
||||
from rare.utils.qt_requests import QtRequests
|
||||
|
||||
logger = getLogger("About")
|
||||
|
||||
|
@ -34,7 +34,7 @@ class About(QWidget):
|
|||
self.ui.open_browser.setVisible(False)
|
||||
self.ui.open_browser.setEnabled(False)
|
||||
|
||||
self.manager = QtRequestManager("json")
|
||||
self.manager = QtRequests(parent=self)
|
||||
self.manager.get(
|
||||
"https://api.github.com/repos/RareDevs/Rare/releases/latest",
|
||||
self.update_available_finished,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from PyQt5.QtGui import QShowEvent, QHideEvent
|
||||
from PyQt5.QtWidgets import QStackedWidget, QTabWidget
|
||||
from legendary.core import LegendaryCore
|
||||
|
||||
|
@ -26,7 +27,7 @@ class Shop(QStackedWidget):
|
|||
self.shop = ShopWidget(cache_dir(), self.core, self.api_core)
|
||||
self.wishlist_widget = Wishlist(self.api_core)
|
||||
|
||||
self.store_tabs = QTabWidget()
|
||||
self.store_tabs = QTabWidget(parent=self)
|
||||
self.store_tabs.addTab(self.shop, self.tr("Games"))
|
||||
self.store_tabs.addTab(self.wishlist_widget, self.tr("Wishlist"))
|
||||
|
||||
|
@ -50,15 +51,23 @@ class Shop(QStackedWidget):
|
|||
self.api_core.update_wishlist.connect(self.update_wishlist)
|
||||
self.wishlist_widget.update_wishlist_signal.connect(self.update_wishlist)
|
||||
|
||||
def showEvent(self, a0: QShowEvent) -> None:
|
||||
if a0.spontaneous() or self.init:
|
||||
return super().showEvent(a0)
|
||||
self.shop.load()
|
||||
self.wishlist_widget.update_wishlist()
|
||||
self.init = True
|
||||
return super().showEvent(a0)
|
||||
|
||||
def hideEvent(self, a0: QHideEvent) -> None:
|
||||
if a0.spontaneous():
|
||||
return super().hideEvent(a0)
|
||||
# TODO: Implement store unloading
|
||||
return super().hideEvent(a0)
|
||||
|
||||
def update_wishlist(self):
|
||||
self.shop.update_wishlist()
|
||||
|
||||
def load(self):
|
||||
if not self.init:
|
||||
self.init = True
|
||||
self.shop.load()
|
||||
self.wishlist_widget.update_wishlist()
|
||||
|
||||
def show_game_info(self, data):
|
||||
self.info.update_game(data)
|
||||
self.setCurrentIndex(2)
|
|
@ -13,8 +13,8 @@ from PyQt5.QtWidgets import (
|
|||
QGridLayout,
|
||||
)
|
||||
|
||||
from rare.components.tabs.store.shop_models import ShopGame
|
||||
from rare.shared import LegendaryCoreSingleton
|
||||
from rare.components.tabs.shop.shop_models import ShopGame
|
||||
from rare.ui.components.tabs.store.shop_game_info import Ui_shop_info
|
||||
from rare.utils.extra_widgets import ImageLabel
|
||||
from rare.utils.misc import icon
|
|
@ -6,7 +6,7 @@ from PyQt5.QtGui import QFont
|
|||
from PyQt5.QtNetwork import QNetworkAccessManager
|
||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout
|
||||
|
||||
from rare.components.tabs.shop.shop_models import ImageUrlModel
|
||||
from rare.components.tabs.store.shop_models import ImageUrlModel
|
||||
from rare.ui.components.tabs.store.wishlist_widget import Ui_WishlistWidget
|
||||
from rare.utils.extra_widgets import ImageLabel
|
||||
from rare.utils.misc import icon
|
|
@ -3,14 +3,14 @@ from logging import getLogger
|
|||
|
||||
from PyQt5.QtCore import pyqtSignal, QObject
|
||||
|
||||
from rare.components.tabs.shop.constants import (
|
||||
from rare.components.tabs.store.constants import (
|
||||
wishlist_query,
|
||||
search_query,
|
||||
add_to_wishlist_query,
|
||||
remove_from_wishlist_query,
|
||||
)
|
||||
from rare.components.tabs.shop.shop_models import BrowseModel
|
||||
from rare.utils.qt_requests import QtRequestManager
|
||||
from rare.components.tabs.store.shop_models import BrowseModel
|
||||
from rare.utils.qt_requests import QtRequests
|
||||
|
||||
logger = getLogger("ShopAPICore")
|
||||
graphql_url = "https://www.epicgames.com/graphql"
|
||||
|
@ -25,8 +25,8 @@ class ShopApiCore(QObject):
|
|||
self.language_code: str = lc
|
||||
self.country_code: str = cc
|
||||
self.locale = f"{self.language_code}-{self.country_code}"
|
||||
self.manager = QtRequestManager()
|
||||
self.auth_manager = QtRequestManager(authorization_token=auth_token)
|
||||
self.manager = QtRequests(parent=self)
|
||||
self.auth_manager = QtRequests(token=auth_token, parent=self)
|
||||
|
||||
self.browse_active = False
|
||||
self.next_browse_request = tuple(())
|
||||
|
@ -52,6 +52,7 @@ class ShopApiCore(QObject):
|
|||
def get_wishlist(self, handle_func):
|
||||
self.auth_manager.post(
|
||||
graphql_url,
|
||||
lambda data: self._handle_wishlist(data, handle_func),
|
||||
{
|
||||
"query": wishlist_query,
|
||||
"variables": {
|
||||
|
@ -59,7 +60,6 @@ class ShopApiCore(QObject):
|
|||
"locale": f"{self.language_code}-{self.country_code}",
|
||||
},
|
||||
},
|
||||
lambda data: self._handle_wishlist(data, handle_func),
|
||||
)
|
||||
|
||||
def _handle_wishlist(self, data, handle_func):
|
||||
|
@ -95,7 +95,7 @@ class ShopApiCore(QObject):
|
|||
}
|
||||
|
||||
self.manager.post(
|
||||
graphql_url, payload, lambda data: self._handle_search(data, handle_func)
|
||||
graphql_url, lambda data: self._handle_search(data, handle_func), payload,
|
||||
)
|
||||
|
||||
def _handle_search(self, data, handle_func):
|
||||
|
@ -189,8 +189,8 @@ class ShopApiCore(QObject):
|
|||
}
|
||||
self.auth_manager.post(
|
||||
graphql_url,
|
||||
payload,
|
||||
lambda data: self._handle_add_to_wishlist(data, handle_func),
|
||||
payload,
|
||||
)
|
||||
|
||||
def _handle_add_to_wishlist(self, data, handle_func):
|
||||
|
@ -216,8 +216,8 @@ class ShopApiCore(QObject):
|
|||
}
|
||||
self.auth_manager.post(
|
||||
graphql_url,
|
||||
payload,
|
||||
lambda data: self._handle_remove_from_wishlist(data, handle_func),
|
||||
payload,
|
||||
)
|
||||
|
||||
def _handle_remove_from_wishlist(self, data, handle_func):
|
|
@ -68,6 +68,10 @@ class ShopWidget(QScrollArea, Ui_ShopWidget):
|
|||
|
||||
self.init_filter()
|
||||
|
||||
self.search_bar.setHidden(True)
|
||||
self.filter_gb.setHidden(True)
|
||||
self.filter_game_gb.setHidden(True)
|
||||
|
||||
# self.search_bar.textChanged.connect(self.load_completer)
|
||||
|
||||
def load(self):
|
|
@ -1,8 +1,8 @@
|
|||
from PyQt5.QtCore import pyqtSignal
|
||||
from PyQt5.QtWidgets import QStackedWidget, QMessageBox
|
||||
|
||||
from rare.components.tabs.shop import ShopApiCore
|
||||
from rare.components.tabs.shop.game_widgets import WishlistWidget
|
||||
from rare.components.tabs.store import ShopApiCore
|
||||
from rare.components.tabs.store.game_widgets import WishlistWidget
|
||||
from rare.ui.components.tabs.store.wishlist import Ui_Wishlist
|
||||
from rare.utils.extra_widgets import WaitingSpinner
|
||||
from rare.utils.misc import icon
|
|
@ -43,22 +43,23 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
def unlock_installed(func):
|
||||
@functools.wraps(func)
|
||||
def unlock(self, *args, **kwargs):
|
||||
self.logger.debug("Using unlock decorator")
|
||||
if not self.core.lgd.lock_installed():
|
||||
self.logger.debug("Data is locked, trying to forcufully release it")
|
||||
self.logger.info("Data is locked, trying to forcufully release it")
|
||||
# self.core.lgd._installed_lock.release(force=True)
|
||||
try:
|
||||
ret = func(self, *args, **kwargs)
|
||||
except Exception as e:
|
||||
raise e
|
||||
finally:
|
||||
self.core.lgd._installed_lock.release(force=True)
|
||||
self.core.lgd.unlock_installed()
|
||||
return ret
|
||||
return unlock
|
||||
|
||||
def resolve_aliases(self, name):
|
||||
return super(LegendaryCLI, self)._resolve_aliases(name)
|
||||
|
||||
@unlock_installed
|
||||
@unlock_installed.__func__
|
||||
def install_game(self, args: LgndrInstallGameArgs) -> Optional[Tuple[DLManager, AnalysisResult, InstalledGame, Game, bool, Optional[str], ConditionCheckResult]]:
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(args.indirect_status, self.logger)
|
||||
|
@ -229,7 +230,7 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
return dlm, analysis, igame, game, args.repair_mode, repair_file, res
|
||||
|
||||
# Rare: This is currently handled in DownloadThread, this is a trial
|
||||
@unlock_installed
|
||||
@unlock_installed.__func__
|
||||
def install_game_real(self, args: LgndrInstallGameRealArgs, dlm: DLManager, game: Game, igame: InstalledGame) -> LgndrInstallGameRealRet:
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(args.indirect_status, self.logger)
|
||||
|
@ -315,7 +316,7 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
|
||||
return ret
|
||||
|
||||
@unlock_installed
|
||||
@unlock_installed.__func__
|
||||
def install_game_cleanup(self, game: Game, igame: InstalledGame, repair_mode: bool = False, repair_file: str = '') -> None:
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(LgndrIndirectStatus(), self.logger)
|
||||
|
@ -386,7 +387,7 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
else:
|
||||
logger.info('Automatic installation not available on Linux.')
|
||||
|
||||
@unlock_installed
|
||||
@unlock_installed.__func__
|
||||
def uninstall_game(self, args: LgndrUninstallGameArgs) -> None:
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(args.indirect_status, self.logger, logging.WARNING)
|
||||
|
@ -562,7 +563,7 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
logger.info(f'Run "legendary repair {args.app_name}" to repair your game installation.')
|
||||
return len(failed), len(missing)
|
||||
|
||||
@unlock_installed
|
||||
@unlock_installed.__func__
|
||||
def import_game(self, args: LgndrImportGameArgs) -> None:
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(args.indirect_status, self.logger)
|
||||
|
@ -667,11 +668,11 @@ class LegendaryCLI(LegendaryCLIReal):
|
|||
logger.info(f'{"DLC" if game.is_dlc else "Game"} "{game.app_title}" has been imported.')
|
||||
return
|
||||
|
||||
@unlock_installed
|
||||
@unlock_installed.__func__
|
||||
def egs_sync(self, args):
|
||||
return super(LegendaryCLI, self).egs_sync(args)
|
||||
|
||||
@unlock_installed
|
||||
@unlock_installed.__func__
|
||||
def move(self, args):
|
||||
# Override logger for the local context to use message as part of the indirect return value
|
||||
logger = LgndrIndirectLogger(args.indirect_status, self.logger)
|
||||
|
|
|
@ -17,16 +17,19 @@ from legendary.models.game import Game, InstalledGame
|
|||
from legendary.models.manifest import ManifestMeta
|
||||
|
||||
from rare.lgndr.downloader.mp.manager import DLManager
|
||||
from rare.lgndr.lfs.lgndry import LGDLFS
|
||||
from rare.lgndr.glue.exception import LgndrException, LgndrLogHandler
|
||||
|
||||
legendary.core.DLManager = DLManager
|
||||
legendary.core.LGDLFS = LGDLFS
|
||||
|
||||
|
||||
# fmt: off
|
||||
class LegendaryCore(LegendaryCoreReal):
|
||||
|
||||
def __init__(self, override_config=None, timeout=10.0):
|
||||
super(LegendaryCore, self).__init__(override_config=override_config, timeout=timeout)
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LegendaryCore, self).__init__(*args, **kwargs)
|
||||
self.log.info("Using Rare's LegendaryCore monkey")
|
||||
self.handler = LgndrLogHandler(logging.CRITICAL)
|
||||
self.log.addHandler(self.handler)
|
||||
|
||||
|
@ -34,15 +37,16 @@ class LegendaryCore(LegendaryCoreReal):
|
|||
def unlock_installed(func):
|
||||
@functools.wraps(func)
|
||||
def unlock(self, *args, **kwargs):
|
||||
self.log.debug("Using unlock decorator")
|
||||
if not self.lgd.lock_installed():
|
||||
self.log.debug("Data is locked, trying to forcufully release it")
|
||||
self.log.info("Data is locked, trying to forcufully release it")
|
||||
# self.lgd._installed_lock.release(force=True)
|
||||
try:
|
||||
ret = func(self, *args, **kwargs)
|
||||
except Exception as e:
|
||||
raise e
|
||||
finally:
|
||||
self.lgd._installed_lock.release(force=True)
|
||||
self.lgd.unlock_installed()
|
||||
return ret
|
||||
return unlock
|
||||
|
||||
|
@ -94,7 +98,7 @@ class LegendaryCore(LegendaryCoreReal):
|
|||
finally:
|
||||
pass
|
||||
|
||||
@unlock_installed
|
||||
@unlock_installed.__func__
|
||||
def egl_import(self, app_name):
|
||||
try:
|
||||
super(LegendaryCore, self).egl_import(app_name)
|
||||
|
@ -140,7 +144,7 @@ class LegendaryCore(LegendaryCoreReal):
|
|||
if delete_files:
|
||||
delete_folder(os.path.join(igame.install_path, '.egstore'))
|
||||
|
||||
@unlock_installed
|
||||
@unlock_installed.__func__
|
||||
def egl_export(self, app_name):
|
||||
try:
|
||||
super(LegendaryCore, self).egl_export(app_name)
|
||||
|
@ -149,6 +153,15 @@ class LegendaryCore(LegendaryCoreReal):
|
|||
finally:
|
||||
pass
|
||||
|
||||
@unlock_installed.__func__
|
||||
def egl_sync(self, app_name=''):
|
||||
try:
|
||||
super(LegendaryCore, self).egl_sync(app_name)
|
||||
except LgndrException as ret:
|
||||
raise ret
|
||||
finally:
|
||||
pass
|
||||
|
||||
def prepare_overlay_install(self, path=None):
|
||||
dlm, analysis_result, igame = super(LegendaryCore, self).prepare_overlay_install(path)
|
||||
# lk: monkeypatch status_q (the queue for download stats)
|
||||
|
|
|
@ -17,6 +17,10 @@ from rare.lgndr.models.downloading import UIUpdate
|
|||
|
||||
# fmt: off
|
||||
class DLManager(DLManagerReal):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DLManager, self).__init__(*args, **kwargs)
|
||||
self.log.info("Using Rare's DLManager monkey")
|
||||
|
||||
# Rare: prototype to avoid undefined variable in type checkers
|
||||
signals_queue: MPQueue
|
||||
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
from dataclasses import dataclass, field
|
||||
from enum import IntEnum
|
||||
from typing import Callable, List, Optional, Dict
|
||||
from typing import List, Optional, Dict
|
||||
|
||||
from rare.lgndr.glue.monkeys import (
|
||||
LgndrIndirectStatus,
|
||||
GetBooleanChoiceProtocol,
|
||||
SdlPromptProtocol,
|
||||
VerifyStdoutProtocol,
|
||||
UiUpdateProtocol,
|
||||
get_boolean_choice_factory,
|
||||
sdl_prompt_factory,
|
||||
verify_stdout_factory,
|
||||
ui_update_factory,
|
||||
DLManagerSignals,
|
||||
)
|
||||
from rare.lgndr.models.downloading import UIUpdate
|
||||
|
||||
"""
|
||||
@dataclass(kw_only=True)
|
||||
|
@ -34,7 +37,7 @@ class LgndrImportGameArgs:
|
|||
yes: bool = False
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
get_boolean_choice: Callable[[str, bool], bool] = get_boolean_choice_factory(True)
|
||||
get_boolean_choice: GetBooleanChoiceProtocol = get_boolean_choice_factory(True)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -45,8 +48,8 @@ class LgndrUninstallGameArgs:
|
|||
yes: bool = False
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
get_boolean_choice_main: Callable[[str, bool], bool] = get_boolean_choice_factory(True)
|
||||
get_boolean_choice_handler: Callable[[str, bool], bool] = get_boolean_choice_factory(True)
|
||||
get_boolean_choice_main: GetBooleanChoiceProtocol = get_boolean_choice_factory(True)
|
||||
get_boolean_choice_handler: GetBooleanChoiceProtocol = get_boolean_choice_factory(True)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -54,7 +57,7 @@ class LgndrVerifyGameArgs:
|
|||
app_name: str
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
verify_stdout: Callable[[int, int, float, float], None] = verify_stdout_factory(None)
|
||||
verify_stdout: VerifyStdoutProtocol = verify_stdout_factory(None)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -95,11 +98,11 @@ class LgndrInstallGameArgs:
|
|||
yes: bool = True
|
||||
# Rare: Extra arguments
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
get_boolean_choice: Callable[[str, bool], bool] = get_boolean_choice_factory(True)
|
||||
verify_stdout: Callable[[int, int, float, float], None] = verify_stdout_factory(None)
|
||||
get_boolean_choice: GetBooleanChoiceProtocol = get_boolean_choice_factory(True)
|
||||
verify_stdout: VerifyStdoutProtocol = verify_stdout_factory(None)
|
||||
|
||||
def __post_init__(self):
|
||||
self.sdl_prompt: Callable[[Dict, str], List[str]] = sdl_prompt_factory(self.install_tag)
|
||||
self.sdl_prompt: SdlPromptProtocol = sdl_prompt_factory(self.install_tag)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -117,7 +120,7 @@ class LgndrInstallGameRealArgs:
|
|||
# Rare: Extra arguments
|
||||
install_prereqs: bool = False
|
||||
indirect_status: LgndrIndirectStatus = field(default_factory=LgndrIndirectStatus)
|
||||
ui_update: Callable[[UIUpdate], None] = ui_update_factory(None)
|
||||
ui_update: UiUpdateProtocol = ui_update_factory(None)
|
||||
dlm_signals: DLManagerSignals = field(default_factory=DLManagerSignals)
|
||||
|
||||
|
||||
|
|
|
@ -1,20 +1,30 @@
|
|||
import logging
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, List, Optional, Dict
|
||||
from typing import Protocol, List, Optional, Dict
|
||||
|
||||
from rare.lgndr.models.downloading import UIUpdate
|
||||
|
||||
logger = logging.getLogger("LgndrMonkeys")
|
||||
|
||||
|
||||
def get_boolean_choice_factory(value: bool = True) -> Callable[[str, bool], bool]:
|
||||
def get_boolean_choice(prompt: str, default: bool) -> bool:
|
||||
class GetBooleanChoiceProtocol(Protocol):
|
||||
def __call__(self, prompt: str, default: bool = ...) -> bool:
|
||||
...
|
||||
|
||||
|
||||
def get_boolean_choice_factory(value: bool = True) -> GetBooleanChoiceProtocol:
|
||||
def get_boolean_choice(prompt: str, default: bool = value) -> bool:
|
||||
logger.debug("get_boolean_choice: %s, default: %s, choice: %s", prompt, default, value)
|
||||
return value
|
||||
return get_boolean_choice
|
||||
|
||||
|
||||
def sdl_prompt_factory(install_tag: Optional[List[str]] = None) -> Callable[[Dict, str], List[str]]:
|
||||
class SdlPromptProtocol(Protocol):
|
||||
def __call__(self, sdl_data: Dict, title: str) -> List[str]:
|
||||
...
|
||||
|
||||
|
||||
def sdl_prompt_factory(install_tag: Optional[List[str]] = None) -> SdlPromptProtocol:
|
||||
def sdl_prompt(sdl_data: Dict, title: str) -> List[str]:
|
||||
logger.debug("sdl_prompt: %s", title)
|
||||
for key in sdl_data.keys():
|
||||
|
@ -25,9 +35,12 @@ def sdl_prompt_factory(install_tag: Optional[List[str]] = None) -> Callable[[Dic
|
|||
return sdl_prompt
|
||||
|
||||
|
||||
def verify_stdout_factory(
|
||||
callback: Callable[[int, int, float, float], None] = None
|
||||
) -> Callable[[int, int, float, float], None]:
|
||||
class VerifyStdoutProtocol(Protocol):
|
||||
def __call__(self, a0: int, a1: int, a2: float, a3: float) -> None:
|
||||
...
|
||||
|
||||
|
||||
def verify_stdout_factory(callback: VerifyStdoutProtocol = None) -> VerifyStdoutProtocol:
|
||||
def verify_stdout(a0: int, a1: int, a2: float, a3: float) -> None:
|
||||
if callback is not None and callable(callback):
|
||||
callback(a0, a1, a2, a3)
|
||||
|
@ -36,7 +49,12 @@ def verify_stdout_factory(
|
|||
return verify_stdout
|
||||
|
||||
|
||||
def ui_update_factory(callback: Callable[[UIUpdate], None] = None) -> Callable[[UIUpdate], None]:
|
||||
class UiUpdateProtocol(Protocol):
|
||||
def __call__(self, status: UIUpdate) -> None:
|
||||
...
|
||||
|
||||
|
||||
def ui_update_factory(callback: UiUpdateProtocol = None) -> UiUpdateProtocol:
|
||||
def ui_update(status: UIUpdate) -> None:
|
||||
if callback is not None and callable(callback):
|
||||
callback(status)
|
||||
|
|
0
rare/lgndr/lfs/__init__.py
Normal file
0
rare/lgndr/lfs/__init__.py
Normal file
15
rare/lgndr/lfs/lgndry.py
Normal file
15
rare/lgndr/lfs/lgndry.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
import os
|
||||
|
||||
from filelock import FileLock
|
||||
from legendary.lfs.lgndry import LGDLFS as LGDLFSReal
|
||||
|
||||
|
||||
class LGDLFS(LGDLFSReal):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(LGDLFS, self).__init__(*args, **kwargs)
|
||||
self.log.info("Using Rare's LGDLFS monkey")
|
||||
# Rare: Default FileLock in Python 3.11 is thread-local, so replace it with a non-local verison
|
||||
self._installed_lock = FileLock(os.path.join(self.path, 'installed.json') + '.lock', thread_local=False)
|
||||
|
||||
def unlock_installed(self):
|
||||
self._installed_lock.release(force=True)
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'rare/ui/components/dialogs/install_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# 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.
|
||||
|
@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_InstallDialog(object):
|
||||
def setupUi(self, InstallDialog):
|
||||
InstallDialog.setObjectName("InstallDialog")
|
||||
InstallDialog.resize(324, 232)
|
||||
InstallDialog.resize(272, 238)
|
||||
InstallDialog.setWindowTitle("InstallDialog")
|
||||
self.install_dialog_layout = QtWidgets.QFormLayout(InstallDialog)
|
||||
self.install_dialog_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
|
@ -25,9 +25,6 @@ class Ui_InstallDialog(object):
|
|||
self.install_dir_label = QtWidgets.QLabel(InstallDialog)
|
||||
self.install_dir_label.setObjectName("install_dir_label")
|
||||
self.install_dialog_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.install_dir_label)
|
||||
self.install_dir_layout = QtWidgets.QHBoxLayout()
|
||||
self.install_dir_layout.setObjectName("install_dir_layout")
|
||||
self.install_dialog_layout.setLayout(1, QtWidgets.QFormLayout.FieldRole, self.install_dir_layout)
|
||||
self.platform_label = QtWidgets.QLabel(InstallDialog)
|
||||
self.platform_label.setObjectName("platform_label")
|
||||
self.install_dialog_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.platform_label)
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>324</width>
|
||||
<height>232</height>
|
||||
<width>272</width>
|
||||
<height>238</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -31,9 +31,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="install_dir_layout"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="platform_label">
|
||||
<property name="text">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'rare/ui/components/dialogs/launch_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# 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.
|
||||
|
@ -36,7 +36,7 @@ class Ui_LaunchDialog(object):
|
|||
|
||||
def retranslateUi(self, LaunchDialog):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
LaunchDialog.setWindowTitle(_translate("LaunchDialog", "Launching Rare"))
|
||||
LaunchDialog.setWindowTitle(_translate("LaunchDialog", "Launching - Rare"))
|
||||
self.title_label.setText(_translate("LaunchDialog", "<h2>Launching Rare</h2>"))
|
||||
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Launching Rare</string>
|
||||
<string>Launching - Rare</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="launch_layout">
|
||||
<item>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'rare/ui/components/dialogs/login/browser_login.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.7
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# 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.
|
||||
|
@ -14,16 +14,35 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_BrowserLogin(object):
|
||||
def setupUi(self, BrowserLogin):
|
||||
BrowserLogin.setObjectName("BrowserLogin")
|
||||
BrowserLogin.resize(182, 210)
|
||||
BrowserLogin.resize(320, 243)
|
||||
BrowserLogin.setWindowTitle("BrowserLogin")
|
||||
self.browser_layout = QtWidgets.QGridLayout(BrowserLogin)
|
||||
self.browser_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
|
||||
self.browser_layout.setObjectName("browser_layout")
|
||||
self.main_layout = QtWidgets.QVBoxLayout(BrowserLogin)
|
||||
self.main_layout.setObjectName("main_layout")
|
||||
self.title_label = QtWidgets.QLabel(BrowserLogin)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.title_label.sizePolicy().hasHeightForWidth())
|
||||
self.title_label.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.title_label.setFont(font)
|
||||
self.title_label.setObjectName("title_label")
|
||||
self.main_layout.addWidget(self.title_label)
|
||||
self.form_layout = QtWidgets.QFormLayout()
|
||||
self.form_layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
|
||||
self.form_layout.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
|
||||
self.form_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.form_layout.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
||||
self.form_layout.setObjectName("form_layout")
|
||||
self.open_button = QtWidgets.QPushButton(BrowserLogin)
|
||||
self.open_button.setObjectName("open_button")
|
||||
self.form_layout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.open_button)
|
||||
self.link_layout = QtWidgets.QHBoxLayout()
|
||||
self.link_layout.setObjectName("link_layout")
|
||||
self.link_text = QtWidgets.QLineEdit(BrowserLogin)
|
||||
self.link_text.setText("")
|
||||
self.link_text.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
|
||||
self.link_text.setReadOnly(True)
|
||||
self.link_text.setPlaceholderText("")
|
||||
self.link_text.setObjectName("link_text")
|
||||
|
@ -32,47 +51,40 @@ class Ui_BrowserLogin(object):
|
|||
self.copy_button.setText("")
|
||||
self.copy_button.setObjectName("copy_button")
|
||||
self.link_layout.addWidget(self.copy_button)
|
||||
self.browser_layout.addLayout(self.link_layout, 2, 0, 1, 2)
|
||||
spacerItem = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.browser_layout.addItem(spacerItem, 4, 0, 1, 2)
|
||||
self.open_button = QtWidgets.QPushButton(BrowserLogin)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.open_button.sizePolicy().hasHeightForWidth())
|
||||
self.open_button.setSizePolicy(sizePolicy)
|
||||
self.open_button.setObjectName("open_button")
|
||||
self.browser_layout.addWidget(self.open_button, 1, 0, 1, 1)
|
||||
self.sid_layout = QtWidgets.QHBoxLayout()
|
||||
self.sid_layout.setObjectName("sid_layout")
|
||||
self.browser_layout.addLayout(self.sid_layout, 1, 1, 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)
|
||||
self.info_label = QtWidgets.QLabel(BrowserLogin)
|
||||
self.link_layout.setStretch(0, 1)
|
||||
self.form_layout.setLayout(0, QtWidgets.QFormLayout.FieldRole, self.link_layout)
|
||||
self.sid_label = QtWidgets.QLabel(BrowserLogin)
|
||||
self.sid_label.setText("authorizationCode")
|
||||
self.sid_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.sid_label.setObjectName("sid_label")
|
||||
self.form_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.sid_label)
|
||||
self.status_label = QtWidgets.QLabel(BrowserLogin)
|
||||
font = QtGui.QFont()
|
||||
font.setItalic(True)
|
||||
self.info_label.setFont(font)
|
||||
self.status_label.setFont(font)
|
||||
self.status_label.setText("")
|
||||
self.status_label.setObjectName("status_label")
|
||||
self.form_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.status_label)
|
||||
self.main_layout.addLayout(self.form_layout)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.main_layout.addItem(spacerItem)
|
||||
self.info_label = QtWidgets.QLabel(BrowserLogin)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.info_label.sizePolicy().hasHeightForWidth())
|
||||
self.info_label.setSizePolicy(sizePolicy)
|
||||
self.info_label.setWordWrap(True)
|
||||
self.info_label.setObjectName("info_label")
|
||||
self.browser_layout.addWidget(self.info_label, 5, 0, 1, 2)
|
||||
self.status_label = QtWidgets.QLabel(BrowserLogin)
|
||||
self.status_label.setText("")
|
||||
self.status_label.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft)
|
||||
self.status_label.setObjectName("status_label")
|
||||
self.browser_layout.addWidget(self.status_label, 3, 0, 1, 2)
|
||||
self.main_layout.addWidget(self.info_label)
|
||||
|
||||
self.retranslateUi(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.info_label.setText(_translate("BrowserLogin", "Click the button to open the login page in a browser or copy the link and paste it in a browser. After logging in, copy the <b><code>authorizationCode</code></b> in the input above."))
|
||||
self.open_button.setText(_translate("BrowserLogin", "Open Browser"))
|
||||
self.info_label.setText(_translate("BrowserLogin", "<i>Click the <strong>Open Browser</strong> button to open the login page in your web browser or copy the link and paste it in any web browser. After logging in using the browser, copy the text in the quotes after </i><code><b>authorizationCode</b></code><i> in the same line into the empty input above.<br><br><strong>DO NOT SHARE THE INFORMATION IN THE BROWSER PAGE WITH ANYONE IN ANY FORM (TEXT OR SCREENSHOT)!</strong></i>"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -6,75 +6,22 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>182</width>
|
||||
<height>210</height>
|
||||
<width>320</width>
|
||||
<height>243</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">BrowserLogin</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="browser_layout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="link_layout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="link_text">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="copy_button">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<spacer name="vspacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="open_button">
|
||||
<layout class="QVBoxLayout" name="main_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="title_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open Browser</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="sid_layout"/>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="title_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
|
@ -86,31 +33,104 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="form_layout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetFixedSize</enum>
|
||||
</property>
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="open_button">
|
||||
<property name="text">
|
||||
<string>Open Browser</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="link_layout" stretch="1,0">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="link_text">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="copy_button">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="sid_label">
|
||||
<property name="text">
|
||||
<string notr="true">authorizationCode</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="status_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="vscaper">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="info_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Click the button to open the login page in a browser or copy the link and paste it in a browser. After logging in, copy the <b><code>authorizationCode</code></b> in the input above.</string>
|
||||
<string><i>Click the <strong>Open Browser</strong> button to open the login page in your web browser or copy the link and paste it in any web browser. After logging in using the browser, copy the text in the quotes after </i><code><b>authorizationCode</b></code><i> in the same line into the empty input above.<br><br><strong>DO NOT SHARE THE INFORMATION IN THE BROWSER PAGE WITH ANYONE IN ANY FORM (TEXT OR SCREENSHOT)!</strong></i></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="status_label">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'rare/ui/components/dialogs/login/import_login.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.7
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# 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.
|
||||
|
@ -14,24 +14,35 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_ImportLogin(object):
|
||||
def setupUi(self, ImportLogin):
|
||||
ImportLogin.setObjectName("ImportLogin")
|
||||
ImportLogin.resize(242, 120)
|
||||
ImportLogin.resize(233, 156)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(ImportLogin.sizePolicy().hasHeightForWidth())
|
||||
ImportLogin.setSizePolicy(sizePolicy)
|
||||
ImportLogin.setWindowTitle("ImportLogin")
|
||||
self.import_layout = QtWidgets.QGridLayout(ImportLogin)
|
||||
self.import_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
|
||||
self.import_layout.setObjectName("import_layout")
|
||||
self.prefix_label = QtWidgets.QLabel(ImportLogin)
|
||||
self.prefix_label.setObjectName("prefix_label")
|
||||
self.import_layout.addWidget(self.prefix_label, 1, 0, 1, 1)
|
||||
self.main_layout = QtWidgets.QVBoxLayout(ImportLogin)
|
||||
self.main_layout.setObjectName("main_layout")
|
||||
self.title_label = QtWidgets.QLabel(ImportLogin)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.title_label.sizePolicy().hasHeightForWidth())
|
||||
self.title_label.setSizePolicy(sizePolicy)
|
||||
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)
|
||||
self.prefix_tool = QtWidgets.QToolButton(ImportLogin)
|
||||
self.prefix_tool.setObjectName("prefix_tool")
|
||||
self.import_layout.addWidget(self.prefix_tool, 1, 2, 1, 1)
|
||||
self.main_layout.addWidget(self.title_label)
|
||||
self.form_layout = QtWidgets.QFormLayout()
|
||||
self.form_layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
|
||||
self.form_layout.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
|
||||
self.form_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||
self.form_layout.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
||||
self.form_layout.setObjectName("form_layout")
|
||||
self.prefix_layout = QtWidgets.QHBoxLayout()
|
||||
self.prefix_layout.setObjectName("prefix_layout")
|
||||
self.prefix_combo = QtWidgets.QComboBox(ImportLogin)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
|
@ -40,33 +51,43 @@ class Ui_ImportLogin(object):
|
|||
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_layout.addWidget(self.prefix_combo)
|
||||
self.prefix_tool = QtWidgets.QToolButton(ImportLogin)
|
||||
self.prefix_tool.setObjectName("prefix_tool")
|
||||
self.prefix_layout.addWidget(self.prefix_tool)
|
||||
self.prefix_layout.setStretch(0, 1)
|
||||
self.form_layout.setLayout(0, QtWidgets.QFormLayout.FieldRole, self.prefix_layout)
|
||||
self.prefix_label = QtWidgets.QLabel(ImportLogin)
|
||||
self.prefix_label.setObjectName("prefix_label")
|
||||
self.form_layout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.prefix_label)
|
||||
self.status_label = QtWidgets.QLabel(ImportLogin)
|
||||
font = QtGui.QFont()
|
||||
font.setItalic(True)
|
||||
self.status_label.setFont(font)
|
||||
self.status_label.setText("")
|
||||
self.status_label.setWordWrap(True)
|
||||
self.status_label.setObjectName("status_label")
|
||||
self.import_layout.addWidget(self.status_label, 2, 1, 1, 2)
|
||||
self.form_layout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.status_label)
|
||||
self.main_layout.addLayout(self.form_layout)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.main_layout.addItem(spacerItem)
|
||||
self.info_label = QtWidgets.QLabel(ImportLogin)
|
||||
font = QtGui.QFont()
|
||||
font.setItalic(True)
|
||||
self.info_label.setFont(font)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.info_label.sizePolicy().hasHeightForWidth())
|
||||
self.info_label.setSizePolicy(sizePolicy)
|
||||
self.info_label.setWordWrap(True)
|
||||
self.info_label.setObjectName("info_label")
|
||||
self.import_layout.addWidget(self.info_label, 4, 0, 1, 3)
|
||||
spacerItem = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.import_layout.addItem(spacerItem, 3, 0, 1, 3)
|
||||
self.main_layout.addWidget(self.info_label)
|
||||
|
||||
self.retranslateUi(ImportLogin)
|
||||
|
||||
def retranslateUi(self, ImportLogin):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
self.prefix_label.setText(_translate("ImportLogin", "Select prefix"))
|
||||
self.title_label.setText(_translate("ImportLogin", "Import existing session from EGL"))
|
||||
self.prefix_tool.setText(_translate("ImportLogin", "Browse"))
|
||||
self.info_label.setText(_translate("ImportLogin", "You will get logged out from EGL in the process."))
|
||||
self.prefix_label.setText(_translate("ImportLogin", "Select prefix"))
|
||||
self.info_label.setText(_translate("ImportLogin", "<i>Please select the Wine prefix where Epic Games Launcher is installed. You will get logged out from EGL in the process.</i>"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -6,26 +6,28 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>242</width>
|
||||
<height>120</height>
|
||||
<width>233</width>
|
||||
<height>156</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">ImportLogin</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="import_layout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="prefix_label">
|
||||
<property name="text">
|
||||
<string>Select prefix</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="3">
|
||||
<layout class="QVBoxLayout" name="main_layout">
|
||||
<item>
|
||||
<widget class="QLabel" name="title_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
|
@ -37,69 +39,94 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QToolButton" name="prefix_tool">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="form_layout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetFixedSize</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="prefix_layout" stretch="1,0">
|
||||
<item>
|
||||
<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>
|
||||
<widget class="QToolButton" name="prefix_tool">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="prefix_label">
|
||||
<property name="text">
|
||||
<string>Select prefix</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="status_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</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="2" column="1" colspan="2">
|
||||
<widget class="QLabel" name="status_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<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="3" column="0" colspan="3">
|
||||
<item>
|
||||
<spacer name="vspacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="info_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><i>Please select the Wine prefix where Epic Games Launcher is installed. You will get logged out from EGL in the process.</i></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'rare/ui/components/dialogs/login/landing_page.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# 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.
|
||||
|
@ -14,49 +14,58 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_LandingPage(object):
|
||||
def setupUi(self, LandingPage):
|
||||
LandingPage.setObjectName("LandingPage")
|
||||
LandingPage.resize(311, 87)
|
||||
LandingPage.resize(293, 78)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(LandingPage.sizePolicy().hasHeightForWidth())
|
||||
LandingPage.setSizePolicy(sizePolicy)
|
||||
LandingPage.setWindowTitle("LandingPage")
|
||||
self.landing_layout = QtWidgets.QGridLayout(LandingPage)
|
||||
self.landing_layout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
|
||||
self.landing_layout.setObjectName("landing_layout")
|
||||
self.main_layout = QtWidgets.QFormLayout(LandingPage)
|
||||
self.main_layout.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
|
||||
self.main_layout.setLabelAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
||||
self.main_layout.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
||||
self.main_layout.setObjectName("main_layout")
|
||||
self.login_label = QtWidgets.QLabel(LandingPage)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.login_label.sizePolicy().hasHeightForWidth())
|
||||
self.login_label.setSizePolicy(sizePolicy)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.login_label.setFont(font)
|
||||
self.login_label.setObjectName("login_label")
|
||||
self.landing_layout.addWidget(self.login_label, 0, 0, 1, 3)
|
||||
self.main_layout.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.login_label)
|
||||
self.login_browser_radio = QtWidgets.QRadioButton(LandingPage)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, 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.landing_layout.addWidget(self.login_browser_radio, 1, 0, 1, 1)
|
||||
self.login_import_radio = QtWidgets.QRadioButton(LandingPage)
|
||||
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.landing_layout.addWidget(self.login_import_radio, 2, 0, 1, 1)
|
||||
self.main_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.login_browser_radio)
|
||||
self.login_browser_label = QtWidgets.QLabel(LandingPage)
|
||||
font = QtGui.QFont()
|
||||
font.setItalic(True)
|
||||
self.login_browser_label.setFont(font)
|
||||
self.login_browser_label.setObjectName("login_browser_label")
|
||||
self.landing_layout.addWidget(self.login_browser_label, 1, 1, 1, 2)
|
||||
self.main_layout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.login_browser_label)
|
||||
self.login_import_radio = QtWidgets.QRadioButton(LandingPage)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, 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.main_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.login_import_radio)
|
||||
self.login_import_label = QtWidgets.QLabel(LandingPage)
|
||||
font = QtGui.QFont()
|
||||
font.setItalic(True)
|
||||
self.login_import_label.setFont(font)
|
||||
self.login_import_label.setObjectName("login_import_label")
|
||||
self.landing_layout.addWidget(self.login_import_label, 2, 1, 1, 2)
|
||||
self.landing_layout.setColumnStretch(2, 1)
|
||||
self.landing_layout.setRowStretch(1, 1)
|
||||
self.landing_layout.setRowStretch(2, 1)
|
||||
self.main_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.login_import_label)
|
||||
|
||||
self.retranslateUi(LandingPage)
|
||||
|
||||
|
@ -64,8 +73,8 @@ class Ui_LandingPage(object):
|
|||
_translate = QtCore.QCoreApplication.translate
|
||||
self.login_label.setText(_translate("LandingPage", "Select login method"))
|
||||
self.login_browser_radio.setText(_translate("LandingPage", "Browser"))
|
||||
self.login_import_radio.setText(_translate("LandingPage", "Import"))
|
||||
self.login_browser_label.setText(_translate("LandingPage", "Login using a browser."))
|
||||
self.login_import_radio.setText(_translate("LandingPage", "Import"))
|
||||
self.login_import_label.setText(_translate("LandingPage", "Import from Epic Games Launcher"))
|
||||
|
||||
|
||||
|
|
|
@ -6,19 +6,37 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>311</width>
|
||||
<height>87</height>
|
||||
<width>293</width>
|
||||
<height>78</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">LandingPage</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="landing_layout" rowstretch="0,1,1" columnstretch="0,0,1">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
<layout class="QFormLayout" name="main_layout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="3">
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="login_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
|
@ -33,7 +51,7 @@
|
|||
<item row="1" column="0">
|
||||
<widget class="QRadioButton" name="login_browser_radio">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
|
@ -43,20 +61,7 @@
|
|||
</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="1" colspan="2">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="login_browser_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
|
@ -68,7 +73,20 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QRadioButton" name="login_import_radio">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="login_import_label">
|
||||
<property name="font">
|
||||
<font>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'rare/ui/components/dialogs/login/login_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.7
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# 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.
|
||||
|
@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_LoginDialog(object):
|
||||
def setupUi(self, LoginDialog):
|
||||
LoginDialog.setObjectName("LoginDialog")
|
||||
LoginDialog.resize(324, 132)
|
||||
LoginDialog.resize(241, 128)
|
||||
self.login_layout = QtWidgets.QVBoxLayout(LoginDialog)
|
||||
self.login_layout.setObjectName("login_layout")
|
||||
spacerItem = QtWidgets.QSpacerItem(0, 17, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
|
||||
|
@ -46,7 +46,7 @@ class Ui_LoginDialog(object):
|
|||
|
||||
def retranslateUi(self, LoginDialog):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
LoginDialog.setWindowTitle(_translate("LoginDialog", "Rare Login"))
|
||||
LoginDialog.setWindowTitle(_translate("LoginDialog", "Login - Rare"))
|
||||
self.welcome_label.setText(_translate("LoginDialog", "<h1>Welcome to Rare</h1>"))
|
||||
self.exit_button.setText(_translate("LoginDialog", "Exit"))
|
||||
self.back_button.setText(_translate("LoginDialog", "Back"))
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>324</width>
|
||||
<height>132</height>
|
||||
<width>241</width>
|
||||
<height>128</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Rare Login</string>
|
||||
<string>Login - Rare</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="login_layout" stretch="0,0,0,0,0">
|
||||
<item>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'rare/ui/components/tabs/games/integrations/egl_sync_group.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
# Created by: PyQt5 UI code generator 5.15.10
|
||||
#
|
||||
# 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.
|
||||
|
@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||
class Ui_EGLSyncGroup(object):
|
||||
def setupUi(self, EGLSyncGroup):
|
||||
EGLSyncGroup.setObjectName("EGLSyncGroup")
|
||||
EGLSyncGroup.resize(217, 88)
|
||||
EGLSyncGroup.resize(424, 106)
|
||||
EGLSyncGroup.setWindowTitle("EGLSyncGroup")
|
||||
EGLSyncGroup.setCheckable(False)
|
||||
EGLSyncGroup.setChecked(False)
|
||||
|
@ -24,19 +24,21 @@ class Ui_EGLSyncGroup(object):
|
|||
self.egl_path_edit_label = QtWidgets.QLabel(EGLSyncGroup)
|
||||
self.egl_path_edit_label.setObjectName("egl_path_edit_label")
|
||||
self.egl_sync_layout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.egl_path_edit_label)
|
||||
self.egl_path_edit_layout = QtWidgets.QHBoxLayout()
|
||||
self.egl_path_edit_layout.setObjectName("egl_path_edit_layout")
|
||||
self.egl_sync_layout.setLayout(0, QtWidgets.QFormLayout.FieldRole, self.egl_path_edit_layout)
|
||||
self.egl_sync_check_label = QtWidgets.QLabel(EGLSyncGroup)
|
||||
self.egl_sync_check_label.setObjectName("egl_sync_check_label")
|
||||
self.egl_sync_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.egl_sync_check_label)
|
||||
self.egl_sync_layout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.egl_sync_check_label)
|
||||
self.egl_sync_check = QtWidgets.QCheckBox(EGLSyncGroup)
|
||||
self.egl_sync_check.setText("")
|
||||
font = QtGui.QFont()
|
||||
font.setItalic(True)
|
||||
self.egl_sync_check.setFont(font)
|
||||
self.egl_sync_check.setObjectName("egl_sync_check")
|
||||
self.egl_sync_layout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.egl_sync_check)
|
||||
self.egl_sync_layout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.egl_sync_check)
|
||||
self.import_export_layout = QtWidgets.QVBoxLayout()
|
||||
self.import_export_layout.setObjectName("import_export_layout")
|
||||
self.egl_sync_layout.setLayout(2, QtWidgets.QFormLayout.SpanningRole, self.import_export_layout)
|
||||
self.egl_sync_layout.setLayout(3, QtWidgets.QFormLayout.SpanningRole, self.import_export_layout)
|
||||
self.egl_path_info_label = QtWidgets.QLabel(EGLSyncGroup)
|
||||
self.egl_path_info_label.setObjectName("egl_path_info_label")
|
||||
self.egl_sync_layout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.egl_path_info_label)
|
||||
|
||||
self.retranslateUi(EGLSyncGroup)
|
||||
|
||||
|
@ -45,6 +47,8 @@ class Ui_EGLSyncGroup(object):
|
|||
EGLSyncGroup.setTitle(_translate("EGLSyncGroup", "Sync with Epic Games Launcher"))
|
||||
self.egl_path_edit_label.setText(_translate("EGLSyncGroup", "Prefix/Manifest path"))
|
||||
self.egl_sync_check_label.setText(_translate("EGLSyncGroup", "Enable automatic sync"))
|
||||
self.egl_sync_check.setText(_translate("EGLSyncGroup", "This will immediately synchronize with EGL"))
|
||||
self.egl_path_info_label.setText(_translate("EGLSyncGroup", "Estimated path"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>217</width>
|
||||
<height>88</height>
|
||||
<width>424</width>
|
||||
<height>106</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -33,26 +33,35 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="egl_path_edit_layout"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="egl_sync_check_label">
|
||||
<property name="text">
|
||||
<string>Enable automatic sync</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="egl_sync_check">
|
||||
<property name="font">
|
||||
<font>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
<string>This will immediately synchronize with EGL</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<layout class="QVBoxLayout" name="import_export_layout"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="egl_path_info_label">
|
||||
<property name="text">
|
||||
<string>Estimated path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import Qt, pyqtSignal
|
||||
|
@ -14,8 +13,8 @@ from PyQt5.QtWidgets import (
|
|||
)
|
||||
|
||||
from rare.utils.misc import icon as qta_icon
|
||||
from rare.utils.paths import tmp_dir
|
||||
from rare.utils.qt_requests import QtRequestManager
|
||||
from rare.utils.paths import cache_dir
|
||||
from rare.utils.qt_requests import QtRequests
|
||||
|
||||
logger = getLogger("ExtraWidgets")
|
||||
|
||||
|
@ -81,8 +80,10 @@ class ImageLabel(QLabel):
|
|||
|
||||
def __init__(self, parent=None):
|
||||
super(ImageLabel, self).__init__(parent=parent)
|
||||
self.path = tmp_dir()
|
||||
self.manager = QtRequestManager("bytes")
|
||||
self.manager = QtRequests(
|
||||
cache=str(cache_dir().joinpath("store")),
|
||||
parent=self
|
||||
)
|
||||
|
||||
def update_image(self, url, name="", size: tuple = (240, 320)):
|
||||
self.setFixedSize(*size)
|
||||
|
@ -95,11 +96,7 @@ class ImageLabel(QLabel):
|
|||
else:
|
||||
name_extension = "tall"
|
||||
self.name = f"{self.name}_{name_extension}.png"
|
||||
if not os.path.exists(os.path.join(self.path, self.name)):
|
||||
self.manager.get(url, self.image_ready)
|
||||
# self.request.finished.connect(self.image_ready)
|
||||
else:
|
||||
self.show_image()
|
||||
self.manager.get(url, self.image_ready)
|
||||
|
||||
def image_ready(self, data):
|
||||
try:
|
||||
|
@ -115,17 +112,9 @@ class ImageLabel(QLabel):
|
|||
transformMode=Qt.SmoothTransformation,
|
||||
)
|
||||
|
||||
image.save(os.path.join(self.path, self.name))
|
||||
|
||||
pixmap = QPixmap().fromImage(image)
|
||||
self.setPixmap(pixmap)
|
||||
|
||||
def show_image(self):
|
||||
self.image = QPixmap(os.path.join(self.path, self.name)).scaled(
|
||||
*self.img_size, transformMode=Qt.SmoothTransformation
|
||||
)
|
||||
self.setPixmap(self.image)
|
||||
|
||||
|
||||
class ButtonLineEdit(QLineEdit):
|
||||
buttonClicked = pyqtSignal()
|
||||
|
|
|
@ -1,109 +1,139 @@
|
|||
import json
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from email.message import Message
|
||||
from logging import getLogger
|
||||
from typing import Callable
|
||||
from typing import Callable, Dict, TypeVar, List, Tuple
|
||||
from typing import Union
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, QUrl, QJsonParseError, QJsonDocument
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply
|
||||
import orjson
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, QUrl, QUrlQuery, pyqtSlot
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply, QNetworkDiskCache
|
||||
|
||||
logger = getLogger("QtRequests")
|
||||
|
||||
|
||||
class QtRequestManager(QObject):
|
||||
data_ready = pyqtSignal(object)
|
||||
request = None
|
||||
request_active = None
|
||||
|
||||
def __init__(self, type: str = "json", authorization_token: str = None):
|
||||
super(QtRequestManager, self).__init__()
|
||||
self.manager = QNetworkAccessManager()
|
||||
self.type = type
|
||||
self.authorization_token = authorization_token
|
||||
self.request_queue = []
|
||||
|
||||
def post(self, url: str, payload: dict, handle_func):
|
||||
if not self.request_active:
|
||||
request = QNetworkRequest(QUrl(url))
|
||||
request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json")
|
||||
self.request_active = RequestQueueItem(handle_func=handle_func)
|
||||
payload = json.dumps(payload).encode("utf-8")
|
||||
|
||||
request.setHeader(
|
||||
QNetworkRequest.UserAgentHeader,
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36",
|
||||
)
|
||||
|
||||
if self.authorization_token is not None:
|
||||
request.setRawHeader(
|
||||
b"Authorization", self.authorization_token.encode()
|
||||
)
|
||||
|
||||
self.request = self.manager.post(request, payload)
|
||||
self.request.finished.connect(self.prepare_data)
|
||||
|
||||
else:
|
||||
self.request_queue.append(
|
||||
RequestQueueItem(
|
||||
method="post", url=url, payload=payload, handle_func=handle_func
|
||||
)
|
||||
)
|
||||
|
||||
def get(self, url: str, handle_func: Callable[[Union[dict, bytes]], None]):
|
||||
if not self.request_active:
|
||||
request = QNetworkRequest(QUrl(url))
|
||||
request.setHeader(
|
||||
QNetworkRequest.UserAgentHeader,
|
||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36",
|
||||
)
|
||||
|
||||
self.request_active = RequestQueueItem(handle_func=handle_func)
|
||||
self.request = self.manager.get(request)
|
||||
self.request.finished.connect(self.prepare_data)
|
||||
else:
|
||||
self.request_queue.append(
|
||||
RequestQueueItem(method="get", url=url, handle_func=handle_func)
|
||||
)
|
||||
|
||||
def prepare_data(self):
|
||||
# self.request_active = False
|
||||
data = {} if self.type == "json" else b""
|
||||
if self.request:
|
||||
try:
|
||||
if self.request.error() == QNetworkReply.NoError:
|
||||
if self.type == "json":
|
||||
error = QJsonParseError()
|
||||
json_data = QJsonDocument.fromJson(
|
||||
self.request.readAll().data(), error
|
||||
)
|
||||
if QJsonParseError.NoError == error.error:
|
||||
data = json.loads(json_data.toJson().data().decode())
|
||||
else:
|
||||
logger.error(error.errorString())
|
||||
else:
|
||||
data = self.request.readAll().data()
|
||||
|
||||
except RuntimeError as e:
|
||||
logger.error(str(e))
|
||||
self.request_active.handle_func(data)
|
||||
self.request.deleteLater()
|
||||
self.request_active = None
|
||||
|
||||
if self.request_queue:
|
||||
if self.request_queue[0].method == "post":
|
||||
self.post(
|
||||
self.request_queue[0].url,
|
||||
self.request_queue[0].payload,
|
||||
self.request_queue[0].handle_func,
|
||||
)
|
||||
else:
|
||||
self.get(self.request_queue[0].url, self.request_queue[0].handle_func)
|
||||
self.request_queue.pop(0)
|
||||
REQUEST_LIMIT = 8
|
||||
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"
|
||||
RequestHandler = TypeVar("RequestHandler", bound=Callable[[Union[Dict, bytes]], None])
|
||||
|
||||
|
||||
@dataclass
|
||||
class RequestQueueItem:
|
||||
method: str = None
|
||||
url: str = None
|
||||
handle_func: Callable[[Union[dict, bytes]], None] = None
|
||||
payload: dict = None
|
||||
url: QUrl = None
|
||||
payload: Dict = field(default_factory=dict)
|
||||
params: Dict = field(default_factory=dict)
|
||||
handlers: List[RequestHandler] = field(default_factory=list)
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.method == other.method and self.url == other.url
|
||||
|
||||
|
||||
class QtRequests(QObject):
|
||||
data_ready = pyqtSignal(object)
|
||||
|
||||
def __init__(self, cache: str = None, token: str = None, parent=None):
|
||||
super(QtRequests, self).__init__(parent=parent)
|
||||
self.log = getLogger(f"{type(self).__name__}_{type(parent).__name__}")
|
||||
self.manager = QNetworkAccessManager(self)
|
||||
self.manager.finished.connect(self.__on_finished)
|
||||
self.manager.finished.connect(self.__process_next)
|
||||
self.cache = None
|
||||
if cache is not None:
|
||||
self.log.debug("Using cache dir %s", cache)
|
||||
self.cache = QNetworkDiskCache(self)
|
||||
self.cache.setCacheDirectory(cache)
|
||||
self.manager.setCache(self.cache)
|
||||
if token is not None:
|
||||
self.log.debug("Manager is authorized")
|
||||
self.token = token
|
||||
|
||||
self.__pending_requests = []
|
||||
self.__active_requests = {}
|
||||
|
||||
@staticmethod
|
||||
def __prepare_query(url, params) -> QUrl:
|
||||
url = QUrl(url)
|
||||
query = QUrlQuery(url)
|
||||
for k, v in params.items():
|
||||
query.addQueryItem(str(k), str(v))
|
||||
url.setQuery(query)
|
||||
return url
|
||||
|
||||
def __prepare_request(self, item: RequestQueueItem) -> QNetworkRequest:
|
||||
request = QNetworkRequest(item.url)
|
||||
request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json;charset=UTF-8")
|
||||
request.setHeader(QNetworkRequest.UserAgentHeader, USER_AGENT)
|
||||
request.setAttribute(QNetworkRequest.RedirectPolicyAttribute, QNetworkRequest.NoLessSafeRedirectPolicy)
|
||||
if self.cache is not None:
|
||||
request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.PreferCache)
|
||||
if self.token is not None:
|
||||
request.setRawHeader(b"Authorization", self.token.encode())
|
||||
return request
|
||||
|
||||
def __post(self, item: RequestQueueItem):
|
||||
request = self.__prepare_request(item)
|
||||
payload = orjson.dumps(item.payload) # pylint: disable=maybe-no-member
|
||||
reply = self.manager.post(request, payload)
|
||||
reply.errorOccurred.connect(self.__on_error)
|
||||
self.__active_requests[reply] = item
|
||||
|
||||
def post(self, url: str, handler: RequestHandler, payload: dict):
|
||||
item = RequestQueueItem(method="post", url=QUrl(url), payload=payload, handlers=[handler])
|
||||
if len(self.__active_requests) < REQUEST_LIMIT:
|
||||
self.__post(item)
|
||||
else:
|
||||
self.__pending_requests.append(item)
|
||||
|
||||
def __get(self, item: RequestQueueItem):
|
||||
request = self.__prepare_request(item)
|
||||
reply = self.manager.get(request)
|
||||
reply.errorOccurred.connect(self.__on_error)
|
||||
self.__active_requests[reply] = item
|
||||
|
||||
def get(self, url: str, handler: RequestHandler, payload: Dict = None, params: Dict = None):
|
||||
url = self.__prepare_query(url, params) if params is not None else QUrl(url)
|
||||
item = RequestQueueItem(method="get", url=url, payload=payload, handlers=[handler])
|
||||
if len(self.__active_requests) < REQUEST_LIMIT:
|
||||
self.__get(item)
|
||||
else:
|
||||
self.__pending_requests.append(item)
|
||||
|
||||
def __on_error(self, error: QNetworkReply.NetworkError) -> None:
|
||||
self.log.error(error)
|
||||
|
||||
@staticmethod
|
||||
def __parse_content_type(header) -> Tuple[str, str]:
|
||||
# lk: this looks weird but `cgi` is deprecated, PEP 594 suggests this way of parsing MIME
|
||||
m = Message()
|
||||
m['content-type'] = header
|
||||
return m.get_content_type(), m.get_content_charset()
|
||||
|
||||
def __process_next(self):
|
||||
if self.__pending_requests:
|
||||
item = self.__pending_requests.pop(0)
|
||||
if item.method == "post":
|
||||
self.__post(item)
|
||||
elif item.method == "get":
|
||||
self.__get(item)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
@pyqtSlot(QNetworkReply)
|
||||
def __on_finished(self, reply: QNetworkReply):
|
||||
item = self.__active_requests.pop(reply, None)
|
||||
if item is None:
|
||||
self.log.error("QNetworkReply: %s without associated item", reply.url().toString())
|
||||
reply.deleteLater()
|
||||
return
|
||||
if reply.error():
|
||||
self.log.error(reply.errorString())
|
||||
else:
|
||||
mimetype, charset = self.__parse_content_type(reply.header(QNetworkRequest.ContentTypeHeader))
|
||||
maintype, subtype = mimetype.split("/")
|
||||
bin_data = reply.readAll().data()
|
||||
if mimetype == "application/json":
|
||||
data = orjson.loads(bin_data)
|
||||
elif maintype == "image":
|
||||
data = bin_data
|
||||
else:
|
||||
data = None
|
||||
for handler in item.handlers:
|
||||
handler(data)
|
||||
reply.deleteLater()
|
||||
|
|
|
@ -137,18 +137,11 @@ class IndicatorLineEdit(QWidget):
|
|||
self.line_edit.setObjectName(f"{type(self).__name__}Edit")
|
||||
self.line_edit.setPlaceholderText(placeholder if placeholder else self.tr("Default"))
|
||||
self.line_edit.setSizePolicy(horiz_policy, QSizePolicy.Fixed)
|
||||
# Add hint_label to line_edit
|
||||
self.line_edit.setLayout(QHBoxLayout())
|
||||
self.hint_label = QLabel()
|
||||
self.hint_label.setObjectName(f"{type(self).__name__}Label")
|
||||
self.hint_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
self.line_edit.layout().setContentsMargins(0, 0, 10, 0)
|
||||
self.line_edit.layout().addWidget(self.hint_label)
|
||||
# Add completer
|
||||
self.setCompleter(completer)
|
||||
layout.addWidget(self.line_edit)
|
||||
if edit_func is not None:
|
||||
self.indicator_label = QLabel()
|
||||
self.indicator_label = QLabel(self)
|
||||
self.indicator_label.setPixmap(qta_icon("ei.info-circle", color="gray").pixmap(16, 16))
|
||||
self.indicator_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
||||
layout.addWidget(self.indicator_label)
|
||||
|
@ -188,10 +181,6 @@ class IndicatorLineEdit(QWidget):
|
|||
def setText(self, text: str):
|
||||
self.line_edit.setText(text)
|
||||
|
||||
def setHintText(self, text: str):
|
||||
self.hint_label.setFrameRect(self.line_edit.rect())
|
||||
self.hint_label.setText(text)
|
||||
|
||||
def setCompleter(self, completer: Optional[QCompleter]):
|
||||
if old := self.line_edit.completer():
|
||||
old.deleteLater()
|
||||
|
|
|
@ -18,7 +18,7 @@ from PyQt5.QtWidgets import (
|
|||
QTabBar,
|
||||
QTabWidget,
|
||||
QVBoxLayout,
|
||||
QScrollArea, QLayout,
|
||||
QScrollArea, QLayout, QSizePolicy,
|
||||
)
|
||||
|
||||
from rare.utils.misc import icon as qta_icon
|
||||
|
@ -100,13 +100,14 @@ class SideTabContainer(QWidget):
|
|||
|
||||
if not hasattr(widget, "implements_scrollarea") or not widget.implements_scrollarea:
|
||||
self.scrollarea = QScrollArea(self)
|
||||
self.scrollarea.setWidgetResizable(True)
|
||||
self.scrollarea.setSizeAdjustPolicy(QScrollArea.AdjustToContents)
|
||||
self.scrollarea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
self.scrollarea.setFrameStyle(QScrollArea.NoFrame)
|
||||
self.scrollarea.setMinimumWidth(
|
||||
widget.sizeHint().width() + self.scrollarea.verticalScrollBar().sizeHint().width()
|
||||
)
|
||||
self.scrollarea.setWidgetResizable(True)
|
||||
widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
|
||||
self.scrollarea.setWidget(widget)
|
||||
layout.addWidget(self.scrollarea)
|
||||
else:
|
||||
|
|
Loading…
Reference in a new issue