Process and show search results.
[dorian] / librarydialog.cpp
1 #include <QtGui>
2 #include <QDebug>
3 #include <QFileInfo>
4 #include <QDir>
5 #include <QModelIndex>
6
7 #ifdef Q_WS_MAEMO_5
8 #include <QtMaemo5/QMaemo5InformationBox>
9 #endif
10
11 #include "librarydialog.h"
12 #include "library.h"
13 #include "sortedlibrary.h"
14 #include "book.h"
15 #include "infodialog.h"
16 #include "settings.h"
17 #include "listwindow.h"
18 #include "listview.h"
19 #include "trace.h"
20 #include "bookfinder.h"
21 #include "searchdialog.h"
22 #include "platform.h"
23 #include "searchresultsdialog.h"
24
25 LibraryDialog::LibraryDialog(QWidget *parent): ListWindow(parent)
26 {
27     setWindowTitle(tr("Library"));
28
29     // Add actions
30
31 #ifndef Q_WS_MAEMO_5
32     addItemAction(tr("Details"), this, SLOT(onDetails()));
33     addItemAction(tr("Read"), this, SLOT(onRead()));
34     addItemAction(tr("Delete"), this, SLOT(onRemove()));
35 #endif // ! Q_WS_MAEMO_5
36
37     addAction(tr("Add book"), this, SLOT(onAdd()), "add");
38     addAction(tr("Add books from folder"), this, SLOT(onAddFolder()), "folder");
39     addAction(tr("Search the Web"), this, SLOT(onSearch()), "search");
40
41     // Create and add list view
42     list = new ListView(this);
43     sortedLibrary = new SortedLibrary(this);
44     list->setModel(sortedLibrary);
45     list->setSelectionMode(QAbstractItemView::SingleSelection);
46     list->setSpacing(1);
47     Library *library = Library::instance();
48     QModelIndex current = library->nowReading();
49     setSelected(current);
50     addList(list);
51
52     progress = new QProgressDialog(tr("Adding books"), "", 0, 0, this);
53     progress->reset();
54     progress->setMinimumDuration(0);
55     progress->setWindowModality(Qt::WindowModal);
56     progress->setCancelButton(0);
57 #ifdef Q_WS_S60
58     progress->setFixedWidth(
59             QApplication::desktop()->availableGeometry().width());
60 #endif
61
62     connect(Library::instance(), SIGNAL(nowReadingChanged()),
63             this, SLOT(onCurrentBookChanged()));
64     connect(Library::instance(),
65             SIGNAL(rowsInserted(const QModelIndex &, int, int)),
66             this,
67             SLOT(onBookAdded()));
68     connect(list, SIGNAL(activated(const QModelIndex &)),
69             this, SLOT(onItemActivated(const QModelIndex &)));
70
71     // Create search dialog
72     searchDialog = new SearchDialog(this);
73     connect(Search::instance(), SIGNAL(endSearch()),
74             this, SLOT(showSearchResults()));
75 }
76
77 void LibraryDialog::onAdd()
78 {
79     Library *library = Library::instance();
80
81     // Figure out directory to show
82     QString lastDir = Settings::instance()->value("lastdir").toString();
83     if (lastDir == "") {
84         lastDir = QDir::homePath();
85     }
86
87     // Get book file name
88     QString path = QFileDialog::getOpenFileName(this, tr("Add Book"),
89                                                 lastDir, "Books (*.epub)");
90     if (path == "") {
91         return;
92     }
93
94     // Save directory selected
95     Settings::instance()->setValue("lastdir", QFileInfo(path).absolutePath());
96
97     // Add book to library
98     QModelIndex index = library->find(path);
99     if (index.isValid()) {
100 #ifdef Q_WS_MAEMO_5
101         QMaemo5InformationBox::information(this,
102             tr("This book is already in the library"),
103             QMaemo5InformationBox::DefaultTimeout);
104 #else
105         (void)QMessageBox::information(this, tr("Dorian"),
106             tr("This book is already in the library"), QMessageBox::Ok);
107 #endif // Q_WS_MAEMO_5
108         setSelected(index);
109     }
110     else {
111         library->add(path);
112     }
113 }
114
115 void LibraryDialog::onBookAdded()
116 {
117     Library *library = Library::instance();
118     setSelected(library->index(library->rowCount() - 1));
119 }
120
121 #ifndef Q_WS_MAEMO_5
122
123 void LibraryDialog::onRemove()
124 {
125     QModelIndex current = sortedLibrary->mapToSource(list->currentIndex());
126     if (current.isValid()) {
127         Book *currentBook = Library::instance()->book(current);
128         QString title = currentBook->name();
129         if (QMessageBox::Yes ==
130             QMessageBox::question(this, tr("Delete book"),
131                 tr("Delete book \"%1\" from library?").
132                     arg(currentBook->shortName()),
133                 QMessageBox::Yes | QMessageBox::No)) {
134             Library::instance()->remove(current);
135         }
136     }
137 }
138
139 void LibraryDialog::onRead()
140 {
141     qDebug() << "LibraryDialog::onRead";
142     QModelIndex current = sortedLibrary->mapToSource(list->currentIndex());
143     if (current.isValid()) {
144         Library::instance()->setNowReading(current);
145     }
146 }
147
148 void LibraryDialog::onDetails()
149 {
150     onItemActivated(list->currentIndex());
151 }
152
153 #endif // Q_WS_MAEMO_5
154
155 void LibraryDialog::onItemActivated(const QModelIndex &index)
156 {
157     qDebug() << "LibraryDialog::onItemActivated";
158     QModelIndex libraryIndex = sortedLibrary->mapToSource(index);
159     Book *book = Library::instance()->book(libraryIndex);
160     (new InfoDialog(book, this))->exec();
161 }
162
163 QString LibraryDialog::createItemText(const Book *book)
164 {
165     QString text = book->title + "\n";
166     if (book->creators.size()) {
167         text += book->creators[0];
168         for (int i = 1; i < book->creators.size(); i++) {
169             text += ", " + book->creators[i];
170         }
171     }
172     return text;
173 }
174
175 void LibraryDialog::onCurrentBookChanged()
176 {
177     close();
178 }
179
180 void LibraryDialog::setSelected(const QModelIndex &libraryIndex)
181 {
182     QModelIndex sortedIndex = sortedLibrary->mapFromSource(libraryIndex);
183     list->selectionModel()->clearSelection();
184     if (sortedIndex.isValid()) {
185         list->selectionModel()->select(sortedIndex,
186                                        QItemSelectionModel::Select);
187         list->setCurrentIndex(sortedIndex);
188     }
189 }
190
191 QModelIndex LibraryDialog::selected() const
192 {
193     QModelIndexList selectedItems = list->selectionModel()->selectedIndexes();
194     if (selectedItems.size()) {
195         return sortedLibrary->mapToSource(selectedItems[0]);
196     }
197     return QModelIndex();
198 }
199
200 void LibraryDialog::onAddFolder()
201 {
202     Trace t("LibraryDialog::onAddFolder");
203
204     // Get folder name
205     Settings *settings = Settings::instance();
206     QString last =
207             settings->value("lastfolderadded", QDir::homePath()).toString();
208     QString path =
209             QFileDialog::getExistingDirectory(this, tr("Select folder"), last);
210     if (path == "") {
211         return;
212     }
213     settings->setValue("lastfolderadded", QFileInfo(path).absolutePath());
214     qDebug() << path;
215
216     // Add books from folder
217     progress->setWindowTitle(tr("Adding books"));
218     BookFinder *bookFinder = new BookFinder(this);
219     Library *library = Library::instance();
220     connect(bookFinder, SIGNAL(begin(int)), progress, SLOT(setMaximum(int)));
221     connect(bookFinder, SIGNAL(add(const QString &)),
222             this, SLOT(onAddFromFolder(const QString &)));
223     connect(bookFinder, SIGNAL(add(const QString &)),
224             library, SLOT(add(const QString &)));
225     connect(bookFinder, SIGNAL(done(int)),
226             this, SLOT(onAddFromFolderDone(int)));
227     bookFinder->find(path, Library::instance()->bookPaths());
228 }
229
230 void LibraryDialog::onAddFromFolderDone(int added)
231 {
232     QString msg;
233
234     switch (added) {
235     case 0: msg = tr("No new books found"); break;
236     case 1: msg = tr("One book added"); break;
237     default: msg = tr("%1 books added").arg(added);
238     }
239
240     progress->reset();
241     qDebug() << "LibraryDialog::onRefreshDone:" << msg;
242 #ifdef Q_WS_MAEMO_5
243     QMaemo5InformationBox::information(this, msg);
244 #else
245     // FIXME
246 #endif
247 }
248
249 void LibraryDialog::onAddFromFolder(const QString &path)
250 {
251     progress->setLabelText(QFileInfo(path).fileName());
252     progress->setValue(progress->value() + 1);
253 }
254
255 void LibraryDialog::onSearch()
256 {
257     int ret = searchDialog->exec();
258     if (ret != QDialog::Accepted) {
259         return;
260     }
261     Search::instance()->start(searchDialog->query());
262 }
263
264 void LibraryDialog::showSearchResults()
265 {
266     QList<Search::Result> results = Search::instance()->results();
267     if (results.count() == 0) {
268         QMessageBox::information(this, tr("Search results"), tr("No books found"));
269         return;
270     }
271
272     SearchResultsDialog *dialog = new SearchResultsDialog(results, this);
273     connect(dialog, SIGNAL(add(const Search::Result &)),
274             this, SLOT(onAddSearchResult(const Search::Result &)));
275     dialog->show();
276 }