diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f8c55241e..191c78c2f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,353 +1,356 @@ # SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: none # target_include_directories does not handle empty include paths include_directories( ${Boost_INCLUDE_DIRS} ${GPGME_INCLUDES} ) add_definitions(-DTRANSLATION_DOMAIN=\"libkleopatra\") #add_definitions( -DQT_NO_CAST_FROM_ASCII ) #add_definitions( -DQT_NO_CAST_TO_ASCII ) kde_enable_exceptions() add_definitions( -DGPGMEPP_ERR_SOURCE_DEFAULT=13 ) # 13 is GPG_ERR_SOURCE_KLEO, even if gpg-error's too old to know about add_subdirectory( pics ) if (BUILD_TESTING) add_subdirectory( tests ) endif() add_library(KF5Libkleo) add_library(KF5::Libkleo ALIAS KF5Libkleo) ########### next target ############### target_sources(KF5Libkleo PRIVATE kleo/checksumdefinition.cpp kleo/checksumdefinition.h kleo/debug.cpp kleo/debug.h kleo/defaultkeyfilter.cpp kleo/defaultkeyfilter.h kleo/defaultkeygenerationjob.cpp kleo/defaultkeygenerationjob.h kleo/docaction.cpp kleo/dn.cpp kleo/dn.h kleo/enum.cpp kleo/enum.h kleo/kconfigbasedkeyfilter.cpp kleo/kconfigbasedkeyfilter.h kleo/keyfilter.h kleo/keyfiltermanager.cpp kleo/keyfiltermanager.h kleo/keygroup.cpp kleo/keygroup.h kleo/keygroupconfig.cpp kleo/keygroupconfig.h kleo/keygroupimportexport.cpp kleo/keygroupimportexport.h kleo/keyresolver.cpp kleo/keyresolver.h kleo/keyresolvercore.cpp kleo/keyresolvercore.h kleo/keyserverconfig.cpp kleo/keyserverconfig.h kleo/kleoexception.cpp kleo/kleoexception.h kleo/oidmap.cpp kleo/oidmap.h kleo/predicates.h kleo/stl_util.h models/keycache.cpp models/keycache.h models/keycache_p.h models/keylist.h models/keylistmodel.cpp models/keylistmodel.h models/keylistmodelinterface.cpp models/keylistmodelinterface.h models/keylistsortfilterproxymodel.cpp models/keylistsortfilterproxymodel.h models/keyrearrangecolumnsproxymodel.cpp models/keyrearrangecolumnsproxymodel.h models/subkeylistmodel.cpp models/subkeylistmodel.h models/useridlistmodel.cpp models/useridlistmodel.h utils/algorithm.h utils/assuan.cpp utils/assuan.h utils/classify.cpp utils/classify.h utils/compat.cpp utils/compat.h utils/cryptoconfig.cpp utils/cryptoconfig.h utils/cryptoconfig_p.h utils/filesystemwatcher.cpp utils/filesystemwatcher.h utils/formatting.cpp utils/formatting.h utils/gnupg-registry.c utils/gnupg-registry.h utils/gnupg.cpp utils/gnupg.h utils/hex.cpp utils/hex.h utils/keyhelpers.cpp utils/keyhelpers.h utils/qtstlhelpers.cpp utils/qtstlhelpers.h utils/scdaemon.cpp utils/scdaemon.h utils/stringutils.cpp utils/stringutils.h utils/test.cpp utils/test.h utils/uniquelock.cpp utils/uniquelock.h ) ecm_qt_declare_logging_category(KF5Libkleo HEADER libkleo_debug.h IDENTIFIER LIBKLEO_LOG CATEGORY_NAME org.kde.pim.libkleo DESCRIPTION "libkleo (kleo_core)" EXPORT LIBKLEO ) target_sources(KF5Libkleo PRIVATE ui/auditlogviewer.cpp ui/auditlogviewer.h ui/cryptoconfigentryreaderport.cpp ui/cryptoconfigentryreaderport_p.h ui/cryptoconfigmodule.cpp ui/cryptoconfigmodule.h ui/cryptoconfigmodule_p.h ui/directoryserviceswidget.cpp ui/directoryserviceswidget.h ui/dnattributeorderconfigwidget.cpp ui/dnattributeorderconfigwidget.h ui/editdirectoryservicedialog.cpp ui/editdirectoryservicedialog.h ui/filenamerequester.cpp ui/filenamerequester.h ui/kdhorizontalline.cpp ui/kdhorizontalline.h ui/messagebox.cpp ui/messagebox.h ui/progressbar.cpp ui/progressbar.h ui/progressdialog.cpp ui/progressdialog.h - ) + ui/readerportselection.cpp + ui/readerportselection.h +) ecm_qt_declare_logging_category(KF5Libkleo HEADER kleo_ui_debug.h IDENTIFIER KLEO_UI_LOG CATEGORY_NAME org.kde.pim.kleo_ui DESCRIPTION "libkleo (kleo_ui)" OLD_CATEGORY_NAMES log_kleo_ui EXPORT LIBKLEO ) target_sources(KF5Libkleo PRIVATE # make this a separate lib. ui/keyapprovaldialog.cpp ui/keyapprovaldialog.h ui/keylistview.cpp ui/keylistview.h ui/keyrequester.cpp ui/keyrequester.h ui/keyselectioncombo.cpp ui/keyselectioncombo.h ui/keyselectiondialog.cpp ui/keyselectiondialog.h ui/newkeyapprovaldialog.cpp ui/newkeyapprovaldialog.h ) target_link_libraries(KF5Libkleo PUBLIC QGpgme Gpgmepp PRIVATE Qt${QT_MAJOR_VERSION}::Widgets KF5::I18n KF5::Completion KF5::ConfigCore KF5::CoreAddons KF5::WidgetsAddons KF5::ItemModels KF5::Codecs) # Boost::headers may not be available for old versions of Boost if (TARGET Boost::headers) target_link_libraries(KF5Libkleo PRIVATE Boost::headers) endif() if (KF5PimTextEdit_FOUND) add_definitions(-DHAVE_PIMTEXTEDIT) target_link_libraries(KF5Libkleo PRIVATE KF5::PimTextEdit) endif() if (COMPILE_WITH_UNITY_CMAKE_SUPPORT) set_target_properties(KF5Libkleo PROPERTIES UNITY_BUILD ON) endif() generate_export_header(KF5Libkleo BASE_NAME kleo) if(WIN32) target_link_libraries(KF5Libkleo ${GPGME_VANILLA_LIBRARIES} ) endif() set_target_properties(KF5Libkleo PROPERTIES VERSION ${LIBKLEO_VERSION} SOVERSION ${LIBKLEO_SOVERSION} EXPORT_NAME Libkleo ) install(TARGETS KF5Libkleo EXPORT KF5LibkleoTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS} ) target_include_directories(KF5Libkleo INTERFACE "$") target_include_directories(KF5Libkleo PUBLIC "$") ecm_generate_headers(libkleo_CamelCase_HEADERS HEADER_NAMES ChecksumDefinition Debug DefaultKeyFilter DefaultKeyGenerationJob DocAction Dn Enum KConfigBasedKeyFilter KeyFilter KeyFilterManager KeyGroup KeyGroupConfig KeyGroupImportExport KeyResolver KeyResolverCore KeyserverConfig KleoException OidMap Predicates Stl_Util REQUIRED_HEADERS libkleo_HEADERS PREFIX Libkleo RELATIVE kleo ) ecm_generate_headers(libkleo_CamelCase_models_HEADERS HEADER_NAMES KeyCache KeyList KeyListModel KeyListModelInterface KeyListSortFilterProxyModel KeyRearrangeColumnsProxyModel SubkeyListModel UserIDListModel REQUIRED_HEADERS libkleo_models_HEADERS PREFIX Libkleo RELATIVE models ) ecm_generate_headers(libkleo_CamelCase_utils_HEADERS HEADER_NAMES Algorithm Assuan Classify Compat CryptoConfig FileSystemWatcher Formatting GnuPG Hex KeyHelpers QtStlHelpers SCDaemon StringUtils Test UniqueLock REQUIRED_HEADERS libkleo_utils_HEADERS PREFIX Libkleo RELATIVE utils ) ecm_generate_headers(libkleo_CamelCase_ui_HEADERS HEADER_NAMES CryptoConfigModule DNAttributeOrderConfigWidget DirectoryServicesWidget EditDirectoryServiceDialog FileNameRequester KDHorizontalLine KeyApprovalDialog KeyRequester KeySelectionCombo KeySelectionDialog MessageBox NewKeyApprovalDialog ProgressDialog + ReaderPortSelection REQUIRED_HEADERS libkleo_ui_HEADERS PREFIX Libkleo RELATIVE ui ) ecm_generate_pri_file(BASE_NAME Libkleo LIB_NAME KF5Libkleo DEPS "QGpgme" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF}/Libkleo ) install(FILES ${libkleo_CamelCase_HEADERS} ${libkleo_CamelCase_models_HEADERS} ${libkleo_CamelCase_ui_HEADERS} ${libkleo_CamelCase_utils_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/Libkleo/Libkleo COMPONENT Devel ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kleo_export.h ${libkleo_HEADERS} ${libkleo_models_HEADERS} ${libkleo_ui_HEADERS} ${libkleo_utils_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/Libkleo/libkleo COMPONENT Devel ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) if ( WIN32 ) install ( FILES libkleopatrarc-win32.desktop DESTINATION ${KDE_INSTALL_CONFDIR} RENAME libkleopatrarc ) else () install ( FILES libkleopatrarc.desktop DESTINATION ${KDE_INSTALL_CONFDIR} RENAME libkleopatrarc ) endif () if (BUILD_QCH) ecm_add_qch( KF5Libkleo_QCH NAME KF5Libkleo BASE_NAME KF5Libkleo VERSION ${PIM_VERSION} ORG_DOMAIN org.kde SOURCES # using only public headers, to cover only public API ${libkleo_HEADERS} ${libkleo_models_HEADERS} ${libkleo_ui_HEADERS} ${libkleo_utils_HEADERS} #MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" #IMAGE_DIRS "${CMAKE_SOURCE_DIR}/docs/pics" LINK_QCHS Qt5Core_QCH Qt5Gui_QCH Qt5Widgets_QCH INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} BLANK_MACROS KLEO_EXPORT TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} COMPONENT Devel ) endif() diff --git a/src/ui/cryptoconfigentryreaderport.cpp b/src/ui/cryptoconfigentryreaderport.cpp index 6cd8d00d8..dc87d61bf 100644 --- a/src/ui/cryptoconfigentryreaderport.cpp +++ b/src/ui/cryptoconfigentryreaderport.cpp @@ -1,135 +1,75 @@ /* ui/cryptoconfigentryreaderport.cpp This file is part of libkleopatra SPDX-FileCopyrightText: 2021 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "cryptoconfigentryreaderport_p.h" #include "cryptoconfigmodule.h" +#include "readerportselection.h" #include "utils/scdaemon.h" #include #include #if __has_include() # include #endif -#include #include #include #include #include namespace Kleo { CryptoConfigEntryReaderPort::CryptoConfigEntryReaderPort(CryptoConfigModule *module, QGpgME::CryptoConfigEntry *entry, const QString &entryName, QGridLayout *layout, QWidget *parent) : CryptoConfigEntryGUI{module, entry, entryName} - , mComboBox{new QComboBox{parent}} - , mCustomEntryPlaceholderText{i18nc("@item:inlistbox", "Custom entry")} + , mReaderPort{new ReaderPortSelection{parent}} { auto const label = new QLabel{i18nc("@label:listbox Reader for smart cards", "Reader to connect to"), parent}; - label->setBuddy(mComboBox); - - mComboBox->addItem(i18nc("@item:inlistbox", "Default reader")); - - GpgME::Error err; - const auto readers = SCDaemon::getReaders(err); - if (err) { - qCWarning(LIBKLEO_LOG) << "Getting available smart card readers failed:" << err; - } else { - std::for_each(std::begin(readers), std::end(readers), - [this](const auto &reader) { - mComboBox->addItem(QString::fromStdString(reader)); - }); - } - - mComboBox->addItem(mCustomEntryPlaceholderText); - mComboBox->setToolTip(xi18nc("@info:tooltip", - "Select the smart card reader that GnuPG shall use." - "The first item will make GnuPG use the first reader that is found." - "The last item allows you to enter a custom reader ID or reader port number." - "All other items represent readers that were found by GnuPG." - "")); + label->setBuddy(mReaderPort); if (entry->isReadOnly()) { label->setEnabled(false); - mComboBox->setEnabled(false); + mReaderPort->setEnabled(false); } else { - connect(mComboBox, qOverload(&QComboBox::currentIndexChanged), + connect(mReaderPort, &ReaderPortSelection::valueChanged, this, &CryptoConfigEntryReaderPort::slotChanged); - connect(mComboBox, qOverload(&QComboBox::currentIndexChanged), - this, &CryptoConfigEntryReaderPort::onCurrentIndexChanged); - connect(mComboBox, &QComboBox::editTextChanged, - this, &CryptoConfigEntryReaderPort::slotChanged); - connect(mComboBox, &QComboBox::editTextChanged, - this, &CryptoConfigEntryReaderPort::onEditTextChanged); } const int row = layout->rowCount(); layout->addWidget(label, row, 1); - layout->addWidget(mComboBox, row, 2); + layout->addWidget(mReaderPort, row, 2); } void CryptoConfigEntryReaderPort::doSave() { if (mEntry->isReadOnly()) { return; } - const int index = mComboBox->currentIndex(); - if (index == 0) { - mEntry->setStringValue({}); - } else if (mComboBox->currentText() != mCustomEntryPlaceholderText) { - mEntry->setStringValue(mComboBox->currentText()); - } + mEntry->setStringValue(mReaderPort->value()); } void CryptoConfigEntryReaderPort::doLoad() { - const QString s = mEntry->stringValue(); - if (s.isEmpty()) { - mComboBox->setCurrentIndex(0); - return; - } - for (int i = 1; i < mComboBox->count() - 1; ++i) { - if (s == mComboBox->itemText(i)) { - mComboBox->setCurrentIndex(i); - return; - } - } - mComboBox->setCurrentIndex(mComboBox->count() - 1); - mComboBox->setEditText(s); -} - -void CryptoConfigEntryReaderPort::onCurrentIndexChanged(int index) -{ - // the last item serves as input for a custom entry - mComboBox->setEditable(index == mComboBox->count() - 1); -} - -void CryptoConfigEntryReaderPort::onEditTextChanged(const QString &text) -{ - const int lastIndex = mComboBox->count() - 1; - // do not overwrite the text of the custom item with the text of another item - if (mComboBox->currentIndex() == lastIndex) { - mComboBox->setItemText(lastIndex, text); - } + mReaderPort->setValue(mEntry->stringValue()); } } // namespace Kleo diff --git a/src/ui/cryptoconfigentryreaderport_p.h b/src/ui/cryptoconfigentryreaderport_p.h index 14b465403..0623bc97f 100644 --- a/src/ui/cryptoconfigentryreaderport_p.h +++ b/src/ui/cryptoconfigentryreaderport_p.h @@ -1,44 +1,41 @@ /* ui/cryptoconfigentryreaderport_p.h This file is part of libkleopatra SPDX-FileCopyrightText: 2021 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "cryptoconfigmodule_p.h" namespace Kleo { class CryptoConfigModule; +class ReaderPortSelection; /** * A widget manager for the reader-port entry of scdaemon in the crypto config */ class CryptoConfigEntryReaderPort : public CryptoConfigEntryGUI { Q_OBJECT public: CryptoConfigEntryReaderPort(CryptoConfigModule *module, QGpgME::CryptoConfigEntry *entry, const QString &entryName, QGridLayout *layout, QWidget *parent = nullptr); private: void doSave() override; void doLoad() override; - void onCurrentIndexChanged(int); - void onEditTextChanged(const QString &); - private: - QComboBox *const mComboBox = nullptr; - const QString mCustomEntryPlaceholderText; + ReaderPortSelection *const mReaderPort = nullptr; }; } diff --git a/src/ui/readerportselection.cpp b/src/ui/readerportselection.cpp new file mode 100644 index 000000000..abb954589 --- /dev/null +++ b/src/ui/readerportselection.cpp @@ -0,0 +1,145 @@ +/* + ui/readerportselection.cpp + + This file is part of libkleopatra + SPDX-FileCopyrightText: 2022 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include + +#include "readerportselection.h" + +#include "utils/scdaemon.h" + +#include + +#if __has_include() +# include +#endif + +#include +#include + +#include + +#include + +using namespace Kleo; + +class ReaderPortSelection::Private +{ +public: + Private(ReaderPortSelection *q); + + void setValue(const QString &value); + QString value() const; + +private: + void onCurrentIndexChanged(int); + void onEditTextChanged(const QString &); + +private: + ReaderPortSelection *const q = nullptr; + QComboBox *const mComboBox = nullptr; + const QString mCustomEntryPlaceholderText; +}; + +ReaderPortSelection::Private::Private(Kleo::ReaderPortSelection *qq) + : q{qq} + , mComboBox{new QComboBox{qq}} + , mCustomEntryPlaceholderText{i18nc("@item:inlistbox", "Custom entry")} +{ + auto layout = new QHBoxLayout{q}; + layout->setContentsMargins({}); + layout->addWidget(mComboBox); + + mComboBox->addItem(i18nc("@item:inlistbox", "Default reader"), {}); + + GpgME::Error err; + const auto readers = SCDaemon::getReaders(err); + if (err) { + qCWarning(LIBKLEO_LOG) << "Getting available smart card readers failed:" << err; + } else { + std::for_each(std::begin(readers), std::end(readers), + [this](const auto &reader) { + const auto readerId = QString::fromStdString(reader); + mComboBox->addItem(readerId, readerId); + }); + } + + mComboBox->addItem(mCustomEntryPlaceholderText, {}); + mComboBox->setToolTip(xi18nc("@info:tooltip", + "Select the smart card reader that GnuPG shall use." + "The first item will make GnuPG use the first reader that is found." + "The last item allows you to enter a custom reader ID or reader port number." + "All other items represent readers that were found by GnuPG." + "")); + + connect(mComboBox, qOverload(&QComboBox::currentIndexChanged), + q, [this](int index) { + onCurrentIndexChanged(index); + Q_EMIT q->valueChanged(q->value()); + }); + connect(mComboBox, &QComboBox::editTextChanged, + q, [this](const QString &text) { + onEditTextChanged(text); + Q_EMIT q->valueChanged(q->value()); + }); +} + +void ReaderPortSelection::Private::setValue(const QString &value) +{ + if (value.isEmpty()) { + mComboBox->setCurrentIndex(0); + return; + } + const int indexOfValue = mComboBox->findData(value); + if (indexOfValue != -1) { + mComboBox->setCurrentIndex(indexOfValue); + } else { + mComboBox->setCurrentIndex(mComboBox->count() - 1); + mComboBox->setEditText(value); + } +} + +QString ReaderPortSelection::Private::value() const +{ + return mComboBox->currentData().toString(); +} + +void ReaderPortSelection::Private::onCurrentIndexChanged(int index) +{ + // the last item serves as input for a custom entry + mComboBox->setEditable(index == mComboBox->count() - 1); +} + +void ReaderPortSelection::Private::onEditTextChanged(const QString &text) +{ + const int lastIndex = mComboBox->count() - 1; + // do not overwrite the text of the custom item with the text of another item + if (mComboBox->currentIndex() == lastIndex) { + mComboBox->setItemText(lastIndex, text); + mComboBox->setItemData(lastIndex, text); + } +} + +ReaderPortSelection::ReaderPortSelection(QWidget *parent) + : QWidget{parent} + , d{new Private{this}} +{ +} + +ReaderPortSelection::~ReaderPortSelection() = default; + +void ReaderPortSelection::setValue(const QString &value) +{ + d->setValue(value); +} + +QString ReaderPortSelection::value() const +{ + return d->value(); +} diff --git a/src/ui/readerportselection.h b/src/ui/readerportselection.h new file mode 100644 index 000000000..75b978fd8 --- /dev/null +++ b/src/ui/readerportselection.h @@ -0,0 +1,38 @@ +/* + ui/readerportselection.h + + This file is part of libkleopatra + SPDX-FileCopyrightText: 2022 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include + +#include "kleo_export.h" + +namespace Kleo +{ + +class KLEO_EXPORT ReaderPortSelection : public QWidget +{ + Q_OBJECT +public: + ReaderPortSelection(QWidget *parent = nullptr); + ~ReaderPortSelection() override; + + void setValue(const QString &value); + QString value() const; + +Q_SIGNALS: + void valueChanged(const QString &newValue); + +private: + class Private; + const std::unique_ptr d; +}; + +}