############################################################################### # sgbackup - The SaveGame Backup tool # # Copyright (C) 2024,2025 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 . # ############################################################################### from gi.repository import Gtk,GLib,Gio from gi.repository.GObject import GObject,Property,Signal,SignalFlags from ..i18n import gettext as _,gettext_noop as N_ from ..game import GameManager,Game,EpicGameData,EpicWindowsData from ..epic import Epic,EpicGameInfo,EpicIgnoredApp from ..utility import PLATFORM_WINDOWS from ._gamedialog import GameDialog class EpicNewAppsDialogSorter(Gtk.Sorter): def do_compare(self,item1:EpicGameInfo,item2:EpicGameInfo): name1 = item1.name.lower() name2 = item2.name.lower() if name1 > name2: return Gtk.Ordering.LARGER elif name1 < name2: return Gtk.Ordering.SMALLER return Gtk.Ordering.EQUAL class EpicNewAppsDialog(Gtk.Dialog): def __init__(self,parent:Gtk.Window|None=None): Gtk.Dialog.__init__(self, transient_for=parent, title=_("SGBackup: Manage new Epic-Games apps"), modal=False) self.set_default_size(800,600) scrolled = Gtk.ScrolledWindow() epic = Epic() self.__liststore = Gio.ListStore.new(EpicGameInfo) for info in epic.find_new_apps(): self.__liststore.append(info) sort_model = Gtk.SortListModel(model=self.__liststore, sorter=EpicNewAppsDialogSorter()) selection = Gtk.SingleSelection(model=sort_model, autoselect=False, can_unselect=True) factory = Gtk.SignalListItemFactory() factory.connect('setup',self._on_listview_setup) factory.connect('bind',self._on_listview_bind) self.__listview = Gtk.ListView(model=selection,factory=factory,hexpand=True,vexpand=True) scrolled.set_child(self.__listview) self.get_content_area().append(scrolled) self.__close_button = self.add_button(_("Close"),Gtk.ResponseType.OK) def _on_listview_setup(self,factory,item): child = Gtk.Grid(column_spacing=4,row_spacing=2) child.name_label = Gtk.Label(xalign=0.0,hexpand=True) child.attach(child.name_label,1,0,1,1) label = Gtk.Label(label=_("CatalogItemId:"), use_markup=False, xalign=0.0) child.catalogitemid_label = Gtk.Label(xalign=0.0, use_markup=False, hexpand=True) child.attach(label,0,1,1,1) child.attach(child.catalogitemid_label,1,1,1,1) label = Gtk.Label(label=_("Installation Directory:"), use_markup=False, xalign=0.0) child.installdir_label = Gtk.Label(xalign=0.0, use_markup=False, hexpand=True) child.attach(label,0,2,1,1) child.attach(child.installdir_label,1,2,1,1) actiongrid = Gtk.Grid(row_spacing=2,column_spacing=2) icon = Gtk.Image.new_from_icon_name('list-add-symbolic') icon.set_pixel_size(16) child.new_button = Gtk.Button() child.new_button.set_child(icon) child.new_button.set_tooltip_text(_("Add Epic-Games-app as a new game.")) actiongrid.attach(child.new_button,0,0,1,1) icon = Gtk.Image.new_from_icon_name('edit-delete-symbolic') icon.set_pixel_size(16) child.ignore_button = Gtk.Button() child.ignore_button.set_child(icon) child.ignore_button.set_tooltip_text(_("Add Epic-Games-app to the ignore list.")) actiongrid.attach(child.ignore_button,1,0,1,1) icon = Gtk.Image.new_from_icon_name('edit-find-symbolic') icon.set_pixel_size(16) child.lookup_button = Gtk.Button() child.lookup_button.set_child(icon) child.lookup_button.set_tooltip_text(_("Lookup Epic-Games-app for already registered game.")) actiongrid.attach(child.lookup_button,0,1,1,1) icon = Gtk.Image.new_from_icon_name('folder-download-symbolic') icon.set_pixel_size(16) child.online_button = Gtk.Button() child.online_button.set_child(icon) child.online_button.set_tooltip_text(_("Lookup Epic-Games-app online.")) actiongrid.attach(child.online_button,1,1,1,1) child.attach(actiongrid,2,0,1,3) item.set_child(child) def _on_listview_bind(self,factory,item): child = item.get_child() data = item.get_item() child.name_label.set_markup("{}".format( GLib.markup_escape_text(data.name))) child.catalogitemid_label.set_text(data.catalog_item_id) child.installdir_label.set_text(data.installdir) if hasattr(child.new_button,'_signal_clicked_connector'): child.new_button.disconnect(child.new_button._signal_clicked_connector) child.new_button._signal_clicked_connector = child.new_button.connect('clicked', self._on_listview_new_button_clicked, data) if hasattr(child.ignore_button,'_signal_clicked_connector'): child.ignore_button.disconnect(child.ignore_button._signal_clicked_connector) child.ignore_button._signal_clicked_connector = child.ignore_button.connect('clicked', self._on_listview_ignore_button_clicked, data) if hasattr(child.lookup_button,'_signal_clicked_connector'): child.lookup_button.disconnect(child.lookup_button._signal_clicked_connector) child.lookup_button._signal_clicked_connector = child.lookup_button.connect('clicked', self._on_listview_lookup_button_clicked, data) child.lookup_button.set_sensitive(False) if hasattr(child.online_button,'_signal_clicked_connector'): child.online_button.disconnect(child.online_button._signal_clicked_connector) child.online_button._signal_clicked_connector = child.online_button.connect('clicked', self._on_listview_online_button_clicked, data) child.online_button.set_sensitive(False) def _on_game_dialog_response(self,dialog,response,info:EpicGameInfo): if response == Gtk.ResponseType.APPLY: for i in range(self.__liststore.get_n_items()): item = self.__liststore.get_item(i) if item.catalog_item_id == info.catalog_item_id: self.__liststore.remove(i) break def _on_listview_new_button_clicked(self,button:Gtk.Button,info:EpicGameInfo): game = Game("",info.name,"") if PLATFORM_WINDOWS: windows = EpicWindowsData("","",installdir=info.installdir) else: windows = None game.epic = EpicGameData(catalog_item_id=info.catalog_item_id, windows=windows) dialog = GameDialog(parent=self,game=game) dialog.connect_after('response',self._on_dialog_reponse,info) dialog.present() def _on_ignore_dialog_response(self,dialog,response,info:EpicGameInfo): if response == Gtk.ResponseType.YES: epic = Epic() epic.add_ignored_app(EpicIgnoredApp(info.catalog_item_id, info.name, dialog.reason_entry.get_text())) for i in range(self.__liststore.get_n_items()): item = self.__liststore.get_item() if item.catalog_item_id == info.catalog_item_id: self.__liststore.remove(i) break dialog.hide() dialog.destroy() def _on_listview_ignore_button_clicked(self,button:Gtk.Button,info:EpicGameInfo): dialog = Gtk.MessageDialog(transient_for=self, text=_("Do you really won to add the game {game} to the ignore list?").format( game=GLib.markup_escape_text(info.name)), use_markup=True, secondary_text=_("Please enter a reason below."), secondary_use_markup=True, buttons=Gtk.ButtonsType.YES_NO, modal=False) dialog.reason_entry = Gtk.Entry() dialog.reason_entry.set_hexpand(True) dialog.get_content_area().append(dialog.reason_entry) dialog.connect('response',self._on_ignore_dialog_response,info) dialog.present() def _on_listview_lookup_button_clicked(self,button:Gtk.Button,info:EpicGameInfo): pass def _on_listview_online_button_clicked(self,button:Gtk.Button,info:EpicGameInfo): pass def do_response(self,response): self.hide() self.destroy()