[go: up one dir, main page]

File: search_view.py

package info (click to toggle)
cozy 1.3.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,140 kB
  • sloc: python: 8,014; xml: 392; makefile: 2
file content (120 lines) | stat: -rw-r--r-- 4,223 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import threading
from typing import Callable, Sequence

from gi.repository import Adw, Gtk

import inject
from cozy.model.book import Book
from cozy.ui.headerbar import Headerbar
from cozy.ui.widgets.book_row import BookRow
from cozy.ui.widgets.search_results import ArtistResultRow
from cozy.view_model.search_view_model import SearchViewModel


@Gtk.Template.from_resource("/com/github/geigi/cozy/search_page.ui")
class SearchView(Adw.Bin):
    __gtype_name__ = "SearchView"

    stack: Gtk.Stack = Gtk.Template.Child()
    search_scroller: Gtk.ScrolledWindow = Gtk.Template.Child()
    start_searching_page: Adw.StatusPage = Gtk.Template.Child()
    nothing_found_page: Adw.StatusPage = Gtk.Template.Child()

    book_result_box: Adw.PreferencesGroup = Gtk.Template.Child()
    author_result_box: Adw.PreferencesGroup = Gtk.Template.Child()
    reader_result_box: Adw.PreferencesGroup = Gtk.Template.Child()

    book_result_list: Gtk.ListBox = Gtk.Template.Child()
    author_result_list: Gtk.ListBox = Gtk.Template.Child()
    reader_result_list: Gtk.ListBox = Gtk.Template.Child()

    view_model = inject.attr(SearchViewModel)
    main_view = inject.attr("MainWindow")

    search_thread: threading.Thread

    def __init__(self, main_window_builder: Gtk.Builder, headerbar: Headerbar) -> None:
        super().__init__()

        self.library_stack: Gtk.Stack = main_window_builder.get_object("library_stack")
        self.library_stack.add_child(self)

        self.split_view: Gtk.Stack = main_window_builder.get_object("split_view")

        self.search_bar = headerbar.search_bar
        self.entry = headerbar.search_entry
        self.entry.connect("search-changed", self._on_search_changed)

        self.search_thread = threading.Thread(target=self.view_model.search)

        self.view_model.bind_to("close", self.close)
        self.main_view.create_action("search", self.open, ["<primary>f"])

    def open(self, *_) -> None:
        self.library_stack.set_visible_child(self)
        self.search_bar.set_search_mode(True)
        self.main_view.play_pause_action.set_enabled(False)

    def close(self) -> None:
        self.library_stack.set_visible_child(self.split_view)
        self.search_bar.set_search_mode(False)
        self.main_view.play_pause_action.set_enabled(True)

    def on_state_changed(self, widget: Gtk.Widget, param) -> None:
        if widget.get_property(param.name):
            self.open()
        else:
            self.close()

    def _on_search_changed(self, _) -> None:
        search_query = self.entry.get_text()
        if not search_query:
            self.stack.set_visible_child(self.start_searching_page)
            return

        if self.search_thread.is_alive():
            self.search_thread.join(timeout=0.1)

        self.search_thread = threading.Thread(
            target=self.view_model.search, args=(search_query, self._display_results)
        )
        self.search_thread.start()

    def _display_results(self, books: list[Book], authors: list[str], readers: list[str]) -> None:
        if not any((books, authors, readers)):
            self.stack.set_visible_child(self.nothing_found_page)
            return

        self.stack.set_visible_child(self.search_scroller)
        self._populate_listbox(
            books, self.book_result_list, self.book_result_box, self.view_model.jump_to_book
        )
        self._populate_listbox(
            authors, self.author_result_list, self.author_result_box, self.view_model.jump_to_author
        )
        self._populate_listbox(
            readers, self.reader_result_list, self.reader_result_box, self.view_model.jump_to_reader
        )

    def _populate_listbox(
        self,
        results: Sequence[str | Book],
        listbox: Gtk.ListBox,
        box: Adw.PreferencesGroup,
        callback: Callable[[str | Book], None],
    ) -> None:
        box.set_visible(False)
        listbox.remove_all()

        if not results:
            return

        if isinstance(results[0], Book):
            row_type = BookRow
        else:
            row_type = ArtistResultRow

        for result in results:
            listbox.append(row_type(result, callback))

        box.set_visible(True)