9#include "third_party/pdfium/public/fpdf_doc.h"
10#include "third_party/pdfium/public/fpdf_text.h"
12#include <QLoggingCategory>
48 d_ptr{std::make_unique<QPdfLinkModelPrivate>(
this)}
74 return d->links.size();
83 const auto &link =
d->links.at(
index.row());
88 return link.rectangles().empty() ?
QVariant() : link.rectangles().constFirst();
94 return link.location();
101 return link.toString();
161 for (
const auto &link : std::as_const(
d->links)) {
162 for (
const auto &
rect : link.rectangles()) {
163 if (
rect.contains(point))
177 FPDF_PAGE pdfPage = FPDF_LoadPage(doc,
page);
182 q->beginResetModel();
190 hasNext = FPDFLink_Enumerate(pdfPage, &linkStart, &linkAnnot);
194 bool ok = FPDFLink_GetAnnotRect(linkAnnot, &
rect);
196 qCWarning(qLcLink) <<
"skipping link with invalid bounding box";
207 if (
int quadPointsCount = FPDFLink_CountQuadPoints(linkAnnot) > 0) {
208 for (
int i = 0;
i < quadPointsCount; ++
i) {
209 FS_QUADPOINTSF point;
210 if (FPDFLink_GetQuadPoints(linkAnnot,
i, &point)) {
213 poly <<
QPointF(point.x1, point.y1);
214 poly <<
QPointF(point.x2, point.y2);
215 poly <<
QPointF(point.x3, point.y3);
216 poly <<
QPointF(point.x4, point.y4);
217 QRectF bounds = poly.boundingRect();
219 qCDebug(qLcLink) <<
"quadpoints" <<
i <<
"of" << quadPointsCount <<
":" << poly <<
"mapped bounds" << bounds;
220 linkData.d->rects << bounds;
228 FPDF_DEST dest = FPDFLink_GetDest(doc, linkAnnot);
229 FPDF_ACTION action = FPDFLink_GetAction(linkAnnot);
230 switch (FPDFAction_GetType(action)) {
231 case PDFACTION_UNSUPPORTED:
232 case PDFACTION_GOTO: {
233 linkData.d->page = FPDFDest_GetDestPageIndex(doc, dest);
234 if (linkData.d->page < 0) {
235 qCWarning(qLcLink) <<
"skipping link with invalid page number" << linkData.d->page;
238 FPDF_BOOL hasX, hasY, hasZoom;
240 ok = FPDFDest_GetLocationInPage(dest, &hasX, &hasY, &hasZoom, &
x, &
y, &zoom);
242 qCWarning(qLcLink) <<
"link with invalid location and/or zoom @" << linkData.d->rects;
248 linkData.d->zoom = zoom;
251 case PDFACTION_URI: {
252 unsigned long len = FPDFAction_GetURIPath(doc, action,
nullptr, 0);
254 qCWarning(qLcLink) <<
"skipping link with empty URI @" << linkData.d->rects;
258 unsigned long got = FPDFAction_GetURIPath(doc, action,
buf.data(),
len);
264 case PDFACTION_LAUNCH:
265 case PDFACTION_REMOTEGOTO: {
266 unsigned long len = FPDFAction_GetFilePath(action,
nullptr, 0);
268 qCWarning(qLcLink) <<
"skipping link with empty file path @" << linkData.d->rects;
272 unsigned long got = FPDFAction_GetFilePath(action,
buf.data(),
len);
287 FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage);
289 FPDF_PAGELINK webLinks = FPDFLink_LoadWebLinks(textPage);
291 int count = FPDFLink_CountWebLinks(webLinks);
294 int len = FPDFLink_GetURL(webLinks,
i,
nullptr, 0);
296 qCWarning(qLcLink) <<
"skipping link" <<
i <<
"with empty URL";
298 QList<unsigned short>
buf(
len);
299 int got = FPDFLink_GetURL(webLinks,
i,
buf.data(),
len);
302 reinterpret_cast<const char16_t *
>(
buf.data()), got - 1);
304 len = FPDFLink_CountRects(webLinks,
i);
305 for (
int r = 0;
r <
len; ++
r) {
314 FPDFLink_CloseWebLinks(webLinks);
316 FPDFText_ClosePage(textPage);
320 FPDF_ClosePage(pdfPage);
322 for (
const auto &l :
links)
331 qCDebug(qLcLink) <<
"sees document statusChanged" << status;
338#include "moc_qpdflinkmodel_p.cpp"
QObject * parent() const
Returns a pointer to the parent object.
QByteArray toLower() const &
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
QPointF mapPageToView(FPDF_PAGE pdfPage, double x, double y) const
The QPdfDocument class loads a PDF document and renders pages from it.
Status
This enum describes the current status of the document.
void statusChanged(QPdfDocument::Status status)
The QPdfLinkModel class holds the geometry and the destination for each link that the specified \l pa...
QHash< int, QByteArray > roleNames() const override
void pageChanged(int page)
int page
The page to load links from.
~QPdfLinkModel() override
Destroys the model.
QVariant data(const QModelIndex &index, int role) const override
\reimp
QPdfDocument * document
The document to load links from.
QPdfLink linkAt(QPointF point) const
Returns a \l {QPdfLink::isValid()}{valid} link if found under the point (given in units of points,...
Role
\value Link A QPdfLink object.
void setDocument(QPdfDocument *document)
int rowCount(const QModelIndex &parent) const override
\reimp
The QPdfLink class defines a link between a region on a page (such as a hyperlink or a search result)...
\inmodule QtCore\reentrant
The QPolygonF class provides a list of points using floating point precision.
\inmodule QtCore\reentrant
constexpr qreal bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr qreal right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf16(const char16_t *, qsizetype size=-1)
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Combined button and popup list for selecting options.
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLint GLint GLint GLint GLint x
[0]
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLenum GLuint GLenum GLsizei const GLchar * buf
GLdouble GLdouble GLdouble GLdouble q
static bool hasNext(const Symbols &symbols, int i)
obj metaObject() -> className()
myObject disconnect()
[26]