Merge remote-tracking branch 'remotes/origin/signdoc'
@@ -10,6 +10,6 @@ Pdf4QtPlugin {
|
||||
]
|
||||
Properties {
|
||||
condition: qbs.hostOS.contains("windows")
|
||||
cpp.defines: "DIMENTIONPLUGIN_LIBRARY"
|
||||
cpp.defines: "DIMENSIONPLUGIN_LIBRARY"
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ SUBDIRS += \
|
||||
RedactPlugin \
|
||||
OutputPreviewPlugin \
|
||||
ObjectInspectorPlugin \
|
||||
AudioBookPlugin
|
||||
AudioBookPlugin \
|
||||
SignaturePlugin
|
||||
|
||||
|
||||
|
7
Pdf4QtViewerPlugins/SignaturePlugin/SignaturePlugin.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"Name" : "Signature",
|
||||
"Author" : "Jakub Melka",
|
||||
"Version" : "1.0.0",
|
||||
"License" : "LGPL v3",
|
||||
"Description" : "Electronically or digitally sign PDF document."
|
||||
}
|
68
Pdf4QtViewerPlugins/SignaturePlugin/SignaturePlugin.pro
Normal file
@@ -0,0 +1,68 @@
|
||||
# Copyright (C) 2022 Jakub Melka
|
||||
#
|
||||
# This file is part of PDF4QT.
|
||||
#
|
||||
# PDF4QT is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# with the written consent of the copyright owner, any later version.
|
||||
#
|
||||
# PDF4QT is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
TEMPLATE = lib
|
||||
DEFINES += SIGNATUREPLUGIN_LIBRARY
|
||||
|
||||
QT += gui widgets
|
||||
|
||||
LIBS += -L$$OUT_PWD/../..
|
||||
|
||||
LIBS += -lPdf4QtLib
|
||||
|
||||
QMAKE_CXXFLAGS += /std:c++latest /utf-8
|
||||
|
||||
INCLUDEPATH += $$PWD/../../Pdf4QtLib/Sources
|
||||
|
||||
DESTDIR = $$OUT_PWD/../../pdfplugins
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
Pdf4Qt_OPENSSL_PATH = $$absolute_path(../../Tools, $$[QT_INSTALL_PREFIX])
|
||||
|
||||
# Link OpenSSL
|
||||
LIBS += -L$$Pdf4Qt_OPENSSL_PATH/OpenSSL/Win_x64/bin -L$$Pdf4Qt_OPENSSL_PATH/OpenSSL/Win_x64/lib -llibcrypto -llibssl
|
||||
INCLUDEPATH += $$Pdf4Qt_OPENSSL_PATH/OpenSSL/Win_x64/include
|
||||
DEPENDPATH += $$Pdf4Qt_OPENSSL_PATH/OpenSSL/Win_x64/include
|
||||
|
||||
SOURCES += \
|
||||
certificatemanager.cpp \
|
||||
certificatemanagerdialog.cpp \
|
||||
createcertificatedialog.cpp \
|
||||
signatureplugin.cpp \
|
||||
signdialog.cpp
|
||||
|
||||
HEADERS += \
|
||||
certificatemanager.h \
|
||||
certificatemanagerdialog.h \
|
||||
createcertificatedialog.h \
|
||||
signatureplugin.h \
|
||||
signdialog.h
|
||||
|
||||
CONFIG += force_debug_info
|
||||
|
||||
DISTFILES += \
|
||||
SignaturePlugin.json
|
||||
|
||||
RESOURCES += \
|
||||
icons.qrc
|
||||
|
||||
FORMS += \
|
||||
certificatemanagerdialog.ui \
|
||||
createcertificatedialog.ui \
|
||||
signdialog.ui
|
||||
|
15
Pdf4QtViewerPlugins/SignaturePlugin/SignaturePlugin.qbs
Normal file
@@ -0,0 +1,15 @@
|
||||
import qbs
|
||||
|
||||
Pdf4QtPlugin {
|
||||
name: "SignaturePlugin"
|
||||
files: [
|
||||
"*.h",
|
||||
"*.cpp",
|
||||
"*.ui",
|
||||
"icons.qrc",
|
||||
]
|
||||
Properties {
|
||||
condition: qbs.hostOS.contains("windows")
|
||||
cpp.defines: "SIGNATUREPLUGIN_LIBRARY"
|
||||
}
|
||||
}
|
13
Pdf4QtViewerPlugins/SignaturePlugin/accept-mark.svg
Normal 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 |
35
Pdf4QtViewerPlugins/SignaturePlugin/activate.svg
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M22.52,5.539c-0.157-0.208-0.406-0.292-0.655-0.239c-0.214,0.042-0.379,0.179-0.491,0.411
|
||||
c-0.093,0.199-0.189,0.396-0.286,0.594L21,6.484l-0.076-0.036l0.385-0.784c0.228-0.49,0.318-0.908,0.283-1.315
|
||||
c-0.098-1.286-0.982-2.325-2.247-2.646C19.099,1.643,18.85,1.611,18.6,1.611c-1.073,0-2.012,0.56-2.448,1.46
|
||||
c-2.148,4.415-4.288,8.831-6.421,13.249c-0.104,0.213-0.163,0.475-0.158,0.72c0.017,1.006,0.06,2.014,0.102,2.961
|
||||
c0.009,0.183,0.021,0.43,0.146,0.596c0.143,0.19,0.136,0.335-0.034,0.595c-0.023,0.038-0.041,0.081-0.062,0.13
|
||||
c-0.147,0.347-0.01,0.728,0.319,0.886c0.087,0.043,0.179,0.065,0.274,0.065c0.238,0,0.458-0.135,0.586-0.355
|
||||
c0.042-0.071,0.077-0.146,0.112-0.221c0.03-0.067,0.062-0.132,0.093-0.187c0.012-0.017,0.042-0.037,0.049-0.041
|
||||
c0.349-0.018,0.665-0.14,0.964-0.369c0.743-0.55,1.489-1.097,2.238-1.637c0.252-0.182,0.443-0.413,0.588-0.707
|
||||
c1.016-2.102,2.035-4.198,3.055-6.297c0.771-1.588,1.544-3.177,2.314-4.767c0.008-0.017,0.016-0.033,0.024-0.05
|
||||
c0.024,0.012,0.049,0.025,0.073,0.037l-2.31,4.762c-0.052,0.104-0.095,0.209-0.124,0.317c-0.086,0.35,0.112,0.688,0.463,0.782
|
||||
c0.063,0.018,0.123,0.026,0.183,0.026c0.182,0,0.441-0.083,0.637-0.477l2.249-4.64c0.224-0.458,0.446-0.915,0.67-1.373
|
||||
l0.401-0.827C22.709,6.001,22.686,5.755,22.52,5.539z M18.052,9.316c-0.135,0.285-0.27,0.563-0.401,0.838l-1.302,2.679
|
||||
c-0.826,1.701-1.652,3.403-2.476,5.104c-0.075,0.152-0.108,0.107-0.187,0.093c-1.024-0.164-1.89-0.596-2.646-1.32
|
||||
c-0.025-0.023-0.032-0.034-0.014-0.061c1.055-2.166,2.105-4.33,3.156-6.496l1.064-2.195C16.184,8.41,17.113,8.861,18.052,9.316z
|
||||
M18.562,2.766v0.169c0.666,0,1.169,0.278,1.497,0.825c0.266,0.446,0.273,0.889,0.022,1.395c-0.349,0.691-0.685,1.388-1.021,2.084
|
||||
l-0.405,0.841c-0.008,0.012-0.014,0.024-0.02,0.038l-2.804-1.358c0.071-0.151,0.143-0.298,0.212-0.442l0.466-0.963
|
||||
c0.253-0.521,0.506-1.042,0.756-1.563c0.271-0.564,0.704-0.852,1.281-0.858L18.562,2.766L18.562,2.766z M12.541,19.15l-0.27,0.198
|
||||
c-0.317,0.231-0.635,0.463-0.948,0.695c-0.119,0.086-0.185,0.105-0.25,0.071c-0.055-0.028-0.081-0.068-0.086-0.237
|
||||
c-0.012-0.349-0.025-0.693-0.039-1.053l-0.02-0.496C11.438,18.672,11.96,18.939,12.541,19.15z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M7.684,22.389c-1.105,0-1.947-0.215-2.457-0.847C4.544,20.695,4.598,19.261,5.4,16.89
|
||||
c0.505-1.492,0.518-2.515,0.035-2.955c-0.804-0.737-2.982-0.025-3.682,0.282l-0.418-0.951c0.339-0.147,3.359-1.42,4.801-0.098
|
||||
c0.82,0.751,0.903,2.116,0.247,4.055c-0.648,1.916-0.766,3.15-0.349,3.667c0.465,0.578,1.855,0.505,3.152,0.358l0.116,1.032
|
||||
C8.716,22.346,8.174,22.389,7.684,22.389z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.0 KiB |
250
Pdf4QtViewerPlugins/SignaturePlugin/certificatemanager.cpp
Normal file
@@ -0,0 +1,250 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "certificatemanager.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/rsaerr.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/pkcs12.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
CertificateManager::CertificateManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
using openssl_ptr = std::unique_ptr<T, void(*)(T*)>;
|
||||
|
||||
void CertificateManager::createCertificate(const NewCertificateInfo& info)
|
||||
{
|
||||
openssl_ptr<BIO> pksBuffer(BIO_new(BIO_s_mem()), &BIO_free_all);
|
||||
|
||||
if (pksBuffer)
|
||||
{
|
||||
openssl_ptr<BIGNUM> bignumber(BN_new(), &BN_free);
|
||||
openssl_ptr<RSA> rsaKey(RSA_new(), &RSA_free);
|
||||
|
||||
BN_set_word(bignumber.get(), RSA_F4);
|
||||
const int rsaResult = RSA_generate_key_ex(rsaKey.get(), info.rsaKeyLength, bignumber.get(), nullptr);
|
||||
if (rsaResult)
|
||||
{
|
||||
openssl_ptr<X509> certificate(X509_new(), &X509_free);
|
||||
openssl_ptr<EVP_PKEY> privateKey(EVP_PKEY_new(), &EVP_PKEY_free);
|
||||
|
||||
EVP_PKEY_set1_RSA(privateKey.get(), rsaKey.get());
|
||||
ASN1_INTEGER* serialNumber = X509_get_serialNumber(certificate.get());
|
||||
ASN1_INTEGER_set(serialNumber, info.serialNumber);
|
||||
|
||||
// Set validity of the certificate
|
||||
X509_gmtime_adj(X509_getm_notBefore(certificate.get()), 0);
|
||||
X509_gmtime_adj(X509_getm_notAfter(certificate.get()), info.validityInSeconds);
|
||||
|
||||
// Set name
|
||||
X509_NAME* name = X509_get_subject_name(certificate.get());
|
||||
|
||||
auto addString = [name](const char* identifier, QString string)
|
||||
{
|
||||
if (string.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray stringUtf8 = string.toUtf8();
|
||||
X509_NAME_add_entry_by_txt(name, identifier, MBSTRING_UTF8, reinterpret_cast<const unsigned char*>(stringUtf8.constData()), stringUtf8.length(), -1, 0);
|
||||
};
|
||||
addString("C", info.certCountryCode);
|
||||
addString("O", info.certOrganization);
|
||||
addString("OU", info.certOrganizationUnit);
|
||||
addString("CN", info.certCommonName);
|
||||
addString("E", info.certEmail);
|
||||
|
||||
X509_EXTENSION* extension = nullptr;
|
||||
X509V3_CTX context = { };
|
||||
X509V3_set_ctx_nodb(&context);
|
||||
X509V3_set_ctx(&context, certificate.get(), certificate.get(), nullptr, nullptr, 0);
|
||||
extension = X509V3_EXT_conf_nid (NULL, &context, NID_key_usage, "digitalSignature, keyAgreement");
|
||||
X509_add_ext(certificate.get(), extension, -1);
|
||||
X509_EXTENSION_free(extension);
|
||||
|
||||
X509_set_issuer_name(certificate.get(), name);
|
||||
|
||||
// Set public key
|
||||
X509_set_pubkey(certificate.get(), privateKey.get());
|
||||
X509_sign(certificate.get(), privateKey.get(), EVP_sha512());
|
||||
|
||||
// Private key password
|
||||
QByteArray privateKeyPaswordUtf8 = info.privateKeyPasword.toUtf8();
|
||||
|
||||
// Write the data
|
||||
openssl_ptr<PKCS12> pkcs12(PKCS12_create(privateKeyPaswordUtf8.constData(),
|
||||
nullptr,
|
||||
privateKey.get(),
|
||||
certificate.get(),
|
||||
nullptr,
|
||||
0,
|
||||
0,
|
||||
PKCS12_DEFAULT_ITER,
|
||||
PKCS12_DEFAULT_ITER,
|
||||
0), &PKCS12_free);
|
||||
i2d_PKCS12_bio(pksBuffer.get(), pkcs12.get());
|
||||
|
||||
BUF_MEM* pksMemoryBuffer = nullptr;
|
||||
BIO_get_mem_ptr(pksBuffer.get(), &pksMemoryBuffer);
|
||||
|
||||
if (!info.fileName.isEmpty())
|
||||
{
|
||||
QFile file(info.fileName);
|
||||
if (file.open(QFile::WriteOnly | QFile::Truncate))
|
||||
{
|
||||
file.write(pksMemoryBuffer->data, pksMemoryBuffer->length);
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QFileInfoList CertificateManager::getCertificates()
|
||||
{
|
||||
QDir directory(getCertificateDirectory());
|
||||
return directory.entryInfoList(QStringList() << "*.pfx", QDir::Files | QDir::NoDotAndDotDot | QDir::Readable, QDir::Name);
|
||||
}
|
||||
|
||||
QString CertificateManager::getCertificateDirectory()
|
||||
{
|
||||
QDir directory(QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).front() + "/certificates/");
|
||||
return directory.absolutePath();
|
||||
}
|
||||
|
||||
QString CertificateManager::generateCertificateFileName()
|
||||
{
|
||||
QString directoryString = getCertificateDirectory();
|
||||
QDir directory(directoryString);
|
||||
|
||||
int certificateIndex = 1;
|
||||
while (true)
|
||||
{
|
||||
QString fileName = directory.absoluteFilePath(QString("cert_%1.pfx").arg(certificateIndex++));
|
||||
if (!QFile::exists(fileName))
|
||||
{
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool CertificateManager::isCertificateValid(QString fileName, QString password)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (file.open(QFile::ReadOnly))
|
||||
{
|
||||
QByteArray data = file.readAll();
|
||||
file.close();
|
||||
|
||||
openssl_ptr<BIO> pksBuffer(BIO_new(BIO_s_mem()), &BIO_free_all);
|
||||
BIO_write(pksBuffer.get(), data.constData(), data.length());
|
||||
|
||||
openssl_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(pksBuffer.get(), nullptr), &PKCS12_free);
|
||||
if (pkcs12)
|
||||
{
|
||||
const char* passwordPointer = nullptr;
|
||||
QByteArray passwordByteArray = password.isEmpty() ? QByteArray() : password.toUtf8();
|
||||
if (!passwordByteArray.isEmpty())
|
||||
{
|
||||
passwordPointer = passwordByteArray.constData();
|
||||
}
|
||||
|
||||
return PKCS12_parse(pkcs12.get(), passwordPointer, nullptr, nullptr, nullptr) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SignatureFactory::sign(QString certificateName, QString password, QByteArray data, QByteArray& result)
|
||||
{
|
||||
QFile file(certificateName);
|
||||
if (file.open(QFile::ReadOnly))
|
||||
{
|
||||
QByteArray certificateData = file.readAll();
|
||||
file.close();
|
||||
|
||||
openssl_ptr<BIO> certificateBuffer(BIO_new(BIO_s_mem()), &BIO_free_all);
|
||||
BIO_write(certificateBuffer.get(), certificateData.constData(), certificateData.length());
|
||||
|
||||
openssl_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(certificateBuffer.get(), nullptr), &PKCS12_free);
|
||||
if (pkcs12)
|
||||
{
|
||||
const char* passwordPointer = nullptr;
|
||||
QByteArray passwordByteArray = password.isEmpty() ? QByteArray() : password.toUtf8();
|
||||
if (!passwordByteArray.isEmpty())
|
||||
{
|
||||
passwordPointer = passwordByteArray.constData();
|
||||
}
|
||||
|
||||
EVP_PKEY* key = nullptr;
|
||||
X509* certificate = nullptr;
|
||||
STACK_OF(X509)* certificates = nullptr;
|
||||
if (PKCS12_parse(pkcs12.get(), passwordPointer, &key, &certificate, &certificates) == 1)
|
||||
{
|
||||
openssl_ptr<BIO> signedDataBuffer(BIO_new(BIO_s_mem()), &BIO_free_all);
|
||||
BIO_write(signedDataBuffer.get(), data.constData(), data.length());
|
||||
|
||||
PKCS7* signature = PKCS7_sign(certificate, key, certificates, signedDataBuffer.get(), PKCS7_DETACHED | PKCS7_BINARY);
|
||||
if (signature)
|
||||
{
|
||||
openssl_ptr<BIO> outputBuffer(BIO_new(BIO_s_mem()), &BIO_free_all);
|
||||
i2d_PKCS7_bio(outputBuffer.get(), signature);
|
||||
|
||||
BUF_MEM* pksMemoryBuffer = nullptr;
|
||||
BIO_get_mem_ptr(outputBuffer.get(), &pksMemoryBuffer);
|
||||
|
||||
result = QByteArray(pksMemoryBuffer->data, int(pksMemoryBuffer->length));
|
||||
|
||||
EVP_PKEY_free(key);
|
||||
X509_free(certificate);
|
||||
sk_X509_free(certificates);
|
||||
return true;
|
||||
}
|
||||
|
||||
EVP_PKEY_free(key);
|
||||
X509_free(certificate);
|
||||
sk_X509_free(certificates);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace pdfplugin
|
64
Pdf4QtViewerPlugins/SignaturePlugin/certificatemanager.h
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CERTIFICATEMANAGER_H
|
||||
#define CERTIFICATEMANAGER_H
|
||||
|
||||
#include <QString>
|
||||
#include <QFileInfoList>
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
class CertificateManager
|
||||
{
|
||||
public:
|
||||
CertificateManager();
|
||||
|
||||
struct NewCertificateInfo
|
||||
{
|
||||
QString fileName;
|
||||
QString privateKeyPasword;
|
||||
|
||||
QString certCountryCode;
|
||||
QString certOrganization;
|
||||
QString certOrganizationUnit;
|
||||
QString certCommonName;
|
||||
QString certEmail;
|
||||
|
||||
int rsaKeyLength = 1024;
|
||||
int validityInSeconds = 2 * 365 * 24 * 3600;
|
||||
long serialNumber = 1;
|
||||
};
|
||||
|
||||
void createCertificate(const NewCertificateInfo& info);
|
||||
|
||||
static QFileInfoList getCertificates();
|
||||
static QString getCertificateDirectory();
|
||||
static QString generateCertificateFileName();
|
||||
static bool isCertificateValid(QString fileName, QString password);
|
||||
};
|
||||
|
||||
class SignatureFactory
|
||||
{
|
||||
public:
|
||||
static bool sign(QString certificateName, QString password, QByteArray data, QByteArray& result);
|
||||
};
|
||||
|
||||
} // namespace pdfplugin
|
||||
|
||||
#endif // CERTIFICATEMANAGER_H
|
133
Pdf4QtViewerPlugins/SignaturePlugin/certificatemanagerdialog.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "certificatemanagerdialog.h"
|
||||
#include "ui_certificatemanagerdialog.h"
|
||||
#include "createcertificatedialog.h"
|
||||
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QPushButton>
|
||||
#include <QFileSystemModel>
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
CertificateManagerDialog::CertificateManagerDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::CertificateManagerDialog),
|
||||
m_newCertificateButton(nullptr),
|
||||
m_openCertificateDirectoryButton(nullptr),
|
||||
m_deleteCertificateButton(nullptr),
|
||||
m_importCertificateButton(nullptr),
|
||||
m_certificateFileModel(nullptr)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QDir::root().mkpath(CertificateManager::getCertificateDirectory());
|
||||
|
||||
m_certificateFileModel = new QFileSystemModel(this);
|
||||
QModelIndex rootIndex = m_certificateFileModel->setRootPath(CertificateManager::getCertificateDirectory());
|
||||
ui->fileView->setModel(m_certificateFileModel);
|
||||
ui->fileView->setRootIndex(rootIndex);
|
||||
|
||||
m_newCertificateButton = ui->buttonBox->addButton(tr("Create"), QDialogButtonBox::ActionRole);
|
||||
m_openCertificateDirectoryButton = ui->buttonBox->addButton(tr("Open Directory"), QDialogButtonBox::ActionRole);
|
||||
m_deleteCertificateButton = ui->buttonBox->addButton(tr("Delete"), QDialogButtonBox::ActionRole);
|
||||
m_importCertificateButton = ui->buttonBox->addButton(tr("Import"), QDialogButtonBox::ActionRole);
|
||||
|
||||
connect(m_newCertificateButton, &QPushButton::clicked, this, &CertificateManagerDialog::onNewCertificateClicked);
|
||||
connect(m_openCertificateDirectoryButton, &QPushButton::clicked, this, &CertificateManagerDialog::onOpenCertificateDirectoryClicked);
|
||||
connect(m_deleteCertificateButton, &QPushButton::clicked, this, &CertificateManagerDialog::onDeleteCertificateClicked);
|
||||
connect(m_importCertificateButton, &QPushButton::clicked, this, &CertificateManagerDialog::onImportCertificateClicked);
|
||||
|
||||
setMinimumSize(pdf::PDFWidgetUtils::scaleDPI(this, QSize(640, 480)));
|
||||
}
|
||||
|
||||
CertificateManagerDialog::~CertificateManagerDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CertificateManagerDialog::onNewCertificateClicked()
|
||||
{
|
||||
CreateCertificateDialog dialog(this);
|
||||
if (dialog.exec() == CreateCertificateDialog::Accepted)
|
||||
{
|
||||
const CertificateManager::NewCertificateInfo info = dialog.getNewCertificateInfo();
|
||||
m_certificateManager.createCertificate(info);
|
||||
}
|
||||
}
|
||||
|
||||
void CertificateManagerDialog::onOpenCertificateDirectoryClicked()
|
||||
{
|
||||
QDesktopServices::openUrl(QString("file:///%1").arg(CertificateManager::getCertificateDirectory(), QUrl::TolerantMode));
|
||||
}
|
||||
|
||||
void CertificateManagerDialog::onDeleteCertificateClicked()
|
||||
{
|
||||
QFileInfo fileInfo = m_certificateFileModel->fileInfo(ui->fileView->currentIndex());
|
||||
if (fileInfo.exists())
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Confirm delete"), tr("Do you want to delete certificate '%1'?").arg(fileInfo.fileName()), QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes)
|
||||
{
|
||||
QFile file(fileInfo.filePath());
|
||||
if (!file.remove())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Cannot delete certificate '%1'").arg(fileInfo.fileName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CertificateManagerDialog::onImportCertificateClicked()
|
||||
{
|
||||
QString selectedFile = QFileDialog::getOpenFileName(this, tr("Import Certificate"), QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation), tr("Certificate file (*.pfx);;All files (*.*)"));
|
||||
|
||||
if (selectedFile.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(selectedFile);
|
||||
if (file.exists())
|
||||
{
|
||||
QString path = CertificateManager::getCertificateDirectory();
|
||||
QString targetFile = QString("%1/%2").arg(path, QFileInfo(file).fileName());
|
||||
if (QFile::exists(targetFile))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Target file exists. Please rename the certificate file to import."));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file.copy(targetFile))
|
||||
{
|
||||
QMessageBox::information(this, tr("Import Certificate"), tr("Certificate '%1' was successfully imported.").arg(file.fileName()));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, tr("Import Certificate"), tr("Error occured during certificate '%1' import.").arg(file.fileName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdfplugin
|
@@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CERTIFICATEMANAGERDIALOG_H
|
||||
#define CERTIFICATEMANAGERDIALOG_H
|
||||
|
||||
#include "certificatemanager.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QAction;
|
||||
class QFileSystemModel;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CertificateManagerDialog;
|
||||
}
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
class CertificateManagerDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CertificateManagerDialog(QWidget* parent);
|
||||
virtual ~CertificateManagerDialog() override;
|
||||
|
||||
private:
|
||||
void onNewCertificateClicked();
|
||||
void onOpenCertificateDirectoryClicked();
|
||||
void onDeleteCertificateClicked();
|
||||
void onImportCertificateClicked();
|
||||
|
||||
Ui::CertificateManagerDialog* ui;
|
||||
CertificateManager m_certificateManager;
|
||||
QPushButton* m_newCertificateButton;
|
||||
QPushButton* m_openCertificateDirectoryButton;
|
||||
QPushButton* m_deleteCertificateButton;
|
||||
QPushButton* m_importCertificateButton;
|
||||
QFileSystemModel* m_certificateFileModel;
|
||||
};
|
||||
|
||||
} // namespace pdfplugin
|
||||
|
||||
#endif // CERTIFICATEMANAGERDIALOG_H
|
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CertificateManagerDialog</class>
|
||||
<widget class="QDialog" name="CertificateManagerDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>789</width>
|
||||
<height>511</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Certificate Manager</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="certificateGroupBox">
|
||||
<property name="title">
|
||||
<string>Certificates</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QTreeView" name="fileView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>CertificateManagerDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>CertificateManagerDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
80
Pdf4QtViewerPlugins/SignaturePlugin/certificates.svg
Normal file
@@ -0,0 +1,80 @@
|
||||
<?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">
|
||||
<g>
|
||||
<path fill="#292D32" stroke="#292D32" stroke-width="0.2" stroke-miterlimit="10" d="M11.987,14.505
|
||||
c-2.647,0.009-4.82-2.152-4.828-4.801c-0.01-2.663,2.153-4.833,4.818-4.837c2.656-0.003,4.824,2.144,4.828,4.8
|
||||
C16.82,12.329,14.656,14.501,11.987,14.505z M11.958,13.266c1.961,0.02,3.586-1.575,3.61-3.538
|
||||
c0.023-1.964-1.566-3.599-3.525-3.622C10.048,6.084,8.42,7.665,8.396,9.641C8.374,11.625,9.969,13.245,11.958,13.266z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#292D32" stroke="#292D32" stroke-width="0.3" stroke-miterlimit="10" d="
|
||||
M11.287,10.553c0.721-0.681,1.413-1.333,2.104-1.987c0.166-0.156,0.33-0.314,0.498-0.468c0.189-0.174,0.41-0.183,0.561-0.027
|
||||
c0.154,0.158,0.137,0.374-0.057,0.556c-0.932,0.881-1.865,1.761-2.798,2.638c-0.21,0.198-0.409,0.193-0.612-0.013
|
||||
c-0.476-0.483-0.947-0.97-1.42-1.456c-0.114-0.118-0.2-0.259-0.12-0.413c0.052-0.1,0.161-0.193,0.266-0.234
|
||||
c0.155-0.061,0.281,0.042,0.389,0.153c0.357,0.368,0.715,0.735,1.071,1.104C11.208,10.446,11.24,10.494,11.287,10.553z"/>
|
||||
<g>
|
||||
<path fill="#292D32" d="M19.605,9.754c-0.025-0.07-0.025-0.168,0-0.247c0.203-0.596,0.377-1.082,0.547-1.53
|
||||
c0.059-0.156,0.033-0.271-0.094-0.396c-0.373-0.355-0.76-0.74-1.154-1.142c-0.055-0.055-0.098-0.137-0.105-0.201
|
||||
c-0.061-0.479-0.125-1.045-0.172-1.618c-0.014-0.186-0.094-0.285-0.275-0.341c-0.48-0.159-0.99-0.329-1.498-0.511
|
||||
c-0.084-0.031-0.174-0.104-0.223-0.179c-0.316-0.489-0.615-0.986-0.84-1.365C15.703,2.08,15.607,2.03,15.426,2.05
|
||||
c-0.547,0.076-1.096,0.138-1.66,0.202c-0.047,0.006-0.107-0.002-0.107-0.002c-0.52-0.337-1.043-0.679-1.563-1.02L12.07,1.213
|
||||
h-0.144L11.9,1.23c-0.095,0.063-0.192,0.125-0.289,0.187c-0.218,0.139-0.444,0.283-0.65,0.449
|
||||
c-0.426,0.35-0.866,0.451-1.398,0.315c-0.216-0.054-0.44-0.074-0.657-0.093C8.787,2.077,8.668,2.066,8.551,2.05
|
||||
c-0.189-0.027-0.276,0.073-0.33,0.161C7.979,2.619,7.688,3.1,7.379,3.575C7.321,3.662,7.218,3.743,7.123,3.778
|
||||
C6.622,3.967,6.108,4.138,5.627,4.294C5.459,4.349,5.388,4.442,5.371,4.625c-0.047,0.58-0.112,1.143-0.169,1.616
|
||||
C5.193,6.31,5.15,6.393,5.098,6.445c-0.34,0.347-0.719,0.722-1.158,1.148c-0.091,0.089-0.165,0.198-0.092,0.39
|
||||
c0.201,0.532,0.384,1.046,0.545,1.528c0.025,0.075,0.026,0.177,0,0.247c-0.167,0.499-0.349,1.007-0.541,1.511
|
||||
c-0.065,0.172-0.039,0.297,0.095,0.432c0.348,0.325,0.712,0.683,1.146,1.126c0.057,0.058,0.102,0.147,0.108,0.224
|
||||
c0.067,0.547,0.126,1.098,0.174,1.636c0.015,0.151,0.08,0.234,0.229,0.289c0.175,0.056,0.349,0.114,0.527,0.175
|
||||
c0.088,0.03,0.177,0.061,0.268,0.091l0.872,0.238l0.547,0.922l0.003,0.011c0.13,0.209,0.26,0.416,0.376,0.622
|
||||
c0.078,0.132,0.174,0.191,0.313,0.191c0.021,0,0.043-0.002,0.069-0.005c0.497-0.066,0.995-0.128,1.493-0.188l0.045-0.007
|
||||
c0.063-0.008,0.134-0.011,0.196-0.004l0.005-0.002l0.016,0.009c0.036,0.006,0.076,0.011,0.09,0.03c0.003,0.004-0.002-0.004,0,0
|
||||
l1.556,0.89c0,0-0.005,0.023-0.012,0.052c0.083,0.009,0.164-0.012,0.241-0.052l1.364-0.884c0.002-0.002,0-0.008,0.002-0.01
|
||||
c0.014-0.017,0.037-0.026,0.064-0.032v-0.001l0,0c0.027-0.006,0.057-0.007,0.076-0.007c0.025,0,0.053,0.001,0.082,0.005
|
||||
c0.24,0.022,0.482,0.054,0.725,0.084c0.141,0.017,0.279,0.034,0.418,0.051c0.061,0.006,0.125,0.019,0.188,0.031
|
||||
c0.178,0.034,0.367,0.054,0.494,0.003l1.182-2.006h0.961c0.188-0.069,0.363-0.135,0.547-0.182c0.254-0.065,0.305-0.23,0.32-0.402
|
||||
c0.039-0.53,0.102-1.061,0.166-1.557c0.006-0.073,0.051-0.161,0.107-0.22c0.355-0.366,0.725-0.73,1.131-1.111
|
||||
c0.146-0.138,0.178-0.273,0.104-0.468C19.967,10.791,19.793,10.304,19.605,9.754z M18.111,9.891
|
||||
c0.086,0.221,0.166,0.447,0.248,0.672c0.059,0.162,0.115,0.324,0.176,0.484c0.031,0.078,0.025,0.107-0.033,0.16
|
||||
c-0.281,0.266-0.58,0.56-0.914,0.9c-0.092,0.098-0.154,0.23-0.17,0.354c-0.059,0.406-0.105,0.836-0.139,1.277
|
||||
c-0.006,0.084-0.027,0.106-0.117,0.138c-0.396,0.13-0.807,0.265-1.211,0.418c-0.117,0.043-0.229,0.132-0.293,0.231
|
||||
c-0.258,0.392-0.475,0.743-0.664,1.073c-0.063,0.112-0.129,0.104-0.215,0.096c-0.443-0.064-0.846-0.114-1.232-0.152l-0.033-0.001
|
||||
c-0.109,0-0.236,0.033-0.352,0.095c-0.316,0.191-0.658,0.409-1.049,0.668c-0.049,0.032-0.083,0.047-0.112,0.047
|
||||
c-0.018,0-0.048-0.004-0.105-0.043c-0.328-0.222-0.682-0.446-1.076-0.685c-0.065-0.044-0.138-0.065-0.186-0.079
|
||||
c-0.013-0.004-0.023-0.007-0.031-0.011l-0.023-0.009l-0.438,0.054c-0.315,0.038-0.613,0.074-0.915,0.116
|
||||
c-0.097,0.016-0.161,0.021-0.231-0.098c-0.192-0.34-0.408-0.693-0.661-1.081c-0.059-0.091-0.159-0.17-0.278-0.22
|
||||
c-0.426-0.157-0.822-0.292-1.208-0.414c-0.096-0.033-0.122-0.054-0.128-0.153c-0.035-0.444-0.08-0.854-0.136-1.251
|
||||
c-0.017-0.132-0.088-0.272-0.195-0.386c-0.271-0.289-0.559-0.563-0.836-0.828l-0.061-0.058c-0.057-0.058-0.059-0.083-0.033-0.146
|
||||
l0.029-0.077c0.135-0.362,0.274-0.736,0.393-1.112C5.929,9.734,5.928,9.549,5.88,9.4C5.751,8.992,5.597,8.581,5.464,8.235
|
||||
C5.436,8.155,5.441,8.13,5.499,8.075C5.86,7.731,6.151,7.445,6.411,7.176c0.087-0.086,0.156-0.218,0.173-0.338
|
||||
c0.053-0.401,0.1-0.831,0.143-1.314C6.733,5.455,6.748,5.438,6.82,5.415C7.19,5.293,7.619,5.15,8.033,4.998
|
||||
c0.125-0.046,0.251-0.147,0.322-0.256c0.249-0.377,0.48-0.763,0.673-1.089c0.054-0.09,0.088-0.08,0.149-0.072
|
||||
c0.479,0.066,0.916,0.118,1.334,0.158c0.095,0.008,0.21-0.021,0.309-0.079c0.356-0.22,0.724-0.447,1.079-0.691
|
||||
c0.054-0.036,0.084-0.04,0.102-0.04c0.03,0,0.065,0.014,0.113,0.046c0.354,0.236,0.717,0.467,1.08,0.688
|
||||
c0.074,0.048,0.184,0.076,0.291,0.076l0.041-0.001c0.486-0.051,0.916-0.102,1.309-0.156c0.055-0.007,0.086-0.021,0.133,0.061
|
||||
c0.207,0.353,0.434,0.729,0.68,1.09c0.074,0.113,0.203,0.215,0.336,0.267c0.211,0.079,0.422,0.15,0.631,0.221
|
||||
c0.191,0.065,0.383,0.13,0.572,0.2c0.031,0.011,0.078,0.069,0.08,0.099c0.033,0.233,0.057,0.466,0.082,0.698
|
||||
c0.023,0.211,0.045,0.421,0.072,0.628c0.012,0.11,0.076,0.236,0.162,0.321c0.311,0.32,0.623,0.628,0.928,0.915
|
||||
c0.055,0.053,0.059,0.073,0.031,0.141C18.475,8.4,18.41,8.58,18.346,8.759c-0.078,0.216-0.156,0.432-0.236,0.643
|
||||
C18.045,9.564,18.047,9.719,18.111,9.891z"/>
|
||||
</g>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#292D32" d="M14.105,22.69c0.283,0,0.5-0.146,0.641-0.435
|
||||
c0.209-0.434,0.42-0.868,0.629-1.303l0.426-0.881c0.031-0.064,0.064-0.127,0.1-0.196l0.084-0.159l0.078,0.021
|
||||
c0.701,0.196,1.398,0.388,2.094,0.579l0.17,0.047c0.051,0.015,0.104,0.029,0.156,0.045c0.074,0.022,0.15,0.045,0.225,0.063
|
||||
c0.084,0.021,0.164,0.03,0.238,0.03c0.205,0,0.369-0.077,0.504-0.235c0.191-0.222,0.223-0.478,0.098-0.76
|
||||
c-0.275-0.615-0.553-1.229-0.832-1.844c-0.133-0.296-0.285-0.62-0.441-0.955c-0.301-0.65-0.613-1.322-0.859-1.908l-1.152,0.738
|
||||
l0.547,1.245c0.264,0.584,0.527,1.17,0.799,1.773l0.084,0.187l-0.199-0.049c-0.041-0.01-0.074-0.017-0.102-0.022
|
||||
c-0.033-0.008-0.061-0.014-0.086-0.021l-1.369-0.376c-0.527-0.146-0.777-0.032-1.018,0.466l-0.49,1.01
|
||||
c-0.063,0.13-0.125,0.26-0.213,0.438l-0.094,0.19l-1.525-3.376l-0.826,0.324l-0.825-0.324l-1.527,3.376l-0.093-0.19
|
||||
c-0.087-0.178-0.15-0.308-0.213-0.438l-0.49-1.009c-0.24-0.498-0.492-0.61-1.017-0.466l-1.371,0.377
|
||||
c-0.024,0.007-0.05,0.013-0.085,0.021c-0.027,0.006-0.06,0.013-0.101,0.022l-0.199,0.049l0.084-0.187
|
||||
c0.271-0.604,0.535-1.189,0.8-1.774l0.655-1.438l-1.362-0.281c-0.224,0.534-0.477,1.064-0.722,1.578
|
||||
c-0.162,0.34-0.324,0.68-0.479,1.021c-0.278,0.615-0.556,1.229-0.831,1.844c-0.126,0.282-0.094,0.538,0.096,0.759
|
||||
c0.185,0.217,0.429,0.285,0.742,0.206c0.076-0.019,0.151-0.041,0.227-0.063c0.052-0.016,0.104-0.03,0.156-0.045l0.17-0.047
|
||||
c0.695-0.191,1.392-0.383,2.093-0.579l0.078-0.021l0.083,0.159c0.036,0.069,0.069,0.133,0.1,0.197l0.425,0.88
|
||||
c0.21,0.435,0.419,0.869,0.63,1.303c0.141,0.288,0.356,0.435,0.641,0.435c0.299-0.006,0.511-0.154,0.647-0.441
|
||||
c0.023-0.048,0.044-0.094,0.065-0.14l1.623-3.59l1.623,3.59c0.021,0.046,0.043,0.092,0.064,0.139
|
||||
c0.137,0.288,0.35,0.437,0.631,0.442l0.018,0.098l0,0V22.69z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.0 KiB |
51
Pdf4QtViewerPlugins/SignaturePlugin/clear.svg
Normal file
@@ -0,0 +1,51 @@
|
||||
<?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">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M22.52,5.539c-0.156-0.208-0.406-0.292-0.654-0.239c-0.215,0.042-0.379,0.179-0.491,0.411
|
||||
c-0.093,0.199-0.188,0.396-0.286,0.594L21,6.484l-0.076-0.036l0.385-0.784c0.229-0.49,0.318-0.908,0.283-1.315
|
||||
c-0.098-1.286-0.982-2.325-2.246-2.646C19.1,1.643,18.85,1.611,18.6,1.611c-1.072,0-2.012,0.56-2.447,1.46
|
||||
c-2.148,4.415-4.289,8.831-6.421,13.25c-0.104,0.213-0.163,0.475-0.158,0.72c0.017,1.006,0.06,2.015,0.102,2.961
|
||||
c0.009,0.183,0.021,0.431,0.146,0.597c0.143,0.189,0.136,0.334-0.034,0.594c-0.023,0.039-0.041,0.082-0.062,0.131
|
||||
c-0.147,0.347-0.01,0.728,0.319,0.886c0.087,0.043,0.179,0.065,0.274,0.065c0.238,0,0.458-0.135,0.586-0.355
|
||||
c0.042-0.07,0.077-0.146,0.112-0.221c0.03-0.067,0.062-0.133,0.093-0.188c0.012-0.017,0.042-0.037,0.049-0.041
|
||||
c0.349-0.018,0.665-0.14,0.964-0.369c0.743-0.55,1.489-1.097,2.237-1.637c0.252-0.182,0.443-0.413,0.589-0.707
|
||||
c1.016-2.102,2.034-4.197,3.055-6.297c0.771-1.588,1.544-3.177,2.313-4.767c0.009-0.017,0.017-0.033,0.024-0.05
|
||||
c0.024,0.012,0.05,0.025,0.073,0.037l-2.311,4.762c-0.051,0.104-0.095,0.209-0.123,0.317c-0.086,0.35,0.111,0.688,0.463,0.782
|
||||
c0.063,0.019,0.123,0.026,0.183,0.026c0.183,0,0.44-0.084,0.638-0.478l2.248-4.64c0.225-0.458,0.446-0.915,0.67-1.373l0.401-0.827
|
||||
C22.709,6.001,22.686,5.755,22.52,5.539z M18.052,9.316c-0.135,0.285-0.27,0.563-0.401,0.838l-1.301,2.679
|
||||
c-0.826,1.701-1.652,3.403-2.477,5.104c-0.075,0.151-0.107,0.106-0.188,0.092c-1.023-0.163-1.89-0.596-2.646-1.319
|
||||
c-0.025-0.022-0.032-0.034-0.014-0.062c1.055-2.166,2.105-4.33,3.156-6.496l1.064-2.195C16.184,8.41,17.113,8.861,18.052,9.316z
|
||||
M18.563,2.766v0.169c0.666,0,1.168,0.278,1.496,0.825c0.267,0.446,0.273,0.889,0.022,1.395c-0.349,0.691-0.685,1.388-1.021,2.084
|
||||
L18.654,8.08c-0.008,0.012-0.014,0.024-0.02,0.038L15.831,6.76c0.071-0.151,0.144-0.298,0.212-0.442l0.466-0.963
|
||||
c0.253-0.521,0.507-1.042,0.757-1.563c0.271-0.564,0.703-0.852,1.28-0.858L18.563,2.766L18.563,2.766z M12.541,19.15l-0.27,0.197
|
||||
c-0.317,0.231-0.635,0.463-0.948,0.695c-0.119,0.086-0.185,0.105-0.25,0.07c-0.055-0.027-0.081-0.067-0.086-0.236
|
||||
c-0.012-0.35-0.025-0.693-0.039-1.053l-0.02-0.496C11.438,18.672,11.96,18.939,12.541,19.15z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M7.684,22.389c-1.105,0-1.947-0.215-2.457-0.847c-0.683-0.847-0.629-2.28,0.173-4.651
|
||||
c0.505-1.492,0.518-2.516,0.035-2.955c-0.804-0.738-2.982-0.025-3.682,0.281l-0.418-0.951c0.339-0.146,3.359-1.419,4.801-0.098
|
||||
c0.82,0.751,0.903,2.116,0.247,4.055c-0.648,1.916-0.766,3.15-0.349,3.668c0.465,0.578,1.855,0.504,3.152,0.357l0.116,1.031
|
||||
C8.716,22.346,8.174,22.389,7.684,22.389z"/>
|
||||
</g>
|
||||
</g>
|
||||
<circle fill="#F12D32" cx="8.572" cy="5.808" r="4.197"/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M6.366,7.536c0-0.004,0-0.009,0-0.013C6.367,7.508,6.375,7.502,6.377,7.49
|
||||
c0.006-0.127,0.07-0.231,0.157-0.32c0.438-0.433,0.866-0.871,1.301-1.302c0.066-0.063,0.066-0.049,0-0.115
|
||||
C7.401,5.316,6.969,4.88,6.531,4.446C6.457,4.373,6.402,4.285,6.384,4.18c-0.006-0.028-0.012-0.051-0.018-0.08
|
||||
c0-0.004,0-0.011,0-0.016C6.37,4.071,6.377,4.057,6.377,4.042c0.019-0.201,0.161-0.374,0.365-0.419
|
||||
c0.033-0.008,0.07-0.015,0.106-0.022c0.005,0,0.008,0,0.008,0C6.867,3.604,6.878,3.61,6.886,3.61
|
||||
c0.141,0.005,0.249,0.076,0.344,0.174c0.435,0.437,0.874,0.873,1.312,1.31c0.027,0.026,0.048,0.032,0.073,0
|
||||
c0.006-0.009,0.015-0.02,0.027-0.027C9.076,4.63,9.51,4.199,9.945,3.765c0.072-0.076,0.159-0.125,0.259-0.147
|
||||
c0.032-0.004,0.059-0.011,0.091-0.016h0.005c0.018,0.002,0.036,0.009,0.049,0.009c0.237,0.017,0.442,0.261,0.429,0.495
|
||||
c-0.013,0.14-0.069,0.251-0.164,0.345c-0.44,0.438-0.88,0.875-1.315,1.315c-0.042,0.042-0.042,0.042,0,0.086
|
||||
c0.435,0.437,0.871,0.868,1.306,1.307c0.019,0.013,0.034,0.035,0.051,0.048c0.227,0.247,0.136,0.652-0.177,0.768
|
||||
c-0.2,0.076-0.38,0.035-0.531-0.116C9.51,7.421,9.064,6.976,8.629,6.539c-0.048-0.05-0.048-0.05-0.096,0
|
||||
c-0.444,0.44-0.887,0.888-1.329,1.328C7.068,8,6.907,8.042,6.727,7.992c-0.184-0.05-0.293-0.178-0.339-0.365
|
||||
C6.375,7.595,6.372,7.565,6.366,7.536z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.3 KiB |
16
Pdf4QtViewerPlugins/SignaturePlugin/create-dot.svg
Normal 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">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M4.679,14.168c0-2.972,2.008-5.06,4.817-5.06c2.811,0,4.735,2.088,4.735,5.06
|
||||
c0,2.889-1.848,5.057-4.815,5.057C6.604,19.225,4.679,17.057,4.679,14.168z"/>
|
||||
</g>
|
||||
<path fill="#292D32" d="M12.926,7.973c0,0.318,0.227,0.577,0.506,0.577h5.382c0.277,0,0.507-0.259,0.507-0.577l0,0
|
||||
c0-0.318-0.229-0.576-0.507-0.576h-5.382C13.152,7.396,12.926,7.655,12.926,7.973L12.926,7.973z"/>
|
||||
<path fill="#292D32" d="M16.121,11.169c0.317,0,0.576-0.228,0.576-0.508V5.283c0-0.279-0.259-0.508-0.576-0.508l0,0
|
||||
c-0.315,0-0.574,0.229-0.574,0.508v5.38C15.547,10.943,15.806,11.169,16.121,11.169L16.121,11.169z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,14 @@
|
||||
<?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">
|
||||
<g>
|
||||
<path fill="none" stroke="#292D32" stroke-width="1.5" stroke-miterlimit="10" d="M2.219,16.916c0,0,1.829-5.375,9.253-3.27
|
||||
c7.8,2.213,8.95,1.967,10.308-0.605"/>
|
||||
<path fill="#292D32" d="M14.854,9.8c0,0.271,0.192,0.49,0.429,0.49h4.568c0.236,0,0.431-0.22,0.431-0.49l0,0
|
||||
c0-0.27-0.193-0.489-0.431-0.489h-4.568C15.047,9.311,14.854,9.53,14.854,9.8L14.854,9.8z"/>
|
||||
<path fill="#292D32" d="M17.567,12.516c0.27,0,0.489-0.196,0.489-0.433V7.517c0-0.237-0.22-0.432-0.489-0.432l0,0
|
||||
c-0.269,0-0.488,0.194-0.488,0.432v4.565C17.079,12.322,17.299,12.516,17.567,12.516L17.567,12.516z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,19 @@
|
||||
<?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">
|
||||
<g>
|
||||
<g>
|
||||
<circle fill="#292D32" cx="3.012" cy="14.734" r="1.631"/>
|
||||
<path fill="#292D32" d="M22.55,14.455c-0.039-0.09-0.091-0.176-0.163-0.242l-2.266-2.265c-0.294-0.297-0.771-0.297-1.064,0
|
||||
c-0.293,0.292-0.293,0.767,0,1.062l0.948,0.938h-7.672H5.83v1.584h14.18l-0.938,0.939c-0.295,0.293-0.295,0.771,0,1.057
|
||||
c0.144,0.15,0.337,0.221,0.527,0.221c0.194,0,0.38-0.07,0.528-0.221l2.263-2.27c0.074-0.061,0.134-0.143,0.164-0.236
|
||||
c0.049-0.082,0.065-0.184,0.065-0.285C22.604,14.645,22.586,14.543,22.55,14.455z"/>
|
||||
</g>
|
||||
<path fill="#292D32" d="M13.716,9.075c0,0.281,0.2,0.51,0.445,0.51h4.749c0.246,0,0.448-0.229,0.448-0.51l0,0
|
||||
c0-0.28-0.201-0.509-0.448-0.509h-4.749C13.916,8.566,13.716,8.794,13.716,9.075L13.716,9.075z"/>
|
||||
<path fill="#292D32" d="M16.536,6.252c-0.279,0-0.508,0.202-0.508,0.449v4.746c0,0.25,0.229,0.451,0.508,0.451l0,0
|
||||
c0.28,0,0.509-0.203,0.509-0.45V6.701C17.045,6.455,16.816,6.252,16.536,6.252"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
16
Pdf4QtViewerPlugins/SignaturePlugin/create-line.svg
Normal 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">
|
||||
<g>
|
||||
|
||||
<rect x="3.138" y="12.585" transform="matrix(-0.7801 0.6256 -0.6256 -0.7801 29.7118 16.3621)" fill="#292D32" width="17.685" height="1.633"/>
|
||||
<path fill="#292D32" d="M14.923,5.652h-1.865V3.788c0-0.247-0.229-0.449-0.511-0.449c-0.279,0-0.508,0.202-0.508,0.449v1.864
|
||||
h-1.867C9.928,5.653,9.727,5.881,9.727,6.161c0,0.281,0.201,0.51,0.445,0.51h1.867v1.862c0,0.25,0.229,0.451,0.508,0.451
|
||||
c0.282,0,0.511-0.203,0.511-0.449V6.671h1.865c0.246,0,0.447-0.229,0.447-0.51C15.37,5.881,15.169,5.652,14.923,5.652z"/>
|
||||
<path fill="#292D32" d="M3.815,20.035c0.579,0.721,1.634,0.836,2.356,0.256c0.723-0.58,0.839-1.633,0.261-2.354
|
||||
c-0.58-0.725-1.635-0.842-2.358-0.262C3.352,18.256,3.236,19.313,3.815,20.035z"/>
|
||||
<circle fill="#292D32" cx="18.878" cy="7.87" r="1.677"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
28
Pdf4QtViewerPlugins/SignaturePlugin/create-no-mark.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?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">
|
||||
<g>
|
||||
<circle fill="#F12D32" cx="10.482" cy="13.178" r="7.749"/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M6.412,16.367c0-0.009,0-0.015,0-0.023c0.002-0.028,0.013-0.04,0.02-0.062
|
||||
c0.01-0.233,0.13-0.426,0.289-0.586c0.81-0.802,1.6-1.61,2.403-2.405c0.122-0.117,0.122-0.09,0-0.211
|
||||
c-0.803-0.808-1.602-1.614-2.411-2.411c-0.132-0.142-0.234-0.306-0.269-0.494c-0.01-0.053-0.019-0.096-0.032-0.147
|
||||
c0-0.008,0-0.021,0-0.028c0.006-0.027,0.02-0.049,0.02-0.078c0.033-0.371,0.298-0.688,0.671-0.778
|
||||
c0.065-0.012,0.131-0.024,0.201-0.037c0.004,0,0.01,0,0.01,0c0.021,0.002,0.038,0.017,0.055,0.017
|
||||
C7.63,9.131,7.826,9.262,8.002,9.443c0.803,0.807,1.612,1.614,2.419,2.416c0.049,0.051,0.09,0.062,0.137,0
|
||||
c0.01-0.017,0.027-0.037,0.048-0.047c0.803-0.803,1.603-1.604,2.41-2.402c0.131-0.143,0.293-0.233,0.477-0.274
|
||||
c0.06-0.008,0.113-0.021,0.169-0.031h0.008c0.034,0.002,0.067,0.019,0.096,0.019c0.435,0.032,0.814,0.479,0.79,0.913
|
||||
c-0.027,0.258-0.127,0.465-0.305,0.641c-0.813,0.804-1.626,1.615-2.427,2.418c-0.082,0.082-0.082,0.082,0,0.164
|
||||
c0.801,0.805,1.605,1.604,2.409,2.412c0.032,0.024,0.064,0.066,0.094,0.091c0.417,0.454,0.25,1.204-0.326,1.421
|
||||
c-0.368,0.137-0.702,0.057-0.976-0.217c-0.815-0.812-1.637-1.626-2.439-2.443c-0.088-0.086-0.088-0.086-0.176,0
|
||||
c-0.82,0.817-1.638,1.645-2.454,2.455c-0.251,0.244-0.548,0.323-0.883,0.231c-0.335-0.092-0.539-0.329-0.623-0.675
|
||||
C6.428,16.475,6.425,16.422,6.412,16.367z"/>
|
||||
</g>
|
||||
<path fill="#292D32" d="M15.623,5.896c0,0.281,0.2,0.51,0.445,0.51h4.749c0.246,0,0.448-0.229,0.448-0.51l0,0
|
||||
c0-0.28-0.201-0.509-0.448-0.509h-4.749C15.823,5.388,15.623,5.616,15.623,5.896L15.623,5.896z"/>
|
||||
<path fill="#292D32" d="M18.443,3.074c-0.279,0-0.508,0.202-0.508,0.449v4.746c0,0.25,0.229,0.451,0.508,0.451l0,0
|
||||
c0.28,0,0.509-0.203,0.509-0.45V3.523C18.952,3.276,18.724,3.074,18.443,3.074"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
14
Pdf4QtViewerPlugins/SignaturePlugin/create-rectangle.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<?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">
|
||||
<g>
|
||||
|
||||
<rect x="3.069" y="8.156" fill="none" stroke="#292D32" stroke-width="1.4" stroke-miterlimit="10" width="12.628" height="12.629"/>
|
||||
<path fill="#292D32" d="M15.287,6.038c0,0.281,0.2,0.51,0.445,0.51h4.749c0.246,0,0.448-0.229,0.448-0.51l0,0
|
||||
c0-0.279-0.201-0.508-0.448-0.508h-4.749C15.487,5.53,15.287,5.758,15.287,6.038L15.287,6.038z"/>
|
||||
<path fill="#292D32" d="M18.107,3.215c-0.279,0-0.508,0.203-0.508,0.449v4.746c0,0.25,0.229,0.451,0.508,0.451l0,0
|
||||
c0.28,0,0.509-0.203,0.509-0.45V3.665C18.616,3.418,18.388,3.215,18.107,3.215"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1014 B |
@@ -0,0 +1,14 @@
|
||||
<?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">
|
||||
<g>
|
||||
<path fill="none" stroke="#292D32" stroke-width="1.4" stroke-miterlimit="10" d="M5.069,8.156h8.628c1.104,0,2,0.896,2,2v8.629
|
||||
c0,1.104-0.896,2-2,2H5.069c-1.104,0-2-0.896-2-2v-8.629C3.069,9.051,3.965,8.156,5.069,8.156z"/>
|
||||
<path fill="#292D32" d="M15.287,6.038c0,0.281,0.2,0.51,0.445,0.51h4.749c0.246,0,0.448-0.229,0.448-0.51l0,0
|
||||
c0-0.279-0.201-0.508-0.448-0.508h-4.749C15.487,5.53,15.287,5.758,15.287,6.038L15.287,6.038z"/>
|
||||
<path fill="#292D32" d="M18.107,3.215c-0.279,0-0.508,0.203-0.508,0.449v4.746c0,0.25,0.229,0.451,0.508,0.451l0,0
|
||||
c0.28,0,0.509-0.203,0.509-0.45V3.665C18.616,3.418,18.388,3.215,18.107,3.215"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
23
Pdf4QtViewerPlugins/SignaturePlugin/create-svg-image.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<?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">
|
||||
<g>
|
||||
<path fill="none" stroke="#292D32" stroke-width="1.4" stroke-miterlimit="10" d="M5.069,8.156h8.628c1.104,0,2,0.896,2,2v8.629
|
||||
c0,1.104-0.896,2-2,2H5.069c-1.104,0-2-0.896-2-2v-8.629C3.069,9.051,3.965,8.156,5.069,8.156z"/>
|
||||
<path fill="#292D32" d="M15.287,6.038c0,0.281,0.199,0.51,0.445,0.51h4.748c0.246,0,0.449-0.229,0.449-0.51l0,0
|
||||
c0-0.279-0.201-0.508-0.449-0.508h-4.748C15.486,5.53,15.287,5.758,15.287,6.038L15.287,6.038z"/>
|
||||
<path fill="#292D32" d="M18.107,3.215c-0.279,0-0.508,0.203-0.508,0.449V8.41c0,0.25,0.229,0.451,0.508,0.451l0,0
|
||||
c0.279,0,0.509-0.203,0.509-0.45V3.665C18.616,3.418,18.389,3.215,18.107,3.215"/>
|
||||
</g>
|
||||
<path fill="#292D32" d="M13.564,12.111c0.007,1.156-0.962,2.128-2.12,2.13c-1.174,0-2.135-0.961-2.135-2.13
|
||||
c0-1.165,0.947-2.117,2.12-2.128C12.591,9.969,13.559,10.933,13.564,12.111z M11.429,13.078c0.525,0.007,0.974-0.435,0.975-0.963
|
||||
c0.002-0.53-0.437-0.972-0.969-0.972c-0.52,0-0.955,0.43-0.965,0.955C10.458,12.627,10.894,13.072,11.429,13.078z"/>
|
||||
<path fill="#292D32" d="M15.411,17.156c-0.478-0.384-0.938-0.75-1.396-1.104c-0.638-0.505-1.34-0.527-1.999-0.055
|
||||
c-0.583,0.417-1.176,0.846-1.758,1.273c-0.252,0.176-0.407,0.165-0.627-0.044c-0.57-0.582-1.141-1.153-1.713-1.724
|
||||
c-0.681-0.681-1.526-0.715-2.263-0.088c-0.935,0.79-1.867,1.57-2.802,2.361c-0.011,0.011-0.021,0.022-0.044,0.032v1.594
|
||||
c0.056-0.109,0.154-0.221,0.275-0.319c1.121-0.912,2.23-1.856,3.351-2.789c0.252-0.221,0.428-0.21,0.658,0.033
|
||||
c0.572,0.581,1.143,1.164,1.713,1.746c0.649,0.659,1.461,0.715,2.197,0.153c0.55-0.428,1.099-0.856,1.66-1.285
|
||||
c0.23-0.187,0.384-0.187,0.614,0c0.704,0.56,1.417,1.132,2.109,1.702c0.01,0.007,0.015,0.02,0.023,0.027V17.156z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
23
Pdf4QtViewerPlugins/SignaturePlugin/create-text.svg
Normal file
@@ -0,0 +1,23 @@
|
||||
<?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">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M6.694,16.22h-3.22l-0.465,1.132H1.275l2.947-7.224h1.734l2.949,7.224H7.157L6.694,16.22z M6.155,14.905
|
||||
l-1.072-2.64l-1.072,2.64H6.155z"/>
|
||||
<path fill="#292D32" d="M15.564,14.633c0,1.666-1.047,2.851-2.5,2.851c-0.763,0-1.388-0.327-1.82-0.897v0.766H9.706v-7.349h1.539
|
||||
v2.672c0.432-0.557,1.057-0.881,1.82-0.881C14.518,11.794,15.564,12.968,15.564,14.633z M14.072,14.633
|
||||
c0-0.905-0.598-1.545-1.453-1.545c-0.748,0-1.292,0.546-1.375,1.331v0.425c0.083,0.794,0.626,1.347,1.375,1.347
|
||||
C13.475,16.188,14.072,15.545,14.072,14.633z"/>
|
||||
<path fill="#292D32" d="M16.34,14.633c0-1.545,1.367-2.839,2.98-2.839c0.879,0,1.605,0.354,2.133,0.921l-1.021,0.875
|
||||
c-0.273-0.307-0.705-0.505-1.125-0.505c-0.799,0-1.48,0.708-1.48,1.536c0,0.851,0.682,1.568,1.494,1.568
|
||||
c0.422,0,0.859-0.208,1.146-0.53l1.02,0.86c-0.539,0.592-1.271,0.961-2.178,0.961C17.697,17.483,16.34,16.169,16.34,14.633z"/>
|
||||
</g>
|
||||
<path fill="#292D32" d="M18.639,8.562c0,0.203,0.145,0.369,0.322,0.369h3.438c0.18,0,0.326-0.166,0.326-0.369l0,0
|
||||
c0-0.202-0.146-0.368-0.326-0.368h-3.438C18.783,8.193,18.639,8.359,18.639,8.562L18.639,8.562z"/>
|
||||
<path fill="#292D32" d="M20.682,6.518c-0.203,0-0.369,0.146-0.369,0.325v3.436c0,0.183,0.166,0.328,0.369,0.328l0,0
|
||||
c0.201,0,0.367-0.147,0.367-0.326V6.843C21.049,6.664,20.885,6.518,20.682,6.518"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
19
Pdf4QtViewerPlugins/SignaturePlugin/create-vertical-line.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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">
|
||||
<g>
|
||||
<g>
|
||||
<circle fill="#292D32" cx="8.556" cy="20.988" r="1.631"/>
|
||||
<path fill="#292D32" d="M8.277,1.45c-0.09,0.038-0.176,0.091-0.242,0.163L5.77,3.879c-0.297,0.294-0.297,0.771,0,1.064
|
||||
c0.292,0.293,0.767,0.293,1.062,0l0.938-0.948v7.672v6.503h1.584V3.99l0.939,0.938c0.293,0.295,0.772,0.295,1.057,0
|
||||
c0.15-0.144,0.222-0.337,0.222-0.527c0-0.193-0.069-0.379-0.222-0.527L9.08,1.609C9.019,1.536,8.937,1.477,8.843,1.445
|
||||
C8.761,1.396,8.66,1.381,8.558,1.381C8.466,1.396,8.365,1.414,8.277,1.45z"/>
|
||||
</g>
|
||||
<path fill="#292D32" d="M12.793,4.273c0,0.281,0.2,0.51,0.445,0.51h4.749c0.246,0,0.447-0.229,0.447-0.51l0,0
|
||||
c0-0.28-0.2-0.509-0.447-0.509h-4.749C12.993,3.764,12.793,3.992,12.793,4.273L12.793,4.273z"/>
|
||||
<path fill="#292D32" d="M15.613,1.45c-0.279,0-0.509,0.202-0.509,0.449v4.746c0,0.25,0.229,0.451,0.509,0.451l0,0
|
||||
c0.28,0,0.509-0.203,0.509-0.45V1.899C16.122,1.653,15.894,1.45,15.613,1.45"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
21
Pdf4QtViewerPlugins/SignaturePlugin/create-yes-mark.svg
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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="#57B400" cx="10.453" cy="13.176" r="7.736"/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M15.982,10.202c-0.053,0.27-0.221,0.466-0.413,0.657c-1.996,1.992-3.996,3.988-5.987,5.976
|
||||
c-0.271,0.276-0.585,0.392-0.961,0.259c-0.131-0.047-0.262-0.134-0.364-0.235c-1.016-1.004-2.024-2.022-3.038-3.034
|
||||
c-0.152-0.15-0.243-0.329-0.291-0.535c0-0.074,0-0.147,0-0.22c0.049-0.203,0.127-0.39,0.287-0.536
|
||||
c0.378-0.332,0.881-0.307,1.255,0.068c0.783,0.776,1.562,1.557,2.346,2.342c0.026,0.03,0.05,0.06,0.089,0.121
|
||||
c0.047-0.057,0.063-0.091,0.094-0.116c1.812-1.81,3.625-3.625,5.441-5.445c0.262-0.262,0.568-0.376,0.931-0.262
|
||||
c0.32,0.104,0.507,0.323,0.591,0.648c0.008,0.026,0.016,0.047,0.022,0.065C15.982,10.043,15.982,10.121,15.982,10.202z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M15.623,5.896c0,0.281,0.2,0.51,0.445,0.51h4.748c0.246,0,0.449-0.229,0.449-0.51l0,0
|
||||
c0-0.28-0.201-0.509-0.449-0.509h-4.748C15.823,5.388,15.623,5.616,15.623,5.896L15.623,5.896z"/>
|
||||
<path fill="#292D32" d="M18.443,3.074c-0.279,0-0.508,0.202-0.508,0.449v4.746c0,0.25,0.229,0.451,0.508,0.451l0,0
|
||||
c0.279,0,0.509-0.203,0.509-0.45V3.523C18.952,3.276,18.725,3.074,18.443,3.074"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
162
Pdf4QtViewerPlugins/SignaturePlugin/createcertificatedialog.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "createcertificatedialog.h"
|
||||
#include "ui_createcertificatedialog.h"
|
||||
|
||||
#include "certificatemanager.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QDate>
|
||||
#include <QCalendar>
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
CreateCertificateDialog::CreateCertificateDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::CreateCertificateDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->fileNameEdit->setReadOnly(true);
|
||||
ui->fileNameEdit->setText(CertificateManager::generateCertificateFileName());
|
||||
|
||||
ui->keyLengthCombo->addItem(tr("1024 bits"), 1024);
|
||||
ui->keyLengthCombo->addItem(tr("2048 bits"), 2048);
|
||||
ui->keyLengthCombo->addItem(tr("4096 bits"), 4096);
|
||||
ui->keyLengthCombo->setCurrentIndex(ui->keyLengthCombo->findData(2048));
|
||||
|
||||
QList<QLocale> locales = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
|
||||
std::sort(locales.begin(), locales.end(), [](const QLocale& left, const QLocale& right) { return QString::compare(left.nativeCountryName(), right.nativeCountryName(), Qt::CaseInsensitive) < 0; });
|
||||
|
||||
int currentIndex = 0;
|
||||
QLocale currentLocale = QLocale::system();
|
||||
|
||||
for (const QLocale& locale : locales)
|
||||
{
|
||||
if (locale.country() == QLocale::AnyCountry)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (locale.nativeCountryName().isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QString localeName = locale.name();
|
||||
QString countryCode = localeName.split(QChar('_')).back();
|
||||
QString text = QString("%1 | %2").arg(countryCode, locale.nativeCountryName());
|
||||
|
||||
if (ui->countryCombo->findText(text) >= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (locale.bcp47Name() == currentLocale.bcp47Name())
|
||||
{
|
||||
currentIndex = ui->countryCombo->count();
|
||||
}
|
||||
|
||||
ui->countryCombo->addItem(text, countryCode);
|
||||
}
|
||||
|
||||
ui->countryCombo->setCurrentIndex(currentIndex);
|
||||
ui->countryCombo->setMaxVisibleItems(25);
|
||||
|
||||
QDate minDate = QDate::currentDate();
|
||||
ui->validTillEdit->setMinimumDate(minDate);
|
||||
|
||||
QDate selectedDate = minDate;
|
||||
selectedDate = selectedDate.addYears(5, ui->validTillEdit->calendar());
|
||||
ui->validTillEdit->setSelectedDate(selectedDate);
|
||||
}
|
||||
|
||||
CreateCertificateDialog::~CreateCertificateDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CreateCertificateDialog::accept()
|
||||
{
|
||||
if (validate())
|
||||
{
|
||||
bool ok = false;
|
||||
QString password1 = QInputDialog::getText(this, tr("Certificate Protection"), tr("Enter password to protect your certificate."), QLineEdit::Password, QString(), &ok);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QString password2 = QInputDialog::getText(this, tr("Certificate Protection"), tr("Enter password again to verify password text."), QLineEdit::Password, QString(), &ok);
|
||||
|
||||
if (password1 != password2)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Reentered password is not equal to the first one!"));
|
||||
return;
|
||||
}
|
||||
|
||||
QDate date = ui->validTillEdit->selectedDate();
|
||||
QDate currentDate = QDate::currentDate();
|
||||
int days = currentDate.daysTo(date);
|
||||
|
||||
// Fill certificate info
|
||||
m_newCertificateInfo.fileName = ui->fileNameEdit->text();
|
||||
m_newCertificateInfo.privateKeyPasword = password1;
|
||||
m_newCertificateInfo.certCountryCode = ui->countryCombo->currentData().toString();
|
||||
m_newCertificateInfo.certOrganization = ui->organizationEdit->text();
|
||||
m_newCertificateInfo.certOrganizationUnit = ui->organizationUnitEdit->text();
|
||||
m_newCertificateInfo.certCommonName = ui->commonNameEdit->text();
|
||||
m_newCertificateInfo.certEmail = ui->emailEdit->text();
|
||||
m_newCertificateInfo.rsaKeyLength = ui->keyLengthCombo->currentData().toInt();
|
||||
m_newCertificateInfo.validityInSeconds = days * 24 * 3600;
|
||||
|
||||
BaseClass::accept();
|
||||
}
|
||||
}
|
||||
|
||||
bool CreateCertificateDialog::validate()
|
||||
{
|
||||
// validate empty text fields
|
||||
if (ui->commonNameEdit->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Please enter a name!"));
|
||||
ui->commonNameEdit->setFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ui->organizationEdit->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Please enter an organization name!"));
|
||||
ui->organizationEdit->setFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ui->emailEdit->text().isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Please enter an email address!"));
|
||||
ui->emailEdit->setFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace plugin
|
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef CREATECERTIFICATEDIALOG_H
|
||||
#define CREATECERTIFICATEDIALOG_H
|
||||
|
||||
#include "certificatemanager.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CreateCertificateDialog;
|
||||
}
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
class CreateCertificateDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
using BaseClass = QDialog;
|
||||
|
||||
public:
|
||||
explicit CreateCertificateDialog(QWidget* parent);
|
||||
virtual ~CreateCertificateDialog() override;
|
||||
|
||||
const CertificateManager::NewCertificateInfo& getNewCertificateInfo() const { return m_newCertificateInfo; }
|
||||
|
||||
public slots:
|
||||
virtual void accept() override;
|
||||
|
||||
private:
|
||||
bool validate();
|
||||
|
||||
CertificateManager::NewCertificateInfo m_newCertificateInfo;
|
||||
|
||||
Ui::CreateCertificateDialog* ui;
|
||||
};
|
||||
|
||||
} // namespace plugin
|
||||
|
||||
#endif // CREATECERTIFICATEDIALOG_H
|
182
Pdf4QtViewerPlugins/SignaturePlugin/createcertificatedialog.ui
Normal file
@@ -0,0 +1,182 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CreateCertificateDialog</class>
|
||||
<widget class="QDialog" name="CreateCertificateDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>514</width>
|
||||
<height>488</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Create Certificate</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="certificateGroupBox">
|
||||
<property name="title">
|
||||
<string>Create Self Signed Certificate</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="commonNameEdit">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="organizationLabel">
|
||||
<property name="text">
|
||||
<string>Organization</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="organizationUnitLabel">
|
||||
<property name="text">
|
||||
<string>Organization Unit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="emailLabel">
|
||||
<property name="text">
|
||||
<string>Email</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="organizationEdit">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="organizationUnitEdit">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="emailEdit">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="countryLabel">
|
||||
<property name="text">
|
||||
<string>Country</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="keyLengthLabel">
|
||||
<property name="text">
|
||||
<string>Key length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="validityLabel">
|
||||
<property name="text">
|
||||
<string>Valid till</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCalendarWidget" name="validTillEdit"/>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="keyLengthCombo"/>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="countryCombo"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="fileNameEdit"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="certificateFileLabel">
|
||||
<property name="text">
|
||||
<string>Certificate file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>CreateCertificateDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>CreateCertificateDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
22
Pdf4QtViewerPlugins/SignaturePlugin/icons.qrc
Normal file
@@ -0,0 +1,22 @@
|
||||
<RCC>
|
||||
<qresource prefix="/pdfplugins/signatureplugin">
|
||||
<file>accept-mark.svg</file>
|
||||
<file>reject-mark.svg</file>
|
||||
<file>activate.svg</file>
|
||||
<file>certificates.svg</file>
|
||||
<file>clear.svg</file>
|
||||
<file>create-dot.svg</file>
|
||||
<file>create-freehand-curve.svg</file>
|
||||
<file>create-horizontal-line.svg</file>
|
||||
<file>create-line.svg</file>
|
||||
<file>create-no-mark.svg</file>
|
||||
<file>create-rectangle.svg</file>
|
||||
<file>create-rounded-rectangle.svg</file>
|
||||
<file>create-svg-image.svg</file>
|
||||
<file>create-text.svg</file>
|
||||
<file>create-vertical-line.svg</file>
|
||||
<file>create-yes-mark.svg</file>
|
||||
<file>sign-digitally.svg</file>
|
||||
<file>sign-electronically.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
16
Pdf4QtViewerPlugins/SignaturePlugin/reject-mark.svg
Normal 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 |
109
Pdf4QtViewerPlugins/SignaturePlugin/sign-digitally.svg
Normal file
@@ -0,0 +1,109 @@
|
||||
<?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">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M22.52,5.539c-0.156-0.208-0.406-0.292-0.653-0.239c-0.216,0.042-0.38,0.179-0.491,0.411
|
||||
c-0.093,0.199-0.188,0.396-0.286,0.594L21,6.484l-0.076-0.036l0.385-0.784c0.229-0.49,0.318-0.908,0.283-1.315
|
||||
c-0.098-1.286-0.982-2.325-2.246-2.646C19.1,1.643,18.85,1.611,18.6,1.611c-1.072,0-2.012,0.56-2.447,1.46
|
||||
c-2.147,4.415-4.289,8.831-6.42,13.25c-0.104,0.214-0.163,0.476-0.158,0.721c0.017,1.006,0.06,2.016,0.102,2.961
|
||||
c0.009,0.184,0.021,0.432,0.146,0.598c0.143,0.188,0.136,0.334-0.034,0.594c-0.023,0.039-0.041,0.082-0.062,0.131
|
||||
c-0.147,0.347-0.01,0.729,0.319,0.886c0.087,0.043,0.179,0.065,0.274,0.065c0.238,0,0.458-0.135,0.586-0.355
|
||||
c0.042-0.07,0.077-0.146,0.112-0.221c0.03-0.067,0.062-0.133,0.093-0.188c0.012-0.018,0.042-0.037,0.049-0.041
|
||||
c0.349-0.019,0.665-0.141,0.964-0.369c0.743-0.551,1.488-1.098,2.236-1.638c0.252-0.183,0.443-0.413,0.59-0.707
|
||||
c1.016-2.103,2.033-4.196,3.055-6.297c0.771-1.588,1.544-3.177,2.313-4.767c0.01-0.017,0.018-0.033,0.024-0.05
|
||||
c0.024,0.012,0.05,0.025,0.073,0.037l-2.311,4.762c-0.052,0.104-0.096,0.208-0.123,0.317c-0.086,0.351,0.11,0.688,0.463,0.782
|
||||
c0.063,0.02,0.123,0.025,0.183,0.025c0.183,0,0.44-0.084,0.638-0.478l2.248-4.64c0.225-0.458,0.446-0.915,0.67-1.373l0.401-0.827
|
||||
C22.709,6.001,22.686,5.755,22.52,5.539z M18.052,9.316c-0.135,0.285-0.27,0.563-0.401,0.838l-1.301,2.679
|
||||
c-0.826,1.701-1.651,3.403-2.477,5.104c-0.075,0.15-0.107,0.105-0.188,0.092c-1.023-0.163-1.891-0.596-2.646-1.319
|
||||
c-0.025-0.022-0.032-0.034-0.014-0.062c1.055-2.166,2.105-4.331,3.157-6.497l1.063-2.195C16.184,8.41,17.113,8.861,18.052,9.316z
|
||||
M18.563,2.935L18.563,2.935c0.666,0,1.168,0.278,1.496,0.825c0.268,0.446,0.273,0.889,0.022,1.395
|
||||
c-0.349,0.691-0.685,1.388-1.021,2.084L18.654,8.08c-0.008,0.012-0.014,0.024-0.021,0.038L15.831,6.76
|
||||
c0.071-0.151,0.144-0.298,0.212-0.442l0.466-0.963c0.253-0.521,0.507-1.042,0.757-1.563c0.271-0.564,0.703-0.852,1.28-0.858
|
||||
L18.563,2.935L18.563,2.935z M12.541,19.15l-0.27,0.197c-0.317,0.23-0.635,0.463-0.948,0.694c-0.119,0.086-0.185,0.104-0.25,0.069
|
||||
c-0.055-0.026-0.081-0.066-0.086-0.235c-0.012-0.351-0.025-0.692-0.039-1.054l-0.02-0.495
|
||||
C11.438,18.672,11.96,18.939,12.541,19.15z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M7.684,22.389c-1.105,0-1.947-0.215-2.457-0.847c-0.683-0.847-0.629-2.28,0.173-4.651
|
||||
c0.505-1.492,0.518-2.516,0.035-2.955c-0.804-0.738-2.982-0.024-3.682,0.281l-0.418-0.951c0.339-0.146,3.359-1.418,4.801-0.098
|
||||
c0.82,0.751,0.903,2.116,0.247,4.055c-0.648,1.916-0.766,3.15-0.349,3.668c0.465,0.578,1.855,0.504,3.152,0.357l0.116,1.031
|
||||
C8.716,22.346,8.174,22.389,7.684,22.389z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#292D32" stroke="#292D32" stroke-width="0.2" stroke-miterlimit="10" d="M8.341,8.233
|
||||
C7.022,8.237,5.939,7.161,5.936,5.841c-0.005-1.327,1.072-2.408,2.4-2.41C9.659,3.43,10.739,4.5,10.741,5.823
|
||||
C10.749,7.149,9.671,8.231,8.341,8.233z M8.327,7.615c0.977,0.011,1.786-0.784,1.798-1.762c0.011-0.978-0.78-1.793-1.756-1.804
|
||||
C7.375,4.038,6.564,4.825,6.552,5.81C6.541,6.798,7.335,7.605,8.327,7.615z"/>
|
||||
<path fill="#292D32" stroke="#292D32" stroke-width="0.3" stroke-miterlimit="10" d="M7.992,6.264
|
||||
C8.351,5.925,8.696,5.6,9.04,5.274c0.083-0.078,0.165-0.156,0.249-0.233c0.095-0.087,0.204-0.091,0.28-0.013
|
||||
c0.076,0.079,0.068,0.186-0.029,0.277C9.075,5.744,8.61,6.182,8.146,6.619C8.041,6.718,7.942,6.715,7.84,6.612
|
||||
c-0.236-0.24-0.472-0.483-0.707-0.726c-0.057-0.059-0.1-0.128-0.06-0.206C7.1,5.631,7.154,5.585,7.206,5.564
|
||||
c0.077-0.03,0.14,0.021,0.194,0.077C7.578,5.824,7.756,6.007,7.933,6.19C7.953,6.21,7.969,6.235,7.992,6.264z"/>
|
||||
<g>
|
||||
<path fill="#292D32" d="M12.136,5.866c-0.012-0.034-0.012-0.083,0-0.123c0.102-0.296,0.188-0.539,0.272-0.762
|
||||
c0.03-0.078,0.017-0.135-0.047-0.198c-0.185-0.176-0.379-0.368-0.575-0.569c-0.027-0.027-0.049-0.068-0.052-0.1
|
||||
c-0.03-0.239-0.063-0.521-0.086-0.806c-0.007-0.093-0.046-0.143-0.137-0.17c-0.239-0.079-0.494-0.164-0.747-0.254
|
||||
c-0.041-0.016-0.086-0.052-0.111-0.09c-0.157-0.243-0.307-0.491-0.418-0.68c-0.043-0.072-0.091-0.097-0.182-0.087
|
||||
C9.782,2.065,9.508,2.096,9.227,2.128C9.204,2.131,9.174,2.127,9.174,2.127C8.915,1.959,8.654,1.789,8.396,1.62L8.382,1.611H8.311
|
||||
L8.297,1.62C8.25,1.65,8.202,1.681,8.154,1.712C8.045,1.782,7.933,1.854,7.83,1.936C7.618,2.11,7.398,2.161,7.133,2.094
|
||||
C7.025,2.066,6.914,2.056,6.806,2.047C6.747,2.042,6.688,2.036,6.629,2.028c-0.094-0.014-0.137,0.037-0.164,0.08
|
||||
c-0.121,0.204-0.266,0.443-0.42,0.68c-0.029,0.043-0.08,0.083-0.127,0.101c-0.25,0.094-0.506,0.18-0.746,0.257
|
||||
C5.089,3.173,5.053,3.22,5.044,3.311C5.021,3.6,4.989,3.88,4.96,4.116C4.956,4.15,4.935,4.192,4.909,4.217
|
||||
C4.739,4.391,4.551,4.577,4.332,4.79C4.287,4.834,4.25,4.888,4.286,4.984c0.1,0.265,0.191,0.521,0.271,0.761
|
||||
c0.012,0.038,0.013,0.088,0,0.123C4.475,6.117,4.383,6.37,4.288,6.621C4.256,6.707,4.269,6.769,4.335,6.836
|
||||
c0.174,0.162,0.355,0.34,0.571,0.562C4.935,7.426,4.957,7.471,4.96,7.509c0.033,0.272,0.063,0.547,0.087,0.815
|
||||
c0.008,0.075,0.04,0.116,0.114,0.144c0.087,0.027,0.174,0.057,0.262,0.087C5.467,8.57,5.512,8.585,5.557,8.601l0.434,0.119
|
||||
l0.273,0.459l0.001,0.005c0.065,0.104,0.129,0.208,0.188,0.31C6.492,9.559,6.54,9.589,6.609,9.589c0.01,0,0.021,0,0.034-0.003
|
||||
c0.248-0.033,0.496-0.063,0.744-0.093l0.022-0.004C7.44,9.485,7.476,9.484,7.507,9.487l0.002-0.001l0.008,0.005
|
||||
c0.018,0.003,0.038,0.005,0.045,0.015c0.001,0.002-0.001-0.002,0,0l0.775,0.444c0,0-0.002,0.012-0.006,0.025
|
||||
c0.041,0.005,0.082-0.006,0.12-0.025l0.68-0.441c0.001-0.001,0-0.004,0.001-0.005C9.139,9.495,9.15,9.491,9.164,9.488V9.487l0,0
|
||||
c0.013-0.003,0.028-0.003,0.038-0.003c0.013,0,0.026,0,0.041,0.002c0.119,0.011,0.241,0.027,0.361,0.042
|
||||
c0.07,0.008,0.139,0.017,0.208,0.025c0.03,0.003,0.062,0.009,0.094,0.015c0.089,0.018,0.183,0.027,0.246,0.002l0.589-1h0.479
|
||||
c0.093-0.035,0.18-0.067,0.272-0.091c0.126-0.033,0.152-0.114,0.159-0.2c0.019-0.265,0.051-0.528,0.083-0.776
|
||||
c0.003-0.036,0.025-0.08,0.053-0.109c0.177-0.183,0.362-0.364,0.564-0.553c0.072-0.069,0.088-0.137,0.052-0.233
|
||||
C12.316,6.383,12.229,6.141,12.136,5.866z M11.392,5.934c0.043,0.11,0.083,0.223,0.124,0.334c0.029,0.081,0.058,0.162,0.087,0.242
|
||||
c0.016,0.039,0.013,0.054-0.016,0.08c-0.14,0.132-0.29,0.279-0.456,0.448c-0.046,0.049-0.077,0.115-0.084,0.177
|
||||
c-0.029,0.203-0.052,0.417-0.069,0.636c-0.003,0.042-0.014,0.052-0.058,0.069c-0.198,0.064-0.402,0.131-0.604,0.208
|
||||
c-0.059,0.021-0.114,0.066-0.146,0.115c-0.128,0.195-0.236,0.37-0.331,0.534C9.808,8.833,9.775,8.83,9.732,8.825
|
||||
C9.511,8.793,9.311,8.769,9.118,8.75l-0.017,0c-0.054,0-0.118,0.016-0.175,0.048C8.769,8.892,8.598,9,8.404,9.13
|
||||
C8.379,9.145,8.362,9.153,8.348,9.153c-0.009,0-0.023-0.002-0.052-0.021C8.132,9.021,7.956,8.909,7.759,8.79
|
||||
C7.728,8.768,7.691,8.758,7.667,8.75C7.66,8.749,7.655,8.748,7.652,8.745L7.64,8.741L7.422,8.768
|
||||
C7.265,8.787,7.117,8.805,6.966,8.825c-0.048,0.008-0.08,0.01-0.115-0.048c-0.096-0.17-0.203-0.346-0.33-0.538
|
||||
c-0.029-0.046-0.079-0.085-0.138-0.11C6.171,8.05,5.973,7.983,5.781,7.922C5.733,7.906,5.72,7.895,5.717,7.846
|
||||
C5.7,7.625,5.678,7.421,5.65,7.223C5.641,7.157,5.606,7.087,5.552,7.03C5.417,6.887,5.274,6.75,5.136,6.618l-0.03-0.029
|
||||
C5.077,6.56,5.076,6.547,5.089,6.516l0.015-0.038c0.067-0.18,0.137-0.367,0.196-0.554c0.024-0.068,0.023-0.16-0.001-0.234
|
||||
C5.234,5.486,5.158,5.282,5.091,5.109C5.077,5.07,5.08,5.057,5.109,5.03c0.179-0.172,0.325-0.314,0.454-0.448
|
||||
C5.606,4.539,5.64,4.473,5.649,4.413C5.675,4.214,5.699,4,5.72,3.758c0.003-0.034,0.011-0.042,0.047-0.054
|
||||
c0.184-0.061,0.398-0.131,0.604-0.208c0.062-0.022,0.125-0.073,0.16-0.127c0.124-0.188,0.239-0.38,0.335-0.543
|
||||
c0.027-0.045,0.044-0.04,0.074-0.036C7.179,2.823,7.397,2.849,7.605,2.87C7.653,2.874,7.71,2.859,7.759,2.83
|
||||
C7.937,2.72,8.12,2.607,8.297,2.486c0.027-0.018,0.042-0.02,0.051-0.02c0.015,0,0.033,0.007,0.057,0.023
|
||||
C8.58,2.606,8.762,2.721,8.942,2.832C8.979,2.855,9.034,2.87,9.087,2.87l0.021-0.001C9.35,2.843,9.564,2.818,9.76,2.792
|
||||
c0.028-0.004,0.043-0.011,0.066,0.03c0.103,0.175,0.216,0.363,0.339,0.542c0.037,0.057,0.101,0.107,0.167,0.133
|
||||
c0.105,0.04,0.21,0.075,0.314,0.11c0.095,0.032,0.19,0.064,0.285,0.099c0.015,0.006,0.039,0.035,0.04,0.05
|
||||
C10.988,3.873,11,3.989,11.012,4.105c0.011,0.104,0.023,0.209,0.036,0.313c0.006,0.055,0.038,0.118,0.081,0.16
|
||||
c0.155,0.16,0.31,0.313,0.462,0.456c0.027,0.027,0.029,0.037,0.015,0.071c-0.033,0.088-0.065,0.178-0.097,0.267
|
||||
c-0.039,0.107-0.078,0.215-0.118,0.32C11.359,5.771,11.36,5.849,11.392,5.934z"/>
|
||||
</g>
|
||||
<path fill="#292D32" d="M9.396,12.311c0.141,0,0.249-0.072,0.319-0.216c0.104-0.217,0.209-0.433,0.313-0.649l0.212-0.439
|
||||
c0.015-0.032,0.032-0.063,0.049-0.097l0.042-0.079l0.039,0.01c0.35,0.099,0.697,0.193,1.044,0.289l0.084,0.023
|
||||
c0.025,0.007,0.052,0.015,0.077,0.022c0.038,0.011,0.075,0.023,0.113,0.032c0.042,0.01,0.082,0.015,0.118,0.015
|
||||
c0.102,0,0.184-0.039,0.251-0.117c0.095-0.111,0.111-0.239,0.049-0.379c-0.137-0.306-0.275-0.612-0.415-0.918
|
||||
c-0.066-0.147-0.142-0.309-0.22-0.476c-0.149-0.324-0.306-0.659-0.428-0.95l-0.574,0.368l0.272,0.62
|
||||
c0.132,0.292,0.263,0.583,0.398,0.883l0.042,0.094l-0.099-0.024c-0.021-0.005-0.038-0.009-0.051-0.011
|
||||
c-0.017-0.004-0.03-0.007-0.042-0.01L10.31,10.11c-0.263-0.072-0.387-0.016-0.507,0.233l-0.244,0.503
|
||||
c-0.031,0.065-0.063,0.129-0.106,0.218l-0.046,0.095l-0.76-1.682L8.234,9.638L7.823,9.477l-0.761,1.682l-0.046-0.095
|
||||
c-0.043-0.089-0.075-0.153-0.106-0.218l-0.245-0.502c-0.119-0.249-0.245-0.304-0.506-0.232l-0.683,0.188
|
||||
c-0.012,0.003-0.025,0.006-0.042,0.01c-0.014,0.003-0.03,0.006-0.05,0.011l-0.099,0.024l0.042-0.093
|
||||
c0.135-0.301,0.267-0.592,0.398-0.884l0.327-0.716l-0.679-0.14C5.261,8.777,5.134,9.042,5.013,9.298
|
||||
C4.932,9.467,4.851,9.637,4.774,9.806c-0.139,0.306-0.277,0.613-0.414,0.919c-0.063,0.141-0.047,0.268,0.047,0.378
|
||||
c0.092,0.108,0.214,0.142,0.37,0.103c0.038-0.01,0.075-0.021,0.113-0.032c0.026-0.008,0.051-0.015,0.078-0.022l0.084-0.023
|
||||
c0.346-0.095,0.694-0.19,1.043-0.288l0.039-0.01l0.041,0.079c0.019,0.035,0.035,0.066,0.05,0.097l0.212,0.439
|
||||
c0.104,0.217,0.208,0.433,0.313,0.648c0.07,0.144,0.178,0.218,0.319,0.218c0.149-0.003,0.255-0.077,0.322-0.221
|
||||
c0.012-0.023,0.022-0.046,0.033-0.07l0.809-1.789l0.808,1.789c0.011,0.023,0.021,0.047,0.032,0.07
|
||||
c0.068,0.144,0.174,0.218,0.314,0.221l0.009,0.048l0,0L9.396,12.311L9.396,12.311z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
44
Pdf4QtViewerPlugins/SignaturePlugin/sign-electronically.svg
Normal file
@@ -0,0 +1,44 @@
|
||||
<?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="#57B400" cx="8.629" cy="5.827" r="4.192"/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M11.625,4.216c-0.029,0.146-0.12,0.252-0.225,0.356C10.32,5.652,9.236,6.733,8.157,7.81
|
||||
C8.01,7.96,7.84,8.022,7.637,7.95C7.566,7.925,7.495,7.878,7.439,7.824C6.889,7.279,6.342,6.728,5.793,6.179
|
||||
C5.71,6.097,5.661,6.001,5.635,5.889c0-0.041,0-0.08,0-0.119c0.026-0.11,0.069-0.211,0.155-0.291
|
||||
C5.996,5.3,6.269,5.313,6.471,5.516c0.424,0.42,0.846,0.844,1.271,1.269C7.756,6.802,7.769,6.818,7.79,6.851
|
||||
C7.816,6.82,7.824,6.802,7.841,6.789c0.982-0.981,1.964-1.965,2.948-2.951c0.143-0.143,0.308-0.204,0.505-0.143
|
||||
c0.174,0.057,0.275,0.175,0.32,0.352c0.005,0.014,0.009,0.025,0.013,0.035C11.625,4.129,11.625,4.172,11.625,4.216z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M22.52,5.539c-0.156-0.208-0.406-0.292-0.653-0.239c-0.216,0.042-0.38,0.179-0.491,0.411
|
||||
c-0.093,0.199-0.188,0.396-0.286,0.594L21,6.484l-0.076-0.036l0.385-0.784c0.229-0.49,0.318-0.908,0.283-1.315
|
||||
c-0.098-1.286-0.982-2.325-2.246-2.646C19.1,1.643,18.85,1.611,18.6,1.611c-1.072,0-2.012,0.56-2.447,1.46
|
||||
c-2.147,4.415-4.289,8.831-6.42,13.25c-0.104,0.214-0.163,0.476-0.158,0.721c0.017,1.006,0.06,2.016,0.102,2.961
|
||||
c0.009,0.184,0.021,0.432,0.146,0.598c0.143,0.188,0.136,0.334-0.034,0.594c-0.023,0.039-0.041,0.082-0.062,0.131
|
||||
c-0.147,0.347-0.01,0.729,0.319,0.886c0.087,0.043,0.179,0.065,0.274,0.065c0.238,0,0.458-0.135,0.586-0.355
|
||||
c0.042-0.07,0.077-0.146,0.112-0.221c0.03-0.067,0.062-0.133,0.093-0.188c0.012-0.018,0.042-0.037,0.049-0.041
|
||||
c0.349-0.019,0.665-0.141,0.964-0.369c0.743-0.551,1.488-1.098,2.236-1.638c0.252-0.183,0.443-0.413,0.59-0.707
|
||||
c1.016-2.103,2.033-4.196,3.055-6.297c0.771-1.588,1.544-3.177,2.313-4.767c0.01-0.017,0.018-0.033,0.024-0.05
|
||||
c0.024,0.012,0.05,0.025,0.073,0.037l-2.311,4.762c-0.052,0.104-0.096,0.208-0.123,0.317c-0.086,0.351,0.11,0.688,0.463,0.782
|
||||
c0.063,0.02,0.123,0.025,0.183,0.025c0.183,0,0.44-0.084,0.638-0.478l2.248-4.64c0.225-0.458,0.446-0.915,0.67-1.373l0.401-0.827
|
||||
C22.709,6.001,22.686,5.755,22.52,5.539z M18.052,9.316c-0.135,0.285-0.27,0.563-0.401,0.838l-1.301,2.679
|
||||
c-0.826,1.701-1.651,3.403-2.477,5.104c-0.075,0.15-0.107,0.105-0.188,0.092c-1.023-0.163-1.891-0.596-2.646-1.319
|
||||
c-0.025-0.022-0.032-0.034-0.014-0.062c1.055-2.166,2.105-4.331,3.157-6.497l1.063-2.195C16.184,8.41,17.113,8.861,18.052,9.316z
|
||||
M18.563,2.766v0.169c0.666,0,1.168,0.278,1.496,0.825c0.268,0.446,0.273,0.889,0.022,1.395c-0.349,0.691-0.685,1.388-1.021,2.084
|
||||
L18.654,8.08c-0.008,0.012-0.014,0.024-0.021,0.038L15.831,6.76c0.071-0.151,0.144-0.298,0.212-0.442l0.466-0.963
|
||||
c0.253-0.521,0.507-1.042,0.757-1.563c0.271-0.564,0.703-0.852,1.28-0.858L18.563,2.766L18.563,2.766z M12.541,19.15l-0.27,0.197
|
||||
c-0.317,0.23-0.635,0.463-0.948,0.694c-0.119,0.086-0.185,0.104-0.25,0.069c-0.055-0.026-0.081-0.066-0.086-0.235
|
||||
c-0.012-0.351-0.025-0.692-0.039-1.054l-0.02-0.495C11.438,18.672,11.96,18.939,12.541,19.15z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#292D32" d="M7.684,22.389c-1.105,0-1.947-0.215-2.457-0.847c-0.683-0.847-0.629-2.28,0.173-4.651
|
||||
c0.505-1.492,0.518-2.516,0.035-2.955c-0.804-0.738-2.982-0.024-3.682,0.281l-0.418-0.951c0.339-0.146,3.359-1.418,4.801-0.098
|
||||
c0.82,0.751,0.903,2.116,0.247,4.055c-0.648,1.916-0.766,3.15-0.349,3.668c0.465,0.578,1.855,0.504,3.152,0.357l0.116,1.031
|
||||
C8.716,22.346,8.174,22.389,7.684,22.389z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
666
Pdf4QtViewerPlugins/SignaturePlugin/signatureplugin.cpp
Normal file
@@ -0,0 +1,666 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "signatureplugin.h"
|
||||
#include "pdfdrawwidget.h"
|
||||
#include "pdfutils.h"
|
||||
#include "pdfpagecontenteditorwidget.h"
|
||||
#include "pdfpagecontenteditorstylesettings.h"
|
||||
#include "pdfdocumentbuilder.h"
|
||||
#include "certificatemanagerdialog.h"
|
||||
#include "signdialog.h"
|
||||
#include "pdfdocumentwriter.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QToolButton>
|
||||
#include <QMainWindow>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
SignaturePlugin::SignaturePlugin() :
|
||||
pdf::PDFPlugin(nullptr),
|
||||
m_actions({ }),
|
||||
m_tools({ }),
|
||||
m_editorWidget(nullptr),
|
||||
m_scene(nullptr),
|
||||
m_sceneSelectionChangeEnabled(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SignaturePlugin::setWidget(pdf::PDFWidget* widget)
|
||||
{
|
||||
Q_ASSERT(!m_widget);
|
||||
|
||||
BaseClass::setWidget(widget);
|
||||
|
||||
QAction* activateAction = new QAction(QIcon(":/pdfplugins/signatureplugin/activate.svg"), tr("Activate signature creator"), this);
|
||||
QAction* createTextAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-text.svg"), tr("Create Text Label"), this);
|
||||
QAction* createFreehandCurveAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-freehand-curve.svg"), tr("Create Freehand Curve"), this);
|
||||
QAction* createAcceptMarkAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-yes-mark.svg"), tr("Create Accept Mark"), this);
|
||||
QAction* createRejectMarkAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-no-mark.svg"), tr("Create Reject Mark"), this);
|
||||
QAction* createRectangleAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-rectangle.svg"), tr("Create Rectangle"), this);
|
||||
QAction* createRoundedRectangleAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-rounded-rectangle.svg"), tr("Create Rounded Rectangle"), this);
|
||||
QAction* createHorizontalLineAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-horizontal-line.svg"), tr("Create Horizontal Line"), this);
|
||||
QAction* createVerticalLineAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-vertical-line.svg"), tr("Create Vertical Line"), this);
|
||||
QAction* createLineAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-line.svg"), tr("Create Line"), this);
|
||||
QAction* createDotAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-dot.svg"), tr("Create Dot"), this);
|
||||
QAction* createSvgImageAction = new QAction(QIcon(":/pdfplugins/signatureplugin/create-svg-image.svg"), tr("Create SVG Image"), this);
|
||||
QAction* clearAction = new QAction(QIcon(":/pdfplugins/signatureplugin/clear.svg"), tr("Clear All Graphics"), this);
|
||||
QAction* signElectronicallyAction = new QAction(QIcon(":/pdfplugins/signatureplugin/sign-electronically.svg"), tr("Sign Electronically"), this);
|
||||
QAction* signDigitallyAction = new QAction(QIcon(":/pdfplugins/signatureplugin/sign-digitally.svg"), tr("Sign Digitally With Certificate"), this);
|
||||
QAction* certificatesAction = new QAction(QIcon(":/pdfplugins/signatureplugin/certificates.svg"), tr("Certificates Manager"), this);
|
||||
|
||||
activateAction->setObjectName("signaturetool_activateAction");
|
||||
createTextAction->setObjectName("signaturetool_createTextAction");
|
||||
createFreehandCurveAction->setObjectName("signaturetool_createFreehandCurveAction");
|
||||
createAcceptMarkAction->setObjectName("signaturetool_createAcceptMarkAction");
|
||||
createRejectMarkAction->setObjectName("signaturetool_createRejectMarkAction");
|
||||
createRectangleAction->setObjectName("signaturetool_createRectangleAction");
|
||||
createRoundedRectangleAction->setObjectName("signaturetool_createRoundedRectangleAction");
|
||||
createHorizontalLineAction->setObjectName("signaturetool_createHorizontalLineAction");
|
||||
createVerticalLineAction->setObjectName("signaturetool_createVerticalLineAction");
|
||||
createLineAction->setObjectName("signaturetool_createLineAction");
|
||||
createDotAction->setObjectName("signaturetool_createDotAction");
|
||||
createSvgImageAction->setObjectName("signaturetool_createSvgImageAction");
|
||||
clearAction->setObjectName("signaturetool_clearAction");
|
||||
signElectronicallyAction->setObjectName("signaturetool_signElectronicallyAction");
|
||||
signDigitallyAction->setObjectName("signaturetool_signDigitallyAction");
|
||||
certificatesAction->setObjectName("signaturetool_certificatesAction");
|
||||
|
||||
activateAction->setCheckable(true);
|
||||
createTextAction->setCheckable(true);
|
||||
createFreehandCurveAction->setCheckable(true);
|
||||
createAcceptMarkAction->setCheckable(true);
|
||||
createRejectMarkAction->setCheckable(true);
|
||||
createRectangleAction->setCheckable(true);
|
||||
createRoundedRectangleAction->setCheckable(true);
|
||||
createHorizontalLineAction->setCheckable(true);
|
||||
createVerticalLineAction->setCheckable(true);
|
||||
createLineAction->setCheckable(true);
|
||||
createDotAction->setCheckable(true);
|
||||
createSvgImageAction->setCheckable(true);
|
||||
|
||||
m_actions[Activate] = activateAction;
|
||||
m_actions[Text] = createTextAction;
|
||||
m_actions[FreehandCurve] = createFreehandCurveAction;
|
||||
m_actions[AcceptMark] = createAcceptMarkAction;
|
||||
m_actions[RejectMark] = createRejectMarkAction;
|
||||
m_actions[Rectangle] = createRectangleAction;
|
||||
m_actions[RoundedRectangle] = createRoundedRectangleAction;
|
||||
m_actions[HorizontalLine] = createHorizontalLineAction;
|
||||
m_actions[VerticalLine] = createVerticalLineAction;
|
||||
m_actions[Line] = createLineAction;
|
||||
m_actions[Dot] = createDotAction;
|
||||
m_actions[SvgImage] = createSvgImageAction;
|
||||
m_actions[Clear] = clearAction;
|
||||
m_actions[SignElectronically] = signElectronicallyAction;
|
||||
m_actions[SignDigitally] = signDigitallyAction;
|
||||
m_actions[Certificates] = 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[TextTool] = new pdf::PDFCreatePCElementTextTool(widget->getDrawWidgetProxy(), &m_scene, createTextAction, this);
|
||||
m_tools[FreehandCurveTool] = new pdf::PDFCreatePCElementFreehandCurveTool(widget->getDrawWidgetProxy(), &m_scene, createFreehandCurveAction, this);
|
||||
m_tools[AcceptMarkTool] = new pdf::PDFCreatePCElementImageTool(widget->getDrawWidgetProxy(), &m_scene, createAcceptMarkAction, acceptMarkContent, false, this);
|
||||
m_tools[RejectMarkTool] = new pdf::PDFCreatePCElementImageTool(widget->getDrawWidgetProxy(), &m_scene, createRejectMarkAction, rejectMarkContent, false, 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);
|
||||
m_tools[VerticalLineTool] = new pdf::PDFCreatePCElementLineTool(widget->getDrawWidgetProxy(), &m_scene, createVerticalLineAction, false, true, this);
|
||||
m_tools[LineTool] = new pdf::PDFCreatePCElementLineTool(widget->getDrawWidgetProxy(), &m_scene, createLineAction, false, false, this);
|
||||
m_tools[DotTool] = new pdf::PDFCreatePCElementDotTool(widget->getDrawWidgetProxy(), &m_scene, createDotAction, this);
|
||||
m_tools[ImageTool] = new pdf::PDFCreatePCElementImageTool(widget->getDrawWidgetProxy(), &m_scene, createSvgImageAction, QByteArray(), true, this);
|
||||
|
||||
pdf::PDFToolManager* toolManager = widget->getToolManager();
|
||||
for (pdf::PDFWidgetTool* tool : m_tools)
|
||||
{
|
||||
toolManager->addTool(tool);
|
||||
connect(tool, &pdf::PDFWidgetTool::toolActivityChanged, this, &SignaturePlugin::onToolActivityChanged);
|
||||
}
|
||||
|
||||
m_widget->addInputInterface(&m_scene);
|
||||
m_widget->getDrawWidgetProxy()->registerDrawInterface(&m_scene);
|
||||
m_scene.setWidget(m_widget);
|
||||
connect(&m_scene, &pdf::PDFPageContentScene::sceneChanged, this, &SignaturePlugin::onSceneChanged);
|
||||
connect(&m_scene, &pdf::PDFPageContentScene::selectionChanged, this, &SignaturePlugin::onSceneSelectionChanged);
|
||||
connect(&m_scene, &pdf::PDFPageContentScene::editElementRequest, this, &SignaturePlugin::onSceneEditElement);
|
||||
connect(clearAction, &QAction::triggered, &m_scene, &pdf::PDFPageContentScene::clear);
|
||||
connect(activateAction, &QAction::triggered, this, &SignaturePlugin::setActive);
|
||||
connect(signElectronicallyAction, &QAction::triggered, this, &SignaturePlugin::onSignElectronically);
|
||||
connect(signDigitallyAction, &QAction::triggered, this, &SignaturePlugin::onSignDigitally);
|
||||
connect(certificatesAction, &QAction::triggered, this, &SignaturePlugin::onOpenCertificatesManager);
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void SignaturePlugin::setDocument(const pdf::PDFModifiedDocument& document)
|
||||
{
|
||||
BaseClass::setDocument(document);
|
||||
|
||||
if (document.hasReset())
|
||||
{
|
||||
setActive(false);
|
||||
updateActions();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<QAction*> SignaturePlugin::getActions() const
|
||||
{
|
||||
std::vector<QAction*> result;
|
||||
|
||||
result.push_back(m_actions[Activate]);
|
||||
result.push_back(m_actions[SignElectronically]);
|
||||
result.push_back(m_actions[SignDigitally]);
|
||||
result.push_back(m_actions[Certificates]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SignaturePlugin::onSceneChanged(bool graphicsOnly)
|
||||
{
|
||||
if (!graphicsOnly)
|
||||
{
|
||||
updateActions();
|
||||
}
|
||||
|
||||
if (m_editorWidget)
|
||||
{
|
||||
m_editorWidget->updateItemsInListWidget();
|
||||
}
|
||||
|
||||
updateGraphics();
|
||||
}
|
||||
|
||||
void SignaturePlugin::onSceneSelectionChanged()
|
||||
{
|
||||
if (m_editorWidget && m_sceneSelectionChangeEnabled)
|
||||
{
|
||||
m_editorWidget->setSelection(m_scene.getSelectedElementIds());
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::onWidgetSelectionChanged()
|
||||
{
|
||||
Q_ASSERT(m_editorWidget);
|
||||
|
||||
pdf::PDFTemporaryValueChange guard(&m_sceneSelectionChangeEnabled, false);
|
||||
m_scene.setSelectedElementIds(m_editorWidget->getSelection());
|
||||
}
|
||||
|
||||
pdf::PDFWidgetTool* SignaturePlugin::getActiveTool()
|
||||
{
|
||||
for (pdf::PDFWidgetTool* currentTool : m_tools)
|
||||
{
|
||||
if (currentTool->isActive())
|
||||
{
|
||||
return currentTool;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SignaturePlugin::onToolActivityChanged()
|
||||
{
|
||||
if (m_editorWidget)
|
||||
{
|
||||
pdf::PDFWidgetTool* activeTool = getActiveTool();
|
||||
|
||||
const pdf::PDFPageContentElement* element = nullptr;
|
||||
pdf::PDFCreatePCElementTool* tool = qobject_cast<pdf::PDFCreatePCElementTool*>(activeTool);
|
||||
if (tool)
|
||||
{
|
||||
element = tool->getElement();
|
||||
}
|
||||
|
||||
m_editorWidget->loadStyleFromElement(element);
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::onSceneEditElement(const std::set<pdf::PDFInteger>& elements)
|
||||
{
|
||||
if (elements.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFPageContentElement* element = nullptr;
|
||||
for (pdf::PDFInteger id : elements)
|
||||
{
|
||||
element = m_scene.getElementById(id);
|
||||
if (element)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!element)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (pdf::PDFPageContentEditorStyleSettings::showEditElementStyleDialog(m_dataExchangeInterface->getMainWindow(), element))
|
||||
{
|
||||
updateGraphics();
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::onSignElectronically()
|
||||
{
|
||||
Q_ASSERT(m_document);
|
||||
Q_ASSERT(!m_scene.isEmpty());
|
||||
|
||||
if (QMessageBox::question(m_dataExchangeInterface->getMainWindow(), tr("Confirm Signature"), tr("Document will be signed electronically. Do you want to continue?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
|
||||
{
|
||||
pdf::PDFDocumentModifier modifier(m_document);
|
||||
|
||||
std::set<pdf::PDFInteger> pageIndices = m_scene.getPageIndices();
|
||||
for (pdf::PDFInteger pageIndex : pageIndices)
|
||||
{
|
||||
const pdf::PDFPage* page = m_document->getCatalog()->getPage(pageIndex);
|
||||
pdf::PDFPageContentStreamBuilder pageContentStreamBuilder(modifier.getBuilder(),
|
||||
pdf::PDFContentStreamBuilder::CoordinateSystem::PDF,
|
||||
pdf::PDFPageContentStreamBuilder::Mode::PlaceAfter);
|
||||
QPainter* painter = pageContentStreamBuilder.begin(page->getPageReference());
|
||||
QList<pdf::PDFRenderError> errors;
|
||||
pdf::PDFTextLayoutGetter nullGetter(nullptr, pageIndex);
|
||||
m_scene.drawElements(painter, pageIndex, nullGetter, QMatrix(), nullptr, errors);
|
||||
pageContentStreamBuilder.end(painter);
|
||||
modifier.markPageContentsChanged();
|
||||
}
|
||||
m_scene.clear();
|
||||
|
||||
if (modifier.finalize())
|
||||
{
|
||||
emit m_widget->getToolManager()->documentModified(pdf::PDFModifiedDocument(modifier.getDocument(), nullptr, modifier.getFlags()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::onSignDigitally()
|
||||
{
|
||||
// Jakub Melka: do we have certificates? If not,
|
||||
// open certificate dialog, so the user can create
|
||||
// a new one.
|
||||
if (CertificateManager::getCertificates().isEmpty())
|
||||
{
|
||||
onOpenCertificatesManager();
|
||||
|
||||
if (CertificateManager::getCertificates().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SignDialog dialog(m_dataExchangeInterface->getMainWindow(), m_scene.isEmpty());
|
||||
if (dialog.exec() == SignDialog::Accepted)
|
||||
{
|
||||
QByteArray data = "SampleDataToBeSigned" + QByteArray::number(QDateTime::currentMSecsSinceEpoch());
|
||||
QByteArray signature;
|
||||
if (!SignatureFactory::sign(dialog.getCertificatePath(), dialog.getPassword(), data, signature))
|
||||
{
|
||||
QMessageBox::critical(m_widget, tr("Error"), tr("Failed to create digital signature."));
|
||||
return;
|
||||
}
|
||||
|
||||
QString signatureName = QString("pdf4qt_signature_%1").arg(QString::number(QDateTime::currentMSecsSinceEpoch()));
|
||||
|
||||
pdf::PDFInteger offsetMark = 123456789123;
|
||||
constexpr const char* offsetMarkString = "123456789123";
|
||||
const auto offsetMarkStringLength = std::strlen(offsetMarkString);
|
||||
|
||||
pdf::PDFDocumentBuilder builder(m_document);
|
||||
pdf::PDFObjectReference signatureDictionary = builder.createSignatureDictionary("Adobe.PPKLite", "adbe.pkcs7.detached", signature, QDateTime::currentDateTime(), offsetMark);
|
||||
pdf::PDFObjectReference formField = builder.createFormFieldSignature(signatureName, { }, signatureDictionary);
|
||||
builder.createAcroForm({ formField });
|
||||
|
||||
const pdf::PDFCatalog* catalog = m_document->getCatalog();
|
||||
if (dialog.getSignMethod() == SignDialog::SignDigitallyInvisible)
|
||||
{
|
||||
if (catalog->getPageCount() > 0)
|
||||
{
|
||||
const pdf::PDFObjectReference pageReference = catalog->getPage(0)->getPageReference();
|
||||
builder.createInvisibleFormFieldWidget(formField, pageReference);
|
||||
}
|
||||
}
|
||||
else if (dialog.getSignMethod() == SignDialog::SignDigitally)
|
||||
{
|
||||
Q_ASSERT(!m_scene.isEmpty());
|
||||
const pdf::PDFInteger pageIndex = *m_scene.getPageIndices().begin();
|
||||
const pdf::PDFPage* page = catalog->getPage(pageIndex);
|
||||
|
||||
pdf::PDFContentStreamBuilder contentBuilder(page->getMediaBox().size(), pdf::PDFContentStreamBuilder::CoordinateSystem::PDF);
|
||||
QPainter* painter = contentBuilder.begin();
|
||||
QList<pdf::PDFRenderError> errors;
|
||||
pdf::PDFTextLayoutGetter nullGetter(nullptr, pageIndex);
|
||||
m_scene.drawPage(painter, pageIndex, nullptr, nullGetter, QMatrix(), errors);
|
||||
pdf::PDFContentStreamBuilder::ContentStream contentStream = contentBuilder.end(painter);
|
||||
|
||||
QRectF boundingRect = m_scene.getBoundingBox(pageIndex);
|
||||
std::vector<pdf::PDFObject> copiedObjects = builder.copyFrom({ contentStream.resources, contentStream.contents }, contentStream.document.getStorage(), true);
|
||||
Q_ASSERT(copiedObjects.size() == 2);
|
||||
|
||||
pdf::PDFObjectReference resourcesReference = copiedObjects[0].getReference();
|
||||
pdf::PDFObjectReference formReference = copiedObjects[1].getReference();
|
||||
|
||||
// Create form object
|
||||
pdf::PDFObjectFactory formFactory;
|
||||
|
||||
formFactory.beginDictionary();
|
||||
|
||||
formFactory.beginDictionaryItem("Type");
|
||||
formFactory << pdf::WrapName("XObject");
|
||||
formFactory.endDictionaryItem();
|
||||
|
||||
formFactory.beginDictionaryItem("Subtype");
|
||||
formFactory << pdf::WrapName("Form");
|
||||
formFactory.endDictionaryItem();
|
||||
|
||||
formFactory.beginDictionaryItem("BBox");
|
||||
formFactory << boundingRect;
|
||||
formFactory.endDictionaryItem();
|
||||
|
||||
formFactory.beginDictionaryItem("Resources");
|
||||
formFactory << resourcesReference;
|
||||
formFactory.endDictionaryItem();
|
||||
|
||||
formFactory.endDictionary();
|
||||
|
||||
builder.mergeTo(formReference, formFactory.takeObject());
|
||||
|
||||
builder.createFormFieldWidget(formField, page->getPageReference(), formReference, boundingRect);
|
||||
}
|
||||
|
||||
QString reasonText = dialog.getReasonText();
|
||||
if (!reasonText.isEmpty())
|
||||
{
|
||||
builder.setSignatureReason(signatureDictionary, reasonText);
|
||||
}
|
||||
|
||||
QString contactInfoText = dialog.getContactInfoText();
|
||||
if (!contactInfoText.isEmpty())
|
||||
{
|
||||
builder.setSignatureContactInfo(signatureDictionary, contactInfoText);
|
||||
}
|
||||
|
||||
pdf::PDFDocument signedDocument = builder.build();
|
||||
|
||||
// 1) Save the document with incorrect signature
|
||||
QBuffer buffer;
|
||||
pdf::PDFDocumentWriter writer(m_widget->getDrawWidgetProxy()->getProgress());
|
||||
buffer.open(QBuffer::ReadWrite);
|
||||
writer.write(&buffer, &signedDocument);
|
||||
|
||||
const int indexOfSignature = buffer.data().indexOf(signature.toHex());
|
||||
if (indexOfSignature == -1)
|
||||
{
|
||||
QMessageBox::critical(m_widget, tr("Error"), tr("Failed to create digital signature."));
|
||||
buffer.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) Write ranges to be checked
|
||||
const pdf::PDFInteger i1 = 0;
|
||||
const pdf::PDFInteger i2 = indexOfSignature - 1;
|
||||
const pdf::PDFInteger i3 = i2 + signature.size() * 2 + 2;
|
||||
const pdf::PDFInteger i4 = buffer.data().size() - i3;
|
||||
|
||||
auto writeInt = [&](pdf::PDFInteger offset)
|
||||
{
|
||||
QString offsetString = QString::number(offset);
|
||||
offsetString = offsetString.leftJustified(static_cast<int>(offsetMarkStringLength), ' ', true);
|
||||
const auto index = buffer.data().lastIndexOf(QString(offsetMarkString), indexOfSignature);
|
||||
buffer.seek(index);
|
||||
buffer.write(offsetString.toLocal8Bit());
|
||||
};
|
||||
|
||||
writeInt(i4);
|
||||
writeInt(i3);
|
||||
writeInt(i2);
|
||||
writeInt(i1);
|
||||
|
||||
// 3) Sign the data
|
||||
QByteArray dataToBeSigned;
|
||||
buffer.seek(i1);
|
||||
dataToBeSigned.append(buffer.read(i2));
|
||||
buffer.seek(i3);
|
||||
dataToBeSigned.append(buffer.read(i4));
|
||||
|
||||
if (!SignatureFactory::sign(dialog.getCertificatePath(), dialog.getPassword(), dataToBeSigned, signature))
|
||||
{
|
||||
QMessageBox::critical(m_widget, tr("Error"), tr("Failed to create digital signature."));
|
||||
buffer.close();
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.seek(i2 + 1);
|
||||
buffer.write(signature.toHex());
|
||||
|
||||
buffer.close();
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(m_dataExchangeInterface->getMainWindow(), tr("Save Signed Document"), getSignedFileName(), tr("Portable Document (*.pdf);;All files (*.*)"));
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
QFile signedFile(fileName);
|
||||
if (signedFile.open(QFile::WriteOnly | QFile::Truncate))
|
||||
{
|
||||
signedFile.write(buffer.data());
|
||||
signedFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString SignaturePlugin::getSignedFileName() const
|
||||
{
|
||||
QFileInfo fileInfo(m_dataExchangeInterface->getOriginalFileName());
|
||||
|
||||
return fileInfo.path() + "/" + fileInfo.baseName() + "_SIGNED.pdf";
|
||||
}
|
||||
|
||||
void SignaturePlugin::onOpenCertificatesManager()
|
||||
{
|
||||
CertificateManagerDialog dialog(m_dataExchangeInterface->getMainWindow());
|
||||
dialog.exec();
|
||||
}
|
||||
|
||||
void SignaturePlugin::onPenChanged(const QPen& pen)
|
||||
{
|
||||
if (pdf::PDFCreatePCElementTool* activeTool = qobject_cast<pdf::PDFCreatePCElementTool*>(getActiveTool()))
|
||||
{
|
||||
activeTool->setPen(pen);
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::onBrushChanged(const QBrush& brush)
|
||||
{
|
||||
if (pdf::PDFCreatePCElementTool* activeTool = qobject_cast<pdf::PDFCreatePCElementTool*>(getActiveTool()))
|
||||
{
|
||||
activeTool->setBrush(brush);
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::onFontChanged(const QFont& font)
|
||||
{
|
||||
if (pdf::PDFCreatePCElementTool* activeTool = qobject_cast<pdf::PDFCreatePCElementTool*>(getActiveTool()))
|
||||
{
|
||||
activeTool->setFont(font);
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::onAlignmentChanged(Qt::Alignment alignment)
|
||||
{
|
||||
if (pdf::PDFCreatePCElementTool* activeTool = qobject_cast<pdf::PDFCreatePCElementTool*>(getActiveTool()))
|
||||
{
|
||||
activeTool->setAlignment(alignment);
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::onTextAngleChanged(pdf::PDFReal angle)
|
||||
{
|
||||
if (pdf::PDFCreatePCElementTool* activeTool = qobject_cast<pdf::PDFCreatePCElementTool*>(getActiveTool()))
|
||||
{
|
||||
activeTool->setTextAngle(angle);
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::setActive(bool active)
|
||||
{
|
||||
if (m_scene.isActive() != active)
|
||||
{
|
||||
// Abort active tool, if we are deactivating the plugin
|
||||
if (!active)
|
||||
{
|
||||
if (pdf::PDFWidgetTool* tool = m_widget->getToolManager()->getActiveTool())
|
||||
{
|
||||
auto it = std::find(m_tools.cbegin(), m_tools.cend(), tool);
|
||||
if (it != m_tools.cend())
|
||||
{
|
||||
m_widget->getToolManager()->setActiveTool(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_scene.setActive(active);
|
||||
if (!active)
|
||||
{
|
||||
m_scene.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
updateDockWidget();
|
||||
}
|
||||
|
||||
m_actions[Activate]->setChecked(active);
|
||||
updateActions();
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::updateActions()
|
||||
{
|
||||
m_actions[Activate]->setEnabled(m_document);
|
||||
|
||||
if (!m_scene.isActive() || !m_document)
|
||||
{
|
||||
// Inactive scene - disable all except activate action and certificates
|
||||
for (QAction* action : m_actions)
|
||||
{
|
||||
if (action == m_actions[Activate] ||
|
||||
action == m_actions[Certificates])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
action->setEnabled(false);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const bool isSceneNonempty = !m_scene.isEmpty();
|
||||
|
||||
// Tool actions
|
||||
for (auto actionId : { Text, FreehandCurve, AcceptMark, RejectMark,
|
||||
Rectangle, RoundedRectangle, HorizontalLine,
|
||||
VerticalLine, Line, Dot, SvgImage })
|
||||
{
|
||||
m_actions[actionId]->setEnabled(true);
|
||||
}
|
||||
|
||||
// Clear action
|
||||
QAction* clearAction = m_actions[Clear];
|
||||
clearAction->setEnabled(isSceneNonempty);
|
||||
|
||||
// Sign actions
|
||||
QAction* signElectronicallyAction = m_actions[SignElectronically];
|
||||
signElectronicallyAction->setEnabled(isSceneNonempty);
|
||||
QAction* signDigitallyAction = m_actions[SignDigitally];
|
||||
signDigitallyAction->setEnabled(m_document);
|
||||
}
|
||||
|
||||
void SignaturePlugin::updateGraphics()
|
||||
{
|
||||
if (m_widget)
|
||||
{
|
||||
m_widget->getDrawWidget()->getWidget()->update();
|
||||
}
|
||||
}
|
||||
|
||||
void SignaturePlugin::updateDockWidget()
|
||||
{
|
||||
if (m_editorWidget)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_editorWidget = new pdf::PDFPageContentEditorWidget(m_dataExchangeInterface->getMainWindow());
|
||||
m_editorWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
|
||||
m_dataExchangeInterface->getMainWindow()->addDockWidget(Qt::RightDockWidgetArea, m_editorWidget, Qt::Vertical);
|
||||
m_editorWidget->setFloating(false);
|
||||
m_editorWidget->setWindowTitle(tr("Signature Toolbox"));
|
||||
m_editorWidget->setScene(&m_scene);
|
||||
connect(m_editorWidget, &pdf::PDFPageContentEditorWidget::operationTriggered, &m_scene, &pdf::PDFPageContentScene::performOperation);
|
||||
connect(m_editorWidget, &pdf::PDFPageContentEditorWidget::itemSelectionChangedByUser, this, &SignaturePlugin::onWidgetSelectionChanged);
|
||||
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::AlignTop))->setIcon(QIcon(":/resources/pce-align-top.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::AlignCenterVertically))->setIcon(QIcon(":/resources/pce-align-v-center.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::AlignBottom))->setIcon(QIcon(":/resources/pce-align-bottom.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::AlignLeft))->setIcon(QIcon(":/resources/pce-align-left.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::AlignCenterHorizontally))->setIcon(QIcon(":/resources/pce-align-h-center.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::AlignRight))->setIcon(QIcon(":/resources/pce-align-right.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::SetSameHeight))->setIcon(QIcon(":/resources/pce-same-height.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::SetSameWidth))->setIcon(QIcon(":/resources/pce-same-width.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::SetSameSize))->setIcon(QIcon(":/resources/pce-same-size.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::CenterHorizontally))->setIcon(QIcon(":/resources/pce-center-h.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::CenterVertically))->setIcon(QIcon(":/resources/pce-center-v.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::CenterHorAndVert))->setIcon(QIcon(":/resources/pce-center-vh.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::LayoutVertically))->setIcon(QIcon(":/resources/pce-layout-v.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::LayoutHorizontally))->setIcon(QIcon(":/resources/pce-layout-h.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::LayoutForm))->setIcon(QIcon(":/resources/pce-layout-form.svg"));
|
||||
m_editorWidget->getToolButtonForOperation(static_cast<int>(pdf::PDFPageContentElementManipulator::Operation::LayoutGrid))->setIcon(QIcon(":/resources/pce-layout-grid.svg"));
|
||||
|
||||
for (QAction* action : m_actions)
|
||||
{
|
||||
m_editorWidget->addAction(action);
|
||||
}
|
||||
|
||||
connect(m_editorWidget, &pdf::PDFPageContentEditorWidget::penChanged, this, &SignaturePlugin::onPenChanged);
|
||||
connect(m_editorWidget, &pdf::PDFPageContentEditorWidget::brushChanged, this, &SignaturePlugin::onBrushChanged);
|
||||
connect(m_editorWidget, &pdf::PDFPageContentEditorWidget::fontChanged, this, &SignaturePlugin::onFontChanged);
|
||||
connect(m_editorWidget, &pdf::PDFPageContentEditorWidget::alignmentChanged, this, &SignaturePlugin::onAlignmentChanged);
|
||||
connect(m_editorWidget, &pdf::PDFPageContentEditorWidget::textAngleChanged, this, &SignaturePlugin::onTextAngleChanged);
|
||||
}
|
||||
|
||||
}
|
128
Pdf4QtViewerPlugins/SignaturePlugin/signatureplugin.h
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SIGNATURESPLUGIN_H
|
||||
#define SIGNATURESPLUGIN_H
|
||||
|
||||
#include "pdfplugin.h"
|
||||
#include "pdfpagecontentelements.h"
|
||||
#include "pdfpagecontenteditortools.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFPageContentEditorWidget;
|
||||
}
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
class SignaturePlugin : public pdf::PDFPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "PDF4QT.SignaturePlugin" FILE "SignaturePlugin.json")
|
||||
|
||||
private:
|
||||
using BaseClass = pdf::PDFPlugin;
|
||||
|
||||
public:
|
||||
SignaturePlugin();
|
||||
|
||||
virtual void setWidget(pdf::PDFWidget* widget) override;
|
||||
virtual void setDocument(const pdf::PDFModifiedDocument& document) override;
|
||||
virtual std::vector<QAction*> getActions() const override;
|
||||
|
||||
private:
|
||||
void onSceneChanged(bool graphicsOnly);
|
||||
void onSceneSelectionChanged();
|
||||
void onWidgetSelectionChanged();
|
||||
void onToolActivityChanged();
|
||||
void onSceneEditElement(const std::set<pdf::PDFInteger>& elements);
|
||||
void onSignElectronically();
|
||||
void onSignDigitally();
|
||||
void onOpenCertificatesManager();
|
||||
|
||||
void onPenChanged(const QPen& pen);
|
||||
void onBrushChanged(const QBrush& brush);
|
||||
void onFontChanged(const QFont& font);
|
||||
void onAlignmentChanged(Qt::Alignment alignment);
|
||||
void onTextAngleChanged(pdf::PDFReal angle);
|
||||
|
||||
enum Action
|
||||
{
|
||||
// Activate action
|
||||
Activate,
|
||||
|
||||
// Create graphics actions
|
||||
Text,
|
||||
FreehandCurve,
|
||||
AcceptMark,
|
||||
RejectMark,
|
||||
Rectangle,
|
||||
RoundedRectangle,
|
||||
HorizontalLine,
|
||||
VerticalLine,
|
||||
Line,
|
||||
Dot,
|
||||
SvgImage,
|
||||
Clear,
|
||||
|
||||
// Sign actions
|
||||
SignElectronically,
|
||||
SignDigitally,
|
||||
Certificates,
|
||||
|
||||
LastAction
|
||||
};
|
||||
|
||||
enum Tools
|
||||
{
|
||||
TextTool,
|
||||
FreehandCurveTool,
|
||||
AcceptMarkTool,
|
||||
RejectMarkTool,
|
||||
RectangleTool,
|
||||
RoundedRectangleTool,
|
||||
HorizontalLineTool,
|
||||
VerticalLineTool,
|
||||
LineTool,
|
||||
DotTool,
|
||||
ImageTool,
|
||||
LastTool
|
||||
};
|
||||
|
||||
void setActive(bool active);
|
||||
|
||||
void updateActions();
|
||||
void updateGraphics();
|
||||
void updateDockWidget();
|
||||
|
||||
QString getSignedFileName() const;
|
||||
|
||||
std::array<QAction*, LastAction> m_actions;
|
||||
std::array<pdf::PDFWidgetTool*, LastTool> m_tools;
|
||||
pdf::PDFPageContentEditorWidget* m_editorWidget;
|
||||
|
||||
pdf::PDFPageContentScene m_scene;
|
||||
bool m_sceneSelectionChangeEnabled;
|
||||
pdf::PDFWidgetTool* getActiveTool();
|
||||
};
|
||||
|
||||
} // namespace pdfplugin
|
||||
|
||||
#endif // SIGNATURESPLUGIN_H
|
105
Pdf4QtViewerPlugins/SignaturePlugin/signdialog.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "signdialog.h"
|
||||
#include "ui_signdialog.h"
|
||||
|
||||
#include "certificatemanager.h"
|
||||
|
||||
#include <openssl/pkcs7.h>
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
SignDialog::SignDialog(QWidget* parent, bool isSceneEmpty) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::SignDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if (!isSceneEmpty)
|
||||
{
|
||||
ui->methodCombo->addItem(tr("Sign digitally"), SignDigitally);
|
||||
}
|
||||
|
||||
ui->methodCombo->addItem(tr("Sign digitally (invisible signature)"), SignDigitallyInvisible);
|
||||
ui->methodCombo->setCurrentIndex(0);
|
||||
|
||||
QFileInfoList certificates = CertificateManager::getCertificates();
|
||||
for (const QFileInfo& certificateFileInfo : certificates)
|
||||
{
|
||||
ui->certificateCombo->addItem(certificateFileInfo.fileName(), certificateFileInfo.absoluteFilePath());
|
||||
}
|
||||
}
|
||||
|
||||
SignDialog::~SignDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
SignDialog::SignMethod SignDialog::getSignMethod() const
|
||||
{
|
||||
return static_cast<SignMethod>(ui->methodCombo->currentData().toInt());
|
||||
}
|
||||
|
||||
QString SignDialog::getCertificatePath() const
|
||||
{
|
||||
return ui->certificateCombo->currentData().toString();
|
||||
}
|
||||
|
||||
QString SignDialog::getPassword() const
|
||||
{
|
||||
return ui->certificatePasswordEdit->text();
|
||||
}
|
||||
|
||||
QString SignDialog::getReasonText() const
|
||||
{
|
||||
return ui->reasonEdit->text();
|
||||
}
|
||||
|
||||
QString SignDialog::getContactInfoText() const
|
||||
{
|
||||
return ui->contactInfoEdit->text();
|
||||
}
|
||||
|
||||
void SignDialog::accept()
|
||||
{
|
||||
// Check certificate
|
||||
if (!QFile::exists(getCertificatePath()))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Certificate does not exist."));
|
||||
ui->certificateCombo->setFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check we can access the certificate
|
||||
if (!CertificateManager::isCertificateValid(getCertificatePath(), ui->certificatePasswordEdit->text()))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Password to open certificate is invalid."));
|
||||
ui->certificatePasswordEdit->setFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
} // namespace pdfplugin
|
||||
|
||||
|
||||
|
59
Pdf4QtViewerPlugins/SignaturePlugin/signdialog.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2022 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SIGNDIALOG_H
|
||||
#define SIGNDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SignDialog;
|
||||
}
|
||||
|
||||
namespace pdfplugin
|
||||
{
|
||||
|
||||
class SignDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SignDialog(QWidget* parent, bool isSceneEmpty);
|
||||
virtual ~SignDialog() override;
|
||||
|
||||
virtual void accept() override;
|
||||
|
||||
enum SignMethod
|
||||
{
|
||||
SignDigitally,
|
||||
SignDigitallyInvisible
|
||||
};
|
||||
|
||||
SignMethod getSignMethod() const;
|
||||
QString getCertificatePath() const;
|
||||
QString getPassword() const;
|
||||
QString getReasonText() const;
|
||||
QString getContactInfoText() const;
|
||||
|
||||
private:
|
||||
Ui::SignDialog* ui;
|
||||
};
|
||||
|
||||
} // namespace pdfplugin
|
||||
|
||||
#endif // SIGNDIALOG_H
|
160
Pdf4QtViewerPlugins/SignaturePlugin/signdialog.ui
Normal file
@@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SignDialog</class>
|
||||
<widget class="QDialog" name="SignDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>501</width>
|
||||
<height>332</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="selectCertificateGroupBox">
|
||||
<property name="title">
|
||||
<string>Sign Method</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="methodLabel">
|
||||
<property name="text">
|
||||
<string>Method</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="methodCombo"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="certificateLabel">
|
||||
<property name="text">
|
||||
<string>Certificate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="certificateCombo"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="passwordLabel">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="certificatePasswordEdit">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="parametersGroupBox">
|
||||
<property name="title">
|
||||
<string>Parameters</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="reasonLabel">
|
||||
<property name="text">
|
||||
<string>Reason</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="reasonEdit">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="contactInfoLabel">
|
||||
<property name="text">
|
||||
<string>Contact Info</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="contactInfoEdit">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>SignDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>SignDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|