5 #include <qtextdocument.h> // Qt::escape is currently defined here...
6 #include <QDirIterator>
8 #include <QtAlgorithms>
11 #include "opshandler.h"
12 #include "opserrorhandler.h"
13 #include "extractzip.h"
15 #include "containerhandler.h"
21 Book::Book(const QString &path_)
25 QFileInfo info(path_);
26 mPath = info.absoluteFilePath();
27 title = info.baseName();
28 cover = QIcon(":/icons/book.png");
32 QString Book::path() const
39 qDebug() << "Book::open" << path();
46 else if (!extract()) {
47 fail("Could not extract content of " + path() + ".");
50 fail("Could not parse content of " + path() + ".");
59 qDebug() << "Book::close";
62 QDir::setCurrent(QDir::rootPath());
66 QString Book::tmpDir() const
68 return QDir::tempPath() + "/dorian/book";
71 void Book::fail(const QString &details, const QString &error)
76 QString errorPage = "<html><head><title>" + Qt::escape(error) +
77 "</title></head><body><h1>" + Qt::escape(error) + "</h1><p>" +
78 Qt::escape(details) + "</p></body></html>";
79 content["error"].href = errorPage;
80 content["error"].type = "text/html";
86 QString tmp = tmpDir();
87 qDebug() << "Book::extract: Extracting" << mPath << "to" << tmp;
89 QDir::setCurrent(QDir::rootPath());
91 qCritical() << "*** Book::extract: Failed to remove" << tmp;
96 qCritical() << "*** Book::extract: Could not create" << tmp;
100 // If book comes from resource, copy it to the temporary directory first
101 QString bookPath = path();
102 if (bookPath.startsWith(":/books/")) {
104 QString dst(tmp + "/book.epub");
105 if (!src.copy(dst)) {
106 qCritical() << "*** Book::extract: Failed to copy built-in book to"
113 QString oldDir = QDir::currentPath();
114 if (!QDir::setCurrent(tmp)) {
115 qCritical() << "*** Book::extract: Could not change to" << tmp;
118 ret = extractZip(bookPath);
120 qCritical() << "*** Book::extract: Extracting ZIP failed";
122 QDir::setCurrent(oldDir);
128 qDebug() << "Book::parse";
131 QFile bookFile(opsPath());
132 QXmlSimpleReader reader;
133 QXmlInputSource *source = new QXmlInputSource(&bookFile);
134 OpsHandler *opsHandler = new OpsHandler(*this);
135 OpsErrorHandler *opsErrorHandler = new OpsErrorHandler();
136 reader.setContentHandler(opsHandler);
137 reader.setErrorHandler(opsErrorHandler);
139 ret = reader.parse(source);
141 qCritical() << "*** Book::parse: XML parsing failed";
149 bool Book::clearDir(const QString &dir)
155 QDirIterator i(dir, QDirIterator::Subdirectories);
156 while (i.hasNext()) {
157 QString entry = i.next();
158 if (entry.endsWith("/.") || entry.endsWith("/..")) {
161 QFileInfo info(entry);
163 if (!clearDir(entry)) {
168 if (!QFile::remove(entry)) {
169 qCritical() << "*** Book::clearDir: Could not remove" << entry;
170 // FIXME: To be investigated: This is happening too often
194 qDebug() << "Book::load" << path();
196 QString key = "book/" + path() + "/";
197 qDebug() << " key" << key;
200 title = settings.value(key + "title").toString();
201 qDebug() << " title" << title;
202 creators = settings.value(key + "creators").toStringList();
203 date = settings.value(key + "date").toString();
204 publisher = settings.value(key + "publisher").toString();
205 datePublished = settings.value(key + "datepublished").toString();
206 subject = settings.value(key + "subject").toString();
207 source = settings.value(key + "source").toString();
208 rights = settings.value(key + "rights").toString();
209 mLastBookmark.chapter = settings.value(key + "lastchapter").toInt();
210 mLastBookmark.pos = settings.value(key + "lastpos").toReal();
213 int size = settings.value(key + "bookmarks").toInt();
214 for (int i = 0; i < size; i++) {
215 int chapter = settings.value(key + "bookmark" + QString::number(i) +
217 qreal pos = settings.value(key + "bookmark" + QString::number(i) +
219 qDebug() << " Bookmark" << i << "at" << chapter << "," << pos;
220 mBookmarks.append(Bookmark(chapter, pos));
226 qDebug() << "Book::save";
228 QString key = "book/" + path() + "/";
229 qDebug() << " key" << key;
232 settings.setValue(key + "title", title);
233 qDebug() << " title" << title;
234 settings.setValue(key + "creators", creators);
235 settings.setValue(key + "date", date);
236 settings.setValue(key + "publisher", publisher);
237 settings.setValue(key + "datepublished", datePublished);
238 settings.setValue(key + "subject", subject);
239 settings.setValue(key + "source", source);
240 settings.setValue(key + "rights", rights);
241 settings.setValue(key + "lastchapter", mLastBookmark.chapter);
242 settings.setValue(key + "lastpos", mLastBookmark.pos);
245 settings.setValue(key + "bookmarks", mBookmarks.size());
246 for (int i = 0; i < mBookmarks.size(); i++) {
247 qDebug() << " Bookmark" << i << "at" << mBookmarks[i].chapter << ","
248 << mBookmarks[i].pos;
249 settings.setValue(key + "bookmark" + QString::number(i) + "/chapter",
250 mBookmarks[i].chapter);
251 settings.setValue(key + "bookmark" + QString::number(i) + "/pos",
256 void Book::setLastBookmark(int chapter, qreal position)
258 mLastBookmark.chapter = chapter;
259 mLastBookmark.pos = position;
263 Book::Bookmark Book::lastBookmark() const
265 return Book::Bookmark(mLastBookmark);
268 void Book::addBookmark(int chapter, qreal position)
270 mBookmarks.append(Bookmark(chapter, position));
271 qSort(mBookmarks.begin(), mBookmarks.end());
275 QList<Book::Bookmark> Book::bookmarks() const
280 QString Book::opsPath()
284 QFile container(tmpDir() + "/META-INF/container.xml");
285 qDebug() << "Book::opsPath" << container.fileName();
286 QXmlSimpleReader reader;
287 QXmlInputSource *source = new QXmlInputSource(&container);
288 ContainerHandler *containerHandler = new ContainerHandler();
289 OpsErrorHandler *opsErrorHandler = new OpsErrorHandler();
290 reader.setContentHandler(containerHandler);
291 reader.setErrorHandler(opsErrorHandler);
292 if (reader.parse(source)) {
293 ret = tmpDir() + "/" + containerHandler->rootFile;
294 mRootPath = QFileInfo(ret).absoluteDir().absolutePath();
295 qDebug() << " OSP path" << ret;
296 qDebug() << " Root dir" << mRootPath;
298 delete containerHandler;
303 QString Book::rootPath() const
308 QString Book::name() const