Signature plugin: Accept/reject mark

This commit is contained in:
Jakub Melka 2022-02-19 19:30:52 +01:00
parent b61fcff27d
commit f4e00f2f03
10 changed files with 308 additions and 22 deletions

View File

@ -15,7 +15,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
QT += gui widgets xml
QT += gui widgets xml svg
TARGET = Pdf4QtLib
TEMPLATE = lib

View File

@ -17,8 +17,10 @@
#include "pdfpagecontenteditortools.h"
#include "pdfpagecontentelements.h"
#include "pdfpainterutils.h"
#include <QPen>
#include <QPainter>
namespace pdf
{
@ -33,6 +35,32 @@ PDFCreatePCElementTool::PDFCreatePCElementTool(PDFDrawWidgetProxy* proxy,
}
QRectF PDFCreatePCElementTool::getRectangleFromPickTool(PDFPickTool* pickTool,
const QMatrix& pagePointToDevicePointMatrix)
{
const std::vector<QPointF>& points = pickTool->getPickedPoints();
if (points.empty())
{
return QRectF();
}
QPointF mousePoint = pagePointToDevicePointMatrix.inverted().map(pickTool->getSnappedPoint());
QPointF point = points.front();
qreal xMin = qMin(point.x(), mousePoint.x());
qreal xMax = qMax(point.x(), mousePoint.x());
qreal yMin = qMin(point.y(), mousePoint.y());
qreal yMax = qMax(point.y(), mousePoint.y());
qreal width = xMax - xMin;
qreal height = yMax - yMin;
if (!qFuzzyIsNull(width) && !qFuzzyIsNull(height))
{
return QRectF(xMin, yMin, width, height);
}
return QRectF();
}
PDFCreatePCElementRectangleTool::PDFCreatePCElementRectangleTool(PDFDrawWidgetProxy* proxy,
PDFPageContentScene* scene,
QAction* action,
@ -77,28 +105,14 @@ void PDFCreatePCElementRectangleTool::drawPage(QPainter* painter,
return;
}
const std::vector<QPointF>& points = m_pickTool->getPickedPoints();
if (points.empty())
QRectF rectangle = getRectangleFromPickTool(m_pickTool, pagePointToDevicePointMatrix);
if (!rectangle.isValid())
{
return;
}
m_element->setPageIndex(pageIndex);
QPointF mousePoint = pagePointToDevicePointMatrix.inverted().map(m_pickTool->getSnappedPoint());
QPointF point = points.front();
qreal xMin = qMin(point.x(), mousePoint.x());
qreal xMax = qMax(point.x(), mousePoint.x());
qreal yMin = qMin(point.y(), mousePoint.y());
qreal yMax = qMax(point.y(), mousePoint.y());
qreal width = xMax - xMin;
qreal height = yMax - yMin;
if (!qFuzzyIsNull(width) && !qFuzzyIsNull(height))
{
QRectF rect(xMin, yMin, width, height);
m_element->setRectangle(rect);
}
m_element->setRectangle(rectangle);
m_element->drawPage(painter, pageIndex, compiledPage, layoutGetter, pagePointToDevicePointMatrix, errors);
}
@ -221,4 +235,78 @@ void PDFCreatePCElementLineTool::onPointPicked(PDFInteger pageIndex, QPointF pag
setActive(false);
}
PDFCreatePCElementSvgTool::PDFCreatePCElementSvgTool(PDFDrawWidgetProxy* proxy,
PDFPageContentScene* scene,
QAction* action,
QByteArray content,
QObject* parent) :
BaseClass(proxy, scene, action, parent),
m_pickTool(nullptr),
m_element(nullptr)
{
m_pickTool = new PDFPickTool(proxy, PDFPickTool::Mode::Rectangles, this);
m_pickTool->setDrawSelectionRectangle(false);
addTool(m_pickTool);
connect(m_pickTool, &PDFPickTool::rectanglePicked, this, &PDFCreatePCElementSvgTool::onRectanglePicked);
m_element = new PDFPageContentSvgElement();
m_element->setContent(content);
updateActions();
}
PDFCreatePCElementSvgTool::~PDFCreatePCElementSvgTool()
{
delete m_element;
}
void PDFCreatePCElementSvgTool::drawPage(QPainter* painter,
PDFInteger pageIndex,
const PDFPrecompiledPage* compiledPage,
PDFTextLayoutGetter& layoutGetter,
const QMatrix& pagePointToDevicePointMatrix,
QList<PDFRenderError>& errors) const
{
BaseClass::drawPage(painter, pageIndex, compiledPage, layoutGetter, pagePointToDevicePointMatrix, errors);
if (pageIndex != m_pickTool->getPageIndex())
{
return;
}
QRectF rectangle = getRectangleFromPickTool(m_pickTool, pagePointToDevicePointMatrix);
if (!rectangle.isValid())
{
return;
}
m_element->setPageIndex(pageIndex);
m_element->setRectangle(rectangle);
{
PDFPainterStateGuard guard(painter);
painter->setWorldMatrix(pagePointToDevicePointMatrix, true);
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(Qt::DotLine);
painter->setBrush(Qt::NoBrush);
painter->drawRect(rectangle);
}
m_element->drawPage(painter, pageIndex, compiledPage, layoutGetter, pagePointToDevicePointMatrix, errors);
}
void PDFCreatePCElementSvgTool::onRectanglePicked(PDFInteger pageIndex, QRectF pageRectangle)
{
if (pageRectangle.isEmpty())
{
return;
}
m_element->setPageIndex(pageIndex);
m_element->setRectangle(pageRectangle);
m_scene->addElement(m_element->clone());
setActive(false);
}
} // namespace pdf

View File

@ -24,6 +24,7 @@ namespace pdf
{
class PDFPageContentScene;
class PDFPageContentSvgElement;
class PDFPageContentElementLine;
class PDFPageContentElementRectangle;
@ -36,6 +37,8 @@ public:
QObject* parent);
protected:
static QRectF getRectangleFromPickTool(PDFPickTool* pickTool, const QMatrix& pagePointToDevicePointMatrix);
PDFPageContentScene* m_scene;
};
@ -69,6 +72,36 @@ private:
PDFPageContentElementRectangle* m_element;
};
/// Tool that displays SVG image
class PDF4QTLIBSHARED_EXPORT PDFCreatePCElementSvgTool : public PDFCreatePCElementTool
{
Q_OBJECT
private:
using BaseClass = PDFCreatePCElementTool;
public:
explicit PDFCreatePCElementSvgTool(PDFDrawWidgetProxy* proxy,
PDFPageContentScene* scene,
QAction* action,
QByteArray content,
QObject* parent);
virtual ~PDFCreatePCElementSvgTool() override;
virtual void drawPage(QPainter* painter,
PDFInteger pageIndex,
const PDFPrecompiledPage* compiledPage,
PDFTextLayoutGetter& layoutGetter,
const QMatrix& pagePointToDevicePointMatrix,
QList<PDFRenderError>& errors) const override;
private:
void onRectanglePicked(pdf::PDFInteger pageIndex, QRectF pageRectangle);
PDFPickTool* m_pickTool;
PDFPageContentSvgElement* m_element;
};
/// Tool that creates line element.
class PDF4QTLIBSHARED_EXPORT PDFCreatePCElementLineTool : public PDFCreatePCElementTool
{

View File

@ -21,6 +21,7 @@
#include <QPainter>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QSvgRenderer>
namespace pdf
{
@ -293,4 +294,88 @@ void PDFPageContentElementLine::setLine(const QLineF& newLine)
}
}
PDFPageContentSvgElement::PDFPageContentSvgElement() :
m_renderer(std::make_unique<QSvgRenderer>())
{
}
PDFPageContentSvgElement::~PDFPageContentSvgElement()
{
}
PDFPageContentSvgElement* PDFPageContentSvgElement::clone() const
{
PDFPageContentSvgElement* copy = new PDFPageContentSvgElement();
copy->setPageIndex(getPageIndex());
copy->setRectangle(getRectangle());
copy->setContent(getContent());
return copy;
}
void PDFPageContentSvgElement::drawPage(QPainter* painter,
PDFInteger pageIndex,
const PDFPrecompiledPage* compiledPage,
PDFTextLayoutGetter& layoutGetter,
const QMatrix& pagePointToDevicePointMatrix,
QList<PDFRenderError>& errors) const
{
Q_UNUSED(compiledPage);
Q_UNUSED(layoutGetter);
Q_UNUSED(errors);
if (pageIndex != getPageIndex() || !getRectangle().isValid())
{
return;
}
PDFPainterStateGuard guard(painter);
painter->setWorldMatrix(pagePointToDevicePointMatrix, true);
painter->setRenderHint(QPainter::Antialiasing);
QRectF viewBox = m_renderer->viewBoxF();
if (!viewBox.isValid())
{
return;
}
QRectF renderBox = getRectangle();
QSizeF viewBoxSize = viewBox.size();
QSizeF renderBoxSize = viewBoxSize.scaled(renderBox.size(), Qt::KeepAspectRatio);
QRectF targetRenderBox = QRectF(QPointF(), renderBoxSize);
targetRenderBox.moveCenter(renderBox.center());
painter->translate(targetRenderBox.bottomLeft());
painter->scale(1.0, -1.0);
targetRenderBox.moveTopLeft(QPointF(0, 0));
m_renderer->render(painter, targetRenderBox);
}
const QByteArray& PDFPageContentSvgElement::getContent() const
{
return m_content;
}
void PDFPageContentSvgElement::setContent(const QByteArray& newContent)
{
if (m_content != newContent)
{
m_content = newContent;
m_renderer->load(m_content);
}
}
const QRectF& PDFPageContentSvgElement::getRectangle() const
{
return m_rectangle;
}
void PDFPageContentSvgElement::setRectangle(const QRectF& newRectangle)
{
m_rectangle = newRectangle;
}
} // namespace pdf

View File

@ -24,10 +24,12 @@
#include <QBrush>
#include <QCursor>
class QSvgRenderer;
namespace pdf
{
class PDFPageContentElement
class PDF4QTLIBSHARED_EXPORT PDFPageContentElement
{
public:
explicit PDFPageContentElement() = default;
@ -49,7 +51,7 @@ protected:
PDFInteger m_pageIndex = -1;
};
class PDFPageContentStyledElement : public PDFPageContentElement
class PDF4QTLIBSHARED_EXPORT PDFPageContentStyledElement : public PDFPageContentElement
{
public:
explicit PDFPageContentStyledElement() = default;
@ -66,7 +68,7 @@ protected:
QBrush m_brush;
};
class PDFPageContentElementRectangle : public PDFPageContentStyledElement
class PDF4QTLIBSHARED_EXPORT PDFPageContentElementRectangle : public PDFPageContentStyledElement
{
public:
virtual ~PDFPageContentElementRectangle() = default;
@ -91,7 +93,7 @@ private:
QRectF m_rectangle;
};
class PDFPageContentElementLine : public PDFPageContentStyledElement
class PDF4QTLIBSHARED_EXPORT PDFPageContentElementLine : public PDFPageContentStyledElement
{
public:
virtual ~PDFPageContentElementLine() = default;
@ -123,6 +125,33 @@ private:
QLineF m_line;
};
class PDF4QTLIBSHARED_EXPORT PDFPageContentSvgElement : public PDFPageContentElement
{
public:
PDFPageContentSvgElement();
virtual ~PDFPageContentSvgElement();
virtual PDFPageContentSvgElement* clone() const override;
virtual void drawPage(QPainter* painter,
PDFInteger pageIndex,
const PDFPrecompiledPage* compiledPage,
PDFTextLayoutGetter& layoutGetter,
const QMatrix& pagePointToDevicePointMatrix,
QList<PDFRenderError>& errors) const override;
const QByteArray& getContent() const;
void setContent(const QByteArray& newContent);
const QRectF& getRectangle() const;
void setRectangle(const QRectF& newRectangle);
private:
QRectF m_rectangle;
QByteArray m_content;
std::unique_ptr<QSvgRenderer> m_renderer;
};
class PDF4QTLIBSHARED_EXPORT PDFPageContentScene : public QObject,
public IDocumentDrawInterface,
public IDrawWidgetInputInterface

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Vrstva_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<circle fill="#21E900" cx="12" cy="12" r="11.098"/>
<g>
<path fill="#FFFFFF" d="M10.896,18.354c-0.24,0-0.474-0.087-0.658-0.247L6.28,14.649c-0.416-0.363-0.459-0.995-0.095-1.411
c0.363-0.414,0.996-0.458,1.411-0.095l3.042,2.656l5.56-9.652c0.274-0.478,0.887-0.643,1.365-0.368
c0.479,0.276,0.644,0.887,0.367,1.366l-6.167,10.707c-0.149,0.26-0.407,0.438-0.702,0.487
C11.005,18.349,10.95,18.354,10.896,18.354z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 889 B

View File

@ -1,4 +1,6 @@
<RCC>
<qresource prefix="/pdfplugins/signatureplugin">
<file>accept-mark.svg</file>
<file>reject-mark.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Vrstva_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<circle fill="#C80000" cx="12" cy="12" r="11.098"/>
<g>
<g>
<path fill="#FFFFFF" d="M13.713,12l5.063-4.201c0.46-0.381,0.524-1.07,0.143-1.539c-0.394-0.466-1.077-0.531-1.54-0.141
l-5.382,4.466L6.622,6.119C6.157,5.733,5.469,5.796,5.084,6.26C4.699,6.728,4.763,7.417,5.227,7.798L10.289,12l-5.062,4.204
c-0.464,0.389-0.528,1.074-0.143,1.54c0.216,0.258,0.527,0.394,0.84,0.394c0.246,0,0.491-0.079,0.697-0.253l5.377-4.462
l5.38,4.462c0.207,0.174,0.458,0.253,0.698,0.253c0.31,0,0.625-0.133,0.842-0.394c0.382-0.466,0.317-1.151-0.143-1.54L13.713,12z"
/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -103,6 +103,24 @@ void SignaturePlugin::setWidget(pdf::PDFWidget* widget)
m_actions[SignDigitally] = signDigitallyAction;
m_actions[Ceritificates] = certificatesAction;
QFile acceptMarkFile(":/pdfplugins/signatureplugin/accept-mark.svg");
QByteArray acceptMarkContent;
if (acceptMarkFile.open(QFile::ReadOnly))
{
acceptMarkContent = acceptMarkFile.readAll();
acceptMarkFile.close();
}
QFile rejectMarkFile(":/pdfplugins/signatureplugin/reject-mark.svg");
QByteArray rejectMarkContent;
if (rejectMarkFile.open(QFile::ReadOnly))
{
rejectMarkContent = rejectMarkFile.readAll();
rejectMarkFile.close();
}
m_tools[AcceptMarkTool] = new pdf::PDFCreatePCElementSvgTool(widget->getDrawWidgetProxy(), &m_scene, createAcceptMarkAction, acceptMarkContent, this);
m_tools[RejectMarkTool] = new pdf::PDFCreatePCElementSvgTool(widget->getDrawWidgetProxy(), &m_scene, createRejectMarkAction, rejectMarkContent, this);
m_tools[RectangleTool] = new pdf::PDFCreatePCElementRectangleTool(widget->getDrawWidgetProxy(), &m_scene, createRectangleAction, false, this);
m_tools[RoundedRectangleTool] = new pdf::PDFCreatePCElementRectangleTool(widget->getDrawWidgetProxy(), &m_scene, createRoundedRectangleAction, true, this);
m_tools[HorizontalLineTool] = new pdf::PDFCreatePCElementLineTool(widget->getDrawWidgetProxy(), &m_scene, createHorizontalLineAction, true, false, this);

View File

@ -74,6 +74,8 @@ private:
enum Tools
{
AcceptMarkTool,
RejectMarkTool,
RectangleTool,
RoundedRectangleTool,
HorizontalLineTool,