bibliotheca_window.md 4.9 KB

BibliothecaWindow Module Overview

BibliothecaWindow is the top-level GTK window that stitches together the data model (BookList) and the UI widgets (BookShelf, BookDetails, search bar, placeholders). It owns the application chrome and orchestrates imports, filtering, and state transitions between empty / shelf / no-results / details views.

Responsibilities

  • Build the header bar (add button, back button, search toggle) and main layout.
  • Manage the search UI (Gtk::SearchBar + Gtk::SearchEntry) and pipe queries to BookShelf::setFilter().
  • Host a Gtk::Stack that swaps between:
    • Empty library placeholder.
    • Library grid (BookShelf).
    • "No results" message when filtering yields nothing.
    • Book details view (BookDetails).
  • Handle "Add books" action: open a file dialog, import metadata/covers on a worker thread, detect duplicates, and enqueue BookList::upsertMany().
  • Show toast notifications for import results and errors.
  • Navigate to BookDetails when a book is activated.
  • Handle keyboard navigation (Enter, Escape, Backspace).

Layout overview

Gtk::Window (BibliothecaWindow)
 └── Gtk::Box m_mainBox (vertical)
     ├── Gtk::SearchBar m_searchBar
     │    └── Gtk::SearchEntry m_searchEntry
     └── Gtk::Overlay m_overlay
          ├── Gtk::Stack m_stack
          │    ├── Gtk::Box m_placeholder        // empty library
          │    ├── BookShelf (GridView)          // main shelf view
          │    ├── Gtk::Box m_noResults          // "no match" placeholder
          │    └── BookDetails                   // book details view
          └── Gtk::Revealer m_toastRevealer      // toast notification overlay
               └── Gtk::Box m_toastBox
                    ├── Gtk::Label m_toastLabel
                    └── Gtk::Button m_toastCloseButton

The header bar carries:

  • Add (+) button to import books
  • Back button (visible on details view)
  • Search toggle button that activates the search bar

Event flow

  1. Startup: constructor calls buildHeaderBar(), buildPlaceholder(), buildToast(), creates the shelf and details widgets, search widgets, and stack, then calls updateVisibleView() to pick the correct page.
  2. Search:
    • Clicking the search toggle (or pressing Ctrl+F) toggles the Gtk::SearchBar.
    • Typing updates m_lastQuery, calls BookShelf::setFilter(), and refreshes the stack (showing "no results" if the filtered shelf is empty).
    • Search query is preserved when navigating to details and restored on return.
    • Leaving the search mode clears the entry (only on shelf/noresults views).
  3. Importing books:
    • onAddBookClicked() opens Gtk::FileDialog::open_multiple().
    • Each selected file is processed on a background thread: compute SHA-256, call import_book_assets(), merge metadata, collect into a vector.
    • Duplicates are detected by matching SHA-256 hash against existing books.
    • Once done, the vector is enqueued back onto the main loop via BookList::upsertMany(), and the UI refreshes.
    • Toast notifications show import results ("Added N books", "N duplicates").
  4. Activation: BookShelf::signalBookActivated() connects to BibliothecaWindow::onBookActivated(), which navigates to the BookDetails view for the selected book.
  5. Keyboard navigation:
    • Enter/Return: Open selected book from shelf view.
    • Escape: Go back from details, close search bar, or clear selection.
    • Backspace: Go back from details view.

Signals & slots

BibliothecaWindow subscribes to the relevant BookList signals to call updateVisibleView() whenever the library changes. This keeps the stack in sync with imports, deletions, and resets without manual intervention.

It also subscribes to BookDetails::signalBookRemoved() to navigate back to the shelf when the currently displayed book is deleted.

Toast notifications

The toast system uses a Gtk::Revealer overlay to show temporary messages:

  • Success messages (green styling) for successful imports.
  • Error messages (red styling) for failed imports.
  • Mixed messages when some imports succeed and others fail.
  • Auto-hide after 4 seconds with manual close button.

Extension points

  • Drag-and-drop import: wire a drop controller onto m_mainBox that reuses the existing import flow.
  • Search enhancements: add tag chips as quick filters in the search UI.
  • Loading indicator: add spinner during import operations.

Expected usage

BibliothecaWindow is the root window instantiated in main.cpp. Other modules should construct it with an existing DatabaseManager and BookList:

auto window = Gtk::make_managed<BibliothecaWindow>(db, bookList);
app->add_window(*window);

The window takes ownership of the BookShelf and BookDetails widgets and manages presentation according to the current state of the library and active search query.