16 # define ICON_PREFIX ":/icons/mac/"
18 # define ICON_PREFIX ":/icons/"
21 BookView::BookView(QWidget *parent):
22 QWebView(parent), contentIndex(-1), mBook(0),
23 restorePositionAfterLoad(false), positionAfterLoad(0), loaded(false),
24 contentsHeight(0), decorated(false)
26 Trace t("BookView::BookView");
27 settings()->setAttribute(QWebSettings::AutoLoadImages, true);
28 settings()->setAttribute(QWebSettings::JavascriptEnabled, true);
29 settings()->setAttribute(QWebSettings::JavaEnabled, false);
30 settings()->setAttribute(QWebSettings::PluginsEnabled, false);
31 settings()->setAttribute(QWebSettings::PrivateBrowsingEnabled, true);
32 settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, false);
33 settings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard, false);
34 settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, false);
35 settings()->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled,
37 settings()->setAttribute(QWebSettings::LocalStorageEnabled, false);
38 settings()->setAttribute(QWebSettings::ZoomTextOnly, true);
39 settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,
41 settings()->setDefaultTextEncoding("utf-8");
42 page()->setContentEditable(false);
44 #if defined(Q_WS_MAEMO_5)
45 // Suppress unwanted text selections on Maemo
46 installEventFilter(this);
48 QWebFrame *frame = page()->mainFrame();
49 #if defined(Q_WS_MAEMO_5)
50 frame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
52 frame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
54 bookmarkImage = QImage(":/icons/bookmark.png");
56 connect(this, SIGNAL(loadFinished(bool)), this, SLOT(onLoadFinished(bool)));
57 connect(frame, SIGNAL(javaScriptWindowObjectCleared()),
58 this, SLOT(addJavaScriptObjects()));
59 connect(frame, SIGNAL(contentsSizeChanged(const QSize &)),
60 this, SLOT(onContentsSizeChanged(const QSize &)));
61 connect(Settings::instance(), SIGNAL(valueChanged(const QString &)),
62 this, SLOT(onSettingsChanged(const QString &)));
63 Settings *s = Settings::instance();
64 s->setValue("zoom", s->value("zoom", 160));
65 s->setValue("font", s->value("font",
66 #if defined(Q_WS_MAEMO_5) || defined(Q_WS_X11)
68 #elif defined(Q_WS_MAC)
74 s->setValue("scheme", s->value("scheme", "default"));
82 Trace t("BookView::~BookView");
86 void BookView::loadContent(int index)
88 Trace t("BookView::loadContent");
92 if ((index < 0) || (index >= mBook->parts.size())) {
96 QString contentFile(mBook->content[mBook->parts[index]].href);
97 if (mBook->parts[index] == "error") {
103 emit partLoadStart(index);
104 load(QUrl(contentFile));
106 contentIndex = index;
109 void BookView::setBook(Book *book)
111 Trace t("BookView::setBook");
113 // Save position in current book
116 // Open new book, restore last position
122 restoreLastBookmark();
126 setHtml(tr("Failed to open book"));
131 setHtml(tr("No book"));
136 Book *BookView::book()
141 void BookView::goPrevious()
143 Trace t("BookView::goPrevious");
144 loadContent(contentIndex - 1);
147 void BookView::goNext()
149 Trace t("BookView::goNext");
150 loadContent(contentIndex + 1);
153 void BookView::setLastBookmark()
155 Trace t("BookView::setLastBookmark");
157 int height = contentsHeight;
158 int pos = page()->mainFrame()->scrollPosition().y();
159 t.trace(QString("At %1 (%2%, height %3)").
160 arg(pos).arg((qreal)pos / (qreal)height * 100).arg(height));
161 mBook->setLastBookmark(contentIndex, (qreal)pos / (qreal)height);
165 void BookView::restoreLastBookmark()
167 Trace t("BookView::restoreLastBookmark");
169 goToBookmark(mBook->lastBookmark());
173 void BookView::goToBookmark(const Book::Bookmark &bookmark)
175 Trace t("BookView::goToBookmark");
177 if (bookmark.part != contentIndex) {
178 t.trace(QString("Loading new part %1").arg(bookmark.part));
179 mBook->setLastBookmark(bookmark.part, bookmark.pos);
180 restorePositionAfterLoad = true;
181 positionAfterLoad = bookmark.pos;
182 loadContent(bookmark.part);
184 goToPosition(bookmark.pos);
189 void BookView::onLoadFinished(bool ok)
191 Trace t("BookView::onLoadFinished");
198 onSettingsChanged("scheme");
199 emit partLoadEnd(contentIndex);
203 void BookView::onSettingsChanged(const QString &key)
205 Trace t("BookView::onSettingsChanged " + key);
207 setZoomFactor(Settings::instance()->value(key).toFloat() / 100.);
209 else if (key == "font") {
210 QString face = Settings::instance()->value("font").toString();
211 settings()->setFontFamily(QWebSettings::StandardFont, face);
213 else if (key == "scheme") {
214 QWebFrame *frame = page()->mainFrame();
215 QString scheme = Settings::instance()->value("scheme").toString();
216 if ((scheme != "day") && (scheme != "night") && (scheme != "sand") &&
217 (scheme != "default")) {
220 QFile script(":/styles/" + scheme + ".js");
221 script.open(QFile::ReadOnly);
222 QString scriptText = script.readAll();
224 QVariant ret = frame->evaluateJavaScript(scriptText);
228 void BookView::paintEvent(QPaintEvent *e)
230 QWebView::paintEvent(e);
231 if (!mBook || !loaded) {
236 QPoint scrollPos = page()->mainFrame()->scrollPosition();
237 QPixmap bookmarkPixmap = QPixmap::fromImage(bookmarkImage);
238 QPainter painter(this);
239 foreach (Book::Bookmark b, mBook->bookmarks()) {
240 if (b.part != contentIndex) {
243 int height = contentsHeight;
244 int bookmarkPos = (qreal)height * (qreal)b.pos;
245 painter.drawPixmap(2, bookmarkPos - scrollPos.y(), bookmarkPixmap);
249 void BookView::mousePressEvent(QMouseEvent *e)
251 QWebView::mousePressEvent(e);
253 QWebFrame *frame = page()->mainFrame();
254 if (frame->scrollBarGeometry(Qt::Vertical).contains(e->pos())) {
258 #endif // Q_WS_MAEMO_5
262 void BookView::mouseReleaseEvent(QMouseEvent *e)
264 QWebView::mouseReleaseEvent(e);
268 void BookView::wheelEvent(QWheelEvent *e)
270 QWebView::wheelEvent(e);
274 void BookView::addBookmark()
276 Trace t("BookView::addBookmark");
280 int y = page()->mainFrame()->scrollPosition().y();
281 int height = page()->mainFrame()->contentsSize().height();
282 t.trace(QString().setNum((qreal)y / (qreal)height));
283 mBook->addBookmark(contentIndex, (qreal)y / (qreal)height);
287 void BookView::addNavigationBar()
289 Trace t("BookView::addNavigationBar");
295 "<a href=\"javascript:bv.goPrevious();\">"
296 "<img width=\"95\" height=\"95\" style=\"float:left;clear:none;\" "
302 "<a href=\"javascript:bv.goNext();\">"
303 "<img width=\"95\" height=\"95\" style=\"float:right;clear:none;\" "
308 if (contentIndex == 0) {
311 if (contentIndex >= mBook->parts.size() - 1) {
315 QWebFrame *frame = page()->currentFrame();
316 QString headerScript = "document.body.innerHTML = '" +
317 naviPrev + naviNext + "<br />" + "' + document.body.innerHTML;";
318 QString trailerScript = "document.body.innerHTML += '<br /><br />" +
319 naviPrev + naviNext + "';";
321 frame->evaluateJavaScript(headerScript);
322 frame->evaluateJavaScript(trailerScript);
326 QString BookView::tmpPath()
328 return QDir::tempPath() + "/dorian";
331 void BookView::extractIcons()
333 QFile next(ICON_PREFIX + QString("/next.png"));
334 QFile prev(ICON_PREFIX + QString("/previous.png"));
336 QDir().mkpath(tmpPath());
337 next.copy(tmpPath() + "/next.png");
338 prev.copy(tmpPath() + "/previous.png");
341 void BookView::removeIcons()
343 QFile(ICON_PREFIX + QString("/next.png")).remove();
344 QFile(ICON_PREFIX + QString("/previous.png")).remove();
345 QDir().rmpath(tmpPath());
348 bool BookView::eventFilter(QObject *o, QEvent *e)
351 if (e->type() != QEvent::Paint && e->type() != QEvent::MouseMove) {
352 if (e->type() == QEvent::Resize) {
353 Trace::trace(QString("BookView::eventFilter QEvent::Resize to %1").
354 arg(page()->mainFrame()->contentsSize().height()));
356 Trace::trace(QString("BookView::eventFilter %1").
357 arg(Trace::event(e->type())));
363 case QEvent::MouseButtonPress:
364 emit suppressedMouseButtonPress();
367 case QEvent::MouseButtonRelease:
369 mousePressed = false;
371 case QEvent::MouseMove:
376 case QEvent::MouseButtonDblClick:
382 return QObject::eventFilter(o, e);
385 void BookView::addJavaScriptObjects()
387 page()->mainFrame()->addToJavaScriptWindowObject("bv", this);
390 void BookView::onContentsSizeChanged(const QSize &size)
392 contentsHeight = size.height();
394 if (restorePositionAfterLoad) {
395 Trace::trace("BookView::onContentSizeChanged: Time to restore");
396 restorePositionAfterLoad = false;
397 goToPosition(positionAfterLoad);
402 void BookView::leaveEvent(QEvent *e)
404 Trace t("BookView::leaveEvent");
405 // Save current position, to be restored later
407 QWebView::leaveEvent(e);
410 void BookView::enterEvent(QEvent *e)
412 Trace t("BookView::enterEvent");
413 // Restore position saved at Leave event. This seems to be required,
414 // after temporarily switching from portrait to landscape and back
415 restoreLastBookmark();
416 QWebView::enterEvent(e);
419 void BookView::goToPosition(qreal position)
421 int scrollPos = (qreal)contentsHeight * position;
422 page()->mainFrame()->setScrollPosition(QPoint(0, scrollPos));
424 Trace::trace(QString("BookView::goToPosition: To %1 (%2%, height %3)").
425 arg(scrollPos).arg(position * 100).arg(contentsHeight));
428 void BookView::showProgress()
431 qreal pos = (qreal)(page()->mainFrame()->scrollPosition().y()) /
432 (qreal)contentsHeight;
433 emit progress(mBook->getProgress(contentIndex, pos));