/*************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include "bookwidget.h" #include "theme.h" #include "settings.h" #include "renderer.h" //#include "ktextprogressdlg.h" class TQStringList; class TQRect; class TQPixmap; BookWidget::BookWidget(TQWidget *parent, const char *name) : TQWidget(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(TQt::WNoAutoErase); setFocusPolicy(TQWidget::StrongFocus); connect(&m_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(loadLine())); connect(m_renderer.get(), TQT_SIGNAL(renderingFinished()), this, TQT_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 TQTextStream(&m_file)); m_textLines.reset(new TQStringList); TQString name(encoding()); TQTextCodec *codec = TQTextCodec::codecForName(encoding().latin1()); // 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(), TQT_SIGNAL(cancelClicked()), TQT_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()); } TQString BookWidget::currentURL() { return m_url.path(); } void BookWidget::drawContent(TQPainter& paint) { const TQRect lrect (rectLeftPage()); const TQRect 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(TQPainter & paint) { if (m_renderer->isEmpty()) return; const TQRect lrect (rectLeftPage()); const TQRect rrect(rectRightPage()); const TQString number = TQString::number(currentPage() + 2); // setup font TQFont pageFont(font()); int pointSize = 10; pageFont.setPointSize(pointSize); pageFont.setBold(false); pageFont.setItalic(false); pageFont.setUnderline(false); paint.setFont(pageFont); const TQFontMetrics fm(pageFont); const int width = fm.width(number); //paint page numbers const int offset = 8; paint.drawText(lrect.left(), TQWidget::height() - offset, TQString::number(currentPage() + 1)); paint.drawText(rrect.left() + rrect.width() - width, TQWidget::height() - offset, number); } void BookWidget::drawBookmark(TQPainter & paint, Bookmark const& bm) { const TQRect lrect (rectLeftPage()); const TQRect rrect(rectRightPage()); const TQPixmap & bookmarkImage = Theme::self()->bookmarkPixmap(); const int width = bookmarkImage.width(); paint.drawPixmap(TQWidget::width()/2 - width/2, 0, bookmarkImage); if (!bm.name().isEmpty()) { paint.save(); paint.translate(TQWidget::width()/2., 20.); paint.rotate(90.); const TQString text = bm.name() + " (" + bm.dateTime().toString(Qt::LocalDate) + ")"; paint.drawText(0, 0, text); paint.restore(); } } void BookWidget::paintEvent(TQPaintEvent* event) { // use cached page pixmap if the page wasn't modified if (!modified()) { TQRect 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 TQRect lrect (rectLeftPage()); const TQRect rrect(rectRightPage()); const unsigned int curPage = currentPage(); TQPixmap pm(size()); TQPainter paint(&pm); //draw background image const TQPixmap & image = Theme::self()->bgPixmap(TQWidget::size()); paint.drawPixmap(0, 0, image); if (m_renderer->busy()) { TQFont f(font()); f.setPointSize(20); paint.setFont(f); const TQFontMetrics fm(f); TQString 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() { TQSize 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(TQMouseEvent * event) { if (event->button() == Qt::LeftButton) { if (rectLeftPage().contains(event->pos())) { prevPage(); } else if (rectRightPage().contains(event->pos())) { nextPage(); } } TQWidget::mousePressEvent(event); } const TQRect BookWidget::rectLeftPage() const { return TQRect(m_left_margin, m_top_margin, m_renderer->pageSize().width(), m_renderer->pageSize().height()); } const TQRect BookWidget::rectRightPage() const { return TQRect(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(TQWheelEvent * e) { e->accept(); if (e->delta() > 0) prevPage(); else nextPage(); } void BookWidget::resizeEvent(TQResizeEvent * e) { m_modified = true; setupPageSize(); m_renderer->render(); // //if size become lower recalc current page // if (currentPage() > m_renderer->pageCount()) // lastPage(); TQWidget::resizeEvent(e); } TQSize BookWidget::minimumSizeHint() const { return TQSize(400, 300); } void BookWidget::setFont(const TQFont & font) { m_modified = true; TQWidget::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(TQKeyEvent * e) { if (e->key() == TQt::Key_Right || e->key() == TQt::Key_Down || e->key() == TQt::Key_Space) { nextPage(); } else if (e->key() == TQt::Key_Left || e->key() == TQt::Key_Up) { prevPage(); } else if (e->key() == TQt::Key_Home) { firstPage(); } else if (e->key() == TQt::Key_End) { lastPage(); } TQWidget::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()) TQT_TQWIDGET(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 TQStringList & a_encodings) { m_encodings = a_encodings; } void BookWidget::setEncoding(const TQString & a_encoding) { m_encoding = (m_encodings.findIndex(a_encoding)); } void BookWidget::addBookmark(const TQString& name) { m_bookmarks.push_back(Bookmark(currentPage(), name)); std::sort(m_bookmarks.begin(), m_bookmarks.end()); // TDEAction menu = new TDEAction() saveBookmarks(); } void BookWidget::saveBookmarks( ) { const TQString fileName = "kbookreader/" + m_url.fileName(); TQFile::remove(TDEGlobal::dirs()->findResource("appdata", m_url.fileName())); TDEConfig config(fileName, false, false, "data"); for (Bookmarks::size_type i = 0; i < m_bookmarks.size(); ++i) { const Bookmark & bm = m_bookmarks[i]; config.setGroup(tqtr("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 TQString fileName = "kbookreader/" + m_url.fileName(); TDEConfig config(fileName, true, false, "data"); TQStringList groups = config.groupList(); typedef TQStringList::const_iterator IT; for (IT it = groups.constBegin(); it != groups.constEnd(); ++it) { config.setGroup(*it); const TQString name = config.readEntry("name"); const unsigned int page = config.readUnsignedNumEntry("page"); const TQDateTime 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"