diff options
| -rw-r--r-- | README.md | 4 | ||||
| -rw-r--r-- | src/book_flow.py | 122 | ||||
| -rw-r--r-- | src/book_form.py | 6 | ||||
| -rw-r--r-- | src/filters.py | 40 | ||||
| -rw-r--r-- | src/main_window.py | 46 |
5 files changed, 134 insertions, 84 deletions
@@ -18,6 +18,4 @@ pytest # Improvements -- filters: - - textual search - https://stackoverflow.com/questions/55828169/how-to-filter-gtk-flowbox-children-with-gtk-entrysearch +- filters: textual search diff --git a/src/book_flow.py b/src/book_flow.py index 9698aab..bfd7114 100644 --- a/src/book_flow.py +++ b/src/book_flow.py @@ -24,9 +24,10 @@ class BookFlow(Gtk.ScrolledWindow): Gtk.ScrolledWindow.__init__(self) self.set_vexpand(True) - self._flow_box = Gtk.FlowBox() - self.set_child(self._flow_box) + self._flowbox = Gtk.FlowBox() + self.set_child(self._flowbox) + self._books = books self._window = window self._resources = resources self._library = library @@ -34,41 +35,82 @@ class BookFlow(Gtk.ScrolledWindow): self._conn = conn self._msg = msg self._picture_cache = PictureCache() + self._flowbox_children = {} - self.reset(books, progress, genre) + self.update_filters(progress, genre) + self._flowbox.set_sort_func(self._sort_books) + for book_id, data in books.items(): + self.add(book_id, data) + + def get(self): + return self._books def select_book(self, book_id): - if book_id in self._flow_box_children: - self._flow_box.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._flow_box.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._flow_box.append(flow_box_child) + if book_id in self._flowbox_children: + self._flowbox.select_child(self._flowbox_children[book_id]) + + def update_filters(self, progress, genre): + def f(flow_box_child): + book_id = flow_box_child.get_name() + data = self._books[book_id] + return self._is_selected(data, progress, genre) + + self._flowbox.set_filter_func(f) + + def add(self, book_id, data): + self._books[book_id] = data + + 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) + flow_box_child.set_name(book_id) + self._flowbox_children[book_id] = flow_box_child + self._flowbox.append(flow_box_child) + + def remove(self, book_id): + del self._books[book_id] + self._flowbox.remove(self._flowbox_children[book_id]) + del self._flowbox_children[book_id] + self._picture_cache.invalidate(f'{self._library}/{book_id}/cover-min.png') # Private + def _sort_books(self, child1, child2): + book_id1 = child1.get_name() + book_id2 = child2.get_name() + data1 = self._books[book_id1] + data2 = self._books[book_id2] + + author1 = author_key(data1) + author2 = author_key(data2) + + if author1 < author2: + return -1 + elif author1 > author2: + return 1 + + year1 = year_key(data1) + year2 = year_key(data2) + + if year1 < year2: + return -1 + elif year1 > year2: + return 1 + + return 0 + def _is_selected(self, data, progress, genre): if data['progress'] != progress: return False @@ -115,7 +157,7 @@ class BookFlow(Gtk.ScrolledWindow): 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() + BookForm(self._window, self._resources, self._library, self._conn, 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() @@ -128,14 +170,16 @@ class BookFlow(Gtk.ScrolledWindow): 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 author.split()[-1].lower() return '' + +def year_key(data): + if 'year' in data: + try: + return int(data['year']) + except Exception: + return 0 + return 0 diff --git a/src/book_form.py b/src/book_form.py index ed1c938..5968592 100644 --- a/src/book_form.py +++ b/src/book_form.py @@ -13,7 +13,7 @@ import src.str_format as str_format class BookForm(Gtk.Window): - def __init__(self, parent_window, resources, library, conn, init_progress, msg, book = None): + def __init__(self, parent_window, resources, library, conn, msg, book = None): Gtk.Window.__init__(self) self._book = book @@ -49,7 +49,7 @@ class BookForm(Gtk.Window): top_form.append(year_lang_progress) self._year = labeled_entry(year_lang_progress, 'Année') self._lang = dropdown(year_lang_progress, 'Langue', models.langs) - self._progress = dropdown(year_lang_progress, 'Progrès', models.all_progress, init_progress) + self._progress = dropdown(year_lang_progress, 'Progrès', models.all_progress) # Authors, genres authors_genres = Gtk.Grid() @@ -90,6 +90,8 @@ class BookForm(Gtk.Window): update_entry(self._year, str(data['year'])) if 'lang' in data: self._lang.set_selected(models.langs.index(data['lang'])) + if 'progress' in data: + self._progress.set_selected(models.all_progress.index(data['progress'])) for author in data['authors']: self._authors.add_entry(author) for genre in data['genres']: diff --git a/src/filters.py b/src/filters.py index e81c3cf..ed3cb06 100644 --- a/src/filters.py +++ b/src/filters.py @@ -6,43 +6,59 @@ import src.models as models class Filters(Gtk.Box): - def __init__(self, init_books, progress, genres, genre, msg): + def __init__(self, init_books, init_progress, init_genre, msg): Gtk.Box.__init__(self, spacing=10) + genres = models.get_genres(init_books) + self._progress = init_progress + self._genre = init_genre self._msg = msg self._progress_dropdown = Gtk.DropDown.new_from_strings(models.all_progress) - self._progress_dropdown.set_selected(models.all_progress.index(progress)) + self._progress_dropdown.set_selected(models.all_progress.index(self._progress)) self._progress_dropdown.connect('notify::selected-item', self._on_selected_progress) self.append(self._progress_dropdown) - self._genres_dropdown = self._get_genres_dropdown(genres, genre) + self._genres_dropdown = self._get_genres_dropdown(genres) self.append(self._genres_dropdown) + def get_progress(self): + return self._progress + + def get_genre(self): + return self._genre + + def set_genre(self, genre): + self._genre = genre + def select_progress(self, progress): + self._progress = progress self._progress_dropdown.set_selected(models.all_progress.index(progress)) # Hacky, this replaces the dropdown by a new one - def actualize_genres(self, genres, genre): + def actualize_genres(self, books): + genres = models.get_genres(books) + self._genre = self._genre if self._genre in genres else models.all_genres + if self._last_installed_genres != genres: - new_dropdown = self._get_genres_dropdown(genres, genre) + new_dropdown = self._get_genres_dropdown(genres) self.insert_child_after(new_dropdown, self._genres_dropdown) self.remove(self._genres_dropdown) self._genres_dropdown = new_dropdown else: - self._genres_dropdown.set_selected(genres.index(genre)) + self._genres_dropdown.set_selected(genres.index(self._genre)) - def _get_genres_dropdown(self, genres, genre): + def _get_genres_dropdown(self, genres): self._last_installed_genres = genres dropdown = Gtk.DropDown.new_from_strings(genres) - dropdown.set_selected(genres.index(genre)) + dropdown.set_selected(genres.index(self._genre)) dropdown.connect('notify::selected-item', self._on_selected_genre) return dropdown def _on_selected_progress(self, dropdown, _data): - progress = dropdown.get_selected_item().get_string() - self._msg(['progress-selected', progress]) + self._progress = dropdown.get_selected_item().get_string() + self._msg(['progress-selected', self._progress]) def _on_selected_genre(self, dropdown, _data): - genre = dropdown.get_selected_item().get_string() - self._msg(['genre-selected', genre]) + self._genre = dropdown.get_selected_item().get_string() + self._msg(['genre-selected', self._genre]) diff --git a/src/main_window.py b/src/main_window.py index 5053a81..c01c120 100644 --- a/src/main_window.py +++ b/src/main_window.py @@ -18,51 +18,41 @@ class MainWindow(Gtk.ApplicationWindow): utils.set_header_bar(self, 'Books') - # State - self._books = db.get_books(conn) - self._progress = 'Reading' - self._genres = models.get_genres(self._books) - self._genre = models.all_genres + init_books = db.get_books(conn) + init_progress = 'Reading' + init_genre = models.all_genres add_book_button = Gtk.Button(label='Ajouter un livre') - add_book_button.connect('clicked', lambda _: BookForm(self, resources, library, conn, self._progress, self._msg).present()) + add_book_button.connect('clicked', lambda _: BookForm(self, resources, library, conn, self._msg).present()) header = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) utils.set_margin(header, 20) - self._filters = Filters(self._books, self._progress, self._genres, self._genre, self._msg) + self._filters = Filters(init_books, init_progress, init_genre, self._msg) self._filters.set_hexpand(True) header.append(self._filters) header.append(add_book_button) box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0) box.append(header) - self._book_flow = BookFlow(self, resources, library, ereader, conn, self._books, self._progress, self._genre, self._msg) - box.append(self._book_flow) + self._books = BookFlow(self, resources, library, ereader, conn, init_books, init_progress, init_genre, self._msg) + box.append(self._books) self.set_child(box) def _msg(self, msg): match msg: case ['progress-selected', progress]: - self._progress = progress - self._book_flow.reset(self._books, self._progress, self._genre) + self._books.update_filters(self._filters.get_progress(), self._filters.get_genre()) case ['genre-selected', genre]: - self._genre = genre - self._book_flow.reset(self._books, self._progress, self._genre) + self._books.update_filters(self._filters.get_progress(), self._filters.get_genre()) case ['book-saved', book_id, data]: - self._books[book_id] = data - self._progress = data['progress'] self._filters.select_progress(data['progress']) - if not self._genre in data['genres']: - self._genre = models.all_genres - self._actualize_genres() - self._book_flow.reset(self._books, self._progress, self._genre, book_id) - self._book_flow.select_book(book_id) + if not self._filters.get_genre() in data['genres']: + self._filters.set_genre(models.all_genres) + self._filters.actualize_genres(self._books.get()) + if book_id in self._books.get(): + self._books.remove(book_id) + self._books.add(book_id, data) + self._books.select_book(book_id) case ['book-deleted', book_id, data]: - del self._books[book_id] - self._actualize_genres() - self._book_flow.reset(self._books, self._progress, self._genre) - - def _actualize_genres(self): - self._genres = models.get_genres(self._books) - self._genre = self._genre if self._genre in self._genres else models.all_genres - self._filters.actualize_genres(self._genres, self._genre) + self._filters.actualize_genres(self._books.get()) + self._books.remove(book_id) |
