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.main_window import MainWindow
|
||||
from rare.components.tray_icon import TrayIcon
|
||||
from rare.utils import legendary_utils
|
||||
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
|
||||
|
@ -158,6 +159,16 @@ class App(QApplication):
|
|||
self.mainwindow.show_window_centralized()
|
||||
|
||||
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.launch_dialog.close()
|
||||
self.tray_icon = TrayIcon(self)
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import os
|
||||
import platform
|
||||
from multiprocessing import Queue as MPQueue
|
||||
from typing import Tuple
|
||||
|
||||
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 legendary.core import LegendaryCore
|
||||
from legendary.models.downloading import ConditionCheckResult
|
||||
from legendary.models.game import Game
|
||||
from legendary.utils.selective_dl import games
|
||||
from rare import shared
|
||||
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.status_q = MPQueue()
|
||||
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.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.setWindowTitle(f'{self.windowTitle()} - {header} "{self.game.app_title}"')
|
||||
|
||||
default_path = os.path.expanduser("~/legendary")
|
||||
if self.core.lgd.config.has_option("Legendary", "install_dir"):
|
||||
default_path = self.core.lgd.config.get("Legendary", "install_dir")
|
||||
if not self.dl_item.options.base_path:
|
||||
self.dl_item.options.base_path = shared.core.lgd.config.get("Legendary", "install_dir",
|
||||
fallback=os.path.expanduser("~/legendary"))
|
||||
|
||||
self.install_dir_edit = PathEdit(
|
||||
path=default_path,
|
||||
path=self.dl_item.options.base_path,
|
||||
file_type=QFileDialog.DirectoryOnly,
|
||||
edit_func=self.option_changed,
|
||||
parent=self,
|
||||
|
@ -125,6 +134,16 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
|||
|
||||
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.verify_button.clicked.connect(self.verify_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.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.force = self.force_download_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):
|
||||
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.signals.result.connect(self.on_worker_result)
|
||||
info_worker.signals.failed.connect(self.on_worker_failed)
|
||||
|
@ -182,11 +202,16 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
|||
self.get_options()
|
||||
self.get_download_info()
|
||||
|
||||
def option_changed(self, path):
|
||||
def option_changed(self, path) -> Tuple[bool, str, str]:
|
||||
self.options_changed = True
|
||||
self.install_button.setEnabled(False)
|
||||
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):
|
||||
if option == "download_only":
|
||||
|
@ -250,6 +275,10 @@ class InstallDialog(QDialog, Ui_InstallDialog):
|
|||
self.result_ready.emit(self.dl_item)
|
||||
a0.accept()
|
||||
|
||||
def keyPressEvent(self, e: QKeyEvent) -> None:
|
||||
if e.key() == Qt.Key_Escape:
|
||||
self.cancel_clicked()
|
||||
|
||||
|
||||
class InstallInfoWorkerSignals(QObject):
|
||||
result = pyqtSignal(InstallDownloadModel)
|
||||
|
@ -258,15 +287,18 @@ class InstallInfoWorkerSignals(QObject):
|
|||
|
||||
|
||||
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__()
|
||||
self.signals = InstallInfoWorkerSignals()
|
||||
self.core = core
|
||||
self.dl_item = dl_item
|
||||
self.is_overlay_install = self.dl_item.options.overlay
|
||||
self.game = game
|
||||
|
||||
@pyqtSlot()
|
||||
def run(self):
|
||||
try:
|
||||
if not self.is_overlay_install:
|
||||
download = InstallDownloadModel(
|
||||
*self.core.prepare_download(
|
||||
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,
|
||||
)
|
||||
)
|
||||
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)
|
||||
else:
|
||||
self.signals.failed.emit(
|
||||
|
|
|
@ -46,19 +46,19 @@ class BrowserLogin(QWidget, Ui_BrowserLogin):
|
|||
return self.sid_edit.is_valid
|
||||
|
||||
@staticmethod
|
||||
def text_changed(text) -> Tuple[bool, str]:
|
||||
def text_changed(text) -> Tuple[bool, str, str]:
|
||||
if text:
|
||||
text = text.strip()
|
||||
if text.startswith("{") and text.endswith("}"):
|
||||
try:
|
||||
text = json.loads(text).get("sid")
|
||||
except json.JSONDecodeError:
|
||||
return False, text
|
||||
return False, text, IndicatorLineEdit.reasons.wrong_format
|
||||
elif '"' in text:
|
||||
text = text.strip('"')
|
||||
return len(text) == 32, text
|
||||
return len(text) == 32, text, IndicatorLineEdit.reasons.wrong_format
|
||||
else:
|
||||
return False, text
|
||||
return False, text, ""
|
||||
|
||||
def do_login(self):
|
||||
self.status_label.setText(self.tr("Logging in..."))
|
||||
|
|
|
@ -13,9 +13,10 @@ from PyQt5.QtWidgets import QMessageBox
|
|||
|
||||
from legendary.core import LegendaryCore
|
||||
from legendary.models.downloading import UIUpdate, WriterTask
|
||||
from rare import shared
|
||||
from rare.utils.models import InstallQueueItemModel
|
||||
|
||||
logger = getLogger("Download")
|
||||
logger = getLogger("DownloadThread")
|
||||
|
||||
|
||||
class DownloadThread(QThread):
|
||||
|
@ -31,6 +32,7 @@ class DownloadThread(QThread):
|
|||
self.igame = queue_item.download.igame
|
||||
self.repair = queue_item.download.repair
|
||||
self.repair_file = queue_item.download.repair_file
|
||||
self.queue_item = queue_item
|
||||
self._kill = False
|
||||
|
||||
def run(self):
|
||||
|
@ -140,9 +142,15 @@ class DownloadThread(QThread):
|
|||
return
|
||||
self.status.emit("dl_finished")
|
||||
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)
|
||||
|
||||
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:
|
||||
postinstall = self.core.install_game(self.igame)
|
||||
if postinstall:
|
||||
|
|
|
@ -133,6 +133,8 @@ class GamesTab(QStackedWidget, Ui_GamesTab):
|
|||
|
||||
def installation_started(self, app_name: str):
|
||||
game = self.core.get_game(app_name, False)
|
||||
if not game:
|
||||
return
|
||||
if game.is_dlc:
|
||||
return
|
||||
self.installing_widget.set_game(app_name)
|
||||
|
|
|
@ -88,17 +88,17 @@ class GameInfo(QWidget, Ui_GameInfo):
|
|||
)
|
||||
return
|
||||
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.summary.connect(self.finish_verify)
|
||||
self.verify_progress.setValue(0)
|
||||
self.verify_threads[self.game.app_name] = 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
|
||||
if progress[2] == self.game.app_name:
|
||||
self.verify_progress.setValue(progress[0] * 100 // progress[1])
|
||||
if app_name == self.game.app_name:
|
||||
self.verify_progress.setValue(num * 100 // total)
|
||||
|
||||
def finish_verify(self, failed, missing, app_name):
|
||||
if failed == missing == 0:
|
||||
|
|
|
@ -66,7 +66,7 @@ class GameSettings(QWidget, Ui_GameSettings):
|
|||
"",
|
||||
file_type=QFileDialog.DirectoryOnly,
|
||||
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,
|
||||
)
|
||||
self.cloud_gb.layout().addRow(
|
||||
|
@ -296,12 +296,12 @@ class GameSettings(QWidget, Ui_GameSettings):
|
|||
|
||||
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:
|
||||
text = os.path.expanduser("~/.proton")
|
||||
return True, text
|
||||
return True, 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):
|
||||
self.core.lgd.config.set(
|
||||
|
|
|
@ -88,9 +88,9 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
|
|||
self.egl_path_edit.setText(path)
|
||||
|
||||
@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:
|
||||
return True, path
|
||||
return True, path, ""
|
||||
if os.path.exists(os.path.join(path, "system.reg")) and os.path.exists(
|
||||
os.path.join(path, "dosdevices/c:")
|
||||
):
|
||||
|
@ -104,10 +104,10 @@ class EGLSyncGroup(QGroupBox, Ui_EGLSyncGroup):
|
|||
"ProgramData/Epic/EpicGamesLauncher/Data/Manifests"
|
||||
):
|
||||
# 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):
|
||||
return True, path
|
||||
return False, path
|
||||
return True, path, ""
|
||||
return False, path, PathEdit.reasons.dir_not_exist
|
||||
|
||||
@staticmethod
|
||||
def egl_path_edit_save_cb(path):
|
||||
|
|
|
@ -99,13 +99,15 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
|
|||
self.import_button.setEnabled(False)
|
||||
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(os.path.join(path, ".egstore")):
|
||||
return True, path
|
||||
return True, path, ""
|
||||
elif os.path.basename(path) in self.install_dir_list:
|
||||
return True, path
|
||||
return False, path
|
||||
return True, path, ""
|
||||
else:
|
||||
return False, path, PathEdit.reasons.dir_not_exist
|
||||
return False, path, ""
|
||||
|
||||
def path_changed(self, path):
|
||||
self.info_label.setText(str())
|
||||
|
@ -114,13 +116,13 @@ class ImportGroup(QGroupBox, Ui_ImportGroup):
|
|||
else:
|
||||
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:
|
||||
return False, text
|
||||
return False, text, ""
|
||||
if text in self.app_name_list:
|
||||
return True, text
|
||||
return True, text, ""
|
||||
else:
|
||||
return False, text
|
||||
return False, text, IndicatorLineEdit.reasons.game_not_installed
|
||||
|
||||
def app_name_changed(self, text):
|
||||
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
|
||||
|
||||
import rare.shared as shared
|
||||
from rare.components.tabs.settings.eos import EosWidget
|
||||
from rare.components.tabs.settings.ubisoft_activation import UbiActivationHelper
|
||||
from rare.ui.components.tabs.settings.legendary import Ui_LegendarySettings
|
||||
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.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)
|
||||
|
||||
|
@ -96,14 +100,18 @@ class LegendarySettings(QWidget, Ui_LegendarySettings):
|
|||
QThreadPool.globalInstance().start(worker)
|
||||
|
||||
@staticmethod
|
||||
def locale_edit_cb(text: str) -> Tuple[bool, str]:
|
||||
def locale_edit_cb(text: str) -> Tuple[bool, str, str]:
|
||||
if text:
|
||||
if re.match("^[a-zA-Z]{2,3}[-_][a-zA-Z]{2,3}$", text):
|
||||
language, country = text.replace("_", "-").split("-")
|
||||
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:
|
||||
return True, text
|
||||
return False, text, IndicatorLineEdit.reasons.wrong_format
|
||||
|
||||
else:
|
||||
return True, text, ""
|
||||
|
||||
def locale_save_cb(self, text: str):
|
||||
if text:
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtWidgets import QFileDialog, QWidget
|
||||
|
@ -21,6 +22,7 @@ class LinuxSettings(QWidget, Ui_LinuxSettings):
|
|||
self.wine_prefix = PathEdit(
|
||||
self.load_prefix(),
|
||||
file_type=QFileDialog.DirectoryOnly,
|
||||
edit_func=lambda path: (os.path.isdir(path), path, PathEdit.reasons.dir_not_exist),
|
||||
save_func=self.save_prefix,
|
||||
)
|
||||
self.prefix_layout.addWidget(self.wine_prefix)
|
||||
|
@ -50,6 +52,7 @@ class LinuxSettings(QWidget, Ui_LinuxSettings):
|
|||
def save_prefix(self, text: str):
|
||||
self.save_setting(text, f"{self.name}.env", "WINEPREFIX")
|
||||
self.save_setting(text, self.name, "wine_prefix")
|
||||
shared.signals.wine_prefix_updated.emit()
|
||||
|
||||
@staticmethod
|
||||
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):
|
||||
def setupUi(self, LegendarySettings):
|
||||
LegendarySettings.setObjectName("LegendarySettings")
|
||||
LegendarySettings.resize(564, 374)
|
||||
LegendarySettings.resize(905, 568)
|
||||
LegendarySettings.setWindowTitle("LegendarySettings")
|
||||
self.gridLayout = QtWidgets.QGridLayout(LegendarySettings)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
|
@ -26,11 +26,13 @@ class Ui_LegendarySettings(object):
|
|||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.locale_group.sizePolicy().hasHeightForWidth())
|
||||
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_layout = QtWidgets.QVBoxLayout(self.locale_group)
|
||||
self.locale_layout.setObjectName("locale_layout")
|
||||
self.right_layout.addWidget(self.locale_group)
|
||||
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_layout = QtWidgets.QVBoxLayout(self.cleanup_group)
|
||||
self.cleanup_layout.setObjectName("cleanup_layout")
|
||||
|
@ -45,19 +47,16 @@ class Ui_LegendarySettings(object):
|
|||
self.cleanup_layout.addWidget(self.refresh_game_meta_btn)
|
||||
self.right_layout.addWidget(self.cleanup_group)
|
||||
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.setObjectName("left_layout")
|
||||
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_layout = QtWidgets.QVBoxLayout(self.install_dir_group)
|
||||
self.install_dir_layout.setObjectName("install_dir_layout")
|
||||
self.left_layout.addWidget(self.install_dir_group)
|
||||
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_layout = QtWidgets.QFormLayout(self.download_group)
|
||||
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.left_layout.addWidget(self.download_group)
|
||||
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)
|
||||
self.gridLayout.addItem(spacerItem, 2, 0, 1, 2)
|
||||
self.gridLayout.addItem(spacerItem, 4, 0, 1, 2)
|
||||
|
||||
self.retranslateUi(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_button.setText(_translate("LegendarySettings", "Remove everything"))
|
||||
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.download_group.setTitle(_translate("LegendarySettings", "Download Settings"))
|
||||
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_line.setPlaceholderText(_translate("LegendarySettings", "Default"))
|
||||
self.disable_https_label.setText(_translate("LegendarySettings", "Disable HTTPS"))
|
||||
self.ubisoft_gb.setTitle(_translate("LegendarySettings", "Link Ubisoft Games"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>564</width>
|
||||
<height>374</height>
|
||||
<width>905</width>
|
||||
<height>568</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -27,6 +27,9 @@
|
|||
<property name="title">
|
||||
<string>Locale</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="locale_layout"/>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -35,6 +38,9 @@
|
|||
<property name="title">
|
||||
<string>Cleanup</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="cleanup_layout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="clean_keep_manifests_button">
|
||||
|
@ -62,14 +68,6 @@
|
|||
</item>
|
||||
</layout>
|
||||
</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">
|
||||
<layout class="QVBoxLayout" name="left_layout">
|
||||
<item>
|
||||
|
@ -77,6 +75,9 @@
|
|||
<property name="title">
|
||||
<string>Default Installation Directory</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="install_dir_layout"/>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -85,6 +86,9 @@
|
|||
<property name="title">
|
||||
<string>Download Settings</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="download_layout">
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
|
@ -219,6 +223,24 @@
|
|||
</layout>
|
||||
</item>
|
||||
<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">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
|
|
|
@ -143,16 +143,25 @@ class FlowLayout(QLayout):
|
|||
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):
|
||||
textChanged = pyqtSignal(str)
|
||||
is_valid = False
|
||||
reasons = IndicatorReasons()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
text: str = "",
|
||||
ph_text: str = "",
|
||||
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,
|
||||
horiz_policy: QSizePolicy = QSizePolicy.Expanding,
|
||||
parent=None,
|
||||
|
@ -219,20 +228,25 @@ class IndicatorLineEdit(QWidget):
|
|||
self.hint_label.setFrameRect(self.line_edit.rect())
|
||||
self.hint_label.setText(text)
|
||||
|
||||
def __indicator(self, res):
|
||||
def __indicator(self, res, reason=None):
|
||||
color = "green" if res else "red"
|
||||
self.indicator_label.setPixmap(
|
||||
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):
|
||||
if self.edit_func is not None:
|
||||
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():
|
||||
self.line_edit.setText(text)
|
||||
self.line_edit.blockSignals(False)
|
||||
self.__indicator(self.is_valid)
|
||||
self.__indicator(self.is_valid, reason)
|
||||
if self.is_valid:
|
||||
self.__save(text)
|
||||
self.textChanged.emit(text)
|
||||
|
@ -286,7 +300,7 @@ class PathEdit(IndicatorLineEdit):
|
|||
type_filter: str = "",
|
||||
name_filter: 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,
|
||||
horiz_policy: QSizePolicy = QSizePolicy.Expanding,
|
||||
parent=None,
|
||||
|
|
|
@ -4,11 +4,11 @@ import shutil
|
|||
from logging import getLogger
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, QCoreApplication, QObject, QRunnable
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
from legendary.core import LegendaryCore
|
||||
from legendary.models.game import VerifyResult
|
||||
from legendary.utils.lfs import validate_files
|
||||
from rare import shared
|
||||
|
||||
logger = getLogger("Legendary Utils")
|
||||
|
||||
|
@ -92,7 +92,7 @@ def update_manifest(app_name: str, core: LegendaryCore):
|
|||
|
||||
|
||||
class VerifySignals(QObject):
|
||||
status = pyqtSignal(tuple)
|
||||
status = pyqtSignal(int, int, str)
|
||||
summary = pyqtSignal(int, int, str)
|
||||
|
||||
|
||||
|
@ -100,52 +100,37 @@ class VerifyWorker(QRunnable):
|
|||
num: int = 0
|
||||
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__()
|
||||
self.core, self.app_name = core, app_name
|
||||
self.app_name = app_name
|
||||
self.signals = VerifySignals()
|
||||
self.setAutoDelete(True)
|
||||
|
||||
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')
|
||||
return
|
||||
igame = self.core.get_installed_game(self.app_name)
|
||||
|
||||
logger.info(f'Loading installed manifest for "{igame.title}"')
|
||||
manifest_data, _ = self.core.get_installed_manifest(self.app_name)
|
||||
if not manifest_data:
|
||||
update_manifest(self.app_name, self.core)
|
||||
manifest_data, _ = self.core.get_installed_manifest(self.app_name)
|
||||
if not manifest_data:
|
||||
self.signals.summary.emit(-1, -1, self.app_name)
|
||||
return
|
||||
logger.info(f'Loading installed manifest for "{self.app_name}"')
|
||||
igame = shared.core.get_installed_game(self.app_name)
|
||||
manifest_data, _ = shared.core.get_installed_manifest(self.app_name)
|
||||
manifest = shared.core.load_manifest(manifest_data)
|
||||
|
||||
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
|
||||
file_list = [(f.filename, f.sha_hash.hex()) for f in files]
|
||||
self.total = len(file_list)
|
||||
self.num = 0
|
||||
total = len(file_list)
|
||||
num = 0
|
||||
failed = []
|
||||
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 = []
|
||||
try:
|
||||
for result, path, result_hash in validate_files(
|
||||
igame.install_path, file_list
|
||||
):
|
||||
self.signals.status.emit((self.num, self.total, self.app_name))
|
||||
self.num += 1
|
||||
for result, path, result_hash, _ in validate_files(igame.install_path, file_list):
|
||||
num += 1
|
||||
self.signals.status.emit(num, total, self.app_name)
|
||||
|
||||
if result == VerifyResult.HASH_MATCH:
|
||||
repair_file.append(f"{result_hash}:{path}")
|
||||
|
@ -158,38 +143,21 @@ class VerifyWorker(QRunnable):
|
|||
logger.error(f'File is missing: "{path}"')
|
||||
missing.append(path)
|
||||
else:
|
||||
logger.error(
|
||||
f'Other failure (see log), treating file as missing: "{path}"'
|
||||
)
|
||||
logger.error(f'Other failure (see log), treating file as missing: "{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
|
||||
if repair_file:
|
||||
repair_filename = os.path.join(
|
||||
self.core.lgd.get_tmp_path(), f"{self.app_name}.repair"
|
||||
)
|
||||
with open(repair_filename, "w") as f:
|
||||
f.write("\n".join(repair_file))
|
||||
repair_filename = os.path.join(shared.core.lgd.get_tmp_path(), f'{self.app_name}.repair')
|
||||
with open(repair_filename, 'w') as f:
|
||||
f.write('\n'.join(repair_file))
|
||||
logger.debug(f'Written repair file to "{repair_filename}"')
|
||||
|
||||
if not missing and not failed:
|
||||
logger.info("Verification finished successfully.")
|
||||
self.signals.summary.emit(0, 0, self.app_name)
|
||||
|
||||
logger.info('Verification finished successfully.')
|
||||
else:
|
||||
logger.error(
|
||||
f"Verification finished, {len(failed)} file(s) corrupted, {len(missing)} file(s) are missing."
|
||||
)
|
||||
logger.warning(
|
||||
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)
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ from legendary.models.game import Game, InstalledGame
|
|||
@dataclass
|
||||
class InstallOptionsModel:
|
||||
app_name: str
|
||||
base_path: str = os.path.expanduser("~/legendary")
|
||||
base_path: str = ""
|
||||
max_workers: int = os.cpu_count() * 2
|
||||
repair: bool = False
|
||||
no_install: bool = False
|
||||
|
@ -24,6 +24,7 @@ class InstallOptionsModel:
|
|||
update: bool = False
|
||||
silent: bool = False
|
||||
platform: str = ""
|
||||
overlay: bool = False
|
||||
|
||||
def set_no_install(self, enabled: bool) -> None:
|
||||
self.no_install = enabled
|
||||
|
@ -134,7 +135,11 @@ class Signals(QObject):
|
|||
install_game = pyqtSignal(InstallOptionsModel)
|
||||
installation_finished = pyqtSignal(bool, str)
|
||||
|
||||
overlay_installation_finished = pyqtSignal()
|
||||
|
||||
update_gamelist = pyqtSignal(list)
|
||||
game_uninstalled = pyqtSignal(str)
|
||||
|
||||
set_discord_rpc = pyqtSignal(str) # app_name of running game
|
||||
|
||||
wine_prefix_updated = pyqtSignal()
|
||||
|
|
Loading…
Reference in a new issue