import gi gi.require_version('Gtk', '4.0') from gi.repository import Gtk, Gio, GLib import pathlib import os import subprocess import logging import src.utils as utils logger = logging.getLogger(__name__) class BookEntries(Gtk.Box): def __init__(self, window): Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=10) self._window = window self._books = {} # Dict {path: name} header = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) header.append(get_label('Books')) add_button = Gtk.Button(label='+') add_button.connect('clicked', lambda _: self._open_dialog()) header.append(add_button) self.append(header) self._entries = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) self.append(self._entries) self._setup_filedialog() def get_books(self): return self._books def _setup_filedialog(self): self._filedialog = Gtk.FileDialog.new() self._filedialog.set_title('Select a book') f = Gtk.FileFilter() f.set_name('Book files') f.add_mime_type('application/epub+zip') f.add_mime_type('application/vnd.amazon.ebook') filters = Gio.ListStore.new(Gtk.FileFilter) filters.append(f) self._filedialog.set_filters(filters) self._filedialog.set_default_filter(f) def _open_dialog(self): self._filedialog.open(self._window, None, self._open_dialog_callback) def _open_dialog_callback(self, dialog, result): try: file = dialog.open_finish(result) if file is not None: # https://github.com/GNOME/glib/blob/main/gio/glocalfile.c path = pathlib.Path(file.get_path()) self.add_book(path) except GLib.Error as error: logger.error(f'Error opening file: %s', error.message) def add_book(self, path): name = os.path.splitext(os.path.basename(path))[0] self._books[path] = name line = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10) entry = Gtk.Entry() entry.set_text(name) entry.set_hexpand(True) entry.connect('changed', self._update_book, path) line.append(entry) line.append(open_book_button(path)) remove_button = Gtk.Button(label='-') remove_button.connect('clicked', lambda _: self._remove_book(line, path)) line.append(remove_button) self._entries.append(line) def _update_book(self, entry, path): self._books[path] = entry.get_text() def _remove_book(self, line, path): del self._books[path] self._entries.remove(line) def get_label(text): label = Gtk.Label() label.set_text(text) return label def open_book_button(path): open_button = Gtk.Button(label='Ouvrir') open_button.connect('clicked', lambda _: open_book(path)) return open_button def open_book(path): subprocess.run(['xdg-open', path])