Skip to content

Commit

Permalink
Merge pull request #104 from dcaliste/links
Browse files Browse the repository at this point in the history
[office] Defer link scan on a page on request instead at load time.
  • Loading branch information
pvuorela authored Dec 15, 2016
2 parents e7cf259 + a252dc3 commit 65585d3
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 62 deletions.
22 changes: 18 additions & 4 deletions pdf/pdfcanvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct PDFPage {
, requested(false)
, renderWidth(0)
, texture(nullptr)
, linksLoaded(false)
{ }

int index;
Expand All @@ -53,7 +54,8 @@ struct PDFPage {

QList<Patch> patches;

QList<QPair<QRectF, QUrl> > links;
bool linksLoaded;
PDFDocument::LinkList links;
};

class PDFCanvas::Private
Expand Down Expand Up @@ -202,6 +204,7 @@ void PDFCanvas::setDocument(PDFDocument *doc)
d->document = doc;

connect(d->document, &PDFDocument::documentLoadedChanged, this, &PDFCanvas::documentLoaded);
connect(d->document, &PDFDocument::linksFinished, this, &PDFCanvas::linksFinished);
connect(d->document, &PDFDocument::pageFinished, this, &PDFCanvas::pageFinished);
connect(d->document, &PDFDocument::pageSizesFinished, this, &PDFCanvas::pageSizesFinished);
connect(d->document, &PDFDocument::documentLockedChanged, this, &PDFCanvas::documentLoaded);
Expand Down Expand Up @@ -293,8 +296,6 @@ void PDFCanvas::layout()
return;
}

PDFDocument::LinkMap links = d->document->linkTargets();

float totalHeight = 0.f;
for (int i = 0; i < d->pageCount; ++i) {
QSizeF unscaledSize = d->pageSizes.at(i);
Expand All @@ -303,13 +304,13 @@ void PDFCanvas::layout()
PDFPage page;
page.index = i;
page.rect = QRectF(0, totalHeight, width(), width() * ratio);
page.links = links.values(i);
page.requested = false; // We're cancelling all requests below
if (d->pages.contains(i)) {
page.renderWidth = d->pages.value(i).renderWidth;
page.textureArea = d->pages.value(i).textureArea;
page.texture = d->pages.value(i).texture;
page.patches = d->pages.value(i).patches;
page.links = d->pages.value(i).links;
}
d->pages.insert(i, page);

Expand Down Expand Up @@ -453,6 +454,16 @@ QPointF PDFCanvas::fromPageToItem(int index, const QPointF &point) const
point.y() * page.rect.height() + page.rect.y());
}

void PDFCanvas::linksFinished(int id, const QList<QPair<QRectF, QUrl> > &links)
{
PDFPage &page = d->pages[id];

page.linksLoaded = true;
page.links = links;
if (!page.links.isEmpty())
update();
}

void PDFCanvas::pageModified(int id, const QRectF &subpart)
{
PDFPage &page = d->pages[id];
Expand Down Expand Up @@ -587,6 +598,9 @@ QSGNode* PDFCanvas::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeDa
};

if (showPage) {
if (!page.linksLoaded)
d->document->requestLinksAtPage(i);

textureLimit.moveTo(0, 0);
bool fullPageFit = textureLimit.contains(pageRect);
QRect showableArea = {
Expand Down
1 change: 1 addition & 0 deletions pdf/pdfcanvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class PDFCanvas : public QQuickItem
virtual QSGNode* updatePaintNode(QSGNode *node, UpdatePaintNodeData*);

private Q_SLOTS:
void linksFinished(int id, const QList<QPair<QRectF, QUrl> > &links);
void pageModified(int id, const QRectF &subpart);
void pageFinished(int id, int pageRenderWidth,
QRect subpart, QSGTexture *texture, int extraData);
Expand Down
19 changes: 14 additions & 5 deletions pdf/pdfdocument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,6 @@ bool PDFDocument::isModified() const
return d->modified;
}

PDFDocument::LinkMap PDFDocument::linkTargets() const
{
return d->thread->linkTargets();
}

PDFDocument::TextList PDFDocument::textBoxesAtPage(int page)
{
return d->thread->textBoxesAtPage(page);
Expand Down Expand Up @@ -211,6 +206,15 @@ void PDFDocument::requestUnLock(const QString &password)
d->thread->queueJob(job);
}

void PDFDocument::requestLinksAtPage(int page)
{
if (!isLoaded() || isLocked())
return;

LinksJob* job = new LinksJob(page);
d->thread->queueJob(job);
}

void PDFDocument::requestPage(int index, int size, QQuickWindow *window,
QRect subpart, int extraData)
{
Expand Down Expand Up @@ -303,6 +307,11 @@ void PDFDocument::jobFinished(PDFJob *job)
emit pageCountChanged();
break;
}
case PDFJob::LinksJob: {
LinksJob* j = static_cast<LinksJob*>(job);
emit linksFinished(j->m_page, j->m_links);
break;
}
case PDFJob::RenderPageJob: {
RenderPageJob* j = static_cast<RenderPageJob*>(job);
emit pageFinished(j->m_index, j->renderWidth(), j->m_subpart,
Expand Down
5 changes: 3 additions & 2 deletions pdf/pdfdocument.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class PDFDocument : public QObject, public QQmlParserStatus
~PDFDocument();

public:
typedef QMultiMap<int, QPair<QRectF, QUrl> > LinkMap;
typedef QList<QPair<QRectF, QUrl> > LinkList;
typedef QList<QPair<QRectF, Poppler::TextBox*> > TextList;

QString source() const;
Expand All @@ -61,7 +61,6 @@ class PDFDocument : public QObject, public QQmlParserStatus
bool searching() const;
QObject* searchModel() const;

LinkMap linkTargets() const;
TextList textBoxesAtPage(int page);

bool isLoaded() const;
Expand All @@ -83,6 +82,7 @@ public Q_SLOTS:
void setSource(const QString &source);
void setAutoSavePath(const QString &filename);
void requestUnLock(const QString &password);
void requestLinksAtPage(int page);
void requestPage(int index, int size, QQuickWindow *window,
QRect subpart = QRect(), int extraData = 0);
void prioritizeRequest(int index, int size, QRect subpart = QRect());
Expand All @@ -109,6 +109,7 @@ public Q_SLOTS:
void documentFailedChanged();
void documentLockedChanged();
void documentModifiedChanged();
void linksFinished(int page, const LinkList &links);
void pageFinished(int index, int resolution, QRect subpart,
QSGTexture *page, int extraData);
void pageSizesFinished(const QList<QSizeF> &heights);
Expand Down
57 changes: 57 additions & 0 deletions pdf/pdfjob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "pdfjob.h"

#include <QtMath>
#include <QUrlQuery>
#include <poppler-qt5.h>

LoadDocumentJob::LoadDocumentJob(const QString &source)
Expand Down Expand Up @@ -48,6 +49,62 @@ void UnLockDocumentJob::run()
m_document->unlock(m_password.toUtf8(), m_password.toUtf8());
}

LinksJob::LinksJob(int page)
: PDFJob(PDFJob::LinksJob), m_page(page)
{
}

void LinksJob::run()
{
Q_ASSERT(m_document);

if (m_document->isLocked() || m_page < 0 || m_page >= m_document->numPages())
return;

Poppler::Page *page = m_document->page(m_page);
QList<Poppler::Link*> links = page->links();
for (Poppler::Link* link : links) {
// link->linkArea() may return negative heights,
// as mentioned in Freedesktop bug:
// https://bugs.freedesktop.org/show_bug.cgi?id=93900
// To avoid later unexpected asumption on height,
// link->linkArea() is normalized.
switch (link->linkType()) {
case (Poppler::Link::Browse): {
Poppler::LinkBrowse *realLink = static_cast<Poppler::LinkBrowse*>(link);
QRectF linkArea = link->linkArea().normalized();
m_links.append(QPair<QRectF, QUrl>(linkArea, realLink->url()));
break;
}
case (Poppler::Link::Goto): {
Poppler::LinkGoto *gotoLink = static_cast<Poppler::LinkGoto*>(link);
// Not handling goto link to external file currently.
if (gotoLink->isExternal())
break;
QRectF linkArea = link->linkArea().normalized();
QUrl linkURL = QUrl("");
QUrlQuery query = QUrlQuery();
query.addQueryItem("page", QString::number(gotoLink->destination().pageNumber()));
if (gotoLink->destination().isChangeLeft()) {
query.addQueryItem("left", QString::number(gotoLink->destination().left()));
}
if (gotoLink->destination().isChangeTop()) {
query.addQueryItem("top", QString::number(gotoLink->destination().top()));
}
linkURL.setQuery(query);
m_links.append(QPair<QRectF, QUrl>(linkArea, linkURL));
break;
}
default:
break;
}

}

qDeleteAll(links);
delete page;
}

RenderPageJob::RenderPageJob(int index, uint width, QQuickWindow *window,
QRect subpart, int extraData)
: PDFJob(PDFJob::RenderPageJob), m_index(index), m_subpart(subpart), m_page(0), m_extraData(extraData), m_window(window), m_width(width)
Expand Down
13 changes: 13 additions & 0 deletions pdf/pdfjob.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class PDFJob : public QObject
enum JobType {
LoadDocumentJob,
UnLockDocumentJob,
LinksJob,
RenderPageJob,
PageSizesJob,
SearchDocumentJob,
Expand Down Expand Up @@ -80,6 +81,18 @@ class UnLockDocumentJob : public PDFJob
QString m_password;
};

class LinksJob : public PDFJob
{
Q_OBJECT
public:
LinksJob(int page);

virtual void run();

int m_page;
QList<QPair<QRectF, QUrl> > m_links;
};

class RenderPageJob : public PDFJob
{
Q_OBJECT
Expand Down
51 changes: 0 additions & 51 deletions pdf/pdfrenderthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include <QMutex>
#include <QDebug>
#include <QCoreApplication>
#include <QUrlQuery>
#include <QSaveFile>

#include "pdfjob.h"
Expand Down Expand Up @@ -185,55 +184,6 @@ class PDFRenderThreadPrivate
QMap<int, QList<QPair <QRectF, Poppler::TextBox*> > > textBoxes;
QMap<int, QList<Poppler::Annotation*> > annotations;

void rescanDocumentLinks()
{
linkTargets.clear();

for (int i = 0; i < document->numPages(); ++i) {
Poppler::Page *page = document->page(i);
QList<Poppler::Link*> links = page->links();
for (Poppler::Link* link : links) {
// link->linkArea() may return negative heights,
// as mentioned in Freedesktop bug:
// https://bugs.freedesktop.org/show_bug.cgi?id=93900
// To avoid later unexpected asumption on height,
// link->linkArea() is normalized.
switch (link->linkType()) {
case (Poppler::Link::Browse): {
Poppler::LinkBrowse *realLink = static_cast<Poppler::LinkBrowse*>(link);
QRectF linkArea = link->linkArea().normalized();
linkTargets.insert(i, QPair<QRectF, QUrl>(linkArea, realLink->url()));
break;
}
case (Poppler::Link::Goto): {
Poppler::LinkGoto *gotoLink = static_cast<Poppler::LinkGoto*>(link);
// Not handling goto link to external file currently.
if (gotoLink->isExternal())
break;
QRectF linkArea = link->linkArea().normalized();
QUrl linkURL = QUrl("");
QUrlQuery query = QUrlQuery();
query.addQueryItem("page", QString::number(gotoLink->destination().pageNumber()));
if (gotoLink->destination().isChangeLeft()) {
query.addQueryItem("left", QString::number(gotoLink->destination().left()));
}
if (gotoLink->destination().isChangeTop()) {
query.addQueryItem("top", QString::number(gotoLink->destination().top()));
}
linkURL.setQuery(query);
linkTargets.insert(i, QPair<QRectF, QUrl>(linkArea, linkURL));
break;
}
default:
break;
}

}

qDeleteAll(links);
delete page;
}
}
void retrieveTextBoxes(int i)
{
if (i < 0 || i >= document->numPages()) {
Expand Down Expand Up @@ -526,7 +476,6 @@ void PDFRenderThreadQueue::processPendingJob()
d->loadFailure = true;
} else if (!d->document->isLocked()) {
d->tocModel = new PDFTocModel(d->document);
d->rescanDocumentLinks();
}

job->deleteLater();
Expand Down

0 comments on commit 65585d3

Please sign in to comment.