214 lines
4.8 KiB
C++
Executable File
214 lines
4.8 KiB
C++
Executable File
#include "nglpdfpage.h"
|
|
#include <utility>
|
|
|
|
#include <QtGui/QPainter>
|
|
#include <QtGui/QMouseEvent>
|
|
#include <QtCore/QUrl>
|
|
#include <math.h>
|
|
#include <iostream>
|
|
|
|
namespace NGL
|
|
{
|
|
template <typename T>
|
|
static inline T getRotatedSize(const T &in, Poppler::Page::Rotation rot)
|
|
{
|
|
switch (rot)
|
|
{
|
|
case Poppler::Page::Rotate0:
|
|
case Poppler::Page::Rotate180:
|
|
return in;
|
|
case Poppler::Page::Rotate90:
|
|
case Poppler::Page::Rotate270:
|
|
return in.transposed();
|
|
}
|
|
Q_ASSERT(false);
|
|
return in;
|
|
}
|
|
|
|
PDFPage::PDFPage(QWidget *parent)
|
|
: QWidget(parent)
|
|
, m_page(nullptr)
|
|
, m_scaleFactor(1.0)
|
|
, m_rotation(Poppler::Page::Rotate0)
|
|
{
|
|
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
setMouseTracking(true);
|
|
}
|
|
|
|
PDFPage::~PDFPage()
|
|
{
|
|
delete m_page;
|
|
}
|
|
|
|
void PDFPage::setPopplerPage(Poppler::Page *page)
|
|
{
|
|
if (m_page == page)
|
|
return;
|
|
delete m_page;
|
|
m_page = page;
|
|
m_links.clear();
|
|
m_linkRects.clear();
|
|
if (!m_page)
|
|
return;
|
|
|
|
// Poppler::Page::links() returns std::vector<std::unique_ptr<Poppler::Link>> in Poppler Qt6
|
|
auto links = m_page->links();
|
|
for (auto &linkUp : links)
|
|
{
|
|
Poppler::Link *link = linkUp.get();
|
|
if (!link)
|
|
continue;
|
|
if (link->linkType() == Poppler::Link::Browse ||
|
|
link->linkType() == Poppler::Link::Goto)
|
|
m_links.emplace_back(std::move(linkUp));
|
|
else
|
|
std::cerr << "linktype: " << link->linkType() << std::endl;
|
|
}
|
|
|
|
rebuildInternalData();
|
|
}
|
|
|
|
void PDFPage::setZoomFactor(double zoom)
|
|
{
|
|
if (qFuzzyCompare(m_scaleFactor, zoom))
|
|
return;
|
|
m_scaleFactor = zoom;
|
|
rebuildInternalData();
|
|
}
|
|
|
|
void PDFPage::setRotation(Poppler::Page::Rotation rot)
|
|
{
|
|
if (m_rotation == rot)
|
|
return;
|
|
m_rotation = rot;
|
|
rebuildInternalData();
|
|
}
|
|
|
|
void PDFPage::clearPixmap()
|
|
{
|
|
m_pdfPixmap = QPixmap();
|
|
}
|
|
|
|
QImage PDFPage::getPrintableImage(int resolution) const
|
|
{
|
|
if (!m_page)
|
|
return QImage();
|
|
|
|
|
|
Poppler::Page::Rotation rot = Poppler::Page::Rotate0;
|
|
|
|
if (m_page->orientation() == Poppler::Page::Landscape)
|
|
rot = Poppler::Page::Rotate270;
|
|
else if (m_page->orientation() == Poppler::Page::Seascape)
|
|
rot = Poppler::Page::Rotate90;
|
|
else if (m_page->orientation() == Poppler::Page::UpsideDown)
|
|
rot = Poppler::Page::Rotate180;
|
|
Q_UNUSED(rot)
|
|
|
|
|
|
return m_page->renderToImage(resolution, resolution, -1, -1, -1, -1, m_rotation);
|
|
}
|
|
|
|
QSize PDFPage::sizeHint() const
|
|
{
|
|
if (!m_page)
|
|
return QSize();
|
|
return getRotatedSize(m_page->pageSize(), m_rotation);
|
|
}
|
|
|
|
void PDFPage::paintEvent(QPaintEvent *event)
|
|
{
|
|
Q_UNUSED(event)
|
|
if (!m_page)
|
|
return;
|
|
if (m_pdfPixmap.isNull())
|
|
{
|
|
const QImage img = m_page->renderToImage(m_scaleFactor * 72, m_scaleFactor * 72, -1, -1, -1, -1, m_rotation);
|
|
m_pdfPixmap = QPixmap::fromImage(img);
|
|
emit pageRendered();
|
|
}
|
|
QPainter p(this);
|
|
p.drawPixmap(0, 0, m_pdfPixmap);
|
|
p.end();
|
|
}
|
|
|
|
void PDFPage::mouseMoveEvent(QMouseEvent *event)
|
|
{
|
|
const QPointF pos = event->position();
|
|
for (const auto &linkRect : std::as_const(m_linkRects))
|
|
{
|
|
if (linkRect.contains(pos))
|
|
{
|
|
setCursor(Qt::PointingHandCursor);
|
|
return;
|
|
}
|
|
}
|
|
setCursor(Qt::ArrowCursor);
|
|
QWidget::mouseMoveEvent(event);
|
|
}
|
|
|
|
void PDFPage::mouseReleaseEvent(QMouseEvent *event)
|
|
{
|
|
const QPointF pos = event->position();
|
|
for (int i = 0; i < m_linkRects.size(); ++i)
|
|
{
|
|
if (m_linkRects.at(i).contains(pos))
|
|
{
|
|
const Poppler::Link *link = m_links.at(i).get();
|
|
if (!link)
|
|
continue;
|
|
if (link->linkType() == Poppler::Link::Browse)
|
|
{
|
|
const Poppler::LinkBrowse *linkBrowse = static_cast<const Poppler::LinkBrowse *>(link);
|
|
emit externalLinkClicked(linkBrowse->url());
|
|
return;
|
|
}
|
|
else if (link->linkType() == Poppler::Link::Goto)
|
|
{
|
|
const Poppler::LinkGoto *linkGoto = static_cast<const Poppler::LinkGoto *>(link);
|
|
if (linkGoto->isExternal())
|
|
{
|
|
const QUrl url = QUrl::fromLocalFile(linkGoto->fileName());
|
|
emit externalLinkClicked(url.toString());
|
|
return;
|
|
}
|
|
emit linkClicked(linkGoto->destination());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
QWidget::mouseReleaseEvent(event);
|
|
}
|
|
|
|
void PDFPage::rebuildInternalData()
|
|
{
|
|
clearPixmap();
|
|
|
|
if (!m_page)
|
|
return;
|
|
|
|
const QSizeF s(rotatedPageSize());
|
|
const int w = qRound(s.width() * m_scaleFactor);
|
|
const int h = qRound(s.height() * m_scaleFactor);
|
|
setMinimumSize(w, h);
|
|
resize(sizeHint());
|
|
|
|
|
|
m_linkRects.clear();
|
|
m_linkRects.reserve(static_cast<int>(m_links.size()));
|
|
for (const auto &linkUp : m_links)
|
|
{
|
|
const Poppler::Link *link = linkUp.get();
|
|
if (!link)
|
|
continue;
|
|
const QRectF r = link->linkArea();
|
|
m_linkRects += QRectF(r.x() * w, r.y() * h, r.width() * w, r.height() * h);
|
|
}
|
|
}
|
|
|
|
QSizeF PDFPage::rotatedPageSize() const
|
|
{
|
|
return m_page ? getRotatedSize(m_page->pageSizeF(), m_rotation) : QSizeF();
|
|
}
|
|
}
|