Fix forward navigation control on Linux.
[dorian] / librarydialog.cpp
index dfae909..9e985b2 100644 (file)
@@ -1,78 +1,71 @@
-#include <QtGui>
-#include <QDebug>
-#include <QFileInfo>
 #include <QDir>
-#include <QModelIndex>
-
-#ifdef Q_WS_MAEMO_5
-#include <QtMaemo5/QMaemo5InformationBox>
-#endif
+#include <QtGui>
 
 #include "librarydialog.h"
 #include "library.h"
 #include "sortedlibrary.h"
 #include "book.h"
 #include "infodialog.h"
+#include "settings.h"
+#include "listwindow.h"
+#include "trace.h"
+#include "bookfinder.h"
+#include "searchdialog.h"
+#include "platform.h"
+#include "searchresultsdialog.h"
+#include "progressdialog.h"
+#include "settings.h"
 
 LibraryDialog::LibraryDialog(QWidget *parent):
-        QDialog(parent, Qt::Dialog | Qt::WindowTitleHint |
-                Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint)
+        ListWindow(tr("(No books)"), parent)
 {
+    TRACE;
     setWindowTitle(tr("Library"));
-    list = new QListView(this);
+    setAttribute(Qt::WA_DeleteOnClose, true);
+
+    // Add menu actions
+    sortByTitle =
+            addMenuAction(tr("Sort by title"), this, SLOT(onSortByTitle()));
+    sortByAuthor =
+            addMenuAction(tr("Sort by author"), this, SLOT(onSortByAuthor()));
+
+    // Set model
     sortedLibrary = new SortedLibrary(this);
-    list->setModel(sortedLibrary);
-    list->setSelectionMode(QAbstractItemView::SingleSelection);
-    list->setUniformItemSizes(true);
-#ifndef Q_WS_MAEMO_5
-    setSizeGripEnabled(true);
-#endif
-
-#if 0 // FIXME
-    Book *current = library->current();
-    if (library->size() && current) {
-        list->setItemSelected(list->item(library->find(current)), true);
+    setModel(sortedLibrary);
+
+    // Add action buttons
+    addButton(tr("Add book"), this, SLOT(onAdd()), "add");
+    addButton(tr("Add books from folder"), this,
+              SLOT(onAddFolder()), "folder");
+    addButton(tr("Search the Web"), this, SLOT(onSearch()), "search");
+    addItemButton(tr("Delete"), this, SLOT(onDelete()), "delete");
+
+    // Set selected item
+    Library *library = Library::instance();
+    QModelIndex current = library->nowReading();
+    setCurrentItem(sortedLibrary->mapFromSource(current));
+
+    // Search dialog box
+    searchDialog = new SearchDialog(this);
+    connect(Search::instance(), SIGNAL(endSearch()),
+            this, SLOT(showSearchResults()));
+
+    // Progress bar
+    progress = new ProgressDialog(tr("Adding books"), this);
+
+    connect(library, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
+            this, SLOT(onBookAdded()));
+    connect(this, SIGNAL(activated(const QModelIndex &)),
+            this, SLOT(onItemActivated(const QModelIndex &)));
+
+    // Retrieve default sort criteria
+    switch (Settings::instance()->value("lib/sortby").toInt()) {
+    case SortedLibrary::SortByAuthor:
+        onSortByAuthor();
+        break;
+    default:
+        onSortByTitle();
     }
-#endif
-
-    QHBoxLayout *horizontalLayout = new QHBoxLayout(this);
-    horizontalLayout->addWidget(list);
-
-    QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Vertical);
-#ifndef Q_WS_MAEMO_5
-    detailsButton = new QPushButton(tr("Details"), this);
-    readButton = new QPushButton(tr("Read"), this);
-    removeButton = new QPushButton(tr("Delete"), this);
-#endif
-    addButton = new QPushButton(tr("Add"), this);
-
-#ifndef Q_WS_MAEMO_5
-    buttonBox->addButton(detailsButton, QDialogButtonBox::ActionRole);
-    buttonBox->addButton(readButton, QDialogButtonBox::AcceptRole);
-    buttonBox->addButton(removeButton, QDialogButtonBox::ActionRole);
-#endif // Q_WS_MAEMO_5
-    buttonBox->addButton(addButton, QDialogButtonBox::ActionRole);
-
-    horizontalLayout->addWidget(buttonBox);
-
-    connect(Library::instance(), SIGNAL(currentBookChanged()),
-            this, SLOT(onCurrentBookChanged()));
-#ifndef Q_WS_MAEMO_5
-    connect(list, SIGNAL(itemSelectionChanged()),
-            this, SLOT(onItemSelectionChanged()));
-    connect(detailsButton, SIGNAL(clicked()), this, SLOT(onDetails()));
-    connect(readButton, SIGNAL(clicked()), this, SLOT(onRead()));
-    connect(removeButton, SIGNAL(clicked()), this, SLOT(onRemove()));
-#endif
-    connect(addButton, SIGNAL(clicked()), this, SLOT(onAdd()));
-#ifdef Q_WS_MAEMO_5
-    connect(list, SIGNAL(itemActivated(QListWidgetItem *)),
-            this, SLOT(onItemActivated(QListWidgetItem *)));
-#endif
-
-#ifndef Q_WS_MAEMO_5
-    onItemSelectionChanged();
-#endif
 }
 
 void LibraryDialog::onAdd()
@@ -80,36 +73,27 @@ void LibraryDialog::onAdd()
     Library *library = Library::instance();
 
     // Figure out directory to show
-    if (lastDir == "") {
-        if (library->rowCount()) {
-            QModelIndex lastIndex = library->index(library->rowCount() - 1);
-            Book lastBook = library->data(lastIndex,
-                                          Library::BookRole).value<Book>();
-            QFileInfo info(lastBook.path());
-            lastDir = info.absolutePath();
-        }
-    }
+    QString lastDir = Settings::instance()->value("lastdir").toString();
     if (lastDir == "") {
         lastDir = QDir::homePath();
     }
 
     // Get book file name
-    QString path = QFileDialog::getOpenFileName(this, tr("Add Book"),
+    QString path = QFileDialog::getOpenFileName(this, tr("Add book"),
                                                 lastDir, "Books (*.epub)");
-    qDebug() << "LibraryDialog::onAdd" << path;
     if (path == "") {
         return;
     }
 
+    // Save directory selected
+    Settings::instance()->setValue("lastdir", QFileInfo(path).absolutePath());
+
     // Add book to library
-    lastDir = QFileInfo(path).absolutePath();
-    if (library->find(path).isValid()) {
-#ifdef Q_WS_MAEMO_5
-        QMaemo5InformationBox::information(this,
-            tr("This book is already in the library"),
-            QMaemo5InformationBox::DefaultTimeout);
-#endif
-        // FIXME: Select existing book
+    QModelIndex index = library->find(path);
+    if (index.isValid()) {
+        Platform::instance()->information(
+                tr("This book is already in the library"), this);
+        setSelected(sortedLibrary->mapFromSource(index));
     }
     else {
         library->add(path);
@@ -118,100 +102,164 @@ void LibraryDialog::onAdd()
 
 void LibraryDialog::onBookAdded()
 {
-#if 0 // FIXME
     Library *library = Library::instance();
-    int index = library->size() - 1;
-    Book *book = library->at(index);
-    QListWidgetItem *item = new QListWidgetItem(book->cover,
-                                                createItemText(book));
-    list->addItem(item);
-    list->setCurrentItem(item);
-#endif
+    setSelected(sortedLibrary->
+                mapFromSource(library->index(library->rowCount() - 1)));
 }
 
-#ifndef Q_WS_MAEMO_5
+void LibraryDialog::onItemActivated(const QModelIndex &index)
+{
+    TRACE;
+
+    QModelIndex libraryIndex = sortedLibrary->mapToSource(index);
+    Book *book = Library::instance()->book(libraryIndex);
+    int ret = (new InfoDialog(book, this))->exec();
 
-void LibraryDialog::onRemove()
+    switch (ret) {
+    case InfoDialog::Read:
+        Library::instance()->setNowReading(libraryIndex);
+        close();
+        break;
+    case InfoDialog::Delete:
+        Library::instance()->remove(libraryIndex);
+        break;
+    default:
+        ;
+    }
+}
+
+void LibraryDialog::onDelete()
 {
-    qDebug() << "LibraryDialog::onRemove";
-    QModelIndex current = sortedLibrary->mapToSource(list->currentIndex());
-    if (current.isValid()) {
-        Book currentBook =
-                Library::instance()->data(current, Library::BookRole).value<Book>();
-        QString title = currentBook.name();
-        if (QMessageBox::Yes ==
-            QMessageBox::question(this, "Delete book",
-                                  "Delete book \"" + title + "\"?",
-                                  QMessageBox::Yes
-#ifndef Q_WS_MAEMO_5
-                                  , QMessageBox::No
-#endif
-                                  )) {
-            Library::instance()->remove(current);
+    QModelIndex current = currentItem();
+    if (!current.isValid()) {
+        return;
+    }
+    QModelIndex libraryIndex = sortedLibrary->mapToSource(current);
+    Book *book = Library::instance()->book(libraryIndex);
+    if (QMessageBox::Yes !=
+        QMessageBox::question(this, tr("Delete book"),
+            tr("Delete book \"%1\"?").arg(book->shortName()),
+            QMessageBox::Yes | QMessageBox::No)) {
+        return;
+    }
+    Library::instance()->remove(libraryIndex);
+}
+
+QString LibraryDialog::createItemText(Book *book)
+{
+    Q_ASSERT(book);
+    QString text = book->shortName() + "\n";
+    if (book->creators.size()) {
+        text += book->creators[0];
+        for (int i = 1; i < book->creators.size(); i++) {
+            text += ", " + book->creators[i];
         }
     }
+    return text;
 }
 
-void LibraryDialog::onRead()
+void LibraryDialog::setSelected(const QModelIndex &libraryIndex)
 {
-    qDebug() << "LibraryDialog::onRead";
-    QModelIndex current = sortedLibrary->mapToSource(list->currentIndex());
-    if (current.isValid()) {
-        Library::instance()->setCurrent(current);
+    QModelIndex sortedIndex = sortedLibrary->mapFromSource(libraryIndex);
+    if (sortedIndex.isValid()) {
+        setCurrentItem(sortedIndex);
     }
 }
 
-void LibraryDialog::onDetails()
+void LibraryDialog::onAddFolder()
 {
-#if 0 // FIXME
-    onItemActivated(list->selectedItems()[0]);
-#endif
+    TRACE;
+
+    // Get folder name
+    Settings *settings = Settings::instance();
+    QString last =
+            settings->value("lastfolderadded", QDir::homePath()).toString();
+    QString path =
+            QFileDialog::getExistingDirectory(this, tr("Select folder"), last);
+    if (path == "") {
+        return;
+    }
+    settings->setValue("lastfolderadded", QFileInfo(path).absolutePath());
+    qDebug() << path;
+
+    // Add books from folder
+    progress->setWindowTitle(tr("Adding books"));
+    BookFinder *bookFinder = new BookFinder(this);
+    Library *library = Library::instance();
+    connect(bookFinder, SIGNAL(begin(int)), progress, SLOT(setMaximum(int)));
+    connect(bookFinder, SIGNAL(add(const QString &)),
+            this, SLOT(onAddFromFolder(const QString &)));
+    connect(bookFinder, SIGNAL(add(const QString &)),
+            library, SLOT(add(const QString &)));
+    connect(bookFinder, SIGNAL(done(int)),
+            this, SLOT(onAddFromFolderDone(int)));
+    bookFinder->find(path, Library::instance()->bookPaths());
 }
 
-#endif // Q_WS_MAEMO_5
+void LibraryDialog::onAddFromFolderDone(int added)
+{
+    QString msg;
 
-void LibraryDialog::onItemActivated(const QModelIndex &index)
+    switch (added) {
+    case 0: msg = tr("No new books found"); break;
+    case 1: msg = tr("One book added"); break;
+    default: msg = tr("%1 books added").arg(added);
+    }
+
+    progress->reset();
+    qDebug() << "LibraryDialog::onRefreshDone:" << msg;
+    Platform::instance()->information(msg, this);
+}
+
+void LibraryDialog::onAddFromFolder(const QString &path)
 {
-    qDebug() << "LibraryDialog::onItemActivated";
-#if 0 // FIXME
-    int row = list->row(item);
-    Book *book = Library::instance()->at(row);
-    InfoDialog *info = new InfoDialog(book, this);
-    info->exec();
-#endif
+    progress->setLabelText(QFileInfo(path).fileName());
+    progress->setValue(progress->value() + 1);
 }
 
-QString LibraryDialog::createItemText(const Book *book)
+void LibraryDialog::onSearch()
 {
-    QString text = book->title + "\n";
-    if (book->creators.size()) {
-        text += book->creators[0];
-        for (int i = 1; i < book->creators.size(); i++) {
-            text += ", " + book->creators[i];
-        }
+    TRACE;
+    int ret = searchDialog->exec();
+    qDebug() << "Search dialog returned" << ret;
+    if (ret != QDialog::Accepted) {
+        return;
     }
-    return text;
+    progress->setLabelText(tr("Searching Project Gutenberg"));
+    progress->showWait();
+    Search::instance()->start(searchDialog->query());
 }
 
-#ifndef Q_WS_MAEMO_5
-
-void LibraryDialog::onItemSelectionChanged()
+void LibraryDialog::showSearchResults()
 {
-#if 0 // FIXME
-    bool enable = list->selectedItems().size();
-    qDebug() << "LibraryDialog::onItemSelectionChanged" << enable;
-    readButton->setEnabled(enable);
-    qDebug() << " readButton";
-    detailsButton->setEnabled(enable);
-    qDebug() << " detailsButton";
-    removeButton->setEnabled(enable);
-    qDebug() << " removeButton";
-#endif
+    progress->reset();
+    QList<Search::Result> results = Search::instance()->results();
+    if (results.isEmpty()) {
+        QMessageBox::information(this, tr("Search results"),
+                                 tr("No books found"));
+        return;
+    }
+
+    SearchResultsDialog *dialog = new SearchResultsDialog(results, this);
+    connect(dialog, SIGNAL(add(const Search::Result &)),
+            this, SLOT(onAddSearchResult(const Search::Result &)));
+    dialog->show();
 }
 
-#endif // Q_WS_MAEMO_5
+void LibraryDialog::onSortByAuthor()
+{
+    TRACE;
+    sortedLibrary->setSortBy(SortedLibrary::SortByAuthor);
+    Settings::instance()->setValue("lib/sortby", SortedLibrary::SortByAuthor);
+    sortByAuthor->setChecked(true);
+    sortByTitle->setChecked(false);
+}
 
-void LibraryDialog::onCurrentBookChanged()
+void LibraryDialog::onSortByTitle()
 {
-    close();
+    TRACE;
+    sortedLibrary->setSortBy(SortedLibrary::SortByTitle);
+    Settings::instance()->setValue("lib/sortby", SortedLibrary::SortByTitle);
+    sortByAuthor->setChecked(false);
+    sortByTitle->setChecked(true);
 }