Be more tolerant to book removals. Document Settings class. Fix BookFinder.
[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
18 LibraryDialog::LibraryDialog(QWidget *parent): QMainWindow(parent)
19 {
20 #ifdef Q_WS_MAEMO_5
21     setAttribute(Qt::WA_Maemo5StackedWindow, true);
22 #endif
23     setWindowTitle(tr("Library"));
24
25     QFrame *frame = new QFrame(this);
26     setCentralWidget(frame);
27     QHBoxLayout *horizontalLayout = new QHBoxLayout(frame);
28     frame->setLayout(horizontalLayout);
29
30     list = new QListView(this);
31     sortedLibrary = new SortedLibrary(this);
32     list->setModel(sortedLibrary);
33     list->setSelectionMode(QAbstractItemView::SingleSelection);
34     list->setSpacing(1);
35     list->setUniformItemSizes(true);
36
37     Library *library = Library::instance();
38     QModelIndex current = library->nowReading();
39     setSelected(current);
40     horizontalLayout->addWidget(list);
41
42 #ifndef Q_WS_MAEMO_5
43     QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Vertical);
44     detailsButton = new QPushButton(tr("Details"), this);
45     readButton = new QPushButton(tr("Read"), this);
46     removeButton = new QPushButton(tr("Delete"), this);
47     addButton = new QPushButton(tr("Add"), this);
48
49     buttonBox->addButton(detailsButton, QDialogButtonBox::ActionRole);
50     buttonBox->addButton(readButton, QDialogButtonBox::AcceptRole);
51     buttonBox->addButton(removeButton, QDialogButtonBox::ActionRole);
52     buttonBox->addButton(addButton, QDialogButtonBox::ActionRole);
53     horizontalLayout->addWidget(buttonBox);
54 #else
55     QAction *addBookAction = menuBar()->addAction(tr("Add book"));
56 #endif // Q_WS_MAEMO_5
57
58     connect(Library::instance(), SIGNAL(nowReadingChanged()),
59             this, SLOT(onCurrentBookChanged()));
60     connect(Library::instance(),
61             SIGNAL(rowsInserted(const QModelIndex &, int, int)),
62             this,
63             SLOT(onBookAdded()));
64     connect(list, SIGNAL(activated(const QModelIndex &)),
65             this, SLOT(onItemActivated(const QModelIndex &)));
66 #ifndef Q_WS_MAEMO_5
67     connect(addButton, SIGNAL(clicked()), this, SLOT(onAdd()));
68     connect(detailsButton, SIGNAL(clicked()), this, SLOT(onDetails()));
69     connect(readButton, SIGNAL(clicked()), this, SLOT(onRead()));
70     connect(removeButton, SIGNAL(clicked()), this, SLOT(onRemove()));
71     connect(list->selectionModel(),
72             SIGNAL(selectionChanged(const QItemSelection &,
73                                     const QItemSelection &)),
74             this, SLOT(onItemSelectionChanged()));
75     onItemSelectionChanged();
76 #else
77     connect(addBookAction, SIGNAL(triggered()), this, SLOT(onAdd()));
78 #endif // !Q_WS_MAEMO_5
79 }
80
81 void LibraryDialog::onAdd()
82 {
83     Library *library = Library::instance();
84
85     // Figure out directory to show
86     QString lastDir = Settings::instance()->value("lastdir").toString();
87     if (lastDir == "") {
88         lastDir = QDir::homePath();
89     }
90
91     // Get book file name
92     QString path = QFileDialog::getOpenFileName(this, tr("Add Book"),
93                                                 lastDir, "Books (*.epub)");
94     if (path == "") {
95         return;
96     }
97
98     // Save directory selected
99     Settings::instance()->setValue("lastdir", QFileInfo(path).absolutePath());
100
101     // Add book to library
102     QModelIndex index = library->find(path);
103     if (index.isValid()) {
104 #ifdef Q_WS_MAEMO_5
105         QMaemo5InformationBox::information(this,
106             tr("This book is already in the library"),
107             QMaemo5InformationBox::DefaultTimeout);
108 #else
109         (void)QMessageBox::information(this, tr("Dorian"),
110             tr("This book is already in the library"), QMessageBox::Ok);
111 #endif // Q_WS_MAEMO_5
112         setSelected(index);
113     }
114     else {
115         library->add(path);
116     }
117 }
118
119 void LibraryDialog::onBookAdded()
120 {
121     Library *library = Library::instance();
122     setSelected(library->index(library->rowCount() - 1));
123 }
124
125 #ifndef Q_WS_MAEMO_5
126
127 void LibraryDialog::onRemove()
128 {
129     QModelIndex current = sortedLibrary->mapToSource(list->currentIndex());
130     if (current.isValid()) {
131         Book *currentBook = Library::instance()->book(current);
132         QString title = currentBook->name();
133         if (QMessageBox::Yes ==
134             QMessageBox::question(this, tr("Delete book"),
135                 tr("Delete book \"%1\" from library?").
136                     arg(currentBook->shortName()),
137                 QMessageBox::Yes | QMessageBox::No)) {
138             Library::instance()->remove(current);
139         }
140     }
141 }
142
143 void LibraryDialog::onRead()
144 {
145     qDebug() << "LibraryDialog::onRead";
146     QModelIndex current = sortedLibrary->mapToSource(list->currentIndex());
147     if (current.isValid()) {
148         Library::instance()->setNowReading(current);
149     }
150 }
151
152 void LibraryDialog::onDetails()
153 {
154     onItemActivated(list->currentIndex());
155 }
156
157 #endif // Q_WS_MAEMO_5
158
159 void LibraryDialog::onItemActivated(const QModelIndex &index)
160 {
161     qDebug() << "LibraryDialog::onItemActivated";
162     QModelIndex libraryIndex = sortedLibrary->mapToSource(index);
163     Book *book = Library::instance()->book(libraryIndex);
164     (new InfoDialog(book, this))->exec();
165 }
166
167 QString LibraryDialog::createItemText(const Book *book)
168 {
169     QString text = book->title + "\n";
170     if (book->creators.size()) {
171         text += book->creators[0];
172         for (int i = 1; i < book->creators.size(); i++) {
173             text += ", " + book->creators[i];
174         }
175     }
176     return text;
177 }
178
179 #ifndef Q_WS_MAEMO_5
180
181 void LibraryDialog::onItemSelectionChanged()
182 {
183     bool enable = selected().isValid();
184     readButton->setEnabled(enable);
185     detailsButton->setEnabled(enable);
186     removeButton->setEnabled(enable);
187 }
188
189 #endif // Q_WS_MAEMO_5
190
191 void LibraryDialog::onCurrentBookChanged()
192 {
193     close();
194 }
195
196 void LibraryDialog::setSelected(const QModelIndex &libraryIndex)
197 {
198     QModelIndex sortedIndex = sortedLibrary->mapFromSource(libraryIndex);
199     list->selectionModel()->clearSelection();
200     if (sortedIndex.isValid()) {
201         list->selectionModel()->select(sortedIndex,
202                                        QItemSelectionModel::Select);
203         list->setCurrentIndex(sortedIndex);
204     }
205 }
206
207 QModelIndex LibraryDialog::selected() const
208 {
209     QModelIndexList selectedItems = list->selectionModel()->selectedIndexes();
210     if (selectedItems.size()) {
211         return sortedLibrary->mapToSource(selectedItems[0]);
212     }
213     return QModelIndex();
214 }
215
216 void LibraryDialog::closeEvent(QCloseEvent *event)
217 {
218 #ifdef Q_WS_MAEMO_5
219     menuBar()->clear();
220 #endif
221     event->accept();
222 }