Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34572537
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
101 KB
Subscribers
None
View Options
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f8937ebd8..36041e791 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,644 +1,646 @@
# SPDX-FileCopyrightText: none
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(icons)
add_subdirectory(mimetypes)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
if (NOT DISABLE_KWATCHGNUPG)
add_subdirectory(kwatchgnupg)
endif()
add_subdirectory(libkleopatraclient)
add_subdirectory(conf)
if(WIN32)
set(_kleopatra_extra_uiserver_SRCS uiserver/uiserver_win.cpp)
set(_kleopatra_extra_SRCS
pics/gpg4win.qrc
selftest/registrycheck.cpp selftest/registrycheck.h
utils/gnupg-registry.c
utils/userinfo_win.cpp
utils/winapi-helpers.cpp utils/winapi-helpers.h
utils/windowsprocessdevice.cpp utils/windowsprocessdevice.h
versioninfo.rc kleopatra.w32-manifest
)
else()
set(_kleopatra_extra_uiserver_SRCS uiserver/uiserver_unix.cpp)
set(_kleopatra_extra_SRCS)
endif()
set(_kleopatra_uiserver_SRCS
${_kleopatra_extra_uiserver_SRCS}
selftest/uiservercheck.cpp selftest/uiservercheck.h
uiserver/assuanserverconnection.cpp uiserver/assuanserverconnection.h
uiserver/createchecksumscommand.cpp uiserver/createchecksumscommand.h
uiserver/decryptverifycommandemailbase.cpp uiserver/decryptverifycommandemailbase.h
uiserver/decryptverifycommandfilesbase.cpp uiserver/decryptverifycommandfilesbase.h
uiserver/echocommand.cpp uiserver/echocommand.h
uiserver/encryptcommand.cpp uiserver/encryptcommand.h
uiserver/importfilescommand.cpp uiserver/importfilescommand.h
uiserver/prepencryptcommand.cpp uiserver/prepencryptcommand.h
uiserver/prepsigncommand.cpp uiserver/prepsigncommand.h
uiserver/selectcertificatecommand.cpp
uiserver/sessiondata.cpp uiserver/sessiondata.h
uiserver/signcommand.cpp uiserver/signcommand.h
uiserver/signencryptfilescommand.cpp
uiserver/uiserver.cpp
uiserver/verifychecksumscommand.cpp uiserver/verifychecksumscommand.h
)
set(_kleopatra_uiserver_extra_libs LibAssuan::LibAssuan LibGpgError::LibGpgError)
if(HAVE_GPG_ERR_SOURCE_KLEO)
add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_KLEO)
add_definitions(-DGPGMEPP_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_KLEO)
else()
add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_USER_1)
add_definitions(-DGPGMEPP_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_USER_1)
endif()
if(KPim6IdentityManagementCore_FOUND AND KPim6MailTransport_FOUND AND KPim6AkonadiMime_FOUND)
set(_kleopatra_mail_libs
KPim6::IdentityManagementCore # Export OpenPGP keys using WKS
KPim6::MailTransport
KPim6::AkonadiMime
)
add_definitions(-DMAILAKONADI_ENABLED)
endif()
ki18n_wrap_ui(_kleopatra_uiserver_SRCS crypto/gui/signingcertificateselectionwidget.ui)
set(_kleopatra_SRCS
${_kleopatra_extra_SRCS}
accessibility/accessiblelink.cpp
accessibility/accessiblelink_p.h
accessibility/accessiblerichtextlabel.cpp
accessibility/accessiblerichtextlabel_p.h
accessibility/accessiblevaluelabel.cpp
accessibility/accessiblevaluelabel_p.h
accessibility/accessiblewidgetfactory.cpp
accessibility/accessiblewidgetfactory.h
commands/addadskcommand.cpp
commands/addadskcommand.h
commands/addsubkeycommand.cpp
commands/addsubkeycommand.h
commands/adduseridcommand.cpp
commands/adduseridcommand.h
commands/authenticatepivcardapplicationcommand.cpp
commands/authenticatepivcardapplicationcommand.h
commands/cardcommand.cpp
commands/cardcommand.h
commands/certificatetocardcommand.cpp
commands/certificatetocardcommand.h
commands/certificatetopivcardcommand.cpp
commands/certificatetopivcardcommand.h
commands/certifycertificatecommand.cpp
commands/certifycertificatecommand.h
commands/certifygroupcommand.cpp
commands/certifygroupcommand.h
commands/changeexpirycommand.cpp
commands/changeexpirycommand.h
commands/changeownertrustcommand.cpp
commands/changeownertrustcommand.h
commands/changepassphrasecommand.cpp
commands/changepassphrasecommand.h
commands/changepincommand.cpp
commands/changepincommand.h
commands/changeroottrustcommand.cpp
commands/changeroottrustcommand.h
commands/checksumcreatefilescommand.cpp
commands/checksumcreatefilescommand.h
commands/checksumverifyfilescommand.cpp
commands/checksumverifyfilescommand.h
commands/clearcrlcachecommand.cpp
commands/clearcrlcachecommand.h
commands/command.cpp
commands/command.h
commands/createcsrforcardkeycommand.cpp
commands/createcsrforcardkeycommand.h
commands/creategroupcommand.cpp
commands/creategroupcommand.h
commands/createopenpgpkeyfromcardkeyscommand.cpp
commands/createopenpgpkeyfromcardkeyscommand.h
commands/decryptverifyclipboardcommand.cpp
commands/decryptverifyclipboardcommand.h
commands/decryptverifyfilescommand.cpp
commands/decryptverifyfilescommand.h
commands/deletecertificatescommand.cpp
commands/deletecertificatescommand.h
commands/detailscommand.cpp
commands/detailscommand.h
commands/dumpcertificatecommand.cpp
commands/dumpcertificatecommand.h
commands/dumpcrlcachecommand.cpp
commands/dumpcrlcachecommand.h
commands/encryptclipboardcommand.cpp
commands/encryptclipboardcommand.h
commands/exportcertificatecommand.cpp
commands/exportcertificatecommand.h
commands/exportgroupscommand.cpp
commands/exportgroupscommand.h
commands/exportopenpgpcertstoservercommand.cpp
commands/exportopenpgpcertstoservercommand.h
commands/exportopenpgpcerttoprovidercommand.cpp
commands/exportopenpgpcerttoprovidercommand.h
commands/exportpaperkeycommand.cpp
commands/exportpaperkeycommand.h
commands/exportsecretkeycommand.cpp
commands/exportsecretkeycommand.h
commands/exportsecretsubkeycommand.cpp
commands/exportsecretsubkeycommand.h
commands/generateopenpgpcardkeysandcertificatecommand.cpp
commands/generateopenpgpcardkeysandcertificatecommand.h
commands/genrevokecommand.cpp
commands/genrevokecommand.h
commands/gnupgprocesscommand.cpp
commands/gnupgprocesscommand.h
commands/importcertificatefromclipboardcommand.cpp
commands/importcertificatefromclipboardcommand.h
commands/importcertificatefromdatacommand.cpp
commands/importcertificatefromdatacommand.h
commands/importcertificatefromfilecommand.cpp
commands/importcertificatefromfilecommand.h
commands/importcertificatefromkeyservercommand.cpp
commands/importcertificatefromkeyservercommand.h
commands/importcertificatefrompivcardcommand.cpp
commands/importcertificatefrompivcardcommand.h
commands/importcertificatescommand.cpp
commands/importcertificatescommand.h
commands/importcrlcommand.cpp
commands/importcrlcommand.h
commands/importpaperkeycommand.cpp
commands/importpaperkeycommand.h
commands/keytocardcommand.cpp
commands/keytocardcommand.h
commands/lookupcertificatescommand.cpp
commands/lookupcertificatescommand.h
commands/newcertificatesigningrequestcommand.cpp
commands/newcertificatesigningrequestcommand.h
commands/newopenpgpcertificatecommand.cpp
commands/newopenpgpcertificatecommand.h
commands/openpgpgeneratecardkeycommand.cpp
commands/openpgpgeneratecardkeycommand.h
commands/pivgeneratecardkeycommand.cpp
commands/pivgeneratecardkeycommand.h
commands/refreshcertificatescommand.cpp
commands/refreshcertificatescommand.h
commands/refreshopenpgpcertscommand.cpp
commands/refreshopenpgpcertscommand.h
commands/refreshx509certscommand.cpp
commands/refreshx509certscommand.h
commands/reloadkeyscommand.cpp
commands/reloadkeyscommand.h
commands/revokecertificationcommand.cpp
commands/revokecertificationcommand.h
commands/revokekeycommand.cpp
commands/revokekeycommand.h
commands/revokeuseridcommand.cpp
commands/revokeuseridcommand.h
commands/selftestcommand.cpp
commands/selftestcommand.h
commands/setinitialpincommand.cpp
commands/setinitialpincommand.h
commands/setpivcardapplicationadministrationkeycommand.cpp
commands/setpivcardapplicationadministrationkeycommand.h
commands/setprimaryuseridcommand.cpp
commands/setprimaryuseridcommand.h
commands/signclipboardcommand.cpp
commands/signclipboardcommand.h
commands/signencryptfilescommand.cpp
commands/signencryptfilescommand.h
commands/signencryptfoldercommand.cpp
commands/signencryptfoldercommand.h
commands/togglecertificateenabledcommand.cpp
commands/togglecertificateenabledcommand.h
commands/viewemailfilescommand.cpp
commands/viewemailfilescommand.h
conf/configuredialog.cpp
conf/configuredialog.h
conf/groupsconfigdialog.cpp
conf/groupsconfigdialog.h
conf/groupsconfigwidget.cpp
conf/groupsconfigwidget.h
crypto/autodecryptverifyfilescontroller.cpp
crypto/autodecryptverifyfilescontroller.h
crypto/certificateresolver.cpp
crypto/certificateresolver.h
crypto/checksumsutils_p.cpp
crypto/checksumsutils_p.h
crypto/controller.cpp
crypto/controller.h
crypto/createchecksumscontroller.cpp
crypto/createchecksumscontroller.h
crypto/decryptverifyemailcontroller.cpp
crypto/decryptverifyemailcontroller.h
crypto/decryptverifyfilescontroller.cpp
crypto/decryptverifyfilescontroller.h
crypto/decryptverifytask.cpp
crypto/decryptverifytask.h
crypto/encryptemailcontroller.cpp
crypto/encryptemailcontroller.h
crypto/encryptemailtask.cpp
crypto/encryptemailtask.h
crypto/gui/certificatelineedit.cpp
crypto/gui/certificatelineedit.h
crypto/gui/certificateselectionline.cpp
crypto/gui/certificateselectionline.h
crypto/gui/decryptverifyfilesdialog.cpp
crypto/gui/decryptverifyfilesdialog.h
crypto/gui/decryptverifyfileswizard.cpp
crypto/gui/decryptverifyfileswizard.h
crypto/gui/decryptverifyoperationwidget.cpp
crypto/gui/decryptverifyoperationwidget.h
crypto/gui/encryptemailwizard.cpp
crypto/gui/encryptemailwizard.h
crypto/gui/newresultpage.cpp
crypto/gui/newresultpage.h
crypto/gui/objectspage.cpp
crypto/gui/objectspage.h
crypto/gui/resolverecipientspage.cpp
crypto/gui/resolverecipientspage.h
crypto/gui/resultitemwidget.cpp
crypto/gui/resultitemwidget.h
crypto/gui/resultlistwidget.cpp
crypto/gui/resultlistwidget.h
crypto/gui/resultpage.cpp
crypto/gui/resultpage.h
crypto/gui/signemailwizard.cpp
crypto/gui/signemailwizard.h
crypto/gui/signencryptemailconflictdialog.cpp
crypto/gui/signencryptemailconflictdialog.h
crypto/gui/signencryptfileswizard.cpp
crypto/gui/signencryptfileswizard.h
crypto/gui/signencryptwidget.cpp
crypto/gui/signencryptwidget.h
crypto/gui/signencryptwizard.cpp
crypto/gui/signencryptwizard.h
crypto/gui/signerresolvepage.cpp
crypto/gui/signerresolvepage.h
crypto/gui/signingcertificateselectiondialog.cpp
crypto/gui/signingcertificateselectiondialog.h
crypto/gui/signingcertificateselectionwidget.cpp
crypto/gui/signingcertificateselectionwidget.h
crypto/gui/unknownrecipientwidget.cpp
crypto/gui/unknownrecipientwidget.h
crypto/gui/verifychecksumsdialog.cpp
crypto/gui/verifychecksumsdialog.h
crypto/gui/wizard.cpp
crypto/gui/wizard.h
crypto/gui/wizardpage.cpp
crypto/gui/wizardpage.h
crypto/newsignencryptemailcontroller.cpp
crypto/newsignencryptemailcontroller.h
crypto/recipient.cpp
crypto/recipient.h
crypto/sender.cpp
crypto/sender.h
crypto/signemailcontroller.cpp
crypto/signemailcontroller.h
crypto/signemailtask.cpp
crypto/signemailtask.h
crypto/signencryptfilescontroller.cpp
crypto/signencryptfilescontroller.h
crypto/signencrypttask.cpp
crypto/signencrypttask.h
crypto/task.cpp
crypto/task.h
crypto/taskcollection.cpp
crypto/taskcollection.h
crypto/verifychecksumscontroller.cpp
crypto/verifychecksumscontroller.h
dialogs/addsubkeydialog.cpp
dialogs/addsubkeydialog.h
dialogs/adduseriddialog.cpp
dialogs/adduseriddialog.h
dialogs/animatedexpander.cpp
dialogs/animatedexpander.h
dialogs/certificatedetailsdialog.cpp
dialogs/certificatedetailsdialog.h
dialogs/certificatedetailsinputwidget.cpp
dialogs/certificatedetailsinputwidget.h
dialogs/certificatedetailswidget.cpp
dialogs/certificatedetailswidget.h
dialogs/certificatedumpwidget.cpp
dialogs/certificatedumpwidget.h
dialogs/certificateselectiondialog.cpp
dialogs/certificateselectiondialog.h
dialogs/certifycertificatedialog.cpp
dialogs/certifycertificatedialog.h
dialogs/certifywidget.cpp
dialogs/certifywidget.h
dialogs/createcsrforcardkeydialog.cpp
dialogs/createcsrforcardkeydialog.h
dialogs/copytosmartcarddialog.cpp
dialogs/copytosmartcarddialog.h
dialogs/debugdialog.cpp
dialogs/debugdialog.h
dialogs/deletecertificatesdialog.cpp
dialogs/deletecertificatesdialog.h
dialogs/editgroupdialog.cpp
dialogs/editgroupdialog.h
dialogs/expirydialog.cpp
dialogs/expirydialog.h
dialogs/exportdialog.cpp
dialogs/exportdialog.h
dialogs/gencardkeydialog.cpp
dialogs/gencardkeydialog.h
dialogs/groupdetailsdialog.cpp
dialogs/groupdetailsdialog.h
dialogs/lookupcertificatesdialog.cpp
dialogs/lookupcertificatesdialog.h
dialogs/pivcardapplicationadministrationkeyinputdialog.cpp
dialogs/pivcardapplicationadministrationkeyinputdialog.h
dialogs/revokekeydialog.cpp
dialogs/revokekeydialog.h
dialogs/revokerswidget.cpp
dialogs/revokerswidget.h
dialogs/selftestdialog.cpp
dialogs/selftestdialog.h
dialogs/setinitialpindialog.cpp
dialogs/setinitialpindialog.h
dialogs/smartcardwindow.cpp
dialogs/smartcardwindow.h
dialogs/subkeyswidget.cpp
dialogs/subkeyswidget.h
dialogs/trustchainwidget.cpp
dialogs/trustchainwidget.h
dialogs/updatenotification.cpp
dialogs/updatenotification.h
dialogs/useridswidget.cpp
dialogs/useridswidget.h
dialogs/weboftrustwidget.cpp
dialogs/weboftrustwidget.h
interfaces/anchorprovider.h
interfaces/focusfirstchild.h
newcertificatewizard/advancedsettingsdialog.cpp
newcertificatewizard/advancedsettingsdialog_p.h
newcertificatewizard/enterdetailspage.cpp
newcertificatewizard/enterdetailspage_p.h
newcertificatewizard/keycreationpage.cpp
newcertificatewizard/keycreationpage_p.h
newcertificatewizard/listwidget.cpp
newcertificatewizard/listwidget.h
newcertificatewizard/newcertificatewizard.cpp
newcertificatewizard/newcertificatewizard.h
newcertificatewizard/resultpage.cpp
newcertificatewizard/resultpage_p.h
newcertificatewizard/wizardpage.cpp
newcertificatewizard/wizardpage_p.h
selftest/compliancecheck.cpp
selftest/compliancecheck.h
selftest/enginecheck.cpp
selftest/enginecheck.h
selftest/gpgagentcheck.cpp
selftest/gpgagentcheck.h
selftest/gpgconfcheck.cpp
selftest/gpgconfcheck.h
selftest/libkleopatrarccheck.cpp
selftest/libkleopatrarccheck.h
selftest/selftest.cpp
selftest/selftest.h
smartcard/algorithminfo.h
smartcard/card.cpp
smartcard/card.h
smartcard/deviceinfowatcher.cpp
smartcard/deviceinfowatcher.h
smartcard/keypairinfo.cpp
smartcard/keypairinfo.h
smartcard/netkeycard.cpp
smartcard/netkeycard.h
smartcard/openpgpcard.cpp
smartcard/openpgpcard.h
smartcard/p15card.cpp
smartcard/p15card.h
smartcard/pivcard.cpp
smartcard/pivcard.h
smartcard/readerstatus.cpp
smartcard/readerstatus.h
smartcard/utils.cpp
smartcard/utils.h
utils/accessibility.cpp
utils/accessibility.h
utils/action_data.cpp
utils/action_data.h
utils/applicationstate.cpp
utils/applicationstate.h
utils/archivedefinition.cpp
utils/archivedefinition.h
utils/certificatepair.h
utils/clipboardmenu.cpp
utils/clipboardmenu.h
utils/debug-helpers.cpp
utils/debug-helpers.h
utils/dragqueen.cpp
utils/dragqueen.h
utils/email.cpp
utils/email.h
utils/emptypassphraseprovider.cpp
utils/emptypassphraseprovider.h
utils/filedialog.cpp
utils/filedialog.h
+ utils/fileutils.cpp
+ utils/fileutils.h
utils/gui-helper.cpp
utils/gui-helper.h
utils/headerview.cpp
utils/headerview.h
utils/input.cpp
utils/input.h
utils/iodevicelogger.cpp
utils/iodevicelogger.h
utils/kdpipeiodevice.cpp
utils/kdpipeiodevice.h
utils/keyexportdraghandler.cpp
utils/keyexportdraghandler.h
utils/kuniqueservice.cpp
utils/kuniqueservice.h
utils/log.cpp
utils/log.h
utils/memory-helpers.h
utils/migration.cpp
utils/migration.h
utils/output.cpp
utils/output.h
utils/overwritedialog.cpp
utils/overwritedialog.h
utils/path-helper.cpp
utils/path-helper.h
utils/scrollarea.cpp
utils/scrollarea.h
utils/statusmessage.cpp
utils/statusmessage.h
utils/systemtrayicon.cpp
utils/systemtrayicon.h
utils/tags.cpp
utils/tags.h
utils/types.cpp
utils/types.h
utils/userinfo.cpp
utils/userinfo.h
utils/writecertassuantransaction.cpp
utils/writecertassuantransaction.h
utils/wsastarter.cpp
utils/wsastarter.h
view/anchorcache.cpp
view/anchorcache_p.h
view/cardkeysview.cpp
view/cardkeysview.h
view/htmllabel.cpp
view/htmllabel.h
view/infofield.cpp
view/infofield.h
view/keycacheoverlay.cpp
view/keycacheoverlay.h
view/keylistcontroller.cpp
view/keylistcontroller.h
view/keytreeview.cpp
view/keytreeview.h
view/netkeywidget.cpp
view/netkeywidget.h
view/overlaywidget.cpp
view/overlaywidget.h
view/p15cardwidget.cpp
view/p15cardwidget.h
view/padwidget.cpp
view/padwidget.h
view/pgpcardwidget.cpp
view/pgpcardwidget.h
view/pivcardwidget.cpp
view/pivcardwidget.h
view/progressoverlay.cpp
view/progressoverlay.h
view/searchbar.cpp
view/searchbar.h
view/smartcardactions.cpp
view/smartcardactions.h
view/smartcardswidget.cpp
view/smartcardswidget.h
view/smartcardwidget.cpp
view/smartcardwidget.h
view/tabwidget.cpp
view/tabwidget.h
view/textoverlay.cpp
view/textoverlay.h
view/urllabel.cpp
view/urllabel.h
view/waitwidget.cpp
view/waitwidget.h
view/welcomewidget.cpp
view/welcomewidget.h
aboutdata.cpp
aboutdata.h
kleopatra.qrc
kleopatraapplication.cpp
kleopatraapplication.h
main.cpp
mainwindow.cpp
mainwindow.h
systrayicon.cpp
systrayicon.h
kleopatra_options.h
)
if(WIN32)
configure_file (versioninfo.rc.in versioninfo.rc)
configure_file (kleopatra.w32-manifest.in kleopatra.w32-manifest)
set(_kleopatra_SRCS
${CMAKE_CURRENT_BINARY_DIR}/kleopatra.w32-manifest
${CMAKE_CURRENT_BINARY_DIR}/versioninfo.rc
conf/kmessageboxdontaskagainstorage.cpp
conf/kmessageboxdontaskagainstorage.h
${_kleopatra_SRCS}
)
endif()
set (_kleopatra_SRCS conf/kleopageconfigdialog.cpp conf/kleopageconfigdialog.h ${_kleopatra_SRCS})
ecm_qt_declare_logging_category(_kleopatra_SRCS HEADER kleopatra_debug.h IDENTIFIER KLEOPATRA_LOG CATEGORY_NAME org.kde.pim.kleopatra
DESCRIPTION "kleopatra (kleopatra)"
OLD_CATEGORY_NAMES log_kleopatra
EXPORT KLEOPATRA
)
if(KLEO_MODEL_TEST)
add_definitions(-DKLEO_MODEL_TEST)
set(_kleopatra_SRCS ${_kleopatra_SRCS} models/modeltest.cpp)
endif()
ki18n_wrap_ui(_kleopatra_SRCS
dialogs/setinitialpindialog.ui
newcertificatewizard/listwidget.ui
)
kconfig_add_kcfg_files(_kleopatra_SRCS
kcfg/emailoperationspreferences.kcfgc
kcfg/fileoperationspreferences.kcfgc
kcfg/settings.kcfgc
kcfg/smimevalidationpreferences.kcfgc
kcfg/tooltippreferences.kcfgc
)
file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/icons/*-apps-kleopatra.png")
ecm_add_app_icon(_kleopatra_SRCS ICONS ${ICONS_SRCS})
add_executable(kleopatra_bin ${_kleopatra_SRCS} ${_kleopatra_uiserver_SRCS})
# For the ConfigureDialog & KCMs
target_link_libraries(kleopatra_bin kcm_kleopatra_static)
#if (COMPILE_WITH_UNITY_CMAKE_SUPPORT)
# set_target_properties(kleopatra_bin PROPERTIES UNITY_BUILD ON)
#endif()
set_target_properties(kleopatra_bin PROPERTIES OUTPUT_NAME kleopatra)
if (WIN32)
set(_kleopatra_platform_libs "secur32")
endif ()
target_link_libraries(kleopatra_bin
Gpgmepp
KPim6::Libkleo
KPim6::Mime
KPim6::MimeTreeParserWidgets
KF6::Codecs
KF6::CoreAddons
KF6::Crash
KF6::I18n
KF6::IconThemes
KF6::ItemModels
KF6::KIOCore
KF6::KIOWidgets
KF6::WindowSystem
KF6::XmlGui
Qt::Network
Qt::PrintSupport # Printing secret keys
kleopatraclientcore
${_kleopatra_extra_libs}
${_kleopatra_mail_libs}
${_kleopatra_uiserver_extra_libs}
${_kleopatra_dbusaddons_libs}
${_kleopatra_platform_libs}
)
target_link_libraries(kleopatra_bin QGpgmeQt6)
install(TARGETS kleopatra_bin ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
install(
PROGRAMS data/org.kde.kleopatra.desktop data/kleopatra_import.desktop
DESTINATION ${KDE_INSTALL_APPDIR}
)
install(FILES data/org.kde.kleopatra.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
install(FILES data/kleopatra-mime.xml DESTINATION ${KDE_INSTALL_MIMEDIR})
install(
PROGRAMS data/kleopatra_signencryptfiles.desktop
data/kleopatra_signencryptfolders.desktop
data/kleopatra_decryptverifyfiles.desktop
data/kleopatra_decryptverifyfolders.desktop
DESTINATION ${KDE_INSTALL_DATADIR}/kio/servicemenus
)
install(FILES kleopatradebugcommandsrc DESTINATION ${KDE_INSTALL_CONFDIR})
diff --git a/src/crypto/gui/decryptverifyfilesdialog.cpp b/src/crypto/gui/decryptverifyfilesdialog.cpp
index 31f46d02b..fc47205bc 100644
--- a/src/crypto/gui/decryptverifyfilesdialog.cpp
+++ b/src/crypto/gui/decryptverifyfilesdialog.cpp
@@ -1,242 +1,214 @@
/* crypto/gui/decryptverifyfilesdialog.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "decryptverifyfilesdialog.h"
#include "kleopatra_debug.h"
#include "crypto/decryptverifytask.h"
#include "crypto/gui/resultlistwidget.h"
#include "crypto/gui/resultpage.h"
#include "crypto/taskcollection.h"
+#include "utils/fileutils.h"
#include "utils/path-helper.h"
#include <Libkleo/FileNameRequester>
#include <QLabel>
#include <QProgressBar>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWindow>
#include <KConfigGroup>
#include <KLocalizedContext>
#include <KLocalizedString>
#include <KMessageBox>
#include <KSharedConfig>
#include <KTitleWidget>
#include <MimeTreeParserWidgets/MessageViewerDialog>
using namespace Kleo;
using namespace Kleo::Crypto;
using namespace Kleo::Crypto::Gui;
using namespace MimeTreeParser::Widgets;
DecryptVerifyFilesDialog::DecryptVerifyFilesDialog(const std::shared_ptr<TaskCollection> &coll, QWidget *parent)
: QDialog(parent)
, m_tasks(coll)
, m_buttonBox(new QDialogButtonBox)
{
readConfig();
auto vLay = new QVBoxLayout(this);
auto labels = new QWidget;
auto outputLayout = new QHBoxLayout;
m_outputLocationFNR = new FileNameRequester;
m_outputLocationFNR->setButtonHint(i18nc("@info:tooltip", "Choose output folder"));
auto outLabel = new QLabel(i18nc("@label:textbox", "&Output folder:"));
outLabel->setBuddy(m_outputLocationFNR);
outputLayout->addWidget(outLabel);
outputLayout->addWidget(m_outputLocationFNR);
m_outputLocationFNR->setFilter(QDir::Dirs);
vLay->addLayout(outputLayout);
m_progressLabelLayout = new QVBoxLayout(labels);
vLay->addWidget(labels);
m_progressBar = new QProgressBar;
vLay->addWidget(m_progressBar);
m_resultList = new ResultListWidget;
connect(m_resultList, &ResultListWidget::showButtonClicked, this, &DecryptVerifyFilesDialog::showContent);
vLay->addWidget(m_resultList);
m_tasks = coll;
Q_ASSERT(m_tasks);
m_resultList->setTaskCollection(coll);
connect(m_tasks.get(), &TaskCollection::progress, this, &DecryptVerifyFilesDialog::progress);
connect(m_tasks.get(), &TaskCollection::done, this, &DecryptVerifyFilesDialog::allDone);
connect(m_tasks.get(), &TaskCollection::started, this, &DecryptVerifyFilesDialog::started);
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(m_buttonBox, &QDialogButtonBox::clicked, this, &DecryptVerifyFilesDialog::btnClicked);
layout()->addWidget(m_buttonBox);
bool hasOutputs = false;
for (const auto &t : coll->tasks()) {
if (!qobject_cast<VerifyDetachedTask *>(t.get())) {
hasOutputs = true;
break;
}
}
if (hasOutputs) {
setWindowTitle(i18nc("@title:window", "Decrypt/Verify Files"));
m_saveButton = QDialogButtonBox::SaveAll;
m_buttonBox->addButton(QDialogButtonBox::Discard);
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &DecryptVerifyFilesDialog::checkAccept);
} else {
outLabel->setVisible(false);
m_outputLocationFNR->setVisible(false);
setWindowTitle(i18nc("@title:window", "Verify Files"));
m_buttonBox->addButton(QDialogButtonBox::Close);
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
}
if (m_saveButton) {
m_buttonBox->addButton(m_saveButton);
m_buttonBox->button(m_saveButton)->setEnabled(false);
}
m_finishedWidget = new KTitleWidget;
m_finishedWidget->setText(i18nc("@title", "Finished"));
m_progressLabelLayout->addWidget(m_finishedWidget);
m_finishedWidget->setVisible(false);
m_progressLabel = new QLabel;
m_progressLabel->setTextFormat(Qt::RichText);
m_progressLabel->setWordWrap(true);
m_progressLabelLayout->addWidget(m_progressLabel);
}
DecryptVerifyFilesDialog::~DecryptVerifyFilesDialog()
{
qCDebug(KLEOPATRA_LOG);
writeConfig();
}
void DecryptVerifyFilesDialog::allDone()
{
qCDebug(KLEOPATRA_LOG) << "All done";
Q_ASSERT(m_tasks);
m_progressBar->setRange(0, 100);
m_progressBar->setValue(100);
m_progressBar->setVisible(false);
m_progressLabel->setVisible(false);
m_finishedWidget->setVisible(true);
if (m_tasks->allTasksHaveErrors()) {
return;
}
if (m_saveButton != QDialogButtonBox::NoButton) {
m_buttonBox->button(m_saveButton)->setEnabled(true);
} else {
m_buttonBox->removeButton(m_buttonBox->button(QDialogButtonBox::Close));
m_buttonBox->addButton(QDialogButtonBox::Ok);
}
}
void DecryptVerifyFilesDialog::started(const std::shared_ptr<Task> &task)
{
Q_ASSERT(task);
m_progressLabel->setText(task->label());
if (m_saveButton != QDialogButtonBox::NoButton) {
m_buttonBox->button(m_saveButton)->setEnabled(false);
} else if (m_buttonBox->button(QDialogButtonBox::Ok)) {
m_buttonBox->removeButton(m_buttonBox->button(QDialogButtonBox::Ok));
m_buttonBox->addButton(QDialogButtonBox::Close);
}
}
void DecryptVerifyFilesDialog::progress(int progress, int total)
{
Q_ASSERT(progress >= 0);
Q_ASSERT(total >= 0);
m_progressBar->setRange(0, total);
m_progressBar->setValue(progress);
}
void DecryptVerifyFilesDialog::setOutputLocation(const QString &dir)
{
m_outputLocationFNR->setFileName(dir);
}
QString DecryptVerifyFilesDialog::outputLocation() const
{
return m_outputLocationFNR->fileName();
}
void DecryptVerifyFilesDialog::btnClicked(QAbstractButton *btn)
{
if (m_buttonBox->buttonRole(btn) == QDialogButtonBox::DestructiveRole) {
close();
}
}
void DecryptVerifyFilesDialog::checkAccept()
{
- const auto outLoc = outputLocation();
- if (outLoc.isEmpty()) {
- KMessageBox::information(this, i18n("Please select an output folder."), i18nc("@title:window", "No Output Folder"));
- return;
- }
- const QFileInfo fi(outLoc);
-
- if (!fi.exists()) {
- qCDebug(KLEOPATRA_LOG) << "Output dir does not exist. Trying to create.";
- const QDir dir(outLoc);
- if (!dir.mkdir(outLoc)) {
- KMessageBox::information(
- this,
- xi18nc("@info",
- "<para>Failed to create output folder <filename>%1</filename>.</para><para>Please select a different output folder.</para>",
- outLoc),
- i18nc("@title:window", "Unusable Output Folder"));
- } else {
- accept();
- }
- } else if (!fi.isDir()) {
- KMessageBox::information(this, i18n("Please select a different output folder."), i18nc("@title:window", "Invalid Output Folder"));
- } else if (!Kleo::isWritable(fi)) {
- KMessageBox::information(
- this,
- xi18nc("@info",
- "<para>Cannot write in the output folder <filename>%1</filename>.</para><para>Please select a different output folder.</para>",
- outLoc),
- i18nc("@title:window", "Unusable Output Folder"));
- } else {
+ if (Kleo::ensureOutDir(outputLocation(), this)) {
accept();
}
}
void DecryptVerifyFilesDialog::readConfig()
{
KConfigGroup dialog(KSharedConfig::openStateConfig(), QStringLiteral("DecryptVerifyFilesDialog"));
const QSize size = dialog.readEntry("Size", QSize(640, 480));
if (size.isValid()) {
resize(size);
}
}
void DecryptVerifyFilesDialog::writeConfig()
{
KConfigGroup dialog(KSharedConfig::openStateConfig(), QStringLiteral("DecryptVerifyFilesDialog"));
dialog.writeEntry("Size", size());
dialog.sync();
}
void DecryptVerifyFilesDialog::showContent(const std::shared_ptr<const Task::Result> &result)
{
if (auto decryptVerifyResult = std::dynamic_pointer_cast<const DecryptVerifyResult>(result)) {
MessageViewerDialog dialog(decryptVerifyResult->fileName());
dialog.exec();
}
}
#include "moc_decryptverifyfilesdialog.cpp"
diff --git a/src/crypto/gui/decryptverifyfileswizard.cpp b/src/crypto/gui/decryptverifyfileswizard.cpp
index c4f6964e9..ca9412c82 100644
--- a/src/crypto/gui/decryptverifyfileswizard.cpp
+++ b/src/crypto/gui/decryptverifyfileswizard.cpp
@@ -1,277 +1,283 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/gui/decryptverifywizard.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "decryptverifyfileswizard.h"
#include "decryptverifyoperationwidget.h"
+#include "utils/fileutils.h"
#include <crypto/gui/resultpage.h>
#include <crypto/gui/wizardpage.h>
#include <crypto/task.h>
#include <crypto/taskcollection.h>
#include <utils/kleo_assert.h>
#include <utils/scrollarea.h>
#include <Libkleo/FileNameRequester>
#include <Libkleo/Stl_Util>
#include <KGuiItem>
#include <KLocalizedString>
#include <QBoxLayout>
#include <QCheckBox>
#include <QLabel>
#include <QTimer>
#include <QTreeView>
#include <vector>
using namespace Kleo;
using namespace Kleo::Crypto;
using namespace Kleo::Crypto::Gui;
namespace
{
class HLine : public QFrame
{
Q_OBJECT
public:
explicit HLine(QWidget *p = nullptr, Qt::WindowFlags f = {})
: QFrame(p, f)
{
setFrameStyle(static_cast<int>(QFrame::HLine) | static_cast<int>(QFrame::Sunken));
}
};
class OperationsWidget : public WizardPage
{
Q_OBJECT
public:
explicit OperationsWidget(QWidget *p = nullptr);
~OperationsWidget() override;
void setOutputDirectory(const QString &dir)
{
m_ui.outputDirectoryFNR.setFileName(dir);
}
QString outputDirectory() const
{
return m_ui.outputDirectoryFNR.fileName();
}
bool useOutputDirectory() const
{
return m_ui.useOutputDirectoryCB.isChecked();
}
void ensureIndexAvailable(unsigned int idx);
DecryptVerifyOperationWidget *widget(unsigned int idx)
{
return m_widgets.at(idx);
}
bool isComplete() const override
{
return std::all_of(m_widgets.cbegin(), m_widgets.cend(), [](const auto &w) {
switch (w->mode()) {
case DecryptVerifyOperationWidget::VerifyDetachedWithSignature:
case DecryptVerifyOperationWidget::VerifyDetachedWithSignedData: {
const QString sigFileName = w->inputFileName();
const QString dataFileName = w->signedDataFileName();
return !sigFileName.isEmpty() && !dataFileName.isEmpty() && QFile::exists(sigFileName) && QFile::exists(dataFileName);
}
case DecryptVerifyOperationWidget::DecryptVerifyOpaque:;
}
return true;
});
}
+ bool onNext() override
+ {
+ return Kleo::ensureOutDir(outputDirectory(), this);
+ }
+
private:
std::vector<DecryptVerifyOperationWidget *> m_widgets;
struct UI {
QCheckBox useOutputDirectoryCB;
QLabel outputDirectoryLB;
FileNameRequester outputDirectoryFNR;
ScrollArea scrollArea; // ### replace with KDScrollArea when done
QVBoxLayout vlay;
QHBoxLayout hlay;
explicit UI(OperationsWidget *q);
} m_ui;
};
}
class DecryptVerifyFilesWizard::Private
{
friend class ::Kleo::Crypto::Gui::DecryptVerifyFilesWizard;
DecryptVerifyFilesWizard *const q;
public:
Private(DecryptVerifyFilesWizard *qq);
~Private();
void ensureIndexAvailable(unsigned int idx)
{
operationsPage.ensureIndexAvailable(idx);
}
private:
OperationsWidget operationsPage;
Gui::ResultPage resultPage;
};
DecryptVerifyFilesWizard::DecryptVerifyFilesWizard(QWidget *p, Qt::WindowFlags f)
: Wizard(p, f)
, d(new Private(this))
{
}
DecryptVerifyFilesWizard::~DecryptVerifyFilesWizard()
{
}
void DecryptVerifyFilesWizard::setOutputDirectory(const QString &dir)
{
d->operationsPage.setOutputDirectory(dir);
}
QString DecryptVerifyFilesWizard::outputDirectory() const
{
return d->operationsPage.outputDirectory();
}
bool DecryptVerifyFilesWizard::useOutputDirectory() const
{
return d->operationsPage.useOutputDirectory();
}
DecryptVerifyOperationWidget *DecryptVerifyFilesWizard::operationWidget(unsigned int idx)
{
d->ensureIndexAvailable(idx);
return d->operationsPage.widget(idx);
}
void DecryptVerifyFilesWizard::onNext(int id)
{
if (id == OperationsPage) {
QTimer::singleShot(0, this, &DecryptVerifyFilesWizard::operationPrepared);
}
Wizard::onNext(id);
}
void DecryptVerifyFilesWizard::setTaskCollection(const std::shared_ptr<TaskCollection> &coll)
{
kleo_assert(coll);
d->resultPage.setTaskCollection(coll);
}
DecryptVerifyFilesWizard::Private::Private(DecryptVerifyFilesWizard *qq)
: q(qq)
, operationsPage(q)
, resultPage(q)
{
q->setPage(DecryptVerifyFilesWizard::OperationsPage, &operationsPage);
q->setPage(DecryptVerifyFilesWizard::ResultPage, &resultPage);
std::vector<int> order;
order.push_back(DecryptVerifyFilesWizard::OperationsPage);
order.push_back(DecryptVerifyFilesWizard::ResultPage);
q->setPageOrder(order);
operationsPage.setCommitPage(true);
}
DecryptVerifyFilesWizard::Private::~Private()
{
}
OperationsWidget::OperationsWidget(QWidget *p)
: WizardPage(p)
, m_widgets()
, m_ui(this)
{
setTitle(i18n("<b>Choose operations to be performed</b>"));
setSubTitle(
i18n("Here you can check and, if needed, override "
"the operations Kleopatra detected for the input given."));
setCommitPage(true);
setCustomNextButton(KGuiItem(i18nc("@action:button", "&Decrypt/Verify")));
}
OperationsWidget::~OperationsWidget()
{
}
OperationsWidget::UI::UI(OperationsWidget *q)
: useOutputDirectoryCB(i18n("Create all output files in a single folder"), q)
, outputDirectoryLB(i18n("&Output folder:"), q)
, outputDirectoryFNR(q)
, scrollArea(q)
, vlay(q)
, hlay()
{
Q_SET_OBJECT_NAME(useOutputDirectoryCB);
Q_SET_OBJECT_NAME(outputDirectoryLB);
Q_SET_OBJECT_NAME(outputDirectoryFNR);
Q_SET_OBJECT_NAME(scrollArea);
Q_SET_OBJECT_NAME(vlay);
Q_SET_OBJECT_NAME(hlay);
outputDirectoryFNR.setFilter(QDir::Dirs);
useOutputDirectoryCB.setChecked(true);
connect(&useOutputDirectoryCB, &QCheckBox::toggled, &outputDirectoryLB, &QLabel::setEnabled);
connect(&useOutputDirectoryCB, &QCheckBox::toggled, &outputDirectoryFNR, &FileNameRequester::setEnabled);
Q_ASSERT(qobject_cast<QBoxLayout *>(scrollArea.widget()->layout()));
static_cast<QBoxLayout *>(scrollArea.widget()->layout())->addStretch(1);
outputDirectoryLB.setBuddy(&outputDirectoryFNR);
hlay.setContentsMargins(0, 0, 0, 0);
vlay.addWidget(&scrollArea, 1);
vlay.addWidget(&useOutputDirectoryCB);
vlay.addLayout(&hlay);
hlay.addWidget(&outputDirectoryLB);
hlay.addWidget(&outputDirectoryFNR);
}
void OperationsWidget::ensureIndexAvailable(unsigned int idx)
{
if (idx < m_widgets.size()) {
return;
}
Q_ASSERT(m_ui.scrollArea.widget());
Q_ASSERT(qobject_cast<QBoxLayout *>(m_ui.scrollArea.widget()->layout()));
QBoxLayout &blay = *static_cast<QBoxLayout *>(m_ui.scrollArea.widget()->layout());
for (unsigned int i = m_widgets.size(); i < idx + 1; ++i) {
if (i) {
blay.insertWidget(blay.count() - 1, new HLine(m_ui.scrollArea.widget()));
}
auto w = new DecryptVerifyOperationWidget(m_ui.scrollArea.widget());
blay.insertWidget(blay.count() - 1, w);
w->show();
connect(w, &DecryptVerifyOperationWidget::changed, this, &WizardPage::completeChanged);
m_widgets.push_back(w);
}
}
#include "decryptverifyfileswizard.moc"
#include "moc_decryptverifyfileswizard.cpp"
diff --git a/src/crypto/gui/resolverecipientspage.cpp b/src/crypto/gui/resolverecipientspage.cpp
index 72de3407d..69832c24d 100644
--- a/src/crypto/gui/resolverecipientspage.cpp
+++ b/src/crypto/gui/resolverecipientspage.cpp
@@ -1,667 +1,668 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/gui/resolverecipientspage.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "resolverecipientspage.h"
#include "resolverecipientspage_p.h"
#include <dialogs/certificateselectiondialog.h>
#include <crypto/certificateresolver.h>
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <gpgme++/key.h>
#include <KLocalizedString>
#include <QButtonGroup>
#include <QComboBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QListWidget>
#include <QPointer>
#include <QPushButton>
#include <QRadioButton>
#include <QStringList>
#include <QToolButton>
#include <QVBoxLayout>
using namespace GpgME;
using namespace Kleo;
using namespace Kleo::Dialogs;
using namespace Kleo::Crypto;
using namespace Kleo::Crypto::Gui;
using namespace KMime::Types;
ResolveRecipientsPage::ListWidget::ListWidget(QWidget *parent, Qt::WindowFlags flags)
: QWidget(parent, flags)
, m_protocol(UnknownProtocol)
{
m_listWidget = new QListWidget;
m_listWidget->setSelectionMode(QAbstractItemView::MultiSelection);
auto const layout = new QVBoxLayout(this);
layout->addWidget(m_listWidget);
connect(m_listWidget, &QListWidget::itemSelectionChanged, this, &ListWidget::onSelectionChange);
}
ResolveRecipientsPage::ListWidget::~ListWidget()
{
}
void ResolveRecipientsPage::ListWidget::onSelectionChange()
{
const auto widgetskeys = widgets.keys();
for (const QString &i : widgetskeys) {
Q_ASSERT(items.contains(i));
widgets[i]->setSelected(items[i]->isSelected());
}
Q_EMIT selectionChanged();
}
void ResolveRecipientsPage::ListWidget::addEntry(const Mailbox &mbox)
{
addEntry(mbox.prettyAddress(), mbox.prettyAddress(), mbox);
}
void ResolveRecipientsPage::ListWidget::addEntry(const QString &id, const QString &name)
{
addEntry(id, name, Mailbox());
}
void ResolveRecipientsPage::ListWidget::addEntry(const QString &id, const QString &name, const Mailbox &mbox)
{
Q_ASSERT(!widgets.contains(id) && !items.contains(id));
auto item = new QListWidgetItem;
item->setData(IdRole, id);
auto wid = new ItemWidget(id, name, mbox, this);
connect(wid, &ItemWidget::changed, this, &ListWidget::completeChanged);
wid->setProtocol(m_protocol);
item->setSizeHint(wid->sizeHint());
m_listWidget->addItem(item);
m_listWidget->setItemWidget(item, wid);
widgets[id] = wid;
items[id] = item;
}
Mailbox ResolveRecipientsPage::ListWidget::mailbox(const QString &id) const
{
return widgets.contains(id) ? widgets[id]->mailbox() : Mailbox();
}
void ResolveRecipientsPage::ListWidget::setCertificates(const QString &id, const std::vector<Key> &pgp, const std::vector<Key> &cms)
{
Q_ASSERT(widgets.contains(id));
widgets[id]->setCertificates(pgp, cms);
}
Key ResolveRecipientsPage::ListWidget::selectedCertificate(const QString &id) const
{
return widgets.contains(id) ? widgets[id]->selectedCertificate() : Key();
}
GpgME::Key ResolveRecipientsPage::ListWidget::selectedCertificate(const QString &id, GpgME::Protocol prot) const
{
return widgets.contains(id) ? widgets[id]->selectedCertificate(prot) : Key();
}
QStringList ResolveRecipientsPage::ListWidget::identifiers() const
{
return widgets.keys();
}
void ResolveRecipientsPage::ListWidget::setProtocol(GpgME::Protocol prot)
{
if (m_protocol == prot) {
return;
}
m_protocol = prot;
for (ItemWidget *i : std::as_const(widgets)) {
i->setProtocol(prot);
}
}
void ResolveRecipientsPage::ListWidget::removeEntry(const QString &id)
{
if (!widgets.contains(id)) {
return;
}
delete items[id];
items.remove(id);
delete widgets[id];
widgets.remove(id);
}
void ResolveRecipientsPage::ListWidget::showSelectionDialog(const QString &id)
{
if (!widgets.contains(id)) {
return;
}
widgets[id]->showSelectionDialog();
}
QStringList ResolveRecipientsPage::ListWidget::selectedEntries() const
{
QStringList entries;
const QList<QListWidgetItem *> items = m_listWidget->selectedItems();
entries.reserve(items.count());
for (const QListWidgetItem *i : items) {
entries.append(i->data(IdRole).toString());
}
return entries;
}
ResolveRecipientsPage::ItemWidget::ItemWidget(const QString &id, const QString &name, const Mailbox &mbox, QWidget *parent, Qt::WindowFlags flags)
: QWidget(parent, flags)
, m_id(id)
, m_mailbox(mbox)
, m_protocol(UnknownProtocol)
, m_selected(false)
{
Q_ASSERT(!m_id.isEmpty());
setAutoFillBackground(true);
auto layout = new QHBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->addSpacing(15);
m_nameLabel = new QLabel;
m_nameLabel->setText(name);
layout->addWidget(m_nameLabel);
layout->addStretch();
m_certLabel = new QLabel;
m_certLabel->setText(i18n("<i>No certificate selected</i>"));
layout->addWidget(m_certLabel);
m_certCombo = new QComboBox;
connect(m_certCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(changed()));
layout->addWidget(m_certCombo);
m_selectButton = new QToolButton;
m_selectButton->setText(i18n("..."));
connect(m_selectButton, &QAbstractButton::clicked, this, &ItemWidget::showSelectionDialog);
layout->addWidget(m_selectButton);
layout->addSpacing(15);
setCertificates(std::vector<Key>(), std::vector<Key>());
}
void ResolveRecipientsPage::ItemWidget::updateVisibility()
{
m_certLabel->setVisible(m_certCombo->count() == 0);
m_certCombo->setVisible(m_certCombo->count() > 0);
}
ResolveRecipientsPage::ItemWidget::~ItemWidget()
{
}
QString ResolveRecipientsPage::ItemWidget::id() const
{
return m_id;
}
void ResolveRecipientsPage::ItemWidget::setSelected(bool selected)
{
if (m_selected == selected) {
return;
}
m_selected = selected;
setBackgroundRole(selected ? QPalette::Highlight : QPalette::Base);
const QPalette::ColorRole foreground = selected ? QPalette::HighlightedText : QPalette::Text;
setForegroundRole(foreground);
m_nameLabel->setForegroundRole(foreground);
m_certLabel->setForegroundRole(foreground);
}
bool ResolveRecipientsPage::ItemWidget::isSelected() const
{
return m_selected;
}
static CertificateSelectionDialog *createCertificateSelectionDialog(QWidget *parent, GpgME::Protocol prot)
{
auto const dlg = new CertificateSelectionDialog(parent);
const CertificateSelectionDialog::Options options = //
CertificateSelectionDialog::SingleSelection | //
CertificateSelectionDialog::EncryptOnly | //
CertificateSelectionDialog::MultiSelection | //
CertificateSelectionDialog::optionsFromProtocol(prot);
dlg->setOptions(options);
return dlg;
}
void ResolveRecipientsPage::ItemWidget::showSelectionDialog()
{
QPointer<CertificateSelectionDialog> dlg = createCertificateSelectionDialog(this, m_protocol);
if (dlg->exec() == QDialog::Accepted && dlg /* still with us? */) {
const GpgME::Key cert = dlg->selectedCertificate();
if (!cert.isNull()) {
addCertificateToComboBox(cert);
selectCertificateInComboBox(cert);
}
}
delete dlg;
}
Mailbox ResolveRecipientsPage::ItemWidget::mailbox() const
{
return m_mailbox;
}
void ResolveRecipientsPage::ItemWidget::selectCertificateInComboBox(const Key &key)
{
m_certCombo->setCurrentIndex(m_certCombo->findData(QLatin1StringView(key.keyID())));
}
void ResolveRecipientsPage::ItemWidget::addCertificateToComboBox(const GpgME::Key &key)
{
m_certCombo->addItem(Formatting::formatForComboBox(key), QByteArray(key.keyID()));
if (m_certCombo->count() == 1) {
m_certCombo->setCurrentIndex(0);
}
updateVisibility();
}
void ResolveRecipientsPage::ItemWidget::resetCertificates()
{
std::vector<Key> certs;
Key selected;
switch (m_protocol) {
case OpenPGP:
certs = m_pgp;
break;
case CMS:
certs = m_cms;
break;
case UnknownProtocol:
certs = m_cms;
certs.insert(certs.end(), m_pgp.begin(), m_pgp.end());
}
m_certCombo->clear();
for (const Key &i : std::as_const(certs)) {
addCertificateToComboBox(i);
}
if (!m_selectedCertificates[m_protocol].isNull()) {
selectCertificateInComboBox(m_selectedCertificates[m_protocol]);
} else if (m_certCombo->count() > 0) {
m_certCombo->setCurrentIndex(0);
}
updateVisibility();
Q_EMIT changed();
}
void ResolveRecipientsPage::ItemWidget::setProtocol(Protocol prot)
{
if (m_protocol == prot) {
return;
}
m_selectedCertificates[m_protocol] = selectedCertificate();
if (m_protocol != UnknownProtocol) {
(m_protocol == OpenPGP ? m_pgp : m_cms) = certificates();
}
m_protocol = prot;
resetCertificates();
}
void ResolveRecipientsPage::ItemWidget::setCertificates(const std::vector<Key> &pgp, const std::vector<Key> &cms)
{
m_pgp = pgp;
m_cms = cms;
resetCertificates();
}
Key ResolveRecipientsPage::ItemWidget::selectedCertificate() const
{
return KeyCache::instance()->findByKeyIDOrFingerprint(m_certCombo->itemData(m_certCombo->currentIndex(), ListWidget::IdRole).toString().toStdString());
}
GpgME::Key ResolveRecipientsPage::ItemWidget::selectedCertificate(GpgME::Protocol prot) const
{
return prot == m_protocol ? selectedCertificate() : m_selectedCertificates.value(prot);
}
std::vector<Key> ResolveRecipientsPage::ItemWidget::certificates() const
{
std::vector<Key> certs;
for (int i = 0; i < m_certCombo->count(); ++i) {
certs.push_back(KeyCache::instance()->findByKeyIDOrFingerprint(m_certCombo->itemData(i, ListWidget::IdRole).toString().toStdString()));
}
return certs;
}
class ResolveRecipientsPage::Private
{
friend class ::Kleo::Crypto::Gui::ResolveRecipientsPage;
ResolveRecipientsPage *const q;
public:
explicit Private(ResolveRecipientsPage *qq);
~Private();
void setSelectedProtocol(Protocol protocol);
void selectionChanged();
void removeSelectedEntries();
void addRecipient();
void addRecipient(const Mailbox &mbox);
void addRecipient(const QString &id, const QString &name);
void updateProtocolRBVisibility();
void protocolSelected(int prot);
void writeSelectedCertificatesToPreferences();
void completeChangedInternal();
private:
ListWidget *m_listWidget;
QPushButton *m_addButton;
QPushButton *m_removeButton;
QRadioButton *m_pgpRB;
QRadioButton *m_cmsRB;
QLabel *m_additionalRecipientsLabel;
Protocol m_presetProtocol;
Protocol m_selectedProtocol;
bool m_multipleProtocolsAllowed;
std::shared_ptr<RecipientPreferences> m_recipientPreferences;
};
ResolveRecipientsPage::Private::Private(ResolveRecipientsPage *qq)
: q(qq)
, m_presetProtocol(UnknownProtocol)
, m_selectedProtocol(m_presetProtocol)
, m_multipleProtocolsAllowed(false)
, m_recipientPreferences()
{
connect(q, SIGNAL(completeChanged()), q, SLOT(completeChangedInternal()));
q->setTitle(i18n("<b>Recipients</b>"));
auto const layout = new QVBoxLayout(q);
m_listWidget = new ListWidget;
connect(m_listWidget, SIGNAL(selectionChanged()), q, SLOT(selectionChanged()));
connect(m_listWidget, &ListWidget::completeChanged, q, &WizardPage::completeChanged);
layout->addWidget(m_listWidget);
m_additionalRecipientsLabel = new QLabel;
m_additionalRecipientsLabel->setWordWrap(true);
layout->addWidget(m_additionalRecipientsLabel);
m_additionalRecipientsLabel->setVisible(false);
auto buttonWidget = new QWidget;
auto buttonLayout = new QHBoxLayout(buttonWidget);
buttonLayout->setContentsMargins(0, 0, 0, 0);
m_addButton = new QPushButton;
connect(m_addButton, SIGNAL(clicked()), q, SLOT(addRecipient()));
m_addButton->setText(i18n("Add Recipient..."));
buttonLayout->addWidget(m_addButton);
m_removeButton = new QPushButton;
m_removeButton->setEnabled(false);
m_removeButton->setText(i18n("Remove Selected"));
connect(m_removeButton, SIGNAL(clicked()), q, SLOT(removeSelectedEntries()));
buttonLayout->addWidget(m_removeButton);
buttonLayout->addStretch();
layout->addWidget(buttonWidget);
auto protocolWidget = new QWidget;
auto protocolLayout = new QHBoxLayout(protocolWidget);
auto protocolGroup = new QButtonGroup(q);
connect(protocolGroup, &QButtonGroup::idClicked, q, [this](int buttonClicked) {
protocolSelected(buttonClicked);
});
m_pgpRB = new QRadioButton;
m_pgpRB->setText(i18n("OpenPGP"));
protocolGroup->addButton(m_pgpRB, OpenPGP);
protocolLayout->addWidget(m_pgpRB);
m_cmsRB = new QRadioButton;
m_cmsRB->setText(i18n("S/MIME"));
protocolGroup->addButton(m_cmsRB, CMS);
protocolLayout->addWidget(m_cmsRB);
protocolLayout->addStretch();
layout->addWidget(protocolWidget);
}
ResolveRecipientsPage::Private::~Private()
{
}
void ResolveRecipientsPage::Private::completeChangedInternal()
{
const bool isComplete = q->isComplete();
const std::vector<Key> keys = q->resolvedCertificates();
const bool haveSecret = std::find_if(keys.begin(),
keys.end(),
[](const Key &key) {
return key.hasSecret();
})
!= keys.end();
if (isComplete && !haveSecret) {
q->setExplanation(
i18n("<b>Warning:</b> None of the selected certificates seem to be your own. You will not be able to decrypt the encrypted data again."));
} else {
q->setExplanation(QString());
}
}
void ResolveRecipientsPage::Private::updateProtocolRBVisibility()
{
const bool visible = !m_multipleProtocolsAllowed && m_presetProtocol == UnknownProtocol;
m_cmsRB->setVisible(visible);
m_pgpRB->setVisible(visible);
if (visible) {
if (m_selectedProtocol == CMS) {
m_cmsRB->click();
} else {
m_pgpRB->click();
}
}
}
bool ResolveRecipientsPage::isComplete() const
{
const QStringList ids = d->m_listWidget->identifiers();
if (ids.isEmpty()) {
return false;
}
for (const QString &i : ids) {
if (d->m_listWidget->selectedCertificate(i).isNull()) {
return false;
}
}
return true;
}
ResolveRecipientsPage::ResolveRecipientsPage(QWidget *parent)
: WizardPage(parent)
, d(new Private(this))
{
}
ResolveRecipientsPage::~ResolveRecipientsPage()
{
}
Protocol ResolveRecipientsPage::selectedProtocol() const
{
return d->m_selectedProtocol;
}
void ResolveRecipientsPage::Private::setSelectedProtocol(Protocol protocol)
{
if (m_selectedProtocol == protocol) {
return;
}
m_selectedProtocol = protocol;
m_listWidget->setProtocol(m_selectedProtocol);
Q_EMIT q->selectedProtocolChanged();
}
void ResolveRecipientsPage::Private::protocolSelected(int p)
{
const auto protocol = static_cast<Protocol>(p);
Q_ASSERT(protocol != UnknownProtocol);
setSelectedProtocol(protocol);
}
void ResolveRecipientsPage::setPresetProtocol(Protocol prot)
{
if (d->m_presetProtocol == prot) {
return;
}
d->m_presetProtocol = prot;
d->setSelectedProtocol(prot);
if (prot != UnknownProtocol) {
d->m_multipleProtocolsAllowed = false;
}
d->updateProtocolRBVisibility();
}
Protocol ResolveRecipientsPage::presetProtocol() const
{
return d->m_presetProtocol;
}
bool ResolveRecipientsPage::multipleProtocolsAllowed() const
{
return d->m_multipleProtocolsAllowed;
}
void ResolveRecipientsPage::setMultipleProtocolsAllowed(bool allowed)
{
if (d->m_multipleProtocolsAllowed == allowed) {
return;
}
d->m_multipleProtocolsAllowed = allowed;
if (d->m_multipleProtocolsAllowed) {
setPresetProtocol(UnknownProtocol);
d->setSelectedProtocol(UnknownProtocol);
}
d->updateProtocolRBVisibility();
}
void ResolveRecipientsPage::Private::addRecipient(const QString &id, const QString &name)
{
m_listWidget->addEntry(id, name);
}
void ResolveRecipientsPage::Private::addRecipient(const Mailbox &mbox)
{
m_listWidget->addEntry(mbox);
}
void ResolveRecipientsPage::Private::addRecipient()
{
QPointer<CertificateSelectionDialog> dlg = createCertificateSelectionDialog(q, q->selectedProtocol());
if (dlg->exec() != QDialog::Accepted || !dlg /*q already deleted*/) {
return;
}
const std::vector<Key> keys = dlg->selectedCertificates();
int i = 0;
for (const Key &key : keys) {
const QStringList existing = m_listWidget->identifiers();
QString rec = i18n("Recipient");
while (existing.contains(rec)) {
rec = i18nc("%1 == number", "Recipient (%1)", ++i);
}
addRecipient(rec, rec);
const std::vector<Key> pgp = key.protocol() == OpenPGP ? std::vector<Key>(1, key) : std::vector<Key>();
const std::vector<Key> cms = key.protocol() == CMS ? std::vector<Key>(1, key) : std::vector<Key>();
m_listWidget->setCertificates(rec, pgp, cms);
}
Q_EMIT q->completeChanged();
}
static QString listKeysForInfo(const std::vector<Key> &keys)
{
QStringList list;
std::transform(keys.begin(), keys.end(), list.begin(), &Formatting::formatKeyLink);
return list.join(QLatin1StringView("<br/>"));
}
void ResolveRecipientsPage::setAdditionalRecipientsInfo(const std::vector<Key> &recipients)
{
d->m_additionalRecipientsLabel->setVisible(!recipients.empty());
if (recipients.empty()) {
return;
}
d->m_additionalRecipientsLabel->setText(i18n("<qt><p>Recipients predefined via GnuPG settings:</p>%1</qt>", listKeysForInfo(recipients)));
}
std::vector<Key> ResolveRecipientsPage::resolvedCertificates() const
{
std::vector<Key> certs;
const QStringList identifiers = d->m_listWidget->identifiers();
for (const QString &i : identifiers) {
const GpgME::Key cert = d->m_listWidget->selectedCertificate(i);
if (!cert.isNull()) {
certs.push_back(cert);
}
}
return certs;
}
void ResolveRecipientsPage::Private::selectionChanged()
{
m_removeButton->setEnabled(!m_listWidget->selectedEntries().isEmpty());
}
void ResolveRecipientsPage::Private::removeSelectedEntries()
{
const auto selectedEntries{m_listWidget->selectedEntries()};
for (const QString &i : selectedEntries) {
m_listWidget->removeEntry(i);
}
Q_EMIT q->completeChanged();
}
void ResolveRecipientsPage::setRecipientsUserMutable(bool isMutable)
{
d->m_addButton->setVisible(isMutable);
d->m_removeButton->setVisible(isMutable);
}
bool ResolveRecipientsPage::recipientsUserMutable() const
{
return d->m_addButton->isVisible();
}
std::shared_ptr<RecipientPreferences> ResolveRecipientsPage::recipientPreferences() const
{
return d->m_recipientPreferences;
}
void ResolveRecipientsPage::setRecipientPreferences(const std::shared_ptr<RecipientPreferences> &prefs)
{
d->m_recipientPreferences = prefs;
}
void ResolveRecipientsPage::Private::writeSelectedCertificatesToPreferences()
{
if (!m_recipientPreferences) {
return;
}
const auto identifiers{m_listWidget->identifiers()};
for (const QString &i : identifiers) {
const Mailbox mbox = m_listWidget->mailbox(i);
if (!mbox.hasAddress()) {
continue;
}
const Key pgp = m_listWidget->selectedCertificate(i, OpenPGP);
if (!pgp.isNull()) {
m_recipientPreferences->setPreferredCertificate(mbox, OpenPGP, pgp);
}
const Key cms = m_listWidget->selectedCertificate(i, CMS);
if (!cms.isNull()) {
m_recipientPreferences->setPreferredCertificate(mbox, CMS, cms);
}
}
}
-void ResolveRecipientsPage::onNext()
+bool ResolveRecipientsPage::onNext()
{
d->writeSelectedCertificatesToPreferences();
+ return true;
}
#include "moc_resolverecipientspage.cpp"
#include "moc_resolverecipientspage_p.cpp"
diff --git a/src/crypto/gui/resolverecipientspage.h b/src/crypto/gui/resolverecipientspage.h
index b176e8b4d..ec12d2944 100644
--- a/src/crypto/gui/resolverecipientspage.h
+++ b/src/crypto/gui/resolverecipientspage.h
@@ -1,99 +1,99 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/gui/resolverecipientspage.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <crypto/gui/wizardpage.h>
#include <gpgme++/global.h>
#include <memory>
#include <vector>
namespace GpgME
{
class Key;
}
namespace KMime
{
namespace Types
{
class Mailbox;
}
}
namespace Kleo
{
namespace Crypto
{
class RecipientPreferences;
namespace Gui
{
class ResolveRecipientsPage : public WizardPage
{
Q_OBJECT
public:
explicit ResolveRecipientsPage(QWidget *parent = nullptr);
~ResolveRecipientsPage() override;
bool isComplete() const override;
/**
* The protocol selected by the user (which is chosen by
* the user in case none was preset)
*/
GpgME::Protocol selectedProtocol() const;
/**
* the protocol set before the dialog is shown. Defaults to
* GpgME::UnknownProtocol */
GpgME::Protocol presetProtocol() const;
void setPresetProtocol(GpgME::Protocol protocol);
bool multipleProtocolsAllowed() const;
void setMultipleProtocolsAllowed(bool allowed);
/** if true, the user is allowed to remove/add recipients via the UI.
* Defaults to @p false.
*/
bool recipientsUserMutable() const;
void setRecipientsUserMutable(bool isMutable);
void setAdditionalRecipientsInfo(const std::vector<GpgME::Key> &recipients);
std::vector<GpgME::Key> resolvedCertificates() const;
std::shared_ptr<RecipientPreferences> recipientPreferences() const;
void setRecipientPreferences(const std::shared_ptr<RecipientPreferences> &prefs);
Q_SIGNALS:
void selectedProtocolChanged();
private:
- void onNext() override;
+ bool onNext() override;
private:
class Private;
const std::unique_ptr<Private> d;
Q_PRIVATE_SLOT(d, void selectionChanged())
Q_PRIVATE_SLOT(d, void protocolSelected(int))
Q_PRIVATE_SLOT(d, void addRecipient())
Q_PRIVATE_SLOT(d, void removeSelectedEntries())
Q_PRIVATE_SLOT(d, void completeChangedInternal())
class ListWidget;
class ItemWidget;
};
}
}
}
diff --git a/src/crypto/gui/signerresolvepage.cpp b/src/crypto/gui/signerresolvepage.cpp
index fd419a5d8..b2ba86aca 100644
--- a/src/crypto/gui/signerresolvepage.cpp
+++ b/src/crypto/gui/signerresolvepage.cpp
@@ -1,670 +1,671 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/gui/signerresolvepage.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "signerresolvepage.h"
#include "signerresolvepage_p.h"
#include "signingcertificateselectiondialog.h"
#include "crypto/certificateresolver.h"
#include "utils/certificatepair.h"
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <utils/kleo_assert.h>
#include <gpgme++/key.h>
#include <KLocalizedString>
#include <QDialog>
#include <QButtonGroup>
#include <QCheckBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include <QPointer>
#include <QPushButton>
#include <QRadioButton>
#include <QVBoxLayout>
using namespace GpgME;
using namespace Kleo;
using namespace Kleo::Crypto;
using namespace Kleo::Crypto::Gui;
namespace
{
static SignerResolvePage::Operation operationFromFlags(bool sign, bool encrypt)
{
if (!encrypt && sign) {
return SignerResolvePage::SignOnly;
}
if (!sign && encrypt) {
return SignerResolvePage::EncryptOnly;
}
return SignerResolvePage::SignAndEncrypt;
}
static QString formatLabel(Protocol p, const Key &key)
{
return i18nc("%1=protocol (S/Mime, OpenPGP), %2=certificate",
"Sign using %1: %2",
Formatting::displayName(p),
!key.isNull() ? Formatting::formatForComboBox(key) : i18n("No certificate selected"));
}
static std::vector<Protocol> supportedProtocols()
{
std::vector<Protocol> protocols;
protocols.push_back(OpenPGP);
protocols.push_back(CMS);
return protocols;
}
}
AbstractSigningProtocolSelectionWidget::AbstractSigningProtocolSelectionWidget(QWidget *p, Qt::WindowFlags f)
: QWidget(p, f)
{
}
ReadOnlyProtocolSelectionWidget::ReadOnlyProtocolSelectionWidget(QWidget *p, Qt::WindowFlags f)
: AbstractSigningProtocolSelectionWidget(p, f)
{
auto const layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
const auto supportedProtocolsLst = supportedProtocols();
for (const Protocol i : supportedProtocolsLst) {
auto const l = new QLabel;
l->setText(formatLabel(i, Key()));
layout->addWidget(l);
m_labels[i] = l;
}
}
void ReadOnlyProtocolSelectionWidget::setProtocolChecked(Protocol protocol, bool checked)
{
QLabel *const l = label(protocol);
Q_ASSERT(l);
l->setVisible(checked);
}
bool ReadOnlyProtocolSelectionWidget::isProtocolChecked(Protocol protocol) const
{
QLabel *const l = label(protocol);
Q_ASSERT(l);
return l->isVisible();
}
std::set<Protocol> ReadOnlyProtocolSelectionWidget::checkedProtocols() const
{
std::set<Protocol> res;
for (const Protocol i : supportedProtocols()) {
if (isProtocolChecked(i)) {
res.insert(i);
}
}
return res;
}
SigningProtocolSelectionWidget::SigningProtocolSelectionWidget(QWidget *parent, Qt::WindowFlags f)
: AbstractSigningProtocolSelectionWidget(parent, f)
{
m_buttonGroup = new QButtonGroup(this);
connect(m_buttonGroup, &QButtonGroup::idClicked, this, &SigningProtocolSelectionWidget::userSelectionChanged);
auto const layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
for (const Protocol i : supportedProtocols()) {
auto const b = new QCheckBox;
b->setText(formatLabel(i, Key()));
m_buttons[i] = b;
layout->addWidget(b);
m_buttonGroup->addButton(b);
}
setExclusive(true);
}
void SigningProtocolSelectionWidget::setProtocolChecked(Protocol p, bool checked)
{
Q_ASSERT(p != UnknownProtocol);
QCheckBox *const b = button(p);
Q_ASSERT(b);
b->setChecked(checked);
}
bool SigningProtocolSelectionWidget::isProtocolChecked(Protocol p) const
{
Q_ASSERT(p != UnknownProtocol);
const QAbstractButton *const b = button(p);
Q_ASSERT(b);
return b->isChecked();
}
std::set<Protocol> SigningProtocolSelectionWidget::checkedProtocols() const
{
std::set<Protocol> res;
for (auto it = m_buttons.begin(), end = m_buttons.end(); it != end; ++it)
if (it->second->isChecked()) {
res.insert(it->first);
}
return res;
}
void SigningProtocolSelectionWidget::setExclusive(bool exclusive)
{
if (exclusive == isExclusive()) {
return;
}
m_buttonGroup->setExclusive(exclusive);
Q_EMIT userSelectionChanged();
}
QCheckBox *SigningProtocolSelectionWidget::button(Protocol p) const
{
const auto it = m_buttons.find(p);
return it == m_buttons.end() ? nullptr : it->second;
}
QLabel *ReadOnlyProtocolSelectionWidget::label(Protocol p) const
{
const auto it = m_labels.find(p);
return it == m_labels.end() ? nullptr : it->second;
}
bool SigningProtocolSelectionWidget::isExclusive() const
{
return m_buttonGroup->exclusive();
}
void SigningProtocolSelectionWidget::setCertificate(Protocol prot, const Key &key)
{
QAbstractButton *const b = button(prot);
Q_ASSERT(b);
b->setText(formatLabel(prot, key));
}
void ReadOnlyProtocolSelectionWidget::setCertificate(Protocol prot, const Key &key)
{
QLabel *const l = label(prot);
l->setText(formatLabel(prot, key));
}
namespace
{
class ValidatorImpl : public SignerResolvePage::Validator
{
public:
QString explanation() const override
{
return QString();
}
bool isComplete() const override
{
return true;
}
QString customWindowTitle() const override
{
return QString();
}
};
}
class SignerResolvePage::Private
{
friend class ::Kleo::Crypto::Gui::SignerResolvePage;
SignerResolvePage *const q;
public:
explicit Private(SignerResolvePage *qq);
~Private();
void setOperation(Operation operation);
void operationButtonClicked(int operation);
void selectCertificates();
void setCertificates(const CertificatePair &certs);
void updateModeSelectionWidgets();
void updateUi();
bool protocolSelected(Protocol p) const;
bool protocolSelectionActuallyUserMutable() const;
private:
QButtonGroup *signEncryptGroup;
QRadioButton *signAndEncryptRB;
QRadioButton *encryptOnlyRB;
QRadioButton *signOnlyRB;
QGroupBox *signingCertificateBox;
QLabel *signerLabelLabel;
QLabel *signerLabel;
QGroupBox *encryptBox;
QCheckBox *textArmorCO;
QPushButton *selectCertificatesButton;
SigningProtocolSelectionWidget *signingProtocolSelectionWidget;
ReadOnlyProtocolSelectionWidget *readOnlyProtocolSelectionWidget;
std::vector<Protocol> presetProtocols;
bool signingMutable;
bool encryptionMutable;
bool signingSelected;
bool encryptionSelected;
bool multipleProtocolsAllowed;
bool protocolSelectionUserMutable;
CertificatePair certificates;
std::shared_ptr<SignerResolvePage::Validator> validator;
std::shared_ptr<SigningPreferences> signingPreferences;
};
bool SignerResolvePage::Private::protocolSelectionActuallyUserMutable() const
{
return (q->protocolSelectionUserMutable() || presetProtocols.empty()) && q->operation() == SignOnly;
}
SignerResolvePage::Private::Private(SignerResolvePage *qq)
: q(qq)
, presetProtocols()
, signingMutable(true)
, encryptionMutable(true)
, signingSelected(false)
, encryptionSelected(false)
, multipleProtocolsAllowed(false)
, protocolSelectionUserMutable(true)
, validator(new ValidatorImpl)
{
auto layout = new QVBoxLayout(q);
signEncryptGroup = new QButtonGroup(q);
q->connect(signEncryptGroup, &QButtonGroup::idClicked, q, [this](int buttonClicked) {
operationButtonClicked(buttonClicked);
});
signAndEncryptRB = new QRadioButton;
signAndEncryptRB->setText(i18n("Sign and encrypt (OpenPGP only)"));
signAndEncryptRB->setChecked(true);
signEncryptGroup->addButton(signAndEncryptRB, SignAndEncrypt);
layout->addWidget(signAndEncryptRB);
encryptOnlyRB = new QRadioButton;
encryptOnlyRB->setText(i18n("Encrypt only"));
signEncryptGroup->addButton(encryptOnlyRB, EncryptOnly);
layout->addWidget(encryptOnlyRB);
signOnlyRB = new QRadioButton;
signOnlyRB->setText(i18n("Sign only"));
signEncryptGroup->addButton(signOnlyRB, SignOnly);
layout->addWidget(signOnlyRB);
encryptBox = new QGroupBox;
encryptBox->setTitle(i18n("Encryption Options"));
QBoxLayout *const encryptLayout = new QVBoxLayout(encryptBox);
textArmorCO = new QCheckBox;
textArmorCO->setText(i18n("Text output (ASCII armor)"));
encryptLayout->addWidget(textArmorCO);
layout->addWidget(encryptBox);
signingCertificateBox = new QGroupBox;
signingCertificateBox->setTitle(i18n("Signing Options"));
auto signerLayout = new QGridLayout(signingCertificateBox);
signerLayout->setColumnStretch(1, 1);
signerLabelLabel = new QLabel;
signerLabelLabel->setText(i18n("Signer:"));
signerLayout->addWidget(signerLabelLabel, 1, 0);
signerLabel = new QLabel;
signerLayout->addWidget(signerLabel, 1, 1);
signerLabelLabel->setVisible(false);
signerLabel->setVisible(false);
signingProtocolSelectionWidget = new SigningProtocolSelectionWidget;
connect(signingProtocolSelectionWidget, SIGNAL(userSelectionChanged()), q, SLOT(updateUi()));
signerLayout->addWidget(signingProtocolSelectionWidget, 2, 0, 1, -1);
readOnlyProtocolSelectionWidget = new ReadOnlyProtocolSelectionWidget;
signerLayout->addWidget(readOnlyProtocolSelectionWidget, 3, 0, 1, -1);
selectCertificatesButton = new QPushButton;
selectCertificatesButton->setText(i18n("Change Signing Certificates..."));
selectCertificatesButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
signerLayout->addWidget(selectCertificatesButton, 4, 0, 1, -1, Qt::AlignLeft);
q->connect(selectCertificatesButton, SIGNAL(clicked()), q, SLOT(selectCertificates()));
layout->addWidget(signingCertificateBox);
layout->addStretch();
}
void SignerResolvePage::setValidator(const std::shared_ptr<SignerResolvePage::Validator> &validator)
{
Q_ASSERT(validator);
d->validator = validator;
d->updateUi();
}
std::shared_ptr<SignerResolvePage::Validator> SignerResolvePage::validator() const
{
return d->validator;
}
SignerResolvePage::Private::~Private()
{
}
bool SignerResolvePage::Private::protocolSelected(Protocol p) const
{
Q_ASSERT(p != UnknownProtocol);
return signingProtocolSelectionWidget->isProtocolChecked(p);
}
void SignerResolvePage::Private::setCertificates(const CertificatePair &certs)
{
certificates = certs;
readOnlyProtocolSelectionWidget->setCertificate(GpgME::OpenPGP, certs.openpgp);
signingProtocolSelectionWidget->setCertificate(GpgME::OpenPGP, certs.openpgp);
readOnlyProtocolSelectionWidget->setCertificate(GpgME::CMS, certs.cms);
signingProtocolSelectionWidget->setCertificate(GpgME::CMS, certs.cms);
updateUi();
}
void SignerResolvePage::Private::updateUi()
{
const bool ismutable = protocolSelectionActuallyUserMutable();
readOnlyProtocolSelectionWidget->setVisible(!ismutable);
signingProtocolSelectionWidget->setVisible(ismutable);
q->setExplanation(validator->explanation());
Q_EMIT q->completeChanged();
const QString customTitle = validator->customWindowTitle();
if (!customTitle.isEmpty()) {
Q_EMIT q->windowTitleChanged(customTitle);
}
selectCertificatesButton->setEnabled(signingProtocolSelectionWidget->checkedProtocols().size() > 0);
}
void SignerResolvePage::setProtocolSelectionUserMutable(bool ismutable)
{
if (d->protocolSelectionUserMutable == ismutable) {
return;
}
d->protocolSelectionUserMutable = ismutable;
d->updateModeSelectionWidgets();
}
bool SignerResolvePage::protocolSelectionUserMutable() const
{
return d->protocolSelectionUserMutable;
}
void SignerResolvePage::setMultipleProtocolsAllowed(bool allowed)
{
if (d->multipleProtocolsAllowed == allowed) {
return;
}
d->multipleProtocolsAllowed = allowed;
d->updateModeSelectionWidgets();
}
bool SignerResolvePage::multipleProtocolsAllowed() const
{
return d->multipleProtocolsAllowed;
}
void SignerResolvePage::Private::updateModeSelectionWidgets()
{
const bool bothMutable = signingMutable && encryptionMutable;
const bool noSigningPossible = !signingSelected && !signingMutable;
const bool noEncryptionPossible = !encryptionSelected && !encryptionMutable;
signAndEncryptRB->setChecked(signingSelected && encryptionSelected);
signOnlyRB->setChecked(signingSelected && !encryptionSelected);
encryptOnlyRB->setChecked(encryptionSelected && !signingSelected);
const bool canSignAndEncrypt = !noSigningPossible && !noEncryptionPossible && bothMutable && presetProtocols != std::vector<Protocol>(1, CMS);
const bool canSignOnly = !encryptionSelected || encryptionMutable;
const bool canEncryptOnly = !signingSelected || signingMutable;
signAndEncryptRB->setEnabled(canSignAndEncrypt);
signOnlyRB->setEnabled(canSignOnly);
encryptOnlyRB->setEnabled(canEncryptOnly);
const bool buttonsVisible = signingMutable || encryptionMutable;
signOnlyRB->setVisible(buttonsVisible);
encryptOnlyRB->setVisible(buttonsVisible);
signAndEncryptRB->setVisible(buttonsVisible);
signingProtocolSelectionWidget->setExclusive(!multipleProtocolsAllowed);
signingCertificateBox->setVisible(!noSigningPossible);
encryptBox->setVisible(!noEncryptionPossible);
updateUi();
}
void SignerResolvePage::Private::selectCertificates()
{
QPointer<SigningCertificateSelectionDialog> dlg = new SigningCertificateSelectionDialog(q);
dlg->setAllowedProtocols(signingProtocolSelectionWidget->checkedProtocols());
if (dlg->exec() == QDialog::Accepted && dlg) {
const auto certs = dlg->selectedCertificates();
setCertificates(certs);
if (signingPreferences && dlg->rememberAsDefault()) {
signingPreferences->setPreferredCertificate(OpenPGP, certs.openpgp);
signingPreferences->setPreferredCertificate(CMS, certs.cms);
}
}
delete dlg;
updateUi();
}
void SignerResolvePage::Private::operationButtonClicked(int mode_)
{
const auto op = static_cast<SignerResolvePage::Operation>(mode_);
signingCertificateBox->setEnabled(op != EncryptOnly);
encryptBox->setEnabled(op != SignOnly);
if (op == SignAndEncrypt) {
signingProtocolSelectionWidget->setProtocolChecked(CMS, false);
readOnlyProtocolSelectionWidget->setProtocolChecked(CMS, false);
signingProtocolSelectionWidget->setProtocolChecked(OpenPGP, true);
readOnlyProtocolSelectionWidget->setProtocolChecked(OpenPGP, true);
}
updateUi();
}
void SignerResolvePage::Private::setOperation(Operation op)
{
switch (op) {
case SignOnly:
signOnlyRB->click();
break;
case EncryptOnly:
encryptOnlyRB->click();
break;
case SignAndEncrypt:
signAndEncryptRB->click();
break;
}
}
SignerResolvePage::Operation SignerResolvePage::operation() const
{
return operationFromFlags(signingSelected(), encryptionSelected());
}
SignerResolvePage::SignerResolvePage(QWidget *parent, Qt::WindowFlags f)
: WizardPage(parent, f)
, d(new Private(this))
{
setTitle(i18n("<b>Choose Operation to be Performed</b>"));
// setSubTitle( i18n( "TODO" ) );
setPresetProtocol(UnknownProtocol);
d->setCertificates({});
d->updateModeSelectionWidgets();
d->operationButtonClicked(EncryptOnly);
}
SignerResolvePage::~SignerResolvePage()
{
}
void SignerResolvePage::setSignersAndCandidates(const std::vector<KMime::Types::Mailbox> &signers, const std::vector<std::vector<GpgME::Key>> &keys)
{
kleo_assert(signers.empty() || signers.size() == keys.size());
switch (signers.size()) {
case 0:
d->signerLabelLabel->setVisible(false);
d->signerLabel->setVisible(false); // TODO: use default identity?
break;
case 1:
d->signerLabelLabel->setVisible(true);
d->signerLabel->setVisible(true); // TODO: use default identity?
d->signerLabel->setText(signers.front().prettyAddress());
break;
default: // > 1
kleo_assert(!"Resolving multiple signers not implemented");
}
d->updateUi();
}
void SignerResolvePage::setPresetProtocol(Protocol protocol)
{
std::vector<Protocol> protocols;
if (protocol != CMS) {
protocols.push_back(OpenPGP);
}
if (protocol != OpenPGP) {
protocols.push_back(CMS);
}
setPresetProtocols(protocols);
d->updateUi();
}
void SignerResolvePage::setPresetProtocols(const std::vector<Protocol> &protocols)
{
d->presetProtocols = protocols;
for (const Protocol i : supportedProtocols()) {
const bool checked = std::find(protocols.begin(), protocols.end(), i) != protocols.end();
d->signingProtocolSelectionWidget->setProtocolChecked(i, checked);
d->readOnlyProtocolSelectionWidget->setProtocolChecked(i, checked);
}
d->updateModeSelectionWidgets();
}
std::set<Protocol> SignerResolvePage::selectedProtocols() const
{
return d->signingProtocolSelectionWidget->checkedProtocols();
}
std::vector<Key> SignerResolvePage::signingCertificates(Protocol protocol) const
{
std::vector<Key> result;
if (protocol != CMS && d->signingProtocolSelectionWidget->isProtocolChecked(OpenPGP) && !d->certificates.openpgp.isNull()) {
result.push_back(d->certificates.openpgp);
}
if (protocol != OpenPGP && d->signingProtocolSelectionWidget->isProtocolChecked(CMS) && !d->certificates.cms.isNull()) {
result.push_back(d->certificates.cms);
}
return result;
}
std::vector<Key> SignerResolvePage::resolvedSigners() const
{
std::vector<Key> result = signingCertificates(CMS);
const std::vector<Key> pgp = signingCertificates(OpenPGP);
result.insert(result.end(), pgp.begin(), pgp.end());
return result;
}
bool SignerResolvePage::isComplete() const
{
Q_ASSERT(d->validator);
return d->validator->isComplete();
}
bool SignerResolvePage::encryptionSelected() const
{
return !d->signOnlyRB->isChecked();
}
void SignerResolvePage::setEncryptionSelected(bool selected)
{
d->encryptionSelected = selected;
d->updateModeSelectionWidgets();
d->setOperation(operationFromFlags(d->signingSelected, d->encryptionSelected));
}
bool SignerResolvePage::signingSelected() const
{
return !d->encryptOnlyRB->isChecked();
}
void SignerResolvePage::setSigningSelected(bool selected)
{
d->signingSelected = selected;
d->updateModeSelectionWidgets();
d->setOperation(operationFromFlags(d->signingSelected, d->encryptionSelected));
}
bool SignerResolvePage::isEncryptionUserMutable() const
{
return d->encryptionMutable;
}
bool SignerResolvePage::isSigningUserMutable() const
{
return d->signingMutable;
}
void SignerResolvePage::setEncryptionUserMutable(bool ismutable)
{
d->encryptionMutable = ismutable;
d->updateModeSelectionWidgets();
}
void SignerResolvePage::setSigningUserMutable(bool ismutable)
{
d->signingMutable = ismutable;
d->updateModeSelectionWidgets();
}
std::set<Protocol> SignerResolvePage::selectedProtocolsWithoutSigningCertificate() const
{
std::set<Protocol> res;
for (const Protocol i : selectedProtocols()) {
if (signingCertificates(i).empty()) {
res.insert(i);
}
}
return res;
}
bool SignerResolvePage::isAsciiArmorEnabled() const
{
return d->textArmorCO->isChecked();
}
void SignerResolvePage::setAsciiArmorEnabled(bool enabled)
{
d->textArmorCO->setChecked(enabled);
}
void SignerResolvePage::setSigningPreferences(const std::shared_ptr<SigningPreferences> &prefs)
{
d->signingPreferences = prefs;
const CertificatePair certs = {prefs ? prefs->preferredCertificate(OpenPGP) : Key(), prefs ? prefs->preferredCertificate(CMS) : Key()};
d->setCertificates(certs);
}
std::shared_ptr<SigningPreferences> SignerResolvePage::signingPreferences() const
{
return d->signingPreferences;
}
-void SignerResolvePage::onNext()
+bool SignerResolvePage::onNext()
{
+ return true;
}
#include "moc_signerresolvepage.cpp"
#include "moc_signerresolvepage_p.cpp"
diff --git a/src/crypto/gui/signerresolvepage.h b/src/crypto/gui/signerresolvepage.h
index b39249990..5c830b7b8 100644
--- a/src/crypto/gui/signerresolvepage.h
+++ b/src/crypto/gui/signerresolvepage.h
@@ -1,121 +1,121 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/gui/signerresolvepage.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <crypto/gui/wizardpage.h>
#include <KMime/Types>
#include <gpgme++/global.h>
#include <memory>
#include <set>
#include <vector>
namespace GpgME
{
class Key;
}
namespace Kleo
{
namespace Crypto
{
class SigningPreferences;
namespace Gui
{
class SignerResolvePage : public WizardPage
{
Q_OBJECT
public:
explicit SignerResolvePage(QWidget *parent = nullptr, Qt::WindowFlags f = {});
~SignerResolvePage() override;
void setSignersAndCandidates(const std::vector<KMime::Types::Mailbox> &signers, const std::vector<std::vector<GpgME::Key>> &keys);
std::vector<GpgME::Key> resolvedSigners() const;
std::vector<GpgME::Key> signingCertificates(GpgME::Protocol protocol = GpgME::UnknownProtocol) const;
bool isComplete() const override;
bool encryptionSelected() const;
void setEncryptionSelected(bool selected);
bool signingSelected() const;
void setSigningSelected(bool selected);
bool isEncryptionUserMutable() const;
void setEncryptionUserMutable(bool ismutable);
bool isSigningUserMutable() const;
void setSigningUserMutable(bool ismutable);
bool isAsciiArmorEnabled() const;
void setAsciiArmorEnabled(bool enabled);
void setPresetProtocol(GpgME::Protocol protocol);
void setPresetProtocols(const std::vector<GpgME::Protocol> &protocols);
std::set<GpgME::Protocol> selectedProtocols() const;
std::set<GpgME::Protocol> selectedProtocolsWithoutSigningCertificate() const;
void setMultipleProtocolsAllowed(bool allowed);
bool multipleProtocolsAllowed() const;
void setProtocolSelectionUserMutable(bool ismutable);
bool protocolSelectionUserMutable() const;
enum Operation {
SignAndEncrypt = 0,
SignOnly,
EncryptOnly,
};
Operation operation() const;
class Validator
{
public:
virtual ~Validator()
{
}
virtual bool isComplete() const = 0;
virtual QString explanation() const = 0;
/**
* returns a custom window title, or a null string if no custom
* title is required.
* (use this if the title needs dynamic adaption
* depending on the user's selection)
*/
virtual QString customWindowTitle() const = 0;
};
void setValidator(const std::shared_ptr<Validator> &);
std::shared_ptr<Validator> validator() const;
void setSigningPreferences(const std::shared_ptr<SigningPreferences> &prefs);
std::shared_ptr<SigningPreferences> signingPreferences() const;
private:
- void onNext() override;
+ bool onNext() override;
private:
class Private;
const std::unique_ptr<Private> d;
Q_PRIVATE_SLOT(d, void operationButtonClicked(int))
Q_PRIVATE_SLOT(d, void selectCertificates())
Q_PRIVATE_SLOT(d, void updateUi())
};
}
}
}
diff --git a/src/crypto/gui/wizard.cpp b/src/crypto/gui/wizard.cpp
index cd4d014f0..f2f9bea3c 100644
--- a/src/crypto/gui/wizard.cpp
+++ b/src/crypto/gui/wizard.cpp
@@ -1,350 +1,352 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/gui/wizard.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "wizard.h"
#include "wizardpage.h"
#include <utils/kleo_assert.h>
#include <Libkleo/Algorithm>
#include <KGuiItem>
#include <KLocalizedString>
#include <KStandardGuiItem>
#include <QPushButton>
#include "kleopatra_debug.h"
#include <QDialogButtonBox>
#include <QFrame>
#include <QLabel>
#include <QStackedWidget>
#include <QTimer>
#include <QVBoxLayout>
#include <map>
#include <set>
using namespace Kleo::Crypto::Gui;
class Wizard::Private
{
friend class ::Wizard;
Wizard *const q;
public:
explicit Private(Wizard *qq);
~Private();
void updateButtonStates();
bool isLastPage(int id) const;
int previousPage() const;
void updateHeader();
private:
std::vector<int> pageOrder;
std::set<int> hiddenPages;
std::map<int, WizardPage *> idToPage;
int currentId = -1;
QStackedWidget *const stack;
QPushButton *nextButton = nullptr;
QPushButton *backButton = nullptr;
QPushButton *cancelButton = nullptr;
KGuiItem finishItem;
KGuiItem nextItem;
QFrame *titleFrame = nullptr;
QLabel *titleLabel = nullptr;
QLabel *subTitleLabel = nullptr;
QFrame *explanationFrame = nullptr;
QLabel *explanationLabel = nullptr;
QTimer *nextPageTimer = nullptr;
};
Wizard::Private::Private(Wizard *qq)
: q(qq)
, stack(new QStackedWidget)
{
nextPageTimer = new QTimer(q);
nextPageTimer->setInterval(0);
connect(nextPageTimer, &QTimer::timeout, q, &Wizard::next);
nextItem = KGuiItem(i18nc("@action:button", "&Next"));
finishItem = KStandardGuiItem::ok();
auto const top = new QVBoxLayout(q);
top->setContentsMargins(0, 0, 0, 0);
titleFrame = new QFrame;
titleFrame->setFrameShape(QFrame::StyledPanel);
titleFrame->setAutoFillBackground(true);
titleFrame->setBackgroundRole(QPalette::Base);
auto const titleLayout = new QVBoxLayout(titleFrame);
titleLabel = new QLabel;
titleLayout->addWidget(titleLabel);
subTitleLabel = new QLabel;
subTitleLabel->setWordWrap(true);
titleLayout->addWidget(subTitleLabel);
top->addWidget(titleFrame);
titleFrame->setVisible(false);
top->addWidget(stack);
explanationFrame = new QFrame;
explanationFrame->setFrameShape(QFrame::StyledPanel);
explanationFrame->setAutoFillBackground(true);
explanationFrame->setBackgroundRole(QPalette::Base);
auto const explanationLayout = new QVBoxLayout(explanationFrame);
explanationLabel = new QLabel;
explanationLabel->setWordWrap(true);
explanationLayout->addWidget(explanationLabel);
top->addWidget(explanationFrame);
explanationFrame->setVisible(false);
auto buttonWidget = new QWidget;
auto buttonLayout = new QHBoxLayout(buttonWidget);
auto const box = new QDialogButtonBox;
cancelButton = box->addButton(QDialogButtonBox::Cancel);
q->connect(cancelButton, &QPushButton::clicked, q, &Wizard::reject);
backButton = new QPushButton;
backButton->setText(i18n("Back"));
q->connect(backButton, &QPushButton::clicked, q, &Wizard::back);
box->addButton(backButton, QDialogButtonBox::ActionRole);
nextButton = new QPushButton;
KGuiItem::assign(nextButton, nextItem);
q->connect(nextButton, &QPushButton::clicked, q, &Wizard::next);
box->addButton(nextButton, QDialogButtonBox::ActionRole);
buttonLayout->addWidget(box);
top->addWidget(buttonWidget);
q->connect(q, &Wizard::rejected, q, &Wizard::canceled);
}
Wizard::Private::~Private()
{
qCDebug(KLEOPATRA_LOG) << q << __func__;
}
bool Wizard::Private::isLastPage(int id) const
{
return !pageOrder.empty() ? pageOrder.back() == id : false;
}
void Wizard::Private::updateButtonStates()
{
const bool isLast = isLastPage(currentId);
const bool canGoToNext = q->canGoToNextPage();
WizardPage *const page = q->page(currentId);
const KGuiItem customNext = page ? page->customNextButton() : KGuiItem();
if (customNext.text().isEmpty() && customNext.icon().isNull()) {
KGuiItem::assign(nextButton, isLast ? finishItem : nextItem);
} else {
KGuiItem::assign(nextButton, customNext);
}
nextButton->setEnabled(canGoToNext);
cancelButton->setEnabled(!isLast || !canGoToNext);
backButton->setEnabled(q->canGoToPreviousPage());
if (page && page->autoAdvance() && page->isComplete()) {
nextPageTimer->start();
}
}
void Wizard::Private::updateHeader()
{
WizardPage *const widget = q->page(currentId);
Q_ASSERT(!widget || stack->indexOf(widget) != -1);
if (widget) {
stack->setCurrentWidget(widget);
}
const QString title = widget ? widget->title() : QString();
const QString subTitle = widget ? widget->subTitle() : QString();
const QString explanation = widget ? widget->explanation() : QString();
titleFrame->setVisible(!title.isEmpty() || !subTitle.isEmpty() || !explanation.isEmpty());
titleLabel->setVisible(!title.isEmpty());
titleLabel->setText(title);
subTitleLabel->setText(subTitle);
subTitleLabel->setVisible(!subTitle.isEmpty());
explanationFrame->setVisible(!explanation.isEmpty());
explanationLabel->setVisible(!explanation.isEmpty());
explanationLabel->setText(explanation);
q->resize(q->sizeHint().expandedTo(q->size()));
}
Wizard::Wizard(QWidget *parent, Qt::WindowFlags f)
: QDialog(parent, f)
, d(new Private(this))
{
}
Wizard::~Wizard()
{
qCDebug(KLEOPATRA_LOG) << this << __func__;
}
void Wizard::setPage(int id, WizardPage *widget)
{
kleo_assert(id != InvalidPage);
kleo_assert(d->idToPage.find(id) == d->idToPage.end());
d->idToPage[id] = widget;
d->stack->addWidget(widget);
connect(widget, SIGNAL(completeChanged()), this, SLOT(updateButtonStates()));
connect(widget, SIGNAL(titleChanged()), this, SLOT(updateHeader()));
connect(widget, SIGNAL(subTitleChanged()), this, SLOT(updateHeader()));
connect(widget, SIGNAL(explanationChanged()), this, SLOT(updateHeader()));
connect(widget, SIGNAL(autoAdvanceChanged()), this, SLOT(updateButtonStates()));
connect(widget, SIGNAL(windowTitleChanged(QString)), this, SLOT(setWindowTitle(QString)));
}
void Wizard::setPageOrder(const std::vector<int> &pageOrder)
{
d->pageOrder = pageOrder;
d->hiddenPages.clear();
if (pageOrder.empty()) {
return;
}
setCurrentPage(pageOrder.front());
}
void Wizard::setCurrentPage(int id)
{
d->currentId = id;
if (id == InvalidPage) {
return;
}
d->updateHeader();
d->updateButtonStates();
}
void Wizard::setPageVisible(int id, bool visible)
{
if (visible) {
d->hiddenPages.erase(id);
} else {
d->hiddenPages.insert(id);
}
if (currentPage() == id && !visible) {
next();
}
}
int Wizard::currentPage() const
{
return d->currentId;
}
bool Wizard::canGoToNextPage() const
{
const WizardPage *const current = currentPageWidget();
return current ? current->isComplete() : false;
}
bool Wizard::canGoToPreviousPage() const
{
const int prev = d->previousPage();
if (prev == InvalidPage) {
return false;
}
const WizardPage *const prevPage = page(prev);
Q_ASSERT(prevPage);
return !prevPage->isCommitPage();
}
void Wizard::next()
{
WizardPage *const current = currentPageWidget();
if (current) {
- current->onNext();
+ if (!current->onNext()) {
+ return;
+ }
}
onNext(d->currentId);
auto it = Kleo::binary_find(d->pageOrder.begin(), d->pageOrder.end(), d->currentId);
Q_ASSERT(it != d->pageOrder.end());
do {
++it;
} while (d->hiddenPages.find(*it) != d->hiddenPages.end());
if (it == d->pageOrder.end()) { // "Finish"
d->currentId = InvalidPage;
close();
} else { // "next"
setCurrentPage(*it);
}
}
int Wizard::Private::previousPage() const
{
if (pageOrder.empty()) {
return InvalidPage;
}
auto it = Kleo::binary_find(pageOrder.begin(), pageOrder.end(), currentId);
if (it == pageOrder.begin() || it == pageOrder.end()) {
return InvalidPage;
}
do {
--it;
} while (it != pageOrder.begin() && hiddenPages.find(*it) != hiddenPages.end());
return *it;
}
void Wizard::back()
{
onBack(d->currentId);
const int prev = d->previousPage();
if (prev == InvalidPage) {
return;
}
setCurrentPage(prev);
}
const WizardPage *Wizard::page(int id) const
{
if (id == InvalidPage) {
return nullptr;
}
const auto it = d->idToPage.find(id);
kleo_assert(it != d->idToPage.end());
return (*it).second;
}
const WizardPage *Wizard::currentPageWidget() const
{
return page(d->currentId);
}
WizardPage *Wizard::currentPageWidget()
{
return page(d->currentId);
}
void Wizard::onNext(int currentId)
{
Q_UNUSED(currentId)
}
void Wizard::onBack(int currentId)
{
Q_UNUSED(currentId)
}
WizardPage *Wizard::page(int id)
{
if (id == InvalidPage) {
return nullptr;
}
const auto it = d->idToPage.find(id);
kleo_assert(it != d->idToPage.end());
return (*it).second;
}
#include "moc_wizard.cpp"
diff --git a/src/crypto/gui/wizardpage.cpp b/src/crypto/gui/wizardpage.cpp
index 8c8e40290..3c7f2264a 100644
--- a/src/crypto/gui/wizardpage.cpp
+++ b/src/crypto/gui/wizardpage.cpp
@@ -1,134 +1,135 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/gui/wizardpage.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "wizardpage.h"
#include <KGuiItem>
using namespace Kleo::Crypto::Gui;
class WizardPage::Private
{
friend class ::WizardPage;
WizardPage *const q;
public:
explicit Private(WizardPage *qq);
~Private();
private:
bool commitPage = false;
bool autoAdvance = false;
QString title;
QString subTitle;
QString explanation;
KGuiItem customNextButton;
};
WizardPage::Private::Private(WizardPage *qq)
: q(qq)
{
}
WizardPage::Private::~Private()
{
}
WizardPage::WizardPage(QWidget *parent, Qt::WindowFlags f)
: QWidget(parent, f)
, d(new Private(this))
{
}
bool WizardPage::isCommitPage() const
{
return d->commitPage;
}
void WizardPage::setCommitPage(bool commitPage)
{
d->commitPage = commitPage;
}
bool WizardPage::autoAdvance() const
{
return d->autoAdvance;
}
void WizardPage::setAutoAdvance(bool enabled)
{
if (d->autoAdvance == enabled) {
return;
}
d->autoAdvance = enabled;
Q_EMIT autoAdvanceChanged();
}
QString WizardPage::title() const
{
return d->title;
}
void WizardPage::setTitle(const QString &title)
{
if (d->title == title) {
return;
}
d->title = title;
Q_EMIT titleChanged();
}
QString WizardPage::subTitle() const
{
return d->subTitle;
}
void WizardPage::setSubTitle(const QString &subTitle)
{
if (d->subTitle == subTitle) {
return;
}
d->subTitle = subTitle;
Q_EMIT subTitleChanged();
}
QString WizardPage::explanation() const
{
return d->explanation;
}
void WizardPage::setExplanation(const QString &explanation)
{
if (d->explanation == explanation) {
return;
}
d->explanation = explanation;
Q_EMIT explanationChanged();
}
KGuiItem WizardPage::customNextButton() const
{
return d->customNextButton;
}
void WizardPage::setCustomNextButton(const KGuiItem &item)
{
d->customNextButton = item;
}
WizardPage::~WizardPage()
{
}
-void WizardPage::onNext()
+bool WizardPage::onNext()
{
+ return true;
}
#include "moc_wizardpage.cpp"
diff --git a/src/crypto/gui/wizardpage.h b/src/crypto/gui/wizardpage.h
index 15033134d..8860285e5 100644
--- a/src/crypto/gui/wizardpage.h
+++ b/src/crypto/gui/wizardpage.h
@@ -1,73 +1,73 @@
/* -*- mode: c++; c-basic-offset:4 -*-
crypto/gui/wizardpage.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <QWidget>
#include <memory>
class KGuiItem;
namespace Kleo
{
namespace Crypto
{
namespace Gui
{
class Wizard;
class WizardPage : public QWidget
{
friend class ::Kleo::Crypto::Gui::Wizard;
Q_OBJECT
public:
explicit WizardPage(QWidget *parent = nullptr, Qt::WindowFlags f = {});
~WizardPage() override;
virtual bool isComplete() const = 0;
bool isCommitPage() const;
void setCommitPage(bool commitPage);
bool autoAdvance() const;
void setAutoAdvance(bool enabled);
QString title() const;
void setTitle(const QString &title);
QString subTitle() const;
void setSubTitle(const QString &subTitle);
QString explanation() const;
void setExplanation(const QString &explanation);
KGuiItem customNextButton() const;
void setCustomNextButton(const KGuiItem &item);
Q_SIGNALS:
void completeChanged();
void explanationChanged();
void titleChanged();
void subTitleChanged();
void autoAdvanceChanged();
void windowTitleChanged(const QString &title);
protected:
- virtual void onNext();
+ virtual bool onNext();
private:
class Private;
const std::unique_ptr<Private> d;
};
}
}
}
diff --git a/src/utils/fileutils.cpp b/src/utils/fileutils.cpp
new file mode 100644
index 000000000..24f98b6bc
--- /dev/null
+++ b/src/utils/fileutils.cpp
@@ -0,0 +1,53 @@
+// SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
+// SPDX-FileContributor: Intevation GmbH
+// SPDX-FileCopyrightText: 2024 g10 Code GmbH
+// SPDX-FileContributor: Tobias Fella <tobias.fella@gnupg.com>
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "fileutils.h"
+
+#include <QDir>
+#include <QFileInfo>
+
+#include <KLocalizedString>
+#include <KMessageBox>
+
+#include "kleopatra_debug.h"
+#include "path-helper.h"
+
+bool Kleo::ensureOutDir(const QString &outputDirectory, QWidget *parent)
+{
+ if (outputDirectory.isEmpty()) {
+ KMessageBox::information(parent, i18n("Please select an output folder."), i18nc("@title:window", "No Output Folder"));
+ return false;
+ }
+ const QFileInfo fi(outputDirectory);
+
+ if (!fi.exists()) {
+ qCDebug(KLEOPATRA_LOG) << "Output dir does not exist. Trying to create.";
+ const QDir dir(outputDirectory);
+ if (!dir.mkdir(outputDirectory)) {
+ KMessageBox::information(
+ parent,
+ xi18nc("@info",
+ "<para>Failed to create output folder <filename>%1</filename>.</para><para>Please select a different output folder.</para>",
+ outputDirectory),
+ i18nc("@title:window", "Unusable Output Folder"));
+ return false;
+ } else {
+ return true;
+ }
+ } else if (!fi.isDir()) {
+ KMessageBox::information(parent, i18n("Please select a different output folder."), i18nc("@title:window", "Invalid Output Folder"));
+ return false;
+ } else if (!Kleo::isWritable(fi)) {
+ KMessageBox::information(
+ parent,
+ xi18nc("@info",
+ "<para>Cannot write in the output folder <filename>%1</filename>.</para><para>Please select a different output folder.</para>",
+ outputDirectory),
+ i18nc("@title:window", "Unusable Output Folder"));
+ return false;
+ }
+ return true;
+}
diff --git a/src/utils/fileutils.h b/src/utils/fileutils.h
new file mode 100644
index 000000000..58d6572f5
--- /dev/null
+++ b/src/utils/fileutils.h
@@ -0,0 +1,21 @@
+// SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
+// SPDX-FileContributor: Intevation GmbH
+// SPDX-FileCopyrightText: 2024 g10 Code GmbH
+// SPDX-FileContributor: Tobias Fella <tobias.fella@gnupg.com>
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <QString>
+
+class QWidget;
+
+namespace Kleo
+{
+
+/**
+ * Checks that \p outDir is a valid path, a directory, and writable.
+ * Creates it if necessary and shows error messages as needed.
+ * Returns true if the folder is ready to be used.
+ */
+bool ensureOutDir(const QString &outDir, QWidget *parent);
+
+}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Jan 17, 2:49 AM (6 h, 13 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
d3/91/b1c8b6fcf535529d1a3fbb8298de
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment