[app] Implemented text selection (whole words)
The selected text is getting copied to clipboard.
This commit is contained in:
parent
a48fe1d0e4
commit
89775f269e
6 changed files with 432 additions and 54 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(); }
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
/*
|
||||
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
|
||||
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue