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"