File indexing completed on 2025-01-05 04:55:50

0001 /*
0002     ui/readerportselection.cpp
0003 
0004     This file is part of libkleopatra
0005     SPDX-FileCopyrightText: 2022 g10 Code GmbH
0006     SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include <config-libkleo.h>
0012 
0013 #include "readerportselection.h"
0014 
0015 #include <libkleo/scdaemon.h>
0016 
0017 #include <libkleo_debug.h>
0018 
0019 #include <KLocalizedString>
0020 
0021 #if __has_include(<QGpgME/Debug>)
0022 #include <QGpgME/Debug>
0023 #endif
0024 
0025 #include <QComboBox>
0026 #include <QHBoxLayout>
0027 #include <QLineEdit>
0028 
0029 #include <gpgme++/error.h>
0030 
0031 using namespace Kleo;
0032 
0033 class ReaderPortSelection::Private
0034 {
0035 public:
0036     Private(ReaderPortSelection *q);
0037 
0038     void setValue(const QString &value);
0039     QString value() const;
0040 
0041 private:
0042     void onCurrentIndexChanged(int);
0043     void onEditTextChanged(const QString &);
0044 
0045 private:
0046     ReaderPortSelection *const q = nullptr;
0047     QComboBox *const mComboBox = nullptr;
0048 };
0049 
0050 ReaderPortSelection::Private::Private(Kleo::ReaderPortSelection *qq)
0051     : q{qq}
0052     , mComboBox{new QComboBox{qq}}
0053 {
0054     auto layout = new QHBoxLayout{q};
0055     layout->setContentsMargins({});
0056     layout->addWidget(mComboBox);
0057 
0058     mComboBox->addItem(i18nc("@item:inlistbox", "Default reader"), {});
0059 
0060     GpgME::Error err;
0061     const auto readers = SCDaemon::getReaders(err);
0062     if (err) {
0063         qCWarning(LIBKLEO_LOG) << "Getting available smart card readers failed:" << err;
0064     } else {
0065         std::for_each(std::begin(readers), std::end(readers), [this](const auto &reader) {
0066             const auto readerId = QString::fromStdString(reader);
0067             mComboBox->addItem(readerId, readerId);
0068         });
0069     }
0070 
0071     mComboBox->addItem(QString{}, {});
0072     mComboBox->setToolTip(xi18nc("@info:tooltip",
0073                                  "<para>Select the smart card reader that GnuPG shall use.<list>"
0074                                  "<item>The first item will make GnuPG use the first reader that is found.</item>"
0075                                  "<item>The last item allows you to enter a custom reader ID or reader port number.</item>"
0076                                  "<item>All other items represent readers that were found by GnuPG.</item>"
0077                                  "</list></para>"));
0078 
0079     connect(mComboBox, &QComboBox::currentIndexChanged, q, [this](int index) {
0080         onCurrentIndexChanged(index);
0081         Q_EMIT q->valueChanged(q->value());
0082     });
0083     connect(mComboBox, &QComboBox::editTextChanged, q, [this](const QString &text) {
0084         onEditTextChanged(text);
0085         Q_EMIT q->valueChanged(q->value());
0086     });
0087 }
0088 
0089 void ReaderPortSelection::Private::setValue(const QString &value)
0090 {
0091     if (value.isEmpty()) {
0092         mComboBox->setCurrentIndex(0);
0093         return;
0094     }
0095     const int indexOfValue = mComboBox->findData(value);
0096     if (indexOfValue != -1) {
0097         mComboBox->setCurrentIndex(indexOfValue);
0098     } else {
0099         mComboBox->setCurrentIndex(mComboBox->count() - 1);
0100         mComboBox->setEditText(value);
0101     }
0102 }
0103 
0104 QString ReaderPortSelection::Private::value() const
0105 {
0106     return mComboBox->currentData().toString();
0107 }
0108 
0109 void ReaderPortSelection::Private::onCurrentIndexChanged(int index)
0110 {
0111     // the last item serves as input for a custom entry
0112     mComboBox->setEditable(index == mComboBox->count() - 1);
0113     if (mComboBox->lineEdit()) {
0114         mComboBox->lineEdit()->setPlaceholderText(i18nc("@item:inlistbox", "Custom reader ID or port number"));
0115     }
0116 }
0117 
0118 void ReaderPortSelection::Private::onEditTextChanged(const QString &text)
0119 {
0120     const int lastIndex = mComboBox->count() - 1;
0121     // do not overwrite the text of the custom item with the text of another item
0122     if (mComboBox->currentIndex() == lastIndex) {
0123         mComboBox->setItemText(lastIndex, text);
0124         mComboBox->setItemData(lastIndex, text);
0125     }
0126 }
0127 
0128 ReaderPortSelection::ReaderPortSelection(QWidget *parent)
0129     : QWidget{parent}
0130     , d{new Private{this}}
0131 {
0132 }
0133 
0134 ReaderPortSelection::~ReaderPortSelection() = default;
0135 
0136 void ReaderPortSelection::setValue(const QString &value)
0137 {
0138     d->setValue(value);
0139 }
0140 
0141 QString ReaderPortSelection::value() const
0142 {
0143     return d->value();
0144 }
0145 
0146 #include "moc_readerportselection.cpp"