|
@@ -0,0 +1,114 @@
|
|
|
|
|
+#include "BibliothecaWindow.hpp"
|
|
|
|
|
+#include "Book.hpp"
|
|
|
|
|
+#include <gtkmm/filedialog.h>
|
|
|
|
|
+#include <gtkmm/filefilter.h>
|
|
|
|
|
+#include <giomm/file.h>
|
|
|
|
|
+#include <giomm/cancellable.h>
|
|
|
|
|
+#include <glibmm/error.h>
|
|
|
|
|
+#include <giomm/liststore.h>
|
|
|
|
|
+#include <giomm/asyncresult.h>
|
|
|
|
|
+#include <iostream>
|
|
|
|
|
+#include <vector>
|
|
|
|
|
+
|
|
|
|
|
+BibliothecaWindow::BibliothecaWindow() {
|
|
|
|
|
+ // Window properties
|
|
|
|
|
+ set_title("Bibliotheca");
|
|
|
|
|
+ set_default_size(800, 600);
|
|
|
|
|
+
|
|
|
|
|
+ // Configure HeaderBar
|
|
|
|
|
+ m_addBookButton.set_icon_name("list-add-symbolic");
|
|
|
|
|
+ m_headerBar.pack_end(m_addBookButton);
|
|
|
|
|
+ set_titlebar(m_headerBar);
|
|
|
|
|
+
|
|
|
|
|
+ // Confiure Button
|
|
|
|
|
+ m_addBookButton.set_icon_name("list-add-symbolic");
|
|
|
|
|
+ m_addBookButton.set_tooltip_text("Add books to your library");
|
|
|
|
|
+ m_addBookButton.set_has_frame(false);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // Create the placeholder for the empty library view
|
|
|
|
|
+ auto image = Gtk::make_managed<Gtk::Image>();
|
|
|
|
|
+ auto display = Gdk::Display::get_default();
|
|
|
|
|
+ auto theme = Gtk::IconTheme::get_for_display(display);
|
|
|
|
|
+ const auto want = "folder-open-symbolic";
|
|
|
|
|
+ if (theme && theme->has_icon(want)) {
|
|
|
|
|
+ image->set_from_icon_name(want);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // very safe fallback bundled with GTK
|
|
|
|
|
+ image->set_from_icon_name("image-missing");
|
|
|
|
|
+ }
|
|
|
|
|
+ image->set_pixel_size(64);
|
|
|
|
|
+
|
|
|
|
|
+ auto label = Gtk::make_managed<Gtk::Label>();
|
|
|
|
|
+ label->set_use_markup(true);
|
|
|
|
|
+ label->set_markup("<span size='large' weight='bold'>Your Library is Empty</span>\n"
|
|
|
|
|
+ "<small>Click the ‘+’ button to add your first book.</small>");
|
|
|
|
|
+ label->set_wrap(true);
|
|
|
|
|
+ label->set_xalign(0.5); // horizontal centering
|
|
|
|
|
+ label->set_justify(Gtk::Justification::CENTER);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ m_placeholder.set_orientation(Gtk::Orientation::VERTICAL);
|
|
|
|
|
+ m_placeholder.set_valign(Gtk::Align::CENTER);
|
|
|
|
|
+ m_placeholder.set_halign(Gtk::Align::CENTER);
|
|
|
|
|
+ m_placeholder.set_spacing(12);
|
|
|
|
|
+ m_placeholder.append(*image);
|
|
|
|
|
+ m_placeholder.append(*label);
|
|
|
|
|
+ m_placeholder.set_margin_top(24);
|
|
|
|
|
+ m_placeholder.set_margin_bottom(24);
|
|
|
|
|
+ m_placeholder.set_margin_start(24);
|
|
|
|
|
+ m_placeholder.set_margin_end(24);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // Set the placeholder as the main content for now
|
|
|
|
|
+ set_child(m_placeholder);
|
|
|
|
|
+
|
|
|
|
|
+ m_addBookButton.signal_clicked().connect(sigc::mem_fun(*this, &BibliothecaWindow::onAddBookClicked));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void BibliothecaWindow::onAddBookClicked() {
|
|
|
|
|
+ auto dialog = Gtk::FileDialog::create();
|
|
|
|
|
+ dialog->set_title("Add books");
|
|
|
|
|
+
|
|
|
|
|
+ // Filters
|
|
|
|
|
+ auto epub = Gtk::FileFilter::create();
|
|
|
|
|
+ epub->set_name("EPUB books");
|
|
|
|
|
+ epub->add_suffix("epub");
|
|
|
|
|
+
|
|
|
|
|
+ auto pdf = Gtk::FileFilter::create();
|
|
|
|
|
+ pdf->set_name("PDF books");
|
|
|
|
|
+ pdf->add_suffix("pdf");
|
|
|
|
|
+
|
|
|
|
|
+ auto any = Gtk::FileFilter::create();
|
|
|
|
|
+ any->set_name("All files");
|
|
|
|
|
+ any->add_pattern("*");
|
|
|
|
|
+
|
|
|
|
|
+ // Build a ListStore<Gtk::FileFilter> for set_filters()
|
|
|
|
|
+ auto store = Gio::ListStore<Gtk::FileFilter>::create();
|
|
|
|
|
+ store->append(epub);
|
|
|
|
|
+ store->append(pdf);
|
|
|
|
|
+ store->append(any);
|
|
|
|
|
+ dialog->set_filters(store);
|
|
|
|
|
+
|
|
|
|
|
+ // Async open: single callback, finish inside it
|
|
|
|
|
+ dialog->open_multiple(
|
|
|
|
|
+ *this,
|
|
|
|
|
+ [this, dialog](const Glib::RefPtr<Gio::AsyncResult>& res) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ auto files = dialog->open_multiple_finish(res);
|
|
|
|
|
+ if (files.empty()) return;
|
|
|
|
|
+
|
|
|
|
|
+ for (const auto& f : files) {
|
|
|
|
|
+ m_books.addBook(f->get_path());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // TODO: populate your model and swap placeholder -> shelf view here
|
|
|
|
|
+ // set_child(m_shelfView);
|
|
|
|
|
+ } catch (const Glib::Error& e) {
|
|
|
|
|
+ std::cerr << "File dialog error: " << e.what() << "\n";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|