1
0
Fork 0
mirror of synced 2024-07-03 05:31:23 +12:00
Rare/rare/components/tabs/games/integrations/eos_group.py
loathingKernel a246f4ee16 EosGroup: Remake the UI and integrate with Rare's facilities
* Uninstalling the Overlay now goes through the same procedure as
uninstalling any other game.

* The available prefixes are now listed instead of hiding them inside
a combo box.

* Each listing works indepedently to enable/disable the Overlay for the prefix
2024-01-19 00:57:16 +02:00

250 lines
9.8 KiB
Python

import os
import platform
from logging import getLogger
from typing import Optional
from PyQt5.QtCore import QRunnable, QObject, pyqtSignal, QThreadPool, Qt, pyqtSlot, QSize
from PyQt5.QtWidgets import QGroupBox, QMessageBox, QFrame, QHBoxLayout, QSizePolicy, QLabel, QPushButton, QFormLayout
from legendary.lfs import eos
from rare.lgndr.core import LegendaryCore
from rare.models.game import RareEosOverlay
from rare.shared import RareCore
from rare.ui.components.tabs.games.integrations.eos_widget import Ui_EosWidget
from rare.utils import config_helper
from rare.utils.misc import icon
from rare.widgets.elide_label import ElideLabel
logger = getLogger("EpicOverlay")
class CheckForUpdateWorker(QRunnable):
class CheckForUpdateSignals(QObject):
update_available = pyqtSignal(bool)
def __init__(self, core: LegendaryCore):
super(CheckForUpdateWorker, self).__init__()
self.signals = self.CheckForUpdateSignals()
self.setAutoDelete(True)
self.core = core
def run(self) -> None:
self.core.check_for_overlay_updates()
self.signals.update_available.emit(self.core.overlay_update_available)
class EosPrefixWidget(QFrame):
def __init__(self, overlay: RareEosOverlay, prefix: Optional[str], parent=None):
super(EosPrefixWidget, self).__init__(parent=parent)
self.setFrameShape(QFrame.StyledPanel)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.indicator = QLabel(parent=self)
self.indicator.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Preferred)
self.label = ElideLabel(
prefix if prefix is not None else "Epic Online Services Overlay",
parent=self
)
self.button = QPushButton(parent=self)
self.button.setMinimumWidth(150)
self.button.clicked.connect(self.action)
layout = QHBoxLayout(self)
layout.setContentsMargins(-1, 0, 0, 0)
layout.addWidget(self.indicator)
layout.addWidget(self.label, stretch=1)
layout.addWidget(self.button)
self.overlay = overlay
self.prefix = prefix
self.overlay.signals.game.installed.connect(self.update_state)
self.overlay.signals.game.uninstalled.connect(self.update_state)
self.update_state()
@pyqtSlot()
def update_state(self):
if not self.overlay.is_installed:
self.setDisabled(True)
self.button.setText(self.tr("Unavailable"))
self.indicator.setPixmap(icon("fa.circle-o", color="grey").pixmap(20, 20))
return
self.setDisabled(False)
if self.overlay.is_enabled(self.prefix):
self.button.setText(self.tr("Disable overlay"))
self.indicator.setPixmap(
icon("fa.check-circle-o", color="green").pixmap(QSize(20, 20))
)
else:
self.button.setText(self.tr("Enable overlay"))
self.indicator.setPixmap(
icon("fa.times-circle-o", color="red").pixmap(QSize(20, 20))
)
@pyqtSlot()
def action(self):
if self.overlay.is_enabled(self.prefix):
self.overlay.disable(prefix=self.prefix)
else:
self.overlay.enable(prefix=self.prefix)
self.update_state()
class EosGroup(QGroupBox):
def __init__(self, parent=None):
super(EosGroup, self).__init__(parent=parent)
self.ui = Ui_EosWidget()
self.ui.setupUi(self)
# lk: set object names for CSS properties
self.ui.install_button.setObjectName("InstallButton")
self.ui.uninstall_button.setObjectName("UninstallButton")
self.ui.install_page_layout.setAlignment(Qt.AlignTop)
self.ui.info_page_layout.setAlignment(Qt.AlignTop)
self.ui.install_button.setIcon(icon("ri.install-line"))
self.ui.uninstall_button.setIcon(icon("ri.uninstall-line"))
self.installed_path_label = ElideLabel(parent=self)
self.installed_version_label = ElideLabel(parent=self)
self.ui.info_label_layout.setWidget(0, QFormLayout.FieldRole, self.installed_version_label)
self.ui.info_label_layout.setWidget(1, QFormLayout.FieldRole, self.installed_path_label)
self.rcore = RareCore.instance()
self.core = self.rcore.core()
self.signals = self.rcore.signals()
self.overlay = self.rcore.get_overlay()
self.overlay.signals.game.installed.connect(self.install_finished)
self.overlay.signals.game.uninstalled.connect(self.uninstall_finished)
self.ui.install_button.clicked.connect(self.install_overlay)
self.ui.update_button.clicked.connect(self.install_overlay)
self.ui.uninstall_button.clicked.connect(self.uninstall_overlay)
if self.overlay.is_installed: # installed
self.installed_version_label.setText(f"<b>{self.overlay.version}</b>")
self.installed_path_label.setText(self.overlay.install_path)
self.ui.overlay_stack.setCurrentWidget(self.ui.info_page)
else:
self.ui.overlay_stack.setCurrentWidget(self.ui.install_page)
self.ui.update_button.setEnabled(False)
self.threadpool = QThreadPool.globalInstance()
def showEvent(self, a0) -> None:
self.check_for_update()
self.update_prefixes()
super().showEvent(a0)
def update_prefixes(self):
for widget in self.findChildren(EosPrefixWidget, options=Qt.FindDirectChildrenOnly):
widget.deleteLater()
if platform.system() != "Windows":
prefixes = config_helper.get_wine_prefixes()
if platform.system() == "Darwin":
# TODO: add crossover support
pass
for prefix in prefixes:
widget = EosPrefixWidget(self.overlay, prefix)
self.ui.eos_layout.addWidget(widget)
logger.debug("Updated prefixes")
else:
widget = EosPrefixWidget(self.overlay, None)
self.ui.eos_layout.addWidget(widget)
def check_for_update(self):
if not self.overlay.is_installed:
return
def worker_finished(update_available):
self.ui.update_button.setEnabled(update_available)
worker = CheckForUpdateWorker(self.core)
worker.signals.update_available.connect(worker_finished)
QThreadPool.globalInstance().start(worker)
@pyqtSlot()
def install_finished(self):
if not self.overlay.is_installed:
logger.error("Something went wrong while installing overlay")
QMessageBox.warning(self, "Error", self.tr("Something went wrong while installing Overlay"))
return
self.ui.overlay_stack.setCurrentWidget(self.ui.info_page)
self.installed_version_label.setText(f"<b>{self.overlay.version}</b>")
self.installed_path_label.setText(self.overlay.install_path)
self.ui.update_button.setEnabled(False)
@pyqtSlot()
def uninstall_finished(self):
self.ui.overlay_stack.setCurrentWidget(self.ui.install_page)
def change_enable(self):
enabled = self.ui.enabled_cb.isChecked()
if not enabled:
try:
eos.remove_registry_entries(self.current_prefix)
except PermissionError:
logger.error("Can't disable eos overlay")
QMessageBox.warning(self, "Error", self.tr(
"Failed to disable Overlay. Probably it is installed by Epic Games Launcher"))
return
logger.info("Disabled Epic Overlay")
self.ui.enabled_info_label.setText(self.tr("Disabled"))
else:
if not self.overlay.is_installed:
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.ui.select_pfx_combo.removeItem(self.ui.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}"')
try:
eos.remove_registry_entries(self.current_prefix)
except PermissionError:
logger.error("Can't disable eos overlay")
QMessageBox.warning(self, "Error", self.tr(
"Failed to disable Overlay. Probably it is installed by Epic Games Launcher"))
return
try:
eos.add_registry_entries(path, self.current_prefix)
except PermissionError:
logger.error("Failed to disable eos overlay")
QMessageBox.warning(self, "Error", self.tr(
"Failed to enable EOS overlay. Maybe it is already installed by Epic Games Launcher"))
return
self.ui.enabled_info_label.setText(self.tr("Enabled"))
logger.info(f'Enabled overlay at: {path}')
@pyqtSlot()
def install_overlay(self):
self.overlay.install()
def uninstall_overlay(self):
if not self.overlay.is_installed:
logger.error('No Rare-managed overlay installation found.')
self.ui.overlay_stack.setCurrentWidget(self.ui.install_page)
return
self.overlay.uninstall()