1
0
Fork 0
mirror of synced 2024-06-30 04:00:48 +12:00

Merge pull request #154 from Dummerle/game_meta

Save last played time and add quick launch for tray icon
This commit is contained in:
Dummerle 2022-01-06 18:27:37 +01:00 committed by GitHub
commit 6f99c22a72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 126 additions and 24 deletions

View file

@ -1,3 +1,4 @@
import datetime
import os import os
import platform import platform
import shutil import shutil
@ -14,6 +15,7 @@ from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.components.extra.console import ConsoleWindow from rare.components.extra.console import ConsoleWindow
from rare.components.tabs.games import CloudSaveUtils from rare.components.tabs.games import CloudSaveUtils
from rare.utils import legendary_utils from rare.utils import legendary_utils
from rare.utils.meta import RareGameMeta
logger = getLogger("GameUtils") logger = getLogger("GameUtils")
@ -50,6 +52,7 @@ class GameUtils(QObject):
self.console = ConsoleWindow() self.console = ConsoleWindow()
self.cloud_save_utils = CloudSaveUtils() self.cloud_save_utils = CloudSaveUtils()
self.cloud_save_utils.sync_finished.connect(self.sync_finished) self.cloud_save_utils.sync_finished.connect(self.sync_finished)
self.game_meta = RareGameMeta()
def uninstall_game(self, app_name) -> bool: def uninstall_game(self, app_name) -> bool:
# returns if uninstalled # returns if uninstalled
@ -57,13 +60,13 @@ class GameUtils(QObject):
igame = self.core.get_installed_game(app_name) igame = self.core.get_installed_game(app_name)
if not os.path.exists(igame.install_path): if not os.path.exists(igame.install_path):
if QMessageBox.Yes == QMessageBox.question( if QMessageBox.Yes == QMessageBox.question(
None, None,
"Uninstall", "Uninstall",
self.tr( self.tr(
"Game files of {} do not exist. Remove it from installed games?" "Game files of {} do not exist. Remove it from installed games?"
).format(igame.title), ).format(igame.title),
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes | QMessageBox.No,
QMessageBox.Yes, QMessageBox.Yes,
): ):
self.core.lgd.remove_installed_game(app_name) self.core.lgd.remove_installed_game(app_name)
return True return True
@ -78,7 +81,7 @@ class GameUtils(QObject):
return True return True
def prepare_launch( def prepare_launch(
self, app_name, offline: bool = False, skip_update_check: bool = False self, app_name, offline: bool = False, skip_update_check: bool = False
): ):
game = self.core.get_game(app_name) game = self.core.get_game(app_name)
dont_sync_after_finish = False dont_sync_after_finish = False
@ -102,19 +105,23 @@ class GameUtils(QObject):
) )
def launch_game( def launch_game(
self, self,
app_name: str, app_name: str,
offline: bool = False, offline: bool = False,
skip_update_check: bool = False, skip_update_check: bool = False,
wine_bin: str = None, wine_bin: str = None,
wine_pfx: str = None, wine_pfx: str = None,
ask_always_sync: bool = False, ask_always_sync: bool = False,
): ):
if shared.args.offline: if shared.args.offline:
offline = True offline = True
game = self.core.get_game(app_name) game = self.core.get_game(app_name)
igame = self.core.get_installed_game(app_name) igame = self.core.get_installed_game(app_name)
meta_data = self.game_meta.get_game(app_name)
meta_data.last_played = datetime.datetime.now()
self.game_meta.set_game(app_name, meta_data)
if not game: if not game:
logger.error(f"{app_name} not found") logger.error(f"{app_name} not found")
self.finished.emit(app_name, self.tr("Game not found in available games")) self.finished.emit(app_name, self.tr("Game not found in available games"))
@ -122,13 +129,13 @@ class GameUtils(QObject):
if QSettings().value("confirm_start", False, bool): if QSettings().value("confirm_start", False, bool):
if ( if (
not QMessageBox.question( not QMessageBox.question(
None, None,
"Launch", "Launch",
self.tr("Do you want to launch {}").format(game.app_title), self.tr("Do you want to launch {}").format(game.app_title),
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes | QMessageBox.No,
) )
== QMessageBox.Yes == QMessageBox.Yes
): ):
logger.info("Cancel Startup") logger.info("Cancel Startup")
self.finished.emit(app_name, "") self.finished.emit(app_name, "")

View file

@ -1,6 +1,11 @@
from typing import List
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QSystemTrayIcon, QMenu, QAction from PyQt5.QtWidgets import QSystemTrayIcon, QMenu, QAction
from rare import shared
from rare.utils.meta import GameMeta
class TrayIcon(QSystemTrayIcon): class TrayIcon(QSystemTrayIcon):
def __init__(self, parent): def __init__(self, parent):
@ -14,8 +19,34 @@ class TrayIcon(QSystemTrayIcon):
self.start_rare = QAction("Rare") self.start_rare = QAction("Rare")
self.menu.addAction(self.start_rare) self.menu.addAction(self.start_rare)
self.exit_action = QAction(self.tr("Exit"))
self.menu.addSeparator() self.menu.addSeparator()
self.menu.addAction(self.exit_action) self.text_action = QAction("Quick launch")
self.text_action.setEnabled(False)
self.menu.addAction(self.text_action)
if len(installed := shared.core.get_installed_list()) < 5:
last_played = [GameMeta(i.app_name) for i in sorted(installed, key=lambda x: x.title)]
elif games := sorted(
parent.mainwindow.tab_widget.games_tab.game_utils.game_meta.get_games(),
key=lambda x: x.last_played, reverse=True):
last_played: List[GameMeta] = games[0:5]
else:
last_played = [GameMeta(i.app_name) for i in sorted(installed, key=lambda x: x.title)][0:5]
self.game_actions = []
for game in last_played:
a = QAction(shared.core.get_game(game.app_name).app_title)
a.setProperty("app_name", game.app_name)
self.game_actions.append(a)
a.triggered.connect(
lambda: parent.mainwindow.tab_widget.games_tab.game_utils.prepare_launch(
self.sender().property("app_name"))
)
self.menu.addActions(self.game_actions)
self.menu.addSeparator()
self.exit_action = QAction(self.tr("Exit"))
self.menu.addAction(self.exit_action)
self.setContextMenu(self.menu) self.setContextMenu(self.menu)

64
rare/utils/meta.py Normal file
View file

@ -0,0 +1,64 @@
import json
import os
from dataclasses import dataclass
from datetime import datetime
from logging import getLogger
from typing import Dict
from rare import data_dir
logger = getLogger("GameMeta")
@dataclass
class GameMeta:
app_name: str
last_played: datetime = None
@classmethod
def from_json(cls, data):
return cls(
app_name=data["app_name"],
last_played=datetime.strptime(data.get("last_played", "None"), '%Y-%m-%dT%H:%M:%S.%f')
)
def __dict__(self):
return dict(
app_name=self.app_name,
last_played=self.last_played.strftime("%Y-%m-%dT%H:%M:%S.%f")
)
class RareGameMeta:
_meta: Dict[str, GameMeta] = {}
def __init__(self):
meta_data = {}
if os.path.exists(p := os.path.join(data_dir, "game_meta.json")):
try:
meta_data = json.load(open(p))
except json.JSONDecodeError:
logger.warning("Game meta json file corrupt")
else:
with open(p, "w") as file:
file.write("{}")
for app_name, data in meta_data.items():
self._meta[app_name] = GameMeta.from_json(data)
def get_games(self):
return list(self._meta.values())
def get_game(self, app_name):
return self._meta.get(app_name, GameMeta(app_name))
def set_game(self, app_name: str, game: GameMeta):
self._meta[app_name] = game
self.save_file()
def save_file(self):
json.dump(
{app_name: data.__dict__() for app_name, data in self._meta.items()},
open(os.path.join(data_dir, "game_meta.json"), "w"),
indent=4
)