2022-01-13 11:46:46 +13:00
|
|
|
import os
|
|
|
|
import platform
|
|
|
|
from logging import getLogger
|
2023-09-09 04:38:39 +12:00
|
|
|
from typing import Optional
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
from PyQt5.QtCore import QRunnable, QObject, pyqtSignal, QThreadPool, Qt, pyqtSlot, QSize
|
2024-01-20 01:54:09 +13:00
|
|
|
from PyQt5.QtGui import QShowEvent
|
2023-09-11 04:11:03 +12:00
|
|
|
from PyQt5.QtWidgets import (
|
|
|
|
QGroupBox,
|
|
|
|
QMessageBox,
|
|
|
|
QFrame,
|
|
|
|
QHBoxLayout,
|
|
|
|
QSizePolicy,
|
|
|
|
QLabel,
|
|
|
|
QPushButton,
|
|
|
|
QFormLayout,
|
|
|
|
QComboBox,
|
|
|
|
)
|
2022-11-04 09:34:50 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
from rare.lgndr.core import LegendaryCore
|
|
|
|
from rare.models.game import RareEosOverlay
|
|
|
|
from rare.shared import RareCore
|
2022-11-04 09:39:48 +13:00
|
|
|
from rare.ui.components.tabs.games.integrations.eos_widget import Ui_EosWidget
|
2024-01-20 01:54:09 +13:00
|
|
|
from rare.utils import config_helper as config
|
2024-02-22 00:21:44 +13:00
|
|
|
from rare.utils.misc import qta_icon
|
2023-09-09 04:38:39 +12:00
|
|
|
from rare.widgets.elide_label import ElideLabel
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-04 09:29:15 +12:00
|
|
|
logger = getLogger("EpicOverlay")
|
2022-01-13 11:46:46 +13:00
|
|
|
|
|
|
|
|
2022-01-14 06:58:07 +13:00
|
|
|
class CheckForUpdateWorker(QRunnable):
|
2022-07-11 08:00:35 +12:00
|
|
|
class CheckForUpdateSignals(QObject):
|
|
|
|
update_available = pyqtSignal(bool)
|
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
def __init__(self, core: LegendaryCore):
|
2022-01-14 06:58:07 +13:00
|
|
|
super(CheckForUpdateWorker, self).__init__()
|
2022-07-11 08:00:35 +12:00
|
|
|
self.signals = self.CheckForUpdateSignals()
|
2022-01-14 06:58:07 +13:00
|
|
|
self.setAutoDelete(True)
|
2023-09-09 04:38:39 +12:00
|
|
|
self.core = core
|
2022-01-14 06:58:07 +13:00
|
|
|
|
|
|
|
def run(self) -> None:
|
2022-02-26 06:43:27 +13:00
|
|
|
self.core.check_for_overlay_updates()
|
|
|
|
self.signals.update_available.emit(self.core.overlay_update_available)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
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)
|
|
|
|
|
2024-01-20 01:54:09 +13:00
|
|
|
self.prefix_label = ElideLabel(
|
|
|
|
prefix.replace(os.path.expanduser("~"), "~") if prefix is not None else overlay.app_title,
|
|
|
|
parent=self,
|
|
|
|
)
|
2023-09-11 04:11:03 +12:00
|
|
|
self.overlay_label = ElideLabel(parent=self)
|
|
|
|
self.overlay_label.setDisabled(True)
|
|
|
|
|
|
|
|
self.path_select = QComboBox(self)
|
|
|
|
self.path_select.setMaximumWidth(150)
|
|
|
|
self.path_select.setMinimumWidth(150)
|
2023-09-09 04:38:39 +12:00
|
|
|
|
|
|
|
self.button = QPushButton(parent=self)
|
|
|
|
self.button.setMinimumWidth(150)
|
|
|
|
|
|
|
|
layout = QHBoxLayout(self)
|
|
|
|
layout.setContentsMargins(-1, 0, 0, 0)
|
|
|
|
layout.addWidget(self.indicator)
|
2023-09-11 04:11:03 +12:00
|
|
|
layout.addWidget(self.prefix_label, stretch=2)
|
|
|
|
layout.addWidget(self.overlay_label, stretch=3)
|
|
|
|
layout.addWidget(self.path_select)
|
2023-09-09 04:38:39 +12:00
|
|
|
layout.addWidget(self.button)
|
|
|
|
|
|
|
|
self.overlay = overlay
|
|
|
|
self.prefix = prefix
|
|
|
|
|
2023-09-11 04:11:03 +12:00
|
|
|
self.path_select.currentIndexChanged.connect(self.path_changed)
|
|
|
|
self.button.clicked.connect(self.action)
|
2023-09-09 04:38:39 +12:00
|
|
|
self.overlay.signals.game.installed.connect(self.update_state)
|
|
|
|
self.overlay.signals.game.uninstalled.connect(self.update_state)
|
|
|
|
|
|
|
|
self.update_state()
|
|
|
|
|
2023-09-11 04:11:03 +12:00
|
|
|
@pyqtSlot(int)
|
|
|
|
def path_changed(self, index: int) -> None:
|
|
|
|
path = self.path_select.itemData(index, Qt.UserRole)
|
|
|
|
active_path = os.path.normpath(p) if (p := self.overlay.active_path(self.prefix)) else ""
|
|
|
|
if self.overlay.is_enabled(self.prefix) and (path == active_path):
|
|
|
|
self.button.setText(self.tr("Disable overlay"))
|
|
|
|
else:
|
|
|
|
self.button.setText(self.tr("Enable overlay"))
|
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
@pyqtSlot()
|
2023-09-11 04:11:03 +12:00
|
|
|
def update_state(self) -> None:
|
|
|
|
active_path = os.path.normpath(p) if (p := self.overlay.active_path(self.prefix)) else ""
|
|
|
|
|
2024-01-20 01:54:09 +13:00
|
|
|
self.overlay_label.setText(f"<i>{active_path}</i>")
|
2023-09-11 04:11:03 +12:00
|
|
|
self.path_select.clear()
|
|
|
|
|
|
|
|
if not self.overlay.is_installed and not self.overlay.available_paths(self.prefix):
|
2023-09-09 04:38:39 +12:00
|
|
|
self.setDisabled(True)
|
2024-02-22 00:21:44 +13:00
|
|
|
self.indicator.setPixmap(qta_icon("fa.circle-o", color="grey").pixmap(20, 20))
|
2023-09-11 04:11:03 +12:00
|
|
|
self.overlay_label.setText(self.overlay.active_path(self.prefix))
|
|
|
|
self.button.setText(self.tr("Unavailable"))
|
2023-09-09 04:38:39 +12:00
|
|
|
return
|
|
|
|
|
|
|
|
if self.overlay.is_enabled(self.prefix):
|
2024-02-22 00:21:44 +13:00
|
|
|
self.indicator.setPixmap(qta_icon("fa.check-circle-o", color="green").pixmap(QSize(20, 20)))
|
2023-09-09 04:38:39 +12:00
|
|
|
else:
|
2024-02-22 00:21:44 +13:00
|
|
|
self.indicator.setPixmap(qta_icon("fa.times-circle-o", color="red").pixmap(QSize(20, 20)))
|
2023-09-11 04:11:03 +12:00
|
|
|
|
|
|
|
install_path = os.path.normpath(p) if (p := self.overlay.install_path) else ""
|
|
|
|
|
|
|
|
self.path_select.addItem("Auto-detect", "")
|
|
|
|
self.path_select.setItemData(0, "Auto-detect", Qt.ToolTipRole)
|
|
|
|
for path in self.overlay.available_paths(self.prefix):
|
|
|
|
path = os.path.normpath(path)
|
|
|
|
self.path_select.addItem("Legendary-managed" if path == install_path else "EGL-managed", path)
|
|
|
|
self.path_select.setItemData(self.path_select.findData(path), path, Qt.ToolTipRole)
|
|
|
|
self.path_select.setCurrentIndex(self.path_select.findData(active_path))
|
2023-09-09 04:38:39 +12:00
|
|
|
|
2024-01-20 01:54:09 +13:00
|
|
|
self.setEnabled(self.overlay.state == RareEosOverlay.State.IDLE)
|
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
@pyqtSlot()
|
2023-09-11 04:11:03 +12:00
|
|
|
def action(self) -> None:
|
|
|
|
path = self.path_select.currentData(Qt.UserRole)
|
|
|
|
active_path = os.path.normpath(p) if (p := self.overlay.active_path(self.prefix)) else ""
|
|
|
|
install_path = os.path.normpath(p) if (p := self.overlay.install_path) else ""
|
|
|
|
if self.overlay.is_enabled(self.prefix) and (path == active_path):
|
|
|
|
if not self.overlay.disable(prefix=self.prefix):
|
|
|
|
QMessageBox.warning(
|
2024-01-20 01:54:09 +13:00
|
|
|
self,
|
|
|
|
"Warning",
|
2023-09-11 04:11:03 +12:00
|
|
|
self.tr("Failed to completely disable the active EOS Overlay.{}").format(
|
2024-01-20 01:54:09 +13:00
|
|
|
self.tr(
|
|
|
|
" Since the previous overlay was managed by EGL you can safely ignore this is."
|
|
|
|
)
|
|
|
|
if active_path != install_path
|
|
|
|
else ""
|
2023-09-11 04:11:03 +12:00
|
|
|
),
|
|
|
|
)
|
2023-09-09 04:38:39 +12:00
|
|
|
else:
|
2023-09-11 04:11:03 +12:00
|
|
|
self.overlay.disable(prefix=self.prefix)
|
|
|
|
if not self.overlay.enable(prefix=self.prefix, path=path):
|
|
|
|
QMessageBox.warning(
|
|
|
|
self,
|
|
|
|
"Warning",
|
|
|
|
self.tr("Failed to completely enable EOS overlay.{}").format(
|
2024-01-20 01:54:09 +13:00
|
|
|
self.tr(
|
|
|
|
" Since the previous overlay was managed by EGL you can safely ignore this is."
|
|
|
|
)
|
2023-09-11 04:11:03 +12:00
|
|
|
if active_path != install_path
|
|
|
|
else ""
|
|
|
|
),
|
|
|
|
)
|
2023-09-09 04:38:39 +12:00
|
|
|
self.update_state()
|
|
|
|
|
|
|
|
|
|
|
|
class EosGroup(QGroupBox):
|
2022-11-04 09:34:50 +13:00
|
|
|
def __init__(self, parent=None):
|
2023-09-09 04:38:39 +12:00
|
|
|
super(EosGroup, self).__init__(parent=parent)
|
2023-09-04 09:29:15 +12:00
|
|
|
self.ui = Ui_EosWidget()
|
|
|
|
self.ui.setupUi(self)
|
2023-01-26 04:08:43 +13:00
|
|
|
# lk: set object names for CSS properties
|
2023-09-04 09:29:15 +12:00
|
|
|
self.ui.install_button.setObjectName("InstallButton")
|
|
|
|
self.ui.uninstall_button.setObjectName("UninstallButton")
|
2023-01-26 04:08:43 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
self.ui.install_page_layout.setAlignment(Qt.AlignTop)
|
|
|
|
self.ui.info_page_layout.setAlignment(Qt.AlignTop)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2024-02-22 00:21:44 +13:00
|
|
|
self.ui.install_button.setIcon(qta_icon("ri.install-line"))
|
|
|
|
self.ui.uninstall_button.setIcon(qta_icon("ri.uninstall-line"))
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
self.installed_path_label = ElideLabel(parent=self)
|
|
|
|
self.installed_version_label = ElideLabel(parent=self)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
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)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
self.rcore = RareCore.instance()
|
|
|
|
self.core = self.rcore.core()
|
|
|
|
self.signals = self.rcore.signals()
|
|
|
|
self.overlay = self.rcore.get_overlay()
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2024-01-20 01:54:09 +13:00
|
|
|
self.overlay.signals.widget.update.connect(self.update_state)
|
2023-09-09 04:38:39 +12:00
|
|
|
self.overlay.signals.game.installed.connect(self.install_finished)
|
|
|
|
self.overlay.signals.game.uninstalled.connect(self.uninstall_finished)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
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)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
if self.overlay.is_installed: # installed
|
|
|
|
self.installed_version_label.setText(f"<b>{self.overlay.version}</b>")
|
2023-09-11 04:11:03 +12:00
|
|
|
self.installed_path_label.setText(os.path.normpath(self.overlay.install_path))
|
2023-09-09 04:38:39 +12:00
|
|
|
self.ui.overlay_stack.setCurrentWidget(self.ui.info_page)
|
2022-01-13 11:46:46 +13:00
|
|
|
else:
|
2023-09-09 04:38:39 +12:00
|
|
|
self.ui.overlay_stack.setCurrentWidget(self.ui.install_page)
|
|
|
|
self.ui.update_button.setEnabled(False)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2022-01-19 07:46:16 +13:00
|
|
|
self.threadpool = QThreadPool.globalInstance()
|
2024-01-20 01:54:09 +13:00
|
|
|
self.worker: Optional[CheckForUpdateWorker] = None
|
2022-01-19 07:46:16 +13:00
|
|
|
|
2024-01-20 01:54:09 +13:00
|
|
|
def showEvent(self, a0: QShowEvent) -> None:
|
|
|
|
if a0.spontaneous():
|
|
|
|
return super().showEvent(a0)
|
2023-09-09 04:38:39 +12:00
|
|
|
self.check_for_update()
|
|
|
|
self.update_prefixes()
|
2024-01-20 01:54:09 +13:00
|
|
|
self.update_state()
|
2023-09-09 04:38:39 +12:00
|
|
|
super().showEvent(a0)
|
2022-01-20 08:10:10 +13:00
|
|
|
|
2024-01-20 01:54:09 +13:00
|
|
|
@pyqtSlot()
|
|
|
|
def update_state(self):
|
|
|
|
self.ui.install_button.setEnabled(self.overlay.state == RareEosOverlay.State.IDLE)
|
|
|
|
self.ui.update_button.setEnabled(self.overlay.state == RareEosOverlay.State.IDLE and self.overlay.has_update)
|
|
|
|
self.ui.uninstall_button.setEnabled(self.overlay.state == RareEosOverlay.State.IDLE)
|
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
def update_prefixes(self):
|
|
|
|
for widget in self.findChildren(EosPrefixWidget, options=Qt.FindDirectChildrenOnly):
|
|
|
|
widget.deleteLater()
|
|
|
|
|
|
|
|
if platform.system() != "Windows":
|
2024-01-20 01:54:09 +13:00
|
|
|
prefixes = config.get_prefixes()
|
2024-02-13 05:30:23 +13:00
|
|
|
prefixes = {prefix for prefix, _ in prefixes if config.prefix_exists(prefix)}
|
2023-09-09 04:38:39 +12:00
|
|
|
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)
|
2022-01-20 08:10:10 +13:00
|
|
|
|
2024-01-20 01:54:09 +13:00
|
|
|
@pyqtSlot(bool)
|
|
|
|
def check_for_update_finished(self, update_available: bool):
|
|
|
|
self.worker = None
|
|
|
|
self.ui.update_button.setEnabled(update_available)
|
|
|
|
|
2022-01-13 11:46:46 +13:00
|
|
|
def check_for_update(self):
|
2024-01-20 01:54:09 +13:00
|
|
|
self.ui.update_button.setEnabled(False)
|
2023-09-09 04:38:39 +12:00
|
|
|
if not self.overlay.is_installed:
|
|
|
|
return
|
|
|
|
|
2024-01-20 01:54:09 +13:00
|
|
|
if self.worker is not None:
|
|
|
|
return
|
2022-01-14 06:58:07 +13:00
|
|
|
|
2024-01-20 01:54:09 +13:00
|
|
|
self.worker = CheckForUpdateWorker(self.core)
|
|
|
|
self.worker.signals.update_available.connect(self.check_for_update_finished)
|
|
|
|
QThreadPool.globalInstance().start(self.worker)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
@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"))
|
2022-01-20 08:10:10 +13:00
|
|
|
return
|
2023-09-09 04:38:39 +12:00
|
|
|
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)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
@pyqtSlot()
|
|
|
|
def uninstall_finished(self):
|
|
|
|
self.ui.overlay_stack.setCurrentWidget(self.ui.install_page)
|
2022-01-13 11:46:46 +13:00
|
|
|
|
2023-09-09 04:38:39 +12:00
|
|
|
@pyqtSlot()
|
|
|
|
def install_overlay(self):
|
|
|
|
self.overlay.install()
|
2022-01-13 11:46:46 +13:00
|
|
|
|
|
|
|
def uninstall_overlay(self):
|
2023-09-09 04:38:39 +12:00
|
|
|
if not self.overlay.is_installed:
|
2023-09-11 04:11:03 +12:00
|
|
|
logger.error("No Legendary-managed overlay installation found.")
|
2023-09-09 04:38:39 +12:00
|
|
|
self.ui.overlay_stack.setCurrentWidget(self.ui.install_page)
|
2022-01-13 11:46:46 +13:00
|
|
|
return
|
2023-09-09 04:38:39 +12:00
|
|
|
self.overlay.uninstall()
|