mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-04-12 09:31:11 +02:00
Annotation popup window implementation
This commit is contained in:
parent
6c746ba901
commit
643c85ed35
@ -26,8 +26,14 @@
|
|||||||
#include "pdfparser.h"
|
#include "pdfparser.h"
|
||||||
#include "pdfdrawwidget.h"
|
#include "pdfdrawwidget.h"
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
@ -174,8 +180,9 @@ std::vector<PDFAppeareanceStreams::Key> PDFAnnotation::getDrawKeys() const
|
|||||||
return { PDFAppeareanceStreams::Key{ PDFAppeareanceStreams::Appearance::Normal, QByteArray() } };
|
return { PDFAppeareanceStreams::Key{ PDFAppeareanceStreams::Appearance::Normal, QByteArray() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object)
|
PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference)
|
||||||
{
|
{
|
||||||
|
PDFObject object = storage->getObjectByReference(reference);
|
||||||
PDFAnnotationPtr result;
|
PDFAnnotationPtr result;
|
||||||
|
|
||||||
const PDFDictionary* dictionary = storage->getDictionaryFromObject(object);
|
const PDFDictionary* dictionary = storage->getDictionaryFromObject(object);
|
||||||
@ -185,7 +192,6 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
PDFDocumentDataLoaderDecorator loader(storage);
|
PDFDocumentDataLoaderDecorator loader(storage);
|
||||||
|
|
||||||
QRectF annotationsRectangle = loader.readRectangle(dictionary->get("Rect"), QRectF());
|
QRectF annotationsRectangle = loader.readRectangle(dictionary->get("Rect"), QRectF());
|
||||||
|
|
||||||
// Determine type of annotation
|
// Determine type of annotation
|
||||||
@ -595,6 +601,7 @@ PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load common data for annotation
|
// Load common data for annotation
|
||||||
|
result->m_selfReference = reference;
|
||||||
result->m_rectangle = annotationsRectangle;
|
result->m_rectangle = annotationsRectangle;
|
||||||
result->m_contents = loader.readTextStringFromDictionary(dictionary, "Contents", QString());
|
result->m_contents = loader.readTextStringFromDictionary(dictionary, "Contents", QString());
|
||||||
result->m_pageReference = loader.readReferenceFromDictionary(dictionary, "P");
|
result->m_pageReference = loader.readReferenceFromDictionary(dictionary, "P");
|
||||||
@ -999,7 +1006,8 @@ void PDFAnnotationManager::drawPage(QPainter* painter,
|
|||||||
const PDFAnnotation::Flags annotationFlags = annotation.annotation->getFlags();
|
const PDFAnnotation::Flags annotationFlags = annotation.annotation->getFlags();
|
||||||
if (annotationFlags.testFlag(PDFAnnotation::Hidden) || // Annotation is completely hidden
|
if (annotationFlags.testFlag(PDFAnnotation::Hidden) || // Annotation is completely hidden
|
||||||
(m_target == Target::Print && !annotationFlags.testFlag(PDFAnnotation::Print)) || // Target is print and annotation is marked as not printed
|
(m_target == Target::Print && !annotationFlags.testFlag(PDFAnnotation::Print)) || // Target is print and annotation is marked as not printed
|
||||||
(m_target == Target::View && annotationFlags.testFlag(PDFAnnotation::NoView))) // Target is view, and annotation is disabled for screen
|
(m_target == Target::View && annotationFlags.testFlag(PDFAnnotation::NoView)) || // Target is view, and annotation is disabled for screen
|
||||||
|
annotation.annotation->isReplyTo()) // Annotation is reply to another annotation, display just the first annotation
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1121,7 +1129,7 @@ PDFAnnotationManager::PageAnnotations& PDFAnnotationManager::getPageAnnotations(
|
|||||||
annotations.annotations.reserve(pageAnnotations.size());
|
annotations.annotations.reserve(pageAnnotations.size());
|
||||||
for (PDFObjectReference annotationReference : pageAnnotations)
|
for (PDFObjectReference annotationReference : pageAnnotations)
|
||||||
{
|
{
|
||||||
PDFAnnotationPtr annotationPtr = PDFAnnotation::parse(&m_document->getStorage(), m_document->getObjectByReference(annotationReference));
|
PDFAnnotationPtr annotationPtr = PDFAnnotation::parse(&m_document->getStorage(), annotationReference);
|
||||||
if (annotationPtr)
|
if (annotationPtr)
|
||||||
{
|
{
|
||||||
PageAnnotation annotation;
|
PageAnnotation annotation;
|
||||||
@ -1257,6 +1265,7 @@ void PDFWidgetAnnotationManager::updateFromMouseEvent(QMouseEvent* event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_tooltip = QString();
|
m_tooltip = QString();
|
||||||
|
bool appearanceChanged = false;
|
||||||
|
|
||||||
// We must update appearance states, and update tooltip
|
// We must update appearance states, and update tooltip
|
||||||
PDFWidgetSnapshot snapshot = m_proxy->getSnapshot();
|
PDFWidgetSnapshot snapshot = m_proxy->getSnapshot();
|
||||||
@ -1268,6 +1277,13 @@ void PDFWidgetAnnotationManager::updateFromMouseEvent(QMouseEvent* event)
|
|||||||
PageAnnotations& pageAnnotations = getPageAnnotations(snapshotItem.pageIndex);
|
PageAnnotations& pageAnnotations = getPageAnnotations(snapshotItem.pageIndex);
|
||||||
for (PageAnnotation& pageAnnotation : pageAnnotations.annotations)
|
for (PageAnnotation& pageAnnotation : pageAnnotations.annotations)
|
||||||
{
|
{
|
||||||
|
if (pageAnnotation.annotation->isReplyTo())
|
||||||
|
{
|
||||||
|
// Annotation is reply to another annotation, do not interact with it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PDFAppeareanceStreams::Appearance oldAppearance = pageAnnotation.appearance;
|
||||||
QRectF annotationRect = pageAnnotation.annotation->getRectangle();
|
QRectF annotationRect = pageAnnotation.annotation->getRectangle();
|
||||||
QMatrix matrix = prepareTransformations(snapshotItem.pageToDeviceMatrix, widget, pageAnnotation.annotation->getFlags(), m_document->getCatalog()->getPage(snapshotItem.pageIndex), annotationRect);
|
QMatrix matrix = prepareTransformations(snapshotItem.pageToDeviceMatrix, widget, pageAnnotation.annotation->getFlags(), m_document->getCatalog()->getPage(snapshotItem.pageIndex), annotationRect);
|
||||||
QPainterPath path;
|
QPainterPath path;
|
||||||
@ -1281,7 +1297,7 @@ void PDFWidgetAnnotationManager::updateFromMouseEvent(QMouseEvent* event)
|
|||||||
// Generate tooltip
|
// Generate tooltip
|
||||||
if (m_tooltip.isEmpty())
|
if (m_tooltip.isEmpty())
|
||||||
{
|
{
|
||||||
const PDFMarkupAnnotation* markupAnnotation = dynamic_cast<const PDFMarkupAnnotation*>(pageAnnotation.annotation.data());
|
const PDFMarkupAnnotation* markupAnnotation = pageAnnotation.annotation->asMarkupAnnotation();
|
||||||
if (markupAnnotation)
|
if (markupAnnotation)
|
||||||
{
|
{
|
||||||
QColor backgroundColor = markupAnnotation->getDrawColorFromAnnotationColor(markupAnnotation->getColor());
|
QColor backgroundColor = markupAnnotation->getDrawColorFromAnnotationColor(markupAnnotation->getColor());
|
||||||
@ -1293,13 +1309,137 @@ void PDFWidgetAnnotationManager::updateFromMouseEvent(QMouseEvent* event)
|
|||||||
m_tooltip = QString("<p><b>%1 (%2)</b></p><p>%3</p>").arg(markupAnnotation->getWindowTitle(), markupAnnotation->getCreationDate().toLocalTime().toString(), markupAnnotation->getContents());
|
m_tooltip = QString("<p><b>%1 (%2)</b></p><p>%3</p>").arg(markupAnnotation->getWindowTitle(), markupAnnotation->getCreationDate().toLocalTime().toString(), markupAnnotation->getContents());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate popup window
|
||||||
|
if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton)
|
||||||
|
{
|
||||||
|
const PDFMarkupAnnotation* markupAnnotation = pageAnnotation.annotation->asMarkupAnnotation();
|
||||||
|
if (markupAnnotation)
|
||||||
|
{
|
||||||
|
QDialog* dialog = createDialogForMarkupAnnotations(widget, pageAnnotation, pageAnnotations);
|
||||||
|
|
||||||
|
// Set proper dialog position - according to the popup annotation. If we
|
||||||
|
// do not have popup annotation, then try to use annotations rectangle.
|
||||||
|
if (const PageAnnotation* popupAnnotation = pageAnnotations.getPopupAnnotation(pageAnnotation))
|
||||||
|
{
|
||||||
|
QPoint popupPoint = snapshotItem.pageToDeviceMatrix.map(popupAnnotation->annotation->getRectangle().bottomLeft()).toPoint();
|
||||||
|
popupPoint = widget->mapToGlobal(popupPoint);
|
||||||
|
dialog->move(popupPoint);
|
||||||
|
}
|
||||||
|
else if (markupAnnotation->getRectangle().isValid())
|
||||||
|
{
|
||||||
|
QPoint popupPoint = snapshotItem.pageToDeviceMatrix.map(markupAnnotation->getRectangle().bottomRight()).toPoint();
|
||||||
|
popupPoint = widget->mapToGlobal(popupPoint);
|
||||||
|
dialog->move(popupPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog->exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pageAnnotation.appearance = PDFAppeareanceStreams::Appearance::Normal;
|
pageAnnotation.appearance = PDFAppeareanceStreams::Appearance::Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
appearanceChanged |= oldAppearance != pageAnnotation.appearance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If appearance has changed, then we must redraw the page
|
||||||
|
if (appearanceChanged)
|
||||||
|
{
|
||||||
|
emit widget->getDrawWidgetProxy()->repaintNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog* PDFWidgetAnnotationManager::createDialogForMarkupAnnotations(PDFWidget* widget,
|
||||||
|
const PageAnnotation& pageAnnotation,
|
||||||
|
const PageAnnotations& pageAnnotations)
|
||||||
|
{
|
||||||
|
QDialog* dialog = new QDialog(widget->getDrawWidget()->getWidget(), Qt::Popup);
|
||||||
|
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||||
|
createWidgetsForMarkupAnnotations(dialog, pageAnnotation, pageAnnotations);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDFWidgetAnnotationManager::createWidgetsForMarkupAnnotations(QWidget* parentWidget,
|
||||||
|
const PageAnnotation& pageAnnotation,
|
||||||
|
const PageAnnotations& pageAnnotations)
|
||||||
|
{
|
||||||
|
std::vector<const PageAnnotation*> replies = pageAnnotations.getReplies(pageAnnotation);
|
||||||
|
replies.insert(replies.begin(), &pageAnnotation);
|
||||||
|
|
||||||
|
QScrollArea* scrollArea = new QScrollArea(parentWidget);
|
||||||
|
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||||
|
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout(parentWidget);
|
||||||
|
layout->addWidget(scrollArea);
|
||||||
|
layout->setMargin(0);
|
||||||
|
layout->setContentsMargins(QMargins());
|
||||||
|
|
||||||
|
QWidget* frameWidget = new QWidget(scrollArea);
|
||||||
|
QVBoxLayout* frameLayout = new QVBoxLayout(frameWidget);
|
||||||
|
frameLayout->setMargin(0);
|
||||||
|
scrollArea->setWidget(frameWidget);
|
||||||
|
|
||||||
|
const PDFMarkupAnnotation* markupMainAnnotation = pageAnnotation.annotation->asMarkupAnnotation();
|
||||||
|
QColor color = markupMainAnnotation->getDrawColorFromAnnotationColor(markupMainAnnotation->getColor());
|
||||||
|
QColor titleColor = QColor::fromHslF(color.hueF(), color.saturationF(), 0.2, 1.0);
|
||||||
|
QColor backgroundColor = QColor::fromHslF(color.hueF(), color.saturationF(), 0.9, 1.0);
|
||||||
|
|
||||||
|
QString style = "QGroupBox { "
|
||||||
|
"border: 2px solid black; "
|
||||||
|
"border-color: rgb(%4, %5, %6); "
|
||||||
|
"margin-top: 3ex; "
|
||||||
|
"background-color: rgb(%1, %2, %3); "
|
||||||
|
"}"
|
||||||
|
"QGroupBox::title { "
|
||||||
|
"subcontrol-origin: margin; "
|
||||||
|
"subcontrol-position: top center; "
|
||||||
|
"padding: 0px 8192px; "
|
||||||
|
"background-color: rgb(%4, %5, %6); "
|
||||||
|
"color: #FFFFFF;"
|
||||||
|
"}";
|
||||||
|
style = style.arg(backgroundColor.red()).arg(backgroundColor.green()).arg(backgroundColor.blue()).arg(titleColor.red()).arg(titleColor.green()).arg(titleColor.blue());
|
||||||
|
|
||||||
|
for (const PageAnnotation* annotation : replies)
|
||||||
|
{
|
||||||
|
const PDFMarkupAnnotation* markupAnnotation = annotation->annotation->asMarkupAnnotation();
|
||||||
|
|
||||||
|
if (!markupAnnotation)
|
||||||
|
{
|
||||||
|
// This should not happen...
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGroupBox* groupBox = new QGroupBox(scrollArea);
|
||||||
|
frameLayout->addWidget(groupBox);
|
||||||
|
|
||||||
|
QString title = markupAnnotation->getWindowTitle();
|
||||||
|
if (title.isEmpty())
|
||||||
|
{
|
||||||
|
title = markupAnnotation->getSubject();
|
||||||
|
}
|
||||||
|
|
||||||
|
title = QString("%1 (%2)").arg(title, markupAnnotation->getCreationDate().toLocalTime().toString(Qt::TextDate)).trimmed();
|
||||||
|
|
||||||
|
groupBox->setStyleSheet(style);
|
||||||
|
groupBox->setTitle(title);
|
||||||
|
QVBoxLayout* groupBoxLayout = new QVBoxLayout(groupBox);
|
||||||
|
|
||||||
|
QLabel* label = new QLabel(groupBox);
|
||||||
|
label->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||||
|
label->setWordWrap(true);
|
||||||
|
label->setText(markupAnnotation->getContents());
|
||||||
|
label->setFixedWidth(PDFWidgetUtils::scaleDPI_x(label, 250));
|
||||||
|
label->setMinimumHeight(label->sizeHint().height());
|
||||||
|
groupBoxLayout->addWidget(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
frameWidget->setFixedSize(frameWidget->minimumSizeHint());
|
||||||
|
parentWidget->setFixedSize(scrollArea->sizeHint());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFSimpleGeometryAnnotation::draw(AnnotationDrawParameters& parameters) const
|
void PDFSimpleGeometryAnnotation::draw(AnnotationDrawParameters& parameters) const
|
||||||
@ -1360,6 +1500,11 @@ QColor PDFSimpleGeometryAnnotation::getFillColor() const
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PDFMarkupAnnotation::isReplyTo() const
|
||||||
|
{
|
||||||
|
return m_inReplyTo.isValid() && m_replyType == ReplyType::Reply;
|
||||||
|
}
|
||||||
|
|
||||||
QColor PDFMarkupAnnotation::getStrokeColor() const
|
QColor PDFMarkupAnnotation::getStrokeColor() const
|
||||||
{
|
{
|
||||||
QColor color = PDFAnnotation::getStrokeColor();
|
QColor color = PDFAnnotation::getStrokeColor();
|
||||||
@ -2444,4 +2589,62 @@ void PDFSoundAnnotation::draw(AnnotationDrawParameters& parameters) const
|
|||||||
drawCharacterSymbol(text, getOpacity(), parameters);
|
drawCharacterSymbol(text, getOpacity(), parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PDFAnnotationManager::PageAnnotation* PDFAnnotationManager::PageAnnotations::getPopupAnnotation(const PageAnnotation& pageAnnotation) const
|
||||||
|
{
|
||||||
|
const PDFMarkupAnnotation* markupAnnotation = pageAnnotation.annotation->asMarkupAnnotation();
|
||||||
|
if (markupAnnotation)
|
||||||
|
{
|
||||||
|
const PDFObjectReference popupAnnotation = markupAnnotation->getPopupAnnotation();
|
||||||
|
auto it = std::find_if(annotations.cbegin(), annotations.cend(), [this, popupAnnotation](const PageAnnotation& pa) { return pa.annotation->getSelfReference() == popupAnnotation; });
|
||||||
|
if (it != annotations.cend())
|
||||||
|
{
|
||||||
|
return &*it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const PDFAnnotationManager::PageAnnotation*> PDFAnnotationManager::PageAnnotations::getReplies(const PageAnnotation& pageAnnotation) const
|
||||||
|
{
|
||||||
|
std::vector<const PageAnnotation*> result;
|
||||||
|
|
||||||
|
const PDFObjectReference reference = pageAnnotation.annotation->getSelfReference();
|
||||||
|
for (size_t i = 0, count = annotations.size(); i < count; ++i)
|
||||||
|
{
|
||||||
|
const PageAnnotation& currentAnnotation = annotations[i];
|
||||||
|
if (currentAnnotation.annotation->isReplyTo())
|
||||||
|
{
|
||||||
|
const PDFMarkupAnnotation* markupAnnotation = currentAnnotation.annotation->asMarkupAnnotation();
|
||||||
|
Q_ASSERT(markupAnnotation);
|
||||||
|
|
||||||
|
if (markupAnnotation->getInReplyTo() == reference)
|
||||||
|
{
|
||||||
|
result.push_back(¤tAnnotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto comparator = [](const PageAnnotation* l, const PageAnnotation* r)
|
||||||
|
{
|
||||||
|
QDateTime leftDateTime = l->annotation->getLastModifiedDateTime();
|
||||||
|
QDateTime rightDateTime = r->annotation->getLastModifiedDateTime();
|
||||||
|
|
||||||
|
if (const PDFMarkupAnnotation* markupL = l->annotation->asMarkupAnnotation())
|
||||||
|
{
|
||||||
|
leftDateTime = markupL->getCreationDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const PDFMarkupAnnotation* markupR = r->annotation->asMarkupAnnotation())
|
||||||
|
{
|
||||||
|
rightDateTime = markupR->getCreationDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
return leftDateTime < rightDateTime;
|
||||||
|
};
|
||||||
|
std::sort(result.begin(), result.end(), comparator);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -38,6 +38,7 @@ class QWheelEvent;
|
|||||||
|
|
||||||
namespace pdf
|
namespace pdf
|
||||||
{
|
{
|
||||||
|
class PDFWidget;
|
||||||
class PDFObjectStorage;
|
class PDFObjectStorage;
|
||||||
class PDFDrawWidgetProxy;
|
class PDFDrawWidgetProxy;
|
||||||
class PDFFontCache;
|
class PDFFontCache;
|
||||||
@ -471,6 +472,7 @@ public:
|
|||||||
|
|
||||||
virtual PDFMarkupAnnotation* asMarkupAnnotation() { return nullptr; }
|
virtual PDFMarkupAnnotation* asMarkupAnnotation() { return nullptr; }
|
||||||
virtual const PDFMarkupAnnotation* asMarkupAnnotation() const { return nullptr; }
|
virtual const PDFMarkupAnnotation* asMarkupAnnotation() const { return nullptr; }
|
||||||
|
virtual bool isReplyTo() const { return false; }
|
||||||
|
|
||||||
/// Draws the annotation using parameters. Annotation is drawn onto painter,
|
/// Draws the annotation using parameters. Annotation is drawn onto painter,
|
||||||
/// but actual graphics can be drawn outside of annotation's rectangle.
|
/// but actual graphics can be drawn outside of annotation's rectangle.
|
||||||
@ -483,6 +485,7 @@ public:
|
|||||||
/// Returns a list of appearance states, which must be created for this annotation
|
/// Returns a list of appearance states, which must be created for this annotation
|
||||||
virtual std::vector<PDFAppeareanceStreams::Key> getDrawKeys() const;
|
virtual std::vector<PDFAppeareanceStreams::Key> getDrawKeys() const;
|
||||||
|
|
||||||
|
PDFObjectReference getSelfReference() const { return m_selfReference; }
|
||||||
const QRectF& getRectangle() const { return m_rectangle; }
|
const QRectF& getRectangle() const { return m_rectangle; }
|
||||||
const QString& getContents() const { return m_contents; }
|
const QString& getContents() const { return m_contents; }
|
||||||
PDFObjectReference getPageReference() const { return m_pageReference; }
|
PDFObjectReference getPageReference() const { return m_pageReference; }
|
||||||
@ -499,8 +502,8 @@ public:
|
|||||||
|
|
||||||
/// Parses annotation from the object. If error occurs, then nullptr is returned.
|
/// Parses annotation from the object. If error occurs, then nullptr is returned.
|
||||||
/// \param storage Object storage
|
/// \param storage Object storage
|
||||||
/// \param object Annotation object
|
/// \param reference Annotation object reference
|
||||||
static PDFAnnotationPtr parse(const PDFObjectStorage* storage, PDFObject object);
|
static PDFAnnotationPtr parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
/// Parses quadrilaterals and fills them in the painter path. If no quadrilaterals are defined,
|
/// Parses quadrilaterals and fills them in the painter path. If no quadrilaterals are defined,
|
||||||
/// then annotation rectangle is used. If annotation rectangle is also invalid,
|
/// then annotation rectangle is used. If annotation rectangle is also invalid,
|
||||||
@ -581,7 +584,7 @@ protected:
|
|||||||
void drawCharacterSymbol(QString text, PDFReal opacity, AnnotationDrawParameters& parameters) const;
|
void drawCharacterSymbol(QString text, PDFReal opacity, AnnotationDrawParameters& parameters) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PDFObjectReference m_selfReference; ///< Reference to self
|
||||||
QRectF m_rectangle; ///< Annotation rectangle, in page coordinates, "Rect" entry
|
QRectF m_rectangle; ///< Annotation rectangle, in page coordinates, "Rect" entry
|
||||||
QString m_contents; ///< Text to be displayed to the user (or alternate text), "Content" entry
|
QString m_contents; ///< Text to be displayed to the user (or alternate text), "Content" entry
|
||||||
PDFObjectReference m_pageReference; ///< Reference to annotation's page, "P" entry
|
PDFObjectReference m_pageReference; ///< Reference to annotation's page, "P" entry
|
||||||
@ -607,6 +610,7 @@ public:
|
|||||||
|
|
||||||
virtual PDFMarkupAnnotation* asMarkupAnnotation() override { return this; }
|
virtual PDFMarkupAnnotation* asMarkupAnnotation() override { return this; }
|
||||||
virtual const PDFMarkupAnnotation* asMarkupAnnotation() const override { return this; }
|
virtual const PDFMarkupAnnotation* asMarkupAnnotation() const override { return this; }
|
||||||
|
virtual bool isReplyTo() const override;
|
||||||
|
|
||||||
enum class ReplyType
|
enum class ReplyType
|
||||||
{
|
{
|
||||||
@ -630,7 +634,7 @@ protected:
|
|||||||
virtual QColor getFillColor() const override;
|
virtual QColor getFillColor() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
QString m_windowTitle;
|
QString m_windowTitle;
|
||||||
PDFObjectReference m_popupAnnotation;
|
PDFObjectReference m_popupAnnotation;
|
||||||
@ -674,7 +678,7 @@ public:
|
|||||||
const QString& getStateModel() const { return m_stateModel; }
|
const QString& getStateModel() const { return m_stateModel; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
bool m_open = false;
|
bool m_open = false;
|
||||||
QByteArray m_iconName;
|
QByteArray m_iconName;
|
||||||
@ -707,7 +711,7 @@ public:
|
|||||||
const PDFAnnotationQuadrilaterals& getActivationRegion() const { return m_activationRegion; }
|
const PDFAnnotationQuadrilaterals& getActivationRegion() const { return m_activationRegion; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
PDFActionPtr m_action;
|
PDFActionPtr m_action;
|
||||||
LinkHighlightMode m_highlightMode = LinkHighlightMode::Invert;
|
LinkHighlightMode m_highlightMode = LinkHighlightMode::Invert;
|
||||||
@ -750,7 +754,7 @@ public:
|
|||||||
AnnotationLineEnding getEndLineEnding() const { return m_endLineEnding; }
|
AnnotationLineEnding getEndLineEnding() const { return m_endLineEnding; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
QByteArray m_defaultAppearance;
|
QByteArray m_defaultAppearance;
|
||||||
Justification m_justification = Justification::Left;
|
Justification m_justification = Justification::Left;
|
||||||
@ -803,7 +807,7 @@ protected:
|
|||||||
virtual QColor getFillColor() const override;
|
virtual QColor getFillColor() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
QLineF m_line;
|
QLineF m_line;
|
||||||
AnnotationLineEnding m_startLineEnding = AnnotationLineEnding::None;
|
AnnotationLineEnding m_startLineEnding = AnnotationLineEnding::None;
|
||||||
@ -843,7 +847,7 @@ protected:
|
|||||||
virtual QColor getFillColor() const override;
|
virtual QColor getFillColor() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
AnnotationType m_type;
|
AnnotationType m_type;
|
||||||
std::vector<PDFReal> m_interiorColor;
|
std::vector<PDFReal> m_interiorColor;
|
||||||
@ -886,7 +890,7 @@ protected:
|
|||||||
virtual QColor getFillColor() const override;
|
virtual QColor getFillColor() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
AnnotationType m_type;
|
AnnotationType m_type;
|
||||||
std::vector<QPointF> m_vertices;
|
std::vector<QPointF> m_vertices;
|
||||||
@ -915,7 +919,7 @@ public:
|
|||||||
const PDFAnnotationQuadrilaterals& getHiglightArea() const { return m_highlightArea; }
|
const PDFAnnotationQuadrilaterals& getHiglightArea() const { return m_highlightArea; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
AnnotationType m_type;
|
AnnotationType m_type;
|
||||||
PDFAnnotationQuadrilaterals m_highlightArea;
|
PDFAnnotationQuadrilaterals m_highlightArea;
|
||||||
@ -940,7 +944,7 @@ public:
|
|||||||
Symbol getSymbol() const { return m_symbol; }
|
Symbol getSymbol() const { return m_symbol; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
QRectF m_caretRectangle;
|
QRectF m_caretRectangle;
|
||||||
Symbol m_symbol = Symbol::None;
|
Symbol m_symbol = Symbol::None;
|
||||||
@ -977,7 +981,7 @@ public:
|
|||||||
Stamp getStamp() const { return m_stamp; }
|
Stamp getStamp() const { return m_stamp; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
Stamp m_stamp = Stamp::Draft;
|
Stamp m_stamp = Stamp::Draft;
|
||||||
};
|
};
|
||||||
@ -994,7 +998,7 @@ public:
|
|||||||
const QPainterPath& getInkPath() const { return m_inkPath; }
|
const QPainterPath& getInkPath() const { return m_inkPath; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
QPainterPath m_inkPath;
|
QPainterPath m_inkPath;
|
||||||
};
|
};
|
||||||
@ -1012,7 +1016,7 @@ public:
|
|||||||
bool isOpened() const { return m_opened; }
|
bool isOpened() const { return m_opened; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
bool m_opened = false;
|
bool m_opened = false;
|
||||||
};
|
};
|
||||||
@ -1040,7 +1044,7 @@ public:
|
|||||||
FileAttachmentIcon getIcon() const { return m_icon; }
|
FileAttachmentIcon getIcon() const { return m_icon; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
PDFFileSpecification m_fileSpecification;
|
PDFFileSpecification m_fileSpecification;
|
||||||
FileAttachmentIcon m_icon = FileAttachmentIcon::PushPin;
|
FileAttachmentIcon m_icon = FileAttachmentIcon::PushPin;
|
||||||
@ -1066,7 +1070,7 @@ public:
|
|||||||
Icon getIcon() const { return m_icon; }
|
Icon getIcon() const { return m_icon; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
PDFSound m_sound;
|
PDFSound m_sound;
|
||||||
Icon m_icon = Icon::Speaker;
|
Icon m_icon = Icon::Speaker;
|
||||||
@ -1087,7 +1091,7 @@ public:
|
|||||||
const PDFMovieActivation& getMovieActivation() const { return m_movieActivation; }
|
const PDFMovieActivation& getMovieActivation() const { return m_movieActivation; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
QString m_movieTitle;
|
QString m_movieTitle;
|
||||||
bool m_playMovie = true;
|
bool m_playMovie = true;
|
||||||
@ -1110,7 +1114,7 @@ public:
|
|||||||
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
QString m_screenTitle;
|
QString m_screenTitle;
|
||||||
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
||||||
@ -1143,7 +1147,7 @@ public:
|
|||||||
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
const PDFAnnotationAdditionalActions& getAdditionalActions() const { return m_additionalActions; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
HighlightMode m_highlightMode = HighlightMode::Invert;
|
HighlightMode m_highlightMode = HighlightMode::Invert;
|
||||||
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
PDFAnnotationAppearanceCharacteristics m_appearanceCharacteristics;
|
||||||
@ -1185,7 +1189,7 @@ public:
|
|||||||
PDFReal getRelativeVerticalOffset() const { return m_relativeVerticalOffset; }
|
PDFReal getRelativeVerticalOffset() const { return m_relativeVerticalOffset; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
QMatrix m_matrix;
|
QMatrix m_matrix;
|
||||||
PDFReal m_relativeHorizontalOffset = 0.0;
|
PDFReal m_relativeHorizontalOffset = 0.0;
|
||||||
@ -1207,7 +1211,7 @@ public:
|
|||||||
QRectF getViewBox() const { return m_viewBox; }
|
QRectF getViewBox() const { return m_viewBox; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
PDF3DStream m_stream;
|
PDF3DStream m_stream;
|
||||||
std::optional<PDF3DView> m_defaultView;
|
std::optional<PDF3DView> m_defaultView;
|
||||||
@ -1231,7 +1235,7 @@ public:
|
|||||||
const PDFRichMediaSettings* getSettings() const { return &m_settings; }
|
const PDFRichMediaSettings* getSettings() const { return &m_settings; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObject object);
|
friend static PDFAnnotationPtr PDFAnnotation::parse(const PDFObjectStorage* storage, PDFObjectReference reference);
|
||||||
|
|
||||||
PDFRichMediaContent m_content;
|
PDFRichMediaContent m_content;
|
||||||
PDFRichMediaSettings m_settings;
|
PDFRichMediaSettings m_settings;
|
||||||
@ -1294,6 +1298,7 @@ protected:
|
|||||||
PDFAppeareanceStreams::Appearance appearance = PDFAppeareanceStreams::Appearance::Normal;
|
PDFAppeareanceStreams::Appearance appearance = PDFAppeareanceStreams::Appearance::Normal;
|
||||||
PDFAnnotationPtr annotation;
|
PDFAnnotationPtr annotation;
|
||||||
|
|
||||||
|
/// This mutable appearance stream is protected by main mutex
|
||||||
mutable PDFCachedItem<PDFObject> appearanceStream;
|
mutable PDFCachedItem<PDFObject> appearanceStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1301,6 +1306,19 @@ protected:
|
|||||||
{
|
{
|
||||||
bool isEmpty() const { return annotations.empty(); }
|
bool isEmpty() const { return annotations.empty(); }
|
||||||
|
|
||||||
|
/// Returns popup annotation for given annotation, if annotation doesn't have
|
||||||
|
/// popup annotation attached, then nullptr is returned.
|
||||||
|
/// \param pageAnnotation Page annotation
|
||||||
|
/// \returns Popup annotation or nullptr
|
||||||
|
const PageAnnotation* getPopupAnnotation(const PageAnnotation& pageAnnotation) const;
|
||||||
|
|
||||||
|
/// Returns a list of page annotations, which are replies to this page annotation.
|
||||||
|
/// If page annotation doesn't have any replies, then empty list is returned. Replies
|
||||||
|
/// are returned in order, in which they were created.
|
||||||
|
/// \param pageAnnotation Page annotation
|
||||||
|
/// \returns List of replies
|
||||||
|
std::vector<const PageAnnotation*> getReplies(const PageAnnotation& pageAnnotation) const;
|
||||||
|
|
||||||
std::vector<PageAnnotation> annotations;
|
std::vector<PageAnnotation> annotations;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1393,6 +1411,24 @@ public:
|
|||||||
private:
|
private:
|
||||||
void updateFromMouseEvent(QMouseEvent* event);
|
void updateFromMouseEvent(QMouseEvent* event);
|
||||||
|
|
||||||
|
/// Creates dialog for markup annotations. This function is used only for markup annotations,
|
||||||
|
/// do not use them for other annotations (function can crash).
|
||||||
|
/// \param widget Dialog's parent widget
|
||||||
|
/// \param pageAnnotation Markup annotation
|
||||||
|
/// \param pageAnnotations Page annotations
|
||||||
|
QDialog* createDialogForMarkupAnnotations(PDFWidget* widget,
|
||||||
|
const PageAnnotation& pageAnnotation,
|
||||||
|
const PageAnnotations& pageAnnotations);
|
||||||
|
|
||||||
|
/// Creates widgets for markup annotation main popup widget. Also sets
|
||||||
|
/// default size of parent widget.
|
||||||
|
/// \param parentWidget Parent widget, where widgets are created
|
||||||
|
/// \param pageAnnotation Markup annotation
|
||||||
|
/// \param pageAnnotations Page annotations
|
||||||
|
void createWidgetsForMarkupAnnotations(QWidget* parentWidget,
|
||||||
|
const PageAnnotation& pageAnnotation,
|
||||||
|
const PageAnnotations& pageAnnotations);
|
||||||
|
|
||||||
PDFDrawWidgetProxy* m_proxy;
|
PDFDrawWidgetProxy* m_proxy;
|
||||||
QString m_tooltip;
|
QString m_tooltip;
|
||||||
};
|
};
|
||||||
|
@ -736,7 +736,7 @@ std::array<PDFReal, 4> PDFDocumentBuilder::getAnnotationReductionRectangle(const
|
|||||||
|
|
||||||
void PDFDocumentBuilder::updateAnnotationAppearanceStreams(PDFObjectReference annotationReference)
|
void PDFDocumentBuilder::updateAnnotationAppearanceStreams(PDFObjectReference annotationReference)
|
||||||
{
|
{
|
||||||
PDFAnnotationPtr annotation = PDFAnnotation::parse(&m_storage, m_storage.getObject(annotationReference));
|
PDFAnnotationPtr annotation = PDFAnnotation::parse(&m_storage, annotationReference);
|
||||||
if (!annotation)
|
if (!annotation)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user