diff options
-rw-r--r-- | src/pdf/qpdflink.cpp | 37 | ||||
-rw-r--r-- | src/pdf/qpdflink.h | 6 | ||||
-rw-r--r-- | src/pdf/qpdflink_p.h | 2 | ||||
-rw-r--r-- | src/pdf/qpdflinkmodel.cpp | 59 | ||||
-rw-r--r-- | src/pdf/qpdflinkmodel_p.h | 3 | ||||
-rw-r--r-- | src/pdf/qpdflinkmodel_p_p.h | 18 | ||||
-rw-r--r-- | src/pdfquick/qquickpdflinkmodel_p.h | 8 |
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) }; |