Skip to content

Commit

Permalink
Wrappers: add checkbox to enable/disable wrappers per game
Browse files Browse the repository at this point in the history
  • Loading branch information
loathingKernel committed Jan 14, 2025
1 parent 4b95609 commit d29655a
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 40 deletions.
32 changes: 26 additions & 6 deletions rare/components/tabs/settings/widgets/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
QPushButton,
QLineEdit,
QVBoxLayout,
QComboBox,
QComboBox, QCheckBox,
)

from rare.models.wrapper import Wrapper
Expand Down Expand Up @@ -104,6 +104,8 @@ def __on_index_changed(self, index: int):


class WrapperWidget(QFrame):
# object: current
disable_wrapper = Signal(object)
# object: current, object: new
update_wrapper = Signal(object, object)
# object: current
Expand All @@ -115,9 +117,11 @@ def __init__(self, wrapper: Wrapper, parent=None):
self.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Fixed)
self.setToolTip(wrapper.as_str)

text_lbl = QLabel(wrapper.name, parent=self)
text_lbl.setFont(QFont("monospace"))
text_lbl.setEnabled(wrapper.is_editable)
self.text_lbl = QCheckBox(wrapper.name, parent=self)
self.text_lbl.setChecked(wrapper.is_enabled)
self.text_lbl.setFont(QFont("monospace"))
self.text_lbl.setEnabled(wrapper.is_editable)
self.text_lbl.checkStateChanged.connect(self.__on_state_changed)

image_lbl = QLabel(parent=self)
image_lbl.setPixmap(qta_icon("mdi.drag-vertical").pixmap(QSize(20, 20)))
Expand All @@ -142,7 +146,7 @@ def __init__(self, wrapper: Wrapper, parent=None):
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(image_lbl)
layout.addWidget(text_lbl)
layout.addWidget(self.text_lbl)
layout.addWidget(manage_button)
self.setLayout(layout)

Expand All @@ -155,6 +159,12 @@ def __init__(self, wrapper: Wrapper, parent=None):
def data(self) -> Wrapper:
return self.wrapper

@Slot(Qt.CheckState)
def __on_state_changed(self, state: Qt.CheckState) -> None:
new_wrapper = Wrapper(command=self.wrapper.command, enabled=self.text_lbl.isChecked())
self.update_wrapper.emit(self.wrapper, new_wrapper)
self.deleteLater()

@Slot()
def __on_delete(self) -> None:
self.delete_wrapper.emit(self.wrapper)
Expand Down Expand Up @@ -293,6 +303,7 @@ def __add_wrapper(self, wrapper: Wrapper, position: int = -1):
self.wrapper_container.addWidget(widget)
else:
self.wrapper_container.insertWidget(position, widget)
# widget.disable_wrapper.connect(self.__disable_wrapper)
widget.update_wrapper.connect(self.__update_wrapper)
widget.delete_wrapper.connect(self.__delete_wrapper)

Expand All @@ -319,7 +330,7 @@ def add_user_wrapper(self, wrapper: Wrapper, position: int = -1):
)
return

if wrapper.checksum in self.wrappers.get_game_md5sum_list(self.app_name):
if wrapper.checksum in self.wrappers.get_game_csum_list(self.app_name):
QMessageBox.warning(
self,
self.tr("Warning"),
Expand All @@ -340,6 +351,15 @@ def add_user_wrapper(self, wrapper: Wrapper, position: int = -1):

self.add_wrapper(wrapper, position)

@Slot(object)
def __disable_wrapper(self, wrapper: Wrapper):
wrappers = self.wrappers.get_game_wrapper_list(self.app_name)
index = wrappers.index(wrapper)
wrappers.remove(wrapper)
wrappers.insert(index, wrapper)
self.wrappers.set_game_wrapper_list(self.app_name, wrappers)
self.__add_wrapper(wrapper, index)

@Slot(object)
def __delete_wrapper(self, wrapper: Wrapper):
wrappers = self.wrappers.get_game_wrapper_list(self.app_name)
Expand Down
13 changes: 12 additions & 1 deletion rare/models/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ class WrapperType(IntEnum):


class Wrapper:
def __init__(self, command: Union[str, List[str]], name: str = None, wtype: WrapperType = None):
def __init__(
self, command: Union[str, List[str]], name: str = None, wtype: WrapperType = None, enabled: bool = True
):
self.__command: List[str] = shlex.split(command) if isinstance(command, str) else command
self.__name: str = name if name is not None else os.path.basename(self.__command[0])
self.__wtype: WrapperType = wtype if wtype is not None else WrapperType.USER_DEFINED
self.__enabled: bool = enabled or self.__wtype == WrapperType.COMPAT_TOOL

@property
def is_compat_tool(self) -> bool:
Expand All @@ -26,6 +29,14 @@ def is_compat_tool(self) -> bool:
def is_editable(self) -> bool:
return self.__wtype in {WrapperType.USER_DEFINED, WrapperType.LEGENDARY_IMPORT}

@property
def is_enabled(self) -> bool:
return self.__enabled or self.is_compat_tool

@is_enabled.setter
def is_enabled(self, state: bool) -> None:
self.__enabled = state if not self.is_compat_tool else True

@property
def checksum(self) -> str:
return md5(self.as_str.encode("utf-8")).hexdigest()
Expand Down
97 changes: 64 additions & 33 deletions rare/shared/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
from logging import getLogger
import shlex
from typing import List, Dict, Iterable
from typing import List, Dict, Iterable, Union, Tuple, Set
from rare.utils import config_helper as config

from PySide6.QtCore import QSettings
Expand All @@ -14,6 +14,31 @@
logger = getLogger("Wrappers")


class WrapperEntry:
def __init__(self, checksum: str, enabled: bool = True):
self.__checksum: str = checksum
self.__enabled: bool = enabled

@property
def checksum(self) -> str:
return self.__checksum

@property
def enabled(self) -> bool:
return self.__enabled

@classmethod
def from_dict(cls, data: Dict):
return cls(checksum=data.get("checksum"), enabled=data.get("enabled", True))

@property
def __dict__(self):
return dict(checksum=self.__checksum, enabled=self.__enabled)

# def __eq__(self, other) -> bool:
# return self.checksum == other.checksum


class Wrappers:
def __init__(self):
self.__file = os.path.join(config_dir(), "wrappers.json")
Expand All @@ -30,9 +55,15 @@ def __init__(self):
for wrap_id, wrapper in self.__wrappers_dict.get("wrappers", {}).items():
self.__wrappers.update({wrap_id: Wrapper.from_dict(wrapper)})

self.__applists: Dict[str, List[str]] = {}
self.__applists: Dict[str, List[WrapperEntry]] = {}
for app_name, wrapper_list in self.__wrappers_dict.get("applists", {}).items():
self.__applists.update({app_name: wrapper_list})
if all(isinstance(x, str) for x in wrapper_list):
wlist = [WrapperEntry(y) for y in wrapper_list]
elif all(isinstance(x, dict) for x in wrapper_list):
wlist = [WrapperEntry.from_dict(y) for y in wrapper_list]
else:
wlist = []
self.__applists.update({app_name: wlist})

def import_wrappers(self, core: LegendaryCore, settings: QSettings, app_names: List):
for app_name in app_names:
Expand Down Expand Up @@ -69,34 +100,31 @@ def user_wrappers(self) -> Iterable[Wrapper]:
# yield wrap

def get_game_wrapper_string(self, app_name: str) -> str:
commands = [wrapper.as_str for wrapper in self.get_game_wrapper_list(app_name)]
commands = [wrapper.as_str for wrapper in self.get_game_wrapper_list(app_name) if wrapper.is_enabled]
return " ".join(commands)

def get_game_wrapper_list(self, app_name: str) -> List[Wrapper]:
_wrappers = []
for wrap_id in self.__applists.get(app_name, []):
if wrap := self.__wrappers.get(wrap_id, None):
_wrappers.append(wrap)
return _wrappers
wrappers = []
for entry in self.__applists.get(app_name, []):
if wrap := self.__wrappers.get(entry.checksum, None):
wrap.is_enabled = entry.enabled
wrappers.append(wrap)
return wrappers

def get_game_md5sum_list(self, app_name: str) -> List[str]:
return self.__applists.get(app_name, [])
def get_game_csum_list(self, app_name: str) -> Set[str]:
return {entry.checksum for entry in self.__applists.get(app_name, [])}

def set_game_wrapper_list(self, app_name: str, wrappers: List[Wrapper]) -> None:
_wrappers = sorted(wrappers, key=lambda w: w.is_compat_tool)
for w in _wrappers:
if (md5sum := w.checksum) in self.__wrappers.keys():
if w != self.__wrappers[md5sum]:
logger.error(
"Non-unique md5sum for different wrappers %s, %s",
w.name,
self.__wrappers[md5sum].name,
)
logger.error("Equal csum for unequal wrappers %s, %s", w.name, self.__wrappers[md5sum].name)
if w.is_compat_tool:
self.__wrappers.update({md5sum: w})
else:
self.__wrappers.update({md5sum: w})
self.__applists[app_name] = [w.checksum for w in _wrappers]
self.__applists[app_name] = [WrapperEntry(w.checksum, w.is_enabled) for w in _wrappers]
self.__save_config(app_name)
self.__save_wrappers()

Expand All @@ -105,8 +133,8 @@ def __save_config(self, app_name: str):
config.save_option(app_name, "wrapper", command_string)

def __save_wrappers(self):
existing = {wrap_id for wrap_id in self.__wrappers.keys()}
in_use = {wrap_id for wrappers in self.__applists.values() for wrap_id in wrappers}
existing = {csum for csum in self.__wrappers.keys()}
in_use = {entry.checksum for wrappers in self.__applists.values() for entry in wrappers}

for redudant in existing.difference(in_use):
del self.__wrappers[redudant]
Expand All @@ -128,15 +156,16 @@ def __save_wrappers(self):
config_dir = os.getcwd
global config
config = Namespace()
config.set_option = lambda x, y, z: print(x, y, z)
config.remove_option = lambda x, y: print(x, y)
config.save_config = lambda: print()
config.set_option = lambda x, y, z: print("set_option:", x, y, z)
config.remove_option = lambda x, y: print("remove_option:", x, y)
config.save_config = lambda: print("save_config:")
config.save_option = lambda x, y, z: print("save_option:", x, y, z)

wr = Wrappers()

w1 = Wrapper(command=["/usr/bin/w1"], wtype=WrapperType.NONE)
w2 = Wrapper(command=["/usr/bin/w2"], wtype=WrapperType.COMPAT_TOOL)
w3 = Wrapper(command=["/usr/bin/w3"], wtype=WrapperType.USER_DEFINED)
w3 = Wrapper(command=["/usr/bin/w3"], wtype=WrapperType.USER_DEFINED, enabled=False)
w4 = Wrapper(command=["/usr/bin/w4"], wtype=WrapperType.USER_DEFINED)
wr.set_game_wrapper_list("testgame", [w1, w2, w3, w4])

Expand All @@ -147,19 +176,21 @@ def __save_wrappers(self):
wr.set_game_wrapper_list("testgame", [w1, w2, w3, w6])

w7 = Wrapper(command=["/usr/bin/w2"], wtype=WrapperType.COMPAT_TOOL)
wrs = wr.get_game_wrapper_list("testgame")
wrs.remove(w7)
wr.set_game_wrapper_list("testgame", wrs)
app_wrappers = wr.get_game_wrapper_list("testgame")
pprint([w.as_str for w in app_wrappers])
# item = next(item for item in app_wrappers if item.checksum == w3.checksum)
app_wrappers.remove(w3)
wr.set_game_wrapper_list("testgame", app_wrappers)

game_wrappers = wr.get_game_wrapper_list("testgame")
pprint(game_wrappers)
pprint([w.as_str for w in game_wrappers])
game_wrappers = wr.get_game_wrapper_list("testgame2")
pprint(game_wrappers)
pprint([w.as_str for w in game_wrappers])

for i, tool in enumerate(steam.find_tools()):
wt = Wrapper(command=tool.command(), name=tool.name, wtype=WrapperType.COMPAT_TOOL)
wr.set_game_wrapper_list(f"compat_game_{i}", [wt])
print(wt.as_str)
# for i, tool in enumerate(steam.find_tools()):
# wt = Wrapper(command=tool.command(), name=tool.name, wtype=WrapperType.COMPAT_TOOL)
# wr.set_game_wrapper_list(f"compat_game_{i}", [wt])
# print(wt.as_str)

for wrp in wr.user_wrappers:
pprint(wrp)
pprint(wrp.as_str)

0 comments on commit d29655a

Please sign in to comment.