Merge pull request #412 from loathingKernel/develop
Add option in uninstall dialog to delete the game's folder despite containing files
This commit is contained in:
commit
c5529805c3
8 changed files with 57 additions and 48 deletions
|
@ -1,4 +1,4 @@
|
||||||
from PyQt5.QtCore import pyqtSignal
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QVBoxLayout,
|
QVBoxLayout,
|
||||||
QCheckBox,
|
QCheckBox,
|
||||||
|
@ -23,6 +23,10 @@ class UninstallDialog(ButtonDialog):
|
||||||
self.keep_files.setChecked(bool(options.keep_files))
|
self.keep_files.setChecked(bool(options.keep_files))
|
||||||
self.keep_files.setEnabled(not rgame.is_overlay)
|
self.keep_files.setEnabled(not rgame.is_overlay)
|
||||||
|
|
||||||
|
self.keep_folder = QCheckBox(self.tr("Keep game folder"))
|
||||||
|
self.keep_folder.setChecked(bool(options.keep_folder))
|
||||||
|
self.keep_folder.setEnabled(not rgame.is_overlay)
|
||||||
|
|
||||||
self.keep_config = QCheckBox(self.tr("Keep configuation"))
|
self.keep_config = QCheckBox(self.tr("Keep configuation"))
|
||||||
self.keep_config.setChecked(bool(options.keep_config))
|
self.keep_config.setChecked(bool(options.keep_config))
|
||||||
self.keep_config.setEnabled(not rgame.is_overlay)
|
self.keep_config.setEnabled(not rgame.is_overlay)
|
||||||
|
@ -33,6 +37,7 @@ class UninstallDialog(ButtonDialog):
|
||||||
|
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
layout.addWidget(self.keep_files)
|
layout.addWidget(self.keep_files)
|
||||||
|
layout.addWidget(self.keep_folder)
|
||||||
layout.addWidget(self.keep_config)
|
layout.addWidget(self.keep_config)
|
||||||
layout.addWidget(self.keep_overlay_keys)
|
layout.addWidget(self.keep_overlay_keys)
|
||||||
|
|
||||||
|
@ -42,21 +47,25 @@ class UninstallDialog(ButtonDialog):
|
||||||
self.accept_button.setIcon(qta_icon("ri.uninstall-line"))
|
self.accept_button.setIcon(qta_icon("ri.uninstall-line"))
|
||||||
self.accept_button.setObjectName("UninstallButton")
|
self.accept_button.setObjectName("UninstallButton")
|
||||||
|
|
||||||
if rgame.sdl_name is not None:
|
self.keep_files.stateChanged.connect(self.__on_keep_files_changed)
|
||||||
self.keep_config.setChecked(True)
|
|
||||||
|
|
||||||
self.options: UninstallOptionsModel = options
|
self.options: UninstallOptionsModel = options
|
||||||
|
|
||||||
|
@pyqtSlot(int)
|
||||||
|
def __on_keep_files_changed(self, state: int):
|
||||||
|
self.keep_folder.setCheckState(state if state else Qt.Checked)
|
||||||
|
self.keep_folder.setEnabled(not state)
|
||||||
|
|
||||||
def done_handler(self) -> None:
|
def done_handler(self) -> None:
|
||||||
self.result_ready.emit(self.options)
|
self.result_ready.emit(self.options)
|
||||||
|
|
||||||
def accept_handler(self):
|
def accept_handler(self):
|
||||||
self.options.values = (
|
self.options.set_accepted(
|
||||||
True,
|
keep_files=self.keep_files.isChecked(),
|
||||||
self.keep_files.isChecked(),
|
keep_folder=self.keep_folder.isChecked(),
|
||||||
self.keep_config.isChecked(),
|
keep_config=self.keep_config.isChecked(),
|
||||||
self.keep_overlay_keys.isChecked(),
|
keep_overlay_keys=self.keep_overlay_keys.isChecked(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def reject_handler(self):
|
def reject_handler(self):
|
||||||
self.options.values = (None, None, None, None)
|
self.options.set_rejected()
|
||||||
|
|
|
@ -352,7 +352,6 @@ class DownloadsTab(QWidget):
|
||||||
def __on_uninstall_dialog_closed(self, options: UninstallOptionsModel):
|
def __on_uninstall_dialog_closed(self, options: UninstallOptionsModel):
|
||||||
rgame = self.rcore.get_game(options.app_name)
|
rgame = self.rcore.get_game(options.app_name)
|
||||||
if options and options.accepted:
|
if options and options.accepted:
|
||||||
rgame.set_installed(False)
|
|
||||||
worker = UninstallWorker(self.core, rgame, options)
|
worker = UninstallWorker(self.core, rgame, options)
|
||||||
worker.signals.result.connect(self.__on_uninstall_worker_result)
|
worker.signals.result.connect(self.__on_uninstall_worker_result)
|
||||||
QThreadPool.globalInstance().start(worker)
|
QThreadPool.globalInstance().start(worker)
|
||||||
|
@ -361,6 +360,8 @@ class DownloadsTab(QWidget):
|
||||||
|
|
||||||
@pyqtSlot(RareGame, bool, str)
|
@pyqtSlot(RareGame, bool, str)
|
||||||
def __on_uninstall_worker_result(self, rgame: RareGame, success: bool, message: str):
|
def __on_uninstall_worker_result(self, rgame: RareGame, success: bool, message: str):
|
||||||
if not success:
|
if success:
|
||||||
|
rgame.set_installed(False)
|
||||||
|
else:
|
||||||
QMessageBox.warning(None, self.tr("Uninstall - {}").format(rgame.app_title), message, QMessageBox.Close)
|
QMessageBox.warning(None, self.tr("Uninstall - {}").format(rgame.app_title), message, QMessageBox.Close)
|
||||||
rgame.state = RareGame.State.IDLE
|
rgame.state = RareGame.State.IDLE
|
||||||
|
|
|
@ -305,9 +305,9 @@ class MangoHudSettings(OverlaySettings):
|
||||||
OverlayCheckBox("gpu_power", self.tr("GPU power consumption")),
|
OverlayCheckBox("gpu_power", self.tr("GPU power consumption")),
|
||||||
]
|
]
|
||||||
form = [
|
form = [
|
||||||
(OverlayNumberInput("fps_limit", 0), self.tr("FPS Limit")),
|
(OverlayNumberInput("fps_limit", 0), self.tr("FPS limit")),
|
||||||
(OverlaySelectInput("vsync", mangohud_vsync), self.tr("Vulkan VSync")),
|
(OverlaySelectInput("vsync", mangohud_vsync), self.tr("Vulkan vsync")),
|
||||||
(OverlaySelectInput("gl_vsync", mangohud_gl_vsync), self.tr("OpenGL VSync")),
|
(OverlaySelectInput("gl_vsync", mangohud_gl_vsync), self.tr("OpenGL vsync")),
|
||||||
(OverlayNumberInput("font_size", 24), self.tr("Font size")),
|
(OverlayNumberInput("font_size", 24), self.tr("Font size")),
|
||||||
(OverlaySelectInput("position", mangohud_position), self.tr("Position")),
|
(OverlaySelectInput("position", mangohud_position), self.tr("Position")),
|
||||||
]
|
]
|
||||||
|
|
|
@ -555,7 +555,7 @@ class RareGame(RareGameSlim):
|
||||||
if not self.is_idle:
|
if not self.is_idle:
|
||||||
return False
|
return False
|
||||||
self.signals.game.uninstall.emit(
|
self.signals.game.uninstall.emit(
|
||||||
UninstallOptionsModel(app_name=self.app_name)
|
UninstallOptionsModel(app_name=self.app_name, keep_config=self.sdl_name is not None)
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -85,41 +85,29 @@ class UninstallOptionsModel:
|
||||||
app_name: str
|
app_name: str
|
||||||
accepted: bool = None
|
accepted: bool = None
|
||||||
keep_files: bool = None
|
keep_files: bool = None
|
||||||
|
keep_folder: bool = True
|
||||||
keep_config: bool = None
|
keep_config: bool = None
|
||||||
keep_overlay_keys: bool = None
|
keep_overlay_keys: bool = None
|
||||||
|
|
||||||
def __bool__(self):
|
|
||||||
return (
|
|
||||||
bool(self.app_name)
|
|
||||||
and (self.accepted is not None)
|
|
||||||
and (self.keep_files is not None)
|
|
||||||
and (self.keep_config is not None)
|
|
||||||
and (self.keep_overlay_keys is not None)
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def values(self) -> Tuple[bool, bool, bool, bool]:
|
def __values(self) -> Tuple[bool, bool, bool, bool, bool]:
|
||||||
"""
|
return self.accepted, self.keep_config, self.keep_folder, self.keep_files, self.keep_overlay_keys
|
||||||
This model's options
|
|
||||||
|
|
||||||
:return:
|
@__values.setter
|
||||||
Tuple of `accepted` `keep_files` `keep_config` `keep_overlay_keys`
|
def __values(self, values: Tuple[bool, bool, bool, bool, bool]):
|
||||||
"""
|
self.accepted, self.keep_files, self.keep_folder, self.keep_config, self.keep_overlay_keys = values
|
||||||
return self.accepted, self.keep_config, self.keep_files, self.keep_overlay_keys
|
|
||||||
|
|
||||||
@values.setter
|
def __bool__(self):
|
||||||
def values(self, values: Tuple[bool, bool, bool, bool]):
|
return bool(self.app_name) and all(map(lambda x: x is not None, self.__values))
|
||||||
"""
|
|
||||||
Set this model's options
|
|
||||||
|
|
||||||
:param values:
|
def __iter__(self):
|
||||||
Tuple of `accepted` `keep_files` `keep_config` `keep_overlay_keys`
|
return iter(self.__values)
|
||||||
:return:
|
|
||||||
"""
|
def set_accepted(self, keep_config, keep_folder, keep_files, keep_overlay_keys):
|
||||||
self.accepted = values[0]
|
self.__values = True, keep_config, keep_folder, keep_files, keep_overlay_keys
|
||||||
self.keep_files = values[1]
|
|
||||||
self.keep_config = values[2]
|
def set_rejected(self):
|
||||||
self.keep_overlay_keys = values[3]
|
self.__values = False, None, None, None, None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -138,6 +138,7 @@ class ImageManager(QObject):
|
||||||
# lk: Find updates or initialize if images are missing.
|
# lk: Find updates or initialize if images are missing.
|
||||||
# lk: `updates` will be empty for games without images
|
# lk: `updates` will be empty for games without images
|
||||||
# lk: so everything below it is skipped
|
# lk: so everything below it is skipped
|
||||||
|
# TODO: Move this into the thread, maybe, concurrency could help here too
|
||||||
updates = []
|
updates = []
|
||||||
if not all(file.is_file() for file in self.__img_all(game.app_name)):
|
if not all(file.is_file() for file in self.__img_all(game.app_name)):
|
||||||
# lk: fast path for games without images, convert Rare's logo
|
# lk: fast path for games without images, convert Rare's logo
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import platform
|
import platform
|
||||||
|
import shutil
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ logger = getLogger("UninstallWorker")
|
||||||
|
|
||||||
# TODO: You can use RareGame directly here once this is called inside RareCore and skip metadata fetch
|
# TODO: You can use RareGame directly here once this is called inside RareCore and skip metadata fetch
|
||||||
def uninstall_game(
|
def uninstall_game(
|
||||||
core: LegendaryCore, rgame: RareGame, keep_files=False, keep_config=False, keep_overlay_keys=False
|
core: LegendaryCore, rgame: RareGame, keep_files=False, keep_folder=True, keep_config=False, keep_overlay_keys=False
|
||||||
) -> Tuple[bool, str]:
|
) -> Tuple[bool, str]:
|
||||||
if rgame.is_overlay:
|
if rgame.is_overlay:
|
||||||
logger.info('Deleting overlay installation...')
|
logger.info('Deleting overlay installation...')
|
||||||
|
@ -53,6 +54,8 @@ def uninstall_game(
|
||||||
if link_path.exists():
|
if link_path.exists():
|
||||||
link_path.unlink(missing_ok=True)
|
link_path.unlink(missing_ok=True)
|
||||||
|
|
||||||
|
install_path = rgame.igame.install_path
|
||||||
|
|
||||||
status = LgndrIndirectStatus()
|
status = LgndrIndirectStatus()
|
||||||
LegendaryCLI(core).uninstall_game(
|
LegendaryCLI(core).uninstall_game(
|
||||||
LgndrUninstallGameArgs(
|
LgndrUninstallGameArgs(
|
||||||
|
@ -63,6 +66,12 @@ def uninstall_game(
|
||||||
indirect_status=status,
|
indirect_status=status,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
keep_folder = keep_files if keep_files else keep_folder
|
||||||
|
if not keep_folder:
|
||||||
|
logger.info("Removing game install directory")
|
||||||
|
shutil.rmtree(install_path, ignore_errors=True)
|
||||||
|
|
||||||
if not keep_config:
|
if not keep_config:
|
||||||
logger.info("Removing sections in config file")
|
logger.info("Removing sections in config file")
|
||||||
config.remove_section(rgame.app_name)
|
config.remove_section(rgame.app_name)
|
||||||
|
@ -89,9 +98,10 @@ class UninstallWorker(Worker):
|
||||||
success, message = uninstall_game(
|
success, message = uninstall_game(
|
||||||
self.core,
|
self.core,
|
||||||
self.rgame,
|
self.rgame,
|
||||||
self.options.keep_files,
|
keep_files=self.options.keep_files,
|
||||||
self.options.keep_config,
|
keep_folder=self.options.keep_folder,
|
||||||
self.options.keep_overlay_keys,
|
keep_config=self.options.keep_config,
|
||||||
|
keep_overlay_keys=self.options.keep_overlay_keys,
|
||||||
)
|
)
|
||||||
self.rgame.state = RareGame.State.IDLE
|
self.rgame.state = RareGame.State.IDLE
|
||||||
self.signals.result.emit(self.rgame, success, message)
|
self.signals.result.emit(self.rgame, success, message)
|
||||||
|
|
|
@ -3,7 +3,7 @@ PyQt5
|
||||||
QtAwesome
|
QtAwesome
|
||||||
setuptools
|
setuptools
|
||||||
legendary-gl>=0.20.34; platform_system != "Windows" or platform_system != "Darwin"
|
legendary-gl>=0.20.34; platform_system != "Windows" or platform_system != "Darwin"
|
||||||
legendary-gl @ git+https://github.com/derrod/legendary@96e07ff ; platform_system == "Windows" or platform_system == "Darwin"
|
legendary-gl @ https://github.com/derrod/legendary/archive/96e07ff453910b8cae89af044e317001ce33ac8b.zip ; platform_system == "Windows" or platform_system == "Darwin"
|
||||||
orjson
|
orjson
|
||||||
vdf
|
vdf
|
||||||
pywin32; platform_system == "Windows"
|
pywin32; platform_system == "Windows"
|
||||||
|
|
Loading…
Reference in a new issue