aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--src/book_flow.py122
-rw-r--r--src/book_form.py6
-rw-r--r--src/filters.py40
-rw-r--r--src/main_window.py46
5 files changed, 134 insertions, 84 deletions
diff --git a/README.md b/README.md
index bde805b..04bdb2a 100644
--- a/README.md
+++ b/README.md
@@ -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)