Merge pull request #156 from Dummerle/epic_overlay
Add Settings for Epic Games Overlay. Install, enable and disable,
This commit is contained in:
commit
363142dac7
11
rare/app.py
11
rare/app.py
|
@ -19,6 +19,7 @@ from rare import cache_dir, resources_path
|
||||||
from rare.components.dialogs.launch_dialog import LaunchDialog
|
from rare.components.dialogs.launch_dialog import LaunchDialog
|
||||||
from rare.components.main_window import MainWindow
|
from rare.components.main_window import MainWindow
|
||||||
from rare.components.tray_icon import TrayIcon
|
from rare.components.tray_icon import TrayIcon
|
||||||
|
from rare.utils import legendary_utils
|
||||||
from rare.utils.utils import set_color_pallete, set_style_sheet
|
from rare.utils.utils import set_color_pallete, set_style_sheet
|
||||||
|
|
||||||
start_time = time.strftime("%y-%m-%d--%H-%M") # year-month-day-hour-minute
|
start_time = time.strftime("%y-%m-%d--%H-%M") # year-month-day-hour-minute
|
||||||
|
@ -158,6 +159,16 @@ class App(QApplication):
|
||||||
self.mainwindow.show_window_centralized()
|
self.mainwindow.show_window_centralized()
|
||||||
|
|
||||||
def start_app(self):
|
def start_app(self):
|
||||||
|
for igame in self.core.get_installed_list():
|
||||||
|
if not os.path.exists(igame.install_path):
|
||||||
|
legendary_utils.uninstall(igame.app_name, self.core)
|
||||||
|
logger.info(f"Uninstalled {igame.title}, because no game files exist")
|
||||||
|
continue
|
||||||
|
if not os.path.exists(os.path.join(igame.install_path, igame.executable)):
|
||||||
|
igame.needs_verification = True
|
||||||
|
self.core.lgd.set_installed_game(igame.app_name, igame)
|
||||||
|
logger.info(f"{igame.title} needs verification")
|
||||||
|
|
||||||
self.mainwindow = MainWindow()
|
self.mainwindow = MainWindow()
|
||||||
self.launch_dialog.close()
|
self.launch_dialog.close()
|
||||||
self.tray_icon = TrayIcon(self)
|
self.tray_icon = TrayIcon(self)
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
from multiprocessing import Queue as MPQueue
|
from multiprocessing import Queue as MPQueue
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import Qt, QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtGui import QCloseEvent
|
from PyQt5.QtGui import QCloseEvent, QKeyEvent
|
||||||
from PyQt5.QtWidgets import QDialog, QFileDialog, QCheckBox, QMessageBox
|
from PyQt5.QtWidgets import QDialog, QFileDialog, QCheckBox, QMessageBox
|
||||||
|
|
||||||
from legendary.core import LegendaryCore
|
from legendary.core import LegendaryCore
|
||||||
|
from legendary.models.downloading import ConditionCheckResult
|
||||||
|
from legendary.models.game import Game
|
||||||
from legendary.utils.selective_dl import games
|
from legendary.utils.selective_dl import games
|
||||||
from rare import shared
|
from rare import shared
|
||||||
from rare.ui.components.dialogs.install_dialog import Ui_InstallDialog
|
from rare.ui.components.dialogs.install_dialog import Ui_InstallDialog
|
||||||
|
@ -30,7 +33,13 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
||||||
self.dl_item = dl_item
|
self.dl_item = dl_item
|
||||||
self.dl_item.status_q = MPQueue()
|
self.dl_item.status_q = MPQueue()
|
||||||
self.app_name = self.dl_item.options.app_name
|
self.app_name = self.dl_item.options.app_name
|
||||||
self.game = self.core.get_game(self.app_name)
|
self.game = self.core.get_game(self.app_name) \
|
||||||
|
if not self.dl_item.options.overlay \
|
||||||
|
else Game(app_name=self.app_name, app_title="Epic Overlay")
|
||||||
|
|
||||||
|
self.game_path = self.game.metadata.get('customAttributes', {}). \
|
||||||
|
get('FolderName', {}).get('value', "")
|
||||||
|
|
||||||
self.update = update
|
self.update = update
|
||||||
self.silent = silent
|
self.silent = silent
|
||||||
|
|
||||||
|
@ -45,12 +54,12 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
||||||
self.install_dialog_label.setText(f'<h3>{header} "{self.game.app_title}"</h3>')
|
self.install_dialog_label.setText(f'<h3>{header} "{self.game.app_title}"</h3>')
|
||||||
self.setWindowTitle(f'{self.windowTitle()} - {header} "{self.game.app_title}"')
|
self.setWindowTitle(f'{self.windowTitle()} - {header} "{self.game.app_title}"')
|
||||||
|
|
||||||
default_path = os.path.expanduser("~/legendary")
|
if not self.dl_item.options.base_path:
|
||||||
if self.core.lgd.config.has_option("Legendary", "install_dir"):
|
self.dl_item.options.base_path = shared.core.lgd.config.get("Legendary", "install_dir",
|
||||||
default_path = self.core.lgd.config.get("Legendary", "install_dir")
|
fallback=os.path.expanduser("~/legendary"))
|
||||||
|
|
||||||
self.install_dir_edit = PathEdit(
|
self.install_dir_edit = PathEdit(
|
||||||
path=default_path,
|
path=self.dl_item.options.base_path,
|
||||||
file_type=QFileDialog.DirectoryOnly,
|
file_type=QFileDialog.DirectoryOnly,
|
||||||
edit_func=self.option_changed,
|
edit_func=self.option_changed,
|
||||||
parent=self,
|
parent=self,
|
||||||
|
@ -125,6 +134,16 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
||||||
|
|
||||||
self.install_button.setEnabled(False)
|
self.install_button.setEnabled(False)
|
||||||
|
|
||||||
|
if self.dl_item.options.overlay:
|
||||||
|
self.platform_label.setVisible(False)
|
||||||
|
self.platform_combo_box.setVisible(False)
|
||||||
|
self.ignore_space_info_label.setVisible(False)
|
||||||
|
self.ignore_space_check.setVisible(False)
|
||||||
|
self.ignore_space_label.setVisible(False)
|
||||||
|
self.download_only_check.setVisible(False)
|
||||||
|
self.download_only_info_label.setVisible(False)
|
||||||
|
self.download_only_label.setVisible(False)
|
||||||
|
|
||||||
self.cancel_button.clicked.connect(self.cancel_clicked)
|
self.cancel_button.clicked.connect(self.cancel_clicked)
|
||||||
self.verify_button.clicked.connect(self.verify_clicked)
|
self.verify_button.clicked.connect(self.verify_clicked)
|
||||||
self.install_button.clicked.connect(self.install_clicked)
|
self.install_button.clicked.connect(self.install_clicked)
|
||||||
|
@ -144,6 +163,7 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
||||||
self.dl_item.options.base_path = (
|
self.dl_item.options.base_path = (
|
||||||
self.install_dir_edit.text() if not self.update else None
|
self.install_dir_edit.text() if not self.update else None
|
||||||
)
|
)
|
||||||
|
|
||||||
self.dl_item.options.max_workers = self.max_workers_spin.value()
|
self.dl_item.options.max_workers = self.max_workers_spin.value()
|
||||||
self.dl_item.options.force = self.force_download_check.isChecked()
|
self.dl_item.options.force = self.force_download_check.isChecked()
|
||||||
self.dl_item.options.ignore_space_req = self.ignore_space_check.isChecked()
|
self.dl_item.options.ignore_space_req = self.ignore_space_check.isChecked()
|
||||||
|
@ -157,7 +177,7 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
||||||
|
|
||||||
def get_download_info(self):
|
def get_download_info(self):
|
||||||
self.dl_item.download = None
|
self.dl_item.download = None
|
||||||
info_worker = InstallInfoWorker(self.core, self.dl_item)
|
info_worker = InstallInfoWorker(self.core, self.dl_item, self.game)
|
||||||
info_worker.setAutoDelete(True)
|
info_worker.setAutoDelete(True)
|
||||||
info_worker.signals.result.connect(self.on_worker_result)
|
info_worker.signals.result.connect(self.on_worker_result)
|
||||||
info_worker.signals.failed.connect(self.on_worker_failed)
|
info_worker.signals.failed.connect(self.on_worker_failed)
|
||||||
|
@ -182,11 +202,16 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
||||||
self.get_options()
|
self.get_options()
|
||||||
self.get_download_info()
|
self.get_download_info()
|
||||||
|
|
||||||
def option_changed(self, path):
|
def option_changed(self, path) -> Tuple[bool, str, str]:
|
||||||
self.options_changed = True
|
self.options_changed = True
|
||||||
self.install_button.setEnabled(False)
|
self.install_button.setEnabled(False)
|
||||||
self.verify_button.setEnabled(not self.worker_running)
|
self.verify_button.setEnabled(not self.worker_running)
|
||||||
return True, path
|
# directory is not empty
|
||||||
|
full_path = os.path.join(self.dl_item.options.base_path, self.game_path)
|
||||||
|
if not self.dl_item.options.update and os.path.exists(full_path) and len(os.listdir(full_path)) != 0:
|
||||||
|
return False, path, PathEdit.reasons.dir_not_empty
|
||||||
|
|
||||||
|
return True, path, ""
|
||||||
|
|
||||||
def non_reload_option_changed(self, option: str):
|
def non_reload_option_changed(self, option: str):
|
||||||
if option == "download_only":
|
if option == "download_only":
|
||||||
|
@ -250,6 +275,10 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
||||||
self.result_ready.emit(self.dl_item)
|
self.result_ready.emit(self.dl_item)
|
||||||
a0.accept()
|
a0.accept()
|
||||||
|
|
||||||
|
def keyPressEvent(self, e: QKeyEvent) -> None:
|
||||||
|
if e.key() == Qt.Key_Escape:
|
||||||
|
self.cancel_clicked()
|
||||||
|
|
||||||
|
|
||||||
class InstallInfoWorkerSignals(QObject):
|
class InstallInfoWorkerSignals(QObject):
|
||||||
result = pyqtSignal(InstallDownloadModel)
|
result = pyqtSignal(InstallDownloadModel)
|
||||||
|
@ -258,15 +287,18 @@ class InstallInfoWorkerSignals(QObject):
|
||||||
|
|
||||||
|
|
||||||
class InstallInfoWorker(QRunnable):
|
class InstallInfoWorker(QRunnable):
|
||||||
def __init__(self, core: LegendaryCore, dl_item: InstallQueueItemModel):
|
def __init__(self, core: LegendaryCore, dl_item: InstallQueueItemModel, game: Game = None):
|
||||||
super(InstallInfoWorker, self).__init__()
|
super(InstallInfoWorker, self).__init__()
|
||||||
self.signals = InstallInfoWorkerSignals()
|
self.signals = InstallInfoWorkerSignals()
|
||||||
self.core = core
|
self.core = core
|
||||||
self.dl_item = dl_item
|
self.dl_item = dl_item
|
||||||
|
self.is_overlay_install = self.dl_item.options.overlay
|
||||||
|
self.game = game
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
|
if not self.is_overlay_install:
|
||||||
download = InstallDownloadModel(
|
download = InstallDownloadModel(
|
||||||
*self.core.prepare_download(
|
*self.core.prepare_download(
|
||||||
app_name=self.dl_item.options.app_name,
|
app_name=self.dl_item.options.app_name,
|
||||||
|
@ -296,7 +328,29 @@ class InstallInfoWorker(QRunnable):
|
||||||
sdl_prompt=lambda app_name, title: self.dl_item.options.sdl_list,
|
sdl_prompt=lambda app_name, title: self.dl_item.options.sdl_list,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if not download.res.failures:
|
|
||||||
|
else:
|
||||||
|
if not os.path.exists(path := self.dl_item.options.base_path):
|
||||||
|
os.makedirs(path)
|
||||||
|
|
||||||
|
dlm, analysis, igame = self.core.prepare_overlay_install(
|
||||||
|
path=self.dl_item.options.base_path,
|
||||||
|
status_queue=self.dl_item.status_q,
|
||||||
|
max_workers=self.dl_item.options.max_workers,
|
||||||
|
force=self.dl_item.options.force
|
||||||
|
)
|
||||||
|
|
||||||
|
download = InstallDownloadModel(
|
||||||
|
dlmanager=dlm,
|
||||||
|
analysis=analysis,
|
||||||
|
game=self.game,
|
||||||
|
igame=igame,
|
||||||
|
repair=False,
|
||||||
|
repair_file="",
|
||||||
|
res=ConditionCheckResult() # empty
|
||||||
|
)
|
||||||
|
|
||||||
|
if not download.res or not download.res.failures:
|
||||||
self.signals.result.emit(download)
|
self.signals.result.emit(download)
|
||||||
else:
|
else:
|
||||||
self.signals.failed.emit(
|
self.signals.failed.emit(
|
||||||
|
|
|
@ -46,19 +46,19 @@ class BrowserLogin(QWidget, Ui_BrowserLogin):
|
||||||
return self.sid_edit.is_valid
|
return self.sid_edit.is_valid
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def text_changed(text) -> Tuple[bool, str]:
|
def text_changed(text) -> Tuple[bool, str, str]:
|
||||||
if text:
|
if text:
|
||||||
text = text.strip()
|
text = text.strip()
|
||||||
if text.startswith("{") and text.endswith("}"):
|
if text.startswith("{") and text.endswith("}"):
|
||||||
try:
|
try:
|
||||||
text = json.loads(text).get("sid")
|
text = json.loads(text).get("sid")
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
return False, text
|
return False, text, IndicatorLineEdit.reasons.wrong_format
|
||||||
elif '"' in text:
|
elif '"' in text:
|
||||||
text = text.strip('"')
|
text = text.strip('"')
|
||||||
return len(text) == 32, text
|
return len(text) == 32, text, IndicatorLineEdit.reasons.wrong_format
|
||||||
else:
|
else:
|
||||||
return False, text
|
return False, text, ""
|
||||||
|
|
||||||
def do_login(self):
|
def do_login(self):
|
||||||
self.status_label.setText(self.tr("Logging in..."))
|
self.status_label.setText(self.tr("Logging in..."))
|
||||||
|
|
|
@ -13,9 +13,10 @@ from PyQt5.QtWidgets import QMessageBox
|
||||||
|
|
||||||
from legendary.core import LegendaryCore
|
from legendary.core import LegendaryCore
|
||||||
from legendary.models.downloading import UIUpdate, WriterTask
|
from legendary.models.downloading import UIUpdate, WriterTask
|
||||||
|
from rare import shared
|
||||||
from rare.utils.models import InstallQueueItemModel
|
from rare.utils.models import InstallQueueItemModel
|
||||||
|
|
||||||
logger = getLogger("Download")
|
logger = getLogger("DownloadThread")
|
||||||
|
|
||||||
|
|
||||||
class DownloadThread(QThread):
|
class DownloadThread(QThread):
|
||||||
|
@ -31,6 +32,7 @@ class DownloadThread(QThread):
|
||||||
self.igame = queue_item.download.igame
|
self.igame = queue_item.download.igame
|
||||||
self.repair = queue_item.download.repair
|
self.repair = queue_item.download.repair
|
||||||
self.repair_file = queue_item.download.repair_file
|
self.repair_file = queue_item.download.repair_file
|
||||||
|
self.queue_item = queue_item
|
||||||
self._kill = False
|
self._kill = False
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
@ -140,9 +142,15 @@ class DownloadThread(QThread):
|
||||||
return
|
return
|
||||||
self.status.emit("dl_finished")
|
self.status.emit("dl_finished")
|
||||||
end_t = time.time()
|
end_t = time.time()
|
||||||
logger.info(f"Download finished in {start_time - end_t}s")
|
logger.info(f"Download finished in {end_t - start_time}s")
|
||||||
game = self.core.get_game(self.igame.app_name)
|
game = self.core.get_game(self.igame.app_name)
|
||||||
|
|
||||||
|
if self.queue_item.options.overlay:
|
||||||
|
shared.signals.overlay_installation_finished.emit()
|
||||||
|
self.core.finish_overlay_install(self.igame)
|
||||||
|
self.status.emit("finish")
|
||||||
|
return
|
||||||
|
|
||||||
if not self.no_install:
|
if not self.no_install:
|
||||||
postinstall = self.core.install_game(self.igame)
|
postinstall = self.core.install_game(self.igame)
|
||||||
if postinstall:
|
if postinstall:
|
||||||
|
|
|
@ -133,6 +133,8 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
||||||
|
|
||||||
def installation_started(self, app_name: str):
|
def installation_started(self, app_name: str):
|
||||||
game = self.core.get_game(app_name, False)
|
game = self.core.get_game(app_name, False)
|
||||||
|
if not game:
|
||||||
|
return
|
||||||
if game.is_dlc:
|
if game.is_dlc:
|
||||||
return
|
return
|
||||||
self.installing_widget.set_game(app_name)
|
self.installing_widget.set_game(app_name)
|
||||||
|
|
|
@ -88,17 +88,17 @@ class GameInfo(QWidget, Ui_GameInfo):
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
self.verify_widget.setCurrentIndex(1)
|
self.verify_widget.setCurrentIndex(1)
|
||||||
verify_worker = VerifyWorker(self.core, self.game.app_name)
|
verify_worker = VerifyWorker(self.game.app_name)
|
||||||
verify_worker.signals.status.connect(self.verify_staistics)
|
verify_worker.signals.status.connect(self.verify_staistics)
|
||||||
verify_worker.signals.summary.connect(self.finish_verify)
|
verify_worker.signals.summary.connect(self.finish_verify)
|
||||||
self.verify_progress.setValue(0)
|
self.verify_progress.setValue(0)
|
||||||
self.verify_threads[self.game.app_name] = verify_worker
|
self.verify_threads[self.game.app_name] = verify_worker
|
||||||
self.verify_pool.start(verify_worker)
|
self.verify_pool.start(verify_worker)
|
||||||
|
|
||||||
def verify_staistics(self, progress):
|
def verify_staistics(self, num, total, app_name):
|
||||||
# checked, max, app_name
|
# checked, max, app_name
|
||||||
if progress[2] == self.game.app_name:
|
if app_name == self.game.app_name:
|
||||||
self.verify_progress.setValue(progress[0] * 100 // progress[1])
|
self.verify_progress.setValue(num * 100 // total)
|
||||||
|
|
||||||
def finish_verify(self, failed, missing, app_name):
|
def finish_verify(self, failed, missing, app_name):
|
||||||
if failed == missing == 0:
|
if failed == missing == 0:
|
||||||
|
|
|
@ -66,7 +66,7 @@ class GameSettings(QWidget, Ui_GameSettings):
|
||||||
"",
|
"",
|
||||||
file_type=QFileDialog.DirectoryOnly,
|
file_type=QFileDialog.DirectoryOnly,
|
||||||
ph_text=self.tr("Cloud save path"),
|
ph_text=self.tr("Cloud save path"),
|
||||||
edit_func=lambda text: (os.path.exists(text), text),
|
edit_func=lambda text: (os.path.exists(text), text, PathEdit.reasons.dir_not_exist),
|
||||||
save_func=self.save_save_path,
|
save_func=self.save_save_path,
|
||||||
)
|
)
|
||||||
self.cloud_gb.layout().addRow(
|
self.cloud_gb.layout().addRow(
|
||||||
|
@ -296,12 +296,12 @@ class GameSettings(QWidget, Ui_GameSettings):
|
||||||
|
|
||||||
self.core.lgd.save_config()
|
self.core.lgd.save_config()
|
||||||
|
|
||||||
def proton_prefix_edit(self, text: str) -> Tuple[bool, str]:
|
def proton_prefix_edit(self, text: str) -> Tuple[bool, str, str]:
|
||||||
if not text:
|
if not text:
|
||||||
text = os.path.expanduser("~/.proton")
|
text = os.path.expanduser("~/.proton")
|
||||||
return True, text
|
return True, text, ""
|
||||||
parent = os.path.dirname(text)
|
parent = os.path.dirname(text)
|
||||||
return os.path.exists(parent), text
|
return os.path.exists(parent), text, PathEdit.reasons.dir_not_exist
|
||||||
|
|
||||||
def proton_prefix_save(self, text: str):
|
def proton_prefix_save(self, text: str):
|
||||||
self.core.lgd.config.set(
|
self.core.lgd.config.set(
|
||||||
|
|
|
@ -88,9 +88,9 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
|
||||||
self.egl_path_edit.setText(path)
|
self.egl_path_edit.setText(path)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def egl_path_edit_edit_cb(path) -> Tuple[bool, str]:
|
def egl_path_edit_edit_cb(path) -> Tuple[bool, str, str]:
|
||||||
if not path:
|
if not path:
|
||||||
return True, path
|
return True, path, ""
|
||||||
if os.path.exists(os.path.join(path, "system.reg")) and os.path.exists(
|
if os.path.exists(os.path.join(path, "system.reg")) and os.path.exists(
|
||||||
os.path.join(path, "dosdevices/c:")
|
os.path.join(path, "dosdevices/c:")
|
||||||
):
|
):
|
||||||
|
@ -104,10 +104,10 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
|
||||||
"ProgramData/Epic/EpicGamesLauncher/Data/Manifests"
|
"ProgramData/Epic/EpicGamesLauncher/Data/Manifests"
|
||||||
):
|
):
|
||||||
# lower() might or might not be needed in the check
|
# lower() might or might not be needed in the check
|
||||||
return False, path
|
return False, path, PathEdit.reasons.wrong_path
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return True, path
|
return True, path, ""
|
||||||
return False, path
|
return False, path, PathEdit.reasons.dir_not_exist
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def egl_path_edit_save_cb(path):
|
def egl_path_edit_save_cb(path):
|
||||||
|
|
|
@ -99,13 +99,15 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
|
||||||
self.import_button.setEnabled(False)
|
self.import_button.setEnabled(False)
|
||||||
self.import_button.clicked.connect(self.import_game)
|
self.import_button.clicked.connect(self.import_game)
|
||||||
|
|
||||||
def path_edit_cb(self, path) -> Tuple[bool, str]:
|
def path_edit_cb(self, path) -> Tuple[bool, str, str]:
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
if os.path.exists(os.path.join(path, ".egstore")):
|
if os.path.exists(os.path.join(path, ".egstore")):
|
||||||
return True, path
|
return True, path, ""
|
||||||
elif os.path.basename(path) in self.install_dir_list:
|
elif os.path.basename(path) in self.install_dir_list:
|
||||||
return True, path
|
return True, path, ""
|
||||||
return False, path
|
else:
|
||||||
|
return False, path, PathEdit.reasons.dir_not_exist
|
||||||
|
return False, path, ""
|
||||||
|
|
||||||
def path_changed(self, path):
|
def path_changed(self, path):
|
||||||
self.info_label.setText(str())
|
self.info_label.setText(str())
|
||||||
|
@ -114,13 +116,13 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
|
||||||
else:
|
else:
|
||||||
self.app_name.setText(str())
|
self.app_name.setText(str())
|
||||||
|
|
||||||
def app_name_edit_cb(self, text) -> Tuple[bool, str]:
|
def app_name_edit_cb(self, text) -> Tuple[bool, str, str]:
|
||||||
if not text:
|
if not text:
|
||||||
return False, text
|
return False, text, ""
|
||||||
if text in self.app_name_list:
|
if text in self.app_name_list:
|
||||||
return True, text
|
return True, text, ""
|
||||||
else:
|
else:
|
||||||
return False, text
|
return False, text, IndicatorLineEdit.reasons.game_not_installed
|
||||||
|
|
||||||
def app_name_changed(self, text):
|
def app_name_changed(self, text):
|
||||||
self.info_label.setText(str())
|
self.info_label.setText(str())
|
||||||
|
|
249
rare/components/tabs/settings/eos.py
Normal file
249
rare/components/tabs/settings/eos.py
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
from logging import getLogger
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from PyQt5.QtCore import QRunnable, QObject, pyqtSignal, QThreadPool
|
||||||
|
from PyQt5.QtWidgets import QGroupBox, QMessageBox
|
||||||
|
|
||||||
|
from legendary.utils import eos
|
||||||
|
from rare import shared
|
||||||
|
from rare.ui.components.tabs.settings.eos_widget import Ui_EosWidget
|
||||||
|
from rare.utils.models import InstallOptionsModel
|
||||||
|
|
||||||
|
logger = getLogger("EOS")
|
||||||
|
|
||||||
|
|
||||||
|
def get_wine_prefixes() -> List[str]:
|
||||||
|
if os.path.exists(p := os.path.expanduser("~/.wine")):
|
||||||
|
prefixes = [p]
|
||||||
|
else:
|
||||||
|
prefixes = []
|
||||||
|
for i in shared.core.get_installed_list():
|
||||||
|
# get prefix from environment
|
||||||
|
env = shared.core.get_app_environment(i.app_name)
|
||||||
|
if pfx := env.get("WINEPREFIX"):
|
||||||
|
if pfx not in prefixes and os.path.exists(os.path.join(pfx, "user.reg")):
|
||||||
|
prefixes.append(pfx)
|
||||||
|
if steam_pfx := env.get("STEAM_COMPAT_DATA_PATH"):
|
||||||
|
if steam_pfx not in prefixes and os.path.exists(os.path.join(steam_pfx, "user.reg")):
|
||||||
|
prefixes.append(os.path.join(steam_pfx, "pfx"))
|
||||||
|
return prefixes
|
||||||
|
|
||||||
|
|
||||||
|
class WorkerSignals(QObject):
|
||||||
|
update_available = pyqtSignal(bool)
|
||||||
|
|
||||||
|
|
||||||
|
class CheckForUpdateWorker(QRunnable):
|
||||||
|
def __init__(self):
|
||||||
|
super(CheckForUpdateWorker, self).__init__()
|
||||||
|
self.setAutoDelete(True)
|
||||||
|
self.signals = WorkerSignals()
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
shared.core.check_for_overlay_updates()
|
||||||
|
self.signals.update_available.emit(shared.core.overlay_update_available)
|
||||||
|
|
||||||
|
|
||||||
|
class EosWidget(QGroupBox, Ui_EosWidget):
|
||||||
|
def __init__(self):
|
||||||
|
super(EosWidget, self).__init__()
|
||||||
|
self.setupUi(self)
|
||||||
|
self.core = shared.core
|
||||||
|
|
||||||
|
if platform.system() != "Windows":
|
||||||
|
self.setTitle(f"{self.title()} - {self.tr(' - This won´t work with Wine. It might work in the Future')}")
|
||||||
|
|
||||||
|
self.prefix_enabled = False
|
||||||
|
|
||||||
|
self.info_stack.addWidget(self.installed_info_gb)
|
||||||
|
self.info_stack.addWidget(self.install_overlay_gb)
|
||||||
|
|
||||||
|
self.enabled_cb.stateChanged.connect(self.change_enable)
|
||||||
|
self.uninstall_button.clicked.connect(self.uninstall_overlay)
|
||||||
|
|
||||||
|
self.update_button.setVisible(False)
|
||||||
|
self.update_info_lbl.setVisible(False)
|
||||||
|
self.overlay = self.core.lgd.get_overlay_install_info()
|
||||||
|
|
||||||
|
shared.signals.overlay_installation_finished.connect(self.overlay_installation_finished)
|
||||||
|
shared.signals.wine_prefix_updated.connect(self.update_prefixes)
|
||||||
|
|
||||||
|
self.update_check_button.clicked.connect(self.check_for_update)
|
||||||
|
self.install_button.clicked.connect(self.install_overlay)
|
||||||
|
self.update_button.clicked.connect(lambda: self.install_overlay(True))
|
||||||
|
|
||||||
|
if self.overlay: # installed
|
||||||
|
self.installed_version_lbl.setText(self.overlay.version)
|
||||||
|
self.installed_path_lbl.setText(self.overlay.install_path)
|
||||||
|
else:
|
||||||
|
self.info_stack.setCurrentIndex(1)
|
||||||
|
self.enable_gb.setDisabled(True)
|
||||||
|
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
self.current_prefix = None
|
||||||
|
self.select_pfx_combo.setVisible(False)
|
||||||
|
else:
|
||||||
|
self.current_prefix = os.path.expanduser("~/.wine") \
|
||||||
|
if os.path.exists(os.path.expanduser("~/.wine")) \
|
||||||
|
else None
|
||||||
|
pfxs = get_wine_prefixes()
|
||||||
|
for pfx in pfxs:
|
||||||
|
self.select_pfx_combo.addItem(pfx.replace(os.path.expanduser("~/"), "~/"))
|
||||||
|
if not pfxs:
|
||||||
|
self.enable_gb.setDisabled(True)
|
||||||
|
else:
|
||||||
|
self.select_pfx_combo.setCurrentIndex(0)
|
||||||
|
|
||||||
|
self.select_pfx_combo.currentIndexChanged.connect(self.update_select_combo)
|
||||||
|
if pfxs:
|
||||||
|
self.update_select_combo(None)
|
||||||
|
|
||||||
|
self.enabled_info_label.setText("")
|
||||||
|
|
||||||
|
self.threadpool = QThreadPool.globalInstance()
|
||||||
|
|
||||||
|
def update_prefixes(self):
|
||||||
|
logger.debug("Updated prefixes")
|
||||||
|
pfxs = get_wine_prefixes() # returns /home/whatever
|
||||||
|
self.select_pfx_combo.clear()
|
||||||
|
|
||||||
|
for pfx in pfxs:
|
||||||
|
self.select_pfx_combo.addItem(pfx.replace(os.path.expanduser("~/"), "~/"))
|
||||||
|
|
||||||
|
if self.current_prefix in pfxs:
|
||||||
|
self.select_pfx_combo.setCurrentIndex(
|
||||||
|
self.select_pfx_combo.findText(self.current_prefix.replace(os.path.expanduser("~/"), "~/")))
|
||||||
|
|
||||||
|
def check_for_update(self):
|
||||||
|
def worker_finished(update_available):
|
||||||
|
self.update_button.setVisible(update_available)
|
||||||
|
self.update_info_lbl.setVisible(update_available)
|
||||||
|
self.update_check_button.setDisabled(False)
|
||||||
|
if not update_available:
|
||||||
|
self.update_check_button.setText(self.tr("No update available"))
|
||||||
|
|
||||||
|
self.update_check_button.setDisabled(True)
|
||||||
|
worker = CheckForUpdateWorker()
|
||||||
|
worker.signals.update_available.connect(worker_finished)
|
||||||
|
QThreadPool.globalInstance().start(worker)
|
||||||
|
|
||||||
|
def overlay_installation_finished(self):
|
||||||
|
self.overlay = self.core.lgd.get_overlay_install_info()
|
||||||
|
|
||||||
|
if not self.overlay:
|
||||||
|
logger.error("Something went wrong, when installing overlay")
|
||||||
|
QMessageBox.warning(self, "Error", self.tr("Something went wrong, when installing overlay"))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.info_stack.setCurrentIndex(0)
|
||||||
|
self.installed_version_lbl.setText(self.overlay.version)
|
||||||
|
self.installed_path_lbl.setText(self.overlay.install_path)
|
||||||
|
|
||||||
|
self.update_button.setVisible(False)
|
||||||
|
self.update_info_lbl.setVisible(False)
|
||||||
|
|
||||||
|
self.enable_gb.setEnabled(True)
|
||||||
|
|
||||||
|
def update_select_combo(self, i: None):
|
||||||
|
if i is None:
|
||||||
|
i = self.select_pfx_combo.currentIndex()
|
||||||
|
prefix = os.path.expanduser(self.select_pfx_combo.itemText(i))
|
||||||
|
if platform.system() != "Windows" and not os.path.exists(prefix):
|
||||||
|
return
|
||||||
|
self.current_prefix = prefix
|
||||||
|
reg_paths = eos.query_registry_entries(self.current_prefix)
|
||||||
|
|
||||||
|
overlay_enabled = False
|
||||||
|
if reg_paths['overlay_path'] and self.core.is_overlay_install(reg_paths['overlay_path']):
|
||||||
|
overlay_enabled = True
|
||||||
|
self.enabled_cb.setChecked(overlay_enabled)
|
||||||
|
|
||||||
|
def change_enable(self):
|
||||||
|
enabled = self.enabled_cb.isChecked()
|
||||||
|
if not enabled:
|
||||||
|
eos.remove_registry_entries(self.current_prefix)
|
||||||
|
logger.info("Disabled Epic Overlay")
|
||||||
|
self.enabled_info_label.setText(self.tr("Disabled"))
|
||||||
|
else:
|
||||||
|
if not self.overlay:
|
||||||
|
available_installs = self.core.search_overlay_installs(self.current_prefix)
|
||||||
|
if not available_installs:
|
||||||
|
logger.error('No EOS overlay installs found!')
|
||||||
|
return
|
||||||
|
path = available_installs[0]
|
||||||
|
else:
|
||||||
|
path = self.overlay.install_path
|
||||||
|
|
||||||
|
if not self.core.is_overlay_install(path):
|
||||||
|
logger.error(f'Not a valid Overlay installation: {path}')
|
||||||
|
self.select_pfx_combo.removeItem(self.select_pfx_combo.currentIndex())
|
||||||
|
return
|
||||||
|
|
||||||
|
path = os.path.normpath(path)
|
||||||
|
reg_paths = eos.query_registry_entries(self.current_prefix)
|
||||||
|
if old_path := reg_paths["overlay_path"]:
|
||||||
|
if os.path.normpath(old_path) == path:
|
||||||
|
logger.info(f'Overlay already enabled, nothing to do.')
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
logger.info(f'Updating overlay registry entries from "{old_path}" to "{path}"')
|
||||||
|
eos.remove_registry_entries(self.current_prefix)
|
||||||
|
eos.add_registry_entries(path, self.current_prefix)
|
||||||
|
self.enabled_info_label.setText(self.tr("Enabled"))
|
||||||
|
logger.info(f'Enabled overlay at: {path}')
|
||||||
|
|
||||||
|
def update_checkbox(self):
|
||||||
|
reg_paths = eos.query_registry_entries(self.current_prefix)
|
||||||
|
enabled = False
|
||||||
|
if reg_paths['overlay_path'] and self.core.is_overlay_install(reg_paths['overlay_path']):
|
||||||
|
enabled = True
|
||||||
|
self.enabled_cb.setChecked(enabled)
|
||||||
|
|
||||||
|
def install_overlay(self, update=False):
|
||||||
|
if platform.system() != "Windows":
|
||||||
|
if QMessageBox.No == QMessageBox.question(self, "Warning",
|
||||||
|
self.tr("Epic overlay is currently not supported by wine, so it won't work. Install anyway? "),
|
||||||
|
QMessageBox.Yes | QMessageBox.No, QMessageBox.No):
|
||||||
|
return
|
||||||
|
|
||||||
|
base_path = os.path.expanduser("~/legendary/.overlay")
|
||||||
|
if update:
|
||||||
|
if not self.overlay:
|
||||||
|
self.info_stack.setCurrentIndex(1)
|
||||||
|
self.enable_gb.setDisabled(True)
|
||||||
|
QMessageBox.warning(self, "Warning", self.tr("Overlay is not installed. Could not update"))
|
||||||
|
return
|
||||||
|
base_path = self.overlay.install_path
|
||||||
|
|
||||||
|
options = InstallOptionsModel(app_name="", base_path=base_path,
|
||||||
|
platform="Windows", overlay=True)
|
||||||
|
|
||||||
|
shared.signals.install_game.emit(options)
|
||||||
|
|
||||||
|
def uninstall_overlay(self):
|
||||||
|
if not self.core.is_overlay_installed():
|
||||||
|
logger.error('No legendary-managed overlay installation found.')
|
||||||
|
self.info_stack.setCurrentIndex(1)
|
||||||
|
return
|
||||||
|
|
||||||
|
if QMessageBox.No == QMessageBox.question(
|
||||||
|
self, "Uninstall Overlay", self.tr("Do you want to uninstall overlay?"),
|
||||||
|
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
|
||||||
|
):
|
||||||
|
return
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
eos.remove_registry_entries(None)
|
||||||
|
else:
|
||||||
|
for prefix in [self.select_pfx_combo.itemText(i) for i in range(self.select_pfx_combo.count())]:
|
||||||
|
logger.info(f"Removing registry entries from {prefix}")
|
||||||
|
try:
|
||||||
|
eos.remove_registry_entries(os.path.expanduser(prefix))
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"{prefix}: {e}")
|
||||||
|
|
||||||
|
self.core.remove_overlay_install()
|
||||||
|
self.info_stack.setCurrentIndex(1)
|
||||||
|
|
||||||
|
self.enable_gb.setDisabled(True)
|
|
@ -6,6 +6,7 @@ from PyQt5.QtCore import QRunnable, QObject, pyqtSignal, QThreadPool
|
||||||
from PyQt5.QtWidgets import QSizePolicy, QWidget, QFileDialog, QMessageBox
|
from PyQt5.QtWidgets import QSizePolicy, QWidget, QFileDialog, QMessageBox
|
||||||
|
|
||||||
import rare.shared as shared
|
import rare.shared as shared
|
||||||
|
from rare.components.tabs.settings.eos import EosWidget
|
||||||
from rare.components.tabs.settings.ubisoft_activation import UbiActivationHelper
|
from rare.components.tabs.settings.ubisoft_activation import UbiActivationHelper
|
||||||
from rare.ui.components.tabs.settings.legendary import Ui_LegendarySettings
|
from rare.ui.components.tabs.settings.legendary import Ui_LegendarySettings
|
||||||
from rare.utils.extra_widgets import PathEdit, IndicatorLineEdit
|
from rare.utils.extra_widgets import PathEdit, IndicatorLineEdit
|
||||||
|
@ -84,6 +85,9 @@ class LegendarySettings(QWidget, Ui_LegendarySettings):
|
||||||
self.locale_layout.addWidget(self.locale_edit)
|
self.locale_layout.addWidget(self.locale_edit)
|
||||||
|
|
||||||
self.ubi_helper = UbiActivationHelper(self.ubisoft_gb)
|
self.ubi_helper = UbiActivationHelper(self.ubisoft_gb)
|
||||||
|
self.eos_widget = EosWidget()
|
||||||
|
self.layout().replaceWidget(self.eos_placeholder, self.eos_widget)
|
||||||
|
self.eos_placeholder.deleteLater()
|
||||||
|
|
||||||
self.refresh_game_meta_btn.clicked.connect(self.refresh_game_meta)
|
self.refresh_game_meta_btn.clicked.connect(self.refresh_game_meta)
|
||||||
|
|
||||||
|
@ -96,14 +100,18 @@ class LegendarySettings(QWidget, Ui_LegendarySettings):
|
||||||
QThreadPool.globalInstance().start(worker)
|
QThreadPool.globalInstance().start(worker)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def locale_edit_cb(text: str) -> Tuple[bool, str]:
|
def locale_edit_cb(text: str) -> Tuple[bool, str, str]:
|
||||||
if text:
|
if text:
|
||||||
if re.match("^[a-zA-Z]{2,3}[-_][a-zA-Z]{2,3}$", text):
|
if re.match("^[a-zA-Z]{2,3}[-_][a-zA-Z]{2,3}$", text):
|
||||||
language, country = text.replace("_", "-").split("-")
|
language, country = text.replace("_", "-").split("-")
|
||||||
text = "-".join([language.lower(), country.upper()])
|
text = "-".join([language.lower(), country.upper()])
|
||||||
return bool(re.match("^[a-z]{2,3}-[A-Z]{2,3}$", text)), text
|
if bool(re.match("^[a-z]{2,3}-[A-Z]{2,3}$", text)):
|
||||||
|
return True, text, ""
|
||||||
else:
|
else:
|
||||||
return True, text
|
return False, text, IndicatorLineEdit.reasons.wrong_format
|
||||||
|
|
||||||
|
else:
|
||||||
|
return True, text, ""
|
||||||
|
|
||||||
def locale_save_cb(self, text: str):
|
def locale_save_cb(self, text: str):
|
||||||
if text:
|
if text:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import os
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QFileDialog, QWidget
|
from PyQt5.QtWidgets import QFileDialog, QWidget
|
||||||
|
@ -21,6 +22,7 @@ class LinuxSettings(QWidget, Ui_LinuxSettings):
|
||||||
self.wine_prefix = PathEdit(
|
self.wine_prefix = PathEdit(
|
||||||
self.load_prefix(),
|
self.load_prefix(),
|
||||||
file_type=QFileDialog.DirectoryOnly,
|
file_type=QFileDialog.DirectoryOnly,
|
||||||
|
edit_func=lambda path: (os.path.isdir(path), path, PathEdit.reasons.dir_not_exist),
|
||||||
save_func=self.save_prefix,
|
save_func=self.save_prefix,
|
||||||
)
|
)
|
||||||
self.prefix_layout.addWidget(self.wine_prefix)
|
self.prefix_layout.addWidget(self.wine_prefix)
|
||||||
|
@ -50,6 +52,7 @@ class LinuxSettings(QWidget, Ui_LinuxSettings):
|
||||||
def save_prefix(self, text: str):
|
def save_prefix(self, text: str):
|
||||||
self.save_setting(text, f"{self.name}.env", "WINEPREFIX")
|
self.save_setting(text, f"{self.name}.env", "WINEPREFIX")
|
||||||
self.save_setting(text, self.name, "wine_prefix")
|
self.save_setting(text, self.name, "wine_prefix")
|
||||||
|
shared.signals.wine_prefix_updated.emit()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_setting(section: str, setting: str, fallback: str = str()):
|
def load_setting(section: str, setting: str, fallback: str = str()):
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit d371c0b3c48a422ff7e6c966af649a1502300c2d
|
Subproject commit 747afa1ea2e94ddd8fad80cbf8e407499929b68d
|
151
rare/ui/components/tabs/settings/eos_widget.py
Normal file
151
rare/ui/components/tabs/settings/eos_widget.py
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'rare/ui/components/tabs/settings/eos_widget.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.6
|
||||||
|
#
|
||||||
|
# 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_EosWidget(object):
|
||||||
|
def setupUi(self, EosWidget):
|
||||||
|
EosWidget.setObjectName("EosWidget")
|
||||||
|
EosWidget.resize(1128, 319)
|
||||||
|
EosWidget.setWindowTitle("GroupBox")
|
||||||
|
self.horizontalLayout = QtWidgets.QHBoxLayout(EosWidget)
|
||||||
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
|
self.info_stack = QtWidgets.QStackedWidget(EosWidget)
|
||||||
|
self.info_stack.setObjectName("info_stack")
|
||||||
|
self.horizontalLayout.addWidget(self.info_stack)
|
||||||
|
self.enable_gb = QtWidgets.QGroupBox(EosWidget)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.enable_gb.sizePolicy().hasHeightForWidth())
|
||||||
|
self.enable_gb.setSizePolicy(sizePolicy)
|
||||||
|
self.enable_gb.setObjectName("enable_gb")
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(self.enable_gb)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.select_pfx_combo = QtWidgets.QComboBox(self.enable_gb)
|
||||||
|
self.select_pfx_combo.setObjectName("select_pfx_combo")
|
||||||
|
self.verticalLayout.addWidget(self.select_pfx_combo, 0, QtCore.Qt.AlignTop)
|
||||||
|
self.enabled_cb = QtWidgets.QCheckBox(self.enable_gb)
|
||||||
|
self.enabled_cb.setObjectName("enabled_cb")
|
||||||
|
self.verticalLayout.addWidget(self.enabled_cb)
|
||||||
|
self.enabled_info_label = QtWidgets.QLabel(self.enable_gb)
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setItalic(True)
|
||||||
|
self.enabled_info_label.setFont(font)
|
||||||
|
self.enabled_info_label.setText("")
|
||||||
|
self.enabled_info_label.setObjectName("enabled_info_label")
|
||||||
|
self.verticalLayout.addWidget(self.enabled_info_label)
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
|
self.verticalLayout.addItem(spacerItem)
|
||||||
|
self.horizontalLayout.addWidget(self.enable_gb)
|
||||||
|
self.installed_info_gb = QtWidgets.QGroupBox(EosWidget)
|
||||||
|
self.installed_info_gb.setObjectName("installed_info_gb")
|
||||||
|
self.formLayout = QtWidgets.QFormLayout(self.installed_info_gb)
|
||||||
|
self.formLayout.setObjectName("formLayout")
|
||||||
|
self.installed_version_info_lbl = QtWidgets.QLabel(self.installed_info_gb)
|
||||||
|
self.installed_version_info_lbl.setObjectName("installed_version_info_lbl")
|
||||||
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.installed_version_info_lbl)
|
||||||
|
self.installed_version_lbl = QtWidgets.QLabel(self.installed_info_gb)
|
||||||
|
self.installed_version_lbl.setText("TextLabel")
|
||||||
|
self.installed_version_lbl.setObjectName("installed_version_lbl")
|
||||||
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.installed_version_lbl)
|
||||||
|
self.installed_path_info_lbl = QtWidgets.QLabel(self.installed_info_gb)
|
||||||
|
self.installed_path_info_lbl.setObjectName("installed_path_info_lbl")
|
||||||
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.installed_path_info_lbl)
|
||||||
|
self.installed_path_lbl = QtWidgets.QLabel(self.installed_info_gb)
|
||||||
|
self.installed_path_lbl.setText("TextLabel")
|
||||||
|
self.installed_path_lbl.setObjectName("installed_path_lbl")
|
||||||
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.installed_path_lbl)
|
||||||
|
self.update_available_info_label = QtWidgets.QLabel(self.installed_info_gb)
|
||||||
|
self.update_available_info_label.setObjectName("update_available_info_label")
|
||||||
|
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.update_available_info_label)
|
||||||
|
self.update_check_button = QtWidgets.QPushButton(self.installed_info_gb)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.update_check_button.sizePolicy().hasHeightForWidth())
|
||||||
|
self.update_check_button.setSizePolicy(sizePolicy)
|
||||||
|
self.update_check_button.setMaximumSize(QtCore.QSize(150, 16777215))
|
||||||
|
self.update_check_button.setObjectName("update_check_button")
|
||||||
|
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.update_check_button)
|
||||||
|
self.uninstall_info_label = QtWidgets.QLabel(self.installed_info_gb)
|
||||||
|
self.uninstall_info_label.setObjectName("uninstall_info_label")
|
||||||
|
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.uninstall_info_label)
|
||||||
|
self.uninstall_button = QtWidgets.QPushButton(self.installed_info_gb)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.uninstall_button.sizePolicy().hasHeightForWidth())
|
||||||
|
self.uninstall_button.setSizePolicy(sizePolicy)
|
||||||
|
self.uninstall_button.setMaximumSize(QtCore.QSize(150, 16777215))
|
||||||
|
self.uninstall_button.setObjectName("uninstall_button")
|
||||||
|
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.uninstall_button)
|
||||||
|
self.update_button = QtWidgets.QPushButton(self.installed_info_gb)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Minimum)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.update_button.sizePolicy().hasHeightForWidth())
|
||||||
|
self.update_button.setSizePolicy(sizePolicy)
|
||||||
|
self.update_button.setMaximumSize(QtCore.QSize(150, 16777215))
|
||||||
|
self.update_button.setObjectName("update_button")
|
||||||
|
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.update_button)
|
||||||
|
self.update_info_lbl = QtWidgets.QLabel(self.installed_info_gb)
|
||||||
|
self.update_info_lbl.setObjectName("update_info_lbl")
|
||||||
|
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.update_info_lbl)
|
||||||
|
self.horizontalLayout.addWidget(self.installed_info_gb)
|
||||||
|
self.install_overlay_gb = QtWidgets.QGroupBox(EosWidget)
|
||||||
|
self.install_overlay_gb.setObjectName("install_overlay_gb")
|
||||||
|
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.install_overlay_gb)
|
||||||
|
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||||
|
self.label = QtWidgets.QLabel(self.install_overlay_gb)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
|
||||||
|
self.label.setSizePolicy(sizePolicy)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.verticalLayout_4.addWidget(self.label)
|
||||||
|
self.install_button = QtWidgets.QPushButton(self.install_overlay_gb)
|
||||||
|
self.install_button.setObjectName("install_button")
|
||||||
|
self.verticalLayout_4.addWidget(self.install_button)
|
||||||
|
self.horizontalLayout.addWidget(self.install_overlay_gb)
|
||||||
|
|
||||||
|
self.retranslateUi(EosWidget)
|
||||||
|
self.info_stack.setCurrentIndex(-1)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(EosWidget)
|
||||||
|
|
||||||
|
def retranslateUi(self, EosWidget):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
EosWidget.setTitle(_translate("EosWidget", "Epic Overlay settings"))
|
||||||
|
self.enable_gb.setTitle(_translate("EosWidget", "Enable / Disable"))
|
||||||
|
self.enabled_cb.setText(_translate("EosWidget", "Activated"))
|
||||||
|
self.installed_info_gb.setTitle(_translate("EosWidget", "Installed Info"))
|
||||||
|
self.installed_version_info_lbl.setText(_translate("EosWidget", "Installed version:"))
|
||||||
|
self.installed_path_info_lbl.setText(_translate("EosWidget", "Installed path"))
|
||||||
|
self.update_available_info_label.setText(_translate("EosWidget", "Updates"))
|
||||||
|
self.update_check_button.setText(_translate("EosWidget", "Check for Update"))
|
||||||
|
self.uninstall_info_label.setText(_translate("EosWidget", "Uninstall"))
|
||||||
|
self.uninstall_button.setText(_translate("EosWidget", "Uninstall"))
|
||||||
|
self.update_button.setText(_translate("EosWidget", "Update"))
|
||||||
|
self.update_info_lbl.setText(_translate("EosWidget", "Install Update"))
|
||||||
|
self.install_overlay_gb.setTitle(_translate("EosWidget", "Install Overlay"))
|
||||||
|
self.label.setText(_translate("EosWidget", "No overlays are installed"))
|
||||||
|
self.install_button.setText(_translate("EosWidget", "Install"))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
|
EosWidget = QtWidgets.QGroupBox()
|
||||||
|
ui = Ui_EosWidget()
|
||||||
|
ui.setupUi(EosWidget)
|
||||||
|
EosWidget.show()
|
||||||
|
sys.exit(app.exec_())
|
225
rare/ui/components/tabs/settings/eos_widget.ui
Normal file
225
rare/ui/components/tabs/settings/eos_widget.ui
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>EosWidget</class>
|
||||||
|
<widget class="QGroupBox" name="EosWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1128</width>
|
||||||
|
<height>319</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">GroupBox</string>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Epic Overlay settings</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QStackedWidget" name="info_stack">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="enable_gb">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Enable / Disable</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item alignment="Qt::AlignTop">
|
||||||
|
<widget class="QComboBox" name="select_pfx_combo"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="enabled_cb">
|
||||||
|
<property name="text">
|
||||||
|
<string>Activated</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="enabled_info_label">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<italic>true</italic>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="installed_info_gb">
|
||||||
|
<property name="title">
|
||||||
|
<string>Installed Info</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="installed_version_info_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>Installed version:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="installed_version_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="installed_path_info_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>Installed path</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="installed_path_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true">TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="update_available_info_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Updates</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QPushButton" name="update_check_button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Check for Update</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="uninstall_info_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Uninstall</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QPushButton" name="uninstall_button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Uninstall</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QPushButton" name="update_button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Update</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="update_info_lbl">
|
||||||
|
<property name="text">
|
||||||
|
<string>Install Update</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="install_overlay_gb">
|
||||||
|
<property name="title">
|
||||||
|
<string>Install Overlay</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>No overlays are installed</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="install_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>Install</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
class Ui_LegendarySettings(object):
|
class Ui_LegendarySettings(object):
|
||||||
def setupUi(self, LegendarySettings):
|
def setupUi(self, LegendarySettings):
|
||||||
LegendarySettings.setObjectName("LegendarySettings")
|
LegendarySettings.setObjectName("LegendarySettings")
|
||||||
LegendarySettings.resize(564, 374)
|
LegendarySettings.resize(905, 568)
|
||||||
LegendarySettings.setWindowTitle("LegendarySettings")
|
LegendarySettings.setWindowTitle("LegendarySettings")
|
||||||
self.gridLayout = QtWidgets.QGridLayout(LegendarySettings)
|
self.gridLayout = QtWidgets.QGridLayout(LegendarySettings)
|
||||||
self.gridLayout.setObjectName("gridLayout")
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
|
@ -26,11 +26,13 @@ class Ui_LegendarySettings(object):
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.locale_group.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.locale_group.sizePolicy().hasHeightForWidth())
|
||||||
self.locale_group.setSizePolicy(sizePolicy)
|
self.locale_group.setSizePolicy(sizePolicy)
|
||||||
|
self.locale_group.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
|
||||||
self.locale_group.setObjectName("locale_group")
|
self.locale_group.setObjectName("locale_group")
|
||||||
self.locale_layout = QtWidgets.QVBoxLayout(self.locale_group)
|
self.locale_layout = QtWidgets.QVBoxLayout(self.locale_group)
|
||||||
self.locale_layout.setObjectName("locale_layout")
|
self.locale_layout.setObjectName("locale_layout")
|
||||||
self.right_layout.addWidget(self.locale_group)
|
self.right_layout.addWidget(self.locale_group)
|
||||||
self.cleanup_group = QtWidgets.QGroupBox(LegendarySettings)
|
self.cleanup_group = QtWidgets.QGroupBox(LegendarySettings)
|
||||||
|
self.cleanup_group.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
|
||||||
self.cleanup_group.setObjectName("cleanup_group")
|
self.cleanup_group.setObjectName("cleanup_group")
|
||||||
self.cleanup_layout = QtWidgets.QVBoxLayout(self.cleanup_group)
|
self.cleanup_layout = QtWidgets.QVBoxLayout(self.cleanup_group)
|
||||||
self.cleanup_layout.setObjectName("cleanup_layout")
|
self.cleanup_layout.setObjectName("cleanup_layout")
|
||||||
|
@ -45,19 +47,16 @@ class Ui_LegendarySettings(object):
|
||||||
self.cleanup_layout.addWidget(self.refresh_game_meta_btn)
|
self.cleanup_layout.addWidget(self.refresh_game_meta_btn)
|
||||||
self.right_layout.addWidget(self.cleanup_group)
|
self.right_layout.addWidget(self.cleanup_group)
|
||||||
self.gridLayout.addLayout(self.right_layout, 0, 1, 1, 1)
|
self.gridLayout.addLayout(self.right_layout, 0, 1, 1, 1)
|
||||||
self.ubisoft_gb = QtWidgets.QGroupBox(LegendarySettings)
|
|
||||||
self.ubisoft_gb.setObjectName("ubisoft_gb")
|
|
||||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.ubisoft_gb)
|
|
||||||
self.verticalLayout.setObjectName("verticalLayout")
|
|
||||||
self.gridLayout.addWidget(self.ubisoft_gb, 1, 0, 1, 2)
|
|
||||||
self.left_layout = QtWidgets.QVBoxLayout()
|
self.left_layout = QtWidgets.QVBoxLayout()
|
||||||
self.left_layout.setObjectName("left_layout")
|
self.left_layout.setObjectName("left_layout")
|
||||||
self.install_dir_group = QtWidgets.QGroupBox(LegendarySettings)
|
self.install_dir_group = QtWidgets.QGroupBox(LegendarySettings)
|
||||||
|
self.install_dir_group.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
|
||||||
self.install_dir_group.setObjectName("install_dir_group")
|
self.install_dir_group.setObjectName("install_dir_group")
|
||||||
self.install_dir_layout = QtWidgets.QVBoxLayout(self.install_dir_group)
|
self.install_dir_layout = QtWidgets.QVBoxLayout(self.install_dir_group)
|
||||||
self.install_dir_layout.setObjectName("install_dir_layout")
|
self.install_dir_layout.setObjectName("install_dir_layout")
|
||||||
self.left_layout.addWidget(self.install_dir_group)
|
self.left_layout.addWidget(self.install_dir_group)
|
||||||
self.download_group = QtWidgets.QGroupBox(LegendarySettings)
|
self.download_group = QtWidgets.QGroupBox(LegendarySettings)
|
||||||
|
self.download_group.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
|
||||||
self.download_group.setObjectName("download_group")
|
self.download_group.setObjectName("download_group")
|
||||||
self.download_layout = QtWidgets.QFormLayout(self.download_group)
|
self.download_layout = QtWidgets.QFormLayout(self.download_group)
|
||||||
self.download_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
self.download_layout.setLabelAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
@ -129,8 +128,18 @@ class Ui_LegendarySettings(object):
|
||||||
self.download_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.disable_https_check)
|
self.download_layout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.disable_https_check)
|
||||||
self.left_layout.addWidget(self.download_group)
|
self.left_layout.addWidget(self.download_group)
|
||||||
self.gridLayout.addLayout(self.left_layout, 0, 0, 1, 1)
|
self.gridLayout.addLayout(self.left_layout, 0, 0, 1, 1)
|
||||||
|
self.ubisoft_gb = QtWidgets.QGroupBox(LegendarySettings)
|
||||||
|
self.ubisoft_gb.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
|
||||||
|
self.ubisoft_gb.setObjectName("ubisoft_gb")
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(self.ubisoft_gb)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.gridLayout.addWidget(self.ubisoft_gb, 2, 0, 1, 2)
|
||||||
|
self.eos_placeholder = QtWidgets.QGroupBox(LegendarySettings)
|
||||||
|
self.eos_placeholder.setTitle("GroupBox")
|
||||||
|
self.eos_placeholder.setObjectName("eos_placeholder")
|
||||||
|
self.gridLayout.addWidget(self.eos_placeholder, 3, 0, 1, 2)
|
||||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
self.gridLayout.addItem(spacerItem, 2, 0, 1, 2)
|
self.gridLayout.addItem(spacerItem, 4, 0, 1, 2)
|
||||||
|
|
||||||
self.retranslateUi(LegendarySettings)
|
self.retranslateUi(LegendarySettings)
|
||||||
QtCore.QMetaObject.connectSlotsByName(LegendarySettings)
|
QtCore.QMetaObject.connectSlotsByName(LegendarySettings)
|
||||||
|
@ -142,7 +151,6 @@ class Ui_LegendarySettings(object):
|
||||||
self.clean_keep_manifests_button.setText(_translate("LegendarySettings", "Clean, but keep manifests"))
|
self.clean_keep_manifests_button.setText(_translate("LegendarySettings", "Clean, but keep manifests"))
|
||||||
self.clean_button.setText(_translate("LegendarySettings", "Remove everything"))
|
self.clean_button.setText(_translate("LegendarySettings", "Remove everything"))
|
||||||
self.refresh_game_meta_btn.setText(_translate("LegendarySettings", "Refresh game meta"))
|
self.refresh_game_meta_btn.setText(_translate("LegendarySettings", "Refresh game meta"))
|
||||||
self.ubisoft_gb.setTitle(_translate("LegendarySettings", "Link Ubisoft Games"))
|
|
||||||
self.install_dir_group.setTitle(_translate("LegendarySettings", "Default Installation Directory"))
|
self.install_dir_group.setTitle(_translate("LegendarySettings", "Default Installation Directory"))
|
||||||
self.download_group.setTitle(_translate("LegendarySettings", "Download Settings"))
|
self.download_group.setTitle(_translate("LegendarySettings", "Download Settings"))
|
||||||
self.max_workers_label.setText(_translate("LegendarySettings", "Max Workers"))
|
self.max_workers_label.setText(_translate("LegendarySettings", "Max Workers"))
|
||||||
|
@ -153,6 +161,7 @@ class Ui_LegendarySettings(object):
|
||||||
self.preferred_cdn_label.setText(_translate("LegendarySettings", "Preferred CDN"))
|
self.preferred_cdn_label.setText(_translate("LegendarySettings", "Preferred CDN"))
|
||||||
self.preferred_cdn_line.setPlaceholderText(_translate("LegendarySettings", "Default"))
|
self.preferred_cdn_line.setPlaceholderText(_translate("LegendarySettings", "Default"))
|
||||||
self.disable_https_label.setText(_translate("LegendarySettings", "Disable HTTPS"))
|
self.disable_https_label.setText(_translate("LegendarySettings", "Disable HTTPS"))
|
||||||
|
self.ubisoft_gb.setTitle(_translate("LegendarySettings", "Link Ubisoft Games"))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>564</width>
|
<width>905</width>
|
||||||
<height>374</height>
|
<height>568</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -27,6 +27,9 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Locale</string>
|
<string>Locale</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="locale_layout"/>
|
<layout class="QVBoxLayout" name="locale_layout"/>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -35,6 +38,9 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Cleanup</string>
|
<string>Cleanup</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="cleanup_layout">
|
<layout class="QVBoxLayout" name="cleanup_layout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="clean_keep_manifests_button">
|
<widget class="QPushButton" name="clean_keep_manifests_button">
|
||||||
|
@ -62,14 +68,6 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" colspan="2">
|
|
||||||
<widget class="QGroupBox" name="ubisoft_gb">
|
|
||||||
<property name="title">
|
|
||||||
<string>Link Ubisoft Games</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<layout class="QVBoxLayout" name="left_layout">
|
<layout class="QVBoxLayout" name="left_layout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -77,6 +75,9 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Default Installation Directory</string>
|
<string>Default Installation Directory</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="install_dir_layout"/>
|
<layout class="QVBoxLayout" name="install_dir_layout"/>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -85,6 +86,9 @@
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Download Settings</string>
|
<string>Download Settings</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
<layout class="QFormLayout" name="download_layout">
|
<layout class="QFormLayout" name="download_layout">
|
||||||
<property name="labelAlignment">
|
<property name="labelAlignment">
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
@ -219,6 +223,24 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" colspan="2">
|
<item row="2" column="0" colspan="2">
|
||||||
|
<widget class="QGroupBox" name="ubisoft_gb">
|
||||||
|
<property name="title">
|
||||||
|
<string>Link Ubisoft Games</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QGroupBox" name="eos_placeholder">
|
||||||
|
<property name="title">
|
||||||
|
<string notr="true">GroupBox</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0" colspan="2">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
|
|
@ -143,16 +143,25 @@ class FlowLayout(QLayout):
|
||||||
return parent.spacing()
|
return parent.spacing()
|
||||||
|
|
||||||
|
|
||||||
|
class IndicatorReasons:
|
||||||
|
dir_not_empty = QCoreApplication.translate("IndicatorReasons", "Directory is not empty")
|
||||||
|
wrong_format = QCoreApplication.translate("IndicatorReasons", "Given text has wrong format")
|
||||||
|
game_not_installed = QCoreApplication.translate("IndicatorReasons", "Game is not installed or does not exist")
|
||||||
|
dir_not_exist = QCoreApplication.translate("IndicatorReasons", "Directory does not exist")
|
||||||
|
wrong_path = QCoreApplication.translate("IndicatorReasons", "Wrong Directory")
|
||||||
|
|
||||||
|
|
||||||
class IndicatorLineEdit(QWidget):
|
class IndicatorLineEdit(QWidget):
|
||||||
textChanged = pyqtSignal(str)
|
textChanged = pyqtSignal(str)
|
||||||
is_valid = False
|
is_valid = False
|
||||||
|
reasons = IndicatorReasons()
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
text: str = "",
|
text: str = "",
|
||||||
ph_text: str = "",
|
ph_text: str = "",
|
||||||
completer: QCompleter = None,
|
completer: QCompleter = None,
|
||||||
edit_func: Callable[[str], Tuple[bool, str]] = None,
|
edit_func: Callable[[str], Tuple[bool, str, str]] = None,
|
||||||
save_func: Callable[[str], None] = None,
|
save_func: Callable[[str], None] = None,
|
||||||
horiz_policy: QSizePolicy = QSizePolicy.Expanding,
|
horiz_policy: QSizePolicy = QSizePolicy.Expanding,
|
||||||
parent=None,
|
parent=None,
|
||||||
|
@ -219,20 +228,25 @@ class IndicatorLineEdit(QWidget):
|
||||||
self.hint_label.setFrameRect(self.line_edit.rect())
|
self.hint_label.setFrameRect(self.line_edit.rect())
|
||||||
self.hint_label.setText(text)
|
self.hint_label.setText(text)
|
||||||
|
|
||||||
def __indicator(self, res):
|
def __indicator(self, res, reason=None):
|
||||||
color = "green" if res else "red"
|
color = "green" if res else "red"
|
||||||
self.indicator_label.setPixmap(
|
self.indicator_label.setPixmap(
|
||||||
qta_icon("ei.info-circle", color=color).pixmap(16, 16)
|
qta_icon("ei.info-circle", color=color).pixmap(16, 16)
|
||||||
)
|
)
|
||||||
|
if reason:
|
||||||
|
self.indicator_label.setToolTip(reason)
|
||||||
|
else:
|
||||||
|
self.indicator_label.setToolTip("")
|
||||||
|
|
||||||
def __edit(self, text):
|
def __edit(self, text):
|
||||||
if self.edit_func is not None:
|
if self.edit_func is not None:
|
||||||
self.line_edit.blockSignals(True)
|
self.line_edit.blockSignals(True)
|
||||||
self.is_valid, text = self.edit_func(text)
|
|
||||||
|
self.is_valid, text, reason = self.edit_func(text)
|
||||||
if text != self.line_edit.text():
|
if text != self.line_edit.text():
|
||||||
self.line_edit.setText(text)
|
self.line_edit.setText(text)
|
||||||
self.line_edit.blockSignals(False)
|
self.line_edit.blockSignals(False)
|
||||||
self.__indicator(self.is_valid)
|
self.__indicator(self.is_valid, reason)
|
||||||
if self.is_valid:
|
if self.is_valid:
|
||||||
self.__save(text)
|
self.__save(text)
|
||||||
self.textChanged.emit(text)
|
self.textChanged.emit(text)
|
||||||
|
@ -286,7 +300,7 @@ class PathEdit(IndicatorLineEdit):
|
||||||
type_filter: str = "",
|
type_filter: str = "",
|
||||||
name_filter: str = "",
|
name_filter: str = "",
|
||||||
ph_text: str = "",
|
ph_text: str = "",
|
||||||
edit_func: Callable[[str], Tuple[bool, str]] = None,
|
edit_func: Callable[[str], Tuple[bool, str, str]] = None,
|
||||||
save_func: Callable[[str], None] = None,
|
save_func: Callable[[str], None] = None,
|
||||||
horiz_policy: QSizePolicy = QSizePolicy.Expanding,
|
horiz_policy: QSizePolicy = QSizePolicy.Expanding,
|
||||||
parent=None,
|
parent=None,
|
||||||
|
|
|
@ -4,11 +4,11 @@ import shutil
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, QCoreApplication, QObject, QRunnable
|
from PyQt5.QtCore import pyqtSignal, QCoreApplication, QObject, QRunnable
|
||||||
from PyQt5.QtWidgets import QMessageBox
|
|
||||||
|
|
||||||
from legendary.core import LegendaryCore
|
from legendary.core import LegendaryCore
|
||||||
from legendary.models.game import VerifyResult
|
from legendary.models.game import VerifyResult
|
||||||
from legendary.utils.lfs import validate_files
|
from legendary.utils.lfs import validate_files
|
||||||
|
from rare import shared
|
||||||
|
|
||||||
logger = getLogger("Legendary Utils")
|
logger = getLogger("Legendary Utils")
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ def update_manifest(app_name: str, core: LegendaryCore):
|
||||||
|
|
||||||
|
|
||||||
class VerifySignals(QObject):
|
class VerifySignals(QObject):
|
||||||
status = pyqtSignal(tuple)
|
status = pyqtSignal(int, int, str)
|
||||||
summary = pyqtSignal(int, int, str)
|
summary = pyqtSignal(int, int, str)
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,52 +100,37 @@ class VerifyWorker(QRunnable):
|
||||||
num: int = 0
|
num: int = 0
|
||||||
total: int = 1 # set default to 1 to avoid DivisionByZero before it is initialized
|
total: int = 1 # set default to 1 to avoid DivisionByZero before it is initialized
|
||||||
|
|
||||||
def __init__(self, core, app_name):
|
def __init__(self, app_name):
|
||||||
super(VerifyWorker, self).__init__()
|
super(VerifyWorker, self).__init__()
|
||||||
self.core, self.app_name = core, app_name
|
self.app_name = app_name
|
||||||
self.signals = VerifySignals()
|
self.signals = VerifySignals()
|
||||||
self.setAutoDelete(True)
|
self.setAutoDelete(True)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.core.is_installed(self.app_name):
|
if not shared.core.is_installed(self.app_name):
|
||||||
logger.error(f'Game "{self.app_name}" is not installed')
|
logger.error(f'Game "{self.app_name}" is not installed')
|
||||||
return
|
return
|
||||||
igame = self.core.get_installed_game(self.app_name)
|
|
||||||
|
|
||||||
logger.info(f'Loading installed manifest for "{igame.title}"')
|
logger.info(f'Loading installed manifest for "{self.app_name}"')
|
||||||
manifest_data, _ = self.core.get_installed_manifest(self.app_name)
|
igame = shared.core.get_installed_game(self.app_name)
|
||||||
if not manifest_data:
|
manifest_data, _ = shared.core.get_installed_manifest(self.app_name)
|
||||||
update_manifest(self.app_name, self.core)
|
manifest = shared.core.load_manifest(manifest_data)
|
||||||
manifest_data, _ = self.core.get_installed_manifest(self.app_name)
|
|
||||||
if not manifest_data:
|
|
||||||
self.signals.summary.emit(-1, -1, self.app_name)
|
|
||||||
return
|
|
||||||
|
|
||||||
manifest = self.core.load_manifest(manifest_data)
|
files = sorted(manifest.file_manifest_list.elements,
|
||||||
|
key=lambda a: a.filename.lower())
|
||||||
files = sorted(
|
|
||||||
manifest.file_manifest_list.elements, key=lambda a: a.filename.lower()
|
|
||||||
)
|
|
||||||
|
|
||||||
# build list of hashes
|
# build list of hashes
|
||||||
file_list = [(f.filename, f.sha_hash.hex()) for f in files]
|
file_list = [(f.filename, f.sha_hash.hex()) for f in files]
|
||||||
self.total = len(file_list)
|
total = len(file_list)
|
||||||
self.num = 0
|
num = 0
|
||||||
failed = []
|
failed = []
|
||||||
missing = []
|
missing = []
|
||||||
|
|
||||||
_translate = QCoreApplication.translate
|
logger.info(f'Verifying "{igame.title}" version "{manifest.meta.build_version}"')
|
||||||
|
|
||||||
logger.info(
|
|
||||||
f'Verifying "{igame.title}" version "{manifest.meta.build_version}"'
|
|
||||||
)
|
|
||||||
repair_file = []
|
repair_file = []
|
||||||
try:
|
for result, path, result_hash, _ in validate_files(igame.install_path, file_list):
|
||||||
for result, path, result_hash in validate_files(
|
num += 1
|
||||||
igame.install_path, file_list
|
self.signals.status.emit(num, total, self.app_name)
|
||||||
):
|
|
||||||
self.signals.status.emit((self.num, self.total, self.app_name))
|
|
||||||
self.num += 1
|
|
||||||
|
|
||||||
if result == VerifyResult.HASH_MATCH:
|
if result == VerifyResult.HASH_MATCH:
|
||||||
repair_file.append(f"{result_hash}:{path}")
|
repair_file.append(f"{result_hash}:{path}")
|
||||||
|
@ -158,38 +143,21 @@ class VerifyWorker(QRunnable):
|
||||||
logger.error(f'File is missing: "{path}"')
|
logger.error(f'File is missing: "{path}"')
|
||||||
missing.append(path)
|
missing.append(path)
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(f'Other failure (see log), treating file as missing: "{path}"')
|
||||||
f'Other failure (see log), treating file as missing: "{path}"'
|
|
||||||
)
|
|
||||||
missing.append(path)
|
missing.append(path)
|
||||||
except OSError as e:
|
|
||||||
QMessageBox.warning(
|
|
||||||
None, "Error", _translate("VerifyWorker", "Path does not exist")
|
|
||||||
)
|
|
||||||
logger.error(str(e))
|
|
||||||
except ValueError as e:
|
|
||||||
QMessageBox.warning(
|
|
||||||
None, "Error", _translate("VerifyWorker", "No files to validate")
|
|
||||||
)
|
|
||||||
logger.error(str(e))
|
|
||||||
|
|
||||||
# always write repair file, even if all match
|
# always write repair file, even if all match
|
||||||
if repair_file:
|
if repair_file:
|
||||||
repair_filename = os.path.join(
|
repair_filename = os.path.join(shared.core.lgd.get_tmp_path(), f'{self.app_name}.repair')
|
||||||
self.core.lgd.get_tmp_path(), f"{self.app_name}.repair"
|
with open(repair_filename, 'w') as f:
|
||||||
)
|
f.write('\n'.join(repair_file))
|
||||||
with open(repair_filename, "w") as f:
|
|
||||||
f.write("\n".join(repair_file))
|
|
||||||
logger.debug(f'Written repair file to "{repair_filename}"')
|
logger.debug(f'Written repair file to "{repair_filename}"')
|
||||||
|
|
||||||
if not missing and not failed:
|
if not missing and not failed:
|
||||||
logger.info("Verification finished successfully.")
|
logger.info('Verification finished successfully.')
|
||||||
self.signals.summary.emit(0, 0, self.app_name)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.warning(
|
||||||
f"Verification finished, {len(failed)} file(s) corrupted, {len(missing)} file(s) are missing."
|
f'Verification failed, {len(failed)} file(s) corrupted, {len(missing)} file(s) are missing.')
|
||||||
)
|
|
||||||
self.signals.summary.emit(len(failed), len(missing), self.app_name)
|
self.signals.summary.emit(len(failed), len(missing), self.app_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ from legendary.models.game import Game, InstalledGame
|
||||||
@dataclass
|
@dataclass
|
||||||
class InstallOptionsModel:
|
class InstallOptionsModel:
|
||||||
app_name: str
|
app_name: str
|
||||||
base_path: str = os.path.expanduser("~/legendary")
|
base_path: str = ""
|
||||||
max_workers: int = os.cpu_count() * 2
|
max_workers: int = os.cpu_count() * 2
|
||||||
repair: bool = False
|
repair: bool = False
|
||||||
no_install: bool = False
|
no_install: bool = False
|
||||||
|
@ -24,6 +24,7 @@ class InstallOptionsModel:
|
||||||
update: bool = False
|
update: bool = False
|
||||||
silent: bool = False
|
silent: bool = False
|
||||||
platform: str = ""
|
platform: str = ""
|
||||||
|
overlay: bool = False
|
||||||
|
|
||||||
def set_no_install(self, enabled: bool) -> None:
|
def set_no_install(self, enabled: bool) -> None:
|
||||||
self.no_install = enabled
|
self.no_install = enabled
|
||||||
|
@ -134,7 +135,11 @@ class Signals(QObject):
|
||||||
install_game = pyqtSignal(InstallOptionsModel)
|
install_game = pyqtSignal(InstallOptionsModel)
|
||||||
installation_finished = pyqtSignal(bool, str)
|
installation_finished = pyqtSignal(bool, str)
|
||||||
|
|
||||||
|
overlay_installation_finished = pyqtSignal()
|
||||||
|
|
||||||
update_gamelist = pyqtSignal(list)
|
update_gamelist = pyqtSignal(list)
|
||||||
game_uninstalled = pyqtSignal(str)
|
game_uninstalled = pyqtSignal(str)
|
||||||
|
|
||||||
set_discord_rpc = pyqtSignal(str) # app_name of running game
|
set_discord_rpc = pyqtSignal(str) # app_name of running game
|
||||||
|
|
||||||
|
wine_prefix_updated = pyqtSignal()
|
||||||
|
|
Loading…
Reference in a new issue