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