diff options
Diffstat (limited to 'gamechest/__init__.py')
-rw-r--r-- | gamechest/__init__.py | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/gamechest/__init__.py b/gamechest/__init__.py new file mode 100644 index 0000000..8629624 --- /dev/null +++ b/gamechest/__init__.py @@ -0,0 +1,217 @@ +#!python3 + +''' +Usage: gamechest.py --gamelist=GAMELIST.YAML --gamedir=GAMEDIR +''' + +import logging +import os +from logging import debug, info, warning, critical + + +import docopt +import yaml +import gi +from . import gamemanager + + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk as gtk, GLib as glib, GdkPixbuf as gdkpixbuf +from gi.repository.GdkPixbuf import Pixbuf + + +class GameList: + + def __init__(self, gamelist, gamedir): + debug(f'managing gamedir {gamedir}') + debug(f'reading gamelist from {gamelist}') + with open(gamelist) as stream: + self.yaml_data = yaml.safe_load(stream) + self.gamedir = gamedir + debug('loaded data: %d bytes', len(self.yaml_data)) + + +class Handler: + + def __init__(self, builder, gamelist, gamelist_dir, gamedir): + self.builder = builder + self.gamelist = gamelist + self.gamelist_dir = gamelist_dir + self.gamedir = gamedir + repository_host = gamelist.yaml_data['repository']['host'] + repository_path = gamelist.yaml_data['repository']['path'] + self.game_installer = gamemanager.GameInstaller( + repository_host, repository_path, gamedir) + self.game_remover = gamemanager.GameRemover( + repository_host, repository_path, gamedir) + self.game_status = gamemanager.GameStatus( + repository_host, repository_path, gamedir) + + self.game_title = builder.get_object('game_title') + self.game_image = builder.get_object('game_image') + self.game_characteristics = builder.get_object('game_characteristics') + self.game_description = builder.get_object('game_description') + self.btn_install = builder.get_object('btn_install') + self.btn_update = builder.get_object('btn_update') + self.btn_remove = builder.get_object('btn_remove') + self.game_install_stop_btn = builder.get_object('game_install_stop_btn') + self.game_install_progress = builder.get_object('game_install_progress') + self.global_progression = builder.get_object('global_progression') + + self.game_install_timeout_id = None + self.current_selected_game = None + self.game_image_pixbuf = None + + def on_destroy(self, *args): + gtk.main_quit() + + def on_quit_clicked(self, *args): + print('quit') + gtk.main_quit() + + def gamelist_on_changed(self, selection, *args): + model, treeiter = selection.get_selected() + if treeiter is None: + return + index = model[treeiter][2] + #print("You selected", self.gamelist['games'][model[treeiter][2]]) + debug('selected index: %d', index) + game_item = self.gamelist.yaml_data['games'][index] + self.current_selected_game = game_item + info("You selected (title): %s", game_item['title']) + + self.game_title.set_label(game_item['title']) + if image := game_item.get('image', None): + image_path = f'{self.gamelist_dir}/{image}' + debug('image path: %s', image_path) + if os.path.exists(image_path): + #self.game_image.set_from_file(image_path) + self.game_image_pixbuf = Pixbuf.new_from_file(image_path) + self.game_image_draw() + self.game_characteristics.set_text( + game_item.get('characteristics', 'Unfilled characteristics')) + description = game_item.get('description', 'No description') + self.game_description.set_text(description) + + if self.game_status.exists(game_item['name']): + debug('game status exists') + self.btn_install.hide() + self.btn_update.show() + self.btn_remove.show() + else: + debug('game status does not exist') + + def game_image_on_draw(self, widget, cr, *args): + self.game_image_draw() + + def game_image_draw(self): + if not self.game_image_pixbuf: + return + + orig_width = self.game_image_pixbuf.get_width() + orig_height = self.game_image_pixbuf.get_height() + dest_width = self.game_image.get_allocated_width() + dest_height = self.game_image.get_allocated_height() + ratio_width = dest_width / orig_width + ratio_height = dest_height / orig_height + ratio = min(ratio_width, ratio_height) + + #width, height = self.game_image.get_allocated_size() + pixbuftmp = self.game_image_pixbuf.scale_simple( + orig_width*ratio, + orig_height*ratio, + gdkpixbuf.InterpType.BILINEAR) + self.game_image.set_from_pixbuf(pixbuftmp) + + def on_draw(self, widget, cr, data): + context = widget.get_style_context() + + width = widget.get_allocated_width() + height = widget.get_allocated_height() + Gtk.render_background(context, cr, 0, 0, width, height) + + r, g, b, a = data["color"] + cr.set_source_rgba(r, g, b, a) + cr.rectangle(0, 0, width, height) + cr.fill() + + ############################################################ + # install management + ############################################################ + + def game_install_on_clicked(self, *args): + if not self.current_selected_game: + return + + self.game_install_timeout_id = \ + glib.timeout_add(250, self.game_install_on_timeout, None) + self.game_install_stop_btn.show() + + game_item = self.current_selected_game + self.game_installer.start(game_item) + # set progress bar to 0.0001 in order to update them the first time on + # timeout (most useful for global advance) + self.global_progression.set_fraction(0.0001) + self.game_install_progress.set_fraction(0.0001) + + def game_install_stop(self): + if not self.game_install_timeout_id: + return + glib.source_remove(self.game_install_timeout_id) + self.game_install_timeout_id = None + self.game_installer.stop() + #self.game_install_progress.set_fraction(1) + self.game_install_stop_btn.hide() + + def game_installstop_on_clicked(self, *args): + self.game_install_stop() + + def game_install_on_timeout(self, *args): + status, progress1, progress2 = self.game_installer.poll() + #print(f'status {status} progress1 {progress1} progress2 {progress2}') + old_progress1 = self.global_progression.get_fraction() + if (progress1/100) != old_progress1: + self.global_progression.set_fraction(progress1/100) + self.global_progression.set_text(f'global {progress1:.2f}%') + old_progress2 = self.game_install_progress.get_fraction() + if (progress2/100) != old_progress2: + self.game_install_progress.set_fraction(progress2/100) + self.game_install_progress.set_text(f'step {progress2:.2f}%') + # returning False value means stop timer + if status == self.game_installer.State.ONGOING: + return True + self.game_install_stop() + return False + + +def main(): + logging.basicConfig(level=logging.DEBUG) + logging.getLogger().handlers[0].setFormatter(logging.Formatter( + "gamechest: %(levelname)s: %(funcName)s:%(lineno)s: %(message)s")) + + args = docopt.docopt(__doc__) + debug('args: %s', args) + + gamelist_dir = ( + os.path.dirname(args['--gamelist']) + + '/.' + + os.path.basename(args['--gamelist']) + + '.d' + ) + gamelist = GameList(args['--gamelist'], args['--gamedir']) + + builder = gtk.Builder() + builder.add_from_file('gamechest.glade') + builder.connect_signals( + Handler(builder, gamelist, gamelist_dir, args['--gamedir'])) + + window = builder.get_object('window2') + window.show_all() + + gamelist_store = builder.get_object('gamelist_store') + gamelist_store.clear() + for index, game in enumerate(gamelist.yaml_data['games']): + gamelist_store.append((False, game['title'], index)) + info('%d games loaded', len(gamelist.yaml_data['games'])) + + gtk.main() |