File indexing completed on 2024-06-02 05:12:08

0001 /*
0002     SPDX-FileCopyrightText: 2008 Thomas Baumgart <ipwizard@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kgpgkeyselectiondlg.h"
0008 
0009 // ----------------------------------------------------------------------------
0010 // QT Includes
0011 #include <QPushButton>
0012 #include <QDialogButtonBox>
0013 
0014 // ----------------------------------------------------------------------------
0015 // KDE Includes
0016 
0017 // ----------------------------------------------------------------------------
0018 // Project Includes
0019 
0020 #include "config-kmymoney.h"
0021 #include <kgpgfile.h>
0022 #include <ui_kgpgkeyselectiondlg.h>
0023 
0024 class KGpgKeySelectionDlgPrivate
0025 {
0026     Q_DISABLE_COPY(KGpgKeySelectionDlgPrivate)
0027 
0028 public:
0029     KGpgKeySelectionDlgPrivate()
0030         : ui(new Ui::KGpgKeySelectionDlg)
0031         , needCheckList(true)
0032         , listOk(false)
0033         , checkCount(0)
0034     {
0035     }
0036 
0037     ~KGpgKeySelectionDlgPrivate()
0038     {
0039         delete ui;
0040     }
0041 
0042     Ui::KGpgKeySelectionDlg*  ui;
0043     bool                      needCheckList;
0044     bool                      listOk;
0045     int                       checkCount;
0046 };
0047 
0048 
0049 KGpgKeySelectionDlg::KGpgKeySelectionDlg(QWidget *parent) :
0050     QDialog(parent),
0051     d_ptr(new KGpgKeySelectionDlgPrivate)
0052 {
0053     Q_D(KGpgKeySelectionDlg);
0054     d->ui->setupUi(this);
0055     connect(d->ui->m_secretKey, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &KGpgKeySelectionDlg::slotIdChanged);
0056     connect(d->ui->m_listWidget, &KEditListWidget::changed, this, &KGpgKeySelectionDlg::slotIdChanged);
0057     connect(d->ui->m_listWidget, &KEditListWidget::added, this, &KGpgKeySelectionDlg::slotKeyListChanged);
0058     connect(d->ui->m_listWidget, &KEditListWidget::removed, this, &KGpgKeySelectionDlg::slotKeyListChanged);
0059 }
0060 
0061 KGpgKeySelectionDlg::~KGpgKeySelectionDlg()
0062 {
0063     Q_D(KGpgKeySelectionDlg);
0064     delete d;
0065 }
0066 
0067 void KGpgKeySelectionDlg::setSecretKeys(const QStringList& keyList, const QString& defaultKey)
0068 {
0069     static constexpr char recoveryKeyId[] = "59B0F826D2B08440";
0070 
0071     Q_D(KGpgKeySelectionDlg);
0072     d->ui->m_secretKey->addItem(i18n("No encryption"));
0073 
0074     for (const auto& key : keyList) {
0075         QStringList fields = key.split(':', Qt::SkipEmptyParts);
0076         if (fields[0] != recoveryKeyId) {
0077             // replace parenthesis in name field with brackets
0078             auto name = fields[1];
0079             name.replace('(', "[");
0080             name.replace(')', "]");
0081             name = QString("%1 (0x%2)").arg(name, fields[0]);
0082             d->ui->m_secretKey->addItem(name);
0083             if (name.contains(defaultKey)) {
0084                 d->ui->m_secretKey->setCurrentText(name);
0085             }
0086         }
0087     }
0088 }
0089 
0090 QString KGpgKeySelectionDlg::secretKey() const
0091 {
0092     Q_D(const KGpgKeySelectionDlg);
0093     const bool enabled = (d->ui->m_secretKey->currentIndex() != 0);
0094     QString key;
0095     if (enabled) {
0096         key = d->ui->m_secretKey->currentText();
0097     }
0098     return key;
0099 }
0100 
0101 void KGpgKeySelectionDlg::setAdditionalKeys(const QStringList& list)
0102 {
0103     Q_D(KGpgKeySelectionDlg);
0104     d->ui->m_listWidget->clear();
0105     d->ui->m_listWidget->insertStringList(list);
0106     slotKeyListChanged();
0107 }
0108 
0109 QStringList KGpgKeySelectionDlg::additionalKeys() const
0110 {
0111     Q_D(const KGpgKeySelectionDlg);
0112     return d->ui->m_listWidget->items();
0113 }
0114 
0115 #if 0
0116 void KGpgKeySelectionDlg::slotShowHelp()
0117 {
0118     QString anchor = m_helpAnchor[m_criteriaTab->currentPage()];
0119     if (anchor.isEmpty())
0120         anchor = QString("details.search");
0121 
0122     KHelpClient::invokeHelp(anchor);
0123 }
0124 #endif
0125 
0126 void KGpgKeySelectionDlg::slotKeyListChanged()
0127 {
0128     Q_D(KGpgKeySelectionDlg);
0129     d->needCheckList = true;
0130     slotIdChanged();
0131 }
0132 
0133 void KGpgKeySelectionDlg::slotIdChanged()
0134 {
0135 #ifdef ENABLE_GPG
0136     Q_D(KGpgKeySelectionDlg);
0137     // this looks a bit awkward. Here's why: KGPGFile::keyAvailable() starts
0138     // an external task and processes UI events while it waits for the external
0139     // process to finish. Thus, the first time we get here, the external process
0140     // is started and the user may press a second key which calls this routine
0141     // again.
0142     //
0143     // The second invocation is counted, but the check is not started until the
0144     // first one finishes. Once the external process finishes, we check if we
0145     // were called in the meantime and restart the check.
0146     if (++d->checkCount == 1) {
0147         const bool enabled = (d->ui->m_secretKey->currentIndex() != 0);
0148         d->ui->m_listWidget->setEnabled(enabled);
0149         d->ui->m_keyLed->setState(enabled ? KLed::On : KLed::Off);
0150         while (enabled) {
0151             // first we check the current edit field if filled
0152             bool keysOk = true;
0153             if (!d->ui->m_listWidget->currentText().isEmpty()) {
0154                 keysOk = KGPGFile::keyAvailable(d->ui->m_listWidget->currentText());
0155             }
0156 
0157             // if it is available, then scan the current list if we need to
0158             if (keysOk) {
0159                 if (d->needCheckList) {
0160                     QStringList keys = d->ui->m_listWidget->items();
0161                     QStringList::const_iterator it_s;
0162                     for (it_s = keys.constBegin(); keysOk && it_s != keys.constEnd(); ++it_s) {
0163                         if (!KGPGFile::keyAvailable(*it_s))
0164                             keysOk = false;
0165                     }
0166                     d->listOk = keysOk;
0167                     d->needCheckList = false;
0168 
0169                 } else {
0170                     keysOk = d->listOk;
0171                 }
0172             }
0173 
0174             // did we receive some more requests to check?
0175             if (d->checkCount > 1) {
0176                 d->checkCount = 1;
0177                 continue;
0178             }
0179 
0180             if (!d->ui->m_listWidget->items().isEmpty())  {
0181                 d->ui->m_keyLed->setState(static_cast<KLed::State>(keysOk ? KLed::On : KLed::Off));
0182             } else {
0183                 d->ui->m_keyLed->setState(KLed::On);
0184             }
0185             break;
0186         }
0187 
0188         --d->checkCount;
0189         d->ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!enabled || (d->ui->m_keyLed->state() == KLed::On));
0190     }
0191 #endif
0192 }