mobile: Add Signature Viewing UI

Move a few files from part/ to gui/ since they are also used by the
mobile/ frontend
remotes/origin/work/fhek/foreground_background_text
Albert Astals Cid 4 years ago
parent 28e362b6a1
commit 4cd6bfd30e
  1. 14
      CMakeLists.txt
  2. 2
      generators/kimgio/CMakeLists.txt
  3. 2
      generators/kimgio/tests/kimgiotest.cpp
  4. 163
      gui/certificatemodel.cpp
  5. 40
      gui/certificatemodel.h
  6. 0
      gui/debug_ui.cpp
  7. 0
      gui/debug_ui.h
  8. 0
      gui/guiutils.cpp
  9. 0
      gui/guiutils.h
  10. 0
      gui/pagepainter.cpp
  11. 0
      gui/pagepainter.h
  12. 0
      gui/priorities.h
  13. 144
      gui/signatureguiutils.cpp
  14. 11
      gui/signatureguiutils.h
  15. 94
      gui/signaturemodel.cpp
  16. 28
      gui/signaturemodel.h
  17. 8
      gui/tocmodel.cpp
  18. 3
      gui/tocmodel.h
  19. 3
      mobile/app/app.qrc
  20. 173
      mobile/app/package/contents/ui/CertificateViewerDialog.qml
  21. 28
      mobile/app/package/contents/ui/OkularDrawer.qml
  22. 177
      mobile/app/package/contents/ui/SignaturePropertiesDialog.qml
  23. 64
      mobile/app/package/contents/ui/Signatures.qml
  24. 11
      mobile/components/CMakeLists.txt
  25. 25
      mobile/components/documentitem.cpp
  26. 9
      mobile/components/documentitem.h
  27. 2
      mobile/components/okularplugin.cpp
  28. 4
      mobile/components/pageitem.cpp
  29. 2
      part/annotationactionhandler.cpp
  30. 2
      part/annotationmodel.cpp
  31. 2
      part/annotationpopup.cpp
  32. 2
      part/annotationproxymodels.cpp
  33. 4
      part/annotationwidgets.cpp
  34. 3
      part/bookmarklist.cpp
  35. 126
      part/certificateviewer.cpp
  36. 26
      part/certificateviewer.h
  37. 2
      part/colormodemenu.cpp
  38. 2
      part/drawingtoolactions.cpp
  39. 2
      part/embeddedfilesdialog.cpp
  40. 2
      part/fileprinterpreview.cpp
  41. 6
      part/formwidgets.cpp
  42. 2
      part/latexrenderer.cpp
  43. 4
      part/magnifierview.cpp
  44. 5
      part/pageitemdelegate.cpp
  45. 3
      part/pageitemdelegate.h
  46. 8
      part/pageview.cpp
  47. 10
      part/pageviewannotator.cpp
  48. 2
      part/pageviewmouseannotation.cpp
  49. 59
      part/part.cpp
  50. 8
      part/presentationwidget.cpp
  51. 6
      part/signaturepanel.cpp
  52. 127
      part/signaturepartutils.cpp
  53. 24
      part/signaturepartutils.h
  54. 19
      part/signaturepropertiesdialog.cpp
  55. 4
      part/thumbnaillist.cpp
  56. 2
      part/toc.cpp

@ -374,6 +374,13 @@ install(FILES core/okularGenerator.desktop DESTINATION ${KDE_INSTALL_KSERVICETYP
if(BUILD_DESKTOP)
# okularpart
set(okularpart_SRCS
gui/certificatemodel.cpp
gui/debug_ui.cpp
gui/guiutils.cpp
gui/pagepainter.cpp
gui/signatureguiutils.cpp
gui/signaturemodel.cpp
gui/tocmodel.cpp
part/preferencesdialog.cpp
part/dlgaccessibility.cpp
part/dlgdebug.cpp
@ -404,18 +411,15 @@ if(BUILD_DESKTOP)
part/certificateviewer.cpp
part/colormodemenu.cpp
part/cursorwraphelper.cpp
part/debug_ui.cpp
part/drawingtoolactions.cpp
part/fileprinterpreview.cpp
part/findbar.cpp
part/formwidgets.cpp
part/guiutils.cpp
part/ktreeviewsearchline.cpp
part/latexrenderer.cpp
part/minibar.cpp
part/okmenutitle.cpp
part/pageitemdelegate.cpp
part/pagepainter.cpp
part/pagesizelabel.cpp
part/pageviewannotator.cpp
part/pageviewmouseannotation.cpp
@ -433,13 +437,11 @@ if(BUILD_DESKTOP)
part/snapshottaker.cpp
part/thumbnaillist.cpp
part/toc.cpp
part/tocmodel.cpp
part/toggleactionmenu.cpp
part/videowidget.cpp
part/layers.cpp
part/signatureguiutils.cpp
part/signaturepartutils.cpp
part/signaturepropertiesdialog.cpp
part/signaturemodel.cpp
part/signaturepanel.cpp
)

@ -13,7 +13,7 @@ endif()
if(BUILD_TESTING AND BUILD_DESKTOP AND KF5KExiv2_FOUND)
add_definitions( -DKDESRCDIR="${CMAKE_CURRENT_SOURCE_DIR}/" )
set( kimgiotest_SRCS tests/kimgiotest.cpp ${CMAKE_SOURCE_DIR}/part/pagepainter.cpp ${CMAKE_SOURCE_DIR}/part/guiutils.cpp ${CMAKE_SOURCE_DIR}/part/debug_ui.cpp )
set( kimgiotest_SRCS tests/kimgiotest.cpp ${CMAKE_SOURCE_DIR}/gui/pagepainter.cpp ${CMAKE_SOURCE_DIR}/gui/guiutils.cpp ${CMAKE_SOURCE_DIR}/gui/debug_ui.cpp )
ecm_add_test(${kimgiotest_SRCS} TEST_NAME "kimgiotest" LINK_LIBRARIES okularcore okularpart Qt5::Svg Qt5::Test)
target_compile_definitions(kimgiotest PRIVATE -DGENERATOR_PATH="$<TARGET_FILE:okularGenerator_kimgio>")
endif()

@ -9,7 +9,7 @@
#include <core/observer.h>
#include <core/page.h>
#include <part/pagepainter.h>
#include <gui/pagepainter.h>
#include <QTest>

@ -0,0 +1,163 @@
/*
SPDX-FileCopyrightText: 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "certificatemodel.h"
#include "signatureguiutils.h"
#include <KLocalizedString>
#include <QCryptographicHash>
#include <QDebug>
#include <QFile>
#include <QUrl>
CertificateModel::CertificateModel(const Okular::CertificateInfo &certInfo, QObject *parent)
: QAbstractTableModel(parent)
, m_certificateInfo(certInfo)
{
m_certificateProperties = {Version, SerialNumber, Issuer, IssuedOn, ExpiresOn, Subject, PublicKey, KeyUsage};
}
int CertificateModel::columnCount(const QModelIndex &) const
{
return 2;
}
int CertificateModel::rowCount(const QModelIndex &) const
{
return m_certificateProperties.size();
}
static QString propertyVisibleName(CertificateModel::Property p)
{
switch (p) {
case CertificateModel::Version:
return i18n("Version");
case CertificateModel::SerialNumber:
return i18n("Serial Number");
case CertificateModel::Issuer:
return i18n("Issuer");
case CertificateModel::IssuedOn:
return i18n("Issued On");
case CertificateModel::ExpiresOn:
return i18n("Expires On");
case CertificateModel::Subject:
return i18nc("The person/company that made the signature", "Subject");
case CertificateModel::PublicKey:
return i18n("Public Key");
case CertificateModel::KeyUsage:
return i18n("Key Usage");
case CertificateModel::IssuerName:
case CertificateModel::IssuerEmail:
case CertificateModel::IssuerOrganization:
case CertificateModel::SubjectName:
case CertificateModel::SubjectEmail:
case CertificateModel::SubjectOrganization:
case CertificateModel::Sha1:
case CertificateModel::Sha256:
Q_ASSERT(false);
qWarning() << "Unimplemented";
}
return QString();
}
QString CertificateModel::propertyVisibleValue(CertificateModel::Property p) const
{
switch (p) {
case CertificateModel::Version:
return i18n("V%1", QString::number(m_certificateInfo.version()));
case CertificateModel::SerialNumber:
return m_certificateInfo.serialNumber().toHex(' ');
case CertificateModel::Issuer:
return m_certificateInfo.issuerInfo(Okular::CertificateInfo::DistinguishedName);
case CertificateModel::IssuedOn:
return m_certificateInfo.validityStart().toString(Qt::DefaultLocaleLongDate);
case CertificateModel::ExpiresOn:
return m_certificateInfo.validityEnd().toString(Qt::DefaultLocaleLongDate);
case CertificateModel::Subject:
return m_certificateInfo.subjectInfo(Okular::CertificateInfo::DistinguishedName);
case CertificateModel::PublicKey:
return i18n("%1 (%2 bits)", SignatureGuiUtils::getReadablePublicKeyType(m_certificateInfo.publicKeyType()), m_certificateInfo.publicKeyStrength());
case CertificateModel::KeyUsage:
return SignatureGuiUtils::getReadableKeyUsageCommaSeparated(m_certificateInfo.keyUsageExtensions());
case CertificateModel::IssuerName:
return m_certificateInfo.issuerInfo(Okular::CertificateInfo::CommonName);
case CertificateModel::IssuerEmail:
return m_certificateInfo.issuerInfo(Okular::CertificateInfo::EmailAddress);
case CertificateModel::IssuerOrganization:
return m_certificateInfo.issuerInfo(Okular::CertificateInfo::Organization);
case CertificateModel::SubjectName:
return m_certificateInfo.subjectInfo(Okular::CertificateInfo::CommonName);
case CertificateModel::SubjectEmail:
return m_certificateInfo.subjectInfo(Okular::CertificateInfo::EmailAddress);
case CertificateModel::SubjectOrganization:
return m_certificateInfo.subjectInfo(Okular::CertificateInfo::Organization);
case CertificateModel::Sha1:
return QCryptographicHash::hash(m_certificateInfo.certificateData(), QCryptographicHash::Sha1).toHex(' ');
case CertificateModel::Sha256:
return QCryptographicHash::hash(m_certificateInfo.certificateData(), QCryptographicHash::Sha256).toHex(' ');
}
return QString();
}
QVariant CertificateModel::data(const QModelIndex &index, int role) const
{
const int row = index.row();
if (!index.isValid() || row < 0 || row >= m_certificateProperties.count())
return QVariant();
switch (role) {
case Qt::DisplayRole:
case Qt::ToolTipRole:
switch (index.column()) {
case 0:
return propertyVisibleName(m_certificateProperties[row]);
case 1:
return propertyVisibleValue(m_certificateProperties[row]);
default:
return QString();
}
case PropertyKeyRole:
return m_certificateProperties[row];
case PropertyVisibleValueRole:
return propertyVisibleValue(m_certificateProperties[row]);
}
return QVariant();
}
QVariant CertificateModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::TextAlignmentRole)
return QVariant(Qt::AlignLeft);
if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
return QVariant();
switch (section) {
case 0:
return i18n("Property");
case 1:
return i18n("Value");
default:
return QVariant();
}
}
bool CertificateModel::exportCertificateTo(const QString &path)
{
const QUrl url = QUrl::fromUserInput(path);
if (!url.isLocalFile()) {
return false;
}
QFile targetFile(url.toLocalFile());
if (!targetFile.open(QIODevice::WriteOnly)) {
return false;
}
const QByteArray data = m_certificateInfo.certificateData();
return targetFile.write(data) == data.size();
}

@ -0,0 +1,40 @@
/*
SPDX-FileCopyrightText: 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OKULAR_CERTIFICATEMODEL_H
#define OKULAR_CERTIFICATEMODEL_H
#include <QAbstractTableModel>
#include <QVector>
#include "core/signatureutils.h"
class CertificateModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit CertificateModel(const Okular::CertificateInfo &certInfo, QObject *parent = nullptr);
enum { PropertyKeyRole = Qt::UserRole, PropertyVisibleValueRole };
enum Property { Version, SerialNumber, Issuer, IssuedOn, ExpiresOn, Subject, PublicKey, KeyUsage, IssuerName, IssuerEmail, IssuerOrganization, SubjectName, SubjectEmail, SubjectOrganization, Sha1, Sha256 };
Q_ENUM(Property)
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
Q_INVOKABLE QString propertyVisibleValue(CertificateModel::Property p) const;
Q_INVOKABLE bool exportCertificateTo(const QString &path);
private:
QVector<Property> m_certificateProperties;
const Okular::CertificateInfo &m_certificateInfo;
};
#endif

@ -6,22 +6,15 @@
#include "signatureguiutils.h"
#include <QFileDialog>
#include <QFileInfo>
#include <QInputDialog>
#include <QMimeDatabase>
#include <KLocalizedString>
#include <KMessageBox>
#include "core/document.h"
#include "core/form.h"
#include "core/page.h"
#include "pageview.h"
namespace SignatureGuiUtils
{
QVector<const Okular::FormFieldSignature *> getSignatureFormFields(Okular::Document *doc)
QVector<const Okular::FormFieldSignature *> getSignatureFormFields(const Okular::Document *doc)
{
uint curPage = 0;
const uint endPage = doc->pages() - 1;
@ -152,106 +145,65 @@ QString getReadableKeyUsageNewLineSeparated(Okular::CertificateInfo::KeyUsageExt
return getReadableKeyUsage(kuExtensions, QStringLiteral("\n"));
}
std::unique_ptr<Okular::CertificateInfo> getCertificateAndPasswordForSigning(PageView *pageView, Okular::Document *doc, QString *password, QString *documentPassword)
QString getReadableModificationSummary(const Okular::SignatureInfo &signatureInfo)
{
const Okular::CertificateStore *certStore = doc->certificateStore();
bool userCancelled, nonDateValidCerts;
QList<Okular::CertificateInfo *> certs = certStore->signingCertificatesForNow(&userCancelled, &nonDateValidCerts);
if (userCancelled) {
return nullptr;
}
if (certs.isEmpty()) {
pageView->showNoSigningCertificatesDialog(nonDateValidCerts);
return nullptr;
}
QStringList items;
QHash<QString, Okular::CertificateInfo *> nickToCert;
for (auto cert : qAsConst(certs)) {
items.append(cert->nickName());
nickToCert[cert->nickName()] = cert;
}
bool resok = false;
const QString certNicknameToUse = QInputDialog::getItem(pageView, i18n("Select certificate to sign with"), i18n("Certificates:"), items, 0, false, &resok);
if (!resok) {
qDeleteAll(certs);
return nullptr;
}
// I could not find any case in which i need to enter a password to use the certificate, seems that once you unlcok the firefox/NSS database
// you don't need a password anymore, but still there's code to do that in NSS so we have code to ask for it if needed. What we do is
// ask if the empty password is fine, if it is we don't ask the user anything, if it's not, we ask for a password
Okular::CertificateInfo *cert = nickToCert.value(certNicknameToUse);
bool passok = cert->checkPassword(*password);
while (!passok) {
const QString title = i18n("Enter password (if any) to unlock certificate: %1", certNicknameToUse);
bool ok;
*password = QInputDialog::getText(pageView, i18n("Enter certificate password"), title, QLineEdit::Password, QString(), &ok);
if (ok) {
passok = cert->checkPassword(*password);
const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus();
// signature validation status
if (signatureStatus == Okular::SignatureInfo::SignatureValid) {
if (signatureInfo.signsTotalDocument()) {
return i18n("The document has not been modified since it was signed.");
} else {
passok = false;
break;
return i18n(
"The revision of the document that was covered by this signature has not been modified;\n"
"however there have been subsequent changes to the document.");
}
} else if (signatureStatus == Okular::SignatureInfo::SignatureDigestMismatch) {
return i18n("The document has been modified in a way not permitted by a previous signer.");
} else {
return i18n("The document integrity verification could not be completed.");
}
if (doc->metaData(QStringLiteral("DocumentHasPassword")).toString() == QLatin1String("yes")) {
*documentPassword = QInputDialog::getText(pageView, i18n("Enter document password"), i18n("Enter document password"), QLineEdit::Password, QString(), &passok);
}
if (passok) {
certs.removeOne(cert);
}
qDeleteAll(certs);
return passok ? std::unique_ptr<Okular::CertificateInfo>(cert) : std::unique_ptr<Okular::CertificateInfo>();
}
QString getFileNameForNewSignedFile(PageView *pageView, Okular::Document *doc)
{
QMimeDatabase db;
const QString typeName = doc->documentInfo().get(Okular::DocumentInfo::MimeType);
const QMimeType mimeType = db.mimeTypeForName(typeName);
const QString mimeTypeFilter = i18nc("File type name and pattern", "%1 (%2)", mimeType.comment(), mimeType.globPatterns().join(QLatin1Char(' ')));
const QUrl currentFileUrl = doc->currentDocument();
const QFileInfo currentFileInfo(currentFileUrl.fileName());
const QString localFilePathIfAny = currentFileUrl.isLocalFile() ? QFileInfo(currentFileUrl.path()).canonicalPath() + QLatin1Char('/') : QString();
const QString newFileName =
localFilePathIfAny + i18nc("Used when suggesting a new name for a digitally signed file. %1 is the old file name and %2 it's extension", "%1_signed.%2", currentFileInfo.baseName(), currentFileInfo.completeSuffix());
return QFileDialog::getSaveFileName(pageView, i18n("Save Signed File As"), newFileName, mimeTypeFilter);
}
void signUnsignedSignature(const Okular::FormFieldSignature *form, PageView *pageView, Okular::Document *doc)
std::pair<KMessageWidget::MessageType, QString> documentSignatureMessageWidgetText(const Okular::Document *doc)
{
Q_ASSERT(form && form->signatureType() == Okular::FormFieldSignature::UnsignedSignature);
QString password, documentPassword;
const std::unique_ptr<Okular::CertificateInfo> cert = SignatureGuiUtils::getCertificateAndPasswordForSigning(pageView, doc, &password, &documentPassword);
if (!cert) {
return;
const uint numPages = doc->pages();
bool isDigitallySigned = false;
for (uint i = 0; i < numPages; i++) {
const QLinkedList<Okular::FormField *> formFields = doc->page(i)->formFields();
for (const Okular::FormField *f : formFields) {
if (f->type() == Okular::FormField::FormSignature)
isDigitallySigned = true;
}
}
Okular::NewSignatureData data;
data.setCertNickname(cert->nickName());
data.setCertSubjectCommonName(cert->subjectInfo(Okular::CertificateInfo::CommonName));
data.setPassword(password);
data.setDocumentPassword(documentPassword);
password.clear();
documentPassword.clear();
const QString newFilePath = SignatureGuiUtils::getFileNameForNewSignedFile(pageView, doc);
if (isDigitallySigned) {
const QVector<const Okular::FormFieldSignature *> signatureFormFields = SignatureGuiUtils::getSignatureFormFields(doc);
bool allSignaturesValid = true;
bool anySignatureUnsigned = false;
for (const Okular::FormFieldSignature *signature : signatureFormFields) {
if (signature->signatureType() == Okular::FormFieldSignature::UnsignedSignature) {
anySignatureUnsigned = true;
} else {
const Okular::SignatureInfo &info = signature->signatureInfo();
if (info.signatureStatus() != Okular::SignatureInfo::SignatureValid) {
allSignaturesValid = false;
}
}
}
if (!newFilePath.isEmpty()) {
const bool success = form->sign(data, newFilePath);
if (success) {
emit pageView->requestOpenFile(newFilePath, form->page()->number() + 1);
if (anySignatureUnsigned) {
return {KMessageWidget::Information, i18n("This document has unsigned signature fields.")};
} else if (allSignaturesValid) {
if (signatureFormFields.last()->signatureInfo().signsTotalDocument()) {
return {KMessageWidget::Information, i18n("This document is digitally signed.")};
} else {
return {KMessageWidget::Warning, i18n("This document is digitally signed. There have been changes since last signed.")};
}
} else {
KMessageBox::error(pageView, i18nc("%1 is a file path", "Could not sign. Invalid certificate password or could not write to '%1'", newFilePath));
return {KMessageWidget::Warning, i18n("This document is digitally signed. Some of the signatures could not be validated properly.")};
}
}
return {KMessageWidget::Information, QString()};
}
}

@ -11,9 +11,7 @@
#include "core/signatureutils.h"
#include <memory>
class PageView;
#include <KMessageWidget>
namespace Okular
{
@ -26,17 +24,16 @@ namespace SignatureGuiUtils
/**
* Returns a vector containing signature form fields sorted by date (last is newer).
*/
QVector<const Okular::FormFieldSignature *> getSignatureFormFields(Okular::Document *doc);
QVector<const Okular::FormFieldSignature *> getSignatureFormFields(const Okular::Document *doc);
QString getReadableSignatureStatus(Okular::SignatureInfo::SignatureStatus sigStatus);
QString getReadableCertStatus(Okular::SignatureInfo::CertificateStatus certStatus);
QString getReadableHashAlgorithm(Okular::SignatureInfo::HashAlgorithm hashAlg);
QString getReadablePublicKeyType(Okular::CertificateInfo::PublicKeyType type);
QString getReadableKeyUsageCommaSeparated(Okular::CertificateInfo::KeyUsageExtensions kuExtensions);
QString getReadableKeyUsageNewLineSeparated(Okular::CertificateInfo::KeyUsageExtensions kuExtensions);
QString getReadableModificationSummary(const Okular::SignatureInfo &signatureInfo);
std::unique_ptr<Okular::CertificateInfo> getCertificateAndPasswordForSigning(PageView *pageView, Okular::Document *doc, QString *password, QString *documentPassword);
QString getFileNameForNewSignedFile(PageView *pageView, Okular::Document *doc);
void signUnsignedSignature(const Okular::FormFieldSignature *form, PageView *pageView, Okular::Document *doc);
std::pair<KMessageWidget::MessageType, QString> documentSignatureMessageWidgetText(const Okular::Document *doc);
}
#endif

@ -5,10 +5,13 @@
*/
#include "signaturemodel.h"
#include "certificatemodel.h"
#include "signatureguiutils.h"
#include <KLocalizedString>
#include <QFile>
#include <QIcon>
#include <QPointer>
#include <QVector>
@ -73,6 +76,7 @@ public:
SignatureModel *q;
SignatureItem *root;
QPointer<Okular::Document> document;
mutable QHash<const Okular::FormFieldSignature *, CertificateModel *> certificateForForm;
};
SignatureModelPrivate::SignatureModelPrivate(SignatureModel *qq)
@ -83,6 +87,7 @@ SignatureModelPrivate::SignatureModelPrivate(SignatureModel *qq)
SignatureModelPrivate::~SignatureModelPrivate()
{
qDeleteAll(certificateForForm);
delete root;
}
@ -120,6 +125,7 @@ void SignatureModelPrivate::notifySetup(const QVector<Okular::Page *> &pages, in
if (pages.isEmpty()) {
q->endResetModel();
emit q->countChanged();
return;
}
@ -163,6 +169,7 @@ void SignatureModelPrivate::notifySetup(const QVector<Okular::Page *> &pages, in
}
}
q->endResetModel();
emit q->countChanged();
}
QModelIndex SignatureModelPrivate::indexForItem(SignatureItem *item) const
@ -206,13 +213,15 @@ QVariant SignatureModel::data(const QModelIndex &index, int role) const
if (item == d->root)
return QVariant();
const Okular::FormFieldSignature *form = item->form ? item->form : item->parent->form;
switch (role) {
case Qt::DisplayRole:
case Qt::ToolTipRole:
return item->displayString;
case Qt::DecorationRole:
if (item->type == SignatureItem::RevisionInfo) {
const Okular::SignatureInfo::SignatureStatus signatureStatus = item->form->signatureInfo().signatureStatus();
const Okular::SignatureInfo::SignatureStatus signatureStatus = form->signatureInfo().signatureStatus();
switch (signatureStatus) {
case Okular::SignatureInfo::SignatureValid:
return QIcon::fromTheme(QStringLiteral("dialog-ok"));
@ -226,9 +235,42 @@ QVariant SignatureModel::data(const QModelIndex &index, int role) const
}
return QIcon();
case FormRole:
return QVariant::fromValue<const Okular::FormFieldSignature *>(item->form);
return QVariant::fromValue<const Okular::FormFieldSignature *>(form);
case PageRole:
return item->page;
case ReadableStatusRole:
return SignatureGuiUtils::getReadableSignatureStatus(form->signatureInfo().signatureStatus());
case ReadableModificationSummary:
return SignatureGuiUtils::getReadableModificationSummary(form->signatureInfo());
case SignerNameRole:
return form->signatureInfo().signerName();
case SigningTimeRole:
return form->signatureInfo().signingTime().toString(Qt::DefaultLocaleLongDate);
case SigningLocationRole:
return form->signatureInfo().location();
case SigningReasonRole:
return form->signatureInfo().reason();
case CertificateModelRole: {
auto it = d->certificateForForm.constFind(form);
if (it != d->certificateForForm.constEnd()) {
return QVariant::fromValue(it.value());
}
CertificateModel *cm = new CertificateModel(form->signatureInfo().certificateInfo());
d->certificateForForm.insert(form, cm);
return QVariant::fromValue(cm);
}
case SignatureRevisionIndexRole: {
const Okular::SignatureInfo &signatureInfo = form->signatureInfo();
const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus();
if (signatureStatus != Okular::SignatureInfo::SignatureStatusUnknown && !signatureInfo.signsTotalDocument()) {
const QVector<const Okular::FormFieldSignature *> signatureFormFields = SignatureGuiUtils::getSignatureFormFields(d->document);
return signatureFormFields.indexOf(form);
}
return -1;
}
case IsUnsignedSignatureRole: {
return form->signatureType() == Okular::FormFieldSignature::UnsignedSignature;
}
}
return QVariant();
@ -276,4 +318,52 @@ int SignatureModel::rowCount(const QModelIndex &parent) const
return item->children.count();
}
QHash<int, QByteArray> SignatureModel::roleNames() const
{
static QHash<int, QByteArray> res;
if (res.isEmpty()) {
res = QAbstractItemModel::roleNames();
res.insert(FormRole, "signatureFormField");
res.insert(PageRole, "page");
res.insert(ReadableStatusRole, "readableStatus");
res.insert(ReadableModificationSummary, "readableModificationSummary");
res.insert(SignerNameRole, "signerName");
res.insert(SigningTimeRole, "signingTime");
res.insert(SigningLocationRole, "signingLocation");
res.insert(SigningReasonRole, "signingReason");
res.insert(CertificateModelRole, "certificateModel");
res.insert(SignatureRevisionIndexRole, "signatureRevisionIndex");
res.insert(IsUnsignedSignatureRole, "isUnsignedSignature");
}
return res;
}
bool SignatureModel::saveSignedVersion(int signatureRevisionIndex, const QUrl &filePath) const
{
Q_D(const SignatureModel);
const QVector<const Okular::FormFieldSignature *> signatureFormFields = SignatureGuiUtils::getSignatureFormFields(d->document);
if (signatureRevisionIndex < 0 || signatureRevisionIndex >= signatureFormFields.count()) {
qWarning() << "Invalid signatureRevisionIndex given to saveSignedVersion";
return false;
}
const Okular::FormFieldSignature *signature = signatureFormFields[signatureRevisionIndex];
const QByteArray data = d->document->requestSignedRevisionData(signature->signatureInfo());
if (!filePath.isLocalFile()) {
qWarning() << "Unexpected non local path given to saveSignedVersion" << filePath;
return false;
}
QFile f(filePath.toLocalFile());
if (!f.open(QIODevice::WriteOnly)) {
qWarning() << "Failed to open path for writing in saveSignedVersion" << filePath;
return false;
}
if (f.write(data) != data.size()) {
qWarning() << "Failed to write all data in saveSignedVersion" << filePath;
return false;
}
return true;
}
#include "moc_signaturemodel.cpp"

@ -20,8 +20,22 @@ class SignatureModel : public QAbstractItemModel
{
Q_OBJECT
Q_PROPERTY(int count READ count NOTIFY countChanged)
public:
enum { FormRole = Qt::UserRole + 1000, PageRole };
enum {
FormRole = Qt::UserRole + 1000,
PageRole,
ReadableStatusRole,
ReadableModificationSummary,
SignerNameRole,
SigningTimeRole,
SigningLocationRole,
SigningReasonRole,
CertificateModelRole,
SignatureRevisionIndexRole,
IsUnsignedSignatureRole
};
explicit SignatureModel(Okular::Document *doc, QObject *parent = nullptr);
~SignatureModel() override;
@ -33,6 +47,18 @@ public:
QModelIndex parent(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int count() const
{
return rowCount();
}
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE bool saveSignedVersion(int signatureRevisionIndex, const QUrl &filePath) const;
Q_SIGNALS:
void countChanged();
private:
Q_DECLARE_PRIVATE(SignatureModel)
QScopedPointer<SignatureModelPrivate> d_ptr;

@ -189,8 +189,8 @@ TOCModel::~TOCModel()
QHash<int, QByteArray> TOCModel::roleNames() const
{
QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
roles[(int)PageItemDelegate::PageRole] = "page";
roles[(int)PageItemDelegate::PageLabelRole] = "pageLabel";
roles[PageRole] = "page";
roles[PageLabelRole] = "pageLabel";
roles[HighlightRole] = "highlight";
roles[HighlightedParentRole] = "highlightedParent";
return roles;
@ -240,11 +240,11 @@ QVariant TOCModel::data(const QModelIndex &index, int role) const
break;
case HighlightRole:
return item->highlight;
case PageItemDelegate::PageRole:
case PageRole:
if (item->viewport.isValid())
return item->viewport.pageNumber + 1;
break;
case PageItemDelegate::PageLabelRole:
case PageLabelRole:
if (item->viewport.isValid() && item->viewport.pageNumber < int(d->document->pages()))
return d->document->page(item->viewport.pageNumber)->label();
break;

@ -7,7 +7,6 @@
#ifndef TOCMODEL_H
#define TOCMODEL_H
#include "pageitemdelegate.h"
#include <QAbstractItemModel>
#include <QVector>
@ -29,7 +28,7 @@ class TOCModel : public QAbstractItemModel
Q_PROPERTY(int count READ count NOTIFY countChanged)
public:
enum Roles { HighlightRole = PageItemDelegate::PageLabelRole + 1, HighlightedParentRole };
enum Roles { PageRole = 0x000f0001, PageLabelRole, HighlightRole, HighlightedParentRole };
explicit TOCModel(Okular::Document *document, QObject *parent = nullptr);
~TOCModel() override;

@ -1,5 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>package/contents/ui/CertificateViewerDialog.qml</file>
<file>package/contents/ui/Bookmarks.qml</file>
<file>package/contents/ui/main.qml</file>
<file>package/contents/ui/MainView.qml</file>
@ -9,5 +10,7 @@
<file>package/contents/ui/ThumbnailsBase.qml</file>
<file>package/contents/ui/TreeItem.qml</file>
<file>package/contents/ui/TreeViewDecoration.qml</file>
<file>package/contents/ui/Signatures.qml</file>
<file>package/contents/ui/SignaturePropertiesDialog.qml</file>
</qresource>
</RCC>

@ -0,0 +1,173 @@
/*
* SPDX-FileCopyrightText: 2022 Albert Astals Cid <aacid@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Dialogs 1.3 as QQD
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.17 as Kirigami
import org.kde.okular 2.0
Kirigami.OverlaySheet
{
id: root
property var certificateModel
title: i18n("Certificate Viewer")
ColumnLayout {
// Without this the width is unreasonably narrow, potentially
// https://invent.kde.org/frameworks/kirigami/-/merge_requests/487 fixes it
// check when a kirigami with that is required as minimum version
Layout.preferredWidth: Math.min(Window.window.width, 360)
QQC2.GroupBox {
Layout.fillWidth: true
title: i18n("Issued By")
Kirigami.FormLayout {
width: parent.width
QQC2.Label {
Kirigami.FormData.label: i18n("Common Name:")
text: certificateModel.propertyVisibleValue(CertificateModel.IssuerName)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
Kirigami.FormData.label: i18n("EMail:")
text: certificateModel.propertyVisibleValue(CertificateModel.IssuerEmail)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
Kirigami.FormData.label: i18n("Organization:")
text: certificateModel.propertyVisibleValue(CertificateModel.IssuerOrganization)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
}
}
QQC2.GroupBox {
Layout.fillWidth: true
title: i18n("Issued To")
Kirigami.FormLayout {
width: parent.width
QQC2.Label {
Kirigami.FormData.label: i18n("Common Name:")
text: certificateModel.propertyVisibleValue(CertificateModel.SubjectName)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
Kirigami.FormData.label: i18n("EMail:")
text: certificateModel.propertyVisibleValue(CertificateModel.SubjectEmail)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
Kirigami.FormData.label: i18n("Organization:")
text: certificateModel.propertyVisibleValue(CertificateModel.SubjectOrganization)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
}
}
QQC2.GroupBox {
Layout.fillWidth: true
title: i18n("Validity")
Kirigami.FormLayout {
width: parent.width
QQC2.Label {
Kirigami.FormData.label: i18n("Issued On:")
text: certificateModel.propertyVisibleValue(CertificateModel.IssuedOn)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
Kirigami.FormData.label: i18n("Expires On:")
text: certificateModel.propertyVisibleValue(CertificateModel.ExpiresOn)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
}
}
QQC2.GroupBox {
Layout.fillWidth: true
title: i18n("Fingerprints")
Kirigami.FormLayout {
width: parent.width
QQC2.Label {
Kirigami.FormData.label: i18n("SHA-1 Fingerprint:")
text: certificateModel.propertyVisibleValue(CertificateModel.Sha1)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
Kirigami.FormData.label: i18n("SHA-256 Fingerprint:")
text: certificateModel.propertyVisibleValue(CertificateModel.Sha256)
wrapMode: Text.Wrap
Layout.fillWidth: true
}
}
}
QQC2.DialogButtonBox {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
QQC2.Button {
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.ActionRole
text: i18n("Export...")
onClicked: fileDialog.open()
}
QQC2.Button {
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.DestructiveRole
text: i18n("Close")
icon.name: "dialog-close"
onClicked: root.close()
}
}
QQD.FileDialog {
id: fileDialog
nameFilters: i18n("Certificate File (*.cer)")
folder: "file://" + userPaths.documents
selectExisting: false
onAccepted: {
if (!certificateModel.exportCertificateTo(fileDialog.fileUrl)) {
errorDialog.open();
}
}
}
// TODO Use Kirigami.PromptDialog when we depend on KF >= 5.89
// this way we can probably remove that ridiculous z value
QQC2.Dialog {
id: errorDialog
z: 200
title: i18n("Error")
contentItem: QQC2.Label {
text: i18n("Could not export the certificate.")
}
standardButtons: QQC2.Dialog.Ok
onAccepted: close();
}
}
}

@ -12,6 +12,8 @@ import QtQuick.Layouts 1.15
Kirigami.OverlayDrawer {
id: root
bottomPadding: 0
topPadding: 0
leftPadding: 0
@ -91,6 +93,32 @@ Kirigami.OverlayDrawer {
}
QQC2.ButtonGroup.group: tabPositionGroup
}
QQC2.ToolButton {
id: signatyresButton
enabled: documentItem.signaturesModel.count > 0
text: tabsToolbar.width > Kirigami.Units.gridUnit * 30 ? i18n("Signatures") : ""
icon.name: "application-pkcs7-signature"
checkable: true
flat: false
onCheckedChanged: {
if (checked) {
pageStack.replace(signaturesComponent)
}
}
QQC2.ButtonGroup.group: tabPositionGroup
}
}
}
}
}
Component {
id: signaturesComponent
Signatures {
onDialogOpened: {
// We don't want to have two modal things open at the same time
if (root.modal) {
root.close();
}
}
}

@ -0,0 +1,177 @@
/*
* SPDX-FileCopyrightText: 2022 Albert Astals Cid <aacid@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Dialogs 1.3 as QQD
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.17 as Kirigami
Kirigami.OverlaySheet
{
id: root
property alias signatureValidityText: signatureValidity.text
property alias documentModificationsText: documentModifications.text
property alias signerNameText: signerName.text
property alias signingTimeText: signingTime.text
property alias signingLocationText: signingLocation.text
property alias signingReasonText: signingReason.text
property var certificateModel
property int signatureRevisionIndex: -1
signal saveSignatureSignedVersion(url path)
title: i18n("Signature Properties")
function showErrorDialog() {
errorDialog.open();
}
ColumnLayout {
// Without this the width is unreasonably narrow, potentially
// https://invent.kde.org/frameworks/kirigami/-/merge_requests/487 fixes it
// check when a kirigami with that is required as minimum version
Layout.preferredWidth: Math.min(Window.window.width, 360)
QQC2.GroupBox {
Layout.fillWidth: true
title: i18n("Validity Status")
Kirigami.FormLayout {
width: parent.width
QQC2.Label {
id: signatureValidity
Kirigami.FormData.label: i18n("Signature Validity:")
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
id: documentModifications
Kirigami.FormData.label: i18n("Document Modifications:")
wrapMode: Text.Wrap
Layout.fillWidth: true
}
}
}
QQC2.GroupBox {
title: i18n("Additional Information")
Layout.fillWidth: true
Kirigami.FormLayout {
id: additionalInformationLayout
width: parent.width
QQC2.Label {
id: signerName
Kirigami.FormData.label: i18n("Signed By:")
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
id: signingTime
Kirigami.FormData.label: i18n("Signing Time:")
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
id: signingReason
Kirigami.FormData.label: i18n("Reason:")
visible: text
wrapMode: Text.Wrap
Layout.fillWidth: true
}
QQC2.Label {
id: signingLocation
Kirigami.FormData.label: i18n("Location:")
visible: text
wrapMode: Text.Wrap
Layout.fillWidth: true
}
}
}
QQC2.GroupBox {
title: i18n("Document Version")
Layout.fillWidth: true
visible: root.signatureRevisionIndex >= 0
RowLayout {
width: parent.width
QQC2.Label {
Layout.fillWidth: true
text: i18nc("Document Revision <current> of <total>", "Document Revision %1 of %2", root.signatureRevisionIndex + 1, documentItem.signaturesModel.count)
wrapMode: Text.Wrap
}
QQC2.Button {
text: i18n("Save Signed Version...")
onClicked: {
fileDialog.open();
}
}
}
}
QQC2.DialogButtonBox {
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
QQC2.Button {
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.ActionRole
text: i18n("View Certificate...")
onClicked: {
var dialog = dialogComponent.createObject(Window.window, {
certificateModel: root.certificateModel
})
dialog.open()
}
Component {
id: dialogComponent
CertificateViewerDialog {
onSheetOpenChanged: if(!sheetOpen) {
destroy(1000)
}
}
}
}
QQC2.Button {
QQC2.DialogButtonBox.buttonRole: QQC2.DialogButtonBox.DestructiveRole
text: i18n("Close")
icon.name: "dialog-close"
onClicked: root.close()
}
}
QQD.FileDialog {
id: fileDialog
folder: "file://" + userPaths.documents
selectExisting: false
onAccepted: {
root.saveSignatureSignedVersion(fileDialog.fileUrl);
}
}
// TODO Use Kirigami.PromptDialog when we depend on KF >= 5.89
// this way we can probably remove that ridiculous z value
QQC2.Dialog {
id: errorDialog
z: 200
title: i18n("Error")
contentItem: QQC2.Label {
text: i18n("Could not save the signature.")
}
standardButtons: QQC2.Dialog.Ok
onAccepted: close();
}
}
}

@ -0,0 +1,64 @@
/*
SPDX-FileCopyrightText: 2012 Marco Martin <mart@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Controls 2.15 as QQC2
import QtQuick.Window 2.15
import org.kde.kirigami 2.17 as Kirigami
import org.kde.kitemmodels 1.0
QQC2.ScrollView {
id: root
signal dialogOpened
ListView {
model: KDescendantsProxyModel {
model: documentItem.signaturesModel
expandsByDefault: false
}
delegate: TreeItem {
function displayString(str) {
return str ? str : i18n("Not Available");
}
text: model.display
onClicked: {
if (!model.isUnsignedSignature) {
var dialog = dialogComponent.createObject(Window.window, {
signatureValidityText: model.readableStatus,
documentModificationsText: model.readableModificationSummary,
signerNameText: displayString(model.signerName),
signingTimeText: displayString(model.signingTime),
signingLocationText: model.signingLocation,
signingReasonText: model.signingReason,
certificateModel: model.certificateModel,
signatureRevisionIndex: model.signatureRevisionIndex
})
dialog.open()
root.dialogOpened();
}
}
}
Component {
id: dialogComponent
SignaturePropertiesDialog {
id: dialog
onSheetOpenChanged: if(!sheetOpen) {
destroy(1000)
}
onSaveSignatureSignedVersion: (path) => {
if (!documentItem.signaturesModel.saveSignedVersion(signatureRevisionIndex, path)) {
dialog.showErrorDialog();
}
}
}
}
}
}

@ -1,9 +1,12 @@
set(okular_SRCS
okularplugin.cpp
${CMAKE_SOURCE_DIR}/part/guiutils.cpp
${CMAKE_SOURCE_DIR}/part/tocmodel.cpp
${CMAKE_SOURCE_DIR}/part/pagepainter.cpp
${CMAKE_SOURCE_DIR}/part/debug_ui.cpp
${CMAKE_SOURCE_DIR}/gui/guiutils.cpp
${CMAKE_SOURCE_DIR}/gui/tocmodel.cpp
${CMAKE_SOURCE_DIR}/gui/signaturemodel.cpp
${CMAKE_SOURCE_DIR}/gui/signatureguiutils.cpp
${CMAKE_SOURCE_DIR}/gui/certificatemodel.cpp
${CMAKE_SOURCE_DIR}/gui/pagepainter.cpp
${CMAKE_SOURCE_DIR}/gui/debug_ui.cpp
pageitem.cpp
documentitem.cpp
thumbnailitem.cpp

@ -18,7 +18,9 @@
#include <core/document_p.h>
#include <core/page.h>
#include "part/tocmodel.h"
#include "gui/signatureguiutils.h"
#include "gui/signaturemodel.h"
#include "gui/tocmodel.h"
DocumentItem::DocumentItem(QObject *parent)
: QObject(parent)
@ -27,9 +29,11 @@ DocumentItem::DocumentItem(QObject *parent)
, m_searchInProgress(false)
{
qmlRegisterUncreatableType<TOCModel>("org.kde.okular.private", 1, 0, "TOCModel", QStringLiteral("Do not create objects of this type."));
qmlRegisterUncreatableType<SignatureModel>("org.kde.okular.private", 1, 0, "SignatureModel", QStringLiteral("Do not create objects of this type."));
Okular::Settings::instance(QStringLiteral("okularproviderrc"));
m_document = new Okular::Document(nullptr);
m_tocModel = new TOCModel(m_document, this);
m_signaturesModel = new SignatureModel(m_document, this);
connect(m_document, &Okular::Document::searchFinished, this, &DocumentItem::searchFinished);
connect(m_document->bookmarkManager(), &Okular::BookmarkManager::bookmarksChanged, this, &DocumentItem::bookmarkedPagesChanged);
@ -41,6 +45,7 @@ DocumentItem::DocumentItem(QObject *parent)
DocumentItem::~DocumentItem()
{
delete m_signaturesModel;
delete m_document;
}
@ -75,6 +80,19 @@ void DocumentItem::setUrl(const QUrl &url)
emit supportsSearchingChanged();
emit windowTitleForDocumentChanged();
emit bookmarkedPagesChanged();
KMessageWidget::MessageType messageType;
QString message;
std::tie(messageType, message) = SignatureGuiUtils::documentSignatureMessageWidgetText(m_document);
if (!message.isEmpty()) {
if (messageType == KMessageWidget::Information) {
emit notice(message, -1);
} else if (messageType == KMessageWidget::Warning) {
emit warning(message, -1);
} else {
qWarning() << "Unexpected message type" << messageType;
}
}
}
QString DocumentItem::windowTitleForDocument() const
@ -131,6 +149,11 @@ TOCModel *DocumentItem::tableOfContents() const
return m_tocModel;
}
SignatureModel *DocumentItem::signaturesModel() const
{
return m_signaturesModel;
}
QVariantList DocumentItem::bookmarkedPages() const
{
QList<int> list;

@ -20,6 +20,7 @@ class Document;
}
class Observer;
class SignatureModel;
class TOCModel;
class DocumentItem : public QObject
@ -71,6 +72,11 @@ class DocumentItem : public QObject
*/
Q_PROPERTY(TOCModel *tableOfContents READ tableOfContents CONSTANT)
/**
* Signatures model, if available
*/
Q_PROPERTY(SignatureModel *signaturesModel READ signaturesModel CONSTANT)
/**
* List of pages that contain a bookmark
*/
@ -105,6 +111,8 @@ public:
TOCModel *tableOfContents() const;
SignatureModel *signaturesModel() const;
QVariantList bookmarkedPages() const;
QStringList bookmarks() const;
@ -169,6 +177,7 @@ private Q_SLOTS:
private:
Okular::Document *m_document;
TOCModel *m_tocModel;
SignatureModel *m_signaturesModel;
Observer *m_thumbnailObserver;
Observer *m_pageviewObserver;
QVariantList m_matchingPages;

@ -7,6 +7,7 @@
#include "okularplugin.h"
#include "documentitem.h"
#include "gui/certificatemodel.h"
#include "okularsingleton.h"
#include "pageitem.h"
#include "thumbnailitem.h"
@ -28,4 +29,5 @@ void OkularPlugin::registerTypes(const char *uri)
qmlRegisterType<DocumentItem>(uri, 2, 0, "DocumentItem");
qmlRegisterType<PageItem>(uri, 2, 0, "PageItem");
qmlRegisterType<ThumbnailItem>(uri, 2, 0, "ThumbnailItem");
qmlRegisterUncreatableType<CertificateModel>(uri, 2, 0, "CertificateModel", QStringLiteral("Do not create objects of this type."));
}

@ -17,8 +17,8 @@
#include <core/generator.h>
#include <core/page.h>
#include "part/pagepainter.h"
#include "part/priorities.h"
#include "gui/pagepainter.h"
#include "gui/priorities.h"
#include "settings.h"
#define REDRAW_TIMEOUT 250

@ -28,7 +28,7 @@
#include "actionbar.h"
#include "annotationwidgets.h"
#include "core/annotations.h"
#include "guiutils.h"
#include "gui/guiutils.h"
#include "pageview.h"
#include "pageviewannotator.h"
#include "settings.h"

@ -20,7 +20,7 @@
#include "core/document.h"
#include "core/observer.h"
#include "core/page.h"
#include "guiutils.h"
#include "gui/guiutils.h"
struct AnnItem {
AnnItem();

@ -14,7 +14,7 @@
#include "core/annotations.h"
#include "core/document.h"
#include "guiutils.h"
#include "gui/guiutils.h"
#include "okmenutitle.h"
Q_DECLARE_METATYPE(AnnotationPopup::AnnotPagePair)

@ -12,7 +12,7 @@
#include <QIcon>
#include "annotationmodel.h"
#include "debug_ui.h"
#include "gui/debug_ui.h"
static quint32 mixIndex(int row, int column)
{

@ -35,8 +35,8 @@
#include "core/document.h"
#include "core/document_p.h"
#include "core/page_p.h"
#include "guiutils.h"
#include "pagepainter.h"
#include "gui/guiutils.h"
#include "gui/pagepainter.h"
#define FILEATTACH_ICONSIZE 48

@ -27,6 +27,7 @@
#include "core/action.h"
#include "core/bookmarkmanager.h"
#include "core/document.h"
#include "gui/tocmodel.h"
#include "pageitemdelegate.h"
static const int BookmarkItemType = QTreeWidgetItem::UserType + 1;
@ -46,7 +47,7 @@ public:
m_url.setFragment(QString());
setText(0, m_bookmark.fullText());
if (m_viewport.isValid())
setData(0, PageItemDelegate::PageRole, QString::number(m_viewport.pageNumber + 1));
setData(0, TOCModel::PageRole, QString::number(m_viewport.pageNumber + 1));
}
BookmarkItem(const BookmarkItem &) = delete;

@ -6,6 +6,8 @@
#include "certificateviewer.h"
#include "gui/certificatemodel.h"
#include <KColumnResizer>
#include <KLocalizedString>
#include <KMessageBox>
@ -22,7 +24,7 @@
#include <QTreeView>
#include <QVBoxLayout>
#include "signatureguiutils.h"
#include "gui/signatureguiutils.h"
// DN (DistinguishedName) attributes can be
// C Country
@ -94,113 +96,6 @@ static QString splitDNAttributes(const QString &text)
return splitDNAttributes(QStringList {text});
}
CertificateModel::CertificateModel(const Okular::CertificateInfo &certInfo, QObject *parent)
: QAbstractTableModel(parent)
, m_certificateInfo(certInfo)
{
m_certificateProperties = {Version, SerialNumber, Issuer, IssuedOn, ExpiresOn, Subject, PublicKey, KeyUsage};
}
int CertificateModel::columnCount(const QModelIndex &) const
{
return 2;
}
int CertificateModel::rowCount(const QModelIndex &) const
{
return m_certificateProperties.size();
}
static QString propertyVisibleName(CertificateModel::Property p)
{
switch (p) {
case CertificateModel::Version:
return i18n("Version");
case CertificateModel::SerialNumber:
return i18n("Serial Number");
case CertificateModel::Issuer:
return i18n("Issuer");
case CertificateModel::IssuedOn:
return i18n("Issued On");
case CertificateModel::ExpiresOn:
return i18n("Expires On");
case CertificateModel::Subject:
return i18nc("The person/company that made the signature", "Subject");
case CertificateModel::PublicKey:
return i18n("Public Key");
case CertificateModel::KeyUsage:
return i18n("Key Usage");
}
return QString();
}
static QString propertyVisibleValue(CertificateModel::Property p, const Okular::CertificateInfo &certInfo)
{
switch (p) {
case CertificateModel::Version:
return i18n("V%1", QString::number(certInfo.version()));
case CertificateModel::SerialNumber:
return certInfo.serialNumber().toHex(' ');
case CertificateModel::Issuer:
return certInfo.issuerInfo(Okular::CertificateInfo::DistinguishedName);
case CertificateModel::IssuedOn:
return certInfo.validityStart().toString(Qt::DefaultLocaleLongDate);
case CertificateModel::ExpiresOn:
return certInfo.validityEnd().toString(Qt::DefaultLocaleLongDate);
case CertificateModel::Subject:
return certInfo.subjectInfo(Okular::CertificateInfo::DistinguishedName);
case CertificateModel::PublicKey:
return i18n("%1 (%2 bits)", SignatureGuiUtils::getReadablePublicKeyType(certInfo.publicKeyType()), certInfo.publicKeyStrength());
case CertificateModel::KeyUsage:
return SignatureGuiUtils::getReadableKeyUsageCommaSeparated(certInfo.keyUsageExtensions());
}
return QString();
}
QVariant CertificateModel::data(const QModelIndex &index, int role) const
{
const int row = index.row();
if (!index.isValid() || row < 0 || row >= m_certificateProperties.count())
return QVariant();
switch (role) {
case Qt::DisplayRole:
case Qt::ToolTipRole:
switch (index.column()) {
case 0:
return propertyVisibleName(m_certificateProperties[row]);
case 1:
return propertyVisibleValue(m_certificateProperties[row], m_certificateInfo);
default:
return QString();
}
case PropertyKeyRole:
return m_certificateProperties[row];
case PropertyVisibleValueRole:
return propertyVisibleValue(m_certificateProperties[row], m_certificateInfo);
}
return QVariant();
}
QVariant CertificateModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::TextAlignmentRole)
return QVariant(Qt::AlignLeft);
if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
return QVariant();
switch (section) {
case 0:
return i18n("Property");
case 1:
return i18n("Value");
default:
return QVariant();
}
}
CertificateViewer::CertificateViewer(const Okular::CertificateInfo &certInfo, QWidget *parent)
: KPageDialog(parent)
, m_certificateInfo(certInfo)
@ -303,6 +198,16 @@ void CertificateViewer::updateText(const QModelIndex &index)
case CertificateModel::KeyUsage:
text = SignatureGuiUtils::getReadableKeyUsageNewLineSeparated(m_certificateInfo.keyUsageExtensions());
break;
case CertificateModel::IssuerName:
case CertificateModel::IssuerEmail:
case CertificateModel::IssuerOrganization:
case CertificateModel::SubjectName:
case CertificateModel::SubjectEmail:
case CertificateModel::SubjectOrganization:
case CertificateModel::Sha1:
case CertificateModel::Sha256:
Q_ASSERT(false);
qWarning() << "Unused";
}
m_propertyText->setText(text);
}
@ -312,11 +217,8 @@ void CertificateViewer::exportCertificate()
const QString caption = i18n("Where do you want to save this certificate?");
const QString path = QFileDialog::getSaveFileName(this, caption, QStringLiteral("Certificate.cer"), i18n("Certificate File (*.cer)"));
if (!path.isEmpty()) {
QFile targetFile(path);
targetFile.open(QIODevice::WriteOnly);
if (targetFile.write(m_certificateInfo.certificateData()) == -1) {
if (!m_certificateModel->exportCertificateTo(path)) {
KMessageBox::error(this, i18n("Could not export the certificate"));
}
targetFile.close();
}
}

@ -8,11 +8,11 @@
#define OKULAR_CERTIFICATEVIEWER_H
#include <KPageDialog>
#include <QAbstractTableModel>
#include <QVector>
#include "core/signatureutils.h"
class CertificateModel;
class QTextEdit;
namespace Okular
@ -20,28 +20,6 @@ namespace Okular
class CertificateInfo;
}
class CertificateModel : public QAbstractTableModel
{
Q_OBJECT
public:
explicit CertificateModel(const Okular::CertificateInfo &certInfo, QObject *parent = nullptr);
enum { PropertyKeyRole = Qt::UserRole, PropertyVisibleValueRole };
enum Property { Version, SerialNumber, Issuer, IssuedOn, ExpiresOn, Subject, PublicKey, KeyUsage };
Q_ENUM(Property)
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
private:
QVector<Property> m_certificateProperties;
const Okular::CertificateInfo &m_certificateInfo;
};
class CertificateViewer : public KPageDialog
{
Q_OBJECT

@ -10,7 +10,7 @@
#include <KLocalizedString>
#include <kwidgetsaddons_version.h> // TODO KF6: Remove, this was needed for KActionMenu::setPopupMode().
#include "guiutils.h"
#include "gui/guiutils.h"
#include "settings.h"
ColorModeMenu::ColorModeMenu(KActionCollection *ac, QObject *parent)

@ -7,7 +7,7 @@
#include "drawingtoolactions.h"
#include "debug_ui.h"
#include "gui/debug_ui.h"
#include "settings.h"
#include <KActionCollection>

@ -28,7 +28,7 @@
#include <QVBoxLayout>
#include "core/document.h"
#include "guiutils.h"
#include "gui/guiutils.h"
Q_DECLARE_METATYPE(Okular::EmbeddedFile *)

@ -25,7 +25,7 @@
#include <QLoggingCategory>
#include <kparts/readonlypart.h>
#include "debug_ui.h"
#include "gui/debug_ui.h"
using namespace Okular;

@ -12,7 +12,7 @@
#include "pageview.h"
#include "pageviewutils.h"
#include "revisionviewer.h"
#include "signatureguiutils.h"
#include "signaturepartutils.h"
#include "signaturepropertiesdialog.h"
#include <KLineEdit>
@ -29,7 +29,7 @@
// local includes
#include "core/action.h"
#include "core/document.h"
#include "debug_ui.h"
#include "gui/debug_ui.h"
FormWidgetsController::FormWidgetsController(Okular::Document *doc)
: QObject(doc)
@ -1165,7 +1165,7 @@ void SignatureEdit::signUnsignedSignature()
Okular::FormFieldSignature *formSignature = static_cast<Okular::FormFieldSignature *>(formField());
PageView *pageView = static_cast<PageView *>(parent()->parent());
SignatureGuiUtils::signUnsignedSignature(formSignature, pageView, pageView->document());
SignaturePartUtils::signUnsignedSignature(formSignature, pageView, pageView->document());
}
// Code for additional action handling.

@ -22,7 +22,7 @@
#include <QTemporaryFile>
#include <QTextStream>
#include "debug_ui.h"
#include "gui/debug_ui.h"
namespace GuiUtils
{

@ -9,8 +9,8 @@
#include "core/document.h"
#include "core/generator.h"
#include "pagepainter.h"
#include "priorities.h"
#include "gui/pagepainter.h"
#include "gui/priorities.h"
static const int SCALE = 10;

@ -13,6 +13,7 @@
#include <QVariant>
// local includes
#include "gui/tocmodel.h"
#include "settings.h"
#define PAGEITEMDELEGATE_INTERNALMARGIN 3
@ -46,8 +47,8 @@ void PageItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
void PageItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const
{
QVariant pageVariant = d->index.data(PageRole);
QVariant labelVariant = d->index.data(PageLabelRole);
QVariant pageVariant = d->index.data(TOCModel::PageRole);
QVariant labelVariant = d->index.data(TOCModel::PageLabelRole);
if ((labelVariant.type() != QVariant::String && !pageVariant.canConvert(QVariant::String)) || !Okular::Settings::tocPageColumn()) {
QItemDelegate::drawDisplay(painter, option, rect, text);
return;

@ -17,9 +17,6 @@ public:
explicit PageItemDelegate(QObject *parent = nullptr);
~PageItemDelegate() override;
static const int PageRole = 0x000f0001;
static const int PageLabelRole = 0x000f0002;
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
protected:

@ -71,15 +71,15 @@
#include "colormodemenu.h"
#include "core/annotations.h"
#include "cursorwraphelper.h"
#include "debug_ui.h"
#include "formwidgets.h"
#include "guiutils.h"
#include "gui/debug_ui.h"
#include "gui/guiutils.h"
#include "gui/pagepainter.h"
#include "gui/priorities.h"
#include "okmenutitle.h"
#include "pagepainter.h"
#include "pageviewannotator.h"
#include "pageviewmouseannotation.h"
#include "pageviewutils.h"
#include "priorities.h"
#include "toggleactionmenu.h"
#ifdef HAVE_SPEECH
#include "tts.h"

@ -39,12 +39,12 @@
#include "core/document.h"
#include "core/page.h"
#include "core/signatureutils.h"
#include "debug_ui.h"
#include "editannottooldialog.h"
#include "guiutils.h"
#include "gui/debug_ui.h"
#include "gui/guiutils.h"
#include "pageview.h"
#include "settings.h"
#include "signatureguiutils.h"
#include "signaturepartutils.h"
/** @short PickPointEngine */
class PickPointEngine : public AnnotatorEngine
@ -354,7 +354,7 @@ public:
}
}
const std::unique_ptr<Okular::CertificateInfo> cert = SignatureGuiUtils::getCertificateAndPasswordForSigning(m_pageView, m_document, &passToUse, &documentPassword);
const std::unique_ptr<Okular::CertificateInfo> cert = SignaturePartUtils::getCertificateAndPasswordForSigning(m_pageView, m_document, &passToUse, &documentPassword);
if (!cert) {
m_aborted = true;
passToUse.clear();
@ -985,7 +985,7 @@ QRect PageViewAnnotator::performRouteMouseOrTabletEvent(const AnnotatorEngine::E
if (signatureMode()) {
auto signEngine = static_cast<PickPointEngineSignature *>(m_engine);
if (signEngine->isAccepted()) {
const QString newFilePath = SignatureGuiUtils::getFileNameForNewSignedFile(m_pageView, m_document);
const QString newFilePath = SignaturePartUtils::getFileNameForNewSignedFile(m_pageView, m_document);
if (!newFilePath.isEmpty()) {
const bool success = static_cast<PickPointEngineSignature *>(m_engine)->sign(newFilePath);

@ -25,7 +25,7 @@
#include "core/document.h"
#include "core/page.h"
#include "guiutils.h"
#include "gui/guiutils.h"
#include "pageview.h"
#include "videowidget.h"

@ -93,13 +93,14 @@
#include "core/generator.h"
#include "core/page.h"
#include "core/printoptionswidget.h"
#include "debug_ui.h"
#include "drawingtoolactions.h"
#include "embeddedfilesdialog.h"
#include "extensions.h"
#include "fileprinterpreview.h"
#include "findbar.h"
#include "guiutils.h"
#include "gui/debug_ui.h"
#include "gui/guiutils.h"
#include "gui/signatureguiutils.h"
#include "layers.h"
#include "minibar.h"
#include "okmenutitle.h"
@ -112,7 +113,6 @@
#include "settings.h"
#include "side_reviews.h"
#include "sidebar.h"
#include "signatureguiutils.h"
#include "signaturepanel.h"
#include "thumbnaillist.h"
#include "toc.h"
@ -1573,51 +1573,24 @@ bool Part::openFile()
}
if (ok) {
const uint numPages = m_document->pages();
bool isDigitallySigned = false;
for (uint i = 0; i < numPages; i++) {
const QLinkedList<Okular::FormField *> formFields = m_document->page(i)->formFields();
for (const Okular::FormField *f : formFields) {
if (f->type() == Okular::FormField::FormSignature)
isDigitallySigned = true;
}
}
KMessageWidget::MessageType messageType;
QString message;
std::tie(messageType, message) = SignatureGuiUtils::documentSignatureMessageWidgetText(m_document);
if (isDigitallySigned && Okular::Settings::showEmbeddedContentMessages()) {
if (!message.isEmpty()) {
if (m_embedMode == PrintPreviewMode) {
m_signatureMessage->setText(i18n("All editing and interactive features for this document are disabled. Please save a copy and reopen to edit this document."));
} else {
const QVector<const Okular::FormFieldSignature *> signatureFormFields = SignatureGuiUtils::getSignatureFormFields(m_document);
bool allSignaturesValid = true;
bool anySignatureUnsigned = false;
for (const Okular::FormFieldSignature *signature : signatureFormFields) {
if (signature->signatureType() == Okular::FormFieldSignature::UnsignedSignature) {
anySignatureUnsigned = true;
} else {
const Okular::SignatureInfo &info = signature->signatureInfo();
if (info.signatureStatus() != SignatureInfo::SignatureValid) {
allSignaturesValid = false;
}
}
if (Okular::Settings::showEmbeddedContentMessages()) {
m_signatureMessage->setText(i18n("All editing and interactive features for this document are disabled. Please save a copy and reopen to edit this document."));
m_signatureMessage->setVisible(true);
}
if (anySignatureUnsigned) {
m_signatureMessage->setMessageType(KMessageWidget::Information);
m_signatureMessage->setText(i18n("This document has unsigned signature fields."));
} else if (allSignaturesValid) {
if (signatureFormFields.last()->signatureInfo().signsTotalDocument()) {
m_signatureMessage->setMessageType(KMessageWidget::Information);
m_signatureMessage->setText(i18n("This document is digitally signed."));
} else {
m_signatureMessage->setMessageType(KMessageWidget::Warning);
m_signatureMessage->setText(i18n("This document is digitally signed. There have been changes since last signed."));
}
} else {
m_signatureMessage->setMessageType(KMessageWidget::Warning);
m_signatureMessage->setText(i18n("This document is digitally signed. Some of the signatures could not be validated properly."));
} else {
if (Okular::Settings::showEmbeddedContentMessages() || messageType > KMessageWidget::Information) {
m_signatureMessage->setMessageType(messageType);
m_signatureMessage->setText(message);
m_signatureMessage->setVisible(true);
}
}
m_signatureMessage->setVisible(true);
}
}

@ -56,12 +56,12 @@
#include "core/generator.h"
#include "core/movie.h"
#include "core/page.h"
#include "debug_ui.h"
#include "drawingtoolactions.h"
#include "guiutils.h"
#include "pagepainter.h"
#include "gui/debug_ui.h"
#include "gui/guiutils.h"
#include "gui/pagepainter.h"
#include "gui/priorities.h"
#include "presentationsearchbar.h"
#include "priorities.h"
#include "settings.h"
#include "settings_core.h"
#include "videowidget.h"

@ -6,10 +6,10 @@
#include "signaturepanel.h"
#include "gui/signaturemodel.h"
#include "pageview.h"
#include "revisionviewer.h"
#include "signatureguiutils.h"
#include "signaturemodel.h"
#include "signaturepartutils.h"
#include "signaturepropertiesdialog.h"
#include <kwidgetsaddons_version.h>
@ -114,7 +114,7 @@ void SignaturePanel::slotViewProperties()
void SignaturePanel::signUnsignedSignature()
{
Q_D(SignaturePanel);
SignatureGuiUtils::signUnsignedSignature(d->m_currentForm, d->m_pageView, d->m_document);
SignaturePartUtils::signUnsignedSignature(d->m_currentForm, d->m_pageView, d->m_document);
}
void SignaturePanel::notifySetup(const QVector<Okular::Page *> & /*pages*/, int setupFlags)

@ -0,0 +1,127 @@
/*
SPDX-FileCopyrightText: 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "signaturepartutils.h"
#include "core/document.h"
#include "core/form.h"
#include "core/page.h"
#include "pageview.h"
#include <QFileDialog>
#include <QFileInfo>
#include <QInputDialog>
#include <QMimeDatabase>
#include <KLocalizedString>
#include <KMessageBox>
namespace SignaturePartUtils
{
std::unique_ptr<Okular::CertificateInfo> getCertificateAndPasswordForSigning(PageView *pageView, Okular::Document *doc, QString *password, QString *documentPassword)
{
const Okular::CertificateStore *certStore = doc->certificateStore();
bool userCancelled, nonDateValidCerts;
QList<Okular::CertificateInfo *> certs = certStore->signingCertificatesForNow(&userCancelled, &nonDateValidCerts);
if (userCancelled) {
return nullptr;
}
if (certs.isEmpty()) {
pageView->showNoSigningCertificatesDialog(nonDateValidCerts);
return nullptr;
}
QStringList items;
QHash<QString, Okular::CertificateInfo *> nickToCert;
for (auto cert : qAsConst(certs)) {
items.append(cert->nickName());
nickToCert[cert->nickName()] = cert;
}
bool resok = false;
const QString certNicknameToUse = QInputDialog::getItem(pageView, i18n("Select certificate to sign with"), i18n("Certificates:"), items, 0, false, &resok);
if (!resok) {
qDeleteAll(certs);
return nullptr;
}
// I could not find any case in which i need to enter a password to use the certificate, seems that once you unlcok the firefox/NSS database
// you don't need a password anymore, but still there's code to do that in NSS so we have code to ask for it if needed. What we do is
// ask if the empty password is fine, if it is we don't ask the user anything, if it's not, we ask for a password
Okular::CertificateInfo *cert = nickToCert.value(certNicknameToUse);
bool passok = cert->checkPassword(*password);
while (!passok) {
const QString title = i18n("Enter password (if any) to unlock certificate: %1", certNicknameToUse);
bool ok;
*password = QInputDialog::getText(pageView, i18n("Enter certificate password"), title, QLineEdit::Password, QString(), &ok);
if (ok) {
passok = cert->checkPassword(*password);
} else {
passok = false;
break;
}
}
if (doc->metaData(QStringLiteral("DocumentHasPassword")).toString() == QLatin1String("yes")) {
*documentPassword = QInputDialog::getText(pageView, i18n("Enter document password"), i18n("Enter document password"), QLineEdit::Password, QString(), &passok);
}
if (passok) {
certs.removeOne(cert);
}
qDeleteAll(certs);
return passok ? std::unique_ptr<Okular::CertificateInfo>(cert) : std::unique_ptr<Okular::CertificateInfo>();
}
QString getFileNameForNewSignedFile(PageView *pageView, Okular::Document *doc)
{
QMimeDatabase db;
const QString typeName = doc->documentInfo().get(Okular::DocumentInfo::MimeType);
const QMimeType mimeType = db.mimeTypeForName(typeName);
const QString mimeTypeFilter = i18nc("File type name and pattern", "%1 (%2)", mimeType.comment(), mimeType.globPatterns().join(QLatin1Char(' ')));
const QUrl currentFileUrl = doc->currentDocument();
const QFileInfo currentFileInfo(currentFileUrl.fileName());
const QString localFilePathIfAny = currentFileUrl.isLocalFile() ? QFileInfo(currentFileUrl.path()).canonicalPath() + QLatin1Char('/') : QString();
const QString newFileName =
localFilePathIfAny + i18nc("Used when suggesting a new name for a digitally signed file. %1 is the old file name and %2 it's extension", "%1_signed.%2", currentFileInfo.baseName(), currentFileInfo.completeSuffix());
return QFileDialog::getSaveFileName(pageView, i18n("Save Signed File As"), newFileName, mimeTypeFilter);
}
void signUnsignedSignature(const Okular::FormFieldSignature *form, PageView *pageView, Okular::Document *doc)
{
Q_ASSERT(form && form->signatureType() == Okular::FormFieldSignature::UnsignedSignature);
QString password, documentPassword;
const std::unique_ptr<Okular::CertificateInfo> cert = getCertificateAndPasswordForSigning(pageView, doc, &password, &documentPassword);
if (!cert) {
return;
}
Okular::NewSignatureData data;
data.setCertNickname(cert->nickName());
data.setCertSubjectCommonName(cert->subjectInfo(Okular::CertificateInfo::CommonName));
data.setPassword(password);
data.setDocumentPassword(documentPassword);
password.clear();
documentPassword.clear();
const QString newFilePath = getFileNameForNewSignedFile(pageView, doc);
if (!newFilePath.isEmpty()) {
const bool success = form->sign(data, newFilePath);
if (success) {
emit pageView->requestOpenFile(newFilePath, form->page()->number() + 1);
} else {
KMessageBox::error(pageView, i18nc("%1 is a file path", "Could not sign. Invalid certificate password or could not write to '%1'", newFilePath));
}
}
}
}

@ -0,0 +1,24 @@
/*
SPDX-FileCopyrightText: 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef OKULAR_SIGNATUREPARTUTILS_H
#define OKULAR_SIGNATUREPARTUTILS_H
#include <memory>
#include "gui/signatureguiutils.h"
class PageView;
namespace SignaturePartUtils
{
std::unique_ptr<Okular::CertificateInfo> getCertificateAndPasswordForSigning(PageView *pageView, Okular::Document *doc, QString *password, QString *documentPassword);
QString getFileNameForNewSignedFile(PageView *pageView, Okular::Document *doc);
void signUnsignedSignature(const Okular::FormFieldSignature *form, PageView *pageView, Okular::Document *doc);
}
#endif

@ -21,8 +21,8 @@
#include "core/form.h"
#include "certificateviewer.h"
#include "gui/signatureguiutils.h"
#include "revisionviewer.h"
#include "signatureguiutils.h"
static QString getValidDisplayString(const QString &str)
{
@ -40,27 +40,12 @@ SignaturePropertiesDialog::SignaturePropertiesDialog(Okular::Document *doc, cons
const Okular::SignatureInfo &signatureInfo = form->signatureInfo();
const Okular::SignatureInfo::SignatureStatus signatureStatus = signatureInfo.signatureStatus();
const QString readableSignatureStatus = SignatureGuiUtils::getReadableSignatureStatus(signatureStatus);
const QString modificationSummary = SignatureGuiUtils::getReadableModificationSummary(signatureInfo);
const QString signerName = getValidDisplayString(signatureInfo.signerName());
const QString signingTime = getValidDisplayString(signatureInfo.signingTime().toString(Qt::DefaultLocaleLongDate));
const QString signingLocation = getValidDisplayString(signatureInfo.location());
const QString signingReason = signatureInfo.reason();
// signature validation status
QString modificationSummary;
if (signatureStatus == Okular::SignatureInfo::SignatureValid) {
if (signatureInfo.signsTotalDocument()) {
modificationSummary = i18n("The document has not been modified since it was signed.");
} else {
modificationSummary = i18n(
"The revision of the document that was covered by this signature has not been modified;\n"
"however there have been subsequent changes to the document.");
}
} else if (signatureStatus == Okular::SignatureInfo::SignatureDigestMismatch) {
modificationSummary = i18n("The document has been modified in a way not permitted by a previous signer.");
} else {
modificationSummary = i18n("The document integrity verification could not be completed.");
}
auto signatureStatusBox = new QGroupBox(i18n("Validity Status"));
auto signatureStatusFormLayout = new QFormLayout(signatureStatusBox);
signatureStatusFormLayout->setLabelAlignment(Qt::AlignLeft);

@ -31,8 +31,8 @@
#include "core/generator.h"
#include "core/page.h"
#include "cursorwraphelper.h"
#include "pagepainter.h"
#include "priorities.h"
#include "gui/pagepainter.h"
#include "gui/priorities.h"
#include "settings.h"
class ThumbnailWidget;

@ -21,10 +21,10 @@
// local includes
#include "core/action.h"
#include "gui/tocmodel.h"
#include "ktreeviewsearchline.h"
#include "pageitemdelegate.h"
#include "settings.h"
#include "tocmodel.h"
TOC::TOC(QWidget *parent, Okular::Document *document)
: QWidget(parent)

Loading…
Cancel
Save