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