5 #include <qtextdocument.h> // Qt::escape is currently defined here...
6 #include <QDirIterator>
10 #include "opshandler.h"
11 #include "opserrorhandler.h"
12 #include "extractzip.h"
14 #include "containerhandler.h"
16 Book::Book(const QString &path_)
20 QFileInfo info(path_);
21 mPath = info.absoluteFilePath();
22 title = info.baseName();
23 cover = QIcon(":/icons/book.png");
27 QString Book::path() const
34 qDebug() << "Book::open" << path();
41 else if (!extract()) {
42 fail("Could not extract content of " + path() + ".");
45 fail("Could not parse content of " + path() + ".");
54 qDebug() << "Book::close";
57 QDir::setCurrent(QDir::rootPath());
61 QString Book::tmpDir() const
63 return QDir::tempPath() + "/dorian/book";
66 void Book::fail(const QString &details, const QString &error)
71 QString errorPage = "<html><head><title>" + Qt::escape(error) +
72 "</title></head><body><h1>" + Qt::escape(error) + "</h1><p>" +
73 Qt::escape(details) + "</p></body></html>";
74 content["error"].href = errorPage;
75 content["error"].type = "text/html";
81 QString tmp = tmpDir();
82 qDebug() << "Book::extract: Extracting" << mPath << "to" << tmp;
84 QDir::setCurrent(QDir::rootPath());
86 qCritical() << "*** Book::extract: Failed to remove" << tmp;
91 qCritical() << "*** Book::extract: Could not create" << tmp;
95 // If book comes from resource, copy it to the temporary directory first
96 QString bookPath = path();
97 if (bookPath.startsWith(":/books/")) {
99 QString dst(tmp + "/book.epub");
100 if (!src.copy(dst)) {
101 qCritical() << "*** Book::extract: Failed to copy built-in book to"
108 QString oldDir = QDir::currentPath();
109 if (!QDir::setCurrent(tmp)) {
110 qCritical() << "*** Book::extract: Could not change to" << tmp;
113 ret = extractZip(bookPath);
115 qCritical() << "*** Book::extract: Extracting ZIP failed";
117 QDir::setCurrent(oldDir);
123 qDebug() << "Book::parse";
126 QFile bookFile(opsPath());
127 QXmlSimpleReader reader;
128 QXmlInputSource *source = new QXmlInputSource(&bookFile);
129 OpsHandler *opsHandler = new OpsHandler(*this);
130 OpsErrorHandler *opsErrorHandler = new OpsErrorHandler();
131 reader.setContentHandler(opsHandler);
132 reader.setErrorHandler(opsErrorHandler);
134 ret = reader.parse(source);
136 qCritical() << "*** Book::parse: XML parsing failed";
144 bool Book::clearDir(const QString &dir)
150 QDirIterator i(dir, QDirIterator::Subdirectories);
151 while (i.hasNext()) {
152 QString entry = i.next();
153 if (entry.endsWith("/.") || entry.endsWith("/..")) {
156 QFileInfo info(entry);
158 if (!clearDir(entry)) {
163 if (!QFile::remove(entry)) {
164 qCritical() << "*** Book::clearDir: Could not remove" << entry;
165 // FIXME: To be investigated: This is happening too often
189 qDebug() << "Book::load" << path();
191 QString key = "book/" + path() + "/";
192 qDebug() << " key" << key;
195 title = settings.value(key + "title").toString();
196 qDebug() << " title" << title;
197 creators = settings.value(key + "creators").toStringList();
198 date = settings.value(key + "date").toString();
199 publisher = settings.value(key + "publisher").toString();
200 datePublished = settings.value(key + "datepublished").toString();
201 subject = settings.value(key + "subject").toString();
202 source = settings.value(key + "source").toString();
203 rights = settings.value(key + "rights").toString();
204 mLastBookmark.chapter = settings.value(key + "lastchapter").toInt();
205 mLastBookmark.pos = settings.value(key + "lastpos").toReal();
208 int size = settings.value(key + "bookmarks").toInt();
209 for (int i = 0; i < size; i++) {
210 int chapter = settings.value(key + "bookmark" + QString::number(i) +
212 qreal pos = settings.value(key + "bookmark" + QString::number(i) +
214 qDebug() << " Bookmark" << i << "at" << chapter << "," << pos;
215 mBookmarks.append(Bookmark(chapter, pos));
221 qDebug() << "Book::save";
223 QString key = "book/" + path() + "/";
224 qDebug() << " key" << key;
227 settings.setValue(key + "title", title);
228 qDebug() << " title" << title;
229 settings.setValue(key + "creators", creators);
230 settings.setValue(key + "date", date);
231 settings.setValue(key + "publisher", publisher);
232 settings.setValue(key + "datepublished", datePublished);
233 settings.setValue(key + "subject", subject);
234 settings.setValue(key + "source", source);
235 settings.setValue(key + "rights", rights);
236 settings.setValue(key + "lastchapter", mLastBookmark.chapter);
237 settings.setValue(key + "lastpos", mLastBookmark.pos);
240 settings.setValue(key + "bookmarks", mBookmarks.size());
241 for (int i = 0; i < mBookmarks.size(); i++) {
242 qDebug() << " Bookmark" << i << "at" << mBookmarks[i].chapter << ","
243 << mBookmarks[i].pos;
244 settings.setValue(key + "bookmark" + QString::number(i) + "/chapter",
245 mBookmarks[i].chapter);
246 settings.setValue(key + "bookmark" + QString::number(i) + "/pos",
251 void Book::setLastBookmark(int chapter, qreal position)
253 mLastBookmark.chapter = chapter;
254 mLastBookmark.pos = position;
258 Book::Bookmark Book::lastBookmark() const
260 return Book::Bookmark(mLastBookmark);
263 void Book::addBookmark(int chapter, qreal position)
265 mBookmarks.append(Bookmark(chapter, position));
269 QList<Book::Bookmark> Book::bookmarks() const
274 QString Book::opsPath()
278 QFile container(tmpDir() + "/META-INF/container.xml");
279 qDebug() << "Book::opsPath" << container.fileName();
280 QXmlSimpleReader reader;
281 QXmlInputSource *source = new QXmlInputSource(&container);
282 ContainerHandler *containerHandler = new ContainerHandler();
283 OpsErrorHandler *opsErrorHandler = new OpsErrorHandler();
284 reader.setContentHandler(containerHandler);
285 reader.setErrorHandler(opsErrorHandler);
286 if (reader.parse(source)) {
287 ret = tmpDir() + "/" + containerHandler->rootFile;
288 mRootPath = QFileInfo(ret).absoluteDir().absolutePath();
289 qDebug() << " OSP path" << ret;
290 qDebug() << " Root dir" << mRootPath;
292 delete containerHandler;
297 QString Book::rootPath() const