Slight improvements on Windows.
[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 }
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(const 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         qDebug() << "Book already exists in library";
112         return false;
113     }
114     int size = mBooks.size();
115     beginInsertRows(QModelIndex(), size, size);
116     Book *book = new Book(path);
117     book->peek();
118     mBooks.append(book);
119     save();
120     endInsertRows();
121     return true;
122 }
123
124 void Library::remove(const QModelIndex &index)
125 {
126     Book *toRemove = book(index);
127     if (!toRemove) {
128         return;
129     }
130     int row = index.row();
131     beginRemoveRows(QModelIndex(), row, row);
132     mBooks.removeAt(row);
133     save();
134     endRemoveRows();
135     if (index == mNowReading) {
136         mNowReading = QModelIndex();
137         emit nowReadingChanged();
138     }
139     delete toRemove;
140 }
141
142 void Library::remove(const QString &path)
143 {
144     remove(find(path));
145 }
146
147 QModelIndex Library::nowReading() const
148 {
149     return mNowReading;
150 }
151
152 void Library::setNowReading(const QModelIndex &index)
153 {
154     mNowReading = index;
155     save();
156     emit nowReadingChanged();
157 }
158
159 void Library::clear()
160 {
161     for (int i = 0; i < mBooks.size(); i++) {
162         delete mBooks[i];
163     }
164     mBooks.clear();
165     mNowReading = QModelIndex();
166 }
167
168 QModelIndex Library::find(QString path) const
169 {
170     if (path != "") {
171         QString absolutePath = QFileInfo(path).absoluteFilePath();
172         for (int i = 0; i < mBooks.size(); i++) {
173             if (absolutePath == mBooks[i]->path()) {
174                 return index(i);
175             }
176         }
177     }
178     return QModelIndex();
179 }
180
181 QModelIndex Library::find(const Book *book) const
182 {
183     if (book) {
184         for (int i = 0; i < mBooks.size(); i++) {
185             if (book == mBooks[i]) {
186                 return index(i);
187             }
188         }
189     }
190     return QModelIndex();
191 }
192
193 void Library::onBookOpened(const QString &path)
194 {
195     Trace t("Library::onBookOpened " + path);
196     QModelIndex index = find(path);
197     if (index.isValid()) {
198         emit dataChanged(index, index);
199     }
200 }
201
202 QStringList Library::bookPaths()
203 {
204     QStringList ret;
205     foreach (Book *book, mBooks) {
206         ret.append(book->path());
207     }
208     return ret;
209 }