Show cover images in library.
[dorian] / 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 }
89
90 void Library::save()
91 {
92     QSettings settings;
93     settings.setValue("lib/size", mBooks.size());
94     for (int i = 0; i < mBooks.size(); i++) {
95         QString key = "lib/book" + QString::number(i);
96         settings.setValue(key, mBooks[i]->path());
97     }
98     Book *currentBook = book(mNowReading);
99     settings.setValue("lib/nowreading",
100                       currentBook? currentBook->path(): QString());
101 }
102
103 bool Library::add(QString path)
104 {
105     Trace t("Library::add " + path);
106     if (path == "") {
107         qCritical() << "*** Library::add: Empty path";
108         return false;
109     }
110     if (find(path).isValid()) {
111         t.trace("Book already exists in library");
112         return false;
113     }
114     int size = mBooks.size();
115     Book *book = new Book(path);
116     beginInsertRows(QModelIndex(), size, size);
117     mBooks.append(book);
118     save();
119     endInsertRows();
120     return true;
121 }
122
123 void Library::remove(const QModelIndex &index)
124 {
125     Book *toRemove = book(index);
126     if (!toRemove) {
127         return;
128     }
129     int row = index.row();
130     beginRemoveRows(QModelIndex(), row, row);
131     mBooks.removeAt(row);
132     save();
133     endRemoveRows();
134     if (index == mNowReading) {
135         mNowReading = QModelIndex();
136         emit nowReadingChanged();
137     }
138     delete toRemove;
139 }
140
141 QModelIndex Library::nowReading() const
142 {
143     return mNowReading;
144 }
145
146 void Library::setNowReading(const QModelIndex &index)
147 {
148     mNowReading = index;
149     save();
150     emit nowReadingChanged();
151 }
152
153 void Library::clear()
154 {
155     for (int i = 0; i < mBooks.size(); i++) {
156         delete mBooks[i];
157     }
158     mBooks.clear();
159     mNowReading = QModelIndex();
160 }
161
162 QModelIndex Library::find(QString path) const
163 {
164     if (path != "") {
165         QString absolutePath = QFileInfo(path).absoluteFilePath();
166         for (int i = 0; i < mBooks.size(); i++) {
167             if (absolutePath == mBooks[i]->path()) {
168                 return index(i);
169             }
170         }
171     }
172     return QModelIndex();
173 }
174
175 QModelIndex Library::find(const Book *book) const
176 {
177     if (book) {
178         for (int i = 0; i < mBooks.size(); i++) {
179             if (book == mBooks[i]) {
180                 return index(i);
181             }
182         }
183     }
184     return QModelIndex();
185 }
186
187 void Library::onBookOpened(const QString &path)
188 {
189     Trace t("Library::onBookOpened " + path);
190     QModelIndex index = find(path);
191     if (index.isValid()) {
192         emit dataChanged(index, index);
193     }
194 }