summaryrefslogtreecommitdiffstats
path: root/src/pdf/quick/qquickpdfselection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdf/quick/qquickpdfselection.cpp')
-rw-r--r--src/pdf/quick/qquickpdfselection.cpp541
1 files changed, 0 insertions, 541 deletions
diff --git a/src/pdf/quick/qquickpdfselection.cpp b/src/pdf/quick/qquickpdfselection.cpp
deleted file mode 100644
index bdedb4dfb..000000000
--- a/src/pdf/quick/qquickpdfselection.cpp
+++ /dev/null
@@ -1,541 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtPDF module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickpdfselection_p.h"
-#include "qquickpdfdocument_p.h"
-#include <QClipboard>
-#include <QGuiApplication>
-#include <QLoggingCategory>
-#include <QQuickItem>
-#include <QQmlEngine>
-#include <QRegularExpression>
-#include <QStandardPaths>
-#include <QtPdf/private/qpdfdocument_p.h>
-
-Q_LOGGING_CATEGORY(qLcIm, "qt.pdf.im")
-
-QT_BEGIN_NAMESPACE
-
-static const QRegularExpression WordDelimiter("\\s");
-
-/*!
- \qmltype PdfSelection
- \instantiates QQuickPdfSelection
- \inqmlmodule QtQuick.Pdf
- \ingroup pdf
- \brief A representation of a text selection within a PDF Document.
- \since 5.15
-
- PdfSelection provides the text string and its geometry within a bounding box
- from one point to another.
-
- To modify the selection using the mouse, bind \l fromPoint and \l toPoint
- to the suitable properties of an input handler so that they will be set to
- the positions where the drag gesture begins and ends, respectively; and
- bind the \l hold property so that it will be set to \c true during the drag
- gesture and \c false when the gesture ends.
-
- PdfSelection also directly handles Input Method queries so that text
- selection handles can be used on platforms such as iOS. For this purpose,
- it must have keyboard focus.
-*/
-
-/*!
- Constructs a SearchModel.
-*/
-QQuickPdfSelection::QQuickPdfSelection(QQuickItem *parent)
- : QQuickItem(parent)
-{
-#if QT_CONFIG(im)
- setFlags(ItemIsFocusScope | ItemAcceptsInputMethod);
- // workaround to get Copy instead of Paste on the popover menu (QTBUG-83811)
- setProperty("qt_im_readonly", QVariant(true));
-#endif
-}
-
-QQuickPdfDocument *QQuickPdfSelection::document() const
-{
- return m_document;
-}
-
-void QQuickPdfSelection::setDocument(QQuickPdfDocument *document)
-{
- if (m_document == document)
- return;
-
- if (m_document) {
- disconnect(m_document, &QQuickPdfDocument::sourceChanged,
- this, &QQuickPdfSelection::resetPoints);
- }
- m_document = document;
- emit documentChanged();
- resetPoints();
- connect(m_document, &QQuickPdfDocument::sourceChanged,
- this, &QQuickPdfSelection::resetPoints);
-}
-
-/*!
- \qmlproperty list<list<point>> PdfSelection::geometry
-
- A set of paths in a form that can be bound to the \c paths property of a
- \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of
- rectangles around the text regions that are included in the selection:
-
- \qml
- PdfDocument {
- id: doc
- }
- PdfSelection {
- id: selection
- document: doc
- fromPoint: textSelectionDrag.centroid.pressPosition
- toPoint: textSelectionDrag.centroid.position
- hold: !textSelectionDrag.active
- }
- Shape {
- ShapePath {
- PathMultiline {
- paths: selection.geometry
- }
- }
- }
- DragHandler {
- id: textSelectionDrag
- acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus
- target: null
- }
- \endqml
-
- \sa PathMultiline
-*/
-QList<QPolygonF> QQuickPdfSelection::geometry() const
-{
- return m_geometry;
-}
-
-void QQuickPdfSelection::clear()
-{
- m_hitPoint = QPointF();
- m_fromPoint = QPointF();
- m_toPoint = QPointF();
- m_heightAtAnchor = 0;
- m_heightAtCursor = 0;
- m_fromCharIndex = -1;
- m_toCharIndex = -1;
- m_text.clear();
- m_geometry.clear();
- emit fromPointChanged();
- emit toPointChanged();
- emit textChanged();
- emit selectedAreaChanged();
- QGuiApplication::inputMethod()->update(Qt::ImQueryInput);
-}
-
-void QQuickPdfSelection::selectAll()
-{
- QPdfSelection sel = m_document->m_doc.getAllText(m_page);
- if (sel.text() != m_text) {
- m_text = sel.text();
- if (QGuiApplication::clipboard()->supportsSelection())
- sel.copyToClipboard(QClipboard::Selection);
- emit textChanged();
- }
-
- if (sel.bounds() != m_geometry) {
- m_geometry = sel.bounds();
- emit selectedAreaChanged();
- }
-#if QT_CONFIG(im)
- m_fromCharIndex = sel.startIndex();
- m_toCharIndex = sel.endIndex();
- if (sel.bounds().isEmpty()) {
- m_fromPoint = QPointF();
- m_toPoint = QPointF();
- } else {
- m_fromPoint = sel.bounds().first().boundingRect().topLeft() * m_renderScale;
- m_toPoint = sel.bounds().last().boundingRect().bottomRight() * m_renderScale - QPointF(0, m_heightAtCursor);
- }
-
- QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle | Qt::ImAnchorRectangle);
-#endif
-}
-
-#if QT_CONFIG(im)
-void QQuickPdfSelection::keyReleaseEvent(QKeyEvent *ev)
-{
- qCDebug(qLcIm) << "release" << ev;
- const auto &allText = pageText();
- if (ev == QKeySequence::MoveToPreviousWord) {
- // iOS sends MoveToPreviousWord first to get to the beginning of the word,
- // and then SelectNextWord to select the whole word.
- int i = allText.lastIndexOf(WordDelimiter, m_fromCharIndex - allText.length());
- if (i < 0)
- i = 0;
- else
- i += 1; // don't select the space before the word
- auto sel = m_document->m_doc.getSelectionAtIndex(m_page, i, m_text.length() + m_fromCharIndex - i);
- update(sel);
- QGuiApplication::inputMethod()->update(Qt::ImAnchorRectangle);
- } else if (ev == QKeySequence::SelectNextWord) {
- int i = allText.indexOf(WordDelimiter, m_toCharIndex);
- if (i < 0)
- i = allText.length(); // go to the end of m_textAfter
- auto sel = m_document->m_doc.getSelectionAtIndex(m_page, m_fromCharIndex, m_text.length() + i - m_toCharIndex);
- update(sel);
- QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle);
- } else if (ev == QKeySequence::Copy) {
- copyToClipboard();
- }
-}
-
-void QQuickPdfSelection::inputMethodEvent(QInputMethodEvent *event)
-{
- for (auto attr : event->attributes()) {
- switch (attr.type) {
- case QInputMethodEvent::Cursor:
- qCDebug(qLcIm) << "QInputMethodEvent::Cursor: moved to" << attr.start << "len" << attr.length;
- break;
- case QInputMethodEvent::Selection: {
- auto sel = m_document->m_doc.getSelectionAtIndex(m_page, attr.start, attr.length);
- update(sel);
- qCDebug(qLcIm) << "QInputMethodEvent::Selection: from" << attr.start << "len" << attr.length
- << "result:" << m_fromCharIndex << "->" << m_toCharIndex << sel.boundingRectangle();
- // the iOS plugin decided that it wanted to change the selection, but still has to be told to move the handles (!?)
- QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle | Qt::ImAnchorRectangle);
- break;
- }
- case QInputMethodEvent::Language:
- case QInputMethodEvent::Ruby:
- case QInputMethodEvent::TextFormat:
- break;
- }
- }
-}
-
-QVariant QQuickPdfSelection::inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const
-{
- if (!argument.isNull()) {
- qCDebug(qLcIm) << "IM query" << query << "with arg" << argument;
- if (query == Qt::ImCursorPosition) {
- // If it didn't move since last time, return the same result.
- if (m_hitPoint == argument.toPointF())
- return inputMethodQuery(query);
- m_hitPoint = argument.toPointF();
- auto tp = m_document->m_doc.d->hitTest(m_page, m_hitPoint / m_renderScale);
- qCDebug(qLcIm) << "ImCursorPosition hit testing in px" << m_hitPoint << "pt" << (m_hitPoint / m_renderScale)
- << "got char index" << tp.charIndex << "@" << tp.position << "pt," << tp.position * m_renderScale << "px";
- if (tp.charIndex >= 0) {
- m_toCharIndex = tp.charIndex;
- m_toPoint = tp.position * m_renderScale - QPointF(0, m_heightAtCursor);
- m_heightAtCursor = tp.height * m_renderScale;
- if (qFuzzyIsNull(m_heightAtAnchor))
- m_heightAtAnchor = m_heightAtCursor;
- }
- }
- }
- return inputMethodQuery(query);
-}
-
-QVariant QQuickPdfSelection::inputMethodQuery(Qt::InputMethodQuery query) const
-{
- QVariant ret;
- switch (query) {
- case Qt::ImEnabled:
- ret = true;
- break;
- case Qt::ImHints:
- ret = QVariant(Qt::ImhMultiLine | Qt::ImhNoPredictiveText);
- break;
- case Qt::ImInputItemClipRectangle:
- ret = boundingRect();
- break;
- case Qt::ImAnchorPosition:
- ret = m_fromCharIndex;
- break;
- case Qt::ImAbsolutePosition:
- ret = m_toCharIndex;
- break;
- case Qt::ImCursorPosition:
- ret = m_toCharIndex;
- break;
- case Qt::ImAnchorRectangle:
- ret = QRectF(m_fromPoint, QSizeF(1, m_heightAtAnchor));
- break;
- case Qt::ImCursorRectangle:
- ret = QRectF(m_toPoint, QSizeF(1, m_heightAtCursor));
- break;
- case Qt::ImSurroundingText:
- ret = QVariant(pageText());
- break;
- case Qt::ImTextBeforeCursor:
- ret = QVariant(pageText().mid(0, m_toCharIndex));
- break;
- case Qt::ImTextAfterCursor:
- ret = QVariant(pageText().mid(m_toCharIndex));
- break;
- case Qt::ImCurrentSelection:
- ret = QVariant(m_text);
- break;
- case Qt::ImEnterKeyType:
- break;
- case Qt::ImFont: {
- QFont font = QGuiApplication::font();
- font.setPointSizeF(m_heightAtCursor);
- ret = font;
- break;
- }
- case Qt::ImMaximumTextLength:
- break;
- case Qt::ImPreferredLanguage:
- break;
- case Qt::ImPlatformData:
- break;
- case Qt::ImQueryInput:
- case Qt::ImQueryAll:
- qWarning() << "unexpected composite query";
- break;
- }
- qCDebug(qLcIm) << "IM query" << query << "returns" << ret;
- return ret;
-}
-#endif // QT_CONFIG(im)
-
-const QString &QQuickPdfSelection::pageText() const
-{
- if (m_pageTextDirty) {
- m_pageText = m_document->m_doc.getAllText(m_page).text();
- m_pageTextDirty = false;
- }
- return m_pageText;
-}
-
-void QQuickPdfSelection::resetPoints()
-{
- bool wasHolding = m_hold;
- m_hold = false;
- setFromPoint(QPointF());
- setToPoint(QPointF());
- m_hold = wasHolding;
-}
-
-/*!
- \qmlproperty int PdfSelection::page
-
- The page number on which to search.
-
- \sa QtQuick::Image::currentFrame
-*/
-int QQuickPdfSelection::page() const
-{
- return m_page;
-}
-
-void QQuickPdfSelection::setPage(int page)
-{
- if (m_page == page)
- return;
-
- m_page = page;
- m_pageTextDirty = true;
- emit pageChanged();
- resetPoints();
-}
-
-/*!
- \qmlproperty real PdfSelection::renderScale
- \brief The ratio from points to pixels at which the page is rendered.
-
- This is used to scale \l fromPoint and \l toPoint to find ranges of
- selected characters in the document, because positions within the document
- are always given in points.
-*/
-qreal QQuickPdfSelection::renderScale() const
-{
- return m_renderScale;
-}
-
-void QQuickPdfSelection::setRenderScale(qreal scale)
-{
- if (qFuzzyCompare(scale, m_renderScale))
- return;
-
- m_renderScale = scale;
- emit renderScaleChanged();
- updateResults();
-}
-
-/*!
- \qmlproperty point PdfSelection::fromPoint
-
- The beginning location, in pixels from the upper-left corner of the page,
- from which to find selected text. This can be bound to the
- \c centroid.pressPosition of a \l DragHandler to begin selecting text from
- the position where the user presses the mouse button and begins dragging,
- for example.
-*/
-QPointF QQuickPdfSelection::fromPoint() const
-{
- return m_fromPoint;
-}
-
-void QQuickPdfSelection::setFromPoint(QPointF fromPoint)
-{
- if (m_hold || m_fromPoint == fromPoint)
- return;
-
- m_fromPoint = fromPoint;
- emit fromPointChanged();
- updateResults();
-}
-
-/*!
- \qmlproperty point PdfSelection::toPoint
-
- The ending location, in pixels from the upper-left corner of the page,
- from which to find selected text. This can be bound to the
- \c centroid.position of a \l DragHandler to end selection of text at the
- position where the user is currently dragging the mouse, for example.
-*/
-QPointF QQuickPdfSelection::toPoint() const
-{
- return m_toPoint;
-}
-
-void QQuickPdfSelection::setToPoint(QPointF toPoint)
-{
- if (m_hold || m_toPoint == toPoint)
- return;
-
- m_toPoint = toPoint;
- emit toPointChanged();
- updateResults();
-}
-
-/*!
- \qmlproperty bool PdfSelection::hold
-
- Controls whether to hold the existing selection regardless of changes to
- \l fromPoint and \l toPoint. This property can be set to \c true when the mouse
- or touchpoint is released, so that the selection is not lost due to the
- point bindings changing.
-*/
-bool QQuickPdfSelection::hold() const
-{
- return m_hold;
-}
-
-void QQuickPdfSelection::setHold(bool hold)
-{
- if (m_hold == hold)
- return;
-
- m_hold = hold;
- emit holdChanged();
-}
-
-/*!
- \qmlproperty string PdfSelection::string
-
- The string found.
-*/
-QString QQuickPdfSelection::text() const
-{
- return m_text;
-}
-
-#if QT_CONFIG(clipboard)
-/*!
- \qmlmethod void PdfSelection::copyToClipboard()
-
- Copies plain text from the \l string property to the system clipboard.
-*/
-void QQuickPdfSelection::copyToClipboard() const
-{
- QGuiApplication::clipboard()->setText(m_text);
-}
-#endif
-
-void QQuickPdfSelection::updateResults()
-{
- if (!m_document)
- return;
- QPdfSelection sel = m_document->document().getSelection(m_page,
- m_fromPoint / m_renderScale, m_toPoint / m_renderScale);
- update(sel, true);
-}
-
-void QQuickPdfSelection::update(const QPdfSelection &sel, bool textAndGeometryOnly)
-{
- if (sel.text() != m_text) {
- m_text = sel.text();
- if (QGuiApplication::clipboard()->supportsSelection())
- sel.copyToClipboard(QClipboard::Selection);
- emit textChanged();
- }
-
- if (sel.bounds() != m_geometry) {
- m_geometry = sel.bounds();
- emit selectedAreaChanged();
- }
-
- if (textAndGeometryOnly)
- return;
-
- m_fromCharIndex = sel.startIndex();
- m_toCharIndex = sel.endIndex();
- if (sel.bounds().isEmpty()) {
- m_fromPoint = sel.boundingRectangle().topLeft() * m_renderScale;
- m_toPoint = m_fromPoint;
- } else {
- Qt::InputMethodQueries toUpdate = {};
- QRectF firstLineBounds = sel.bounds().first().boundingRect();
- m_fromPoint = firstLineBounds.topLeft() * m_renderScale;
- if (!qFuzzyCompare(m_heightAtAnchor, firstLineBounds.height())) {
- m_heightAtAnchor = firstLineBounds.height() * m_renderScale;
- toUpdate.setFlag(Qt::ImAnchorRectangle);
- }
- QRectF lastLineBounds = sel.bounds().last().boundingRect();
- if (!qFuzzyCompare(m_heightAtCursor, lastLineBounds.height())) {
- m_heightAtCursor = lastLineBounds.height() * m_renderScale;
- toUpdate.setFlag(Qt::ImCursorRectangle);
- }
- m_toPoint = lastLineBounds.topRight() * m_renderScale;
- if (toUpdate)
- QGuiApplication::inputMethod()->update(toUpdate);
- }
-}
-
-QT_END_NAMESPACE