diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9d54764c8..c8e4426d3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,474 +1,473 @@
cmake_minimum_required(VERSION 3.0)
# KDE Application Version, managed by release script
set (KDE_APPLICATIONS_VERSION_MAJOR "18")
set (KDE_APPLICATIONS_VERSION_MINOR "07")
set (KDE_APPLICATIONS_VERSION_MICRO "70")
set (KDE_APPLICATIONS_VERSION "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}")
project(okular VERSION 1.4.${KDE_APPLICATIONS_VERSION_MICRO})
set(QT_REQUIRED_VERSION "5.8.0")
set(KF5_REQUIRED_VERSION "5.33.0")
find_package(ECM 5.33.0 CONFIG REQUIRED)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
include(ECMInstallIcons)
include(ECMSetupVersion)
include(ECMOptionalAddSubdirectory)
include(GenerateExportHeader)
include(FeatureSummary)
include(ECMAddAppIcon)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(KDEInstallDirs)
include(KDECMakeSettings)
include(ECMAddTests)
include(ECMAddAppIcon)
include(CMakePackageConfigHelpers)
ecm_setup_version(${PROJECT_VERSION}
VARIABLE_PREFIX OKULAR
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/core/version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/Okular5ConfigVersion.cmake")
find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core DBus Test Widgets PrintSupport Svg Qml Quick)
find_package(Qt5 ${QT_REQUIRED_VERSION} OPTIONAL_COMPONENTS TextToSpeech)
if (NOT Qt5TextToSpeech_FOUND)
message(STATUS "Qt5TextToSpeech not found, speech features will be disabled")
else()
add_definitions(-DHAVE_SPEECH)
endif()
if(NOT CMAKE_VERSION VERSION_LESS "3.10.0")
# CMake 3.9+ warns about automoc on files without Q_OBJECT, and doesn't know about other macros.
# 3.10+ lets us provide more macro names that require automoc.
list(APPEND CMAKE_AUTOMOC_MACRO_NAMES "OKULAR_EXPORT_PLUGIN")
endif()
set(optionalComponents)
if (ANDROID)
# we want to make sure that generally all components are found
set(optionalComponents "OPTIONAL_COMPONENTS")
endif()
find_package(KF5 ${KF5_REQUIRED_VERSION} REQUIRED COMPONENTS
Archive
Bookmarks
Completion
Config
ConfigWidgets
CoreAddons
Crash
IconThemes
KIO
Parts
ThreadWeaver
WindowSystem
${optionalComponents}
DocTools
JS
Wallet
)
if(KF5Wallet_FOUND)
add_definitions(-DWITH_KWALLET=1)
endif()
if(KF5JS_FOUND)
add_definitions(-DWITH_KJS=1)
endif()
if(NOT WIN32 AND NOT ANDROID)
find_package(KF5 ${KF5_REQUIRED_VERSION} REQUIRED COMPONENTS
Activities
)
set_package_properties("KF5Activities" PROPERTIES
DESCRIPTION "Activities interface library"
URL "https://api.kde.org/frameworks/kactivities/html/"
TYPE RECOMMENDED
PURPOSE "Required for Activities integration.")
endif()
find_package(KF5Kirigami2)
set_package_properties(KF5Kirigami2 PROPERTIES
DESCRIPTION "A QtQuick based components set"
PURPOSE "Required at runtime by the mobile app"
TYPE RUNTIME
)
find_package(Phonon4Qt5 CONFIG REQUIRED)
find_package(KDEExperimentalPurpose)
set_package_properties(KDEExperimentalPurpose PROPERTIES
DESCRIPTION "A framework for services and actions integration"
PURPOSE "Required for enabling the share menu in Okular"
TYPE OPTIONAL
)
if (KDEExperimentalPurpose_FOUND)
set(PURPOSE_FOUND 1)
else()
set(PURPOSE_FOUND 0)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules)
find_package(ZLIB REQUIRED)
# This is here instead of in generators since we use if(Poppler_Qt5_FOUND) in autotests/
find_package(Poppler "0.12.1" COMPONENTS Qt5)
set_package_properties("Poppler" PROPERTIES
TYPE RECOMMENDED
PURPOSE "Support for PDF files in okular.")
add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
add_definitions(-DTRANSLATION_DOMAIN="okular")
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${PHONON_INCLUDES} core/synctex ${ZLIB_INCLUDE_DIR} ${CMAKE_BINARY_DIR}/core)
option(BUILD_OKULARKIRIGAMI "Builds the touch-friendly frontend" ON)
if (BUILD_OKULARKIRIGAMI)
add_subdirectory( mobile )
endif()
option(BUILD_COVERAGE "Build the project with gcov support" OFF)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0.0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override" )
endif()
endif()
if(BUILD_COVERAGE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov")
endif()
add_subdirectory( ui )
add_subdirectory( shell )
add_subdirectory( generators )
add_subdirectory( autotests )
add_subdirectory( conf/autotests )
if(KF5DocTools_FOUND)
add_subdirectory(doc)
endif()
include(OkularConfigureChecks.cmake)
if(NOT WIN32)
set(MATH_LIB m)
else(NOT WIN32)
set(MATH_LIB)
endif(NOT WIN32)
# okularcore
set(okularcore_SRCS
core/action.cpp
core/annotations.cpp
core/area.cpp
core/audioplayer.cpp
core/bookmarkmanager.cpp
core/chooseenginedialog.cpp
core/document.cpp
core/documentcommands.cpp
core/fontinfo.cpp
core/form.cpp
core/generator.cpp
core/generator_p.cpp
core/misc.cpp
core/movie.cpp
core/observer.cpp
core/debug.cpp
core/page.cpp
core/pagecontroller.cpp
core/pagesize.cpp
core/pagetransition.cpp
core/rotationjob.cpp
core/scripter.cpp
core/sound.cpp
core/sourcereference.cpp
core/textdocumentgenerator.cpp
core/textdocumentsettings.cpp
core/textpage.cpp
core/tilesmanager.cpp
core/utils.cpp
core/view.cpp
core/fileprinter.cpp
core/signatureutils.cpp
core/script/event.cpp
core/synctex/synctex_parser.c
core/synctex/synctex_parser_utils.c
)
qt5_add_resources(okularcore_SRCS
core/script/builtin.qrc
)
ki18n_wrap_ui(okularcore_SRCS
conf/textdocumentsettings.ui
)
install( FILES
core/action.h
core/annotations.h
core/area.h
core/document.h
core/fontinfo.h
core/form.h
core/generator.h
core/global.h
core/page.h
core/pagesize.h
core/pagetransition.h
core/signatureutils.h
core/sound.h
core/sourcereference.h
core/textdocumentgenerator.h
core/textdocumentsettings.h
core/textpage.h
core/tile.h
core/utils.h
core/fileprinter.h
core/observer.h
${CMAKE_CURRENT_BINARY_DIR}/core/version.h
${CMAKE_CURRENT_BINARY_DIR}/core/okularcore_export.h
${CMAKE_CURRENT_BINARY_DIR}/settings_core.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/okular/core COMPONENT Devel)
install( FILES
interfaces/configinterface.h
interfaces/guiinterface.h
interfaces/printinterface.h
interfaces/saveinterface.h
interfaces/viewerinterface.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/okular/interfaces COMPONENT Devel)
ki18n_wrap_ui(okularcore_SRCS
core/chooseenginewidget.ui
)
kconfig_add_kcfg_files(okularcore_SRCS conf/settings_core.kcfgc)
add_library(okularcore SHARED ${okularcore_SRCS})
generate_export_header(okularcore BASE_NAME okularcore EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/core/okularcore_export.h")
if (ANDROID)
set(fileName ${CMAKE_BINARY_DIR}/Okular5Core-android-dependencies.xml)
file(WRITE "${fileName}" "\n"
"\n"
"\n")
install(FILES ${fileName} DESTINATION ${KDE_INSTALL_LIBDIR})
endif()
# Special handling for linking okularcore on OSX/Apple
IF(APPLE)
SET(OKULAR_IOKIT "-framework IOKit" CACHE STRING "Apple IOKit framework")
ENDIF(APPLE)
# Extra library needed by imported synctex code on Windows
if(WIN32)
set(SHLWAPI shlwapi)
endif(WIN32)
target_link_libraries(okularcore
PRIVATE
${OKULAR_IOKIT}
${SHLWAPI}
KF5::Archive
KF5::KIOCore
KF5::KIOWidgets
KF5::I18n
KF5::ThreadWeaver
KF5::Bookmarks
Phonon::phonon4qt5
${MATH_LIB}
${ZLIB_LIBRARIES}
PUBLIC # these are included from the installed headers
KF5::CoreAddons
KF5::XmlGui
KF5::ConfigGui
Qt5::PrintSupport
Qt5::Widgets
)
if (KF5Wallet_FOUND)
target_link_libraries(okularcore PRIVATE KF5::Wallet)
endif()
if (KF5JS_FOUND)
target_sources(okularcore PRIVATE
core/script/executor_kjs.cpp
core/script/kjs_app.cpp
core/script/kjs_console.cpp
core/script/kjs_data.cpp
core/script/kjs_document.cpp
core/script/kjs_field.cpp
core/script/kjs_fullscreen.cpp
core/script/kjs_field.cpp
core/script/kjs_spell.cpp
core/script/kjs_util.cpp
core/script/kjs_event.cpp
)
target_link_libraries(okularcore PRIVATE KF5::JS KF5::JSApi)
endif()
set_target_properties(okularcore PROPERTIES VERSION 9.0.0 SOVERSION 9 OUTPUT_NAME Okular5Core EXPORT_NAME Core)
install(TARGETS okularcore EXPORT Okular5Targets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES conf/okular.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR})
install(FILES conf/okular_core.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR})
install(FILES core/okularGenerator.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR})
# okularpart
set(okularpart_conf_SRCS
conf/preferencesdialog.cpp
conf/dlgaccessibility.cpp
conf/dlgdebug.cpp
conf/dlgeditor.cpp
conf/dlggeneral.cpp
conf/dlgannotations.cpp
conf/dlgperformance.cpp
conf/dlgpresentation.cpp
conf/editannottooldialog.cpp
conf/editdrawingtooldialog.cpp
conf/widgetannottools.cpp
conf/widgetconfigurationtoolsbase.cpp
conf/widgetdrawingtools.cpp
)
set(okularpart_SRCS
${okularpart_conf_SRCS}
part.cpp
extensions.cpp
ui/embeddedfilesdialog.cpp
ui/annotwindow.cpp
ui/annotationmodel.cpp
ui/annotationpopup.cpp
ui/annotationpropertiesdialog.cpp
ui/annotationproxymodels.cpp
ui/annotationtools.cpp
ui/annotationwidgets.cpp
ui/bookmarklist.cpp
- ui/certificateviewer.cpp
ui/debug_ui.cpp
ui/drawingtoolactions.cpp
ui/fileprinterpreview.cpp
ui/findbar.cpp
ui/formwidgets.cpp
ui/guiutils.cpp
ui/ktreeviewsearchline.cpp
ui/latexrenderer.cpp
ui/minibar.cpp
ui/okmenutitle.cpp
ui/pageitemdelegate.cpp
ui/pagepainter.cpp
ui/pagesizelabel.cpp
ui/pageviewannotator.cpp
ui/pageviewmouseannotation.cpp
ui/pageview.cpp
ui/magnifierview.cpp
ui/pageviewutils.cpp
ui/presentationsearchbar.cpp
ui/presentationwidget.cpp
ui/propertiesdialog.cpp
ui/searchlineedit.cpp
ui/searchwidget.cpp
ui/sidebar.cpp
ui/side_reviews.cpp
ui/snapshottaker.cpp
ui/thumbnaillist.cpp
ui/toc.cpp
ui/tocmodel.cpp
ui/toolaction.cpp
ui/videowidget.cpp
ui/layers.cpp
ui/signaturemodel.cpp
ui/signaturepanel.cpp
ui/signaturewidgets.cpp
)
if (Qt5TextToSpeech_FOUND)
set(okularpart_SRCS ${okularpart_SRCS}
ui/tts.cpp)
endif()
ki18n_wrap_ui(okularpart_SRCS
conf/dlgaccessibilitybase.ui
conf/dlgeditorbase.ui
conf/dlggeneralbase.ui
conf/dlgannotationsbase.ui
conf/dlgperformancebase.ui
conf/dlgpresentationbase.ui
)
kconfig_add_kcfg_files(okularpart_SRCS conf/settings.kcfgc)
add_library(okularpart SHARED ${okularpart_SRCS})
generate_export_header(okularpart BASE_NAME okularpart)
target_link_libraries(okularpart okularcore
${MATH_LIB}
Qt5::Svg
Phonon::phonon4qt5
KF5::Archive
KF5::Bookmarks
KF5::I18n
KF5::IconThemes
KF5::ItemViews
KF5::KIOCore
KF5::KIOFileWidgets
KF5::KIOWidgets
KF5::Parts
KF5::Solid
KF5::WindowSystem
)
if(KF5Wallet_FOUND)
target_link_libraries(okularpart KF5::Wallet)
endif()
if (KDEExperimentalPurpose_FOUND)
target_link_libraries(okularpart KDEExperimental::PurposeWidgets)
endif()
set_target_properties(okularpart PROPERTIES PREFIX "")
if (Qt5TextToSpeech_FOUND)
target_link_libraries(okularpart Qt5::TextToSpeech)
endif()
install(TARGETS okularpart DESTINATION ${KDE_INSTALL_PLUGINDIR})
########### install files ###############
install(FILES okular.upd DESTINATION ${KDE_INSTALL_DATADIR}/kconf_update)
install( FILES okular_part.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} )
install( FILES part.rc part-viewermode.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/okular )
install( FILES okular.categories DESTINATION ${KDE_INSTALL_CONFDIR} )
########### cmake files #################
set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/Okular5")
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/Okular5Config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/Okular5Config.cmake"
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
PATH_VARS INCLUDE_INSTALL_DIR CMAKE_INSTALL_PREFIX
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/Okular5Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/Okular5ConfigVersion.cmake"
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
COMPONENT Devel
)
install(EXPORT Okular5Targets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE Okular5Targets.cmake NAMESPACE Okular::)
########### summary #################
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
diff --git a/ui/certificateviewer.cpp b/ui/certificateviewer.cpp
deleted file mode 100644
index c39464eb9..000000000
--- a/ui/certificateviewer.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2018 by Chinmoy Ranjan Pradhan *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- ***************************************************************************/
-
-#include "certificateviewer.h"
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "core/form.h"
-#include "core/page.h"
-#include "core/document.h"
-#include "core/sourcereference.h"
-#include "core/form.h"
-#include "settings.h"
-#include "guiutils.h"
-
-
-CertificateViewerModel::CertificateViewerModel( Okular::SignatureInfo *sigInfo, QObject * parent )
- : QAbstractTableModel( parent )
-{
- m_sigProperties.append( qMakePair( i18n("Subject Name"), sigInfo->signerName() ) );
- m_sigProperties.append( qMakePair( i18n("Subject Distinguished Name"), sigInfo->signerSubjectDN() ) );
- m_sigProperties.append( qMakePair( i18n("Signing Time"), sigInfo->signingTime().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) );
- m_sigProperties.append( qMakePair( i18n("Hash Algorithm"), GuiUtils::getReadableHashAlgorithm( sigInfo->hashAlgorithm() ) ) );
- m_sigProperties.append( qMakePair( i18n("Signature Status"), GuiUtils::getReadableSigState( sigInfo->signatureStatus() ) ) );
- m_sigProperties.append( qMakePair( i18n("Certificate Status"), GuiUtils::getReadableCertState( sigInfo->certificateStatus() ) ) );
- m_sigProperties.append( qMakePair( i18n("Signature Data"), QString::fromUtf8( sigInfo->signature().toHex(' ') ) ) );
- m_sigProperties.append( qMakePair( i18n("Location"), QString( sigInfo->location() ) ) );
- m_sigProperties.append( qMakePair( i18n("Reason"), QString( sigInfo->reason() ) ) );
- m_sigProperties.append( qMakePair( QStringLiteral("----------"), QString("------Certificate Properties--------") ) );
-
- Okular::CertificateInfo *certInfo = sigInfo->certificateInfo();
- m_sigProperties.append( qMakePair( i18n("Version"), QString("V" + QString::number(certInfo->version()) ) ) );
- m_sigProperties.append( qMakePair( i18n("Issuer Name"), certInfo->issuerInfo(Okular::CertificateInfo::CommonName) ) );
- m_sigProperties.append( qMakePair( i18n("Issuer Distinguished Name"), certInfo->issuerInfo(Okular::CertificateInfo::DistinguishedName) ) );
- m_sigProperties.append( qMakePair( i18n("Serial Number"), certInfo->serialNumber().toHex(' ') ) );
- m_sigProperties.append( qMakePair( i18n("Validity Start"), certInfo->validityStart().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) );
- m_sigProperties.append( qMakePair( i18n("Validity End"), certInfo->validityEnd().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) );
- m_sigProperties.append( qMakePair( i18n("Public Key"), certInfo->publicKey().toHex(' ') ) );
- m_sigProperties.append( qMakePair( i18n("Is Self Signed"), certInfo->isSelfSigned() ? QString("true") : QString("false") ) );
-}
-
-
-int CertificateViewerModel::columnCount( const QModelIndex & ) const
-{
- return 2;
-}
-
-int CertificateViewerModel::rowCount( const QModelIndex & ) const
-{
- return m_sigProperties.size();
-}
-
-QVariant CertificateViewerModel::data( const QModelIndex &index, int role ) const
-{
- int row = index.row();
- if ( !index.isValid() || row < 0 || row >= m_sigProperties.count() )
- return QVariant();
-
- switch ( role )
- {
- case Qt::DisplayRole:
- case Qt::ToolTipRole:
- switch ( index.column() )
- {
- case 0:
- return m_sigProperties[row].first;
- case 1:
- return m_sigProperties[row].second;
- default:
- return QString();
- }
- case PropertyValueRole:
- return m_sigProperties[row].second;
- }
-
- return QVariant();
-}
-
-QVariant CertificateViewerModel::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( Okular::SignatureInfo *sigInfo, QWidget *parent )
- : QDialog( parent ), m_sigInfo( sigInfo )
-{
- setModal( true );
- setFixedSize( QSize( 450, 500 ));
- setWindowTitle( i18n("Signature Properties") );
-
- auto sigPropLabel = new QLabel( this );
- sigPropLabel->setText( i18n("Signature Properties:") );
-
- auto sigPropTree = new QTreeView( this );
- sigPropTree->setIndentation( 0 );
- m_sigPropModel = new CertificateViewerModel( m_sigInfo, this );
- sigPropTree->setModel( m_sigPropModel );
- connect( sigPropTree, &QTreeView::clicked, this, &CertificateViewer::updateText );
-
- m_sigPropText = new QTextEdit( this );
- m_sigPropText->setReadOnly( true );
-
- auto btnBox = new QDialogButtonBox( QDialogButtonBox::Close, this );
- btnBox->button( QDialogButtonBox::Close )->setDefault( true );
- connect( btnBox, &QDialogButtonBox::rejected, this, &CertificateViewer::reject );
-
- auto mainLayout = new QVBoxLayout( this );
- mainLayout->addWidget( sigPropLabel );
- mainLayout->addWidget( sigPropTree );
- mainLayout->addWidget( m_sigPropText );
- mainLayout->addWidget( btnBox );
- setLayout( mainLayout );
-}
-
-void CertificateViewer::updateText( const QModelIndex &index )
-{
- m_sigPropText->setText( m_sigPropModel->data( index, CertificateViewerModel::PropertyValueRole ).toString() );
-}
diff --git a/ui/certificateviewer.h b/ui/certificateviewer.h
deleted file mode 100644
index 6616d40b1..000000000
--- a/ui/certificateviewer.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2018 by Chinmoy Ranjan Pradhan *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- ***************************************************************************/
-
-#ifndef OKULAR_CERTIFICATEVIEWER_H
-#define OKULAR_CERTIFICATEVIEWER_H
-
-#include
-#include
-#include
-#include
-#include "core/signatureutils.h"
-#include "core/observer.h"
-#include "fileprinterpreview.h"
-#include "signaturemodel.h"
-
-class QTextEdit;
-
-namespace Okular {
- class Document;
- class FormFieldSignature;
- class SignatureInfo;
-}
-
-class CertificateViewerModel : public QAbstractTableModel
-{
- Q_OBJECT
-
- public:
- explicit CertificateViewerModel( Okular::SignatureInfo *sigInfo, QObject * parent = nullptr );
-
- enum {
- PropertyValueRole = Qt::UserRole
- };
-
- 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< QPair > m_sigProperties;
-};
-
-class CertificateViewer : public QDialog
-{
- Q_OBJECT
-
- public:
- CertificateViewer( Okular::SignatureInfo *sigInfo, QWidget *parent );
-
- private Q_SLOTS:
- void updateText( const QModelIndex &index );
-
- private:
- CertificateViewerModel *m_sigPropModel;
- QTextEdit *m_sigPropText;
- Okular::SignatureInfo *m_sigInfo;
-};
-
-#endif
diff --git a/ui/formwidgets.cpp b/ui/formwidgets.cpp
index 239ce8774..db92bcefc 100644
--- a/ui/formwidgets.cpp
+++ b/ui/formwidgets.cpp
@@ -1,1247 +1,1246 @@
/***************************************************************************
* Copyright (C) 2007 by Pino Toscano *
* Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group *
* company, info@kdab.com. Work sponsored by the *
* LiMux project of the city of Munich *
* Copyright (C) 2018 Intevation GmbH *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include "formwidgets.h"
#include "pageviewutils.h"
#include "signaturewidgets.h"
-#include "certificateviewer.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// local includes
#include "core/form.h"
#include "core/document.h"
#include "core/signatureutils.h"
#include "debug_ui.h"
FormWidgetsController::FormWidgetsController( Okular::Document *doc )
: QObject( doc ), m_doc( doc )
{
// emit changed signal when a form has changed
connect( this, &FormWidgetsController::formTextChangedByUndoRedo,
this, &FormWidgetsController::changed );
connect( this, &FormWidgetsController::formListChangedByUndoRedo,
this, &FormWidgetsController::changed );
connect( this, &FormWidgetsController::formComboChangedByUndoRedo,
this, &FormWidgetsController::changed );
// connect form modification signals to and from document
connect( this, &FormWidgetsController::formTextChangedByWidget,
doc, &Okular::Document::editFormText );
connect( doc, &Okular::Document::formTextChangedByUndoRedo,
this, &FormWidgetsController::formTextChangedByUndoRedo );
connect( this, &FormWidgetsController::formListChangedByWidget,
doc, &Okular::Document::editFormList );
connect( doc, &Okular::Document::formListChangedByUndoRedo,
this, &FormWidgetsController::formListChangedByUndoRedo );
connect( this, &FormWidgetsController::formComboChangedByWidget,
doc, &Okular::Document::editFormCombo );
connect( doc, &Okular::Document::formComboChangedByUndoRedo,
this, &FormWidgetsController::formComboChangedByUndoRedo );
connect( this, &FormWidgetsController::formButtonsChangedByWidget,
doc, &Okular::Document::editFormButtons );
connect( doc, &Okular::Document::formButtonsChangedByUndoRedo,
this, &FormWidgetsController::slotFormButtonsChangedByUndoRedo );
// Connect undo/redo signals
connect( this, &FormWidgetsController::requestUndo,
doc, &Okular::Document::undo );
connect( this, &FormWidgetsController::requestRedo,
doc, &Okular::Document::redo );
connect( doc, &Okular::Document::canUndoChanged,
this, &FormWidgetsController::canUndoChanged );
connect( doc, &Okular::Document::canRedoChanged,
this, &FormWidgetsController::canRedoChanged );
// Connect the generic formWidget refresh signal
connect( doc, &Okular::Document::refreshFormWidget,
this, &FormWidgetsController::refreshFormWidget );
}
FormWidgetsController::~FormWidgetsController()
{
}
void FormWidgetsController::signalAction( Okular::Action *a )
{
emit action( a );
}
void FormWidgetsController::registerRadioButton( FormWidgetIface *fwButton, Okular::FormFieldButton *formButton )
{
if ( !fwButton )
return;
QAbstractButton *button = dynamic_cast(fwButton);
if ( !button )
{
qWarning() << "fwButton is not a QAbstractButton" << fwButton;
return;
}
QList< RadioData >::iterator it = m_radios.begin(), itEnd = m_radios.end();
const int id = formButton->id();
m_buttons.insert( id, button );
for ( ; it != itEnd; ++it )
{
const QList< int >::const_iterator idsIt = qFind( (*it).ids, id );
if ( idsIt != (*it).ids.constEnd() )
{
qCDebug(OkularUiDebug) << "Adding id" << id << "To group including" << (*it).ids;
(*it).group->addButton( button );
(*it).group->setId( button, id );
return;
}
}
const QList< int > siblings = formButton->siblings();
RadioData newdata;
newdata.ids = siblings;
newdata.ids.append( id );
newdata.group = new QButtonGroup();
newdata.group->addButton( button );
newdata.group->setId( button, id );
// Groups of 1 (like checkboxes) can't be exclusive
if (siblings.isEmpty())
newdata.group->setExclusive( false );
connect( newdata.group, SIGNAL( buttonClicked(QAbstractButton* ) ),
this, SLOT( slotButtonClicked( QAbstractButton* ) ) );
m_radios.append( newdata );
}
void FormWidgetsController::dropRadioButtons()
{
QList< RadioData >::iterator it = m_radios.begin(), itEnd = m_radios.end();
for ( ; it != itEnd; ++it )
{
delete (*it).group;
}
m_radios.clear();
m_buttons.clear();
}
bool FormWidgetsController::canUndo()
{
return m_doc->canUndo();
}
bool FormWidgetsController::canRedo()
{
return m_doc->canRedo();
}
void FormWidgetsController::slotButtonClicked( QAbstractButton *button )
{
int pageNumber = -1;
CheckBoxEdit *check = qobject_cast< CheckBoxEdit * >( button );
if ( check )
{
// Checkboxes need to be uncheckable so if clicking a checked one
// disable the exclusive status temporarily and uncheck it
Okular::FormFieldButton *formButton = static_cast( check->formField() );
if ( formButton->state() ) {
const bool wasExclusive = button->group()->exclusive();
button->group()->setExclusive(false);
check->setChecked(false);
button->group()->setExclusive(wasExclusive);
}
pageNumber = check->pageItem()->pageNumber();
}
else if ( RadioButtonEdit *radio = qobject_cast< RadioButtonEdit * >( button ) )
{
pageNumber = radio->pageItem()->pageNumber();
}
const QList< QAbstractButton* > buttons = button->group()->buttons();
QList< bool > checked;
QList< bool > prevChecked;
QList< Okular::FormFieldButton*> formButtons;
foreach ( QAbstractButton* button, buttons )
{
checked.append( button->isChecked() );
Okular::FormFieldButton *formButton = static_cast( dynamic_cast(button)->formField() );
formButtons.append( formButton );
prevChecked.append( formButton->state() );
}
if (checked != prevChecked)
emit formButtonsChangedByWidget( pageNumber, formButtons, checked );
if ( check )
{
// The formButtonsChangedByWidget signal changes the value of the underlying
// Okular::FormField of the checkbox. We need to execute the activiation
// action after this.
check->doActivateAction();
}
}
void FormWidgetsController::slotFormButtonsChangedByUndoRedo( int pageNumber, const QList< Okular::FormFieldButton* > & formButtons)
{
foreach ( Okular::FormFieldButton* formButton, formButtons )
{
int id = formButton->id();
QAbstractButton* button = m_buttons[id];
CheckBoxEdit *check = qobject_cast< CheckBoxEdit * >( button );
if ( check )
{
emit refreshFormWidget( check->formField() );
}
// temporarily disable exclusiveness of the button group
// since it breaks doing/redoing steps into which all the checkboxes
// are unchecked
const bool wasExclusive = button->group()->exclusive();
button->group()->setExclusive(false);
bool checked = formButton->state();
button->setChecked( checked );
button->group()->setExclusive(wasExclusive);
button->setFocus();
}
emit changed( pageNumber );
}
FormWidgetIface * FormWidgetFactory::createWidget( Okular::FormField * ff, QWidget * parent )
{
FormWidgetIface * widget = nullptr;
switch ( ff->type() )
{
case Okular::FormField::FormButton:
{
Okular::FormFieldButton * ffb = static_cast< Okular::FormFieldButton * >( ff );
switch ( ffb->buttonType() )
{
case Okular::FormFieldButton::Push:
widget = new PushButtonEdit( ffb, parent );
break;
case Okular::FormFieldButton::CheckBox:
widget = new CheckBoxEdit( ffb, parent );
break;
case Okular::FormFieldButton::Radio:
widget = new RadioButtonEdit( ffb, parent );
break;
default: ;
}
break;
}
case Okular::FormField::FormText:
{
Okular::FormFieldText * fft = static_cast< Okular::FormFieldText * >( ff );
switch ( fft->textType() )
{
case Okular::FormFieldText::Multiline:
widget = new TextAreaEdit( fft, parent );
break;
case Okular::FormFieldText::Normal:
widget = new FormLineEdit( fft, parent );
break;
case Okular::FormFieldText::FileSelect:
widget = new FileEdit( fft, parent );
break;
}
break;
}
case Okular::FormField::FormChoice:
{
Okular::FormFieldChoice * ffc = static_cast< Okular::FormFieldChoice * >( ff );
switch ( ffc->choiceType() )
{
case Okular::FormFieldChoice::ListBox:
widget = new ListEdit( ffc, parent );
break;
case Okular::FormFieldChoice::ComboBox:
widget = new ComboEdit( ffc, parent );
break;
}
break;
}
case Okular::FormField::FormSignature:
{
Okular::FormFieldSignature * ffs = static_cast< Okular::FormFieldSignature * >( ff );
if ( ffs->isVisible() && ffs->signatureType() != Okular::FormFieldSignature::UnknownType )
widget = new SignatureEdit( ffs, parent );
break;
}
default: ;
}
if ( ff->isReadOnly() )
widget->setVisibility( false );
return widget;
}
FormWidgetIface::FormWidgetIface( QWidget * w, Okular::FormField * ff )
: m_controller( nullptr ), m_ff( ff ), m_widget( w ), m_pageItem( nullptr )
{
}
FormWidgetIface::~FormWidgetIface()
{
m_ff = nullptr;
}
Okular::NormalizedRect FormWidgetIface::rect() const
{
return m_ff->rect();
}
void FormWidgetIface::setWidthHeight( int w, int h )
{
m_widget->resize( w, h );
}
void FormWidgetIface::moveTo( int x, int y )
{
m_widget->move( x, y );
}
bool FormWidgetIface::setVisibility( bool visible )
{
bool hadfocus = m_widget->hasFocus();
if ( hadfocus )
m_widget->clearFocus();
m_widget->setVisible( visible );
return hadfocus;
}
void FormWidgetIface::setCanBeFilled( bool fill )
{
m_widget->setEnabled( fill );
}
void FormWidgetIface::setPageItem( PageViewItem *pageItem )
{
m_pageItem = pageItem;
}
void FormWidgetIface::setFormField( Okular::FormField *field )
{
m_ff = field;
}
Okular::FormField* FormWidgetIface::formField() const
{
return m_ff;
}
PageViewItem* FormWidgetIface::pageItem() const
{
return m_pageItem;
}
void FormWidgetIface::setFormWidgetsController( FormWidgetsController *controller )
{
m_controller = controller;
QObject *obj = dynamic_cast< QObject * > ( this );
QObject::connect( m_controller, &FormWidgetsController::refreshFormWidget, obj,
[this] ( Okular::FormField *form ) {
slotRefresh ( form );
});
}
void FormWidgetIface::slotRefresh( Okular::FormField * form )
{
if ( m_ff != form )
{
return;
}
setVisibility( form->isVisible() && !form->isReadOnly() );
m_widget->setEnabled( !form->isReadOnly() );
}
PushButtonEdit::PushButtonEdit( Okular::FormFieldButton * button, QWidget * parent )
: QPushButton( parent ), FormWidgetIface( this, button )
{
setText( button->caption() );
setVisible( button->isVisible() );
setCursor( Qt::ArrowCursor );
}
CheckBoxEdit::CheckBoxEdit( Okular::FormFieldButton * button, QWidget * parent )
: QCheckBox( parent ), FormWidgetIface( this, button )
{
setText( button->caption() );
setVisible( button->isVisible() );
setCursor( Qt::ArrowCursor );
}
void CheckBoxEdit::setFormWidgetsController( FormWidgetsController *controller )
{
Okular::FormFieldButton *form = static_cast(m_ff);
FormWidgetIface::setFormWidgetsController( controller );
m_controller->registerRadioButton( this, form );
setChecked( form->state() );
}
void CheckBoxEdit::doActivateAction()
{
Okular::FormFieldButton *form = static_cast(m_ff);
if ( form->activationAction() )
m_controller->signalAction( form->activationAction() );
}
void CheckBoxEdit::slotRefresh( Okular::FormField * form )
{
if ( form != m_ff )
{
return;
}
FormWidgetIface::slotRefresh( form );
Okular::FormFieldButton *button = static_cast(m_ff);
bool oldState = isChecked();
bool newState = button->state();
if ( oldState != newState )
{
setChecked( button->state() );
doActivateAction();
}
}
RadioButtonEdit::RadioButtonEdit( Okular::FormFieldButton * button, QWidget * parent )
: QRadioButton( parent ), FormWidgetIface( this, button )
{
setText( button->caption() );
setVisible( button->isVisible() );
setCursor( Qt::ArrowCursor );
}
void RadioButtonEdit::setFormWidgetsController( FormWidgetsController *controller )
{
Okular::FormFieldButton *form = static_cast(m_ff);
FormWidgetIface::setFormWidgetsController( controller );
m_controller->registerRadioButton( this, form );
setChecked( form->state() );
}
FormLineEdit::FormLineEdit( Okular::FormFieldText * text, QWidget * parent )
: QLineEdit( parent ), FormWidgetIface( this, text )
{
int maxlen = text->maximumLength();
if ( maxlen >= 0 )
setMaxLength( maxlen );
setAlignment( text->textAlignment() );
setText( text->text() );
if ( text->isPassword() )
setEchoMode( QLineEdit::Password );
m_prevCursorPos = cursorPosition();
m_prevAnchorPos = cursorPosition();
connect( this, &QLineEdit::textEdited, this, &FormLineEdit::slotChanged );
connect( this, &QLineEdit::cursorPositionChanged, this, &FormLineEdit::slotChanged );
setVisible( text->isVisible() );
}
void FormLineEdit::setFormWidgetsController(FormWidgetsController* controller)
{
FormWidgetIface::setFormWidgetsController(controller);
connect( m_controller, &FormWidgetsController::formTextChangedByUndoRedo,
this, &FormLineEdit::slotHandleTextChangedByUndoRedo );
}
bool FormLineEdit::event( QEvent* e )
{
if ( e->type() == QEvent::KeyPress )
{
QKeyEvent *keyEvent = static_cast< QKeyEvent* >( e );
if ( keyEvent == QKeySequence::Undo )
{
emit m_controller->requestUndo();
return true;
}
else if ( keyEvent == QKeySequence::Redo )
{
emit m_controller->requestRedo();
return true;
}
}
return QLineEdit::event( e );
}
void FormLineEdit::contextMenuEvent( QContextMenuEvent* event )
{
QMenu *menu = createStandardContextMenu();
QList actionList = menu->actions();
enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, DeleteAct, SelectAllAct };
QAction *kundo = KStandardAction::create( KStandardAction::Undo, m_controller, SIGNAL( requestUndo() ), menu );
QAction *kredo = KStandardAction::create( KStandardAction::Redo, m_controller, SIGNAL( requestRedo() ), menu );
connect( m_controller, &FormWidgetsController::canUndoChanged, kundo, &QAction::setEnabled );
connect( m_controller, &FormWidgetsController::canRedoChanged, kredo, &QAction::setEnabled );
kundo->setEnabled( m_controller->canUndo() );
kredo->setEnabled( m_controller->canRedo() );
QAction *oldUndo, *oldRedo;
oldUndo = actionList[UndoAct];
oldRedo = actionList[RedoAct];
menu->insertAction( oldUndo, kundo );
menu->insertAction( oldRedo, kredo );
menu->removeAction( oldUndo );
menu->removeAction( oldRedo );
menu->exec( event->globalPos() );
delete menu;
}
void FormLineEdit::slotChanged()
{
Okular::FormFieldText *form = static_cast(m_ff);
QString contents = text();
int cursorPos = cursorPosition();
if ( contents != form->text() )
{
m_controller->formTextChangedByWidget( pageItem()->pageNumber(),
form,
contents,
cursorPos,
m_prevCursorPos,
m_prevAnchorPos );
}
m_prevCursorPos = cursorPos;
m_prevAnchorPos = cursorPos;
if ( hasSelectedText() ) {
if ( cursorPos == selectionStart() ) {
m_prevAnchorPos = selectionStart() + selectedText().size();
} else {
m_prevAnchorPos = selectionStart();
}
}
}
void FormLineEdit::slotHandleTextChangedByUndoRedo( int pageNumber,
Okular::FormFieldText* textForm,
const QString & contents,
int cursorPos,
int anchorPos )
{
Q_UNUSED(pageNumber);
if ( textForm != m_ff || contents == text() )
{
return;
}
disconnect( this, &QLineEdit::cursorPositionChanged, this, &FormLineEdit::slotChanged );
setText(contents);
setCursorPosition(anchorPos);
cursorForward( true, cursorPos - anchorPos );
connect( this, &QLineEdit::cursorPositionChanged, this, &FormLineEdit::slotChanged );
m_prevCursorPos = cursorPos;
m_prevAnchorPos = anchorPos;
setFocus();
}
void FormLineEdit::slotRefresh( Okular::FormField *form )
{
if (form != m_ff)
{
return;
}
FormWidgetIface::slotRefresh( form );
Okular::FormFieldText *text = static_cast ( form );
setText( text->text() );
}
TextAreaEdit::TextAreaEdit( Okular::FormFieldText * text, QWidget * parent )
: KTextEdit( parent ), FormWidgetIface( this, text )
{
setAcceptRichText( text->isRichText() );
setCheckSpellingEnabled( text->canBeSpellChecked() );
setAlignment( text->textAlignment() );
setPlainText( text->text() );
setUndoRedoEnabled( false );
connect( this, &QTextEdit::textChanged, this, &TextAreaEdit::slotChanged );
connect( this, &QTextEdit::cursorPositionChanged, this, &TextAreaEdit::slotChanged );
connect( this, &KTextEdit::aboutToShowContextMenu,
this, &TextAreaEdit::slotUpdateUndoAndRedoInContextMenu );
m_prevCursorPos = textCursor().position();
m_prevAnchorPos = textCursor().anchor();
setVisible( text->isVisible() );
}
bool TextAreaEdit::event( QEvent* e )
{
if ( e->type() == QEvent::KeyPress )
{
QKeyEvent *keyEvent = static_cast< QKeyEvent* >(e);
if ( keyEvent == QKeySequence::Undo )
{
emit m_controller->requestUndo();
return true;
}
else if ( keyEvent == QKeySequence::Redo )
{
emit m_controller->requestRedo();
return true;
}
}
return KTextEdit::event( e );
}
void TextAreaEdit::slotUpdateUndoAndRedoInContextMenu( QMenu* menu )
{
if ( !menu ) return;
QList actionList = menu->actions();
enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, ClearAct, SelectAllAct, NCountActs };
QAction *kundo = KStandardAction::create( KStandardAction::Undo, m_controller, SIGNAL( requestUndo() ), menu );
QAction *kredo = KStandardAction::create( KStandardAction::Redo, m_controller, SIGNAL( requestRedo() ), menu );
connect(m_controller, &FormWidgetsController::canUndoChanged, kundo, &QAction::setEnabled );
connect(m_controller, &FormWidgetsController::canRedoChanged, kredo, &QAction::setEnabled );
kundo->setEnabled( m_controller->canUndo() );
kredo->setEnabled( m_controller->canRedo() );
QAction *oldUndo, *oldRedo;
oldUndo = actionList[UndoAct];
oldRedo = actionList[RedoAct];
menu->insertAction( oldUndo, kundo );
menu->insertAction( oldRedo, kredo );
menu->removeAction( oldUndo );
menu->removeAction( oldRedo );
}
void TextAreaEdit::setFormWidgetsController( FormWidgetsController* controller )
{
FormWidgetIface::setFormWidgetsController( controller );
connect( m_controller, &FormWidgetsController::formTextChangedByUndoRedo,
this, &TextAreaEdit::slotHandleTextChangedByUndoRedo );
}
void TextAreaEdit::slotHandleTextChangedByUndoRedo( int pageNumber,
Okular::FormFieldText* textForm,
const QString & contents,
int cursorPos,
int anchorPos )
{
Q_UNUSED(pageNumber);
if ( textForm != m_ff )
{
return;
}
setPlainText( contents );
QTextCursor c = textCursor();
c.setPosition( anchorPos );
c.setPosition( cursorPos,QTextCursor::KeepAnchor );
m_prevCursorPos = cursorPos;
m_prevAnchorPos = anchorPos;
setTextCursor( c );
setFocus();
}
void TextAreaEdit::slotChanged()
{
// happens on destruction
if (!m_ff)
return;
Okular::FormFieldText *form = static_cast(m_ff);
QString contents = toPlainText();
int cursorPos = textCursor().position();
if (contents != form->text())
{
m_controller->formTextChangedByWidget( pageItem()->pageNumber(),
form,
contents,
cursorPos,
m_prevCursorPos,
m_prevAnchorPos );
}
m_prevCursorPos = cursorPos;
m_prevAnchorPos = textCursor().anchor();
}
void TextAreaEdit::slotRefresh( Okular::FormField *form )
{
if (form != m_ff)
{
return;
}
FormWidgetIface::slotRefresh( form );
Okular::FormFieldText *text = static_cast ( form );
setPlainText( text->text() );
}
FileEdit::FileEdit( Okular::FormFieldText * text, QWidget * parent )
: KUrlRequester( parent ), FormWidgetIface( this, text )
{
setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly );
setFilter( i18n( "*|All Files" ) );
setUrl( QUrl::fromUserInput( text->text() ) );
lineEdit()->setAlignment( text->textAlignment() );
m_prevCursorPos = lineEdit()->cursorPosition();
m_prevAnchorPos = lineEdit()->cursorPosition();
connect( this, &KUrlRequester::textChanged, this, &FileEdit::slotChanged );
connect( lineEdit(), &QLineEdit::cursorPositionChanged, this, &FileEdit::slotChanged );
setVisible( text->isVisible() );
}
void FileEdit::setFormWidgetsController( FormWidgetsController* controller )
{
FormWidgetIface::setFormWidgetsController( controller );
connect( m_controller, &FormWidgetsController::formTextChangedByUndoRedo,
this, &FileEdit::slotHandleFileChangedByUndoRedo );
}
bool FileEdit::eventFilter( QObject* obj, QEvent* event )
{
if ( obj == lineEdit() ) {
if ( event->type() == QEvent::KeyPress )
{
QKeyEvent *keyEvent = static_cast< QKeyEvent* >( event );
if ( keyEvent == QKeySequence::Undo )
{
emit m_controller->requestUndo();
return true;
}
else if ( keyEvent == QKeySequence::Redo )
{
emit m_controller->requestRedo();
return true;
}
}
else if( event->type() == QEvent::ContextMenu )
{
QContextMenuEvent *contextMenuEvent = static_cast< QContextMenuEvent* >( event );
QMenu *menu = ( (QLineEdit*) lineEdit() )->createStandardContextMenu();
QList< QAction* > actionList = menu->actions();
enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, DeleteAct, SelectAllAct };
QAction *kundo = KStandardAction::create( KStandardAction::Undo, m_controller, SIGNAL( requestUndo() ), menu );
QAction *kredo = KStandardAction::create( KStandardAction::Redo, m_controller, SIGNAL( requestRedo() ), menu );
connect(m_controller, &FormWidgetsController::canUndoChanged, kundo, &QAction::setEnabled );
connect(m_controller, &FormWidgetsController::canRedoChanged, kredo, &QAction::setEnabled );
kundo->setEnabled( m_controller->canUndo() );
kredo->setEnabled( m_controller->canRedo() );
QAction *oldUndo, *oldRedo;
oldUndo = actionList[UndoAct];
oldRedo = actionList[RedoAct];
menu->insertAction( oldUndo, kundo );
menu->insertAction( oldRedo, kredo );
menu->removeAction( oldUndo );
menu->removeAction( oldRedo );
menu->exec( contextMenuEvent->globalPos() );
delete menu;
return true;
}
}
return KUrlRequester::eventFilter( obj, event );
}
void FileEdit::slotChanged()
{
// Make sure line edit's text matches url expansion
if ( text() != url().toLocalFile() )
this->setText( url().toLocalFile() );
Okular::FormFieldText *form = static_cast(m_ff);
QString contents = text();
int cursorPos = lineEdit()->cursorPosition();
if (contents != form->text())
{
m_controller->formTextChangedByWidget( pageItem()->pageNumber(),
form,
contents,
cursorPos,
m_prevCursorPos,
m_prevAnchorPos );
}
m_prevCursorPos = cursorPos;
m_prevAnchorPos = cursorPos;
if ( lineEdit()->hasSelectedText() ) {
if ( cursorPos == lineEdit()->selectionStart() ) {
m_prevAnchorPos = lineEdit()->selectionStart() + lineEdit()->selectedText().size();
} else {
m_prevAnchorPos = lineEdit()->selectionStart();
}
}
}
void FileEdit::slotHandleFileChangedByUndoRedo( int pageNumber,
Okular::FormFieldText* form,
const QString & contents,
int cursorPos,
int anchorPos )
{
Q_UNUSED(pageNumber);
if ( form != m_ff || contents == text() )
{
return;
}
disconnect( this, SIGNAL( cursorPositionChanged( int, int ) ), this, SLOT( slotChanged() ) );
setText( contents );
lineEdit()->setCursorPosition( anchorPos );
lineEdit()->cursorForward( true, cursorPos - anchorPos );
connect( this, SIGNAL(cursorPositionChanged( int, int ) ), this, SLOT( slotChanged() ) );
m_prevCursorPos = cursorPos;
m_prevAnchorPos = anchorPos;
setFocus();
}
ListEdit::ListEdit( Okular::FormFieldChoice * choice, QWidget * parent )
: QListWidget( parent ), FormWidgetIface( this, choice )
{
addItems( choice->choices() );
setSelectionMode( choice->multiSelect() ? QAbstractItemView::ExtendedSelection : QAbstractItemView::SingleSelection );
setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
QList< int > selectedItems = choice->currentChoices();
if ( choice->multiSelect() )
{
foreach ( int index, selectedItems )
if ( index >= 0 && index < count() )
item( index )->setSelected( true );
}
else
{
if ( selectedItems.count() == 1 && selectedItems.at(0) >= 0 && selectedItems.at(0) < count() )
{
setCurrentRow( selectedItems.at(0) );
scrollToItem( item( selectedItems.at(0) ) );
}
}
connect( this, &QListWidget::itemSelectionChanged, this, &ListEdit::slotSelectionChanged );
setVisible( choice->isVisible() );
setCursor( Qt::ArrowCursor );
}
void ListEdit::setFormWidgetsController( FormWidgetsController* controller )
{
FormWidgetIface::setFormWidgetsController( controller );
connect( m_controller, &FormWidgetsController::formListChangedByUndoRedo,
this, &ListEdit::slotHandleFormListChangedByUndoRedo );
}
void ListEdit::slotSelectionChanged()
{
QList< QListWidgetItem * > selection = selectedItems();
QList< int > rows;
foreach( const QListWidgetItem * item, selection )
rows.append( row( item ) );
Okular::FormFieldChoice *form = static_cast(m_ff);
if ( rows != form->currentChoices() ) {
m_controller->formListChangedByWidget( pageItem()->pageNumber(),
form,
rows );
}
}
void ListEdit::slotHandleFormListChangedByUndoRedo( int pageNumber,
Okular::FormFieldChoice* listForm,
const QList< int > & choices )
{
Q_UNUSED(pageNumber);
if ( m_ff != listForm ) {
return;
}
disconnect( this, &QListWidget::itemSelectionChanged, this, &ListEdit::slotSelectionChanged );
for(int i=0; i < count(); i++)
{
item( i )->setSelected( choices.contains(i) );
}
connect( this, &QListWidget::itemSelectionChanged, this, &ListEdit::slotSelectionChanged );
setFocus();
}
ComboEdit::ComboEdit( Okular::FormFieldChoice * choice, QWidget * parent )
: QComboBox( parent ), FormWidgetIface( this, choice )
{
addItems( choice->choices() );
setEditable( true );
setInsertPolicy( NoInsert );
lineEdit()->setReadOnly( !choice->isEditable() );
QList< int > selectedItems = choice->currentChoices();
if ( selectedItems.count() == 1 && selectedItems.at(0) >= 0 && selectedItems.at(0) < count() )
setCurrentIndex( selectedItems.at(0) );
if ( choice->isEditable() && !choice->editChoice().isEmpty() )
lineEdit()->setText( choice->editChoice() );
connect( this, SIGNAL(currentIndexChanged(int)), this, SLOT(slotValueChanged()) );
connect( this, &QComboBox::editTextChanged, this, &ComboEdit::slotValueChanged );
connect( lineEdit(), &QLineEdit::cursorPositionChanged, this, &ComboEdit::slotValueChanged );
setVisible( choice->isVisible() );
setCursor( Qt::ArrowCursor );
m_prevCursorPos = lineEdit()->cursorPosition();
m_prevAnchorPos = lineEdit()->cursorPosition();
}
void ComboEdit::setFormWidgetsController(FormWidgetsController* controller)
{
FormWidgetIface::setFormWidgetsController(controller);
connect( m_controller, &FormWidgetsController::formComboChangedByUndoRedo,
this, &ComboEdit::slotHandleFormComboChangedByUndoRedo);
}
void ComboEdit::slotValueChanged()
{
const QString text = lineEdit()->text();
Okular::FormFieldChoice *form = static_cast(m_ff);
QString prevText;
if ( form->currentChoices().isEmpty() )
{
prevText = form->editChoice();
}
else
{
prevText = form->choices()[form->currentChoices()[0]];
}
int cursorPos = lineEdit()->cursorPosition();
if ( text != prevText )
{
m_controller->formComboChangedByWidget( pageItem()->pageNumber(),
form,
currentText(),
cursorPos,
m_prevCursorPos,
m_prevAnchorPos
);
}
prevText = text;
m_prevCursorPos = cursorPos;
m_prevAnchorPos = cursorPos;
if ( lineEdit()->hasSelectedText() ) {
if ( cursorPos == lineEdit()->selectionStart() ) {
m_prevAnchorPos = lineEdit()->selectionStart() + lineEdit()->selectedText().size();
} else {
m_prevAnchorPos = lineEdit()->selectionStart();
}
}
}
void ComboEdit::slotHandleFormComboChangedByUndoRedo( int pageNumber,
Okular::FormFieldChoice* form,
const QString & text,
int cursorPos,
int anchorPos )
{
Q_UNUSED(pageNumber);
if ( m_ff != form ) {
return;
}
// Determine if text corrisponds to an index choices
int index = -1;
for ( int i = 0; i < count(); i++ )
{
if ( itemText(i) == text )
{
index = i;
}
}
m_prevCursorPos = cursorPos;
m_prevAnchorPos = anchorPos;
disconnect( lineEdit(), &QLineEdit::cursorPositionChanged, this, &ComboEdit::slotValueChanged );
const bool isCustomValue = index == -1;
if ( isCustomValue )
{
setEditText( text );
}
else
{
setCurrentIndex( index );
}
lineEdit()->setCursorPosition( anchorPos );
lineEdit()->cursorForward( true, cursorPos - anchorPos );
connect( lineEdit(), &QLineEdit::cursorPositionChanged, this, &ComboEdit::slotValueChanged );
setFocus();
}
void ComboEdit::contextMenuEvent( QContextMenuEvent* event )
{
QMenu *menu = lineEdit()->createStandardContextMenu();
QList actionList = menu->actions();
enum { UndoAct, RedoAct, CutAct, CopyAct, PasteAct, DeleteAct, SelectAllAct };
QAction *kundo = KStandardAction::create( KStandardAction::Undo, m_controller, SIGNAL( requestUndo() ), menu );
QAction *kredo = KStandardAction::create( KStandardAction::Redo, m_controller, SIGNAL( requestRedo() ), menu );
connect( m_controller, &FormWidgetsController::canUndoChanged, kundo, &QAction::setEnabled );
connect( m_controller, &FormWidgetsController::canRedoChanged, kredo, &QAction::setEnabled );
kundo->setEnabled( m_controller->canUndo() );
kredo->setEnabled( m_controller->canRedo() );
QAction *oldUndo, *oldRedo;
oldUndo = actionList[UndoAct];
oldRedo = actionList[RedoAct];
menu->insertAction( oldUndo, kundo );
menu->insertAction( oldRedo, kredo );
menu->removeAction( oldUndo );
menu->removeAction( oldRedo );
menu->exec( event->globalPos() );
delete menu;
}
bool ComboEdit::event( QEvent* e )
{
if ( e->type() == QEvent::KeyPress )
{
QKeyEvent *keyEvent = static_cast< QKeyEvent* >(e);
if ( keyEvent == QKeySequence::Undo )
{
emit m_controller->requestUndo();
return true;
}
else if ( keyEvent == QKeySequence::Redo )
{
emit m_controller->requestRedo();
return true;
}
}
return QComboBox::event( e );
}
SignatureEdit::SignatureEdit( Okular::FormFieldSignature * signature, QWidget * parent )
: QAbstractButton( parent ), FormWidgetIface( this, signature ),
m_leftMouseButtonPressed( false )
{
// Okular::FormFieldSignature *sigField = static_cast< Okular::FormFieldSignature * >( formField() );
// m_sigInfo = sigField->validate();
setCheckable( false );
setCursor( Qt::PointingHandCursor );
connect( this, &SignatureEdit::clicked, this, &SignatureEdit::slotShowSummary );
}
bool SignatureEdit::event( QEvent * e )
{
switch ( e->type() )
{
case QEvent::MouseButtonPress:
{
QMouseEvent *ev = static_cast< QMouseEvent * >( e );
if ( ev->button() == Qt::LeftButton )
{
m_leftMouseButtonPressed = true;
update();
}
mousePressEvent( ev );
break;
}
case QEvent::MouseButtonRelease:
{
QMouseEvent *ev = static_cast< QMouseEvent * >( e );
m_leftMouseButtonPressed = false;
if ( ev->button() == Qt::LeftButton)
{
update();
}
mouseReleaseEvent( ev );
break;
}
default:
break;
}
return QAbstractButton::event( e );
}
void SignatureEdit::contextMenuEvent( QContextMenuEvent * event )
{
QMenu *menu = new QMenu( this );
QAction *sigVal = new QAction( i18n("Validate Signature"), this );
menu->addAction( sigVal );
connect( sigVal, &QAction::triggered, this, &SignatureEdit::slotShowSummary );
QAction *sigProp = new QAction( i18n("Show Signature Properties"), this );
menu->addAction( sigProp );
connect( sigProp, &QAction::triggered, this, &SignatureEdit::slotShowProperties );
menu->exec( event->globalPos() );
delete menu;
}
void SignatureEdit::paintEvent( QPaintEvent * )
{
QPainter painter( this );
painter.setPen( Qt::black );
if ( m_leftMouseButtonPressed )
{
QColor col = palette().color( QPalette::Active, QPalette::Highlight );
col.setAlpha(50);
painter.setBrush( col );
}
else
{
painter.setBrush( Qt::transparent );
}
painter.drawRect( 0, 0, width()-2, height()-2 );
}
Okular::SignatureInfo *SignatureEdit::validate()
{
Okular::FormFieldSignature *sigField = static_cast< Okular::FormFieldSignature * >( formField() );
m_sigInfo = sigField->validate();
m_signatureValidated = true;
return m_sigInfo;
}
void SignatureEdit::slotShowSummary()
{
Okular::FormFieldSignature *signatureForm = static_cast< Okular::FormFieldSignature * >( formField() );
SignaturePropertiesDialog sigSummaryDlg( m_controller->m_doc, signatureForm, this );
sigSummaryDlg.exec();
}
void SignatureEdit::slotShowProperties()
{
CertificateViewer sigPropDlg( m_sigInfo, this );
sigPropDlg.exec();
}
// Code for additional action handling.
// Challenge: Change preprocessor magic to C++ magic!
//
// The mouseRelease event is special because the PDF spec
// says that the activation action takes precedence over this.
// So the mouse release action is only signaled if no activation
// action exists.
//
// For checkboxes the activation action is not triggered as
// they are still triggered from the clicked signal and additionally
// when the checked state changes.
#define DEFINE_ADDITIONAL_ACTIONS(FormClass, BaseClass) \
void FormClass::mousePressEvent( QMouseEvent *event ) \
{ \
Okular::Action *act = m_ff->additionalAction( Okular::Annotation::MousePressed ); \
if ( act ) \
{ \
m_controller->signalAction( act ); \
} \
BaseClass::mousePressEvent( event ); \
} \
void FormClass::mouseReleaseEvent( QMouseEvent *event ) \
{ \
if ( !QWidget::rect().contains( event->localPos().toPoint() ) ) \
{ \
BaseClass::mouseReleaseEvent( event ); \
return; \
} \
Okular::Action *act = m_ff->activationAction(); \
if ( act && !qobject_cast< CheckBoxEdit* > ( this ) ) \
{ \
m_controller->signalAction( act ); \
} \
else if ( ( act = m_ff->additionalAction( Okular::Annotation::MouseReleased ) ) ) \
{ \
m_controller->signalAction( act ); \
} \
BaseClass::mouseReleaseEvent( event ); \
} \
void FormClass::focusInEvent( QFocusEvent *event ) \
{ \
Okular::Action *act = m_ff->additionalAction( Okular::Annotation::FocusIn ); \
if ( act ) \
{ \
m_controller->signalAction( act ); \
} \
BaseClass::focusInEvent( event ); \
} \
void FormClass::focusOutEvent( QFocusEvent *event ) \
{ \
Okular::Action *act = m_ff->additionalAction( Okular::Annotation::FocusOut ); \
if ( act ) \
{ \
m_controller->signalAction( act ); \
} \
BaseClass::focusOutEvent( event ); \
} \
void FormClass::leaveEvent( QEvent *event ) \
{ \
Okular::Action *act = m_ff->additionalAction( Okular::Annotation::CursorLeaving ); \
if ( act ) \
{ \
m_controller->signalAction( act ); \
} \
BaseClass::leaveEvent( event ); \
} \
void FormClass::enterEvent( QEvent *event ) \
{ \
Okular::Action *act = m_ff->additionalAction( Okular::Annotation::CursorEntering ); \
if ( act ) \
{ \
m_controller->signalAction( act ); \
} \
BaseClass::enterEvent( event ); \
}
DEFINE_ADDITIONAL_ACTIONS( PushButtonEdit, QPushButton )
DEFINE_ADDITIONAL_ACTIONS( CheckBoxEdit, QCheckBox )
DEFINE_ADDITIONAL_ACTIONS( RadioButtonEdit, QRadioButton )
DEFINE_ADDITIONAL_ACTIONS( FormLineEdit, QLineEdit )
DEFINE_ADDITIONAL_ACTIONS( TextAreaEdit, KTextEdit )
DEFINE_ADDITIONAL_ACTIONS( FileEdit, KUrlRequester )
DEFINE_ADDITIONAL_ACTIONS( ListEdit, QListWidget )
DEFINE_ADDITIONAL_ACTIONS( ComboEdit, QComboBox )
DEFINE_ADDITIONAL_ACTIONS( SignatureEdit, QAbstractButton )
#undef DEFINE_ADDITIONAL_ACTIONS
#include "moc_formwidgets.cpp"
diff --git a/ui/signaturewidgets.cpp b/ui/signaturewidgets.cpp
index 2b9bec9b5..0557930ab 100644
--- a/ui/signaturewidgets.cpp
+++ b/ui/signaturewidgets.cpp
@@ -1,168 +1,286 @@
/***************************************************************************
* Copyright (C) 2018 by Chinmoy Ranjan Pradhan *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include "signaturewidgets.h"
-#include "certificateviewer.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "core/form.h"
#include "core/page.h"
#include "core/document.h"
#include "core/sourcereference.h"
#include "core/form.h"
#include "settings.h"
#include "guiutils.h"
+
+CertificateViewerModel::CertificateViewerModel( Okular::SignatureInfo *sigInfo, QObject * parent )
+ : QAbstractTableModel( parent )
+{
+ m_sigProperties.append( qMakePair( i18n("Subject Name"), sigInfo->signerName() ) );
+ m_sigProperties.append( qMakePair( i18n("Subject Distinguished Name"), sigInfo->signerSubjectDN() ) );
+ m_sigProperties.append( qMakePair( i18n("Signing Time"), sigInfo->signingTime().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) );
+ m_sigProperties.append( qMakePair( i18n("Hash Algorithm"), GuiUtils::getReadableHashAlgorithm( sigInfo->hashAlgorithm() ) ) );
+ m_sigProperties.append( qMakePair( i18n("Signature Status"), GuiUtils::getReadableSigState( sigInfo->signatureStatus() ) ) );
+ m_sigProperties.append( qMakePair( i18n("Certificate Status"), GuiUtils::getReadableCertState( sigInfo->certificateStatus() ) ) );
+ m_sigProperties.append( qMakePair( i18n("Signature Data"), QString::fromUtf8( sigInfo->signature().toHex(' ') ) ) );
+ m_sigProperties.append( qMakePair( i18n("Location"), QString( sigInfo->location() ) ) );
+ m_sigProperties.append( qMakePair( i18n("Reason"), QString( sigInfo->reason() ) ) );
+ m_sigProperties.append( qMakePair( QStringLiteral("----------"), QString("------Certificate Properties--------") ) );
+
+ Okular::CertificateInfo *certInfo = sigInfo->certificateInfo();
+ m_sigProperties.append( qMakePair( i18n("Version"), QString("V" + QString::number(certInfo->version()) ) ) );
+ m_sigProperties.append( qMakePair( i18n("Issuer Name"), certInfo->issuerInfo(Okular::CertificateInfo::CommonName) ) );
+ m_sigProperties.append( qMakePair( i18n("Issuer Distinguished Name"), certInfo->issuerInfo(Okular::CertificateInfo::DistinguishedName) ) );
+ m_sigProperties.append( qMakePair( i18n("Serial Number"), certInfo->serialNumber().toHex(' ') ) );
+ m_sigProperties.append( qMakePair( i18n("Validity Start"), certInfo->validityStart().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) );
+ m_sigProperties.append( qMakePair( i18n("Validity End"), certInfo->validityEnd().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) );
+ m_sigProperties.append( qMakePair( i18n("Public Key"), certInfo->publicKey().toHex(' ') ) );
+ m_sigProperties.append( qMakePair( i18n("Is Self Signed"), certInfo->isSelfSigned() ? QString("true") : QString("false") ) );
+}
+
+
+int CertificateViewerModel::columnCount( const QModelIndex & ) const
+{
+ return 2;
+}
+
+int CertificateViewerModel::rowCount( const QModelIndex & ) const
+{
+ return m_sigProperties.size();
+}
+
+QVariant CertificateViewerModel::data( const QModelIndex &index, int role ) const
+{
+ int row = index.row();
+ if ( !index.isValid() || row < 0 || row >= m_sigProperties.count() )
+ return QVariant();
+
+ switch ( role )
+ {
+ case Qt::DisplayRole:
+ case Qt::ToolTipRole:
+ switch ( index.column() )
+ {
+ case 0:
+ return m_sigProperties[row].first;
+ case 1:
+ return m_sigProperties[row].second;
+ default:
+ return QString();
+ }
+ case PropertyValueRole:
+ return m_sigProperties[row].second;
+ }
+
+ return QVariant();
+}
+
+QVariant CertificateViewerModel::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( Okular::SignatureInfo *sigInfo, QWidget *parent )
+ : QDialog( parent ), m_sigInfo( sigInfo )
+{
+ setModal( true );
+ setFixedSize( QSize( 450, 500 ));
+ setWindowTitle( i18n("Signature Properties") );
+
+ auto sigPropLabel = new QLabel( this );
+ sigPropLabel->setText( i18n("Signature Properties:") );
+
+ auto sigPropTree = new QTreeView( this );
+ sigPropTree->setIndentation( 0 );
+ m_sigPropModel = new CertificateViewerModel( m_sigInfo, this );
+ sigPropTree->setModel( m_sigPropModel );
+ connect( sigPropTree, &QTreeView::clicked, this, &CertificateViewer::updateText );
+
+ m_sigPropText = new QTextEdit( this );
+ m_sigPropText->setReadOnly( true );
+
+ auto btnBox = new QDialogButtonBox( QDialogButtonBox::Close, this );
+ btnBox->button( QDialogButtonBox::Close )->setDefault( true );
+ connect( btnBox, &QDialogButtonBox::rejected, this, &SignaturePropertiesDialog::reject );
+
+ auto mainLayout = new QVBoxLayout( this );
+ mainLayout->addWidget( sigPropLabel );
+ mainLayout->addWidget( sigPropTree );
+ mainLayout->addWidget( m_sigPropText );
+ mainLayout->addWidget( btnBox );
+ setLayout( mainLayout );
+}
+
+void CertificateViewer::updateText( const QModelIndex &index )
+{
+ m_sigPropText->setText( m_sigPropModel->data( index, CertificateViewerModel::PropertyValueRole ).toString() );
+}
+
SignaturePropertiesDialog::SignaturePropertiesDialog( Okular::Document *doc, Okular::FormFieldSignature *form, QWidget *parent )
: QDialog( parent ), m_doc( doc ), m_signatureForm( form )
{
setModal( true );
setWindowTitle( i18n("Signature Properties") );
m_signatureInfo = m_signatureForm->validate();
auto mainLayout = new QVBoxLayout;
// signature validation status
auto sigStatusBox = new QGroupBox( i18n("Validity Status") );
auto hBoxLayout = new QHBoxLayout;
auto pixmapLabel = new QLabel;
pixmapLabel->setPixmap( KIconLoader::global()->loadIcon( QLatin1String("application-certificate"),
KIconLoader::Desktop, KIconLoader::SizeSmallMedium ) );
hBoxLayout->addWidget( pixmapLabel );
auto sigStatusFormLayout = new QFormLayout;
const Okular::SignatureInfo::SignatureStatus sigStatus = m_signatureInfo->signatureStatus();
sigStatusFormLayout->addRow( i18n("Signature Validity:"), new QLabel( GuiUtils::getReadableSigState( sigStatus ) ) );
QString modString;
if ( sigStatus == Okular::SignatureInfo::SignatureValid )
{
if ( m_signatureInfo->signsTotalDocument() )
{
modString = i18n("The document has not been modified since it was signed.");
}
else
{
modString = 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 ( sigStatus == Okular::SignatureInfo::SignatureDigestMismatch )
{
modString = i18n("The document has been modified in a way not permitted by a previous signer.");
}
else
{
modString = i18n("The document integrity verification could not be completed.");
}
sigStatusFormLayout->addRow( i18n("Document Modifications:"), new QLabel( modString ) );
hBoxLayout->addLayout( sigStatusFormLayout );
sigStatusBox->setLayout( hBoxLayout );
mainLayout->addWidget( sigStatusBox );
// additional information
auto extraInfoBox = new QGroupBox( i18n("Additional Information") );
auto extraInfoFormLayout = new QFormLayout;
extraInfoFormLayout->addRow( i18n("Signed By:"), new QLabel( m_signatureInfo->signerName() ) );
extraInfoFormLayout->addRow( i18n("Signing Time:"), new QLabel( m_signatureInfo->signingTime().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) );
auto getValidString = [=]( const QString &str ) -> QString {
return !str.isEmpty() ? str : i18n("Not Available");
};
// optional info
extraInfoFormLayout->addRow( i18n("Reason:"), new QLabel( getValidString( m_signatureInfo->reason() ) ) );
extraInfoFormLayout->addRow( i18n("Location:"), new QLabel( getValidString( m_signatureInfo->location() ) ) );
extraInfoBox->setLayout( extraInfoFormLayout );
mainLayout->addWidget( extraInfoBox );
// document version
auto revisionBox = new QGroupBox( i18n("Document Version") );
auto revisionLayout = new QHBoxLayout;
QVector signatureFormFields = GuiUtils::getSignatureFormFields( m_doc );
revisionLayout->addWidget( new QLabel( i18nc("Document Revision of ", "Document Revision %1 of %2",
signatureFormFields.indexOf( m_signatureForm ) + 1, signatureFormFields.size() ) ) );
revisionLayout->addStretch();
auto revisionBtn = new QPushButton( i18n( "View Signed Version...") );
revisionBtn->setEnabled( !m_signatureInfo->signsTotalDocument() );
connect( revisionBtn, &QPushButton::clicked, this, &SignaturePropertiesDialog::viewSignedVersion );
revisionLayout->addWidget( revisionBtn );
revisionBox->setLayout( revisionLayout );
mainLayout->addWidget( revisionBox );
// button box
auto btnBox = new QDialogButtonBox( QDialogButtonBox::Close, this );
auto certPropBtn = new QPushButton( i18n( "Vew Certificate..."), this );
certPropBtn->setVisible(m_signatureInfo->certificateInfo()->isNull());
btnBox->button( QDialogButtonBox::Close )->setDefault( true );
btnBox->addButton( certPropBtn, QDialogButtonBox::ActionRole );
connect( btnBox, &QDialogButtonBox::rejected, this, &SignaturePropertiesDialog::reject );
connect( certPropBtn, &QPushButton::clicked, this, &SignaturePropertiesDialog::viewCertificateProperties );
mainLayout->addWidget( btnBox );
setLayout( mainLayout );
resize( mainLayout->sizeHint() );
}
void SignaturePropertiesDialog::viewCertificateProperties()
{
CertificateViewer sigPropDlg( m_signatureInfo, this );
sigPropDlg.exec();
}
void SignaturePropertiesDialog::viewSignedVersion()
{
QByteArray data;
m_doc->requestSignedRevisionData( m_signatureInfo, &data );
const QString tmpDir = QStandardPaths::writableLocation( QStandardPaths::TempLocation );
QTemporaryFile tf( tmpDir + "/revision_XXXXXX.pdf" );
if ( !tf.open() )
{
KMessageBox::error( this, i18n("Could not open revision for preview" ) );
return;
}
tf.write(data);
RevisionViewer view( tf.fileName(), this);
view.exec();
tf.close();
}
RevisionViewer::RevisionViewer( const QString &filename, QWidget *parent )
: FilePrinterPreview( filename, parent )
{
setWindowTitle( i18n("Revision Preview") );
}
RevisionViewer::~RevisionViewer()
{
}
#include "moc_signaturewidgets.cpp"
diff --git a/ui/signaturewidgets.h b/ui/signaturewidgets.h
index 45766d5ec..b2b683905 100644
--- a/ui/signaturewidgets.h
+++ b/ui/signaturewidgets.h
@@ -1,55 +1,91 @@
/***************************************************************************
* Copyright (C) 2018 by Chinmoy Ranjan Pradhan *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#ifndef OKULAR_SIGNATUREWIDGETS_H
#define OKULAR_SIGNATUREWIDGETS_H
#include
#include
#include
#include
#include "core/signatureutils.h"
#include "core/observer.h"
#include "fileprinterpreview.h"
#include "signaturemodel.h"
class QTextEdit;
namespace Okular {
class Document;
class FormFieldSignature;
class SignatureInfo;
}
+class CertificateViewerModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+ public:
+ explicit CertificateViewerModel( Okular::SignatureInfo *sigInfo, QObject * parent = nullptr );
+
+ enum {
+ PropertyValueRole = Qt::UserRole
+ };
+
+ 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< QPair > m_sigProperties;
+};
+
+class CertificateViewer : public QDialog
+{
+ Q_OBJECT
+
+ public:
+ CertificateViewer( Okular::SignatureInfo *sigInfo, QWidget *parent );
+
+ private Q_SLOTS:
+ void updateText( const QModelIndex &index );
+
+ private:
+ CertificateViewerModel *m_sigPropModel;
+ QTextEdit *m_sigPropText;
+ Okular::SignatureInfo *m_sigInfo;
+};
+
class SignaturePropertiesDialog : public QDialog
{
Q_OBJECT
public:
SignaturePropertiesDialog( Okular::Document *doc, Okular::FormFieldSignature *form, QWidget *parent );
private Q_SLOTS:
void viewSignedVersion();
void viewCertificateProperties();
private:
Okular::Document *m_doc;
Okular::FormFieldSignature *m_signatureForm;
Okular::SignatureInfo *m_signatureInfo;
};
class RevisionViewer : public Okular::FilePrinterPreview
{
Q_OBJECT
public:
RevisionViewer( const QString &filename, QWidget *parent = nullptr );
~RevisionViewer();
};
#endif