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); }
void addSynopsisChildren(QDomNode *parent, int level) { if (!parent || parent->isNull()) return; // keep track of the current listViewItem QDomNode n = parent->firstChild(); while (!n.isNull()) { PDFTocEntry *tocEntry = new PDFTocEntry; tocEntry->level = level; // convert the node to an element (sure it is) QDomElement e = n.toElement(); tocEntry->title = e.tagName(); // Apparently we can have external links in the ToC. // Not doing this for now, but leave it in here as a note to self // if (!e.attribute("ExternalFileName").isNull()) item.setAttribute("ExternalFileName", e.attribute("ExternalFileName")); if (!e.attribute("DestinationName").isNull()) { Poppler::LinkDestination *dest = document->linkDestination(e.attribute("DestinationName")); if (dest) { tocEntry->pageNumber = dest->pageNumber(); delete dest; } //item.setAttribute("ViewportName", e.attribute("DestinationName")); } if (!e.attribute("Destination").isNull()) { //fillViewportFromLinkDestination( vp, Poppler::LinkDestination(e.attribute("Destination")) ); //item.setAttribute( "Viewport", vp.toString() ); Poppler::LinkDestination dest(e.attribute("Destination")); tocEntry->pageNumber = dest.pageNumber(); } // if (!e.attribute("Open").isNull()) item.setAttribute("Open", e.attribute("Open")); // if (!e.attribute("DestinationURI").isNull()) item.setAttribute("URL", e.attribute("DestinationURI")); // Add the entry to the list of ToC entries entries.append(tocEntry); // descend recursively and advance to the next node ++level; if (e.hasChildNodes()) addSynopsisChildren(&n, level); --level; n = n.nextSibling(); } }
static void copyToc(const QUrl &docUrl, Poppler::Document *doc, QDomNode node, QList<Choice> &choices, int indent) { while (!node.isNull()) { if (node.isElement()) { QDomElement el = node.toElement(); QString destName = el.attribute("DestinationName", QString()); if (!destName.isNull()) { Poppler::LinkDestination *dest = doc->linkDestination(destName); QUrl refUrl(docUrl); refUrl.setFragment("page:" + QString::number(dest->pageNumber() - 1)); delete dest; QString displayName(QString(indent * 2, ' ') + el.nodeName()); choices << Choice(displayName, refUrl.toString()); } } if (node.hasChildNodes()) { copyToc(docUrl, doc, node.firstChild(), choices, indent + 1); } node = node.nextSibling(); } }