[app] Implemented text selection (whole words)

The selected text is getting copied to clipboard.
This commit is contained in:
Slava Monich 2017-09-07 19:03:17 +03:00
parent a48fe1d0e4
commit 89775f269e
6 changed files with 432 additions and 54 deletions

View file

@ -41,6 +41,7 @@ SilicaFlickable {
id: root
property variant book
property bool selecting
signal closeBook()
signal pageClicked(var page)
@ -56,7 +57,8 @@ SilicaFlickable {
{ pager: true, page: true, title: true, tools: true }
]
interactive: (!linkMenu || !linkMenu.visible) &&
interactive: !selecting &&
(!linkMenu || !linkMenu.visible) &&
(!imageView || !imageView.visible) &&
(!footnoteView || !footnoteView.visible)
@ -168,6 +170,7 @@ SilicaFlickable {
}
delegate: BooksPageView {
id: pageView
width: bookView.width
height: bookView.height
model: bookModel
@ -180,15 +183,26 @@ SilicaFlickable {
rightSpaceReserved: pageTools.visible ? pageTools.rightSpaceUsed: 0
titleVisible: _currentState.title
pageNumberVisible: _currentState.page
currentPage: bookViewWatcher.currentIndex == index
title: bookModel.title
onJumpToPage: bookView.jumpTo(page)
onPushPosition: stackModel.pushPosition(position) // bookView.jumpTo(page)
onCurrentPageChanged: {
if (currentPage) {
root.selecting = pageView.selecting
}
}
onSelectingChanged: {
if (currentPage) {
root.selecting = pageView.selecting
}
}
onPageClicked: {
root.pageClicked(index)
Settings.pageDetails = (Settings.pageDetails + 1) % _visibilityStates.length
}
onImagePressed: {
if (bookViewWatcher.currentIndex == index) {
if (currentPage) {
if (!imageView) {
imageView = imageViewComponent.createObject(root)
}
@ -196,7 +210,7 @@ SilicaFlickable {
}
}
onBrowserLinkPressed: {
if (bookViewWatcher.currentIndex == index) {
if (currentPage) {
if (!linkMenu) {
linkMenu = linkMenuComponent.createObject(root)
}

View file

@ -43,6 +43,8 @@ Item {
property alias rightMargin: widget.rightMargin
property alias topMargin: widget.topMargin
property alias bottomMargin: widget.bottomMargin
property alias selecting: widget.selecting
property alias currentPage: widget.currentPage
property alias title: titleLabel.text
property real leftSpaceReserved
property real rightSpaceReserved
@ -60,6 +62,7 @@ Item {
id: widget
anchors.fill: parent
model: bookModel
pressed: mouseArea.pressed
onBrowserLinkPressed: view.browserLinkPressed(url)
onImagePressed: view.imagePressed(imageId, rect)
onActiveTouch: pressImage.animate(touchX, touchY)
@ -156,9 +159,17 @@ Item {
}
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: view.pageClicked()
onClicked: {
if (widget.selectionEmpty) {
view.pageClicked()
} else {
widget.clearSelection()
}
}
onPressed: widget.handlePress(mouseX, mouseY)
onPressAndHold: widget.handleLongPress(mouseX, mouseY)
onPositionChanged: widget.handlePositionChanged(mouseX, mouseY)
}
}

View file

@ -42,6 +42,8 @@
#include "HarbourDebug.h"
#include <QGuiApplication>
#include <QClipboard>
#include <QPainter>
static const QString IMAGE_URL("image://%1/%2");
@ -136,7 +138,7 @@ void BooksPageWidget::ResetTask::performTask()
class BooksPageWidget::RenderTask : public BooksTask {
public:
RenderTask(shared_ptr<BooksPageWidget::Data> aData, int aWidth, int aHeight) :
iData(aData), iWidth(aWidth), iHeight(aHeight), iImage(NULL) {}
iData(aData), iWidth(aWidth), iHeight(aHeight) {}
void performTask();
@ -159,6 +161,119 @@ void BooksPageWidget::RenderTask::performTask()
}
}
// ==========================================================================
// BooksPageWidget::ClearSelectionTask
// ==========================================================================
class BooksPageWidget::ClearSelectionTask : public BooksTask {
public:
ClearSelectionTask(shared_ptr<BooksPageWidget::Data> aData, int aWidth,
int aHeight) : iData(aData), iWidth(aWidth), iHeight(aHeight),
iImageUpdated(false) {}
void performTask();
public:
shared_ptr<BooksPageWidget::Data> iData;
int iWidth;
int iHeight;
QImage iImage;
bool iImageUpdated;
};
void BooksPageWidget::ClearSelectionTask::performTask()
{
iData->iView->endSelection();
if (!isCanceled() && iWidth > 0 && iHeight > 0) {
const ZLTextArea& area = iData->iView->textArea();
if (!area.selectionIsEmpty()) {
area.clearSelection();
iImage = QImage(iWidth, iHeight, QImage::Format_RGB32);
if (!isCanceled()) {
QPainter painter(&iImage);
iData->paint(&painter);
iImageUpdated = true;
}
}
}
}
// ==========================================================================
// BooksPageWidget::StartSelectionTask
// ==========================================================================
class BooksPageWidget::StartSelectionTask : public BooksTask {
public:
StartSelectionTask(shared_ptr<BooksPageWidget::Data> aData, int aX, int aY,
int aWidth, int aHeight) : iData(aData), iX(aX), iY(aY),
iWidth(aWidth), iHeight(aHeight), iSelectionEmpty(true) {}
void performTask();
public:
shared_ptr<BooksPageWidget::Data> iData;
int iX;
int iY;
int iWidth;
int iHeight;
QImage iImage;
bool iSelectionEmpty;
};
void BooksPageWidget::StartSelectionTask::performTask()
{
if (!isCanceled() && iWidth > 0 && iHeight > 0) {
iData->iView->startSelection(iX, iY);
iSelectionEmpty = iData->iView->textArea().selectionIsEmpty();
if (!isCanceled()) {
iImage = QImage(iWidth, iHeight, QImage::Format_RGB32);
if (!isCanceled()) {
QPainter painter(&iImage);
iData->paint(&painter);
}
}
}
}
// ==========================================================================
// BooksPageWidget::ExtendSelectionTask
// ==========================================================================
class BooksPageWidget::ExtendSelectionTask : public BooksTask {
public:
ExtendSelectionTask(shared_ptr<BooksPageWidget::Data> aData, int aX, int aY,
int aWidth, int aHeight) : iData(aData), iX(aX), iY(aY),
iWidth(aWidth), iHeight(aHeight), iSelectionChanged(false),
iSelectionEmpty(true) {}
void performTask();
public:
shared_ptr<BooksPageWidget::Data> iData;
int iX;
int iY;
int iWidth;
int iHeight;
QImage iImage;
bool iSelectionChanged;
bool iSelectionEmpty;
};
void BooksPageWidget::ExtendSelectionTask::performTask()
{
if (!isCanceled() && iWidth > 0 && iHeight > 0) {
iSelectionChanged = iData->iView->extendSelection(iX, iY);
iSelectionEmpty = iData->iView->textArea().selectionIsEmpty();
if (iSelectionChanged && !isCanceled()) {
iImage = QImage(iWidth, iHeight, QImage::Format_RGB32);
if (!isCanceled()) {
QPainter painter(&iImage);
iData->paint(&painter);
}
}
}
}
// ==========================================================================
// BooksPageWidget::FootnoteTask
// ==========================================================================
@ -380,10 +495,16 @@ BooksPageWidget::BooksPageWidget(QQuickItem* aParent) :
iModel(NULL),
iResetTask(NULL),
iRenderTask(NULL),
iClearSelectionTask(NULL),
iStartSelectionTask(NULL),
iPressTask(NULL),
iLongPressTask(NULL),
iFootnoteTask(NULL),
iEmpty(false),
iPressed(false),
iSelecting(false),
iSelectionEmpty(true),
iCurrentPage(false),
iPage(-1)
{
connect(iSettings.data(),
@ -403,13 +524,48 @@ BooksPageWidget::BooksPageWidget(QQuickItem* aParent) :
BooksPageWidget::~BooksPageWidget()
{
HDEBUG("page" << iPage);
releaseExtendSelectionTasks();
if (iResetTask) iResetTask->release(this);
if (iRenderTask) iRenderTask->release(this);
if (iClearSelectionTask) iClearSelectionTask->release(this);
if (iStartSelectionTask) iStartSelectionTask->release(this);
if (iPressTask) iPressTask->release(this);
if (iLongPressTask) iLongPressTask->release(this);
if (iFootnoteTask) iFootnoteTask->release(this);
}
void BooksPageWidget::releaseExtendSelectionTasks()
{
while (!iExtendSelectionTasks.isEmpty()) {
const int i = iExtendSelectionTasks.count()-1;
iExtendSelectionTasks.at(i)->release(this);
iExtendSelectionTasks.removeAt(i);
}
}
void BooksPageWidget::setPressed(bool aPressed)
{
if (iPressed != aPressed) {
iPressed = aPressed;
if (!iPressed && iSelecting) {
HDEBUG("leaving selection mode");
iSelecting = false;
Q_EMIT selectingChanged();
}
Q_EMIT pressedChanged();
}
}
void BooksPageWidget::setCurrentPage(bool aCurrentPage)
{
if (iCurrentPage != aCurrentPage) {
iCurrentPage = aCurrentPage;
HDEBUG(iCurrentPage);
if (!iCurrentPage) clearSelection();
Q_EMIT currentPageChanged();
}
}
void BooksPageWidget::setModel(BooksBookModel* aModel)
{
if (iModel != aModel) {
@ -582,7 +738,7 @@ void BooksPageWidget::paint(QPainter* aPainter)
bool BooksPageWidget::loading() const
{
return iPage >= 0 && (iResetTask || iRenderTask);
return iPage >= 0 && iImage.isNull() && (iResetTask || iRenderTask);
}
void BooksPageWidget::resetView()
@ -680,6 +836,75 @@ void BooksPageWidget::onPressTaskDone()
task->release(this);
}
void BooksPageWidget::onClearSelectionTaskDone()
{
HASSERT(sender() == iClearSelectionTask);
ClearSelectionTask* task = iClearSelectionTask;
iClearSelectionTask = NULL;
if (!iSelectionEmpty) {
iSelectionEmpty = true;
HDEBUG("selection cleared");
Q_EMIT selectionEmptyChanged();
}
if (task->iImageUpdated) {
iImage = task->iImage;
update();
}
task->release(this);
}
void BooksPageWidget::onStartSelectionTaskDone()
{
HASSERT(sender() == iStartSelectionTask);
StartSelectionTask* task = iStartSelectionTask;
iStartSelectionTask = NULL;
if (iPressed) {
iImage = task->iImage;
// Emit signals when we are in a consistent state
bool emitSelectionEmpty;
if (iSelectionEmpty != task->iSelectionEmpty) {
iSelectionEmpty = task->iSelectionEmpty;
HDEBUG("selection" << iSelectionEmpty);
emitSelectionEmpty = true;
}
if (!iSelecting) {
iSelecting = true;
HDEBUG("entering selection mode");
Q_EMIT selectingChanged();
}
if (emitSelectionEmpty) {
Q_EMIT selectionEmptyChanged();
}
update();
}
task->release(this);
}
void BooksPageWidget::onExtendSelectionTaskDone()
{
ExtendSelectionTask* task = (ExtendSelectionTask*)sender();
HASSERT(iExtendSelectionTasks.contains(task));
iExtendSelectionTasks.removeOne(task);
if (iSelecting && task->iSelectionChanged) {
iImage = task->iImage;
if (iSelectionEmpty != task->iSelectionEmpty) {
iSelectionEmpty = task->iSelectionEmpty;
HDEBUG("selection" << iSelectionEmpty);
Q_EMIT selectionEmptyChanged();
}
update();
}
task->release(this);
}
void BooksPageWidget::onFootnoteTaskDone()
{
HASSERT(sender() == iFootnoteTask);
@ -769,6 +994,12 @@ void BooksPageWidget::onLongPressTaskDone()
BooksImageProvider::instance()->addImage(iModel, id, task->iImage);
Q_EMIT imagePressed(IMAGE_URL.arg(BooksImageProvider::PROVIDER_ID, id),
task->iRect);
} else if (!iData.isNull()) {
if (iStartSelectionTask) iStartSelectionTask->release(this);
iStartSelectionTask = new StartSelectionTask(iData,
task->iX, task->iY, width(), height());
iTaskQueue->submit(iStartSelectionTask, this,
SLOT(onStartSelectionTaskDone()));
}
task->release(this);
@ -813,8 +1044,8 @@ void BooksPageWidget::handleLongPress(int aX, int aY)
HDEBUG(aX << aY);
if (!iResetTask && !iRenderTask && !iData.isNull()) {
if (iLongPressTask) iLongPressTask->release(this);
iLongPressTask = new PressTask(iData, aX, aY);
iTaskQueue->submit(iLongPressTask, this, SLOT(onLongPressTaskDone()));
iTaskQueue->submit(iLongPressTask = new PressTask(iData, aX, aY),
this, SLOT(onLongPressTaskDone()));
}
}
@ -823,7 +1054,50 @@ void BooksPageWidget::handlePress(int aX, int aY)
HDEBUG(aX << aY);
if (!iResetTask && !iRenderTask && !iData.isNull()) {
if (iPressTask) iPressTask->release(this);
iPressTask = new PressTask(iData, aX, aY);
iTaskQueue->submit(iPressTask, this, SLOT(onPressTaskDone()));
iTaskQueue->submit(iPressTask = new PressTask(iData, aX, aY),
this, SLOT(onPressTaskDone()));
}
}
void BooksPageWidget::handlePositionChanged(int aX, int aY)
{
if (iSelecting && !iData.isNull()) {
HDEBUG(aX << aY);
// Drop the tasks which haven't been started yet
ExtendSelectionTask* task;
for (int i = iExtendSelectionTasks.count()-1; i>=0; i--) {
task = iExtendSelectionTasks.at(i);
if (task->isStarted()) {
break;
} else {
task->release(this);
iExtendSelectionTasks.removeAt(i);
HDEBUG("dropped queued task," << i << "left");
}
}
task = new ExtendSelectionTask(iData, aX, aY, width(), height());
iTaskQueue->submit(task, this, SLOT(onExtendSelectionTaskDone()));
iExtendSelectionTasks.append(task);
} else {
// Finger was moved before we entered selection mode
if (iStartSelectionTask) {
iStartSelectionTask->release(this);
iStartSelectionTask = NULL;
HDEBUG("oops");
}
}
}
void BooksPageWidget::clearSelection()
{
if (!iData.isNull()) {
if (iClearSelectionTask) iClearSelectionTask->release(this);
iTaskQueue->submit(iClearSelectionTask =
new ClearSelectionTask(iData, width(), height()),
this, SLOT(onClearSelectionTaskDone()));
}
if (iSelecting) {
iSelecting = false;
Q_EMIT selectingChanged();
}
}

View file

@ -47,11 +47,16 @@
#include <QQuickPaintedItem>
#include <QTimer>
#include <QList>
class BooksPageWidget: public QQuickPaintedItem, private BooksLoadingProperty
{
Q_OBJECT
Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged)
Q_PROPERTY(bool selecting READ selecting NOTIFY selectingChanged)
Q_PROPERTY(bool selectionEmpty READ selectionEmpty NOTIFY selectionEmptyChanged)
Q_PROPERTY(bool pressed READ pressed WRITE setPressed NOTIFY pressedChanged)
Q_PROPERTY(bool currentPage READ currentPage WRITE setCurrentPage NOTIFY currentPageChanged)
Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged)
Q_PROPERTY(int leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
@ -62,34 +67,48 @@ class BooksPageWidget: public QQuickPaintedItem, private BooksLoadingProperty
public:
class Data;
BooksPageWidget(QQuickItem* aParent = NULL);
explicit BooksPageWidget(QQuickItem* aParent = NULL);
~BooksPageWidget();
bool loading() const;
bool selecting() const;
bool selectionEmpty() const;
int page() const { return iPage; }
bool pressed() const;
void setPressed(bool aPressed);
bool currentPage() const;
void setCurrentPage(bool aCurrentPage);
int page() const;
void setPage(int aPage);
BooksBookModel* model() const { return iModel; }
BooksBookModel* model() const;
void setModel(BooksBookModel* aModel);
int leftMargin() const { return iMargins.iLeft; }
int rightMargin() const { return iMargins.iRight; }
int topMargin() const { return iMargins.iTop; }
int bottomMargin() const { return iMargins.iBottom; }
int leftMargin() const;
int rightMargin() const;
int topMargin() const;
int bottomMargin() const;
void setLeftMargin(int aMargin);
void setRightMargin(int aMargin);
void setTopMargin(int aMargin);
void setBottomMargin(int aMargin);
BooksMargins margins() const { return iMargins; }
BooksMargins margins() const;
Q_INVOKABLE void handleLongPress(int aX, int aY);
Q_INVOKABLE void handlePress(int aX, int aY);
Q_INVOKABLE void handleLongPress(int aX, int aY);
Q_INVOKABLE void handlePositionChanged(int aX, int aY);
Q_INVOKABLE void clearSelection();
Q_SIGNALS:
void loadingChanged();
void pressedChanged();
void selectingChanged();
void selectionEmptyChanged();
void currentPageChanged();
void pageChanged();
void modelChanged();
void leftMarginChanged();
@ -115,6 +134,9 @@ private Q_SLOTS:
void onInvertColorsChanged();
void onResetTaskDone();
void onRenderTaskDone();
void onClearSelectionTaskDone();
void onStartSelectionTaskDone();
void onExtendSelectionTaskDone();
void onPressTaskDone();
void onLongPressTaskDone();
void onFootnoteTaskDone();
@ -123,6 +145,7 @@ private:
void paint(QPainter *painter);
void updateSize();
void resetView();
void releaseExtendSelectionTasks();
void scheduleRepaint();
void cancelRepaint();
bool invertColors() const;
@ -131,6 +154,9 @@ private:
class ResetTask;
class RenderTask;
class PressTask;
class ClearSelectionTask;
class StartSelectionTask;
class ExtendSelectionTask;
class FootnoteTask;
QSharedPointer<BooksSettings> iSettings;
@ -144,13 +170,42 @@ private:
QImage iImage;
ResetTask* iResetTask;
RenderTask* iRenderTask;
ClearSelectionTask* iClearSelectionTask;
StartSelectionTask* iStartSelectionTask;
QList<ExtendSelectionTask*> iExtendSelectionTasks;
PressTask* iPressTask;
PressTask* iLongPressTask;
FootnoteTask* iFootnoteTask;
bool iEmpty;
bool iPressed;
bool iSelecting;
bool iSelectionEmpty;
bool iCurrentPage;
int iPage;
};
inline bool BooksPageWidget::pressed() const
{ return iPressed; }
inline bool BooksPageWidget::selecting() const
{ return iSelecting; }
inline bool BooksPageWidget::selectionEmpty() const
{ return iSelectionEmpty; }
inline bool BooksPageWidget::currentPage() const
{ return iCurrentPage; }
inline int BooksPageWidget::page() const
{ return iPage; }
inline BooksBookModel* BooksPageWidget::model() const
{ return iModel; }
inline int BooksPageWidget::leftMargin() const
{ return iMargins.iLeft; }
inline int BooksPageWidget::rightMargin() const
{ return iMargins.iRight; }
inline int BooksPageWidget::topMargin() const
{ return iMargins.iTop; }
inline int BooksPageWidget::bottomMargin() const
{ return iMargins.iBottom; }
inline BooksMargins BooksPageWidget::margins() const
{ return iMargins; }
inline bool BooksPageWidget::invertColors() const
{ return iSettings && iSettings->invertColors(); }

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2016 Jolla Ltd.
* Copyright (C) 2015-2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
@ -14,7 +14,7 @@
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Nemo Mobile nor the names of its contributors
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
@ -34,6 +34,8 @@
#include "BooksTextView.h"
#include "BooksTextStyle.h"
#include "ZLTextSelectionModel.h"
#define SUPER ZLTextView
const ZLColor BooksTextView::DEFAULT_BACKGROUND(255, 255, 255);
@ -97,12 +99,12 @@ shared_ptr<ZLTextStyle> BooksTextView::baseStyle() const
bool BooksTextView::isSelectionEnabled() const
{
return false;
return true;
}
int BooksTextView::doubleClickDelay() const
{
return isSelectionEnabled() ? 200 : 0;
return 0;
}
shared_ptr<ZLTextPositionIndicatorInfo> BooksTextView::indicatorInfo() const
@ -140,3 +142,22 @@ void BooksTextView::gotoPosition(const BooksPos& aPos)
SUPER::gotoPosition(aPos.iParagraphIndex, aPos.iElementIndex,
aPos.iCharIndex);
}
void BooksTextView::startSelection(int aX, int aY)
{
if (!selectionModel().selectWord(textArea().realX(aX), aY, true)) {
// There's no text where we have clicked
activateSelection(aX, aY);
}
}
bool BooksTextView::extendSelection(int aX, int aY)
{
return selectionModel().extendTo(textArea().realX(aX), aY, true) ==
ZLTextSelectionModel::BOUND_CHANGED;
}
void BooksTextView::endSelection()
{
selectionModel().deactivate();
}

View file

@ -1,35 +1,35 @@
/*
Copyright (C) 2015 Jolla Ltd.
Contact: Slava Monich <slava.monich@jolla.com>
You may use this file under the terms of the BSD license as follows:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Nemo Mobile nor the names of its contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
* Copyright (C) 2015-2017 Jolla Ltd.
* Contact: Slava Monich <slava.monich@jolla.com>
*
* You may use this file under the terms of the BSD license as follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Jolla Ltd nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BOOKS_TEXT_VIEW_H
#define BOOKS_TEXT_VIEW_H
@ -57,6 +57,9 @@ public:
public:
BooksPos position() const;
const BooksPos rewind();
void startSelection(int aX, int aY);
bool extendSelection(int aX, int aY);
void endSelection();
void setInvertColors(bool aInvertColors);
void gotoPosition(const BooksPos& aPos);
bool nextPage();