From 0fb1526d67f714b59fbb30458cd8d5dcd6586cd3 Mon Sep 17 00:00:00 2001 From: loathingKernel <142770+loathingKernel@users.noreply.github.com> Date: Tue, 2 Jan 2024 23:11:47 +0200 Subject: [PATCH] MoveDialog: Refactor MovePopup into a dialog using ActionDialog as base --- .../move_game.py => dialogs/move_dialog.py} | 79 ++++++++++++------- .../tabs/games/game_info/game_info.py | 39 ++++----- rare/models/install.py | 17 +++- .../tabs/games/game_info/game_info.py | 5 +- .../tabs/games/game_info/game_info.ui | 11 +-- 5 files changed, 82 insertions(+), 69 deletions(-) rename rare/components/{tabs/games/game_info/move_game.py => dialogs/move_dialog.py} (76%) diff --git a/rare/components/tabs/games/game_info/move_game.py b/rare/components/dialogs/move_dialog.py similarity index 76% rename from rare/components/tabs/games/game_info/move_game.py rename to rare/components/dialogs/move_dialog.py index 37ebebac..cab68049 100644 --- a/rare/components/tabs/games/game_info/move_game.py +++ b/rare/components/dialogs/move_dialog.py @@ -4,12 +4,14 @@ from enum import auto from logging import getLogger from typing import Tuple, Optional -from PyQt5.QtCore import pyqtSignal, Qt, pyqtSlot -from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFileDialog +from PyQt5.QtCore import pyqtSignal, pyqtSlot +from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QLabel, QFileDialog, QLayout +from rare.models.install import MoveGameModel from rare.models.game import RareGame from rare.shared import RareCore -from rare.utils.misc import path_size, format_size +from rare.utils.misc import path_size, format_size, icon +from rare.widgets.dialogs import ActionDialog, dialog_title_game from rare.widgets.elide_label import ElideLabel from rare.widgets.indicator_edit import PathEdit, IndicatorReasons, IndicatorReasonsCommon @@ -25,12 +27,16 @@ class MovePathEditReasons(IndicatorReasons): NO_SPACE = auto() -class MoveGamePopUp(QWidget): - move_clicked = pyqtSignal(str) - browse_done = pyqtSignal() +class MoveDialog(ActionDialog): + result_ready = pyqtSignal(RareGame, MoveGameModel) + + def __init__(self, rgame: RareGame, parent=None): + super(MoveDialog, self).__init__(parent=parent) + header = self.tr("Move") + self.setWindowTitle(dialog_title_game(header, rgame.app_title)) + + title_label = QLabel(f"

{dialog_title_game(header, rgame.app_title)}

", self) - def __init__(self, parent=None): - super(MoveGamePopUp, self).__init__(parent=parent) self.rcore = RareCore.instance() self.core = RareCore.instance().core() self.rgame: Optional[RareGame] = None @@ -44,19 +50,9 @@ class MoveGamePopUp(QWidget): MovePathEditReasons.NESTED_DIR: self.tr("Game install directories cannot be nested."), MovePathEditReasons.NO_SPACE: self.tr("Not enough space available on drive."), }) - self.path_edit.path_select.clicked.connect(self.browse_done) - - self.button = QPushButton(self.tr("Move")) - self.button.setFixedSize(self.path_edit.path_select.sizeHint()) - self.button.clicked.connect(lambda p: self.move_clicked.emit(self.path_edit.text())) self.warn_label = ElideLabel("", parent=self) - middle_layout = QHBoxLayout() - middle_layout.setAlignment(Qt.AlignRight) - middle_layout.addWidget(self.warn_label, stretch=1) - middle_layout.addWidget(self.button) - font = self.font() font.setBold(True) self.req_space_label = QLabel(self.tr("Required:"), self) @@ -72,11 +68,38 @@ class MoveGamePopUp(QWidget): bottom_layout.addWidget(self.avail_space_label) bottom_layout.addWidget(self.avail_space, stretch=1) - layout: QVBoxLayout = QVBoxLayout(self) + layout = QVBoxLayout() + layout.setSizeConstraint(QLayout.SetFixedSize) + layout.addWidget(title_label) layout.addWidget(self.path_edit) - layout.addLayout(middle_layout) + layout.addWidget(self.warn_label) layout.addLayout(bottom_layout) + self.setCentralLayout(layout) + + self.accept_button.setText(self.tr("Move")) + self.accept_button.setIcon(icon("mdi.folder-move-outline")) + + self.action_button.setHidden(True) + + self.update_game(rgame) + + self.options: MoveGameModel = MoveGameModel(rgame.app_name) + + def action_handler(self): + pass + + def done_handler(self): + self.result_ready.emit(self.rgame, self.options) + + def accept_handler(self): + self.options.accepted = True + self.options.target_path = self.path_edit.text() + + def reject_handler(self): + self.options.accepted = False + self.options.target_path = "" + def refresh_indicator(self): # needed so the edit_func gets run again text = self.path_edit.text() @@ -84,13 +107,13 @@ class MoveGamePopUp(QWidget): self.path_edit.setText(text) def path_edit_callback(self, path: str) -> Tuple[bool, str, int]: - self.button.setEnabled(True) + self.accept_button.setEnabled(True) self.warn_label.setHidden(False) self.req_space.setText("...") self.avail_space.setText("...") def helper_func(reason: int) -> Tuple[bool, str, int]: - self.button.setEnabled(False) + self.accept_button.setEnabled(False) return False, path, reason if not self.rgame.install_path or not path: @@ -141,7 +164,7 @@ class MoveGamePopUp(QWidget): return helper_func(MovePathEditReasons.NO_SPACE) # Fallback - self.button.setEnabled(True) + self.accept_button.setEnabled(True) return True, path, IndicatorReasonsCommon.VALID @pyqtSlot() @@ -151,20 +174,18 @@ class MoveGamePopUp(QWidget): self.setDisabled(True) return # FIXME: Make edit_func lighter instead of blocking signals - self.path_edit.line_edit.blockSignals(True) + # self.path_edit.line_edit.blockSignals(True) + self.setActive(True) self.path_edit.setText(self.rgame.install_path) # FIXME: Make edit_func lighter instead of blocking signals - self.path_edit.line_edit.blockSignals(False) + # self.path_edit.line_edit.blockSignals(False) + self.setActive(False) self.warn_label.setText( self.tr("Moving here will overwrite {}").format(os.path.basename(self.rgame.install_path)) ) self.refresh_indicator() def update_game(self, rgame: RareGame): - if self.rgame is not None: - self.rgame.signals.widget.update.disconnect(self.__update_widget) - self.rgame = None - rgame.signals.widget.update.connect(self.__update_widget) self.rgame = rgame self.__update_widget() diff --git a/rare/components/tabs/games/game_info/game_info.py b/rare/components/tabs/games/game_info/game_info.py index aed40fea..16030470 100644 --- a/rare/components/tabs/games/game_info/game_info.py +++ b/rare/components/tabs/games/game_info/game_info.py @@ -10,13 +10,11 @@ from PyQt5.QtCore import ( pyqtSignal, ) from PyQt5.QtWidgets import ( - QMenu, QWidget, QMessageBox, - QWidgetAction, ) -from rare.models.install import SelectiveDownloadsModel +from rare.models.install import SelectiveDownloadsModel, MoveGameModel from rare.components.dialogs.selective_dialog import SelectiveDialog from rare.models.game import RareGame from rare.shared import RareCore @@ -25,7 +23,7 @@ from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo from rare.utils.misc import format_size, icon from rare.widgets.image_widget import ImageWidget, ImageSize from rare.widgets.side_tab import SideTabContents -from .move_game import MoveGamePopUp, is_game_dir +from rare.components.dialogs.move_dialog import MoveDialog, is_game_dir logger = getLogger("GameInfo") @@ -68,18 +66,9 @@ class GameInfo(QWidget, SideTabContents): self.ui.modify_button.clicked.connect(self.__on_modify) self.ui.verify_button.clicked.connect(self.__on_verify) self.ui.repair_button.clicked.connect(self.__on_repair) + self.ui.move_button.clicked.connect(self.__on_move) self.ui.uninstall_button.clicked.connect(self.__on_uninstall) - self.move_game_pop_up = MoveGamePopUp(self) - move_action = QWidgetAction(self) - move_action.setDefaultWidget(self.move_game_pop_up) - self.ui.move_button.setMenu(QMenu(self.ui.move_button)) - self.ui.move_button.menu().addAction(move_action) - - self.move_game_pop_up.browse_done.connect(self.ui.move_button.showMenu) - self.move_game_pop_up.move_clicked.connect(self.ui.move_button.menu().close) - self.move_game_pop_up.move_clicked.connect(self.__on_move) - self.steam_grade_ratings = { "platinum": self.tr("Platinum"), "gold": self.tr("Gold"), @@ -217,17 +206,24 @@ class GameInfo(QWidget, SideTabContents): if ans == QMessageBox.Yes: self.repair_game(rgame) - @pyqtSlot(str) - def __on_move(self, dst_path: str): + @pyqtSlot() + def __on_move(self): """ This method is to be called from the button only """ - new_install_path = os.path.join(dst_path, os.path.basename(self.rgame.install_path)) + move_dialog = MoveDialog(self.rgame, parent=self) + move_dialog.result_ready.connect(self.move_game) + move_dialog.open() + def move_game(self, rgame: RareGame, model: MoveGameModel): + if not model.accepted: + return + + new_install_path = os.path.join(model.target_path, os.path.basename(self.rgame.install_path)) dir_exists = False if os.path.isdir(new_install_path): dir_exists = is_game_dir(self.rgame.install_path, new_install_path) if not dir_exists: - for item in os.listdir(dst_path): + for item in os.listdir(model.target_path): if os.path.basename(self.rgame.install_path) in os.path.basename(item): ans = QMessageBox.question( self, @@ -248,11 +244,8 @@ class GameInfo(QWidget, SideTabContents): else: return - self.move_game(self.rgame, new_install_path, dir_exists) - - def move_game(self, rgame: RareGame, dst_path, dst_exists): worker = MoveWorker( - self.core, rgame=rgame, dst_path=dst_path, dst_exists=dst_exists + self.core, rgame=rgame, dst_path=model.target_path, dst_exists=dir_exists ) worker.signals.progress.connect(self.__on_move_progress) worker.signals.result.connect(self.__on_move_result) @@ -395,7 +388,5 @@ class GameInfo(QWidget, SideTabContents): else: self.ui.install_button.setText(self.tr("Install")) - self.move_game_pop_up.update_game(rgame) - self.rgame = rgame self.__update_widget() diff --git a/rare/models/install.py b/rare/models/install.py index 05ef39ef..69123d0b 100644 --- a/rare/models/install.py +++ b/rare/models/install.py @@ -101,7 +101,7 @@ class UninstallOptionsModel: This model's options :return: - Tuple of `accepted` `keep_files` `keep_config` + Tuple of `accepted` `keep_files` `keep_config` `keep_overlay_keys` """ return self.accepted, self.keep_config, self.keep_files @@ -111,7 +111,7 @@ class UninstallOptionsModel: Set this model's options :param values: - Tuple of `accepted` `keep_files` `keep_config` + Tuple of `accepted` `keep_files` `keep_config` `keep_overlay_keys` :return: """ self.accepted = values[0] @@ -132,3 +132,16 @@ class SelectiveDownloadsModel: and (self.install_tag is not None) ) + +@dataclass +class MoveGameModel: + app_name: str + accepted: bool = None + target_path: Optional[str] = None + + def __bool__(self): + return ( + bool(self.app_name) + and (self.accepted is not None) + and (self.target_path is not None) + ) diff --git a/rare/ui/components/tabs/games/game_info/game_info.py b/rare/ui/components/tabs/games/game_info/game_info.py index bce4a9d5..3457e942 100644 --- a/rare/ui/components/tabs/games/game_info/game_info.py +++ b/rare/ui/components/tabs/games/game_info/game_info.py @@ -255,15 +255,12 @@ class Ui_GameInfo(object): self.move_button_layout.setContentsMargins(0, 0, 0, 0) self.move_button_layout.setSpacing(0) self.move_button_layout.setObjectName("move_button_layout") - self.move_button = QtWidgets.QToolButton(self.move_button_page) + self.move_button = QtWidgets.QPushButton(self.move_button_page) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.move_button.sizePolicy().hasHeightForWidth()) self.move_button.setSizePolicy(sizePolicy) - self.move_button.setPopupMode(QtWidgets.QToolButton.InstantPopup) - self.move_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly) - self.move_button.setArrowType(QtCore.Qt.DownArrow) self.move_button.setObjectName("move_button") self.move_button_layout.addWidget(self.move_button) self.move_stack.addWidget(self.move_button_page) diff --git a/rare/ui/components/tabs/games/game_info/game_info.ui b/rare/ui/components/tabs/games/game_info/game_info.ui index 64796002..89115667 100644 --- a/rare/ui/components/tabs/games/game_info/game_info.ui +++ b/rare/ui/components/tabs/games/game_info/game_info.ui @@ -488,7 +488,7 @@ 0 - + 0 @@ -498,15 +498,6 @@ Move - - QToolButton::InstantPopup - - - Qt::ToolButtonTextOnly - - - Qt::DownArrow -