diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-03-10 12:57:32 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-03-11 08:31:44 +0100 |
commit | 5dc78ed4e2891205a7162b696b3439a87253140f (patch) | |
tree | 09778a7d19015f627be5efa813bf4730a82c1ed1 | |
parent | f253884934cbdbc16fd9b783a2b115960d11af10 (diff) |
PdfSelection: add selectAll() function; use in examples
The usual shortcut (control-A) now selects all text on the current page,
it is highlighted, and it can be copied to the clipboard.
Change-Id: I5e6d9cae675862808f8b9027cb47024ca65cf2fd
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r-- | examples/pdf/multipage/resources/edit-select-all.svg | 13 | ||||
-rw-r--r-- | examples/pdf/multipage/viewer.qml | 7 | ||||
-rw-r--r-- | examples/pdf/multipage/viewer.qrc | 1 | ||||
-rw-r--r-- | examples/pdf/pdfviewer/resources/edit-select-all.svg | 13 | ||||
-rw-r--r-- | examples/pdf/pdfviewer/viewer.qml | 7 | ||||
-rw-r--r-- | examples/pdf/pdfviewer/viewer.qrc | 1 | ||||
-rw-r--r-- | src/pdf/api/qpdfdocument.h | 1 | ||||
-rw-r--r-- | src/pdf/api/qpdfdocument_p.h | 1 | ||||
-rw-r--r-- | src/pdf/qpdfdocument.cpp | 43 | ||||
-rw-r--r-- | src/pdf/quick/qml/PdfMultiPageView.qml | 5 | ||||
-rw-r--r-- | src/pdf/quick/qml/PdfPageView.qml | 3 | ||||
-rw-r--r-- | src/pdf/quick/qml/PdfScrollablePageView.qml | 3 | ||||
-rw-r--r-- | src/pdf/quick/qquickpdfselection.cpp | 16 | ||||
-rw-r--r-- | src/pdf/quick/qquickpdfselection_p.h | 1 |
14 files changed, 109 insertions, 6 deletions
diff --git a/examples/pdf/multipage/resources/edit-select-all.svg b/examples/pdf/multipage/resources/edit-select-all.svg new file mode 100644 index 000000000..5f21950a0 --- /dev/null +++ b/examples/pdf/multipage/resources/edit-select-all.svg @@ -0,0 +1,13 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <defs id="defs3051"> + <style type="text/css" id="current-color-scheme"> + .ColorScheme-Text { + color:#232629; + } + </style> + </defs> + <path style="fill:currentColor;fill-opacity:1;stroke:none" + d="M 4 4 L 4 5 L 4 8 L 5 8 L 5 5 L 8 5 L 8 4 L 5 4 L 4 4 z M 16 4 L 16 5 L 19 5 L 19 8 L 20 8 L 20 4 L 16 4 z M 6 6 L 6 11 L 11 11 L 11 6 L 6 6 z M 13 6 L 13 11 L 18 11 L 18 6 L 13 6 z M 7 7 L 10 7 L 10 10 L 7 10 L 7 7 z M 14 7 L 17 7 L 17 10 L 14 10 L 14 7 z M 6 13 L 6 18 L 11 18 L 11 13 L 6 13 z M 13 13 L 13 18 L 18 18 L 18 13 L 13 13 z M 7 14 L 10 14 L 10 17 L 7 17 L 7 14 z M 14 14 L 17 14 L 17 17 L 14 17 L 14 14 z M 4 16 L 4 20 L 5 20 L 8 20 L 8 19 L 5 19 L 5 16 L 4 16 z M 19 16 L 19 19 L 16 19 L 16 20 L 20 20 L 20 19 L 20 16 L 19 16 z " + class="ColorScheme-Text" + /> +</svg> diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index 282636564..02513fa5b 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -161,6 +161,13 @@ ApplicationWindow { } ToolButton { action: Action { + shortcut: StandardKey.SelectAll + icon.source: "resources/edit-select-all.svg" + onTriggered: view.selectAll() + } + } + ToolButton { + action: Action { shortcut: StandardKey.Copy icon.source: "resources/edit-copy.svg" enabled: view.selectedText !== "" diff --git a/examples/pdf/multipage/viewer.qrc b/examples/pdf/multipage/viewer.qrc index 1b6fa52f7..ffca51679 100644 --- a/examples/pdf/multipage/viewer.qrc +++ b/examples/pdf/multipage/viewer.qrc @@ -4,6 +4,7 @@ <file>resources/document-open.svg</file> <file>resources/edit-clear.svg</file> <file>resources/edit-copy.svg</file> + <file>resources/edit-select-all.svg</file> <file>resources/go-down-search.svg</file> <file>resources/go-next-view-page.svg</file> <file>resources/go-previous-view-page.svg</file> diff --git a/examples/pdf/pdfviewer/resources/edit-select-all.svg b/examples/pdf/pdfviewer/resources/edit-select-all.svg new file mode 100644 index 000000000..5f21950a0 --- /dev/null +++ b/examples/pdf/pdfviewer/resources/edit-select-all.svg @@ -0,0 +1,13 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> + <defs id="defs3051"> + <style type="text/css" id="current-color-scheme"> + .ColorScheme-Text { + color:#232629; + } + </style> + </defs> + <path style="fill:currentColor;fill-opacity:1;stroke:none" + d="M 4 4 L 4 5 L 4 8 L 5 8 L 5 5 L 8 5 L 8 4 L 5 4 L 4 4 z M 16 4 L 16 5 L 19 5 L 19 8 L 20 8 L 20 4 L 16 4 z M 6 6 L 6 11 L 11 11 L 11 6 L 6 6 z M 13 6 L 13 11 L 18 11 L 18 6 L 13 6 z M 7 7 L 10 7 L 10 10 L 7 10 L 7 7 z M 14 7 L 17 7 L 17 10 L 14 10 L 14 7 z M 6 13 L 6 18 L 11 18 L 11 13 L 6 13 z M 13 13 L 13 18 L 18 18 L 18 13 L 13 13 z M 7 14 L 10 14 L 10 17 L 7 17 L 7 14 z M 14 14 L 17 14 L 17 17 L 14 17 L 14 14 z M 4 16 L 4 20 L 5 20 L 8 20 L 8 19 L 5 19 L 5 16 L 4 16 z M 19 16 L 19 19 L 16 19 L 16 20 L 20 20 L 20 19 L 20 16 L 19 16 z " + class="ColorScheme-Text" + /> +</svg> diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index 40469afcf..75d2daab0 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -164,6 +164,13 @@ ApplicationWindow { } ToolButton { action: Action { + shortcut: StandardKey.SelectAll + icon.source: "resources/edit-select-all.svg" + onTriggered: view.selectAll() + } + } + ToolButton { + action: Action { shortcut: StandardKey.Copy icon.source: "resources/edit-copy.svg" enabled: view.selectedText !== "" diff --git a/examples/pdf/pdfviewer/viewer.qrc b/examples/pdf/pdfviewer/viewer.qrc index 1b6fa52f7..ffca51679 100644 --- a/examples/pdf/pdfviewer/viewer.qrc +++ b/examples/pdf/pdfviewer/viewer.qrc @@ -4,6 +4,7 @@ <file>resources/document-open.svg</file> <file>resources/edit-clear.svg</file> <file>resources/edit-copy.svg</file> + <file>resources/edit-select-all.svg</file> <file>resources/go-down-search.svg</file> <file>resources/go-next-view-page.svg</file> <file>resources/go-previous-view-page.svg</file> diff --git a/src/pdf/api/qpdfdocument.h b/src/pdf/api/qpdfdocument.h index 40df181f4..027cdeb47 100644 --- a/src/pdf/api/qpdfdocument.h +++ b/src/pdf/api/qpdfdocument.h @@ -113,6 +113,7 @@ public: QImage render(int page, QSize imageSize, QPdfDocumentRenderOptions options = QPdfDocumentRenderOptions()); Q_INVOKABLE QPdfSelection getSelection(int page, QPointF start, QPointF end); + Q_INVOKABLE QPdfSelection getAllText(int page); Q_SIGNALS: void passwordChanged(); diff --git a/src/pdf/api/qpdfdocument_p.h b/src/pdf/api/qpdfdocument_p.h index 15d8b8259..2dcb70407 100644 --- a/src/pdf/api/qpdfdocument_p.h +++ b/src/pdf/api/qpdfdocument_p.h @@ -105,6 +105,7 @@ public: static int fpdf_GetBlock(void* param, unsigned long position, unsigned char* pBuf, unsigned long size); static void fpdf_AddSegment(struct _FX_DOWNLOADHINTS* pThis, size_t offset, size_t size); void updateLastError(); + QString getText(FPDF_TEXTPAGE textPage, int startIndex, int count); }; QT_END_NAMESPACE diff --git a/src/pdf/qpdfdocument.cpp b/src/pdf/qpdfdocument.cpp index 1e8a0f527..d56edf4e9 100644 --- a/src/pdf/qpdfdocument.cpp +++ b/src/pdf/qpdfdocument.cpp @@ -393,6 +393,15 @@ void QPdfDocumentPrivate::fpdf_AddSegment(_FX_DOWNLOADHINTS *pThis, size_t offse Q_UNUSED(size); } +QString QPdfDocumentPrivate::getText(FPDF_TEXTPAGE textPage, int startIndex, int count) +{ + QVector<ushort> buf(count + 1); + // TODO is that enough space in case one unicode character is more than one in utf-16? + int len = FPDFText_GetText(textPage, startIndex, count, buf.data()); + Q_ASSERT(len - 1 <= count); // len is number of characters written, including the terminator + return QString::fromUtf16(buf.constData(), len - 1); +} + /*! \class QPdfDocument \since 5.10 @@ -737,15 +746,10 @@ QPdfSelection QPdfDocument::getSelection(int page, QPointF start, QPointF end) int endIndex = FPDFText_GetCharIndexAtPos(textPage, end.x(), pageHeight - end.y(), CharacterHitTolerance, CharacterHitTolerance); if (startIndex >= 0 && endIndex != startIndex) { - QString text; if (startIndex > endIndex) qSwap(startIndex, endIndex); int count = endIndex - startIndex + 1; - QVector<ushort> buf(count + 1); - // TODO is that enough space in case one unicode character is more than one in utf-16? - int len = FPDFText_GetText(textPage, startIndex, count, buf.data()); - Q_ASSERT(len - 1 <= count); // len is number of characters written, including the terminator - text = QString::fromUtf16(buf.constData(), len - 1); + QString text = d->getText(textPage, startIndex, count); QVector<QPolygonF> bounds; int rectCount = FPDFText_CountRects(textPage, startIndex, endIndex - startIndex); for (int i = 0; i < rectCount; ++i) { @@ -767,6 +771,33 @@ QPdfSelection QPdfDocument::getSelection(int page, QPointF start, QPointF end) return QPdfSelection(); } +QPdfSelection QPdfDocument::getAllText(int page) +{ + const QPdfMutexLocker lock; + FPDF_PAGE pdfPage = FPDF_LoadPage(d->doc, page); + double pageHeight = FPDF_GetPageHeight(pdfPage); + FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage); + int count = FPDFText_CountChars(textPage); + if (count < 1) + return QPdfSelection(); + QString text = d->getText(textPage, 0, count); + QVector<QPolygonF> bounds; + int rectCount = FPDFText_CountRects(textPage, 0, count); + for (int i = 0; i < rectCount; ++i) { + double l, r, b, t; + FPDFText_GetRect(textPage, i, &l, &t, &r, &b); + QPolygonF poly; + poly << QPointF(l, pageHeight - t); + poly << QPointF(r, pageHeight - t); + poly << QPointF(r, pageHeight - b); + poly << QPointF(l, pageHeight - b); + poly << QPointF(l, pageHeight - t); + bounds << poly; + } + qCDebug(qLcDoc) << "on page" << page << "got" << count << "chars" << rectCount << "rects"; + return QPdfSelection(text, bounds); +} + QT_END_NAMESPACE #include "moc_qpdfdocument.cpp" diff --git a/src/pdf/quick/qml/PdfMultiPageView.qml b/src/pdf/quick/qml/PdfMultiPageView.qml index 579c9a1ce..70bb5454f 100644 --- a/src/pdf/quick/qml/PdfMultiPageView.qml +++ b/src/pdf/quick/qml/PdfMultiPageView.qml @@ -47,6 +47,11 @@ Item { property bool debug: false property string selectedText + function selectAll() { + var currentItem = tableView.itemAtPos(0, tableView.contentY + root.height / 2) + if (currentItem !== null) + currentItem.selection.selectAll() + } function copySelectionToClipboard() { var currentItem = tableView.itemAtPos(0, tableView.contentY + root.height / 2) if (debug) diff --git a/src/pdf/quick/qml/PdfPageView.qml b/src/pdf/quick/qml/PdfPageView.qml index dfd00a1a8..b90ad2d7f 100644 --- a/src/pdf/quick/qml/PdfPageView.qml +++ b/src/pdf/quick/qml/PdfPageView.qml @@ -46,6 +46,9 @@ Rectangle { property alias status: image.status property alias selectedText: selection.text + function selectAll() { + selection.selectAll() + } function copySelectionToClipboard() { selection.copyToClipboard() } diff --git a/src/pdf/quick/qml/PdfScrollablePageView.qml b/src/pdf/quick/qml/PdfScrollablePageView.qml index 4c43972c9..6076e57df 100644 --- a/src/pdf/quick/qml/PdfScrollablePageView.qml +++ b/src/pdf/quick/qml/PdfScrollablePageView.qml @@ -47,6 +47,9 @@ Flickable { property alias status: image.status property alias selectedText: selection.text + function selectAll() { + selection.selectAll() + } function copySelectionToClipboard() { selection.copyToClipboard() } diff --git a/src/pdf/quick/qquickpdfselection.cpp b/src/pdf/quick/qquickpdfselection.cpp index d313820ba..5371e85e5 100644 --- a/src/pdf/quick/qquickpdfselection.cpp +++ b/src/pdf/quick/qquickpdfselection.cpp @@ -124,6 +124,22 @@ QVector<QPolygonF> QQuickPdfSelection::geometry() const return m_geometry; } +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 geometryChanged(); + } +} + void QQuickPdfSelection::resetPoints() { bool wasHolding = m_hold; diff --git a/src/pdf/quick/qquickpdfselection_p.h b/src/pdf/quick/qquickpdfselection_p.h index a0e6d1a8d..bb4a50fed 100644 --- a/src/pdf/quick/qquickpdfselection_p.h +++ b/src/pdf/quick/qquickpdfselection_p.h @@ -86,6 +86,7 @@ public: QString text() const; QVector<QPolygonF> geometry() const; + Q_INVOKABLE void selectAll(); #if QT_CONFIG(clipboard) Q_INVOKABLE void copyToClipboard() const; #endif |