mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-03-19 12:50:17 +01:00
Signature verification UI
This commit is contained in:
parent
3e6f4ada3d
commit
17d32fd0b8
@ -861,8 +861,8 @@ QDateTime pdf::PDFPublicKeySignatureHandler::getDateTimeFromASN(const ASN1_TIME*
|
||||
tm internalTime = { };
|
||||
if (ASN1_TIME_to_tm(time, &internalTime) > 0)
|
||||
{
|
||||
time_t localTime = mktime(&internalTime);
|
||||
result = QDateTime::fromSecsSinceEpoch(localTime, Qt::LocalTime);
|
||||
time_t localTime = _mkgmtime(&internalTime);
|
||||
result = QDateTime::fromSecsSinceEpoch(localTime, Qt::UTC);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,6 +280,8 @@ public:
|
||||
|
||||
Error_Signatures_Mask = Error_Signature_Invalid | Error_Signature_SourceCertificateMissing | Error_Signature_NoSignaturesFound |
|
||||
Error_Signature_DigestFailure | Error_Signature_DataOther | Error_Signature_DataCoveredBySignatureMissing,
|
||||
|
||||
Warnings_Mask = Warning_Signature_NotCoveredBytes
|
||||
};
|
||||
Q_DECLARE_FLAGS(VerificationFlags, VerificationFlag)
|
||||
|
||||
@ -309,6 +311,7 @@ public:
|
||||
bool isCertificateValid() const { return hasFlag(Certificate_OK); }
|
||||
bool isSignatureValid() const { return hasFlag(Signature_OK); }
|
||||
bool hasError() const { return !isValid(); }
|
||||
bool hasWarning() const { return m_flags & Warnings_Mask; }
|
||||
bool hasCertificateError() const { return m_flags & Error_Certificates_Mask; }
|
||||
bool hasSignatureError() const { return m_flags & Error_Signatures_Mask; }
|
||||
bool hasFlag(VerificationFlag flag) const { return m_flags.testFlag(flag); }
|
||||
@ -318,6 +321,7 @@ public:
|
||||
const QString& getSignatureFieldQualifiedName() const { return m_signatureFieldQualifiedName; }
|
||||
const QStringList& getErrors() const { return m_errors; }
|
||||
const QStringList& getWarnings() const { return m_warnings; }
|
||||
const PDFCertificateInfos& getCertificateInfos() const { return m_certificateInfos; }
|
||||
|
||||
void setSignatureFieldQualifiedName(const QString& signatureFieldQualifiedName);
|
||||
void setSignatureFieldReference(PDFObjectReference signatureFieldReference);
|
||||
|
@ -46,5 +46,9 @@
|
||||
<file>resources/form-settings.svg</file>
|
||||
<file>resources/undo.svg</file>
|
||||
<file>resources/redo.svg</file>
|
||||
<file>resources/result-error.svg</file>
|
||||
<file>resources/result-information.svg</file>
|
||||
<file>resources/result-ok.svg</file>
|
||||
<file>resources/result-warning.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "pdfdocument.h"
|
||||
#include "pdfitemmodels.h"
|
||||
#include "pdfexception.h"
|
||||
#include "pdfsignaturehandler.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
|
||||
#include <QMenu>
|
||||
@ -97,6 +98,7 @@ PDFSidebarWidget::PDFSidebarWidget(pdf::PDFDrawWidgetProxy* proxy, PDFTextToSpee
|
||||
m_pageInfo[Thumbnails] = { ui->thumbnailsButton, ui->thumbnailsPage };
|
||||
m_pageInfo[Attachments] = { ui->attachmentsButton, ui->attachmentsPage };
|
||||
m_pageInfo[Speech] = { ui->speechButton, ui->speechPage };
|
||||
m_pageInfo[Signatures] = { ui->signaturesButton, ui->signaturesPage };
|
||||
|
||||
for (const auto& pageInfo : m_pageInfo)
|
||||
{
|
||||
@ -121,7 +123,7 @@ PDFSidebarWidget::~PDFSidebarWidget()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void PDFSidebarWidget::setDocument(const pdf::PDFModifiedDocument& document)
|
||||
void PDFSidebarWidget::setDocument(const pdf::PDFModifiedDocument& document, const std::vector<pdf::PDFSignatureVerificationResult>& signatures)
|
||||
{
|
||||
m_document = document;
|
||||
m_optionalContentActivity = document.getOptionalContentActivity();
|
||||
@ -196,6 +198,7 @@ void PDFSidebarWidget::setDocument(const pdf::PDFModifiedDocument& document)
|
||||
// Update GUI
|
||||
updateGUI(preferred);
|
||||
updateButtons();
|
||||
updateSignatures(signatures);
|
||||
}
|
||||
|
||||
bool PDFSidebarWidget::isEmpty() const
|
||||
@ -233,6 +236,9 @@ bool PDFSidebarWidget::isEmpty(Page page) const
|
||||
case Speech:
|
||||
return !m_textToSpeech->isValid();
|
||||
|
||||
case Signatures:
|
||||
return !m_signatures.empty();
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
@ -331,6 +337,201 @@ void PDFSidebarWidget::updateButtons()
|
||||
}
|
||||
}
|
||||
|
||||
void PDFSidebarWidget::updateSignatures(const std::vector<pdf::PDFSignatureVerificationResult>& signatures)
|
||||
{
|
||||
ui->signatureTreeWidget->setUpdatesEnabled(false);
|
||||
ui->signatureTreeWidget->clear();
|
||||
|
||||
QIcon okIcon(":/resources/result-ok.svg");
|
||||
QIcon errorIcon(":/resources/result-error.svg");
|
||||
QIcon warningIcon(":/resources/result-warning.svg");
|
||||
QIcon infoIcon(":/resources/result-information.svg");
|
||||
|
||||
for (const pdf::PDFSignatureVerificationResult& signature : signatures)
|
||||
{
|
||||
const pdf::PDFCertificateInfos& certificateInfos = signature.getCertificateInfos();
|
||||
const pdf::PDFCertificateInfo* certificateInfo = !certificateInfos.empty() ? &certificateInfos.front() : nullptr;
|
||||
|
||||
QString text = tr("Signed by - %1").arg(certificateInfo ? certificateInfo->getName(pdf::PDFCertificateInfo::CommonName) : tr("Unknown"));
|
||||
QTreeWidgetItem* rootItem = new QTreeWidgetItem(QStringList(text));
|
||||
|
||||
if (signature.hasError())
|
||||
{
|
||||
rootItem->setIcon(0, errorIcon);
|
||||
}
|
||||
else if (signature.hasWarning())
|
||||
{
|
||||
rootItem->setIcon(0, warningIcon);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootItem->setIcon(0, okIcon);
|
||||
}
|
||||
|
||||
if (signature.isCertificateValid())
|
||||
{
|
||||
QTreeWidgetItem* certificateItem = new QTreeWidgetItem(rootItem, QStringList(tr("Certificate is valid.")));
|
||||
certificateItem->setIcon(0, okIcon);
|
||||
}
|
||||
|
||||
if (signature.isSignatureValid())
|
||||
{
|
||||
QTreeWidgetItem* signatureItem = new QTreeWidgetItem(rootItem, QStringList(tr("Signature is valid.")));
|
||||
signatureItem->setIcon(0, okIcon);
|
||||
}
|
||||
|
||||
for (const QString& error : signature.getErrors())
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(rootItem, QStringList(error));
|
||||
item->setIcon(0, errorIcon);
|
||||
}
|
||||
|
||||
for (const QString& error : signature.getWarnings())
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(rootItem, QStringList(error));
|
||||
item->setIcon(0, warningIcon);
|
||||
}
|
||||
|
||||
if (certificateInfo)
|
||||
{
|
||||
QTreeWidgetItem* certChainRoot = new QTreeWidgetItem(rootItem, QStringList(tr("Certificate validation chain")));
|
||||
certChainRoot->setIcon(0, infoIcon);
|
||||
for (const pdf::PDFCertificateInfo& currentCertificateInfo : certificateInfos)
|
||||
{
|
||||
QTreeWidgetItem* certRoot = new QTreeWidgetItem(certChainRoot, QStringList(currentCertificateInfo.getName(pdf::PDFCertificateInfo::CommonName)));
|
||||
certRoot->setIcon(0, infoIcon);
|
||||
|
||||
auto addName = [certRoot, ¤tCertificateInfo, &infoIcon](pdf::PDFCertificateInfo::NameEntry nameEntry, QString caption)
|
||||
{
|
||||
QString text = currentCertificateInfo.getName(nameEntry);
|
||||
if (!text.isEmpty())
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(certRoot, QStringList(QString("%1: %2").arg(caption, text)));
|
||||
item->setIcon(0, infoIcon);
|
||||
}
|
||||
};
|
||||
|
||||
QString publicKeyMethod;
|
||||
switch (currentCertificateInfo.getPublicKey())
|
||||
{
|
||||
case pdf::PDFCertificateInfo::KeyRSA:
|
||||
publicKeyMethod = tr("Protected by RSA method, %1-bit key").arg(currentCertificateInfo.getKeySize());
|
||||
break;
|
||||
|
||||
case pdf::PDFCertificateInfo::KeyDSA:
|
||||
publicKeyMethod = tr("Protected by DSA method, %1-bit key").arg(currentCertificateInfo.getKeySize());
|
||||
break;
|
||||
|
||||
case pdf::PDFCertificateInfo::KeyEC:
|
||||
publicKeyMethod = tr("Protected by EC method, %1-bit key").arg(currentCertificateInfo.getKeySize());
|
||||
break;
|
||||
|
||||
case pdf::PDFCertificateInfo::KeyDH:
|
||||
publicKeyMethod = tr("Protected by DH method, %1-bit key").arg(currentCertificateInfo.getKeySize());
|
||||
break;
|
||||
|
||||
case pdf::PDFCertificateInfo::KeyUnknown:
|
||||
publicKeyMethod = tr("Unknown protection method, %1-bit key").arg(currentCertificateInfo.getKeySize());
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
addName(pdf::PDFCertificateInfo::CountryName, tr("Country"));
|
||||
addName(pdf::PDFCertificateInfo::OrganizationName, tr("Organization"));
|
||||
addName(pdf::PDFCertificateInfo::OrganizationalUnitName, tr("Org. unit"));
|
||||
addName(pdf::PDFCertificateInfo::DistinguishedName, tr("Name"));
|
||||
addName(pdf::PDFCertificateInfo::StateOrProvinceName, tr("State"));
|
||||
addName(pdf::PDFCertificateInfo::SerialNumber, tr("Serial number"));
|
||||
addName(pdf::PDFCertificateInfo::LocalityName, tr("Locality"));
|
||||
addName(pdf::PDFCertificateInfo::Title, tr("Title"));
|
||||
addName(pdf::PDFCertificateInfo::Surname, tr("Surname"));
|
||||
addName(pdf::PDFCertificateInfo::GivenName, tr("Forename"));
|
||||
addName(pdf::PDFCertificateInfo::Initials, tr("Initials"));
|
||||
addName(pdf::PDFCertificateInfo::Pseudonym, tr("Pseudonym"));
|
||||
addName(pdf::PDFCertificateInfo::GenerationalQualifier, tr("Qualifier"));
|
||||
addName(pdf::PDFCertificateInfo::Email, tr("Email"));
|
||||
|
||||
QTreeWidgetItem* publicKeyItem = new QTreeWidgetItem(certRoot, QStringList(publicKeyMethod));
|
||||
publicKeyItem->setIcon(0, infoIcon);
|
||||
|
||||
QDateTime notValidBefore = currentCertificateInfo.getNotValidBefore().toLocalTime();
|
||||
QDateTime notValidAfter = currentCertificateInfo.getNotValidAfter().toLocalTime();
|
||||
|
||||
if (notValidBefore.isValid())
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(certRoot, QStringList(QString("Valid from: %2").arg(notValidBefore.toString(Qt::DefaultLocaleShortDate))));
|
||||
item->setIcon(0, infoIcon);
|
||||
}
|
||||
|
||||
if (notValidAfter.isValid())
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(certRoot, QStringList(QString("Valid to: %2").arg(notValidAfter.toString(Qt::DefaultLocaleShortDate))));
|
||||
item->setIcon(0, infoIcon);
|
||||
}
|
||||
|
||||
QStringList keyUsages;
|
||||
pdf::PDFCertificateInfo::KeyUsageFlags keyUsageFlags = currentCertificateInfo.getKeyUsage();
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageDigitalSignature))
|
||||
{
|
||||
keyUsages << tr("Digital signatures");
|
||||
}
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageNonRepudiation))
|
||||
{
|
||||
keyUsages << tr("Non-repudiation");
|
||||
}
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageKeyEncipherment))
|
||||
{
|
||||
keyUsages << tr("Key encipherement");
|
||||
}
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageDataEncipherment))
|
||||
{
|
||||
keyUsages << tr("Application data encipherement");
|
||||
}
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageAgreement))
|
||||
{
|
||||
keyUsages << tr("Key agreement");
|
||||
}
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageCertSign))
|
||||
{
|
||||
keyUsages << tr("Verify signatures on certificates");
|
||||
}
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageCrlSign))
|
||||
{
|
||||
keyUsages << tr("Verify signatures on revocation information");
|
||||
}
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageEncipherOnly))
|
||||
{
|
||||
keyUsages << tr("Encipher data during key agreement");
|
||||
}
|
||||
if (keyUsageFlags.testFlag(pdf::PDFCertificateInfo::KeyUsageDecipherOnly))
|
||||
{
|
||||
keyUsages << tr("Decipher data during key agreement");
|
||||
}
|
||||
|
||||
if (!keyUsages.isEmpty())
|
||||
{
|
||||
QTreeWidgetItem* keyUsageRoot = new QTreeWidgetItem(certRoot, QStringList(tr("Key usages")));
|
||||
keyUsageRoot->setIcon(0, infoIcon);
|
||||
|
||||
for (const QString& keyUsage : keyUsages)
|
||||
{
|
||||
QTreeWidgetItem* keyUsageItem = new QTreeWidgetItem(keyUsageRoot, QStringList(keyUsage));
|
||||
keyUsageItem->setIcon(0, infoIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui->signatureTreeWidget->addTopLevelItem(rootItem);
|
||||
}
|
||||
|
||||
ui->signatureTreeWidget->expandToDepth(1);
|
||||
ui->signatureTreeWidget->setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
void PDFSidebarWidget::onPageButtonClicked()
|
||||
{
|
||||
QObject* pushButton = sender();
|
||||
|
@ -37,10 +37,11 @@ class PDFAction;
|
||||
class PDFDocument;
|
||||
class PDFDrawWidgetProxy;
|
||||
class PDFModifiedDocument;
|
||||
class PDFOutlineTreeItemModel;
|
||||
class PDFThumbnailsItemModel;
|
||||
class PDFAttachmentsTreeItemModel;
|
||||
class PDFOutlineTreeItemModel;
|
||||
class PDFOptionalContentActivity;
|
||||
class PDFAttachmentsTreeItemModel;
|
||||
class PDFSignatureVerificationResult;
|
||||
class PDFOptionalContentTreeItemModel;
|
||||
}
|
||||
|
||||
@ -67,10 +68,11 @@ public:
|
||||
OptionalContent,
|
||||
Attachments,
|
||||
Speech,
|
||||
Signatures,
|
||||
_END
|
||||
};
|
||||
|
||||
void setDocument(const pdf::PDFModifiedDocument& document);
|
||||
void setDocument(const pdf::PDFModifiedDocument& document, const std::vector<pdf::PDFSignatureVerificationResult>& signatures);
|
||||
|
||||
/// Returns true, if all items in sidebar are empty
|
||||
bool isEmpty() const;
|
||||
@ -93,6 +95,7 @@ signals:
|
||||
private:
|
||||
void updateGUI(Page preferredPage);
|
||||
void updateButtons();
|
||||
void updateSignatures(const std::vector<pdf::PDFSignatureVerificationResult>& signatures);
|
||||
|
||||
void onPageButtonClicked();
|
||||
void onOutlineItemClicked(const QModelIndex& index);
|
||||
@ -116,6 +119,7 @@ private:
|
||||
pdf::PDFOptionalContentActivity* m_optionalContentActivity;
|
||||
pdf::PDFAttachmentsTreeItemModel* m_attachmentsTreeModel;
|
||||
std::map<Page, PageInfo> m_pageInfo;
|
||||
std::vector<pdf::PDFSignatureVerificationResult> m_signatures;
|
||||
};
|
||||
|
||||
} // namespace pdfviewer
|
||||
|
@ -93,6 +93,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="signaturesButton">
|
||||
<property name="text">
|
||||
<string>Signatures</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="buttonSpacer">
|
||||
<property name="orientation">
|
||||
@ -111,7 +124,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>5</number>
|
||||
<number>6</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="emptyPage"/>
|
||||
<widget class="QWidget" name="bookmarksPage">
|
||||
@ -392,6 +405,37 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="signaturesPage">
|
||||
<layout class="QVBoxLayout" name="signaturesPageLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="signatureTreeWidget">
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -967,8 +967,7 @@ void PDFViewerMainWindow::openDocument(const QString& fileName)
|
||||
{
|
||||
// Verify signatures
|
||||
pdf::PDFForm form = pdf::PDFForm::parse(&document, document.getCatalog()->getFormObject());
|
||||
std::vector<pdf::PDFSignatureVerificationResult> signaturesVerifications = pdf::PDFSignatureHandler::verifySignatures(form, reader.getSource());
|
||||
|
||||
result.signatures = pdf::PDFSignatureHandler::verifySignatures(form, reader.getSource());
|
||||
result.document.reset(new pdf::PDFDocument(qMove(document)));
|
||||
}
|
||||
|
||||
@ -1001,7 +1000,8 @@ void PDFViewerMainWindow::onDocumentReadingFinished()
|
||||
// We add file to recent files only, if we have successfully read the document
|
||||
m_recentFileManager->addRecentFile(m_fileInfo.originalFileName);
|
||||
|
||||
m_pdfDocument = result.document;
|
||||
m_pdfDocument = qMove(result.document);
|
||||
m_signatures = qMove(result.signatures);
|
||||
pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity);
|
||||
setDocument(document);
|
||||
|
||||
@ -1072,7 +1072,7 @@ void PDFViewerMainWindow::setDocument(pdf::PDFModifiedDocument document)
|
||||
m_toolManager->setDocument(document);
|
||||
m_textToSpeech->setDocument(document);
|
||||
m_pdfWidget->setDocument(document);
|
||||
m_sidebarWidget->setDocument(document);
|
||||
m_sidebarWidget->setDocument(document, m_signatures);
|
||||
m_advancedFindWidget->setDocument(document);
|
||||
|
||||
if (m_sidebarWidget->isEmpty())
|
||||
@ -1109,6 +1109,7 @@ void PDFViewerMainWindow::setDocument(pdf::PDFModifiedDocument document)
|
||||
|
||||
void PDFViewerMainWindow::closeDocument()
|
||||
{
|
||||
m_signatures.clear();
|
||||
setDocument(pdf::PDFModifiedDocument());
|
||||
m_pdfDocument.reset();
|
||||
updateActionsAvailability();
|
||||
|
@ -158,6 +158,7 @@ private:
|
||||
pdf::PDFDocumentPointer document;
|
||||
QString errorMessage;
|
||||
pdf::PDFDocumentReader::Result result = pdf::PDFDocumentReader::Result::Cancelled;
|
||||
std::vector<pdf::PDFSignatureVerificationResult> signatures;
|
||||
};
|
||||
|
||||
Ui::PDFViewerMainWindow* ui;
|
||||
@ -179,6 +180,7 @@ private:
|
||||
QWinTaskbarButton* m_taskbarButton;
|
||||
QWinTaskbarProgress* m_progressTaskbarIndicator;
|
||||
PDFFileInfo m_fileInfo;
|
||||
std::vector<pdf::PDFSignatureVerificationResult> m_signatures;
|
||||
|
||||
QFuture<AsyncReadingResult> m_future;
|
||||
QFutureWatcher<AsyncReadingResult>* m_futureWatcher;
|
||||
|
101
PdfForQtViewer/resources/result-error.svg
Normal file
101
PdfForQtViewer/resources/result-error.svg
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="30mm"
|
||||
height="30mm"
|
||||
viewBox="0 0 30 30"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="result-error.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect831"
|
||||
is_visible="true" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="102.28993"
|
||||
inkscape:cy="113.44001"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2035"
|
||||
inkscape:window-x="-13"
|
||||
inkscape:window-y="-13"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Melka</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Vrstva 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-267)">
|
||||
<ellipse
|
||||
style="fill:#c80000;fill-opacity:1;stroke:none;stroke-width:1.13353121;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="path837"
|
||||
cx="14.991481"
|
||||
cy="282.01321"
|
||||
rx="14.859186"
|
||||
ry="14.835566" />
|
||||
<g
|
||||
aria-label="❌"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
id="text841">
|
||||
<path
|
||||
d="m 26.184298,273.67792 -8.458399,8.4708 8.458399,8.47081 -2.666504,2.6665 -8.470801,-8.4584 -8.4708004,8.4584 -2.6665038,-2.6665 8.4583982,-8.47081 -8.4583982,-8.4708 2.6665038,-2.6665 8.4708004,8.4584 8.470801,-8.4584 z"
|
||||
style="font-size:25.39999962px;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332"
|
||||
id="path2020"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
101
PdfForQtViewer/resources/result-information.svg
Normal file
101
PdfForQtViewer/resources/result-information.svg
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="30mm"
|
||||
height="30mm"
|
||||
viewBox="0 0 30 30"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="result-information.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect831"
|
||||
is_visible="true" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="142.64708"
|
||||
inkscape:cy="113.44001"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2035"
|
||||
inkscape:window-x="-13"
|
||||
inkscape:window-y="-13"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Melka</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Vrstva 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-267)">
|
||||
<ellipse
|
||||
style="fill:#0064e6;fill-opacity:1;stroke:none;stroke-width:1.13353121;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="path837"
|
||||
cx="14.991481"
|
||||
cy="282.01321"
|
||||
rx="14.859186"
|
||||
ry="14.835566" />
|
||||
<g
|
||||
aria-label="ℹ"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
id="text841">
|
||||
<path
|
||||
d="m 17.549903,291.45343 h -5.333008 v -13.30771 h 5.333008 z m 0.124023,-15.29209 h -5.581054 v -4.00596 h 5.581054 z"
|
||||
style="font-size:25.39999962px;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332"
|
||||
id="path843"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
101
PdfForQtViewer/resources/result-ok.svg
Normal file
101
PdfForQtViewer/resources/result-ok.svg
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="30mm"
|
||||
height="30mm"
|
||||
viewBox="0 0 30 30"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="result-ok.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect831"
|
||||
is_visible="true" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="102.28993"
|
||||
inkscape:cy="113.44001"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2035"
|
||||
inkscape:window-x="-13"
|
||||
inkscape:window-y="-13"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Melka</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Vrstva 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-267)">
|
||||
<ellipse
|
||||
style="fill:#00c800;fill-opacity:1;stroke:none;stroke-width:1.13353121;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="path837"
|
||||
cx="14.991481"
|
||||
cy="282.01321"
|
||||
rx="14.859186"
|
||||
ry="14.835566" />
|
||||
<g
|
||||
aria-label="✓"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
id="text841">
|
||||
<path
|
||||
d="m 6.6240342,286.2373 q 0,-0.39687 -0.099219,-0.69453 0,-0.89297 1.190625,-1.5875 0.79375,-0.39687 1.190625,-0.39687 0.4960937,0.0992 0.6945312,0.59531 0.5953126,1.38906 0.7937506,1.88516 0.198437,0.39687 0.396875,0.39687 0.198437,0 0.396875,-0.29765 3.373437,-5.95313 6.052343,-9.22735 2.083594,-2.48047 2.579688,-2.87734 1.5875,-1.19063 3.770312,-1.28985 l 0.09922,0.4961 q -1.686719,1.68672 -5.853906,7.54062 -4.067969,5.85391 -5.853906,9.22735 -0.396875,0.89297 -0.992188,1.0914 -0.297656,0.29766 -1.2898438,0.19844 -0.6945313,0.0992 -0.9921875,-0.19844 -0.2976563,-0.19843 -0.5953125,-0.79375 -0.9921875,-2.38125 -1.488282,-4.06797 z"
|
||||
style="font-size:25.39999962px;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332"
|
||||
id="path2605"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
101
PdfForQtViewer/resources/result-warning.svg
Normal file
101
PdfForQtViewer/resources/result-warning.svg
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="30mm"
|
||||
height="30mm"
|
||||
viewBox="0 0 30 30"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="result-warning.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect831"
|
||||
is_visible="true" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="102.28993"
|
||||
inkscape:cy="113.44001"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2035"
|
||||
inkscape:window-x="-13"
|
||||
inkscape:window-y="-13"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Melka</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Vrstva 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-267)">
|
||||
<ellipse
|
||||
style="fill:#dcaf00;fill-opacity:1;stroke:none;stroke-width:1.13353121;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="path837"
|
||||
cx="14.991481"
|
||||
cy="282.01321"
|
||||
rx="14.859186"
|
||||
ry="14.835566" />
|
||||
<g
|
||||
aria-label="⚠"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25.39999962px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||
id="text841">
|
||||
<path
|
||||
d="M 25.20215,290.10568 H 5.0359398 q -0.2108399,0 -0.3844727,-0.12403 -0.1612304,-0.12402 -0.2604492,-0.29765 -0.099219,-0.17364 -0.099219,-0.37207 0,-0.18604 0.099219,-0.38448 L 14.461721,271.04327 q 0.09922,-0.17363 0.272851,-0.26045 0.173633,-0.0868 0.372071,-0.0868 0.198437,0 0.37207,0.0868 0.173633,0.0868 0.272852,0.26045 l 10.095507,17.88418 q 0.09922,0.19844 0.09922,0.38448 0,0.19843 -0.09922,0.37207 -0.09922,0.17363 -0.272851,0.29765 -0.161231,0.12403 -0.372071,0.12403 z M 6.3257835,288.51818 H 23.887502 l -8.780859,-15.55254 z m 9.9342775,-4.51446 h -2.306836 v -6.8833 h 2.306836 z m 0.347265,2.25723 q 0,0.32246 -0.124023,0.59531 -0.111621,0.27285 -0.322461,0.48369 -0.198438,0.19844 -0.471289,0.32246 -0.272852,0.11163 -0.58291,0.11163 -0.310059,0 -0.58291,-0.11163 -0.272852,-0.12402 -0.471289,-0.32246 -0.198438,-0.21084 -0.310059,-0.48369 -0.111621,-0.27285 -0.111621,-0.59531 0,-0.31006 0.111621,-0.59531 0.111621,-0.28526 0.310059,-0.48369 0.198437,-0.21084 0.471289,-0.33487 0.272851,-0.12402 0.58291,-0.12402 0.310058,0 0.58291,0.12402 0.272851,0.12403 0.471289,0.33487 0.21084,0.19843 0.322461,0.48369 0.124023,0.28525 0.124023,0.59531 z"
|
||||
style="font-size:25.39999962px;fill:#ffffff;fill-opacity:1;stroke-width:0.26458332"
|
||||
id="path1445"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
Loading…
x
Reference in New Issue
Block a user