Improve traces. Simplify folder management.
[dorian] / model / library.cpp
1 #include <QSettings>
2 #include <QDebug>
3 #include <QFileInfo>
4
5 #include "library.h"
6 #include "book.h"
7 #include "trace.h"
8
9 Library *Library::mInstance = 0;
10
11 Library::Library(QObject *parent): QAbstractListModel(parent)
12 {
13     load();
14 }
15
16 Library::~Library()
17 {
18     clear();
19 }
20
21 Library *Library::instance()
22 {
23     if (!mInstance) {
24         mInstance = new Library();
25     }
26     return mInstance;
27 }
28
29 int Library::rowCount(const QModelIndex &parent) const
30 {
31     if (parent.isValid()) {
32         return 0;
33     } else {
34         return mBooks.size();
35     }
36 }
37
38 QVariant Library::data(const QModelIndex &index, int role) const
39 {
40     if (!index.isValid()) {
41         return QVariant();
42     }
43
44     switch (role) {
45     case Qt::DisplayRole:
46         return mBooks[index.row()]->name();
47     case Qt::DecorationRole:
48         return QPixmap::fromImage(mBooks[index.row()]->cover);
49     default:
50         return QVariant();
51     }
52 }
53
54 Book *Library::book(const QModelIndex &index)
55 {
56     if (index.isValid()) {
57         if ((index.row() >= 0) && (index.row() < mBooks.size())) {
58             return mBooks[index.row()];
59         } else {
60             qCritical() << "Library::book: Bad index" << index.row();
61         }
62     }
63     return 0;
64 }
65
66 void Library::close()
67 {
68     delete mInstance;
69     mInstance = 0;
70 }
71
72 void Library::load()
73 {
74     QSettings settings;
75     clear();
76     int size = settings.value("lib/size").toInt();
77     for (int i = 0; i < size; i++) {
78         QString key = "lib/book" + QString::number(i);
79         QString path = settings.value(key).toString();
80         Book *book = new Book(path);
81         connect(book, SIGNAL(opened(const QString &)),
82                 this, SLOT(onBookOpened(const QString &)));
83         book->load();
84         mBooks.append(book);
85     }
86     QString currentPath = settings.value("lib/nowreading").toString();
87     mNowReading = find(currentPath);
88     mFolders = settings.value("lib/folders").toStringList();
89 }
90
91 void Library::save()
92 {
93     QSettings settings;
94     settings.setValue("lib/size", mBooks.size());
95     for (int i = 0; i < mBooks.size(); i++) {
96         QString key = "lib/book" + QString::number(i);
97         settings.setValue(key, mBooks[i]->path());
98     }
99     Book *currentBook = book(mNowReading);
100     settings.setValue("lib/nowreading",
101                       currentBook? currentBook->path(): QString());
102     settings.setValue("lib/folders", mFolders);
103 }
104
105 bool Library::add(const QString &path)
106 {
107     Trace t("Library::add " + path);
108     if (path == "") {
109         qCritical() << "Library::add: Empty path";
110         return false;
111     }
112     if (find(path).isValid()) {
113         qDebug() << "Book already exists in library";
114         return false;
115     }
116     int size = mBooks.size();
117     beginInsertRows(QModelIndex(), size, size);
118     Book *book = new Book(path);
119     book->peek();
120     mBooks.append(book);
121     save();
122     endInsertRows();
123     return true;
124 }
125
126 void Library::remove(const QModelIndex &index)
127 {
128     Book *toRemove = book(index);
129     if (!toRemove) {
130         return;
131     }
132     int row = index.row();
133     beginRemoveRows(QModelIndex(), row, row);
134     mBooks.removeAt(row);
135     save();
136     endRemoveRows();
137     if (index == mNowReading) {
138         mNowReading = QModelIndex();
139         emit nowReadingChanged();
140     }
141     delete toRemove;
142 }
143
144 void Library::remove(const QString &path)
145 {
146     remove(find(path));
147 }
148
149 QModelIndex Library::nowReading() const
150 {
151     return mNowReading;
152 }
153
154 void Library::setNowReading(const QModelIndex &index)
155 {
156     mNowReading = index;
157     save();
158     emit nowReadingChanged();
159 }
160
161 void Library::clear()
162 {
163     for (int i = 0; i < mBooks.size(); i++) {
164         delete mBooks[i];
165     }
166     mBooks.clear();
167     mNowReading = QModelIndex();
168 }
169
170 QModelIndex Library::find(QString path) const
171 {
172     if (path != "") {
173         QString absolutePath = QFileInfo(path).absoluteFilePath();
174         for (int i = 0; i < mBooks.size(); i++) {
175             if (absolutePath == mBooks[i]->path()) {
176                 return index(i);
177             }
178         }
179     }
180     return QModelIndex();
181 }
182
183 QModelIndex Library::find(const Book *book) const
184 {
185     if (book) {
186         for (int i = 0; i < mBooks.size(); i++) {
187             if (book == mBooks[i]) {
188                 return index(i);
189             }
190         }
191     }
192     return QModelIndex();
193 }
194
195 void Library::onBookOpened(const QString &path)
196 {
197     Trace t("Library::onBookOpened " + path);
198     QModelIndex index = find(path);
199     if (index.isValid()) {
200         emit dataChanged(index, index);
201     }
202 }
203
204 QStringList Library::bookPaths()
205 {
206     QStringList ret;
207     foreach (Book *book, mBooks) {
208         ret.append(book->path());
209     }
210     return ret;
211 }
212
213 QStringList Library::folders() const
214 {
215     return mFolders;
216 }
217
218 bool Library::addFolder(const QString &folder)
219 {
220     if (!mFolders.contains(folder)) {
221         mFolders.append(folder);
222         save();
223         return true;
224     } else {
225         return false;
226     }
227 }
228
229 bool Library::removeFolder(const QString &folder)
230 {
231     if (mFolders.contains(folder)) {
232         mFolders.removeOne(folder);
233         save();
234         return true;
235     } else {
236         return false;
237     }
238 }
239
240 void Library::scanFolders()
241 {
242 }