2025.02.16 16:06:32 (desktop)

This commit is contained in:
Christian Moser 2025-02-16 16:06:32 +01:00
parent 4aa56401e8
commit f9f4adaf22
Failed to extract signature
7 changed files with 460 additions and 63 deletions

View File

@ -224,7 +224,7 @@ class GameFileMatcher(GObject):
raise TypeError("match_type is not a GameFileType instance!")
self.__match_type = match_type
@Property
@Property(type=str)
def match_file(self)->str:
"""
match_file The matcher value.

View File

@ -36,7 +36,67 @@ from ..archiver import ArchiverManager
__gtype_name__ = __name__
class GameView(Gtk.ScrolledWindow):
class GameViewKeySorter(Gtk.Sorter):
def __init__(self,sort_ascending:bool=True,*args,**kwargs):
Gtk.Sorter.__init__(self)
self.sort_ascending = sort_ascending
@Property(type=bool,default=True)
def sort_ascending(self)->bool:
return self.__sort_ascending
@sort_ascending.setter
def sort_ascending(self,asc:bool):
self.__sort_ascending = asc
def do_compare(self,game1,game2):
if self.sort_ascending:
if game1.key > game2.key:
return Gtk.Ordering.LARGER
elif game1.key < game2.key:
return Gtk.Ordering.SMALLER
else:
return Gtk.Ordering.EQUAL
else:
if game1.key < game2.key:
return Gtk.Ordering.LARGER
elif game1.key > game2.key:
return Gtk.Ordering.SMALLER
else:
return Gtk.Ordering.EQUAL
class GameViewNameSorter(Gtk.Sorter):
def __init__(self,sort_ascending:bool=True,*args,**kwargs):
Gtk.Sorter.__init__(self)
self.sort_ascending = sort_ascending
@Property(type=bool,default=True)
def sort_ascending(self)->bool:
return self.__sort_ascending
@sort_ascending.setter
def sort_ascending(self,asc:bool):
self.__sort_ascending = asc
def do_compare(self,game1,game2):
name1 = game1.name.lower()
name2 = game2.name.lower()
if self.sort_ascending:
if name1 > name2:
return Gtk.Ordering.LARGER
elif name1 < name2:
return Gtk.Ordering.SMALLER
else:
return Gtk.Ordering.EQUAL
else:
if name1 < name2:
return Gtk.Ordering.LARGER
elif name1 > name2:
return Gtk.Ordering.SMALLER
else:
return Gtk.Ordering.EQUAL
class GameView(Gtk.Box):
"""
GameView The View for games.
@ -48,19 +108,70 @@ class GameView(Gtk.ScrolledWindow):
"""
GameView
"""
Gtk.ScrolledWindow.__init__(self)
Gtk.Box.__init__(self,orientation=Gtk.Orientation.VERTICAL)
self.__key_sorter = GameViewKeySorter(True)
self.__name_sorter = GameViewNameSorter(True)
scrolled = Gtk.ScrolledWindow()
scrolled.set_vexpand(True)
scrolled.set_hexpand(True)
# set up the ActionBar for this widget
self.__actionbar = Gtk.ActionBar()
self.actionbar.set_hexpand(True)
icon = Gtk.Image.new_from_icon_name('list-add-symbolic')
icon.set_pixel_size(16)
add_game_button=Gtk.Button()
add_game_button.set_child(icon)
add_game_button.set_tooltip_text("Add a new game.")
add_game_button.connect('clicked',self._on_add_game_button_clicked)
self.actionbar.pack_start(add_game_button)
icon = Gtk.Image.new_from_icon_name('steam-svgrepo-com-symbolic')
icon.set_pixel_size(16)
new_steam_games_button=Gtk.Button()
new_steam_games_button.set_child(icon)
new_steam_games_button.set_tooltip_text("Manage new Steam-Apps")
new_steam_games_button.connect('clicked',self._on_new_steam_games_button_clicked)
self.actionbar.pack_start(new_steam_games_button)
self.actionbar.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL))
icon = Gtk.Image.new_from_icon_name('document-save-symbolic')
icon.set_pixel_size(16)
backup_active_live_button = Gtk.Button()
backup_active_live_button.set_child(icon)
backup_active_live_button.set_tooltip_markup("Backup all <i>active</i> and <i>live</i> Games.")
backup_active_live_button.connect('clicked',self._on_backup_active_live_button_clicked)
self.actionbar.pack_start(backup_active_live_button)
# Add a the search entry
self.__search_entry = Gtk.Entry()
self.__search_entry.set_hexpand(True)
self.actionbar.pack_end(self.__search_entry)
self.actionbar.pack_end(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL))
self.append(self.actionbar)
self.__liststore = Gio.ListStore.new(Game)
for g in GameManager.get_global().games.values():
pass
self.__liststore.append(g)
self.__sort_model = Gtk.SortListModel.new(self._liststore,self.__name_sorter)
self.__sort_model
self.__action_dialog = None
self.__backup_dialog = None
factory_icon = Gtk.SignalListItemFactory.new()
factory_icon.connect('setup',self._on_icon_column_setup)
factory_icon.connect('bind',self._on_icon_column_bind)
factory_icon.connect('unbind',self._on_icon_column_unbind)
column_icon = Gtk.ColumnViewColumn.new("",factory_icon)
factory_key = Gtk.SignalListItemFactory.new()
@ -89,10 +200,13 @@ class GameView(Gtk.ScrolledWindow):
factory_actions = Gtk.SignalListItemFactory.new()
factory_actions.connect('setup',self._on_actions_column_setup)
factory_actions.connect('bind',self._on_actions_column_bind)
#factory_actions.connect('ubind',self._on_actions_column_unbind)
column_actions = Gtk.ColumnViewColumn.new("",factory_actions)
selection = Gtk.SingleSelection.new(self._liststore)
selection = Gtk.SingleSelection.new(self.__sort_model)
self.__columnview = Gtk.ColumnView.new(selection)
self.columnview.set_vexpand(True)
self.columnview.set_hexpand(True)
self.columnview.append_column(column_icon)
self.columnview.append_column(column_key)
self.columnview.append_column(column_name)
@ -101,8 +215,9 @@ class GameView(Gtk.ScrolledWindow):
self.columnview.append_column(column_actions)
self.columnview.set_single_click_activate(True)
scrolled.set_child(self.columnview)
self.set_child(self.columnview)
self.append(scrolled)
self.refresh()
@property
@ -124,18 +239,65 @@ class GameView(Gtk.ScrolledWindow):
"""
return self.__columnview
@property
def actionbar(self)->Gtk.ActionBar:
return self.__actionbar
def refresh(self):
"""
refresh Refresh the view.
This method reloads the installed Games.
"""
self.__liststore.remove_all()
self.emit('refresh')
@Signal(name="refresh",return_type=None,arg_types=(),flags=SignalFlags.RUN_FIRST)
def do_refresh(self):
self._liststore.remove_all()
for game in GameManager.get_global().games.values():
self.__liststore.append(game)
self._liststore.append(game)
def _on_game_dialog_response(self,dialog,response):
if response == Gtk.ResponseType.APPLY:
self.refresh()
@Signal(name='game-active-changed',return_type=None,arg_types=(Game,),flags=SignalFlags.RUN_FIRST)
def do_game_active_changed(self,game:Game):
pass
@Signal(name='game-live-changed',return_type=None,arg_types=(Game,),flags=SignalFlags.RUN_FIRST)
def do_game_live_changed(self,game:Game):
pass
def _on_new_steamapps_dialog_response(self,dialog,response):
self.refresh()
def _on_add_game_button_clicked(self,button):
dialog = GameDialog(parent=self.get_root())
dialog.connect('response',self._on_game_dialog_response)
dialog.present()
def _on_new_steam_games_button_clicked(self,button):
dialog = NewSteamAppsDialog(parent=self.get_root())
dialog.connect('response',self._on_new_steamapps_dialog_response)
dialog.present()
def _on_backup_active_live_button_clicked(self,button):
backup_games = []
for i in range(self._liststore.get_n_items()):
game = self._liststore.get_item(i)
if game.is_live and game.is_active and os.path.exists(os.path.join(game.savegame_root,game.savegame_dir)):
backup_games.append(game)
# TODO:
#dialog = BackupManyDialog(parent=self.get_root(),games=backup_games)
#dialog.set_modal(False)
#dialog.present()
def _on_icon_column_setup(self,factory,item):
item.set_child(Gtk.Image())
image = Gtk.Image()
image.set_pixel_size(24)
item.set_child(image)
def _on_icon_column_bind(self,factory,item):
def transform_to_icon_name(_bidning,sgtype):
@ -145,11 +307,19 @@ class GameView(Gtk.ScrolledWindow):
return ""
icon = item.get_child()
game = item.get_item()
game.bind_property('savegame_type',icon,'icon_name',BindingFlags.SYNC_CREATE,transform_to_icon_name)
if not hasattr(game,'_savegame_type_to_icon_name_binding'):
game._savegame_type_to_icon_name_binding = game.bind_property('savegame_type',icon,'icon_name',BindingFlags.SYNC_CREATE,transform_to_icon_name)
def _on_icon_column_unbind(self,factory,item):
game = item.get_item()
if hasattr(game,'_savegame_type_to_icon_name_binding'):
game._savegame_type_to_icon_name_binding.unbind()
del game._savegame_type_to_icon_name_binding
def _on_key_column_setup(self,factory,item):
item.set_child(Gtk.Label())
label = Gtk.Label()
label.set_xalign(0.0)
item.set_child(label)
def _on_key_column_bind(self,factory,item):
label = item.get_child()
@ -157,12 +327,21 @@ class GameView(Gtk.ScrolledWindow):
game.bind_property('key',label,'label',BindingFlags.SYNC_CREATE)
def _on_name_column_setup(self,factory,item):
item.set_child(Gtk.Label())
label = Gtk.Label()
label.set_xalign(0.0)
label.set_use_markup(True)
item.set_child(label)
def _on_name_column_bind(self,factory,item):
label = item.get_child()
game = item.get_item()
game.bind_property('name',label,'label',BindingFlags.SYNC_CREATE)
if not hasattr(label,'_property_label_from_name_binding'):
label._property_label_from_name_binding = game.bind_property('name',
label,
'label',
BindingFlags.SYNC_CREATE,
lambda _binding,s: "<span weight='bold' size='large'>{}</span>".format(
GLib.markup_escape_text(s)))
def _on_active_column_setup(self,factory,item):
item.set_child(Gtk.Switch())
@ -179,8 +358,9 @@ class GameView(Gtk.ScrolledWindow):
del item._signal_active_state_set
def _on_active_state_set(self,switch,state,game):
game.is_active = state
game.is_active = switch.get_active()
game.save()
self.emit('game-active-changed',game)
def _on_live_column_setup(self,factory,item):
item.set_child(Gtk.Switch())
@ -189,7 +369,8 @@ class GameView(Gtk.ScrolledWindow):
switch = item.get_child()
game = item.get_item()
switch.set_active(game.is_live)
item._signal_live_state_set = switch.connect('state-set',self._on_live_state_set,game)
if not hasattr(item,'_signal_live_state_set'):
item._signal_live_state_set = switch.connect('state-set',self._on_live_state_set,game)
def _on_live_column_unbind(self,factory,item):
if hasattr(item,'_signal_live_state_set'):
@ -198,24 +379,25 @@ class GameView(Gtk.ScrolledWindow):
def _on_live_state_set(self,switch,state,game):
def on_dialog_response(dialog,response):
if response == Gtk.ResponseType.YES:
pass
#archiver.backup(game)
dialog.hide()
dialog.destroy()
if response == Gtk.ResponseType.YES:
dialog = BackupSingleDialog(parent=self.get_root(),game=game)
dialog.run()
game.is_live = switch.get_active()
game.save()
if not game.is_live:
dialog = Gtk.MessageDialog()
dialog = Gtk.MessageDialog(buttons=Gtk.ButtonsType.YES_NO)
dialog.set_transient_for(self.get_root())
dialog.props.buttons = Gtk.ButtonsType.YES_NO
dialog.props.text = "Do you want to create a new savegame for <i>{game}</i>?".format(game=game.name)
dialog.props.use_markup = True
dialog.props.secondary_text = "The new savegame is added to the finsihed savegames for the game."
dialog.props.secondary_use_markup = False
dialog.connect('response',on_dialog_response)
dialog.present()
self.emit('game-live-changed',game)
def _on_actions_column_setup(self,action,item):
child = Gtk.Box.new(Gtk.Orientation.HORIZONTAL,2)
@ -241,15 +423,39 @@ class GameView(Gtk.ScrolledWindow):
child = item.get_child()
game = item.get_item()
archiver_manager = ArchiverManager.get_global()
child.backup_button.connect('clicked',self._on_columnview_backup_button_clicked,item)
child.edit_button.connect('clicked',self._on_columnview_edit_button_clicked,item)
child.remove_button.connect('clicked',self._on_columnview_remove_button_clicked,item)
archiver_manager.bind_property('backup-in-progress',child.backup_button,'sensitive',
BindingFlags.SYNC_CREATE,lambda binding,x: False if x else True)
archiver_manager.bind_property('backup-in-progress',child.edit_button,'sensitive',
BindingFlags.SYNC_CREATE,lambda binding,x: False if x else True)
archiver_manager.bind_property('backup-in-progress',child.remove_button,'sensitive',
BindingFlags.SYNC_CREATE,lambda binding,x: False if x else True)
if not hasattr(child.backup_button,'_signal_clicked_connection'):
child.backup_button._signal_clicked_connection = child.backup_button.connect('clicked',self._on_columnview_backup_button_clicked,item)
if not hasattr(child.backup_button,'_property_backup_in_progress_binding'):
child.backup_button._property_backup_in_progress_binding = archiver_manager.bind_property('backup-in-progress',
child.backup_button,
'sensitive',
BindingFlags.SYNC_CREATE,
lambda binding,x: False if x else True)
if not hasattr(child.edit_button,'_signal_clicked_connection'):
child.edit_button._signal_clicked_connection = child.edit_button.connect('clicked',self._on_columnview_edit_button_clicked,item)
if not hasattr(child.edit_button,'_property_backup_in_progress_binding'):
child.edit_button._property_backup_in_progress_binding = archiver_manager.bind_property('backup-in-progress',
child.edit_button,
'sensitive',
BindingFlags.SYNC_CREATE,
lambda binding,x: False if x else True)
if not hasattr(child.remove_button,'_signal_clicked_connection'):
child.remove_button._signal_clicked_connection = child.remove_button.connect('clicked',self._on_columnview_remove_button_clicked,item)
if not hasattr(child.remove_button,'_property_backup_in_progress_binding'):
child.remove_button._property_backup_in_progress_binding = archiver_manager.bind_property('backup-in-progress',
child.remove_button,'sensitive',
BindingFlags.SYNC_CREATE,
lambda binding,x: False if x else True)
if os.path.exists(os.path.join(game.savegame_root,game.savegame_dir)):
child.backup_button.set_sensitive(True)
else:
child.backup_button.set_sensitive(False)
def _on_columnview_backup_button_clicked(self,button,item):
def on_dialog_response(dialog,response):
@ -361,7 +567,7 @@ class BackupViewData(GObject):
:type: bool
"""
pass
return self.__is_live
@Property(type=str)
def extension(self)->str:
@ -571,11 +777,34 @@ class AppWindow(Gtk.ApplicationWindow):
vbox.append(self.__vpaned)
statusbar = Gtk.Statusbar()
statusbar.set_hexpand(True)
statusbar.set_vexpand(False)
statusbar.push(0,'Running ...')
vbox.append(statusbar)
self.__statusbar = Gtk.Statusbar()
self.statusbar.set_hexpand(True)
self.statusbar.set_vexpand(False)
self.gameview.connect('refresh',self._on_gameview_refresh)
self.gameview.connect('game-active-changed',lambda gv,*data: self._on_gameview_refresh(gv))
self.gameview.connect('game-live-changed',lambda gv,*data: self._on_gameview_refresh(gv))
n_games = self.gameview._liststore.get_n_items()
n_live = 0
n_active = 0
n_finished = 0
for i in range(n_games):
game = self.gameview._liststore.get_item(i)
if game.is_live:
n_live += 1
else:
n_finished += 1
if game.is_active:
n_active += 1
self.statusbar.push(0,'{games} Games -- {active} Games active -- {live} Games live -- {finished} Games finished'.format(
games=n_games,
active=n_active,
live=n_live,
finished=n_finished))
vbox.append(self.statusbar)
self.set_child(vbox)
@ -609,6 +838,10 @@ class AppWindow(Gtk.ApplicationWindow):
"""
return self.__gameview
@property
def statusbar(self):
return self.__statusbar
def refresh(self):
"""
refresh Refresh the views of this window.
@ -617,6 +850,29 @@ class AppWindow(Gtk.ApplicationWindow):
self.gameview.refresh()
#self.backupview.refresh()
def _on_gameview_refresh(self,gameview):
self.statusbar.pop(0)
n_games = gameview._liststore.get_n_items()
n_active = 0
n_live = 0
n_finished = 0
for i in range(n_games):
game = gameview._liststore.get_item(i)
if game.is_live:
n_live += 1
else:
n_finished += 1
if game.is_active:
n_active += 1
self.statusbar.push(0,'{games} Games -- {active} Games active -- {live} Games live -- {finished} Games finished'.format(
games=n_games,
active=n_active,
live=n_live,
finished=n_finished))
class Application(Gtk.Application):
"""
Application The `Gtk.Application` for this app.

View File

@ -1025,9 +1025,9 @@ class GameDialog(Gtk.Dialog):
self.__game_linux = None
if self.get_is_valid_savegame_type(SavegameType.MACOS):
data = get_game_data(self.__linux)
binary = self.__linux.binary_entry.get_text()
if self.__game.linux:
data = get_game_data(self.__macos)
binary = self.__macos.binary_entry.get_text()
if self.__game.macos:
mg = self.__game.macos
mg.savegame_root = data['sgroot']
mg.savegame_dir = data['sgdir']
@ -1187,7 +1187,8 @@ class GameDialog(Gtk.Dialog):
def _on_variable_name_bind(self,factory,item):
label = item.get_child()
data = item.get_item()
data.bind_property('name',label,'label',BindingFlags.SYNC_CREATE)
if not hasattr(label,'_property_data_to_label_binding'):
label._property_data_to_label_binding = data.bind_property('name',label,'label',BindingFlags.SYNC_CREATE)
def _on_variable_value_setup(self,factory,item):
label = Gtk.Label()
@ -1196,7 +1197,8 @@ class GameDialog(Gtk.Dialog):
def _on_variable_value_bind(self,factory,item):
label = item.get_child()
data = item.get_item()
data.bind_property('value',label,'label',BindingFlags.SYNC_CREATE)
if not hasattr(label,'_property_value_to_label_binding'):
label._property_value_to_label_binding = data.bind_property('value',label,'label',BindingFlags.SYNC_CREATE)
def _on_filematch_dropdown_selection_changed(self,dropdown,data,item):
data = item.get_item()
@ -1221,7 +1223,8 @@ class GameDialog(Gtk.Dialog):
if (data.match_type == self.__filematch_dropdown_model.get_item(i).match_type):
dropdown.set_selected(i)
break
dropdown.connect('notify::selected-item',self._on_filematch_dropdown_selection_changed,item)
if not hasattr(dropdown,'_signal_notify_selected_item_connector'):
dropdown._signal_notify_selected_item_connector = dropdown.connect('notify::selected-item',self._on_filematch_dropdown_selection_changed,item)
def _on_filematch_value_setup(self,factory,item,widget):
label = Gtk.EditableLabel()
@ -1232,11 +1235,13 @@ class GameDialog(Gtk.Dialog):
data = item.get_item()
if (data.match_file):
label.set_text(data.match_file)
label.bind_property('text',data,'match_file',BindingFlags.DEFAULT)
label.connect('notify::editing',self._on_filematch_value_notify_editing,widget)
else:
label.bind_property('text',data,'match_file',BindingFlags.DEFAULT)
label.connect('notify::editing',self._on_filematch_value_notify_editing,widget)
if not hasattr(label,'_property_text_to_matchfile_binding'):
label._property_text_to_matchfile_binding = label.bind_property('text',data,'match_file',BindingFlags.DEFAULT)
if not hasattr(label,'_signal_notify_editing_connector'):
label._signal_notify_editing_connector = label.connect('notify::editing',self._on_filematch_value_notify_editing,widget)
if not label.get_text():
label.grab_focus()
label.start_editing()
@ -1293,23 +1298,20 @@ class GameDialog(Gtk.Dialog):
if not label.get_text().strip():
model = widget.columnview.get_model().get_model()
i = 0
while i < model.get_n_items():
for i in reversed(range(model.get_n_items())):
item = model.get_item(i)
if not item.match_file.strip():
model.remove(i)
continue
i += 1
def _on_filematch_value_notify_editing(self,label,param,widget):
if label.props.editing == False:
if not label.get_text().strip():
model = widget.columnview.get_model().get_model()
i = 0
while i < model.get_n_items():
for i in reversed(range(model.get_n_items())):
item = model.get_item(i)
if not item.match_file.strip():
model.remove(i)
continue
i += 1
def _on_windows_regkey_add_button_clicked(self,button,widget):
widget.listview.get_model().get_model().append(RegistryKeyData())

View File

@ -17,7 +17,7 @@
###############################################################################
from gi.repository import Gtk,GLib,Gio
from gi.repository.GObject import GObject,Signal,Property,SignalFlags
from gi.repository.GObject import GObject,Signal,Property,SignalFlags,BindingFlags
from ..settings import settings
from ..archiver import ArchiverManager,Archiver
@ -65,6 +65,38 @@ class ZipfileCompressorDataSorter(Gtk.Sorter):
return Gtk.Ordering.EQUAL
class VariableData(GObject):
def __init__(self,name:str,value:str):
GObject.__init__(self)
self.__name = name
self.__value = value
@Property(type=str)
def name(self)->str:
return self.__name
@name.setter
def name(self,name:str):
self.__name = name
@Property(type=str)
def value(self)->str:
return self.__value
@value.setter
def value(self,value:str):
self.__value = value
class VariableDataSorter(Gtk.Sorter):
def do_compare(self,item1,item2):
if (item1.name < item2.name):
return Gtk.Ordering.SMALLER
elif (item1.name > item2.name):
return Gtk.Ordering.LARGER
else:
return Gtk.Ordering.EQUAL
class SettingsDialog(Gtk.Dialog):
def __init__(self,parent=None):
Gtk.Dialog.__init__(self)
@ -80,6 +112,7 @@ class SettingsDialog(Gtk.Dialog):
self.__stack_sidebar = Gtk.StackSidebar.new()
self.__general_page = self.__add_general_settings_page()
self.__archiver_page = self.__add_archiver_settings_page()
self.__variables_page = self.__add_variables_settings_page()
sidebar_scrolled=Gtk.ScrolledWindow()
sidebar_scrolled.set_child(self.__stack_sidebar)
@ -90,7 +123,6 @@ class SettingsDialog(Gtk.Dialog):
paned.set_vexpand(True)
self.__stack_sidebar.set_stack(self.__stack)
vbox.append(paned)
self.add_button("Apply",Gtk.ResponseType.APPLY)
@ -157,7 +189,6 @@ class SettingsDialog(Gtk.Dialog):
grid.attach(page.archiver_dropdown,1,3,2,1)
vbox.append(grid)
page.set_child(vbox)
@ -212,6 +243,99 @@ class SettingsDialog(Gtk.Dialog):
self.add_page(page,"zipfile","Archiver Settings")
return page
def _on_variable_add_button_clicked(self,button):
variable_model = self.__variables_page.variable_columnview.get_model()
while hasattr(variable_model,'get_model'):
variable_model = variable_model.get_model()
variable_model.append(VariableData("",""))
def __add_variables_settings_page(self):
page = Gtk.Box.new(Gtk.Orientation.VERTICAL,0)
actions = Gtk.ActionBar()
icon=Gtk.Image.new_from_icon_name('list-add-symbolic')
button = Gtk.Button()
button.set_child(icon)
button.connect('clicked',self._on_variable_add_button_clicked)
actions.pack_end(button)
page.append(actions)
scrolled = Gtk.ScrolledWindow()
model = Gio.ListStore.new(VariableData)
for vname,vvalue in settings.variables.items():
model.append(VariableData(vname,vvalue))
sorted_model = Gtk.SortListModel.new(model,VariableDataSorter())
vname_factory = Gtk.SignalListItemFactory()
vname_factory.connect('setup',self._on_variable_name_factory_setup)
vname_factory.connect('bind',self._on_variable_name_factory_bind)
vvalue_factory = Gtk.SignalListItemFactory()
vvalue_factory.connect('setup',self._on_variable_value_factory_setup)
vvalue_factory.connect('bind',self._on_variable_value_factory_bind)
selection = Gtk.SingleSelection(model=sorted_model)
page.variable_columnview = Gtk.ColumnView.new(selection)
vname_column = Gtk.ColumnViewColumn.new("Name",vname_factory)
vname_column.set_expand(True)
page.variable_columnview.append_column(vname_column)
vvalue_column = Gtk.ColumnViewColumn.new("Value",vvalue_factory)
page.variable_columnview.append_column(vvalue_column)
page.variable_columnview.set_vexpand(True)
scrolled.set_child(page.variable_columnview)
scrolled.set_hexpand(True)
page.append(scrolled)
self.add_page(page,"variables","Variables")
return page
def _on_variable_name_notify_editing(self,label,param,*data):
if label.props.editing == False:
if not label.get_text():
model = self.__variables_page.variable_columnview.get_model()
while hasattr(model,'get_model'):
model = model.get_model()
for i in reversed(range(model.get_n_items())):
if not model.get_item(i).name:
model.remove(i)
def _on_variable_name_factory_setup(self,factory,item):
label = Gtk.EditableLabel()
item.set_child(label)
def _on_variable_name_factory_bind(self,factory,item):
data = item.get_item()
label = item.get_child()
label.set_text(data.name)
if not hasattr(label,'_property_text_to_name_binding'):
label._property_text_to_name_binding = label.bind_property('text',data,'name',BindingFlags.DEFAULT)
if not hasattr(label,'_signal_notify_editing_connection'):
label._signal_notify_editing_connection = label.connect('notify::editing',self._on_variable_name_notify_editing)
if not data.name:
label.grab_focus()
label.start_editing()
def _on_variable_value_factory_setup(self,factory,item):
label = Gtk.EditableLabel()
item.set_child(label)
def _on_variable_value_factory_bind(self,factory,item):
label = item.get_child()
data = item.get_item()
label.set_text(data.value)
if not hasattr(label,'_property_text_to_value_binding'):
label._property_text_to_value_binding = label.bind_property('text',data,'name',BindingFlags.DEFAULT)
def _on_archiver_factory_setup(self,factory,item):
label = Gtk.Label()
item.set_child(label)
@ -277,4 +401,13 @@ class SettingsDialog(Gtk.Dialog):
settings.zipfile_compression = self.archiver_page.zf_compressor_dropdown.get_selected_item().compressor
settings.zipfile_compresslevel = self.archiver_page.zf_compresslevel_spinbutton.get_value_as_int()
variables = {}
variable_model = self.__variables_page.variable_columnview.get_model()
while hasattr(variable_model,'get_model'):
variable_model = variable_model.get_model()
for i in range(variable_model.get_n_items()):
vdata = variable_model.get_item(i)
if vdata.name:
variables[vdata.name] = vdata.value
settings.variables = variables

View File

@ -223,6 +223,7 @@ class NewSteamAppsDialog(Gtk.Dialog):
self.__listview = Gtk.ListView.new(selection,factory)
self.__listview.set_vexpand(True)
self.__listview.set_show_separators(True)
self.__listview.set_single_click_activate(True)
scrolled = Gtk.ScrolledWindow()
scrolled.set_child(self.__listview)
@ -286,8 +287,10 @@ class NewSteamAppsDialog(Gtk.Dialog):
child.name_label.set_markup("<span weight='bold' size='large'>{}</span>".format(GLib.markup_escape_text(data.name)))
child.appid_label.set_text(str(data.appid))
child.installdir_label.set_text(data.installdir)
child.add_app_button.connect('clicked',self._on_add_steamapp_button_clicked,data)
child.ignore_app_button.connect('clicked',self._on_ignore_steamapp_button_clicked,data)
if not hasattr(child.add_app_button,'_signal_clicked_connector'):
child.add_app_button._signal_clicked_connector = child.add_app_button.connect('clicked',self._on_add_steamapp_button_clicked,data)
if not hasattr(child.ignore_app_button,'_signal_clicked_connector'):
child.ignore_app_button._signal_clicked_connector = child.ignore_app_button.connect('clicked',self._on_ignore_steamapp_button_clicked,data)
def _on_add_steamapp_button_clicked(self,button,data:SteamApp,*args):
def on_dialog_response(dialog,response):

View File

@ -14,12 +14,12 @@
<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>
<attribute name='label' translatable='true'>New Steam Apps</attribute>
<attribute name='action'>app.steam-new-apps</attribute>
</item>
<item>
<attribute name='label' translatable='true'>Manage new apps</attribute>
<attribute name='action'>app.steam-new-apps</attribute>
<attribute name='label' translatable='true'>Manage Steam Libraries</attribute>
<attribute name='action'>app.steam-manage-libraries</attribute>
</item>
</section>
</submenu>

View File

@ -396,7 +396,10 @@ class Settings(GObject.GObject):
return self.get_string('variables',name,"")
def get_variables(self)->dict[str:str]:
ret = dict(os.environ)
if PLATFORM_WINDOWS:
ret = dict(((name.upper(),value) for name,value in os.environ.items()))
else:
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),