File indexing completed on 2024-06-16 04:56:18

0001 /*  view/welcomewidget.cpp
0002 
0003     This file is part of Kleopatra, the KDE keymanager
0004     SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
0005     SPDX-FileContributor: Intevation GmbH
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "welcomewidget.h"
0013 
0014 #include "htmllabel.h"
0015 
0016 #include <KAboutData>
0017 
0018 #include <QAction>
0019 #include <QHBoxLayout>
0020 #include <QKeyEvent>
0021 #include <QToolButton>
0022 #include <QVBoxLayout>
0023 
0024 #include "commands/importcertificatefromfilecommand.h"
0025 #include "commands/newopenpgpcertificatecommand.h"
0026 
0027 #include <KConfigGroup>
0028 #include <KLocalizedString>
0029 #include <KSharedConfig>
0030 
0031 static const QString templ = QStringLiteral(
0032     "<h3>%1</h3>" // Welcome
0033     "<p>%2<p/><p>%3</p>" // Intro + Explanation
0034     "<ul><li>%4</li><li>%5</li></ul>" //
0035     "<p>%6</p>" // More info
0036     "");
0037 
0038 using namespace Kleo;
0039 
0040 namespace
0041 {
0042 /**
0043  * A tool button that can be activated with the Enter and Return keys additionally to the Space key.
0044  */
0045 class ToolButton : public QToolButton
0046 {
0047     Q_OBJECT
0048 public:
0049     using QToolButton::QToolButton;
0050 
0051 protected:
0052     void keyPressEvent(QKeyEvent *e) override
0053     {
0054         switch (e->key()) {
0055         case Qt::Key_Enter:
0056         case Qt::Key_Return: {
0057             // forward as key press of Key_Select to QToolButton
0058             QKeyEvent alternateEvent{e->type(),
0059                                      Qt::Key_Select,
0060                                      e->modifiers(),
0061                                      e->nativeScanCode(),
0062                                      e->nativeVirtualKey(),
0063                                      e->nativeModifiers(),
0064                                      e->text(),
0065                                      e->isAutoRepeat(),
0066                                      static_cast<ushort>(e->count())};
0067             QToolButton::keyPressEvent(&alternateEvent);
0068             if (!alternateEvent.isAccepted()) {
0069                 e->ignore();
0070             }
0071             break;
0072         }
0073         default:
0074             QToolButton::keyPressEvent(e);
0075         }
0076     }
0077 
0078     void keyReleaseEvent(QKeyEvent *e) override
0079     {
0080         switch (e->key()) {
0081         case Qt::Key_Enter:
0082         case Qt::Key_Return: {
0083             // forward as key release of Key_Select to QToolButton
0084             QKeyEvent alternateEvent{e->type(),
0085                                      Qt::Key_Select,
0086                                      e->modifiers(),
0087                                      e->nativeScanCode(),
0088                                      e->nativeVirtualKey(),
0089                                      e->nativeModifiers(),
0090                                      e->text(),
0091                                      e->isAutoRepeat(),
0092                                      static_cast<ushort>(e->count())};
0093             QToolButton::keyReleaseEvent(&alternateEvent);
0094             if (!alternateEvent.isAccepted()) {
0095                 e->ignore();
0096             }
0097             break;
0098         }
0099         default:
0100             QToolButton::keyReleaseEvent(e);
0101         }
0102     }
0103 };
0104 }
0105 
0106 class WelcomeWidget::Private
0107 {
0108 public:
0109     Private(WelcomeWidget *qq)
0110         : q(qq)
0111     {
0112         auto vLay = new QVBoxLayout(q);
0113         auto hLay = new QHBoxLayout;
0114 
0115         const QString welcome = i18nc("%1 is version", "Welcome to Kleopatra %1", KAboutData::applicationData().version());
0116         const QString introduction = i18n("Kleopatra is a front-end for the crypto software <a href=\"https://gnupg.org\">GnuPG</a>.");
0117 
0118         const QString keyExplanation = i18n("For most actions you need either a public key (certificate) or your own private key.");
0119 
0120         const QString privateKeyExplanation = i18n("The private key is needed to decrypt or sign.");
0121         const QString publicKeyExplanation = i18n("The public key can be used by others to verify your identity or encrypt to you.");
0122 
0123         const QString wikiUrl = i18nc("More info about public key cryptography, please link to your local version of Wikipedia",
0124                                       "https://en.wikipedia.org/wiki/Public-key_cryptography");
0125         const QString learnMore = i18nc("%1 is link a wiki article", "You can learn more about this on <a href=\"%1\">Wikipedia</a>.", wikiUrl);
0126 
0127         const auto labelText = templ.arg(welcome).arg(introduction).arg(keyExplanation).arg(privateKeyExplanation).arg(publicKeyExplanation).arg(learnMore);
0128         mLabel = new HtmlLabel{labelText, q};
0129         mLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
0130         mLabel->setOpenExternalLinks(true);
0131 
0132         auto genKeyAction = new QAction(q);
0133         genKeyAction->setText(i18n("New Key Pair..."));
0134         genKeyAction->setIcon(QIcon::fromTheme(QStringLiteral("view-certificate-add")));
0135 
0136         auto importAction = new QAction(q);
0137         importAction->setText(i18n("Import..."));
0138         importAction->setIcon(QIcon::fromTheme(QStringLiteral("view-certificate-import")));
0139 
0140         connect(importAction, &QAction::triggered, q, [this]() {
0141             import();
0142         });
0143         connect(genKeyAction, &QAction::triggered, q, [this]() {
0144             generate();
0145         });
0146 
0147         mGenerateBtn = new ToolButton{q};
0148         mGenerateBtn->setDefaultAction(genKeyAction);
0149         mGenerateBtn->setIconSize(QSize(64, 64));
0150         mGenerateBtn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
0151         const auto generateBtnDescription = kxi18nc("@info",
0152                                                     "Create a new OpenPGP key pair.<nl/>"
0153                                                     "To create an S/MIME certificate request use "
0154                                                     "<interface>New S/MIME Certification Request</interface> "
0155                                                     "from the <interface>File</interface> menu instead.");
0156         mGenerateBtn->setToolTip(generateBtnDescription.toString());
0157         mGenerateBtn->setAccessibleDescription(generateBtnDescription.toString(Kuit::PlainText));
0158 
0159         KConfigGroup restrictions(KSharedConfig::openConfig(), QStringLiteral("KDE Action Restrictions"));
0160         mGenerateBtn->setEnabled(restrictions.readEntry("action/file_new_certificate", true));
0161 
0162         mImportBtn = new ToolButton{q};
0163         mImportBtn->setDefaultAction(importAction);
0164         mImportBtn->setIconSize(QSize(64, 64));
0165         mImportBtn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
0166         const auto importBtnDescription = kxi18nc("@info",
0167                                                   "Import certificate from a file.<nl/>"
0168                                                   "To import from a public keyserver use <interface>Lookup on Server</interface> instead.");
0169         mImportBtn->setToolTip(importBtnDescription.toString());
0170         mImportBtn->setAccessibleDescription(importBtnDescription.toString(Kuit::PlainText));
0171         mImportBtn->setEnabled(restrictions.readEntry("action/file_import_certificate", true));
0172 
0173         auto btnLayout = new QHBoxLayout;
0174         btnLayout->addStretch(-1);
0175         btnLayout->addWidget(mGenerateBtn);
0176         btnLayout->addWidget(mImportBtn);
0177         btnLayout->addStretch(-1);
0178 
0179         vLay->addStretch(-1);
0180         vLay->addLayout(hLay);
0181         vLay->addLayout(btnLayout);
0182         vLay->addStretch(-1);
0183 
0184         hLay->addStretch(-1);
0185         hLay->addWidget(mLabel);
0186         hLay->addStretch(-1);
0187     }
0188 
0189     void import()
0190     {
0191         mImportBtn->setEnabled(false);
0192         auto cmd = new Kleo::ImportCertificateFromFileCommand();
0193         cmd->setParentWidget(q);
0194 
0195         QObject::connect(cmd, &Kleo::ImportCertificateFromFileCommand::finished, q, [this]() {
0196             mImportBtn->setEnabled(true);
0197         });
0198         cmd->start();
0199     }
0200 
0201     void generate()
0202     {
0203         mGenerateBtn->setEnabled(false);
0204         auto cmd = new NewOpenPGPCertificateCommand;
0205         cmd->setParentWidget(q);
0206 
0207         QObject::connect(cmd, &NewOpenPGPCertificateCommand::finished, q, [this]() {
0208             mGenerateBtn->setEnabled(true);
0209         });
0210         cmd->start();
0211     }
0212 
0213     WelcomeWidget *const q;
0214     HtmlLabel *mLabel = nullptr;
0215     ToolButton *mGenerateBtn = nullptr;
0216     ToolButton *mImportBtn = nullptr;
0217 };
0218 
0219 WelcomeWidget::WelcomeWidget(QWidget *parent)
0220     : QWidget(parent)
0221     , d(new Private(this))
0222 {
0223 }
0224 
0225 void WelcomeWidget::focusFirstChild(Qt::FocusReason reason)
0226 {
0227     d->mLabel->setFocus(reason);
0228 }
0229 
0230 #include "welcomewidget.moc"
0231 
0232 #include "moc_welcomewidget.cpp"