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