diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7c2d60f5b..4d203c3ec 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,636 +1,638 @@ # 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 selftest/registrycheck.cpp selftest/registrycheck.h utils/gnupg-registry.c utils/userinfo_win.cpp 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/addsubkeycommand.cpp commands/addsubkeycommand.h commands/adduseridcommand.cpp commands/adduseridcommand.h commands/authenticatepivcardapplicationcommand.cpp commands/authenticatepivcardapplicationcommand.h commands/cardcommand.cpp commands/cardcommand.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/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/refreshcertificatecommand.cpp commands/refreshcertificatecommand.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/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/cardinfotab.cpp dialogs/cardinfotab.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/debugviewdialog.cpp + dialogs/debugviewdialog.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/nameandemailwidget.cpp dialogs/nameandemailwidget.h dialogs/newopenpgpcertificatedetailsdialog.cpp dialogs/newopenpgpcertificatedetailsdialog.h dialogs/pivcardapplicationadministrationkeyinputdialog.cpp dialogs/pivcardapplicationadministrationkeyinputdialog.h dialogs/revokekeydialog.cpp dialogs/revokekeydialog.h dialogs/selftestdialog.cpp dialogs/selftestdialog.h dialogs/setinitialpindialog.cpp dialogs/setinitialpindialog.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/keyalgo.cpp newcertificatewizard/keyalgo_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/expiration.cpp utils/expiration.h utils/filedialog.cpp utils/filedialog.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/keyparameters.cpp utils/keyparameters.h utils/kuniqueservice.cpp utils/kuniqueservice.h utils/log.cpp utils/log.h utils/memory-helpers.h utils/migration.cpp utils/migration.h utils/multivalidator.cpp utils/multivalidator.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/systemtrayicon.cpp utils/systemtrayicon.h utils/tags.cpp utils/tags.h utils/types.cpp utils/types.h utils/userinfo.cpp utils/userinfo.h utils/validation.cpp utils/validation.h utils/writecertassuantransaction.cpp utils/writecertassuantransaction.h utils/wsastarter.cpp utils/wsastarter.h view/anchorcache.cpp view/anchorcache_p.h view/errorlabel.cpp view/errorlabel.h view/formtextinput.cpp view/formtextinput.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/nullpinwidget.cpp view/nullpinwidget.h view/openpgpkeycardwidget.cpp view/openpgpkeycardwidget.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/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 ) if(WIN32) configure_file (versioninfo.rc.in versioninfo.rc) set(_kleopatra_SRCS ${CMAKE_CURRENT_BINARY_DIR}/versioninfo.rc ${_kleopatra_SRCS}) configure_file (kleopatra.w32-manifest.in kleopatra.w32-manifest) set(_kleopatra_SRCS ${CMAKE_CURRENT_BINARY_DIR}/kleopatra.w32-manifest ${_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 dialogs/trustchainwidget.ui newcertificatewizard/listwidget.ui ) kconfig_add_kcfg_files(_kleopatra_SRCS kcfg/emailoperationspreferences.kcfgc kcfg/fileoperationspreferences.kcfgc kcfg/settings.kcfgc kcfg/smimevalidationpreferences.kcfgc kcfg/tagspreferences.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 ) diff --git a/src/dialogs/debugviewdialog.cpp b/src/dialogs/debugviewdialog.cpp new file mode 100644 index 000000000..c70cee324 --- /dev/null +++ b/src/dialogs/debugviewdialog.cpp @@ -0,0 +1,109 @@ +// SPDX-FileCopyrightText: 2024 g10 Code GmbH +// SPDX-FileContributor: Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "debugviewdialog.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Kleo::Dialogs; + +class DebugViewDialog::Private +{ + friend class ::Kleo::Dialogs::DebugViewDialog; + DebugViewDialog *const q; + +public: + Private(DebugViewDialog *qq) + : q{qq} + , ui{qq} + { + } + + void loadCommands() + { + QStringList commands = { + QStringLiteral("ls"), + QStringLiteral("uname"), + QStringLiteral("uname -r"), + QStringLiteral("whoami"), + QStringLiteral("ps -a"), + }; + for (const auto &command : commands) { + ui.commandsCombo->addItem(command); + } + } + void runCommand() + { + auto process = new QProcess(); + auto command = ui.commandsCombo->currentText().split(QLatin1Char(' ')); + process->start(command[0], command.mid(1)); + connect(process, &QProcess::finished, q, [process, this]() { + if (process->exitCode() != 0) { + ui.result->setText(i18nc("@info", "Error executing command: %1\n%2", process->exitCode(), QString::fromUtf8(process->readAllStandardError()))); + } else { + ui.result->setText(QString::fromUtf8(process->readAllStandardOutput())); + } + q->resize(ui.layout->sizeHint()); + }); + } + +private: + struct UI { + QVBoxLayout *layout; + QComboBox *commandsCombo; + QTextEdit *result; + QDialogButtonBox *buttons; + QPushButton *closeButton; + QPushButton *copyButton; + + explicit UI(DebugViewDialog *qq) + { + layout = new QVBoxLayout; + qq->setLayout(layout); + commandsCombo = new QComboBox; + layout->addWidget(commandsCombo); + + result = new QTextEdit; + result->setReadOnly(true); + result->setFontFamily(QStringLiteral("monospace")); + layout->addWidget(result); + + buttons = new QDialogButtonBox; + closeButton = buttons->addButton(QDialogButtonBox::Close); + copyButton = new QPushButton(QIcon::fromTheme(QStringLiteral("edit-copy")), i18nc("@action:button", "Copy Text")); + buttons->addButton(copyButton, QDialogButtonBox::ActionRole); + + layout->addWidget(buttons); + } + } ui; +}; + +DebugViewDialog::DebugViewDialog(QWidget *parent) + : QDialog(parent) + , d(new Private(this)) +{ + setWindowTitle(i18nc("@title:window", "Debug View")); + d->loadCommands(); + d->runCommand(); + connect(d->ui.commandsCombo, &QComboBox::currentIndexChanged, this, [this]() { + d->runCommand(); + }); + connect(d->ui.closeButton, &QPushButton::clicked, this, [this]() { + close(); + }); + connect(d->ui.copyButton, &QPushButton::clicked, this, [this]() { + QGuiApplication::clipboard()->setText(d->ui.result->toPlainText()); + }); +} + +#include "moc_debugviewdialog.cpp" diff --git a/src/dialogs/debugviewdialog.h b/src/dialogs/debugviewdialog.h new file mode 100644 index 000000000..cf1e04284 --- /dev/null +++ b/src/dialogs/debugviewdialog.h @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2024 g10 Code GmbH +// SPDX-FileContributor: Tobias Fella +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +namespace Kleo +{ +namespace Dialogs +{ + +class DebugViewDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DebugViewDialog(QWidget *parent); + +private: + class Private; + std::unique_ptr d; +}; + +} +} diff --git a/src/kleopatra.rc b/src/kleopatra.rc index da3210b10..66c4e1f19 100644 --- a/src/kleopatra.rc +++ b/src/kleopatra.rc @@ -1,158 +1,160 @@ - + &File &View &Certificates &Tools + + &Settings &Window &Help &More documentation Main Toolbar &Certificates diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e47ed3b9f..aa20bb9bf 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,950 +1,963 @@ /* -*- mode: c++; c-basic-offset:4 -*- mainwindow.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 #include "aboutdata.h" #include "kleopatraapplication.h" #include "mainwindow.h" #include "settings.h" #include #include "view/keycacheoverlay.h" #include "view/keylistcontroller.h" #include "view/padwidget.h" #include "view/searchbar.h" #include "view/smartcardwidget.h" #include "view/tabwidget.h" #include "view/welcomewidget.h" #include "commands/decryptverifyfilescommand.h" #include "commands/importcertificatefromfilecommand.h" #include "commands/importcrlcommand.h" #include "commands/selftestcommand.h" #include "commands/signencryptfilescommand.h" #include "utils/action_data.h" #include "utils/clipboardmenu.h" #include "utils/detail_p.h" #include "utils/filedialog.h" #include "utils/gui-helper.h" #include "utils/keyexportdraghandler.h" #include "utils/userinfo.h" #include +#include "dialogs/debugviewdialog.h" #include "dialogs/updatenotification.h" // needed for GPGME_VERSION_NUMBER #include #include "kleopatra_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #endif #include #include using namespace std::chrono_literals; using namespace Kleo; using namespace Kleo::Commands; using namespace GpgME; static KGuiItem KStandardGuiItem_quit() { static const QString app = KAboutData::applicationData().displayName(); KGuiItem item = KStandardGuiItem::quit(); item.setText(xi18nc("@action:button", "&Quit %1", app)); return item; } static KGuiItem KStandardGuiItem_close() { KGuiItem item = KStandardGuiItem::close(); item.setText(i18nc("@action:button", "Only &Close Window")); return item; } static bool isQuitting = false; namespace { static const std::vector mainViewActionNames = { QStringLiteral("view_certificate_overview"), QStringLiteral("manage_smartcard"), QStringLiteral("pad_view"), }; class CertificateView : public QWidget, public FocusFirstChild { Q_OBJECT public: CertificateView(QWidget *parent = nullptr) : QWidget{parent} , ui{this} { } SearchBar *searchBar() const { return ui.searchBar; } TabWidget *tabWidget() const { return ui.tabWidget; } void focusFirstChild(Qt::FocusReason reason) override { ui.searchBar->lineEdit()->setFocus(reason); } private: struct UI { TabWidget *tabWidget = nullptr; SearchBar *searchBar = nullptr; explicit UI(CertificateView *q) { auto vbox = new QVBoxLayout{q}; vbox->setSpacing(0); searchBar = new SearchBar{q}; vbox->addWidget(searchBar); tabWidget = new TabWidget{q}; vbox->addWidget(tabWidget); tabWidget->connectSearchBar(searchBar); } } ui; }; } class MainWindow::Private { friend class ::MainWindow; MainWindow *const q; public: explicit Private(MainWindow *qq); ~Private(); template void createAndStart() { (new T(this->currentView(), &this->controller))->start(); } template void createAndStart(QAbstractItemView *view) { (new T(view, &this->controller))->start(); } template void createAndStart(const QStringList &a) { (new T(a, this->currentView(), &this->controller))->start(); } template void createAndStart(const QStringList &a, QAbstractItemView *view) { (new T(a, view, &this->controller))->start(); } void closeAndQuit() { if (Kleo::userIsElevated()) { // For users running Kleo with elevated permissions on Windows we // always quit the application to avoid some problems. qApp->quit(); } const QString app = KAboutData::applicationData().displayName(); const int rc = KMessageBox::questionTwoActionsCancel(q, xi18n("%1 may be used by other applications as a service." "You may instead want to close this window without exiting %1.", app), i18nc("@title:window", "Really Quit?"), KStandardGuiItem_close(), KStandardGuiItem_quit(), KStandardGuiItem::cancel(), QLatin1StringView("really-quit-") + app.toLower()); if (rc == KMessageBox::Cancel) { return; } isQuitting = rc == KMessageBox::ButtonCode::SecondaryAction; if (!q->close()) { return; } // WARNING: 'this' might be deleted at this point! if (rc == KMessageBox::ButtonCode::SecondaryAction) { qApp->quit(); } } void configureToolbars() { KEditToolBar dlg(q->factory()); dlg.exec(); } void editKeybindings() { KShortcutsDialog::showDialog(q->actionCollection(), KShortcutsEditor::LetterShortcutsAllowed, q); updateSearchBarClickMessage(); } void updateSearchBarClickMessage() { const QString shortcutStr = focusToClickSearchAction->shortcut().toString(QKeySequence::NativeText); ui.searchTab->searchBar()->updateClickMessage(shortcutStr); } void updateStatusBar() { auto statusBar = std::make_unique(); auto settings = KleopatraApplication::instance()->distributionSettings(); bool showStatusbar = false; if (settings) { const QString statusline = settings->value(QStringLiteral("statusline"), {}).toString(); if (!statusline.isEmpty()) { auto customStatusLbl = new QLabel(statusline); statusBar->insertWidget(0, customStatusLbl); showStatusbar = true; } } if (DeVSCompliance::isActive()) { auto statusLbl = std::make_unique(DeVSCompliance::name()); if (!SystemInfo::isHighContrastModeActive()) { const auto color = KColorScheme(QPalette::Active, KColorScheme::View) .foreground(DeVSCompliance::isCompliant() ? KColorScheme::NormalText : KColorScheme::NegativeText) .color(); const auto background = KColorScheme(QPalette::Active, KColorScheme::View) .background(DeVSCompliance::isCompliant() ? KColorScheme::PositiveBackground : KColorScheme::NegativeBackground) .color(); statusLbl->setStyleSheet(QStringLiteral("QLabel { color: %1; background-color: %2; }").arg(color.name()).arg(background.name())); } statusBar->insertPermanentWidget(0, statusLbl.release()); showStatusbar = true; } if (showStatusbar) { q->setStatusBar(statusBar.release()); // QMainWindow takes ownership } else { q->setStatusBar(nullptr); } } void selfTest() { createAndStart(); } void configureGroups() { // open groups config dialog as independent top-level window KleopatraApplication::instance()->openOrRaiseGroupsConfigDialog(nullptr); } void showHandbook(); void gnupgLogViewer() { // Warning: Don't assume that the program needs to be in PATH. On Windows, it will also be found next to the calling process. if (!QProcess::startDetached(QStringLiteral("kwatchgnupg"), QStringList())) KMessageBox::error(q, i18n("Could not start the GnuPG Log Viewer (kwatchgnupg). " "Please check your installation."), i18n("Error Starting KWatchGnuPG")); } void forceUpdateCheck() { UpdateNotification::forceUpdateCheck(q); } void slotConfigCommitted(); void slotContextMenuRequested(QAbstractItemView *, const QPoint &p) { if (auto const menu = qobject_cast(q->factory()->container(QStringLiteral("listview_popup"), q))) { menu->exec(p); } else { qCDebug(KLEOPATRA_LOG) << "no \"listview_popup\" in kleopatra's ui.rc file"; } } void slotFocusQuickSearch() { ui.searchTab->searchBar()->lineEdit()->setFocus(); } void showView(const QString &actionName, QWidget *widget) { const auto coll = q->actionCollection(); if (coll) { for (const QString &name : mainViewActionNames) { if (auto action = coll->action(name)) { action->setChecked(name == actionName); } } } ui.stackWidget->setCurrentWidget(widget); if (auto ffci = dynamic_cast(widget)) { ffci->focusFirstChild(Qt::TabFocusReason); } } void showCertificateView() { if (KeyCache::instance()->keys().empty()) { showView(QStringLiteral("view_certificate_overview"), ui.welcomeWidget); } else { showView(QStringLiteral("view_certificate_overview"), ui.searchTab); } } void showSmartcardView() { showView(QStringLiteral("manage_smartcard"), ui.scWidget); } void showPadView() { if (!ui.padWidget) { ui.padWidget = new PadWidget; ui.stackWidget->addWidget(ui.padWidget); } showView(QStringLiteral("pad_view"), ui.padWidget); ui.stackWidget->resize(ui.padWidget->sizeHint()); } void restartDaemons() { Kleo::restartGpgAgent(); } private: void setupActions(); QAbstractItemView *currentView() const { return ui.searchTab->tabWidget()->currentView(); } void keyListingDone() { const auto curWidget = ui.stackWidget->currentWidget(); if (curWidget == ui.scWidget || curWidget == ui.padWidget) { return; } showCertificateView(); } private: Kleo::KeyListController controller; bool firstShow : 1; struct UI { CertificateView *searchTab = nullptr; PadWidget *padWidget = nullptr; SmartCardWidget *scWidget = nullptr; WelcomeWidget *welcomeWidget = nullptr; QStackedWidget *stackWidget = nullptr; explicit UI(MainWindow *q); } ui; QAction *focusToClickSearchAction = nullptr; ClipboardMenu *clipboadMenu = nullptr; }; MainWindow::Private::UI::UI(MainWindow *q) : padWidget(nullptr) { auto mainWidget = new QWidget{q}; auto mainLayout = new QVBoxLayout(mainWidget); mainLayout->setContentsMargins({}); stackWidget = new QStackedWidget{q}; searchTab = new CertificateView{q}; stackWidget->addWidget(searchTab); new KeyCacheOverlay(mainWidget, q); scWidget = new SmartCardWidget{q}; stackWidget->addWidget(scWidget); welcomeWidget = new WelcomeWidget{q}; stackWidget->addWidget(welcomeWidget); mainLayout->addWidget(stackWidget); q->setCentralWidget(mainWidget); } MainWindow::Private::Private(MainWindow *qq) : q(qq) , controller(q) , firstShow(true) , ui(q) { KDAB_SET_OBJECT_NAME(controller); AbstractKeyListModel *flatModel = AbstractKeyListModel::createFlatKeyListModel(q); AbstractKeyListModel *hierarchicalModel = AbstractKeyListModel::createHierarchicalKeyListModel(q); KDAB_SET_OBJECT_NAME(flatModel); KDAB_SET_OBJECT_NAME(hierarchicalModel); #if GPGME_VERSION_NUMBER >= 0x011800 // 1.24.0 auto keyExportDragHandler = std::make_shared(); flatModel->setDragHandler(keyExportDragHandler); hierarchicalModel->setDragHandler(keyExportDragHandler); #endif controller.setFlatModel(flatModel); controller.setHierarchicalModel(hierarchicalModel); controller.setTabWidget(ui.searchTab->tabWidget()); ui.searchTab->tabWidget()->setFlatModel(flatModel); ui.searchTab->tabWidget()->setHierarchicalModel(hierarchicalModel); #ifdef Q_OS_UNIX connect(KWaylandExtras::self(), &KWaylandExtras::windowExported, q, [this](const auto &window, const auto &token) { if (window == q->windowHandle()) { qputenv("PINENTRY_GEOM_HINT", QUrl::toPercentEncoding(token)); } }); q->exportWindow(); #endif setupActions(); ui.stackWidget->setCurrentWidget(ui.searchTab); if (auto action = q->actionCollection()->action(QStringLiteral("view_certificate_overview"))) { action->setChecked(true); } connect(&controller, SIGNAL(contextMenuRequested(QAbstractItemView *, QPoint)), q, SLOT(slotContextMenuRequested(QAbstractItemView *, QPoint))); connect(KeyCache::instance().get(), &KeyCache::keyListingDone, q, [this]() { keyListingDone(); }); q->createGUI(QStringLiteral("kleopatra.rc")); // make toolbar buttons accessible by keyboard auto toolbar = q->findChild(); if (toolbar) { auto toolbarButtons = toolbar->findChildren(); for (auto b : toolbarButtons) { b->setFocusPolicy(Qt::TabFocus); } // move toolbar and its child widgets before the central widget in the tab order; // this is necessary to make Shift+Tab work as expected forceSetTabOrder(q, toolbar); auto toolbarChildren = toolbar->findChildren(); std::for_each(std::rbegin(toolbarChildren), std::rend(toolbarChildren), [toolbar](auto w) { forceSetTabOrder(toolbar, w); }); } if (auto action = q->actionCollection()->action(QStringLiteral("help_whats_this"))) { delete action; } q->setAcceptDrops(true); // set default window size q->resize(QSize(1024, 500)); q->setAutoSaveSettings(); updateSearchBarClickMessage(); updateStatusBar(); if (KeyCache::instance()->initialized()) { keyListingDone(); } // delay setting the models to use the key cache so that the UI (including // the "Loading certificate cache..." overlay) is shown before the // blocking key cache initialization happens QMetaObject::invokeMethod( q, [flatModel, hierarchicalModel]() { flatModel->useKeyCache(true, KeyList::AllKeys); hierarchicalModel->useKeyCache(true, KeyList::AllKeys); }, Qt::QueuedConnection); } MainWindow::Private::~Private() { } MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags) : KXmlGuiWindow(parent, flags) , d(new Private(this)) { } MainWindow::~MainWindow() { } void MainWindow::Private::setupActions() { KActionCollection *const coll = q->actionCollection(); const std::vector action_data = { // see keylistcontroller.cpp for more actions // Tools menu #ifndef Q_OS_WIN { "tools_start_kwatchgnupg", i18n("GnuPG Log Viewer"), QString(), "kwatchgnupg", q, [this](bool) { gnupgLogViewer(); }, QString(), }, #endif { "tools_restart_backend", i18nc("@action:inmenu", "Restart Background Processes"), i18nc("@info:tooltip", "Restart the background processes, e.g. after making changes to the configuration."), "view-refresh", q, [this](bool) { restartDaemons(); }, {}, }, + { + "debug_view", + i18nc("@actioon:inmenu", "Debug View"), + i18nc("@info:tooltip", "Show output of common debugging commands."), + "", + q, + [this](bool) { + auto dialog = new Dialogs::DebugViewDialog(q); + dialog->open(); + }, + {}, + }, // Help menu #ifdef Q_OS_WIN { "help_check_updates", i18n("Check for updates"), QString(), "gpg4win-compact", q, [this](bool) { forceUpdateCheck(); }, QString(), }, #endif // View menu { "view_certificate_overview", i18nc("@action show certificate overview", "Certificates"), i18n("Show certificate overview"), "view-certificate", q, [this](bool) { showCertificateView(); }, QString(), }, { "pad_view", i18nc("@action show input / output area for encrypting/signing resp. decrypting/verifying text", "Notepad"), i18n("Show pad for encrypting/decrypting and signing/verifying text"), "note", q, [this](bool) { showPadView(); }, QString(), }, { "manage_smartcard", i18nc("@action show smartcard management view", "Smartcards"), i18n("Show smartcard management"), "auth-sim-locked", q, [this](bool) { showSmartcardView(); }, QString(), }, // Settings menu { "settings_self_test", i18n("Perform Self-Test"), QString(), nullptr, q, [this](bool) { selfTest(); }, QString(), }, { "configure_groups", i18n("Configure Groups..."), QString(), "group", q, [this](bool) { configureGroups(); }, QString(), }, // Toolbar { "configure_groups_toolbar", i18nc("@action:intoolbar", "Groups"), QString(), "group", q, [this](bool) { configureGroups(); }, QString(), }}; make_actions_from_data(action_data, coll); if (!Settings().groupsEnabled()) { if (auto action = coll->action(QStringLiteral("configure_groups"))) { delete action; } } for (const QString &name : mainViewActionNames) { if (auto action = coll->action(name)) { action->setCheckable(true); } } KStandardAction::close(q, SLOT(close()), coll); KStandardAction::quit(q, SLOT(closeAndQuit()), coll); KStandardAction::configureToolbars(q, SLOT(configureToolbars()), coll); KStandardAction::keyBindings(q, SLOT(editKeybindings()), coll); KStandardAction::preferences(qApp, SLOT(openOrRaiseConfigDialog()), coll); focusToClickSearchAction = new QAction(i18n("Set Focus to Quick Search"), q); coll->addAction(QStringLiteral("focus_to_quickseach"), focusToClickSearchAction); coll->setDefaultShortcut(focusToClickSearchAction, QKeySequence(Qt::ALT | Qt::Key_Q)); connect(focusToClickSearchAction, SIGNAL(triggered(bool)), q, SLOT(slotFocusQuickSearch())); clipboadMenu = new ClipboardMenu(q); clipboadMenu->setMainWindow(q); clipboadMenu->clipboardMenu()->setIcon(QIcon::fromTheme(QStringLiteral("edit-paste"))); clipboadMenu->clipboardMenu()->setPopupMode(QToolButton::InstantPopup); coll->addAction(QStringLiteral("clipboard_menu"), clipboadMenu->clipboardMenu()); /* Add additional help actions for documentation */ const auto compendium = new DocAction(QIcon::fromTheme(QStringLiteral("gpg4win-compact")), i18n("Gpg4win Compendium"), i18nc("The Gpg4win compendium is only available" "at this point (24.7.2017) in german and english." "Please check with Gpg4win before translating this filename.", "gpg4win-compendium-en.pdf"), QStringLiteral("../share/gpg4win"), coll); coll->addAction(QStringLiteral("help_doc_compendium"), compendium); /* Documentation centered around the german approved VS-NfD mode for official * RESTRICTED communication. This is only available in some distributions with * the focus on official communications. */ const auto quickguide = new DocAction(QIcon::fromTheme(QStringLiteral("help-contextual")), i18n("&Quickguide"), i18nc("Only available in German and English. Leave to English for other languages.", "encrypt_and_sign_gnupgvsd_en.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_quickguide"), quickguide); const auto symguide = new DocAction(QIcon::fromTheme(QStringLiteral("help-contextual")), i18n("&Password-based encryption"), i18nc("Only available in German and English. Leave to English for other languages.", "symmetric_encryption_gnupgvsd_en.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_symenc"), symguide); const auto groups = new DocAction(QIcon::fromTheme(QStringLiteral("help-contextual")), i18n("&Group configuration"), i18nc("Only available in German and English. Leave to English for other languages.", "groupfeature_gnupgvsd_en.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_groups"), groups); #ifdef Q_OS_WIN const auto gpgol = new DocAction(QIcon::fromTheme(QStringLiteral("help-contextual")), i18n("&Mail encryption in Outlook"), i18nc("Only available in German and English. Leave to English for other languages. Only shown on Windows.", "gpgol_outlook_addin_en.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_gpgol"), gpgol); #endif /* The submenu with advanced topics */ const auto certmngmnt = new DocAction(QIcon::fromTheme(QStringLiteral("help-contextual")), i18n("&Certification Management"), i18nc("Only available in German and English. Leave to English for other languages.", "certification_management_gnupgvsd_en.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_cert_management"), certmngmnt); const auto smartcard = new DocAction(QIcon::fromTheme(QStringLiteral("help-contextual")), i18n("&Smartcard setup"), i18nc("Only available in German and English. Leave to English for other languages.", "smartcard_setup_gnupgvsd_en.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_smartcard"), smartcard); const auto man_gnupg = new DocAction(QIcon::fromTheme(QStringLiteral("help-contextual")), i18n("GnuPG Command&line"), QStringLiteral("gnupg_manual_en.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_gnupg"), man_gnupg); /* The secops */ const auto approvalmanual = new DocAction(QIcon::fromTheme(QStringLiteral("dvipdf")), i18n("Manual for VS-NfD approval (German)"), i18nc("Only available in German. Keep German file name for all languages", "Handbuch-Zulassung-gnupgvsd-v3.2.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_approval_manual"), approvalmanual); const auto vsa10573 = new DocAction(QIcon::fromTheme(QStringLiteral("dvipdf")), i18n("SecOps VSA-10573"), i18nc("Only available in German and English. Leave to English for other languages.", "BSI-VSA-10573-ENG_secops-20220207.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_vsa10573"), vsa10573); const auto vsa10584 = new DocAction(QIcon::fromTheme(QStringLiteral("dvipdf")), i18n("SecOps VSA-10584"), i18nc("Only available in German and English. Leave to English for other languages.", "BSI-VSA-10584-ENG_secops-20220207.pdf"), QStringLiteral("../share/doc/gnupg-vsd"), coll); coll->addAction(QStringLiteral("help_doc_vsa10584"), vsa10584); q->setStandardToolBarMenuEnabled(true); controller.createActions(coll); ui.searchTab->tabWidget()->createActions(coll); } void MainWindow::Private::slotConfigCommitted() { controller.updateConfig(); updateStatusBar(); } void MainWindow::closeEvent(QCloseEvent *e) { // KMainWindow::closeEvent() insists on quitting the application, // so do not let it touch the event... qCDebug(KLEOPATRA_LOG); if (d->controller.hasRunningCommands()) { if (d->controller.shutdownWarningRequired()) { const int ret = KMessageBox::warningContinueCancel(this, i18n("There are still some background operations ongoing. " "These will be terminated when closing the window. " "Proceed?"), i18n("Ongoing Background Tasks")); if (ret != KMessageBox::Continue) { e->ignore(); return; } } d->controller.cancelCommands(); if (d->controller.hasRunningCommands()) { // wait for them to be finished: setEnabled(false); QEventLoop ev; QTimer::singleShot(100ms, &ev, &QEventLoop::quit); connect(&d->controller, &KeyListController::commandsExecuting, &ev, &QEventLoop::quit); ev.exec(); if (d->controller.hasRunningCommands()) qCWarning(KLEOPATRA_LOG) << "controller still has commands running, this may crash now..."; setEnabled(true); } } unexportWindow(); if (isQuitting || qApp->isSavingSession() || Kleo::userIsElevated()) { d->ui.searchTab->tabWidget()->saveViews(); KConfigGroup grp(KConfigGroup(KSharedConfig::openConfig(), autoSaveGroup())); saveMainWindowSettings(grp); e->accept(); } else { e->ignore(); hide(); } } void MainWindow::showEvent(QShowEvent *e) { KXmlGuiWindow::showEvent(e); if (d->firstShow) { d->ui.searchTab->tabWidget()->loadViews(KSharedConfig::openStateConfig(), QStringLiteral("KeyList")); d->firstShow = false; } if (!savedGeometry.isEmpty()) { restoreGeometry(savedGeometry); } } void MainWindow::hideEvent(QHideEvent *e) { savedGeometry = saveGeometry(); KXmlGuiWindow::hideEvent(e); } void MainWindow::importCertificatesFromFile(const QStringList &files) { if (!files.empty()) { d->createAndStart(files); } } static QStringList extract_local_files(const QMimeData *data) { const QList urls = data->urls(); // begin workaround KDE/Qt misinterpretation of text/uri-list QList::const_iterator end = urls.end(); if (urls.size() > 1 && !urls.back().isValid()) { --end; } // end workaround QStringList result; std::transform(urls.begin(), end, std::back_inserter(result), std::mem_fn(&QUrl::toLocalFile)); result.erase(std::remove_if(result.begin(), result.end(), std::mem_fn(&QString::isEmpty)), result.end()); return result; } static bool can_decode_local_files(const QMimeData *data) { if (!data) { return false; } return !extract_local_files(data).empty(); } void MainWindow::dragEnterEvent(QDragEnterEvent *e) { qCDebug(KLEOPATRA_LOG); if (can_decode_local_files(e->mimeData())) { e->acceptProposedAction(); } } void MainWindow::dropEvent(QDropEvent *e) { qCDebug(KLEOPATRA_LOG); if (!can_decode_local_files(e->mimeData())) { return; } e->setDropAction(Qt::CopyAction); const QStringList files = extract_local_files(e->mimeData()); KleopatraApplication::instance()->handleFiles(files); e->accept(); } void MainWindow::readProperties(const KConfigGroup &cg) { qCDebug(KLEOPATRA_LOG); KXmlGuiWindow::readProperties(cg); setHidden(cg.readEntry("hidden", false)); } void MainWindow::saveProperties(KConfigGroup &cg) { qCDebug(KLEOPATRA_LOG); KXmlGuiWindow::saveProperties(cg); cg.writeEntry("hidden", isHidden()); } void MainWindow::exportWindow() { #ifdef Q_OS_UNIX (void)winId(); // Ensures that windowHandle() returns the window KWaylandExtras::self()->exportWindow(windowHandle()); #endif } void MainWindow::unexportWindow() { #ifdef Q_OS_UNIX KWaylandExtras::self()->unexportWindow(windowHandle()); #endif } KeyListController *MainWindow::keyListController() { return &d->controller; } #include "mainwindow.moc" #include "moc_mainwindow.cpp"