Page MenuHome GnuPG

No OneTemporary

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

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

Event Timeline