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