static void fillToc(Poppler::Document *doc, const QDomNode &parent, QTreeWidget *tree, QTreeWidgetItem *parentItem) { QTreeWidgetItem *newitem = 0; for (QDomNode node = parent.firstChild(); !node.isNull(); node = node.nextSibling()) { QDomElement e = node.toElement(); // for some unknown reason e.attribute("Destination") does not exist while Okular successfully uses it; so we cannot use Poppler::LinkDestination(e.attribute(QString::fromLatin1("Destination"))).pageNumber() and must use the following // const int pageNumber = doc->linkDestination(e.attribute(QString::fromLatin1("DestinationName")))->pageNumber(); Poppler::LinkDestination *dest = doc->linkDestination(e.attribute(QString::fromLatin1("DestinationName"))); const double pageNumber = dest->pageNumber() + dest->top(); delete dest; if (!parentItem) { newitem = new QTreeWidgetItem(tree, newitem); } else { newitem = new QTreeWidgetItem(parentItem, newitem); } newitem->setText(0, e.tagName()); newitem->setData(0, Qt::UserRole, pageNumber); bool isOpen = false; if (e.hasAttribute(QString::fromLatin1("Open"))) { isOpen = QVariant(e.attribute(QString::fromLatin1("Open"))).toBool(); } if (isOpen) { tree->expandItem(newitem); } if (e.hasChildNodes()) { fillToc(doc, node, tree, newitem); } } }
static QList<Link> getLinks(Poppler::Page* popplerPage, const QStringList &popplerPageLabels) { QList<Link> links; //QTime t = QTime::currentTime(); QList<Poppler::Link*> popplerLinks = popplerPage->links(); // this is slow //qCritical() << t.msecsTo(QTime::currentTime()); links.reserve(popplerLinks.size()); while (!popplerLinks.isEmpty()) { Poppler::Link *popplerLink = popplerLinks.takeFirst(); Link link; // link.linkArea = popplerLink->linkArea(); const QRectF linkArea = popplerLink->linkArea(); link.linkArea = QRectF(linkArea.left(), qMin(linkArea.top(), linkArea.bottom()), qAbs(linkArea.right() - linkArea.left()), qAbs(linkArea.bottom() - linkArea.top())); // poppler switches top and bottom of this box :( switch (popplerLink->linkType()) { case Poppler::Link::Goto: { const Poppler::LinkGoto *popplerLinkGoto = static_cast<const Poppler::LinkGoto*>(popplerLink); const Poppler::LinkDestination popplerDest = popplerLinkGoto->destination(); link.pageNumber = popplerDest.pageNumber() - 1 + popplerDest.top(); link.pageLabel = popplerPageLabels.at(int(link.pageNumber)); } break; case Poppler::Link::Browse: { const Poppler::LinkBrowse *popplerLinkBrowse = static_cast<const Poppler::LinkBrowse*>(popplerLink); link.url = popplerLinkBrowse->url(); } break; case Poppler::Link::Action: { const Poppler::LinkAction *popplerLinkAction = static_cast<const Poppler::LinkAction*>(popplerLink); link.pageNumber = -1; // since Poppler::LinkAction::ActionType doesn't specify a "None" value, we use pageNumber to distinguish this type of action, we do not check whether popplerLinkAction->actionType() is > 0 because it is not documented that all valid action types have a value > 0 link.actionType = popplerLinkAction->actionType(); } break; case Poppler::Link::Execute: // TODO case Poppler::Link::Sound: // TODO case Poppler::Link::Movie: // not implemented in poppler 0.16 case Poppler::Link::JavaScript: // TODO default: // do nothing break; } links << link; delete popplerLink; } return links; }
void GridLayout::goto_link_destination(const Poppler::LinkDestination &link) { int link_page = link.pageNumber() - 1; float w = res->get_page_width(link_page, false); float h = res->get_page_height(link_page, false); const QPointF link_point = rotate_point(QPointF(link.left() * w, link.top() * h), w, h, res->get_rotation()); QPoint p = get_target_page_distance(link_page); if (link.isChangeLeft()) { p.rx() += link_point.x() * size - width * jump_padding; } if (link.isChangeTop()) { p.ry() += link_point.y() * size - height * jump_padding; } view_point(p); }