2025.01.15 01:24:17

This commit is contained in:
Christian Moser 2025-01-15 01:24:17 +01:00
parent 80aff0dfd3
commit 649053bb20
Failed to extract signature
4 changed files with 121 additions and 34 deletions

View File

@ -30,6 +30,7 @@ import sys
import logging import logging
import pathlib import pathlib
import datetime import datetime
from string import Template
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -783,10 +784,14 @@ class SteamGame(GameData):
ignore_match) ignore_match)
self.appid = int(appid) self.appid = int(appid)
self.installdir = installdir self.installdir = installdir
self.librarydir=None
def get_variables(self): def get_variables(self):
vars = super().get_variables() vars = super().get_variables()
vars["INSTALLDIR"] = self.installdir if self.installdir else "" vars["INSTALLDIR"] = self.installdir if self.installdir else ""
vars["STEAM_APPID"] = str(self.appid)
vars["STEAM_LIBDIR"] = self.librarydir if self.librarydir else ""
return vars
@Property(type=int) @Property(type=int)
def appid(self): def appid(self):
@ -802,12 +807,26 @@ class SteamGame(GameData):
def installdir(self,installdir:str|None): def installdir(self,installdir:str|None):
self.__installdir = installdir self.__installdir = installdir
@Property
def librarydir(self)->str|None:
if not self.__librarydir and self.installdir:
return pathlib.Path(self.installdir).resolve().parent.parent.parent
return self.__librarydir
@librarydir.setter
def librarydir(self,directory):
if not directory:
self.__librarydir = None
elif not os.path.isdir(directory):
raise ValueError("Steam librarydir is not a valid directory!")
self.__librarydir = directory
def serialize(self): def serialize(self):
ret = super().serialize() ret = super().serialize()
ret['appid'] = self.appid ret['appid'] = self.appid
if self.installdir: if self.installdir:
ret['installdir'] = self.installdir ret['installdir'] = self.installdir if self.installdir else ""
ret['librarydir'] = self.librarydir if self.librarydir else ""
return ret return ret
@ -1015,10 +1034,10 @@ class Game(GObject):
@Property(type=str) @Property(type=str)
def dbid(self)->str: def dbid(self)->str:
return self.__id return self.__dbid
@dbid.setter @dbid.setter
def id(self,id:str): def id(self,id:str):
self.__id = id self.__dbid = id
@Property(type=str) @Property(type=str)
def key(self)->str: def key(self)->str:
@ -1077,8 +1096,12 @@ class Game(GObject):
os.path.join(settings.gameconf_dir,'.'.join((self.key,'gameconf'))) os.path.join(settings.gameconf_dir,'.'.join((self.key,'gameconf')))
return self.__filename return self.__filename
@filename.setter @filename.setter
def filename(self,fn:str): def filename(self,fn:str):
if self.__filename and fn != self.__filename and os.path.isfile(self.__filename):
self.__old_filename = self.__filename
if not os.path.isabs(fn): if not os.path.isabs(fn):
self.__filename = GLib.build_filename(settings.gameconf_dir,fn) self.__filename = GLib.build_filename(settings.gameconf_dir,fn)
else: else:
@ -1195,13 +1218,15 @@ class Game(GObject):
def savegame_root(self)->str|None: def savegame_root(self)->str|None:
if not self.game_data: if not self.game_data:
return None return None
return self.game_data.savegame_root t = Template(self.game_data.savegame_root)
return t.safe_substitute(self.get_variables())
@Property @Property
def savegame_dir(self)->str|None: def savegame_dir(self)->str|None:
if not self.game_data: if not self.game_data:
return None return None
return self.game_data.savegame_dir t = Template(self.game_data.savegame_dir)
return t.safe_substitute(self.get_variables())
def add_variable(self,name:str,value:str): def add_variable(self,name:str,value:str):
self.__variables[str(name)] = str(value) self.__variables[str(name)] = str(value)
@ -1210,14 +1235,19 @@ class Game(GObject):
if name in self.__variables: if name in self.__variables:
del self.__variables[name] del self.__variables[name]
def get_variable(self,name): def get_variables(self):
vars = dict(os.environ) vars = settings.get_variables()
#vars.update(settings.variables)
vars.update(self.__variables) vars.update(self.__variables)
game_data = self.game_data game_data = self.game_data
if (game_data is not None): if game_data is not None:
vars.update(game_data.variables) vars.update(game_data.get_variables())
return vars
def get_variable(self,name):
try:
return self.get_variables()[name]
except:
return ""
def serialize(self)->dict: def serialize(self)->dict:
ret = { ret = {
@ -1253,17 +1283,21 @@ class Game(GObject):
return ret return ret
def save(self): def save(self):
old_fname = self.filename path = pathlib.Path(self.filename).resolve() if self.filename else None
if old_fname: if path is None:
old_path = pathlib.Path(self.filename).resolve() logger.error("No filename for saving the game \"{game}\" set! Not saving file!".format(game=self.name))
return
new_path = pathlib.Path(settings.gameconf_dir / '.'.join(self.id,'gameconf')).resolve() if hasattr(self,'__old_filename'):
if old_fname and (str(old_path) != str(new_path)) and old_path.is_file(): old_path = pathlib.Path(self.__old_filename).resolve()
os.unlink(old_path) if old_path.is_file():
if not new_path.parent.is_dir(): os.unlink(old_path)
os.makedirs(new_path.parent) delattr(self,'__old_filename')
with open(new_path,'wt',encoding='utf-8') as ofile: if not path.parent.is_dir():
os.makedirs(path.parent)
with open(path,'wt',encoding='utf-8') as ofile:
ofile.write(json.dumps(self.serialize(),ensure_ascii=False,indent=4)) ofile.write(json.dumps(self.serialize(),ensure_ascii=False,indent=4))
def __bool__(self): def __bool__(self):
@ -1386,7 +1420,7 @@ class GameManager(GObject):
self.add_game(game) self.add_game(game)
def add_game(self,game:Game): def add_game(self,game:Game):
self.__[game.key] = game self.__games[game.key] = game
if (game.steam_macos): if (game.steam_macos):
self.__steam_games[game.steam_macos.appid] = game self.__steam_games[game.steam_macos.appid] = game
self.__steam_macos_games[game.steam_macos.appid] = game self.__steam_macos_games[game.steam_macos.appid] = game

View File

@ -17,7 +17,7 @@
############################################################################### ###############################################################################
from gi.repository import Gio,GLib,Gtk,Pango from gi.repository import Gio,GLib,Gtk,Pango
from gi.repository.GObject import Property,Signal,GObject from gi.repository.GObject import Property,Signal,GObject,BindingFlags
from ..game import ( from ..game import (
Game, Game,
GameFileMatcher, GameFileMatcher,
@ -1051,8 +1051,8 @@ class GameDialog(Gtk.Dialog):
filematch.append(GameFileMatcher(fm_data.match_type,fm_data.match_value)) filematch.append(GameFileMatcher(fm_data.match_type,fm_data.match_value))
for i in range(im_model.get_n_items()): for i in range(im_model.get_n_items()):
fm_data = im_model.get_item(i) im_data = im_model.get_item(i)
ignorematch.append(GameFileMatcher(im_data.match_type,fm_data.match_value)) ignorematch.append(GameFileMatcher(im_data.match_type,im_data.match_value))
for i in range(var_model.get_n_items()): for i in range(var_model.get_n_items()):
var = var_model.get_item(i) var = var_model.get_item(i)
@ -1092,6 +1092,7 @@ class GameDialog(Gtk.Dialog):
self.__game.savegame_type = savegame_type self.__game.savegame_type = savegame_type
self.__game.savegame_name = savegame_name self.__game.savegame_name = savegame_name
self.__game.variables = variables self.__game.variables = variables
self.__game.filename = '.'.join((self.__game.key(),'gameconf'))
else: else:
self.__game = Game(key,name,savegame_name) self.__game = Game(key,name,savegame_name)
self.__game.savegame_type = savegame_type self.__game.savegame_type = savegame_type
@ -1100,16 +1101,20 @@ class GameDialog(Gtk.Dialog):
if self.get_is_valid_savegame_type(SavegameType.WINDOWS): if self.get_is_valid_savegame_type(SavegameType.WINDOWS):
data = get_game_data(self.__windows) data = get_game_data(self.__windows)
installdir = self.__windows.installdir_entry.get_text() installdir = self.__windows.installdir_entry.get_text()
grk_model = self.__windows.lookup_regekys.listview.get_model().get_model() grk_model = self.__windows.lookup_regkeys.listview.get_model().get_model()
irk_model = self.__windows.installdir_regkeys.listview.get_model().get_model() irk_model = self.__windows.installdir_regkeys.listview.get_model().get_model()
grk = [] grk = []
irk = [] irk = []
for i in range(grk_model.get_n_items()): for i in range(grk_model.get_n_items()):
grk.append(grk_model.get_item(i).regkey) item = grk.model.get_item(i)
if item.regkey:
grk.append(item.regkey)
for i in range(irk_model.get_n_items()): for i in range(irk_model.get_n_items()):
irk.append(irk_model.get_item(i).regkey) item = irk.model.get_item(i)
if item.regkey:
irk.append(item.regkey)
if self.__game.windows: if self.__game.windows:
wg = self.__game.windows wg = self.__game.windows
@ -1330,7 +1335,7 @@ class GameDialog(Gtk.Dialog):
def _on_filematch_dropdown_selection_changed(self,dropdown,data,item): def _on_filematch_dropdown_selection_changed(self,dropdown,data,item):
data = item.get_item() data = item.get_item()
data.match_type = dropdown.get_slected_item() data.match_type = dropdown.get_selected_item()
def _on_filematch_type_dropdown_setup(self,factory,item): def _on_filematch_type_dropdown_setup(self,factory,item):
label = Gtk.Label() label = Gtk.Label()
@ -1365,7 +1370,7 @@ class GameDialog(Gtk.Dialog):
else: else:
label.start_editing() label.start_editing()
label.grab_focus() label.grab_focus()
label.bind_property('text',data,'match_value',GObject.BindingFlags.DEFAULT) label.bind_property('text',data,'match_value',BindingFlags.DEFAULT)
label.connect('changed',self._on_filematch_value_label_changed,widget) label.connect('changed',self._on_filematch_value_label_changed,widget)
def _on_windows_regkey_setup(self,factory,item): def _on_windows_regkey_setup(self,factory,item):
@ -1421,7 +1426,7 @@ class GameDialog(Gtk.Dialog):
i = 0 i = 0
while i < model.get_n_items(): while i < model.get_n_items():
item = model.get_item(i) item = model.get_item(i)
if not item.match_value: if not item.match_value.strip():
model.remove(i) model.remove(i)
continue continue
i += 1 i += 1

View File

@ -291,7 +291,7 @@ class NewSteamAppsDialog(Gtk.Dialog):
def on_dialog_response(dialog,response): def on_dialog_response(dialog,response):
if response == Gtk.ResponseType.APPLY: if response == Gtk.ResponseType.APPLY:
for i in range(self.__listmodel.get_n_items()): for i in range(self.__listmodel.get_n_items()):
if data.appid == self.__listmodel.get_item(i): if data.appid == self.__listmodel.get_item(i).appid:
self.__listmodel.remove(i) self.__listmodel.remove(i)
break break
@ -314,6 +314,7 @@ class NewSteamAppsDialog(Gtk.Dialog):
dialog = GameDialog(self,game) dialog = GameDialog(self,game)
dialog.set_title("sgbackup: Add Steam Game") dialog.set_title("sgbackup: Add Steam Game")
dialog.set_modal(False)
dialog.connect('response',on_dialog_response) dialog.connect('response',on_dialog_response)
dialog.present() dialog.present()
@ -331,7 +332,7 @@ class NewSteamAppsDialog(Gtk.Dialog):
dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.YES_NO) dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.YES_NO)
dialog.set_transient_for(self) dialog.set_transient_for(self)
dialog.set_modal(True) dialog.set_modal(False)
dialog.props.text = "Do you want to put <span weight=\"bold\">\"{steamapp}\"</span> on the ignore list?".format(steamapp=data.name) dialog.props.text = "Do you want to put <span weight=\"bold\">\"{steamapp}\"</span> on the ignore list?".format(steamapp=data.name)
dialog.props.use_markup = True dialog.props.use_markup = True

View File

@ -105,6 +105,53 @@ class Settings(GObject.GObject):
return self.parser.get('sgbackup','logLevel') return self.parser.get('sgbackup','logLevel')
return "INFO" return "INFO"
@GObject.Property
def variables(self)->dict[str:str]:
ret = {}
if self.parser.has_section('variables'):
for k,v in self.parser.items('variables'):
ret[k] = v
return ret
@variables.setter
def variables(self,vars:dict[str:str]|list|tuple):
if self.parser.has_section('variables'):
for opt in self.parser['variables'].keys():
self.parser.remove_option('variables',opt)
if not vars:
return
if isinstance(vars,dict):
for k,v in vars.items():
self.parser.set('variables',k,v)
else:
for v in vars:
self.parser.set('variables',v[0],v[1])
def add_variable(self,name:str,value:str):
self.parser.set('variables',name,value)
def remove_variable(self,name:str):
try:
self.parser.remove_option('variables',name)
except:
pass
def get_variable(self,name:str)->str:
try:
return self.parser.get('variables',name)
except:
return ""
def get_variables(self)->dict[str:str]:
ret = dict(os.environ)
ret.update({
"DOCUMENTS": GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DOCUMENTS),
"DOCUMENTS_DIR": GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DOCUMENTS),
})
ret.update(self.variables)
return ret
@GObject.Property(type=str) @GObject.Property(type=str)
def zipfile_compression(self)->str: def zipfile_compression(self)->str:
if self.parser.has_option('zipfile','compression'): if self.parser.has_option('zipfile','compression'):