diff --git a/src/commands/changeownertrustcommand.cpp b/src/commands/changeownertrustcommand.cpp
index b84b39085..68dbb02da 100644
--- a/src/commands/changeownertrustcommand.cpp
+++ b/src/commands/changeownertrustcommand.cpp
@@ -1,238 +1,306 @@
 /* -*- mode: c++; c-basic-offset:4 -*-
     commands/changeownertrustcommand.cpp
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
+    SPDX-FileCopyrightText: 2022 g10 Code GmbH
+    SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #include <config-kleopatra.h>
 
 #include "changeownertrustcommand.h"
 
 #include "command_p.h"
 
-#include <dialogs/ownertrustdialog.h>
-
+#include <Libkleo/Compliance>
 #include <Libkleo/Formatting>
+#include <Libkleo/KeyCache>
+
+#include <KLocalizedString>
 
 #include <QGpgME/Protocol>
 #include <QGpgME/ChangeOwnerTrustJob>
 
 #include <gpgme++/key.h>
 
-#include <KLocalizedString>
 #include "kleopatra_debug.h"
 
 
 using namespace Kleo;
 using namespace Kleo::Commands;
-using namespace Kleo::Dialogs;
 using namespace GpgME;
 using namespace QGpgME;
 
 class ChangeOwnerTrustCommand::Private : public Command::Private
 {
     friend class ::Kleo::Commands::ChangeOwnerTrustCommand;
     ChangeOwnerTrustCommand *q_func() const
     {
         return static_cast<ChangeOwnerTrustCommand *>(q);
     }
 public:
     explicit Private(ChangeOwnerTrustCommand *qq, KeyListController *c);
     ~Private() override;
 
     void init();
 
 private:
-    void slotDialogAccepted();
-    void slotDialogRejected();
     void slotResult(const Error &err);
 
 private:
-    void ensureDialogCreated();
+    void startJob(Key::OwnerTrust trust);
     void createJob();
     void showErrorDialog(const Error &error);
     void showSuccessDialog();
 
 private:
-    QPointer<OwnerTrustDialog> dialog;
     QPointer<ChangeOwnerTrustJob> job;
+    Key::OwnerTrust trustToSet = Key::OwnerTrust::Unknown;
 };
 
 ChangeOwnerTrustCommand::Private *ChangeOwnerTrustCommand::d_func()
 {
     return static_cast<Private *>(d.get());
 }
 const ChangeOwnerTrustCommand::Private *ChangeOwnerTrustCommand::d_func() const
 {
     return static_cast<const Private *>(d.get());
 }
 
 #define d d_func()
 #define q q_func()
 
 ChangeOwnerTrustCommand::Private::Private(ChangeOwnerTrustCommand *qq, KeyListController *c)
     : Command::Private(qq, c),
-      dialog(),
       job()
 {
 
 }
 
 ChangeOwnerTrustCommand::Private::~Private()
 {
     qCDebug(KLEOPATRA_LOG);
 }
 
 ChangeOwnerTrustCommand::ChangeOwnerTrustCommand(KeyListController *c)
     : Command(new Private(this, c))
 {
     d->init();
 }
 
 ChangeOwnerTrustCommand::ChangeOwnerTrustCommand(QAbstractItemView *v, KeyListController *c)
     : Command(v, new Private(this, c))
 {
     d->init();
 }
 
 ChangeOwnerTrustCommand::ChangeOwnerTrustCommand(const Key &key)
     : Command(key, new Private(this, nullptr))
 {
     d->init();
 }
 
 void ChangeOwnerTrustCommand::Private::init()
 {
 
 }
 
 ChangeOwnerTrustCommand::~ChangeOwnerTrustCommand()
 {
     qCDebug(KLEOPATRA_LOG);
 }
 
 void ChangeOwnerTrustCommand::doStart()
 {
-
     if (d->keys().size() != 1) {
         d->finished();
         return;
     }
 
     const Key key = d->key();
-    if (key.protocol() != GpgME::OpenPGP || (key.hasSecret() && key.ownerTrust() == Key::Ultimate)) {
+    if (key.protocol() != GpgME::OpenPGP) {
         d->finished();
         return;
     }
 
-    d->ensureDialogCreated();
-    Q_ASSERT(d->dialog);
-
-    d->dialog->setHasSecretKey(key.hasSecret());
-    d->dialog->setFormattedCertificateName(Formatting::formatForComboBox(key));
-    d->dialog->setOwnerTrust(key.ownerTrust());
-
-    d->dialog->show();
+    const auto keyInfo = Formatting::formatForComboBox(key);
+
+    if (key.hasSecret()) {
+        const auto answer = KMessageBox::questionYesNoCancel(d->parentWidgetOrView(),
+                                                             xi18nc("@info", "Is '%1' your own certificate?", keyInfo),
+                                                             i18nc("@title:window", "Mark Own Certificate"),
+                                                             KGuiItem(i18nc("@action:button", "Yes, it's mine")),
+                                                             KGuiItem(i18nc("@action:button", "No, it's not mine")),
+                                                             KStandardGuiItem::cancel());
+        switch (answer) {
+        case KMessageBox::Yes: {
+            if (key.ownerTrust() < Key::Ultimate) {
+                d->startJob(Key::OwnerTrust::Ultimate);
+            }
+            return;
+        }
+        case KMessageBox::No: {
+            if (key.ownerTrust() == Key::Ultimate) {
+                d->startJob(Key::OwnerTrust::Unknown);
+                return;
+            }
+            // else ask next question
+            break;
+        }
+        case KMessageBox::Cancel: {
+            d->canceled();
+            return;
+        }
+        default:; // cannot happen
+        }
+    }
 
+    if (key.ownerTrust() < Key::OwnerTrust::Full) {
+        const auto text = (DeVSCompliance::isCompliant() && Formatting::isKeyDeVs(key))
+            ? xi18nc("@info %1: a certificate, %2: name of a compliance mode",
+                     "<para>Do you want to grant '%1' the power to mark certificates as %2 for you?</para>"
+                     "<para><emphasis>This means that the owner of this certificate properly check fingerprints "
+                     "and confirms the identities of others.</emphasis></para>",
+                     keyInfo,
+                     DeVSCompliance::name())
+            : xi18nc("@info %1: a certificate",
+                     "<para>Do you want to grant '%1' the power to mark certificates as valid for you?</para>"
+                     "<para><emphasis>This means that the owner of this certificate properly check fingerprints "
+                     "and confirms the identities of others.</emphasis></para>",
+                     keyInfo);
+        const auto answer = KMessageBox::questionYesNo(d->parentWidgetOrView(),
+                                                       text,
+                                                       i18nc("@title:window", "Grant Certification Power"),
+                                                       KGuiItem(i18nc("@action:button", "Grant Power")),
+                                                       KStandardGuiItem::cancel());
+        if (answer == KMessageBox::Yes) {
+            d->startJob(Key::OwnerTrust::Full);
+        } else {
+            d->canceled();
+        }
+    } else {
+        const auto text = (DeVSCompliance::isCompliant() && Formatting::isKeyDeVs(key))
+            ? xi18nc("@info %1: a certificate, %2: name of a compliance mode",
+                     "<para>The certificate '%1' is empowered to mark other certificates as %2 for you.</para>"
+                     "<para>Do you want to revoke this power?</para>",
+                     keyInfo,
+                     DeVSCompliance::name())
+            : xi18nc("@info %1: a certificate",
+                     "<para>The certificate '%1' is empowered to mark other certificates as valid for you.</para>"
+                     "<para>Do you want to revoke this power?</para>",
+                     keyInfo);
+        const auto answer = KMessageBox::questionYesNo(d->parentWidgetOrView(),
+                                                       text,
+                                                       i18nc("@title:window", "Revoke Certification Power"),
+                                                       KGuiItem(i18nc("@action:button", "Revoke Power")),
+                                                       KStandardGuiItem::cancel());
+        if (answer == KMessageBox::Yes) {
+            d->startJob(Key::OwnerTrust::Unknown);
+        } else {
+            d->canceled();
+        }
+    }
 }
 
-void ChangeOwnerTrustCommand::Private::slotDialogAccepted()
+void ChangeOwnerTrustCommand::Private::startJob(Key::OwnerTrust trust)
 {
-    Q_ASSERT(dialog);
-
-    const Key::OwnerTrust trust = dialog->ownerTrust();
-
-    qCDebug(KLEOPATRA_LOG) << "trust " << trust;
+    trustToSet = trust;
 
     createJob();
     Q_ASSERT(job);
 
     if (const Error err = job->start(key(), trust)) {
         showErrorDialog(err);
         finished();
     }
 }
 
-void ChangeOwnerTrustCommand::Private::slotDialogRejected()
-{
-    Q_EMIT q->canceled();
-    finished();
-}
-
 void ChangeOwnerTrustCommand::Private::slotResult(const Error &err)
 {
     if (err.isCanceled())
         ;
     else if (err) {
         showErrorDialog(err);
     } else {
         showSuccessDialog();
     }
     finished();
 }
 
 void ChangeOwnerTrustCommand::doCancel()
 {
     qCDebug(KLEOPATRA_LOG);
     if (d->job) {
         d->job->slotCancel();
     }
 }
 
-void ChangeOwnerTrustCommand::Private::ensureDialogCreated()
-{
-    if (dialog) {
-        return;
-    }
-
-    dialog = new OwnerTrustDialog;
-    applyWindowID(dialog);
-    dialog->setAttribute(Qt::WA_DeleteOnClose);
-
-    connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); });
-    connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); });
-}
-
 void ChangeOwnerTrustCommand::Private::createJob()
 {
     Q_ASSERT(!job);
 
-    const auto backend = (key().protocol() == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime();
-    if (!backend) {
-        return;
-    }
-
-    ChangeOwnerTrustJob *const j = backend->changeOwnerTrustJob();
+    ChangeOwnerTrustJob *const j = QGpgME::openpgp()->changeOwnerTrustJob();
     if (!j) {
         return;
     }
 
     connect(j, &Job::progress,
             q, &Command::progress);
     connect(j, &ChangeOwnerTrustJob::result, q, [this](const GpgME::Error &result) { slotResult(result); });
 
     job = j;
 }
 
 void ChangeOwnerTrustCommand::Private::showErrorDialog(const Error &err)
 {
-    error(i18n("<p>An error occurred while trying to change "
-               "the certification trust for <b>%1</b>:</p><p>%2</p>",
-               Formatting::formatForComboBox(key()),
-               QString::fromLocal8Bit(err.asString())),
-          i18n("Certification Trust Change Error"));
+    const auto keyInfo = Formatting::formatForComboBox(key());
+    switch (trustToSet) {
+    case Key::OwnerTrust::Ultimate:
+        error(xi18nc("@info",
+                     "<para>An error occurred while marking certificate '%1' as your certificate.</para>"
+                     "<para><message>%2</message></para>",
+                     keyInfo,
+                     QString::fromUtf8(err.asString())));
+        break;
+    case Key::OwnerTrust::Full:
+        error(xi18nc("@info",
+                     "<para>An error occurred while granting certification power to '%1'.</para>"
+                     "<para><message>%2</message></para>",
+                     keyInfo,
+                     QString::fromUtf8(err.asString())));
+        break;
+    default:
+        error(xi18nc("@info",
+                     "<para>An error occurred while revoking the certification power of '%1'.</para>"
+                     "<para><message>%2</message></para>",
+                     keyInfo,
+                     QString::fromUtf8(err.asString())));
+    }
 }
 
 void ChangeOwnerTrustCommand::Private::showSuccessDialog()
 {
-    information(i18n("Certification trust changed successfully."),
-                i18n("Certification Trust Change Succeeded"));
+    auto updatedKey = key();
+    updatedKey.update();
+    KeyCache::mutableInstance()->insert(updatedKey);
+
+    const auto keyInfo = Formatting::formatForComboBox(updatedKey);
+    switch (updatedKey.ownerTrust()) {
+    case Key::OwnerTrust::Ultimate:
+        success(i18nc("@info", "Certificate '%1' was marked as your certificate.", keyInfo));
+        break;
+    case Key::OwnerTrust::Full:
+        success(i18nc("@info", "Certification power was granted to '%1'.", keyInfo));
+        break;
+    default:
+        success(i18nc("@info", "The certification power of '%1' was revoked.", keyInfo));
+    }
 }
 
 #undef d
 #undef q
 
 #include "moc_changeownertrustcommand.cpp"
diff --git a/src/view/keylistcontroller.cpp b/src/view/keylistcontroller.cpp
index 743680b8e..99a4f4d7f 100644
--- a/src/view/keylistcontroller.cpp
+++ b/src/view/keylistcontroller.cpp
@@ -1,868 +1,869 @@
 /* -*- mode: c++; c-basic-offset:4 -*-
     controllers/keylistcontroller.cpp
 
     This file is part of Kleopatra, the KDE keymanager
     SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
     SPDX-FileCopyrightText: 2022 Felix Tiede
 
     SPDX-License-Identifier: GPL-2.0-or-later
 */
 
 #include <config-kleopatra.h>
 
 #include "keylistcontroller.h"
 #include "tabwidget.h"
 
 #include <smartcard/readerstatus.h>
 
 #include <utils/action_data.h>
 
 #include <settings.h>
 #include "tooltippreferences.h"
 #include "kleopatra_debug.h"
 #include "commands/exportcertificatecommand.h"
 #include "commands/exportopenpgpcertstoservercommand.h"
 #ifdef MAILAKONADI_ENABLED
 #include "commands/exportopenpgpcerttoprovidercommand.h"
 #endif // MAILAKONADI_ENABLED
 #ifdef QGPGME_SUPPORTS_SECRET_KEY_EXPORT
 # include "commands/exportsecretkeycommand.h"
 #else
 # include "commands/exportsecretkeycommand_old.h"
 #endif
 #include "commands/importcertificatefromfilecommand.h"
 #include "commands/changepassphrasecommand.h"
 #include "commands/lookupcertificatescommand.h"
 #include "commands/reloadkeyscommand.h"
 #include "commands/refreshx509certscommand.h"
 #include "commands/refreshopenpgpcertscommand.h"
 #include "commands/detailscommand.h"
 #include "commands/deletecertificatescommand.h"
 #include "commands/decryptverifyfilescommand.h"
 #include "commands/signencryptfilescommand.h"
 #include "commands/signencryptfoldercommand.h"
 #include "commands/clearcrlcachecommand.h"
 #include "commands/dumpcrlcachecommand.h"
 #include "commands/dumpcertificatecommand.h"
 #include "commands/importcrlcommand.h"
 #include "commands/changeexpirycommand.h"
 #include "commands/changeownertrustcommand.h"
 #include "commands/changeroottrustcommand.h"
 #include "commands/certifycertificatecommand.h"
 #include "commands/revokecertificationcommand.h"
 #include "commands/adduseridcommand.h"
 #include "commands/newcertificatesigningrequestcommand.h"
 #include "commands/newopenpgpcertificatecommand.h"
 #include "commands/checksumverifyfilescommand.h"
 #include "commands/checksumcreatefilescommand.h"
 #include "commands/exportpaperkeycommand.h"
 #include "commands/revokekeycommand.h"
 
 #include <Libkleo/Algorithm>
 #include <Libkleo/KeyCache>
 #include <Libkleo/KeyListModel>
 #include <Libkleo/Formatting>
 
 #include <gpgme++/key.h>
 
 #include <KActionCollection>
 #include <KLocalizedString>
 
 #include <QAbstractItemView>
 #include <QPointer>
 #include <QItemSelectionModel>
 #include <QAction>
 
 #include <algorithm>
 #include <iterator>
 
 // needed for GPGME_VERSION_NUMBER
 #include <gpgme.h>
 
 using namespace Kleo;
 using namespace Kleo::Commands;
 using namespace Kleo::SmartCard;
 using namespace GpgME;
 #ifndef QGPGME_SUPPORTS_SECRET_KEY_EXPORT
 using Kleo::Commands::Compat::ExportSecretKeyCommand;
 #endif
 
 class KeyListController::Private
 {
     friend class ::Kleo::KeyListController;
     KeyListController *const q;
 public:
     explicit Private(KeyListController *qq);
     ~Private();
 
     void connectView(QAbstractItemView *view);
     void connectCommand(Command *cmd);
 
     void connectTabWidget();
     void disconnectTabWidget();
 
     void addCommand(Command *cmd)
     {
         connectCommand(cmd);
         commands.insert(std::lower_bound(commands.begin(), commands.end(), cmd), cmd);
     }
     void addView(QAbstractItemView *view)
     {
         connectView(view);
         views.insert(std::lower_bound(views.begin(), views.end(), view), view);
     }
     void removeView(QAbstractItemView *view)
     {
         view->disconnect(q);
         view->selectionModel()->disconnect(q);
         views.erase(std::remove(views.begin(), views.end(), view), views.end());
     }
 
 public:
     void slotDestroyed(QObject *o)
     {
         qCDebug(KLEOPATRA_LOG) << (void *)o;
         views.erase(std::remove(views.begin(), views.end(), o), views.end());
         commands.erase(std::remove(commands.begin(), commands.end(), o), commands.end());
     }
     void slotDoubleClicked(const QModelIndex &idx);
     void slotActivated(const QModelIndex &idx);
     void slotSelectionChanged(const QItemSelection &old, const QItemSelection &new_);
     void slotContextMenu(const QPoint &pos);
     void slotCommandFinished();
     void slotAddKey(const Key &key);
     void slotAboutToRemoveKey(const Key &key);
     void slotProgress(const QString &what, int current, int total)
     {
         Q_EMIT q->progress(current, total);
         if (!what.isEmpty()) {
             Q_EMIT q->message(what);
         }
     }
     void slotActionTriggered(QAction *action);
     void slotCurrentViewChanged(QAbstractItemView *view)
     {
         if (view && !std::binary_search(views.cbegin(), views.cend(), view)) {
             qCDebug(KLEOPATRA_LOG) << "you need to register view" << view << "before trying to set it as the current view!";
             addView(view);
         }
         currentView = view;
         q->enableDisableActions(view ? view->selectionModel() : nullptr);
     }
 
 private:
     int toolTipOptions() const;
 
 private:
     static Command::Restrictions calculateRestrictionsMask(const QItemSelectionModel *sm);
 
 private:
     struct action_item {
         QPointer<QAction> action;
         Command::Restrictions restrictions;
         Command *(*createCommand)(QAbstractItemView *, KeyListController *);
     };
     std::vector<action_item> actions;
     std::vector<QAbstractItemView *> views;
     std::vector<Command *> commands;
     QPointer<QWidget> parentWidget;
     QPointer<TabWidget> tabWidget;
     QPointer<QAbstractItemView> currentView;
     QPointer<AbstractKeyListModel> flatModel, hierarchicalModel;
     std::vector<QMetaObject::Connection> m_connections;
 };
 
 KeyListController::Private::Private(KeyListController *qq)
     : q(qq),
       actions(),
       views(),
       commands(),
       parentWidget(),
       tabWidget(),
       flatModel(),
       hierarchicalModel()
 {
     connect(KeyCache::instance().get(), &KeyCache::added, q, [this](const GpgME::Key &key) { slotAddKey(key); });
     connect(KeyCache::instance().get(), &KeyCache::aboutToRemove, q, [this](const GpgME::Key &key) { slotAboutToRemoveKey(key); });
 }
 
 KeyListController::Private::~Private() {}
 
 KeyListController::KeyListController(QObject *p)
     : QObject(p), d(new Private(this))
 {
 
 }
 
 KeyListController::~KeyListController() {}
 
 void KeyListController::Private::slotAddKey(const Key &key)
 {
     // ### make model act on keycache directly...
     if (flatModel) {
         flatModel->addKey(key);
     }
     if (hierarchicalModel) {
         hierarchicalModel->addKey(key);
     }
 }
 
 void KeyListController::Private::slotAboutToRemoveKey(const Key &key)
 {
     // ### make model act on keycache directly...
     if (flatModel) {
         flatModel->removeKey(key);
     }
     if (hierarchicalModel) {
         hierarchicalModel->removeKey(key);
     }
 }
 
 void KeyListController::addView(QAbstractItemView *view)
 {
     if (!view || std::binary_search(d->views.cbegin(), d->views.cend(), view)) {
         return;
     }
     d->addView(view);
 }
 
 void KeyListController::removeView(QAbstractItemView *view)
 {
     if (!view || !std::binary_search(d->views.cbegin(), d->views.cend(), view)) {
         return;
     }
     d->removeView(view);
 }
 
 void KeyListController::setCurrentView(QAbstractItemView *view)
 {
     d->slotCurrentViewChanged(view);
 }
 
 std::vector<QAbstractItemView *> KeyListController::views() const
 {
     return d->views;
 }
 
 void KeyListController::setFlatModel(AbstractKeyListModel *model)
 {
     if (model == d->flatModel) {
         return;
     }
 
     d->flatModel = model;
 
     if (model) {
         model->clear();
         if (KeyCache::instance()->initialized()) {
             model->addKeys(KeyCache::instance()->keys());
         }
         model->setToolTipOptions(d->toolTipOptions());
     }
 }
 
 void KeyListController::setHierarchicalModel(AbstractKeyListModel *model)
 {
     if (model == d->hierarchicalModel) {
         return;
     }
 
     d->hierarchicalModel = model;
 
     if (model) {
         model->clear();
         if (KeyCache::instance()->initialized()) {
             model->addKeys(KeyCache::instance()->keys());
         }
         model->setToolTipOptions(d->toolTipOptions());
     }
 }
 
 void KeyListController::setTabWidget(TabWidget *tabWidget)
 {
     if (tabWidget == d->tabWidget) {
         return;
     }
 
     d->disconnectTabWidget();
 
     d->tabWidget = tabWidget;
 
     d->connectTabWidget();
 
     d->slotCurrentViewChanged(tabWidget ? tabWidget->currentView() : nullptr);
 }
 
 void KeyListController::setParentWidget(QWidget *parent)
 {
     d->parentWidget = parent;
 }
 
 QWidget *KeyListController::parentWidget() const
 {
     return d->parentWidget;
 }
 
 void KeyListController::Private::connectTabWidget()
 {
     if (!tabWidget) {
         return;
     }
     const auto views = tabWidget->views();
     std::for_each(views.cbegin(), views.cend(),
                   [this](QAbstractItemView *view) { addView(view); });
 
     m_connections.reserve(3);
     m_connections.push_back(connect(tabWidget, &TabWidget::viewAdded, q, &KeyListController::addView));
     m_connections.push_back(connect(tabWidget, &TabWidget::viewAboutToBeRemoved, q, &KeyListController::removeView));
     m_connections.push_back(connect(tabWidget, &TabWidget::currentViewChanged, q, [this](QAbstractItemView *view) { slotCurrentViewChanged(view); }));
 }
 
 void KeyListController::Private::disconnectTabWidget()
 {
     if (!tabWidget) {
         return;
     }
     for (const auto &connection : m_connections) {
         disconnect(connection);
     }
     m_connections.clear();
 
     const auto views = tabWidget->views();
     std::for_each(views.cbegin(), views.cend(),
                   [this](QAbstractItemView *view) { removeView(view); });
 }
 
 AbstractKeyListModel *KeyListController::flatModel() const
 {
     return d->flatModel;
 }
 
 AbstractKeyListModel *KeyListController::hierarchicalModel() const
 {
     return d->hierarchicalModel;
 }
 
 QAbstractItemView *KeyListController::currentView() const
 {
     return d->currentView;
 }
 
 TabWidget *KeyListController::tabWidget() const
 {
     return d->tabWidget;
 }
 
 void KeyListController::createActions(KActionCollection *coll)
 {
     const std::vector<action_data> common_and_openpgp_action_data = {
         // File menu
         {
             "file_new_certificate", i18n("New OpenPGP Key Pair..."), i18n("Create a new OpenPGP certificate"),
             "view-certificate-add", nullptr, nullptr, QStringLiteral("Ctrl+N")
         },
         {
             "file_export_certificates", i18n("Export..."), i18n("Export the selected certificate (public key) to a file"),
             "view-certificate-export", nullptr, nullptr, QStringLiteral("Ctrl+E")
         },
         {
             "file_export_certificates_to_server", i18n("Publish on Server..."), i18n("Publish the selected certificate (public key) on a public keyserver"),
             "view-certificate-export-server", nullptr, nullptr, QStringLiteral("Ctrl+Shift+E")
         },
 #ifdef MAILAKONADI_ENABLED
         {
             "file_export_certificate_to_provider", i18n("Publish at Mail Provider..."), i18n("Publish the selected certificate (public key) at mail provider's Web Key Directory if offered"),
             "view-certificate-export", nullptr, nullptr, QString()
         },
 #endif // MAILAKONADI_ENABLED
         {
             "file_export_secret_keys", i18n("Backup Secret Keys..."), QString(),
             "view-certificate-export-secret", nullptr, nullptr, QString()
         },
         {
             "file_export_paper_key", i18n("Print Secret Key..."), QString(),
             "document-print", nullptr, nullptr, QString()
         },
         {
             "file_lookup_certificates", i18n("Lookup on Server..."), i18n("Search for certificates online using a public keyserver"),
             "edit-find", nullptr, nullptr, QStringLiteral("Shift+Ctrl+I")
         },
         {
             "file_import_certificates", i18n("Import..."), i18n("Import a certificate from a file"),
             "view-certificate-import", nullptr, nullptr, QStringLiteral("Ctrl+I")
         },
         {
             "file_decrypt_verify_files", i18n("Decrypt/Verify..."), i18n("Decrypt and/or verify files"),
             "document-edit-decrypt-verify", nullptr, nullptr, QString()
         },
         {
             "file_sign_encrypt_files", i18n("Sign/Encrypt..."), i18n("Encrypt and/or sign files"),
             "document-edit-sign-encrypt", nullptr, nullptr, QString()
         },
         {
             "file_sign_encrypt_folder", i18n("Sign/Encrypt Folder..."), i18n("Encrypt and/or sign folders"),
             nullptr/*"folder-edit-sign-encrypt"*/, nullptr, nullptr, QString()
         },
         {
             "file_checksum_create_files", i18n("Create Checksum Files..."), QString(),
             nullptr/*"document-checksum-create"*/, nullptr, nullptr, QString()
         },
         {
             "file_checksum_verify_files", i18n("Verify Checksum Files..."), QString(),
             nullptr/*"document-checksum-verify"*/, nullptr, nullptr, QString()
         },
         // View menu
         {
             "view_redisplay", i18n("Redisplay"), QString(),
             "view-refresh", nullptr, nullptr, QStringLiteral("F5")
         },
         {
             "view_stop_operations", i18n("Stop Operation"), QString(),
             "process-stop", this, [this](bool) { cancelCommands(); }, QStringLiteral("Escape"), RegularQAction, Disabled
         },
         {
             "view_certificate_details", i18n("Details"), QString(),
             "dialog-information", nullptr, nullptr, QString()
         },
         // Certificate menu
 #ifdef QGPGME_SUPPORTS_KEY_REVOCATION
         {
             "certificates_revoke", i18n("Revoke Certificate..."), i18n("Revoke the selected OpenPGP certificate"),
             "view-certificate-revoke", nullptr, nullptr, {}
         },
 #endif
         {
             "certificates_delete", i18n("Delete"), i18n("Delete selected certificates"),
             "edit-delete", nullptr, nullptr, QStringLiteral("Delete")
         },
         {
             "certificates_certify_certificate", i18n("Certify..."), i18n("Certify the validity of the selected certificate"),
             "view-certificate-sign", nullptr, nullptr, QString()
         },
         {
             "certificates_revoke_certification", i18n("Revoke Certification..."), i18n("Revoke the certification of the selected certificate"),
             "view-certificate-revoke", nullptr, nullptr, QString()
         },
         {
             "certificates_change_expiry", i18n("Change End of Validity Period..."), QString(),
             nullptr, nullptr, nullptr, QString()
         },
         {
-            "certificates_change_owner_trust", i18n("Change Certification Trust..."), QString(),
+            "certificates_change_owner_trust", i18nc("@action:inmenu", "Change Certification Power..."),
+            i18nc("@info:tooltip", "Grant or revoke the certification power of the selected certificate"),
             nullptr, nullptr, nullptr, QString()
         },
         {
             "certificates_change_passphrase", i18n("Change Passphrase..."), QString(),
             nullptr, nullptr, nullptr, QString()
         },
         {
             "certificates_add_userid", i18n("Add User ID..."), QString(),
             nullptr, nullptr, nullptr, QString()
         },
         // Tools menu
         {
             "tools_refresh_openpgp_certificates", i18n("Refresh OpenPGP Certificates"), QString(),
             "view-refresh", nullptr, nullptr, QString()
         },
         // Window menu
         // (come from TabWidget)
         // Help menu
         // (come from MainWindow)
     };
 
     static const action_data cms_create_csr_action_data = {
         "file_new_certificate_signing_request", i18n("New S/MIME Certification Request..."), i18n("Create a new S/MIME certificate signing request (CSR)"),
         "view-certificate-add", nullptr, nullptr, {},
     };
 
     static const std::vector<action_data> cms_action_data = {
         // Certificate menu
         {
             "certificates_trust_root", i18n("Trust Root Certificate"), QString(),
             nullptr, nullptr, nullptr, QString()
         },
         {
             "certificates_distrust_root", i18n("Distrust Root Certificate"), QString(),
             nullptr, nullptr, nullptr, QString()
         },
         {
             "certificates_dump_certificate", i18n("Technical Details"), QString(),
             nullptr, nullptr, nullptr, QString()
         },
         // Tools menu
         {
             "tools_refresh_x509_certificates", i18n("Refresh S/MIME Certificates"), QString(),
             "view-refresh", nullptr, nullptr, QString()
         },
         {
             "crl_clear_crl_cache", i18n("Clear CRL Cache"), QString(),
             nullptr, nullptr, nullptr, QString()
         },
         {
             "crl_dump_crl_cache", i18n("Dump CRL Cache"), QString(),
             nullptr, nullptr, nullptr, QString()
         },
         {
             "crl_import_crl", i18n("Import CRL From File..."), QString(),
             nullptr, nullptr, nullptr, QString()
         },
     };
 
     std::vector<action_data> action_data = common_and_openpgp_action_data;
 
     if (const Kleo::Settings settings{}; settings.cmsEnabled()) {
         if (settings.cmsCertificateCreationAllowed()) {
             action_data.push_back(cms_create_csr_action_data);
         }
         action_data.reserve(action_data.size() + cms_action_data.size());
         std::copy(std::begin(cms_action_data), std::end(cms_action_data),
                   std::back_inserter(action_data));
     }
 
     make_actions_from_data(action_data, coll);
 
     if (QAction *action = coll->action(QStringLiteral("view_stop_operations"))) {
         connect(this, &KeyListController::commandsExecuting, action, &QAction::setEnabled);
     }
 
     // ### somehow make this better...
     registerActionForCommand<NewOpenPGPCertificateCommand>(coll->action(QStringLiteral("file_new_certificate")));
     registerActionForCommand<NewCertificateSigningRequestCommand>(coll->action(QStringLiteral("file_new_certificate_signing_request")));
     //---
     registerActionForCommand<LookupCertificatesCommand>(coll->action(QStringLiteral("file_lookup_certificates")));
     registerActionForCommand<ImportCertificateFromFileCommand>(coll->action(QStringLiteral("file_import_certificates")));
     //---
     registerActionForCommand<ExportCertificateCommand>(coll->action(QStringLiteral("file_export_certificates")));
     registerActionForCommand<ExportSecretKeyCommand>(coll->action(QStringLiteral("file_export_secret_keys")));
     registerActionForCommand<ExportPaperKeyCommand>(coll->action(QStringLiteral("file_export_paper_key")));
     registerActionForCommand<ExportOpenPGPCertsToServerCommand>(coll->action(QStringLiteral("file_export_certificates_to_server")));
 #ifdef MAILAKONADI_ENABLED
     registerActionForCommand<ExportOpenPGPCertToProviderCommand>(coll->action(QStringLiteral("file_export_certificate_to_provider")));
 #endif // MAILAKONADI_ENABLED
     //---
     registerActionForCommand<DecryptVerifyFilesCommand>(coll->action(QStringLiteral("file_decrypt_verify_files")));
     registerActionForCommand<SignEncryptFilesCommand>(coll->action(QStringLiteral("file_sign_encrypt_files")));
     registerActionForCommand<SignEncryptFolderCommand>(coll->action(QStringLiteral("file_sign_encrypt_folder")));
     //---
     registerActionForCommand<ChecksumCreateFilesCommand>(coll->action(QStringLiteral("file_checksum_create_files")));
     registerActionForCommand<ChecksumVerifyFilesCommand>(coll->action(QStringLiteral("file_checksum_verify_files")));
 
     registerActionForCommand<ReloadKeysCommand>(coll->action(QStringLiteral("view_redisplay")));
     //coll->action( "view_stop_operations" ) <-- already dealt with in make_actions_from_data()
     registerActionForCommand<DetailsCommand>(coll->action(QStringLiteral("view_certificate_details")));
 
     registerActionForCommand<ChangeOwnerTrustCommand>(coll->action(QStringLiteral("certificates_change_owner_trust")));
     registerActionForCommand<TrustRootCommand>(coll->action(QStringLiteral("certificates_trust_root")));
     registerActionForCommand<DistrustRootCommand>(coll->action(QStringLiteral("certificates_distrust_root")));
     //---
     registerActionForCommand<CertifyCertificateCommand>(coll->action(QStringLiteral("certificates_certify_certificate")));
     if (RevokeCertificationCommand::isSupported()) {
         registerActionForCommand<RevokeCertificationCommand>(coll->action(QStringLiteral("certificates_revoke_certification")));
     }
     //---
     registerActionForCommand<ChangeExpiryCommand>(coll->action(QStringLiteral("certificates_change_expiry")));
     registerActionForCommand<ChangePassphraseCommand>(coll->action(QStringLiteral("certificates_change_passphrase")));
     registerActionForCommand<AddUserIDCommand>(coll->action(QStringLiteral("certificates_add_userid")));
     //---
 #ifdef QGPGME_SUPPORTS_KEY_REVOCATION
     registerActionForCommand<RevokeKeyCommand>(coll->action(QStringLiteral("certificates_revoke")));
 #endif
     registerActionForCommand<DeleteCertificatesCommand>(coll->action(QStringLiteral("certificates_delete")));
     //---
     registerActionForCommand<DumpCertificateCommand>(coll->action(QStringLiteral("certificates_dump_certificate")));
 
     registerActionForCommand<RefreshX509CertsCommand>(coll->action(QStringLiteral("tools_refresh_x509_certificates")));
     registerActionForCommand<RefreshOpenPGPCertsCommand>(coll->action(QStringLiteral("tools_refresh_openpgp_certificates")));
     //---
     registerActionForCommand<ImportCrlCommand>(coll->action(QStringLiteral("crl_import_crl")));
     //---
     registerActionForCommand<ClearCrlCacheCommand>(coll->action(QStringLiteral("crl_clear_crl_cache")));
     registerActionForCommand<DumpCrlCacheCommand>(coll->action(QStringLiteral("crl_dump_crl_cache")));
 
     enableDisableActions(nullptr);
 }
 
 void KeyListController::registerAction(QAction *action, Command::Restrictions restrictions, Command * (*create)(QAbstractItemView *, KeyListController *))
 {
     if (!action) {
         return;
     }
     Q_ASSERT(!action->isCheckable());   // can be added later, for now, disallow
 
     const Private::action_item ai = {
         action, restrictions, create
     };
     connect(action, &QAction::triggered, this, [this, action]() { d->slotActionTriggered(action); });
     d->actions.push_back(ai);
 }
 
 void KeyListController::registerCommand(Command *cmd)
 {
     if (!cmd || std::binary_search(d->commands.cbegin(), d->commands.cend(), cmd)) {
         return;
     }
     d->addCommand(cmd);
     qCDebug(KLEOPATRA_LOG) << (void *)cmd;
     if (d->commands.size() == 1) {
         Q_EMIT commandsExecuting(true);
     }
 }
 
 bool KeyListController::hasRunningCommands() const
 {
     return !d->commands.empty();
 }
 
 bool KeyListController::shutdownWarningRequired() const
 {
     return std::any_of(d->commands.cbegin(), d->commands.cend(), std::mem_fn(&Command::warnWhenRunningAtShutdown));
 }
 
 // slot
 void KeyListController::cancelCommands()
 {
     std::for_each(d->commands.begin(), d->commands.end(), std::mem_fn(&Command::cancel));
 }
 
 void KeyListController::Private::connectView(QAbstractItemView *view)
 {
 
     connect(view, &QObject::destroyed, q, [this](QObject *obj) { slotDestroyed(obj); });
     connect(view, &QAbstractItemView::doubleClicked, q, [this](const QModelIndex &index) { slotDoubleClicked(index); });
     connect(view, &QAbstractItemView::activated, q, [this](const QModelIndex &index) { slotActivated(index); });
     connect(view->selectionModel(), &QItemSelectionModel::selectionChanged,
             q, [this](const QItemSelection &oldSel, const QItemSelection &newSel) {
         slotSelectionChanged(oldSel, newSel);
     });
 
     view->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(view, &QWidget::customContextMenuRequested, q, [this](const QPoint &pos) { slotContextMenu(pos); });
 }
 
 void KeyListController::Private::connectCommand(Command *cmd)
 {
     if (!cmd) {
         return;
     }
     connect(cmd, &QObject::destroyed, q, [this](QObject *obj) { slotDestroyed(obj); });
     connect(cmd, &Command::finished, q, [this] { slotCommandFinished(); });
     //connect( cmd, SIGNAL(canceled()), q, SLOT(slotCommandCanceled()) );
     connect(cmd, &Command::info, q, &KeyListController::message);
     connect(cmd, &Command::progress, q, [this](const QString &message, int current, int total) { slotProgress(message, current, total); });
 }
 
 void KeyListController::Private::slotDoubleClicked(const QModelIndex &idx)
 {
     QAbstractItemView *const view = qobject_cast<QAbstractItemView *>(q->sender());
     if (!view || !std::binary_search(views.cbegin(), views.cend(), view)) {
         return;
     }
 
     if (const auto *const keyListModel = dynamic_cast<KeyListModelInterface *>(view->model())) {
         DetailsCommand *const c = new DetailsCommand{keyListModel->key(idx)};
         c->setParentWidget(parentWidget ? parentWidget : view);
         c->start();
     }
 }
 
 void KeyListController::Private::slotActivated(const QModelIndex &idx)
 {
     Q_UNUSED(idx)
     QAbstractItemView *const view = qobject_cast<QAbstractItemView *>(q->sender());
     if (!view || !std::binary_search(views.cbegin(), views.cend(), view)) {
         return;
     }
 
 }
 
 void KeyListController::Private::slotSelectionChanged(const QItemSelection &old, const QItemSelection &new_)
 {
     Q_UNUSED(old)
     Q_UNUSED(new_)
 
     const QItemSelectionModel *const sm = qobject_cast<QItemSelectionModel *>(q->sender());
     if (!sm) {
         return;
     }
     q->enableDisableActions(sm);
 }
 
 void KeyListController::Private::slotContextMenu(const QPoint &p)
 {
     QAbstractItemView *const view = qobject_cast<QAbstractItemView *>(q->sender());
     if (view && std::binary_search(views.cbegin(), views.cend(), view)) {
         Q_EMIT q->contextMenuRequested(view, view->viewport()->mapToGlobal(p));
     } else {
         qCDebug(KLEOPATRA_LOG) << "sender is not a QAbstractItemView*!";
     }
 }
 
 void KeyListController::Private::slotCommandFinished()
 {
     Command *const cmd = qobject_cast<Command *>(q->sender());
     if (!cmd || !std::binary_search(commands.cbegin(), commands.cend(), cmd)) {
         return;
     }
     qCDebug(KLEOPATRA_LOG) << (void *)cmd;
     if (commands.size() == 1) {
         Q_EMIT q->commandsExecuting(false);
     }
 }
 
 void KeyListController::enableDisableActions(const QItemSelectionModel *sm) const
 {
     const Command::Restrictions restrictionsMask = d->calculateRestrictionsMask(sm);
     for (const Private::action_item &ai : std::as_const(d->actions))
         if (ai.action) {
             ai.action->setEnabled(ai.restrictions == (ai.restrictions & restrictionsMask));
         }
 }
 
 static bool all_secret_are_not_owner_trust_ultimate(const std::vector<Key> &keys)
 {
     for (const Key &key : keys)
         if (key.hasSecret() && key.ownerTrust() == Key::Ultimate) {
             return false;
         }
     return true;
 }
 
 Command::Restrictions find_root_restrictions(const std::vector<Key> &keys)
 {
     bool trusted = false, untrusted = false;
     for (const Key &key : keys)
         if (key.isRoot())
             if (key.userID(0).validity() == UserID::Ultimate) {
                 trusted = true;
             } else {
                 untrusted = true;
             }
         else {
             return Command::NoRestriction;
         }
     if (trusted)
         if (untrusted) {
             return Command::NoRestriction;
         } else {
             return Command::MustBeTrustedRoot;
         }
     else if (untrusted) {
         return Command::MustBeUntrustedRoot;
     } else {
         return Command::NoRestriction;
     }
 }
 
 Command::Restrictions KeyListController::Private::calculateRestrictionsMask(const QItemSelectionModel *sm)
 {
     if (!sm) {
         return Command::NoRestriction;
     }
 
     const KeyListModelInterface *const m = dynamic_cast<const KeyListModelInterface *>(sm->model());
     if (!m) {
         return Command::NoRestriction;
     }
 
     const std::vector<Key> keys = m->keys(sm->selectedRows());
     if (keys.empty()) {
         return Command::NoRestriction;
     }
 
     Command::Restrictions result = Command::NeedSelection;
 
     if (keys.size() == 1) {
         result |= Command::OnlyOneKey;
     }
 
 #if GPGME_VERSION_NUMBER >= 0x011102 // 1.17.2
     // we need to check the primary subkey because Key::hasSecret() is also true if just the secret key stub of an offline key is available
     const auto primaryKeyCanBeUsedForSecretKeyOperations = [](const auto &k) { return k.subkey(0).isSecret(); };
 #else
     // older versions of GpgME did not always set the secret flag for card keys
     const auto primaryKeyCanBeUsedForSecretKeyOperations = [](const auto &k) { return k.subkey(0).isSecret() || k.subkey(0).isCardKey(); };
 #endif
     if (std::all_of(keys.cbegin(), keys.cend(), primaryKeyCanBeUsedForSecretKeyOperations)) {
         result |= Command::NeedSecretKey;
     }
 
     if (std::all_of(std::begin(keys), std::end(keys), [](const auto &k) { return k.subkey(0).isSecret() && !k.subkey(0).isCardKey(); })) {
         result |= Command::NeedSecretKeyData;
     }
 
     if (std::all_of(keys.cbegin(), keys.cend(), [](const Key &key) { return key.protocol() == OpenPGP; })) {
         result |= Command::MustBeOpenPGP;
     } else if (std::all_of(keys.cbegin(), keys.cend(), [](const Key &key) { return key.protocol() == CMS; })) {
         result |= Command::MustBeCMS;
     }
 
     if (Kleo::all_of(keys, [](const auto &key) {
         return !key.isBad();
     })) {
         result |= Command::MustBeValid;
     }
 
     if (all_secret_are_not_owner_trust_ultimate(keys)) {
         result |= Command::MayOnlyBeSecretKeyIfOwnerTrustIsNotYetUltimate;
     }
 
     result |= find_root_restrictions(keys);
 
     if (const ReaderStatus *rs = ReaderStatus::instance()) {
         if (!rs->firstCardWithNullPin().empty()) {
             result |= Command::AnyCardHasNullPin;
         }
         if (rs->anyCardCanLearnKeys()) {
             result |= Command::AnyCardCanLearnKeys;
         }
     }
 
     return result;
 }
 
 void KeyListController::Private::slotActionTriggered(QAction *sender)
 {
     const auto it = std::find_if(actions.cbegin(), actions.cend(),
                                  [sender](const action_item &item) { return item.action == sender; });
     if (it != actions.end())
         if (Command *const c = it->createCommand(this->currentView, q)) {
             if (parentWidget) {
                 c->setParentWidget(parentWidget);
             }
             c->start();
         } else
             qCDebug(KLEOPATRA_LOG) << "createCommand() == NULL for action(?) \""
                                     << qPrintable(sender->objectName()) << "\"";
     else {
         qCDebug(KLEOPATRA_LOG) << "I don't know anything about action(?) \"%s\"", qPrintable(sender->objectName());
     }
 }
 
 int KeyListController::Private::toolTipOptions() const
 {
     using namespace Kleo::Formatting;
     static const int validityFlags = Validity | Issuer | ExpiryDates | CertificateUsage;
     static const int ownerFlags = Subject | UserIDs | OwnerTrust;
     static const int detailsFlags = StorageLocation | CertificateType | SerialNumber | Fingerprint;
 
     const TooltipPreferences prefs;
 
     int flags = KeyID;
     flags |= prefs.showValidity() ? validityFlags : 0;
     flags |= prefs.showOwnerInformation() ? ownerFlags : 0;
     flags |= prefs.showCertificateDetails() ? detailsFlags : 0;
     return flags;
 }
 
 void KeyListController::updateConfig()
 {
     const int opts = d->toolTipOptions();
     if (d->flatModel) {
         d->flatModel->setToolTipOptions(opts);
     }
     if (d->hierarchicalModel) {
         d->hierarchicalModel->setToolTipOptions(opts);
     }
 }
 
 #include "moc_keylistcontroller.cpp"