|
|
|
/***************************************************************************
|
|
|
|
* 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 <tqpainter.h>
|
|
|
|
#include <tqevent.h>
|
|
|
|
#include <tqimage.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kprogress.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
#include <tqtextcodec.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#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(TQ_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()); // 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());
|
|
|
|
|
|
|
|
// KAction menu = new KAction()
|
|
|
|
|
|
|
|
saveBookmarks();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BookWidget::saveBookmarks( )
|
|
|
|
{
|
|
|
|
const TQString fileName = "bookreader/" + 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 = "bookreader/" + 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"
|