summaryrefslogtreecommitdiffstats
path: root/src/bookwidget.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-07-21 04:30:08 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-07-21 04:30:08 +0000
commita3570c360e8884f2bbf60b89e4d9531321ae01ad (patch)
treea6bc829daca69956b99be4dfa3939ff14193ec54 /src/bookwidget.cpp
downloadkbookreader-a3570c360e8884f2bbf60b89e4d9531321ae01ad.tar.gz
kbookreader-a3570c360e8884f2bbf60b89e4d9531321ae01ad.zip
Initial import of kbookreader
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kbookreader@1242482 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/bookwidget.cpp')
-rw-r--r--src/bookwidget.cpp473
1 files changed, 473 insertions, 0 deletions
diff --git a/src/bookwidget.cpp b/src/bookwidget.cpp
new file mode 100644
index 0000000..8eec9df
--- /dev/null
+++ b/src/bookwidget.cpp
@@ -0,0 +1,473 @@
+/***************************************************************************
+* Copyright (C) 2005 by Alexander Nemish *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, *
+* but WITHOUT ANY WARRANTY; without even the implied warranty of *
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+* GNU General Public License for more details. *
+* *
+* You should have received a copy of the GNU General Public License *
+* along with this program; if not, write to the *
+* Free Software Foundation, Inc., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+#include <qpainter.h>
+#include <qevent.h>
+#include <qimage.h>
+#include <kdebug.h>
+#include <kprogress.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qtextcodec.h>
+#include <qstring.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include "bookwidget.h"
+#include "theme.h"
+#include "settings.h"
+#include "renderer.h"
+//#include "ktextprogressdlg.h"
+
+class QStringList;
+class QRect;
+class QPixmap;
+
+BookWidget::BookWidget(QWidget *parent, const char *name)
+ : QWidget(parent, name),
+ m_modified(true),
+ m_currentPage(0),
+ m_left_margin(0),
+ m_right_margin(0),
+ m_top_margin(0),
+ m_bottom_margin(0),
+ m_middle_margin(0),
+ m_encoding(0),
+ m_renderer(new Renderer)
+{
+ //setupPageSize();
+ //setupSlots();
+ m_left_margin = 30;
+ m_right_margin = 30;
+ m_top_margin = 20;
+ m_bottom_margin = 15;
+ m_middle_margin = 20;
+
+ setFont(Settings::font());
+
+ Theme::self()->loadTheme("default");
+
+ setWFlags(Qt::WNoAutoErase);
+ setFocusPolicy(QWidget::StrongFocus);
+
+ connect(&m_timer, SIGNAL(timeout()), this, SLOT(loadLine()));
+ connect(m_renderer.get(), SIGNAL(renderingFinished()), this, SLOT(renderingFinished()));
+}
+
+
+BookWidget::~BookWidget()
+{
+}
+
+void BookWidget::openURL(const KURL & url)
+{
+ m_url = url;
+ m_file.setName(m_url.path());
+ if (! m_file.open(IO_ReadOnly)) return;
+
+ ///@todo Write encoding detection
+ m_stream.reset(new QTextStream(&m_file));
+ m_textLines.reset(new QStringList);
+ QString name(encoding());
+ QTextCodec *codec = QTextCodec::codecForName(encoding()); // get the codec
+ if (codec)
+ m_stream->setCodec(codec);
+ //show progress dialog
+ m_progressDlg.reset(new KProgressDialog(this, "progressDlg", "Loading...",
+ "Loading file ", true));
+ m_progressDlg->setLabel("Loading file " + m_url.path());
+ m_progressDlg->setAllowCancel(true);
+ m_progressDlg->progressBar()->setTotalSteps(0);
+ connect(m_progressDlg.get(), SIGNAL(cancelClicked()), SLOT(cancelLoading()));
+ KDialog::centerOnScreen(m_progressDlg.get());
+ m_progressDlg->show();
+ //start timer for processing gui events
+ m_timer.start(0, false);
+ //load bookmark for the book
+ loadBookmarks();
+ // just for fun, set the status bar
+ emit signalChangeStatusbar(m_url.prettyURL());
+}
+
+QString BookWidget::currentURL()
+{
+ return m_url.path();
+}
+
+void BookWidget::drawContent(QPainter& paint)
+{
+ const QRect lrect (rectLeftPage());
+ const QRect rrect(rectRightPage());
+ const unsigned int curPage = currentPage();
+ //draw pages
+ m_renderer->drawPage(paint, lrect, curPage);
+ m_renderer->drawPage(paint, rrect, curPage + 1);
+}
+
+void BookWidget::drawPageNumbers(QPainter & paint)
+{
+ if (m_renderer->isEmpty())
+ return;
+ const QRect lrect (rectLeftPage());
+ const QRect rrect(rectRightPage());
+ const QString number = QString::number(currentPage() + 2);
+ // setup font
+ QFont pageFont(font());
+ int pointSize = 10;
+ pageFont.setPointSize(pointSize);
+ pageFont.setBold(false);
+ pageFont.setItalic(false);
+ pageFont.setUnderline(false);
+ paint.setFont(pageFont);
+ const QFontMetrics fm(pageFont);
+ const int width = fm.width(number);
+ //paint page numbers
+ const int offset = 8;
+ paint.drawText(lrect.left(), QWidget::height() - offset,
+ QString::number(currentPage() + 1));
+ paint.drawText(rrect.left() + rrect.width() - width,
+ QWidget::height() - offset, number);
+}
+
+void BookWidget::drawBookmark(QPainter & paint, Bookmark const& bm)
+{
+ const QRect lrect (rectLeftPage());
+ const QRect rrect(rectRightPage());
+ const QPixmap & bookmarkImage = Theme::self()->bookmarkPixmap();
+ const int width = bookmarkImage.width();
+ paint.drawPixmap(QWidget::width()/2 - width/2, 0, bookmarkImage);
+ if (!bm.name().isEmpty())
+ {
+ paint.save();
+ paint.translate(QWidget::width()/2., 20.);
+ paint.rotate(90.);
+ const QString text = bm.name() + " (" + bm.dateTime().toString(Qt::LocalDate) + ")";
+ paint.drawText(0, 0, text);
+ paint.restore();
+ }
+}
+
+void BookWidget::paintEvent(QPaintEvent* event)
+{
+ // use cached page pixmap if the page wasn't modified
+ if (!modified())
+ {
+ QRect rect(event->rect());
+ bitBlt(this, rect.x(), rect.y(), &m_cachePixmap, rect.x(), rect.y(), rect.width(), rect.height());
+ return;
+ }
+ // do full painting otherwise
+ setupPageSize();
+ const QRect lrect (rectLeftPage());
+ const QRect rrect(rectRightPage());
+ const unsigned int curPage = currentPage();
+ QPixmap pm(size());
+ QPainter paint(&pm);
+ //draw background image
+ const QPixmap & image = Theme::self()->bgPixmap(QWidget::size());
+ paint.drawPixmap(0, 0, image);
+ if (m_renderer->busy())
+ {
+ QFont f(font());
+ f.setPointSize(20);
+ paint.setFont(f);
+ const QFontMetrics fm(f);
+ QString text = tr("Rendering...");
+ const int w = fm.width(text);
+ const int h = fm.height();
+ const int dx = (lrect.width() - w) / 2;
+ const int dy = (lrect.height() - h) / 2;
+ paint.drawText(lrect.x() + dx, lrect.y() + dy, text);
+ paint.drawText(rrect.x() + dx, rrect.y() + dy, text);
+ }
+ else
+ {
+ paint.setFont(font());
+ //draw pages
+ drawContent(paint);
+ drawPageNumbers(paint);
+ //draw bookmark if it is
+ typedef Bookmarks::const_iterator IT;
+ IT it = std::lower_bound(m_bookmarks.begin(), m_bookmarks.end(), curPage);
+ if (it != m_bookmarks.end() && (*it).page() == curPage)
+ drawBookmark(paint, *it);
+ }
+ paint.end();
+ bitBlt(this, 0, 0, &pm);
+ // store painted pixmap as cache
+ m_cachePixmap = pm;
+ m_modified = false;
+}
+
+void BookWidget::setupPageSize()
+{
+ QSize size((width() - m_left_margin - m_right_margin - 2 * m_middle_margin) / 2,
+ (height() - m_top_margin - m_bottom_margin));
+ m_renderer->setPageSize(size);
+}
+
+void BookWidget::mousePressEvent(QMouseEvent * event)
+{
+ if (event->button() == LeftButton)
+ {
+ if (rectLeftPage().contains(event->pos()))
+ {
+ prevPage();
+ }
+ else if (rectRightPage().contains(event->pos()))
+ {
+ nextPage();
+ }
+ }
+ QWidget::mousePressEvent(event);
+}
+
+const QRect BookWidget::rectLeftPage() const
+{
+ return QRect(m_left_margin, m_top_margin,
+ m_renderer->pageSize().width(),
+ m_renderer->pageSize().height());
+}
+
+const QRect BookWidget::rectRightPage() const
+{
+ return QRect(m_left_margin + 2 * m_middle_margin + m_renderer->pageSize().width(),
+ m_top_margin,
+ m_renderer->pageSize().width(),
+ m_renderer->pageSize().height());
+}
+
+void BookWidget::clearAll()
+{
+ setCurrentPage(0);
+}
+
+
+void BookWidget::prevPage()
+{
+ setCurrentPage(currentPage() - 2);
+}
+
+void BookWidget::nextPage()
+{
+ setCurrentPage(currentPage() + 2);
+}
+
+void BookWidget::firstPage()
+{
+ setCurrentPage(0);
+}
+
+void BookWidget::lastPage()
+{
+ setCurrentPage(m_renderer->pageCount() - 1);
+}
+
+void BookWidget::wheelEvent(QWheelEvent * e)
+{
+ e->accept();
+ if (e->delta() > 0)
+ prevPage();
+ else nextPage();
+}
+
+void BookWidget::resizeEvent(QResizeEvent * e)
+{
+ m_modified = true;
+ setupPageSize();
+ m_renderer->render();
+// //if size become lower recalc current page
+// if (currentPage() > m_renderer->pageCount())
+// lastPage();
+ QWidget::resizeEvent(e);
+}
+
+QSize BookWidget::minimumSizeHint() const
+{
+ return QSize(400, 300);
+}
+
+void BookWidget::setFont(const QFont & font)
+{
+ m_modified = true;
+ QWidget::setFont(font);
+ m_renderer->setFont(font);
+ update();
+}
+
+void BookWidget::setCurrentPage(int number)
+{
+ // do nothing while renderer is working
+ if (m_renderer->busy())
+ return;
+ if (number >= m_renderer->pageCount())
+ number = m_renderer->pageCount() - 1;
+ if (number < 0) number = 0;
+ //only even page numbers allowed
+ int newPage = (number % 2) ? number - 1 : number;
+ if (newPage != m_currentPage)
+ m_modified = true;
+ m_currentPage = newPage;
+ update();
+}
+
+void BookWidget::keyPressEvent(QKeyEvent * e)
+{
+ if (e->key() == Qt::Key_Right || e->key() == Qt::Key_Down
+ || e->key() == Qt::Key_Space)
+ {
+ nextPage();
+ }
+ else if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Up)
+ {
+ prevPage();
+ }
+ else if (e->key() == Qt::Key_Home)
+ {
+ firstPage();
+ }
+ else if (e->key() == Qt::Key_End)
+ {
+ lastPage();
+ }
+
+ QWidget::keyPressEvent(e);
+}
+
+void BookWidget::loadLine()
+{
+ static int lineCount = 0;
+ if (!m_stream->eof())
+ {
+ *m_textLines << m_stream->readLine();
+ //progress update after every 50 lines
+ if (!(++lineCount % 50))
+ m_progressDlg->progressBar()->setProgress(
+ m_progressDlg->progressBar()->progress() + 1);
+ return;
+ }
+ m_timer.stop();
+ //render
+ m_renderer->load(*m_textLines);
+ //setup and show
+ firstPage();
+ //clean up
+ m_progressDlg.reset(0);
+ m_stream.reset(0);
+ m_textLines.reset(0);
+ m_file.close();
+ m_modified = true;
+ emit loadingFinished();
+}
+
+void BookWidget::cancelLoading()
+{
+ m_timer.stop();
+ if (parentWidget())
+ parentWidget()->setCaption("");
+ //clean up
+ m_progressDlg->hide();
+ m_stream.reset(0);
+ m_textLines.reset(0);
+ m_file.close();
+ //setup and show
+ m_renderer->clear();
+ firstPage();
+}
+
+void BookWidget::setParaOffset(int offset)
+{
+ m_modified = true;
+ m_renderer->setParaOffset(offset);
+ update();
+}
+
+void BookWidget::setEncoding(int a_encoding)
+{
+ m_encoding = a_encoding;
+}
+
+void BookWidget::setEncodings(const QStringList & a_encodings)
+{
+ m_encodings = a_encodings;
+}
+
+void BookWidget::setEncoding(const QString & a_encoding)
+{
+ m_encoding = (m_encodings.findIndex(a_encoding));
+}
+
+void BookWidget::addBookmark(const QString& name)
+{
+ m_bookmarks.push_back(Bookmark(currentPage(), name));
+ std::sort(m_bookmarks.begin(), m_bookmarks.end());
+
+// KAction menu = new KAction()
+
+ saveBookmarks();
+}
+
+void BookWidget::saveBookmarks( )
+{
+ const QString fileName = "bookreader/" + m_url.fileName();
+ QFile::remove(KGlobal::dirs()->findResource("appdata", m_url.fileName()));
+ KConfig config(fileName, false, false, "data");
+ for (Bookmarks::size_type i = 0; i < m_bookmarks.size(); ++i)
+ {
+ const Bookmark & bm = m_bookmarks[i];
+ config.setGroup(tr("Bookmark %1").arg(i));
+ config.writeEntry("page", bm.page());
+ config.writeEntry("name", bm.name());
+ config.writeEntry("dateTime", bm.dateTime());
+ }
+}
+
+void BookWidget::loadBookmarks()
+{
+ m_bookmarks.clear();
+ const QString fileName = "bookreader/" + m_url.fileName();
+ KConfig config(fileName, true, false, "data");
+ QStringList groups = config.groupList();
+ typedef QStringList::const_iterator IT;
+ for (IT it = groups.constBegin(); it != groups.constEnd(); ++it)
+ {
+ config.setGroup(*it);
+ const QString name = config.readEntry("name");
+ const unsigned int page = config.readUnsignedNumEntry("page");
+ const QDateTime dateTime = config.readDateTimeEntry("dateTime");
+ const Bookmark bm(page, name, dateTime);
+ m_bookmarks.push_back(bm);
+ }
+ std::sort(m_bookmarks.begin(), m_bookmarks.end());
+}
+
+void BookWidget::setBookmarks(const Bookmarks & bms)
+{
+ m_bookmarks.clear();
+ m_bookmarks = bms;
+ std::sort(m_bookmarks.begin(), m_bookmarks.end());
+ saveBookmarks();
+}
+
+void BookWidget::renderingFinished()
+{
+ m_modified = true;
+ setCurrentPage(currentPage());
+ update();
+}
+
+#include "bookwidget.moc"