import gi gi.require_version("Gtk", "4.0") from gi.repository import Gtk, Gio import glob import shutil import functools import os import subprocess import src.utils as utils import src.db as db import src.models as models from src.book_detail import BookDetail from src.book_delete import BookDelete from src.book_form import BookForm from src.book_transfer import BookTransfer from src.picture_cache import PictureCache import src.book_files as book_files class BookFlow(Gtk.FlowBox): def __init__(self, window, resources, library, ereader, conn, books, progress, genre, msg): Gtk.FlowBox.__init__(self) self._window = window self._resources = resources self._library = library self._ereader = ereader self._conn = conn self._msg = msg self._picture_cache = PictureCache() self.reset(books, progress, genre) def select_book(self, book_id): if book_id in self._flow_box_children: self.select_child(self._flow_box_children[book_id]) def reset(self, books, progress, genre, book_id=None): if book_id: self._picture_cache.invalidate(f'{self._library}/{book_id}/cover-min.png') self.remove_all() self._flow_box_children = {} for book_id, data in sorted(books.items(), key=book_sort): if self._is_selected(data, progress, genre): picture = self._picture_cache.get(f'{self._library}/{book_id}/cover-min.png') picture.set_can_shrink(False) utils.set_margin(picture, 10) gesture_lclick = Gtk.GestureClick() gesture_lclick.connect('released', self._on_left_click, book_id, data) picture.add_controller(gesture_lclick) gesture_rclick = Gtk.GestureClick() gesture_rclick.set_button(3) gesture_rclick.connect('released', self._on_right_click, picture, book_id, data) picture.add_controller(gesture_rclick) flow_box_child = Gtk.FlowBoxChild() flow_box_child.set_child(picture) self._flow_box_children[book_id] = flow_box_child self.append(flow_box_child) # Private def _is_selected(self, data, progress, genre): if data['progress'] != progress: return False if genre == models.all_genres: return True if genre == models.no_genre: return len(data['genres']) == 0 return genre in data['genres'] def _on_left_click(self, gesture, n_press, x, y, book_id, data): if n_press == 2: self._open_detail(book_id, data) def _on_right_click(self, gesture, n_press, x, y, picture, book_id, data): if n_press == 1: popover = Gtk.Popover() popover.set_parent(picture) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5) popover.set_child(box) see_button = Gtk.Button(label='Voir') see_button.connect('clicked', lambda _: self._open_detail(book_id, data)) box.append(see_button) update_button = Gtk.Button(label='Modifier') update_button.connect('clicked', lambda _: self._update_book(book_id, data)) box.append(update_button) delete_button = Gtk.Button(label='Supprimer') delete_button.connect('clicked', lambda _: self._confirm_delete_book(book_id, data)) box.append(delete_button) if self._ereader and os.path.exists(self._ereader): paths = book_files.get(self._library, book_id) if paths: transfer_button = Gtk.Button(label='Transférer') transfer_button.connect('clicked', lambda _: self._transfer_book(book_id, data, paths)) box.append(transfer_button) popover.popup() def _open_detail(self, book_id, data): BookDetail(self._window, self._library, book_id, data).present() def _update_book(self, book_id, data): book = {'id': book_id, 'data': data } BookForm(self._window, self._resources, self._library, self._conn, data['progress'], self._msg, book).present() def _confirm_delete_book(self, book_id, data): BookDelete(self._window, self._library, book_id, data, lambda: self._delete_book(book_id, data)).present() def _delete_book(self, book_id, data): db.delete_book(self._conn, book_id) shutil.rmtree(f'{self._library}/{book_id}', ignore_errors=True) self._msg(['book-deleted', book_id, data]) def _transfer_book(self, book_id, data, paths): BookTransfer(self._window, self._ereader, book_id, data, paths).present() def book_sort(b): key, data = b author = author_key(data) year = data['year'] if 'year' in data else '' return f'{author}{year}' def author_key(data): match data['authors']: case [author, *_]: return author.split()[-1] return ''