15 # define ICON_PREFIX ":/icons/mac/"
17 # define ICON_PREFIX ":/icons/"
20 BookView::BookView(QWidget *parent):
21 QWebView(parent), contentIndex(-1), mBook(0),
22 restorePositionAfterLoad(false), positionAfterLoad(0), loaded(false),
23 contentsHeight(0), decorated(false)
25 Trace t("BookView::BookView");
26 settings()->setAttribute(QWebSettings::AutoLoadImages, true);
27 settings()->setAttribute(QWebSettings::JavascriptEnabled, true);
28 settings()->setAttribute(QWebSettings::JavaEnabled, false);
29 settings()->setAttribute(QWebSettings::PluginsEnabled, false);
30 settings()->setAttribute(QWebSettings::PrivateBrowsingEnabled, true);
31 settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, false);
32 settings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard, false);
33 settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, false);
34 settings()->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled,
36 settings()->setAttribute(QWebSettings::LocalStorageEnabled, false);
37 settings()->setAttribute(QWebSettings::ZoomTextOnly, true);
38 settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,
40 settings()->setDefaultTextEncoding("utf-8");
41 page()->setContentEditable(false);
43 #if defined(Q_WS_MAEMO_5)
44 // Suppress unwanted text selections on Maemo
45 installEventFilter(this);
47 QWebFrame *frame = page()->mainFrame();
48 #if defined(Q_WS_MAEMO_5)
49 frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
51 frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
53 bookmarkImage = QImage(":/icons/bookmark.png");
55 connect(this, SIGNAL(loadFinished(bool)), this, SLOT(onLoadFinished(bool)));
56 connect(frame, SIGNAL(javaScriptWindowObjectCleared()),
57 this, SLOT(addJavaScriptObjects()));
58 connect(frame, SIGNAL(contentsSizeChanged(const QSize &)),
59 this, SLOT(onContentsSizeChanged(const QSize &)));
60 connect(Settings::instance(), SIGNAL(valueChanged(const QString &)),
61 this, SLOT(onSettingsChanged(const QString &)));
62 Settings *s = Settings::instance();
63 s->setValue("zoom", s->value("zoom", 160));
64 s->setValue("font", s->value("font",
65 #if defined(Q_WS_MAEMO_5) || defined(Q_WS_X11)
67 #elif defined(Q_WS_MAC)
73 s->setValue("scheme", s->value("scheme", "default"));
81 Trace t("BookView::~BookView");
85 void BookView::loadContent(int index)
87 Trace t("BookView::loadContent");
91 if ((index < 0) || (index >= mBook->toc.size())) {
95 QString contentFile(mBook->content[mBook->toc[index]].href);
96 if (mBook->toc[index] == "error") {
102 emit chapterLoadStart(index);
103 load(QUrl(contentFile));
105 contentIndex = index;
108 void BookView::setBook(Book *book)
110 Trace t("BookView::setBook");
112 // Save position in current book
115 // Open new book, restore last position
121 restoreLastBookmark();
125 setHtml(tr("Failed to open book"));
130 setHtml(tr("No book"));
135 Book *BookView::book()
140 void BookView::goPrevious()
142 Trace t("BookView::goPrevious");
143 loadContent(contentIndex - 1);
146 void BookView::goNext()
148 Trace t("BookView::goNext");
149 loadContent(contentIndex + 1);
152 void BookView::setLastBookmark()
154 Trace t("BookView::setLastBookmark");
156 int height = contentsHeight;
157 int pos = page()->mainFrame()->scrollPosition().y();
158 t.trace(QString("At %1 (%2%, height %3)").
159 arg(pos).arg((qreal)pos / (qreal)height * 100).arg(height));
160 mBook->setLastBookmark(contentIndex, (qreal)pos / (qreal)height);
164 void BookView::restoreLastBookmark()
166 Trace t("BookView::restoreLastBookmark");
168 goToBookmark(mBook->lastBookmark());
172 void BookView::goToBookmark(const Book::Bookmark &bookmark)
174 Trace t("BookView::goToBookmark");
176 if (bookmark.chapter != contentIndex) {
177 t.trace(QString("Loading new chapter %1").arg(bookmark.chapter));
178 mBook->setLastBookmark(bookmark.chapter, bookmark.pos);
179 restorePositionAfterLoad = true;
180 positionAfterLoad = bookmark.pos;
181 loadContent(bookmark.chapter);
183 goToPosition(bookmark.pos);
188 void BookView::onLoadFinished(bool ok)
190 Trace t("BookView::onLoadFinished");
197 onSettingsChanged("scheme");
198 emit chapterLoadEnd(contentIndex);
201 void BookView::onSettingsChanged(const QString &key)
203 Trace t("BookView::onSettingsChanged " + key);
205 setZoomFactor(Settings::instance()->value(key).toFloat() / 100.);
207 else if (key == "font") {
208 QString face = Settings::instance()->value("font").toString();
209 settings()->setFontFamily(QWebSettings::StandardFont, face);
211 else if (key == "scheme") {
212 QWebFrame *frame = page()->mainFrame();
213 QString scheme = Settings::instance()->value("scheme").toString();
214 if ((scheme != "day") && (scheme != "night") && (scheme != "sand") &&
215 (scheme != "default")) {
218 QFile script(":/styles/" + scheme + ".js");
219 script.open(QFile::ReadOnly);
220 QString scriptText = script.readAll();
222 QVariant ret = frame->evaluateJavaScript(scriptText);
226 void BookView::paintEvent(QPaintEvent *e)
228 QWebView::paintEvent(e);
229 if (!mBook || !loaded) {
234 QPoint scrollPos = page()->mainFrame()->scrollPosition();
235 QPixmap bookmarkPixmap = QPixmap::fromImage(bookmarkImage);
236 QPainter painter(this);
237 foreach (Book::Bookmark b, mBook->bookmarks()) {
238 if (b.chapter != contentIndex) {
241 int height = contentsHeight;
242 int bookmarkPos = (qreal)height * (qreal)b.pos;
243 painter.drawPixmap(2, bookmarkPos - scrollPos.y(), bookmarkPixmap);
247 void BookView::mousePressEvent(QMouseEvent *e)
249 QWebView::mousePressEvent(e);
251 QWebFrame *frame = page()->mainFrame();
252 if (frame->scrollBarGeometry(Qt::Vertical).contains(e->pos())) {
256 #endif // Q_WS_MAEMO_5
260 void BookView::addBookmark()
262 Trace t("BookView::addBookmark");
266 int y = page()->mainFrame()->scrollPosition().y();
267 int height = page()->mainFrame()->contentsSize().height();
268 t.trace(QString().setNum((qreal)y / (qreal)height));
269 mBook->addBookmark(contentIndex, (qreal)y / (qreal)height);
273 void BookView::addNavigationBar()
275 Trace t("BookView::addNavigationBar");
281 "<a href=\"javascript:bv.goPrevious();\">"
282 "<img width=\"95\" height=\"95\" style=\"float:left;clear:none;\" "
288 "<a href=\"javascript:bv.goNext();\">"
289 "<img width=\"95\" height=\"95\" style=\"float:right;clear:none;\" "
294 if (contentIndex == 0) {
297 if (contentIndex >= mBook->toc.size() - 1) {
301 QWebFrame *frame = page()->currentFrame();
302 QString headerScript = "document.body.innerHTML = '" +
303 naviPrev + naviNext + "<br />" + "' + document.body.innerHTML;";
304 QString trailerScript = "document.body.innerHTML += '<br /><br />" +
305 naviPrev + naviNext + "';";
307 frame->evaluateJavaScript(headerScript);
308 frame->evaluateJavaScript(trailerScript);
312 QString BookView::tmpPath()
314 return QDir::tempPath() + "/dorian";
317 void BookView::extractIcons()
319 QFile next(ICON_PREFIX + QString("/next.png"));
320 QFile prev(ICON_PREFIX + QString("/previous.png"));
322 QDir().mkpath(tmpPath());
323 next.copy(tmpPath() + "/next.png");
324 prev.copy(tmpPath() + "/previous.png");
327 void BookView::removeIcons()
329 QFile(ICON_PREFIX + QString("/next.png")).remove();
330 QFile(ICON_PREFIX + QString("/previous.png")).remove();
331 QDir().rmpath(tmpPath());
334 bool BookView::eventFilter(QObject *o, QEvent *e)
337 if (e->type() != QEvent::Paint && e->type() != QEvent::MouseMove) {
338 if (e->type() == QEvent::Resize) {
339 Trace::trace(QString("BookView::eventFilter QEvent::Resize to %1").
340 arg(page()->mainFrame()->contentsSize().height()));
342 Trace::trace(QString("BookView::eventFilter %1").
343 arg(Trace::event(e->type())));
349 case QEvent::MouseButtonPress:
350 emit suppressedMouseButtonPress();
353 case QEvent::MouseButtonRelease:
354 mousePressed = false;
356 case QEvent::MouseMove:
361 case QEvent::MouseButtonDblClick:
367 return QObject::eventFilter(o, e);
370 void BookView::addJavaScriptObjects()
372 page()->mainFrame()->addToJavaScriptWindowObject("bv", this);
375 void BookView::onContentsSizeChanged(const QSize &size)
377 contentsHeight = size.height();
379 if (restorePositionAfterLoad) {
380 Trace::trace("BookView::onContentSizeChanged: Time to restore");
381 restorePositionAfterLoad = false;
382 goToPosition(positionAfterLoad);
387 void BookView::leaveEvent(QEvent *e)
389 Trace t("BookView::leaveEvent");
390 // Save current position, to be restored later
392 QWebView::leaveEvent(e);
395 void BookView::enterEvent(QEvent *e)
397 Trace t("BookView::enterEvent");
398 // Restore position saved at Leave event. This seems to be required,
399 // after temporarily switching from portrait to landscape and back
400 restoreLastBookmark();
401 QWebView::enterEvent(e);
404 void BookView::goToPosition(qreal position)
406 int scrollPos = (qreal)contentsHeight * position;
407 page()->mainFrame()->setScrollPosition(QPoint(0, scrollPos));
409 Trace::trace(QString("BookView::goToPosition: To %1 (%2%, height %3)").
410 arg(scrollPos).arg(position * 100).arg(contentsHeight));