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