mirror of
https://github.com/c9moser/sgbackup.git
synced 2026-01-19 19:40:13 +00:00
added ManageSteamLibraries Dialog
This commit is contained in:
parent
a63453fd87
commit
43a7208cf3
@ -1344,7 +1344,7 @@ class GameManager(GObject):
|
|||||||
return self.__games
|
return self.__games
|
||||||
|
|
||||||
@Property(type=object)
|
@Property(type=object)
|
||||||
def stam_games(self)->dict[int:Game]:
|
def steam_games(self)->dict[int:Game]:
|
||||||
return self.__steam_games
|
return self.__steam_games
|
||||||
|
|
||||||
@Property(type=object)
|
@Property(type=object)
|
||||||
|
|||||||
@ -29,6 +29,7 @@ from ..settings import settings
|
|||||||
from ._settingsdialog import SettingsDialog
|
from ._settingsdialog import SettingsDialog
|
||||||
from ._gamedialog import GameDialog
|
from ._gamedialog import GameDialog
|
||||||
from ..game import Game,GameManager
|
from ..game import Game,GameManager
|
||||||
|
from ._steam import SteamLibrariesDialog
|
||||||
|
|
||||||
__gtype_name__ = __name__
|
__gtype_name__ = __name__
|
||||||
|
|
||||||
@ -554,6 +555,10 @@ class Application(Gtk.Application):
|
|||||||
action_settings.connect('activate',self._on_action_settings)
|
action_settings.connect('activate',self._on_action_settings)
|
||||||
self.add_action(action_settings)
|
self.add_action(action_settings)
|
||||||
|
|
||||||
|
action_steam_manage_libraries = Gio.SimpleAction.new('steam-manage-libraries')
|
||||||
|
action_steam_manage_libraries.connect('activate',self._on_action_steam_manage_libraries)
|
||||||
|
self.add_action(action_steam_manage_libraries)
|
||||||
|
|
||||||
# add accels
|
# add accels
|
||||||
self.set_accels_for_action('app.quit',["<Primary>q"])
|
self.set_accels_for_action('app.quit',["<Primary>q"])
|
||||||
|
|
||||||
@ -598,6 +603,10 @@ class Application(Gtk.Application):
|
|||||||
Gtk.ResponseType.APPLY)
|
Gtk.ResponseType.APPLY)
|
||||||
dialog.present()
|
dialog.present()
|
||||||
|
|
||||||
|
def _on_action_steam_manage_libraries(self,action,param):
|
||||||
|
dialog = SteamLibrariesDialog(self.appwindow)
|
||||||
|
dialog.present()
|
||||||
|
|
||||||
def new_settings_dialog(self)->SettingsDialog:
|
def new_settings_dialog(self)->SettingsDialog:
|
||||||
"""
|
"""
|
||||||
new_settings_dialog Create a new `SettingsDialog`.
|
new_settings_dialog Create a new `SettingsDialog`.
|
||||||
|
|||||||
198
sgbackup/gui/_steam.py
Normal file
198
sgbackup/gui/_steam.py
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
###############################################################################
|
||||||
|
# sgbackup - The SaveGame Backup tool #
|
||||||
|
# Copyright (C) 2024 Christian Moser #
|
||||||
|
# #
|
||||||
|
# This program is free software: you can redistribute it and/or modify #
|
||||||
|
# it under the terms of the GNU General Public License as published by #
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or #
|
||||||
|
# (at your option) any later version. #
|
||||||
|
# #
|
||||||
|
# This program is distributed in the hope that it will be useful, #
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||||
|
# GNU General Public License for more details. #
|
||||||
|
# #
|
||||||
|
# You should have received a copy of the GNU General Public License #
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
from gi.repository import Gtk,Gio,GLib
|
||||||
|
from gi.repository.GObject import GObject,Property,Signal,BindingFlags
|
||||||
|
|
||||||
|
from ..steam import Steam,SteamLibrary
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class SteamLibrariesDialog(Gtk.Dialog):
|
||||||
|
def __init__(self,parent:Gtk.Window|None=None):
|
||||||
|
Gtk.Dialog.__init__(self)
|
||||||
|
self.set_title("sgbackup: Steam Libraries")
|
||||||
|
self.set_default_size(620,480)
|
||||||
|
if parent is not None:
|
||||||
|
self.set_transient_for(parent)
|
||||||
|
|
||||||
|
self.__steam = Steam()
|
||||||
|
|
||||||
|
hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL,2)
|
||||||
|
icon = Gtk.Image.new_from_icon_name('list-add-symbolic')
|
||||||
|
self.__add_lib_button=Gtk.Button()
|
||||||
|
self.__add_lib_button.set_child(icon)
|
||||||
|
self.__add_lib_button.connect('clicked',self._on_add_library_button_clicked)
|
||||||
|
hbox.append(self.__add_lib_button)
|
||||||
|
|
||||||
|
self.__lib_editable = Gtk.EditableLabel()
|
||||||
|
self.__lib_editable.set_hexpand(True)
|
||||||
|
self.__lib_editable.connect('changed',self._on_add_library_label_changed)
|
||||||
|
self._on_add_library_label_changed(self.__lib_editable)
|
||||||
|
hbox.append(self.__lib_editable)
|
||||||
|
|
||||||
|
icon = Gtk.Image.new_from_icon_name('document-open-symbolic')
|
||||||
|
self.__lib_chooser_button = Gtk.Button()
|
||||||
|
self.__lib_chooser_button.set_child(icon)
|
||||||
|
self.__lib_chooser_button.connect('clicked',self._on_choose_library_button_clicked)
|
||||||
|
hbox.append(self.__lib_chooser_button)
|
||||||
|
|
||||||
|
self.get_content_area().append(hbox)
|
||||||
|
|
||||||
|
frame = Gtk.Frame.new("Steam libraries")
|
||||||
|
scrolled = Gtk.ScrolledWindow()
|
||||||
|
|
||||||
|
self.__listmodel = Gio.ListStore.new(SteamLibrary)
|
||||||
|
for lib in self.__steam.libraries:
|
||||||
|
self.__listmodel.append(lib)
|
||||||
|
|
||||||
|
factory = Gtk.SignalListItemFactory()
|
||||||
|
factory.connect('setup',self._on_library_setup)
|
||||||
|
factory.connect('bind',self._on_library_bind)
|
||||||
|
|
||||||
|
selection = Gtk.SingleSelection.new(self.__listmodel)
|
||||||
|
self.__listview = Gtk.ListView.new(selection,factory)
|
||||||
|
|
||||||
|
scrolled.set_child(self.__listview)
|
||||||
|
scrolled.set_hexpand(True)
|
||||||
|
scrolled.set_vexpand(True)
|
||||||
|
frame.set_child(scrolled)
|
||||||
|
frame.set_hexpand(True)
|
||||||
|
frame.set_vexpand(True)
|
||||||
|
self.get_content_area().append(frame)
|
||||||
|
|
||||||
|
self.add_button("Apply",Gtk.ResponseType.APPLY)
|
||||||
|
self.add_button("Cancel",Gtk.ResponseType.CANCEL)
|
||||||
|
|
||||||
|
def _on_add_library_button_clicked(self,button):
|
||||||
|
try:
|
||||||
|
steamlib = SteamLibrary(self.__lib_editable.get_text())
|
||||||
|
for i in range(self.__listmodel.get_n_items()):
|
||||||
|
item = self.__listmodel.get_item(i)
|
||||||
|
if steamlib.directory == item.directory:
|
||||||
|
self.__lib_editable.set_text("")
|
||||||
|
return
|
||||||
|
|
||||||
|
self.__listmodel.append(steamlib)
|
||||||
|
self.__lib_editable.set_text("")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _on_choose_library_button_clicked(self,button):
|
||||||
|
dialog = Gtk.FileDialog.new()
|
||||||
|
dialog.set_title("sgbackup: Select Steam library path")
|
||||||
|
dialog.set_modal(True)
|
||||||
|
if (self.__lib_editable.get_text() and os.path.isdir(self.__lib_editable.get_text())):
|
||||||
|
dialog.set_initial_folder(Gio.File.new_for_path(self.__lib_editable.get_text()))
|
||||||
|
|
||||||
|
dialog.select_folder(self,None,self._on_choose_library_select_folder)
|
||||||
|
|
||||||
|
def _on_choose_library_select_folder(self,dialog,result,*args):
|
||||||
|
try:
|
||||||
|
file = dialog.select_folder_finish(result)
|
||||||
|
except GLib.Error as ex:
|
||||||
|
return
|
||||||
|
|
||||||
|
if file is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.__lib_editable.set_text(file.get_path())
|
||||||
|
|
||||||
|
|
||||||
|
def _on_add_library_label_changed(self,label):
|
||||||
|
if label.get_text() and os.path.isdir(label.get_text()):
|
||||||
|
self.__add_lib_button.set_sensitive(True)
|
||||||
|
else:
|
||||||
|
self.__add_lib_button.set_sensitive(False)
|
||||||
|
|
||||||
|
def _on_list_chooser_button_clicked(self,button,label):
|
||||||
|
dialog = Gtk.FileDialog.new()
|
||||||
|
dialog.set_initial_folder(Gio.File.new_for_path(label.get_text()))
|
||||||
|
dialog.set_modal(True)
|
||||||
|
dialog.set_title("sgbackup: Change Steam library path")
|
||||||
|
dialog.select_folder(self,None,self._on_list_chooser_dialog_select_folder,label)
|
||||||
|
|
||||||
|
def _on_list_chooser_dialog_select_folder(self,dialog,result,label,*data):
|
||||||
|
try:
|
||||||
|
file = dialog.select_folder_finish(result)
|
||||||
|
except GLib.Error as ex:
|
||||||
|
return
|
||||||
|
|
||||||
|
if file is None or not file.get_path():
|
||||||
|
return
|
||||||
|
|
||||||
|
label.set_text(file.get_path())
|
||||||
|
|
||||||
|
|
||||||
|
def _on_list_remove_button_clicked(self,button,label):
|
||||||
|
for i in range(self.__listmodel.get_n_items()):
|
||||||
|
item = self.__listmodel.get_item(i)
|
||||||
|
if label.get_text() == item.directory:
|
||||||
|
self.__listmodel.remove(i)
|
||||||
|
return
|
||||||
|
|
||||||
|
def _on_library_setup(self,factory,item):
|
||||||
|
child = Gtk.Box.new(Gtk.Orientation.HORIZONTAL,2)
|
||||||
|
child.label = Gtk.EditableLabel()
|
||||||
|
child.label.set_hexpand(True)
|
||||||
|
child.append(child.label)
|
||||||
|
|
||||||
|
icon = Gtk.Image.new_from_icon_name('document-open-symbolic')
|
||||||
|
child.chooser_button = Gtk.Button()
|
||||||
|
child.chooser_button.set_child(icon)
|
||||||
|
child.append(child.chooser_button)
|
||||||
|
|
||||||
|
icon = Gtk.Image.new_from_icon_name('list-remove-symbolic')
|
||||||
|
child.remove_button = Gtk.Button()
|
||||||
|
child.remove_button.set_child(icon)
|
||||||
|
child.append(child.remove_button)
|
||||||
|
|
||||||
|
item.set_child(child)
|
||||||
|
|
||||||
|
|
||||||
|
def _on_library_bind(self,factory,item):
|
||||||
|
child = item.get_child()
|
||||||
|
lib = item.get_item()
|
||||||
|
child.label.set_text(lib.directory)
|
||||||
|
child.label.bind_property('text',lib,'directory',BindingFlags.DEFAULT)
|
||||||
|
child.chooser_button.connect('clicked',self._on_list_chooser_button_clicked,child.label)
|
||||||
|
child.remove_button.connect('clicked',self._on_list_remove_button_clicked,child.label)
|
||||||
|
|
||||||
|
def do_response(self,response):
|
||||||
|
if response == Gtk.ResponseType.APPLY:
|
||||||
|
steamlibs = []
|
||||||
|
for i in range(self.__listmodel.get_n_items()):
|
||||||
|
item = self.__listmodel.get_item(i)
|
||||||
|
if os.path.isdir(item.directory):
|
||||||
|
steamlibs.append(item)
|
||||||
|
self.__steam.libraries = steamlibs
|
||||||
|
|
||||||
|
self.hide()
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
|
|
||||||
|
class NewSteamAppsData(GObject):
|
||||||
|
def __init__(self,data):
|
||||||
|
GObject.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
|
class NewSteamAppsDialog(Gtk.Dialog):
|
||||||
|
def __init__(self,parent:Gtk.Window|None=None):
|
||||||
|
Gtk.Dialog.__init__(self)
|
||||||
|
self.__steam = Steam()
|
||||||
|
|
||||||
@ -12,6 +12,12 @@
|
|||||||
</submenu>
|
</submenu>
|
||||||
<submenu>
|
<submenu>
|
||||||
<attribute name='label' translatable='true'>_Steam</attribute>
|
<attribute name='label' translatable='true'>_Steam</attribute>
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name='label' translatable='true'>Manage Libraries</attribute>
|
||||||
|
<attribute name='action'>app.steam-manage-libraries</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
</submenu>
|
</submenu>
|
||||||
<submenu>
|
<submenu>
|
||||||
<attribute name='label' translatable='true'>_Epic</attribute>
|
<attribute name='label' translatable='true'>_Epic</attribute>
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
###############################################################################
|
|
||||||
# sgbackup - The SaveGame Backup tool #
|
|
||||||
# Copyright (C) 2024 Christian Moser #
|
|
||||||
# #
|
|
||||||
# This program is free software: you can redistribute it and/or modify #
|
|
||||||
# it under the terms of the GNU General Public License as published by #
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or #
|
|
||||||
# (at your option) any later version. #
|
|
||||||
# #
|
|
||||||
# This program is distributed in the hope that it will be useful, #
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
||||||
# GNU General Public License for more details. #
|
|
||||||
# #
|
|
||||||
# You should have received a copy of the GNU General Public License #
|
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
|
||||||
###############################################################################
|
|
||||||
@ -229,14 +229,14 @@ class Steam(GObject):
|
|||||||
self.__libraries.append(SteamLibrary(i))
|
self.__libraries.append(SteamLibrary(i))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
with open(str(self.steamlib_list_file),'r',encoding="utf-8") as ifile:
|
with open(str(self.steamlib_list_file),'rt',encoding="utf-8") as ifile:
|
||||||
for line in (i.strip() for i in ifile.readlines()):
|
for line in (i.strip() for i in ifile.readlines()):
|
||||||
if not line or line.startswith('#'):
|
if not line or line.startswith('#'):
|
||||||
continue
|
continue
|
||||||
libdir = Path(line).resolve()
|
libdir = Path(line).resolve()
|
||||||
if libdir.is_dir():
|
if libdir.is_dir():
|
||||||
try:
|
try:
|
||||||
self.add_library(str(libdir))
|
self.__libraries.append(SteamLibrary(str(libdir)))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -259,19 +259,33 @@ class Steam(GObject):
|
|||||||
|
|
||||||
@Property
|
@Property
|
||||||
def ignore_apps_file(self)->Path:
|
def ignore_apps_file(self)->Path:
|
||||||
return Path(settings.config_dir).resolve / 'ignore_steamapps.json'
|
return Path(settings.config_dir).resolve() / 'ignore_steamapps.json'
|
||||||
|
|
||||||
@Property
|
@Property
|
||||||
def libraries(self)->list[SteamLibrary]:
|
def libraries(self)->list[SteamLibrary]:
|
||||||
return self.__libraries
|
return self.__libraries
|
||||||
|
@libraries.setter
|
||||||
|
def libraries(self,steamlibs:list[SteamLibrary|str]):
|
||||||
|
libs=[]
|
||||||
|
for sl in steamlibs:
|
||||||
|
if isinstance(sl,SteamLibrary):
|
||||||
|
libs.append(sl)
|
||||||
|
elif isinstance(sl,str):
|
||||||
|
try:
|
||||||
|
libs.append(SteamLibrary(sl))
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
self.__libraries = libs
|
||||||
|
self.__write_steamlib_list_file()
|
||||||
|
|
||||||
@Property
|
@Property
|
||||||
def ignore_apps(self)->dict[int:IgnoreSteamApp]:
|
def ignore_apps(self)->dict[int:IgnoreSteamApp]:
|
||||||
return self.__ignore_apps
|
return self.__ignore_apps
|
||||||
|
|
||||||
def __write_steamlib_list_file(self):
|
def __write_steamlib_list_file(self):
|
||||||
with open(self.steamlib_list_file,'w',encoding='utf-8') as ofile:
|
with open(self.steamlib_list_file,'wt',encoding='utf-8') as ofile:
|
||||||
ofile.write('\n'.join(str(sl.directory) for sl in self.libraries))
|
output = '\n'.join([sl.directory for sl in self.__libraries])
|
||||||
|
ofile.write(output)
|
||||||
|
|
||||||
def __write_ignore_steamapps_file(self):
|
def __write_ignore_steamapps_file(self):
|
||||||
with open(self.ignore_apps_file,'w',encoding='utf-8') as ofile:
|
with open(self.ignore_apps_file,'w',encoding='utf-8') as ofile:
|
||||||
@ -299,15 +313,15 @@ class Steam(GObject):
|
|||||||
else:
|
else:
|
||||||
libdir = str(steamlib)
|
libdir = str(steamlib)
|
||||||
|
|
||||||
delete_libs=[]
|
|
||||||
for i in range(len(self.__libraries)):
|
|
||||||
if self.__libraries[i].directory == libdir:
|
|
||||||
delete_libs.append(i)
|
|
||||||
|
|
||||||
if delete_libs:
|
for i in sorted(range(len(self.__libraries)),reverse=True):
|
||||||
for i in sorted(delete_libs,reverse=True):
|
if libdir == self.__libraries[i].directory:
|
||||||
del self.__libraries[i]
|
del self.__libraries[i]
|
||||||
self.__write_steamlib_list_file()
|
self.__write_steamlib_list_file()
|
||||||
|
|
||||||
|
def save_libararies(self):
|
||||||
|
self.__write_steamlib_list_file()
|
||||||
|
|
||||||
|
|
||||||
def add_ignore_app(self,app:IgnoreSteamApp):
|
def add_ignore_app(self,app:IgnoreSteamApp):
|
||||||
self.__ignore_apps[app.appid] = app
|
self.__ignore_apps[app.appid] = app
|
||||||
@ -326,7 +340,7 @@ class Steam(GObject):
|
|||||||
new_apps = []
|
new_apps = []
|
||||||
for lib in self.libraries:
|
for lib in self.libraries:
|
||||||
for app in lib.steam_apps:
|
for app in lib.steam_apps:
|
||||||
if not app.appid in STEAM_GAMES and not app.appid in self.ignore_apps:
|
if not app.appid in GameManager.steam_games and not app.appid in self.ignore_apps:
|
||||||
new_apps.append(app)
|
new_apps.append(app)
|
||||||
return sorted(new_apps)
|
return sorted(new_apps)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user