summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2022-06-03 07:56:23 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2022-06-04 20:55:31 +0200
commitfd39e1eeedd71f8511373d399507a0ddeedf592c (patch)
tree8df349d903f4a35ee71b7e9569e9f7c41c7f28da
parent0de16e9a20366b02b544e2279461612c69cdf11b (diff)
downloadqtwebengine-fd39e1eeedd71f8511373d399507a0ddeedf592c.tar.gz
Add link role to QPdfLinkModel, providing a QPdfLink instance
We want to call PdfPageNavigator.jump(link) when a link is clicked; therefore PdfLinkModel needs to provide this object; therefore it makes sense to store the links as QPdfLink instances, and get rid of the redundant internal Link object type. But QPdfLink did not have storage for a QUrl until now. The textStart and textCharCount fields sounded useful, but in practice were set and not used. QPdfLink gains toString() and copyToClipboard() methods. Also removed some unused cruft in qquickpdflinkmodel. [ChangeLog][QtPDF] PdfLinkModel now provides a QPdfLink object for each link. QPdfLink now contains everything necessary to render delegates for links and search results, and handle clicking links; and there is a copyToClipboard() method for use in context menus, which will copy the text returned trom toString(), which is also invokable. Change-Id: Ifa5abe6df8f8d6f9ef98971044c26691ec4b9a36 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
-rw-r--r--src/pdf/qpdflink.cpp37
-rw-r--r--src/pdf/qpdflink.h6
-rw-r--r--src/pdf/qpdflink_p.h2
-rw-r--r--src/pdf/qpdflinkmodel.cpp59
-rw-r--r--src/pdf/qpdflinkmodel_p.h3
-rw-r--r--src/pdf/qpdflinkmodel_p_p.h18
-rw-r--r--src/pdfquick/qquickpdflinkmodel_p.h8
7 files changed, 74 insertions, 59 deletions
diff --git a/src/pdf/qpdflink.cpp b/src/pdf/qpdflink.cpp
index 091a29729..94d4e741d 100644
--- a/src/pdf/qpdflink.cpp
+++ b/src/pdf/qpdflink.cpp
@@ -39,6 +39,8 @@
#include "qpdflink.h"
#include "qpdflink_p.h"
+#include "qpdflinkmodel_p.h"
+#include <QGuiApplication>
QT_BEGIN_NAMESPACE
@@ -126,6 +128,17 @@ qreal QPdfLink::zoom() const
}
/*!
+ \property QPdfLink::url
+
+ This property holds the destination URL if the link is an external hyperlink;
+ otherwise, it's empty.
+*/
+QUrl QPdfLink::url() const
+{
+ return d->url;
+}
+
+/*!
\property QPdfLink::contextBefore
This property holds adjacent text found on the page before the search string.
@@ -167,6 +180,30 @@ QList<QRectF> QPdfLink::rectangles() const
return d->rects;
}
+/*!
+ Returns a translated representation for display.
+
+ \sa copyToClipboard()
+*/
+QString QPdfLink::toString() const
+{
+ static const QString format = QPdfLinkModel::tr("page %1 location %2,%3 zoom %4");
+ return d->page > 0 ? format.arg(QString::number(d->page),
+ QString::number(d->location.x()),
+ QString::number(d->location.y()),
+ QString::number(d->zoom))
+ : d->url.toString();
+}
+
+/*!
+ Copies the toString() representation of the link to the
+ \l {QGuiApplication::clipboard()}{system clipboard} depending on the \a mode given.
+*/
+void QPdfLink::copyToClipboard(QClipboard::Mode mode) const
+{
+ QGuiApplication::clipboard()->setText(toString(), mode);
+}
+
QDebug operator<<(QDebug dbg, const QPdfLink &link)
{
QDebugStateSaver saver(dbg);
diff --git a/src/pdf/qpdflink.h b/src/pdf/qpdflink.h
index 22de24063..64185554b 100644
--- a/src/pdf/qpdflink.h
+++ b/src/pdf/qpdflink.h
@@ -47,6 +47,7 @@
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
#include <QtCore/qshareddata.h>
+#include <QtGui/qclipboard.h>
QT_BEGIN_NAMESPACE
@@ -59,6 +60,7 @@ class QPdfLink
Q_PROPERTY(int page READ page)
Q_PROPERTY(QPointF location READ location)
Q_PROPERTY(qreal zoom READ zoom)
+ Q_PROPERTY(QUrl url READ url)
Q_PROPERTY(QString contextBefore READ contextBefore)
Q_PROPERTY(QString contextAfter READ contextAfter)
Q_PROPERTY(QList<QRectF> rectangles READ rectangles)
@@ -78,15 +80,19 @@ public:
Q_PDF_EXPORT int page() const;
Q_PDF_EXPORT QPointF location() const;
Q_PDF_EXPORT qreal zoom() const;
+ Q_PDF_EXPORT QUrl url() const;
Q_PDF_EXPORT QString contextBefore() const;
Q_PDF_EXPORT QString contextAfter() const;
Q_PDF_EXPORT QList<QRectF> rectangles() const;
+ Q_PDF_EXPORT Q_INVOKABLE QString toString() const;
+ Q_PDF_EXPORT Q_INVOKABLE void copyToClipboard(QClipboard::Mode mode = QClipboard::Clipboard) const;
private: // methods
QPdfLink(int page, QPointF location, qreal zoom);
QPdfLink(int page, QList<QRectF> rects, QString contextBefore, QString contextAfter);
QPdfLink(QPdfLinkPrivate *d);
friend class QPdfDocument;
+ friend class QPdfLinkModelPrivate;
friend class QPdfSearchModelPrivate;
friend class QPdfPageNavigator;
friend class QQuickPdfPageNavigator;
diff --git a/src/pdf/qpdflink_p.h b/src/pdf/qpdflink_p.h
index 7cda6edfc..4acfc4182 100644
--- a/src/pdf/qpdflink_p.h
+++ b/src/pdf/qpdflink_p.h
@@ -55,6 +55,7 @@
#include <QPointF>
#include <QRectF>
+#include <QUrl>
QT_BEGIN_NAMESPACE
@@ -79,6 +80,7 @@ public:
qreal zoom = 1;
QString contextBefore;
QString contextAfter;
+ QUrl url;
QList<QRectF> rects;
};
diff --git a/src/pdf/qpdflinkmodel.cpp b/src/pdf/qpdflinkmodel.cpp
index fba9c23c4..4997cd314 100644
--- a/src/pdf/qpdflinkmodel.cpp
+++ b/src/pdf/qpdflinkmodel.cpp
@@ -37,6 +37,7 @@
**
****************************************************************************/
+#include "qpdflink_p.h"
#include "qpdflinkmodel_p.h"
#include "qpdflinkmodel_p_p.h"
#include "qpdfdocument_p.h"
@@ -76,18 +77,20 @@ int QPdfLinkModel::rowCount(const QModelIndex &parent) const
QVariant QPdfLinkModel::data(const QModelIndex &index, int role) const
{
Q_D(const QPdfLinkModel);
- const QPdfLinkModelPrivate::Link &link = d->links.at(index.row());
+ const auto &link = d->links.at(index.row());
switch (Role(role)) {
+ case Role::Link:
+ return QVariant::fromValue(link);
case Role::Rect:
- return link.rect;
+ return link.rectangles().empty() ? QVariant() : link.rectangles().constFirst();
case Role::Url:
- return link.url;
+ return link.url();
case Role::Page:
- return link.page;
+ return link.page();
case Role::Location:
- return link.location;
+ return link.location();
case Role::Zoom:
- return link.zoom;
+ return link.zoom();
case Role::_Count:
break;
}
@@ -169,16 +172,16 @@ void QPdfLinkModelPrivate::update()
qCWarning(qLcLink) << "skipping link with invalid bounding box";
continue; // while enumerating links
}
- Link linkData;
- linkData.rect = QRectF(rect.left, pageHeight - rect.top,
+ QPdfLink linkData;
+ linkData.d->rects << QRectF(rect.left, pageHeight - rect.top,
rect.right - rect.left, rect.top - rect.bottom);
FPDF_DEST dest = FPDFLink_GetDest(doc, linkAnnot);
FPDF_ACTION action = FPDFLink_GetAction(linkAnnot);
switch (FPDFAction_GetType(action)) {
case PDFACTION_UNSUPPORTED: // this happens with valid links in some PDFs
case PDFACTION_GOTO: {
- linkData.page = FPDFDest_GetDestPageIndex(doc, dest);
- if (linkData.page < 0) {
+ linkData.d->page = FPDFDest_GetDestPageIndex(doc, dest);
+ if (linkData.d->page < 0) {
qCWarning(qLcLink) << "skipping link with invalid page number";
continue; // while enumerating links
}
@@ -186,25 +189,25 @@ void QPdfLinkModelPrivate::update()
FS_FLOAT x, y, zoom;
ok = FPDFDest_GetLocationInPage(dest, &hasX, &hasY, &hasZoom, &x, &y, &zoom);
if (!ok) {
- qCWarning(qLcLink) << "link with invalid location and/or zoom @" << linkData.rect;
+ qCWarning(qLcLink) << "link with invalid location and/or zoom @" << linkData.d->rects;
break; // at least we got a page number, so the link will jump there
}
if (hasX && hasY)
- linkData.location = QPointF(x, pageHeight - y);
+ linkData.d->location = QPointF(x, pageHeight - y);
if (hasZoom)
- linkData.zoom = zoom;
+ linkData.d->zoom = zoom;
break;
}
case PDFACTION_URI: {
unsigned long len = FPDFAction_GetURIPath(doc, action, nullptr, 0);
if (len < 1) {
- qCWarning(qLcLink) << "skipping link with empty URI @" << linkData.rect;
+ qCWarning(qLcLink) << "skipping link with empty URI @" << linkData.d->rects;
continue; // while enumerating links
} else {
QByteArray buf(len, 0);
unsigned long got = FPDFAction_GetURIPath(doc, action, buf.data(), len);
Q_ASSERT(got == len);
- linkData.url = QString::fromLatin1(buf.data(), got - 1);
+ linkData.d->url = QString::fromLatin1(buf.data(), got - 1);
}
break;
}
@@ -212,13 +215,13 @@ void QPdfLinkModelPrivate::update()
case PDFACTION_REMOTEGOTO: {
unsigned long len = FPDFAction_GetFilePath(action, nullptr, 0);
if (len < 1) {
- qCWarning(qLcLink) << "skipping link with empty file path @" << linkData.rect;
+ qCWarning(qLcLink) << "skipping link with empty file path @" << linkData.d->rects;
continue; // while enumerating links
} else {
QByteArray buf(len, 0);
unsigned long got = FPDFAction_GetFilePath(action, buf.data(), len);
Q_ASSERT(got == len);
- linkData.url = QUrl::fromLocalFile(QString::fromLatin1(buf.data(), got - 1)).toString();
+ linkData.d->url = QUrl::fromLocalFile(QString::fromLatin1(buf.data(), got - 1)).toString();
// Unfortunately, according to comments in fpdf_doc.h, if it's PDFACTION_REMOTEGOTO,
// we can't get the page and location without first opening the linked document
@@ -237,7 +240,7 @@ void QPdfLinkModelPrivate::update()
if (webLinks) {
int count = FPDFLink_CountWebLinks(webLinks);
for (int i = 0; i < count; ++i) {
- Link linkData;
+ QPdfLink linkData;
int len = FPDFLink_GetURL(webLinks, i, nullptr, 0);
if (len < 1) {
qCWarning(qLcLink) << "skipping link" << i << "with empty URL";
@@ -245,16 +248,15 @@ void QPdfLinkModelPrivate::update()
QList<unsigned short> buf(len);
int got = FPDFLink_GetURL(webLinks, i, buf.data(), len);
Q_ASSERT(got == len);
- linkData.url = QString::fromUtf16(
+ linkData.d->url = QString::fromUtf16(
reinterpret_cast<const char16_t *>(buf.data()), got - 1);
}
- FPDFLink_GetTextRange(webLinks, i, &linkData.textStart, &linkData.textCharCount);
len = FPDFLink_CountRects(webLinks, i);
for (int r = 0; r < len; ++r) {
double left, top, right, bottom;
bool success = FPDFLink_GetRect(webLinks, i, r, &left, &top, &right, &bottom);
if (success) {
- linkData.rect = QRectF(left, pageHeight - top, right - left, top - bottom);
+ linkData.d->rects << QRectF(left, pageHeight - top, right - left, top - bottom);
links << linkData;
}
}
@@ -267,8 +269,8 @@ void QPdfLinkModelPrivate::update()
// All done
FPDF_ClosePage(pdfPage);
if (Q_UNLIKELY(qLcLink().isDebugEnabled())) {
- for (const Link &l : links)
- qCDebug(qLcLink) << l.rect << l.toString();
+ for (const auto &l : links)
+ qCDebug(qLcLink) << l;
}
q->endResetModel();
}
@@ -281,17 +283,6 @@ void QPdfLinkModel::onStatusChanged(QPdfDocument::Status status)
d->update();
}
-QString QPdfLinkModelPrivate::Link::toString() const
-{
- QString ret;
- if (page >= 0)
- return QLatin1String("page ") + QString::number(page) +
- QLatin1String(" location ") + QString::number(location.x()) + QLatin1Char(',') + QString::number(location.y()) +
- QLatin1String(" zoom ") + QString::number(zoom);
- else
- return url.toString();
-}
-
QT_END_NAMESPACE
#include "moc_qpdflinkmodel_p.cpp"
diff --git a/src/pdf/qpdflinkmodel_p.h b/src/pdf/qpdflinkmodel_p.h
index 495370fe1..35fa28dcd 100644
--- a/src/pdf/qpdflinkmodel_p.h
+++ b/src/pdf/qpdflinkmodel_p.h
@@ -69,7 +69,8 @@ class Q_PDF_EXPORT QPdfLinkModel : public QAbstractListModel
public:
enum class Role : int {
- Rect = Qt::UserRole,
+ Link = Qt::UserRole,
+ Rect,
Url,
Page,
Location,
diff --git a/src/pdf/qpdflinkmodel_p_p.h b/src/pdf/qpdflinkmodel_p_p.h
index 14c8bc734..276a49fe9 100644
--- a/src/pdf/qpdflinkmodel_p_p.h
+++ b/src/pdf/qpdflinkmodel_p_p.h
@@ -52,6 +52,7 @@
//
#include "qpdflinkmodel_p.h"
+#include "qpdflink.h"
#include <private/qabstractitemmodel_p.h>
#include "third_party/pdfium/public/fpdfview.h"
@@ -69,23 +70,8 @@ public:
void update();
- struct Link {
- // where it is on the current page
- QRectF rect;
- int textStart = -1;
- int textCharCount = 0;
- // destination inside PDF
- int page = -1; // -1 means look at the url instead
- QPointF location;
- qreal zoom = 0; // 0 means no specified zoom: don't change when clicking
- // web destination
- QUrl url;
-
- QString toString() const;
- };
-
QPdfDocument *document = nullptr;
- QList<Link> links;
+ QList<QPdfLink> links;
int page = 0;
};
diff --git a/src/pdfquick/qquickpdflinkmodel_p.h b/src/pdfquick/qquickpdflinkmodel_p.h
index 156444828..153639e43 100644
--- a/src/pdfquick/qquickpdflinkmodel_p.h
+++ b/src/pdfquick/qquickpdflinkmodel_p.h
@@ -73,16 +73,8 @@ public:
QQuickPdfDocument *document() const;
void setDocument(QQuickPdfDocument *document);
-signals:
- void documentChanged();
-
-private:
- void updateResults();
-
private:
QQuickPdfDocument *m_quickDocument;
- QList<QPolygonF> m_linksGeometry;
-
Q_DISABLE_COPY(QQuickPdfLinkModel)
};