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