Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option in uninstall dialog to delete the game's folder despite containing files #412

Merged
merged 4 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions rare/components/dialogs/uninstall_dialog.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (
QVBoxLayout,
QCheckBox,
Expand All @@ -23,6 +23,10 @@ def __init__(self, rgame: RareGame, options: UninstallOptionsModel, parent=None)
self.keep_files.setChecked(bool(options.keep_files))
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.setChecked(bool(options.keep_config))
self.keep_config.setEnabled(not rgame.is_overlay)
Expand All @@ -33,6 +37,7 @@ def __init__(self, rgame: RareGame, options: UninstallOptionsModel, parent=None)

layout = QVBoxLayout()
layout.addWidget(self.keep_files)
layout.addWidget(self.keep_folder)
layout.addWidget(self.keep_config)
layout.addWidget(self.keep_overlay_keys)

Expand All @@ -42,21 +47,25 @@ def __init__(self, rgame: RareGame, options: UninstallOptionsModel, parent=None)
self.accept_button.setIcon(qta_icon("ri.uninstall-line"))
self.accept_button.setObjectName("UninstallButton")

if rgame.sdl_name is not None:
self.keep_config.setChecked(True)
self.keep_files.stateChanged.connect(self.__on_keep_files_changed)

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:
self.result_ready.emit(self.options)

def accept_handler(self):
self.options.values = (
True,
self.keep_files.isChecked(),
self.keep_config.isChecked(),
self.keep_overlay_keys.isChecked(),
self.options.set_accepted(
keep_files=self.keep_files.isChecked(),
keep_folder=self.keep_folder.isChecked(),
keep_config=self.keep_config.isChecked(),
keep_overlay_keys=self.keep_overlay_keys.isChecked(),
)

def reject_handler(self):
self.options.values = (None, None, None, None)
self.options.set_rejected()
5 changes: 3 additions & 2 deletions rare/components/tabs/downloads/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,6 @@ def __get_uninstall_options(self, options: UninstallOptionsModel):
def __on_uninstall_dialog_closed(self, options: UninstallOptionsModel):
rgame = self.rcore.get_game(options.app_name)
if options and options.accepted:
rgame.set_installed(False)
worker = UninstallWorker(self.core, rgame, options)
worker.signals.result.connect(self.__on_uninstall_worker_result)
QThreadPool.globalInstance().start(worker)
Expand All @@ -361,6 +360,8 @@ def __on_uninstall_dialog_closed(self, options: UninstallOptionsModel):

@pyqtSlot(RareGame, bool, 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)
rgame.state = RareGame.State.IDLE
6 changes: 3 additions & 3 deletions rare/components/tabs/settings/widgets/overlay.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,9 @@ def __init__(self, parent=None):
OverlayCheckBox("gpu_power", self.tr("GPU power consumption")),
]
form = [
(OverlayNumberInput("fps_limit", 0), self.tr("FPS Limit")),
(OverlaySelectInput("vsync", mangohud_vsync), self.tr("Vulkan VSync")),
(OverlaySelectInput("gl_vsync", mangohud_gl_vsync), self.tr("OpenGL VSync")),
(OverlayNumberInput("fps_limit", 0), self.tr("FPS limit")),
(OverlaySelectInput("vsync", mangohud_vsync), self.tr("Vulkan vsync")),
(OverlaySelectInput("gl_vsync", mangohud_gl_vsync), self.tr("OpenGL vsync")),
(OverlayNumberInput("font_size", 24), self.tr("Font size")),
(OverlaySelectInput("position", mangohud_position), self.tr("Position")),
]
Expand Down
2 changes: 1 addition & 1 deletion rare/models/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ def uninstall(self) -> bool:
if not self.is_idle:
return False
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

Expand Down
48 changes: 18 additions & 30 deletions rare/models/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,41 +85,29 @@ class UninstallOptionsModel:
app_name: str
accepted: bool = None
keep_files: bool = None
keep_folder: bool = True
keep_config: bool = None
keep_overlay_keys: bool = None

@property
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

@__values.setter
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

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)
)
return bool(self.app_name) and all(map(lambda x: x is not None, self.__values))

@property
def values(self) -> Tuple[bool, bool, bool, bool]:
"""
This model's options

:return:
Tuple of `accepted` `keep_files` `keep_config` `keep_overlay_keys`
"""
return self.accepted, self.keep_config, self.keep_files, self.keep_overlay_keys

@values.setter
def values(self, values: Tuple[bool, bool, bool, bool]):
"""
Set this model's options

:param values:
Tuple of `accepted` `keep_files` `keep_config` `keep_overlay_keys`
:return:
"""
self.accepted = values[0]
self.keep_files = values[1]
self.keep_config = values[2]
self.keep_overlay_keys = values[3]
def __iter__(self):
return iter(self.__values)

def set_accepted(self, keep_config, keep_folder, keep_files, keep_overlay_keys):
self.__values = True, keep_config, keep_folder, keep_files, keep_overlay_keys

def set_rejected(self):
self.__values = False, None, None, None, None


@dataclass
Expand Down
1 change: 1 addition & 0 deletions rare/shared/image_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def best_match(key_images: List, image_types: Tuple) -> Dict:
# lk: Find updates or initialize if images are missing.
# lk: `updates` will be empty for games without images
# lk: so everything below it is skipped
# TODO: Move this into the thread, maybe, concurrency could help here too
updates = []
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
Expand Down
18 changes: 14 additions & 4 deletions rare/shared/workers/uninstall.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import platform
import shutil
from logging import getLogger
from typing import Tuple

Expand All @@ -20,7 +21,7 @@

# TODO: You can use RareGame directly here once this is called inside RareCore and skip metadata fetch
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]:
if rgame.is_overlay:
logger.info('Deleting overlay installation...')
Expand Down Expand Up @@ -53,6 +54,8 @@ def uninstall_game(
if link_path.exists():
link_path.unlink(missing_ok=True)

install_path = rgame.igame.install_path

status = LgndrIndirectStatus()
LegendaryCLI(core).uninstall_game(
LgndrUninstallGameArgs(
Expand All @@ -63,6 +66,12 @@ def uninstall_game(
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:
logger.info("Removing sections in config file")
config.remove_section(rgame.app_name)
Expand All @@ -89,9 +98,10 @@ def run_real(self) -> None:
success, message = uninstall_game(
self.core,
self.rgame,
self.options.keep_files,
self.options.keep_config,
self.options.keep_overlay_keys,
keep_files=self.options.keep_files,
keep_folder=self.options.keep_folder,
keep_config=self.options.keep_config,
keep_overlay_keys=self.options.keep_overlay_keys,
)
self.rgame.state = RareGame.State.IDLE
self.signals.result.emit(self.rgame, success, message)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ PyQt5
QtAwesome
setuptools
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
vdf
pywin32; platform_system == "Windows"
Expand Down
Loading