Page MenuHome GnuPG

No OneTemporary

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 88c564965..3374ad5f6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,391 +1,392 @@
# SPDX-FileCopyrightText: none
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(icons)
add_subdirectory(mimetypes)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
if (NOT DISABLE_KWATCHGNUPG)
add_subdirectory(kwatchgnupg)
endif()
add_subdirectory(libkleopatraclient)
add_subdirectory(conf)
add_subdirectory(kconf_update)
if(WIN32)
set(_kleopatra_extra_uiserver_SRCS uiserver/uiserver_win.cpp)
set(_kleopatra_extra_SRCS
utils/gnupg-registry.c
selftest/registrycheck.cpp
utils/windowsprocessdevice.cpp
utils/userinfo_win.cpp
)
else()
set(_kleopatra_extra_uiserver_SRCS uiserver/uiserver_unix.cpp)
set(_kleopatra_extra_SRCS)
endif()
set(_kleopatra_uiserver_SRCS
uiserver/sessiondata.cpp
uiserver/uiserver.cpp
${_kleopatra_extra_uiserver_SRCS}
uiserver/assuanserverconnection.cpp
uiserver/echocommand.cpp
uiserver/decryptverifycommandemailbase.cpp
uiserver/decryptverifycommandfilesbase.cpp
uiserver/signcommand.cpp
uiserver/signencryptfilescommand.cpp
uiserver/prepencryptcommand.cpp
uiserver/prepsigncommand.cpp
uiserver/encryptcommand.cpp
uiserver/selectcertificatecommand.cpp
uiserver/importfilescommand.cpp
uiserver/createchecksumscommand.cpp
uiserver/verifychecksumscommand.cpp
selftest/uiservercheck.cpp
)
if(ASSUAN2_FOUND)
include_directories(${ASSUAN2_INCLUDES})
set(_kleopatra_uiserver_extra_libs ${ASSUAN2_LIBRARIES})
else()
include_directories(${ASSUAN_INCLUDES})
if(WIN32)
set(_kleopatra_uiserver_extra_libs ${ASSUAN_VANILLA_LIBRARIES})
else()
set(_kleopatra_uiserver_extra_libs ${ASSUAN_PTHREAD_LIBRARIES})
endif()
endif()
if(HAVE_GPG_ERR_SOURCE_KLEO)
add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_KLEO)
add_definitions(-DGPGMEPP_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_KLEO)
else()
add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_USER_1)
add_definitions(-DGPGMEPP_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_USER_1)
endif()
ki18n_wrap_ui(_kleopatra_uiserver_SRCS crypto/gui/signingcertificateselectionwidget.ui)
set(_kleopatra_SRCS
utils/accessibility.cpp
utils/gui-helper.cpp
utils/filedialog.cpp
utils/kdpipeiodevice.cpp
utils/headerview.cpp
utils/scrollarea.cpp
utils/dragqueen.cpp
utils/multivalidator.cpp
utils/systemtrayicon.cpp
utils/path-helper.cpp
utils/input.cpp
utils/output.cpp
utils/validation.cpp
utils/wsastarter.cpp
utils/iodevicelogger.cpp
utils/log.cpp
utils/action_data.cpp
utils/types.cpp
utils/archivedefinition.cpp
utils/auditlog.cpp
utils/clipboardmenu.cpp
utils/kuniqueservice.cpp
utils/tags.cpp
utils/writecertassuantransaction.cpp
utils/keyparameters.cpp
utils/userinfo.cpp
selftest/selftest.cpp
selftest/enginecheck.cpp
selftest/gpgconfcheck.cpp
selftest/gpgagentcheck.cpp
selftest/libkleopatrarccheck.cpp
selftest/compliancecheck.cpp
${_kleopatra_extra_SRCS}
view/errorlabel.cpp
+ view/formtextinput.cpp
view/htmllabel.cpp
view/keylistcontroller.cpp
view/keytreeview.cpp
view/searchbar.cpp
view/smartcardwidget.cpp
view/openpgpkeycardwidget.cpp
view/padwidget.cpp
view/pgpcardwidget.cpp
view/pivcardwidget.cpp
view/p15cardwidget.cpp
view/netkeywidget.cpp
view/nullpinwidget.cpp
view/tabwidget.cpp
view/keycacheoverlay.cpp
view/urllabel.cpp
view/waitwidget.cpp
view/welcomewidget.cpp
dialogs/certificateselectiondialog.cpp
dialogs/certifywidget.cpp
dialogs/expirydialog.cpp
dialogs/lookupcertificatesdialog.cpp
dialogs/ownertrustdialog.cpp
dialogs/selftestdialog.cpp
dialogs/certifycertificatedialog.cpp
dialogs/revokecertificationwidget.cpp
dialogs/revokecertificationdialog.cpp
dialogs/adduseriddialog.cpp
dialogs/deletecertificatesdialog.cpp
dialogs/setinitialpindialog.cpp
dialogs/certificatedetailsdialog.cpp
dialogs/certificatedetailswidget.cpp
dialogs/trustchainwidget.cpp
dialogs/weboftrustwidget.cpp
dialogs/weboftrustdialog.cpp
dialogs/exportdialog.cpp
dialogs/subkeyswidget.cpp
dialogs/gencardkeydialog.cpp
dialogs/updatenotification.cpp
dialogs/pivcardapplicationadministrationkeyinputdialog.cpp
dialogs/certificatedetailsinputwidget.cpp
dialogs/createcsrforcardkeydialog.cpp
dialogs/groupdetailsdialog.cpp
dialogs/editgroupdialog.cpp
dialogs/revokekeydialog.cpp
crypto/controller.cpp
crypto/certificateresolver.cpp
crypto/sender.cpp
crypto/recipient.cpp
crypto/task.cpp
crypto/taskcollection.cpp
crypto/decryptverifytask.cpp
crypto/decryptverifyemailcontroller.cpp
crypto/decryptverifyfilescontroller.cpp
crypto/autodecryptverifyfilescontroller.cpp
crypto/encryptemailtask.cpp
crypto/encryptemailcontroller.cpp
crypto/newsignencryptemailcontroller.cpp
crypto/signencrypttask.cpp
crypto/signencryptfilescontroller.cpp
crypto/signemailtask.cpp
crypto/signemailcontroller.cpp
crypto/createchecksumscontroller.cpp
crypto/verifychecksumscontroller.cpp
crypto/gui/wizard.cpp
crypto/gui/wizardpage.cpp
crypto/gui/certificateselectionline.cpp
crypto/gui/certificatelineedit.cpp
crypto/gui/signingcertificateselectionwidget.cpp
crypto/gui/signingcertificateselectiondialog.cpp
crypto/gui/resultitemwidget.cpp
crypto/gui/resultlistwidget.cpp
crypto/gui/resultpage.cpp
crypto/gui/newresultpage.cpp
crypto/gui/signencryptfileswizard.cpp
crypto/gui/signencryptemailconflictdialog.cpp
crypto/gui/decryptverifyoperationwidget.cpp
crypto/gui/decryptverifyfileswizard.cpp
crypto/gui/decryptverifyfilesdialog.cpp
crypto/gui/objectspage.cpp
crypto/gui/resolverecipientspage.cpp
crypto/gui/signerresolvepage.cpp
crypto/gui/encryptemailwizard.cpp
crypto/gui/signemailwizard.cpp
crypto/gui/signencryptwidget.cpp
crypto/gui/signencryptwizard.cpp
crypto/gui/unknownrecipientwidget.cpp
crypto/gui/verifychecksumsdialog.cpp
commands/command.cpp
commands/gnupgprocesscommand.cpp
commands/detailscommand.cpp
commands/exportcertificatecommand.cpp
commands/exportgroupscommand.cpp
commands/importcertificatescommand.cpp
commands/importcertificatefromfilecommand.cpp
commands/importcertificatefromclipboardcommand.cpp
commands/importcertificatefromdatacommand.cpp
commands/importcertificatefromkeyservercommand.cpp
commands/lookupcertificatescommand.cpp
commands/reloadkeyscommand.cpp
commands/refreshx509certscommand.cpp
commands/refreshopenpgpcertscommand.cpp
commands/deletecertificatescommand.cpp
commands/decryptverifyfilescommand.cpp
commands/signencryptfilescommand.cpp
commands/signencryptfoldercommand.cpp
commands/encryptclipboardcommand.cpp
commands/signclipboardcommand.cpp
commands/decryptverifyclipboardcommand.cpp
commands/clearcrlcachecommand.cpp
commands/dumpcrlcachecommand.cpp
commands/dumpcertificatecommand.cpp
commands/importcrlcommand.cpp
commands/changeexpirycommand.cpp
commands/changeownertrustcommand.cpp
commands/changeroottrustcommand.cpp
commands/changepassphrasecommand.cpp
commands/certifycertificatecommand.cpp
commands/revokecertificationcommand.cpp
commands/selftestcommand.cpp
commands/exportsecretkeycommand.cpp
commands/exportsecretkeycommand_old.cpp
commands/exportsecretsubkeycommand.cpp
commands/exportopenpgpcertstoservercommand.cpp
commands/adduseridcommand.cpp
commands/newcertificatecommand.cpp
commands/setinitialpincommand.cpp
commands/learncardkeyscommand.cpp
commands/checksumcreatefilescommand.cpp
commands/checksumverifyfilescommand.cpp
commands/exportpaperkeycommand.cpp
commands/importpaperkeycommand.cpp
commands/genrevokecommand.cpp
commands/keytocardcommand.cpp
commands/cardcommand.cpp
commands/pivgeneratecardkeycommand.cpp
commands/changepincommand.cpp
commands/authenticatepivcardapplicationcommand.cpp
commands/setpivcardapplicationadministrationkeycommand.cpp
commands/certificatetopivcardcommand.cpp
commands/importcertificatefrompivcardcommand.cpp
commands/createopenpgpkeyfromcardkeyscommand.cpp
commands/createcsrforcardkeycommand.cpp
commands/revokekeycommand.cpp
${_kleopatra_uiserver_files}
conf/configuredialog.cpp
conf/groupsconfigdialog.cpp
conf/groupsconfigpage.cpp
conf/groupsconfigwidget.cpp
newcertificatewizard/listwidget.cpp
newcertificatewizard/newcertificatewizard.cpp
smartcard/readerstatus.cpp
smartcard/card.cpp
smartcard/openpgpcard.cpp
smartcard/netkeycard.cpp
smartcard/pivcard.cpp
smartcard/p15card.cpp
smartcard/keypairinfo.cpp
smartcard/utils.cpp
smartcard/deviceinfowatcher.cpp
accessibility/accessiblerichtextlabel.cpp
accessibility/accessiblewidgetfactory.cpp
aboutdata.cpp
systrayicon.cpp
kleopatraapplication.cpp
mainwindow.cpp
main.cpp
kleopatra.qrc
)
if(WIN32)
configure_file (versioninfo.rc.in versioninfo.rc)
set(_kleopatra_SRCS ${CMAKE_CURRENT_BINARY_DIR}/versioninfo.rc ${_kleopatra_SRCS})
endif()
set (_kleopatra_SRCS conf/kleopageconfigdialog.cpp ${_kleopatra_SRCS})
ecm_qt_declare_logging_category(_kleopatra_SRCS HEADER kleopatra_debug.h IDENTIFIER KLEOPATRA_LOG CATEGORY_NAME org.kde.pim.kleopatra
DESCRIPTION "kleopatra (kleopatra)"
OLD_CATEGORY_NAMES log_kleopatra
EXPORT KLEOPATRA
)
if(KLEO_MODEL_TEST)
add_definitions(-DKLEO_MODEL_TEST)
set(_kleopatra_SRCS ${_kleopatra_SRCS} models/modeltest.cpp)
endif()
ki18n_wrap_ui(_kleopatra_SRCS
dialogs/ownertrustdialog.ui
dialogs/selectchecklevelwidget.ui
dialogs/selftestdialog.ui
dialogs/setinitialpindialog.ui
dialogs/trustchainwidget.ui
dialogs/subkeyswidget.ui
newcertificatewizard/listwidget.ui
newcertificatewizard/chooseprotocolpage.ui
newcertificatewizard/enterdetailspage.ui
newcertificatewizard/keycreationpage.ui
newcertificatewizard/resultpage.ui
newcertificatewizard/advancedsettingsdialog.ui
)
kconfig_add_kcfg_files(_kleopatra_SRCS
kcfg/tooltippreferences.kcfgc
kcfg/emailoperationspreferences.kcfgc
kcfg/fileoperationspreferences.kcfgc
kcfg/smimevalidationpreferences.kcfgc
kcfg/tagspreferences.kcfgc
kcfg/settings.kcfgc
)
file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/icons/*-apps-kleopatra.png")
ecm_add_app_icon(_kleopatra_SRCS ICONS ${ICONS_SRCS})
add_executable(kleopatra_bin ${_kleopatra_SRCS} ${_kleopatra_uiserver_SRCS})
# For the ConfigureDialog & KCMs
target_link_libraries(kleopatra_bin kcm_kleopatra_static)
#if (COMPILE_WITH_UNITY_CMAKE_SUPPORT)
# set_target_properties(kleopatra_bin PROPERTIES UNITY_BUILD ON)
#endif()
set_target_properties(kleopatra_bin PROPERTIES OUTPUT_NAME kleopatra)
if (WIN32)
set(_kleopatra_platform_libs "secur32")
endif ()
target_link_libraries(kleopatra_bin
Gpgmepp
QGpgme
${_kleopatra_extra_libs}
KF5::Libkleo
KF5::Mime
KF5::I18n
KF5::XmlGui
KF5::IconThemes
KF5::WindowSystem
KF5::CoreAddons
KF5::ItemModels
KF5::Crash
Qt${QT_MAJOR_VERSION}::Network
Qt${QT_MAJOR_VERSION}::PrintSupport # Printing secret keys
${_kleopatra_uiserver_extra_libs}
${_kleopatra_dbusaddons_libs}
kleopatraclientcore
${_kleopatra_platform_libs}
)
install(TARGETS kleopatra_bin ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
install(
PROGRAMS data/org.kde.kleopatra.desktop data/kleopatra_import.desktop
DESTINATION ${KDE_INSTALL_APPDIR}
)
install(FILES data/org.kde.kleopatra.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
install(
PROGRAMS data/kleopatra_signencryptfiles.desktop
data/kleopatra_signencryptfolders.desktop
data/kleopatra_decryptverifyfiles.desktop
data/kleopatra_decryptverifyfolders.desktop
DESTINATION ${KDE_INSTALL_DATADIR}/kio/servicemenus
)
diff --git a/src/view/formtextinput.cpp b/src/view/formtextinput.cpp
new file mode 100644
index 000000000..7c693193e
--- /dev/null
+++ b/src/view/formtextinput.cpp
@@ -0,0 +1,220 @@
+/* view/formtextinput.cpp
+
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2022 g10 Code GmbH
+ SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "formtextinput.h"
+
+#include "errorlabel.h"
+#include "utils/accessibility.h"
+
+#include <KLocalizedString>
+
+#include <QLabel>
+#include <QLineEdit>
+#include <QPointer>
+#include <QValidator>
+
+#include "kleopatra_debug.h"
+
+namespace Kleo::_detail
+{
+
+class FormTextInputBase::Private
+{
+ FormTextInputBase *q;
+public:
+ Private(FormTextInputBase *q)
+ : q{q}
+ , mErrorMessage{i18n("Error: The entered text is not valid.")}
+ {}
+
+ QString errorMessage() const;
+ void updateError();
+ void updateAccessibleNameAndDescription();
+
+ QPointer<QLabel> mLabel;
+ QPointer<QWidget> mWidget;
+ QPointer<ErrorLabel> mErrorLabel;
+ QPointer<const QValidator> mValidator;
+ QString mAccessibleName;
+ QString mErrorMessage;
+ bool mEditingInProgress = false;
+};
+
+QString FormTextInputBase::Private::errorMessage() const
+{
+ return q->hasAcceptableInput() ? QString{} : mErrorMessage;
+}
+
+void FormTextInputBase::Private::updateError()
+{
+ if (!mErrorLabel) {
+ return;
+ }
+ const auto currentErrorMessage = mErrorLabel->text();
+ const auto newErrorMessage = errorMessage();
+ if (newErrorMessage == currentErrorMessage) {
+ return;
+ }
+ if (currentErrorMessage.isEmpty() && mEditingInProgress) {
+ // delay showing the error message until editing is finished, so that we
+ // do not annoy the user with an error message while they are still
+ // entering the recipient;
+ // on the other hand, we clear the error message immediately if it does
+ // not apply anymore and we update the error message immediately if it
+ // changed
+ return;
+ }
+ mErrorLabel->setVisible(!newErrorMessage.isEmpty());
+ mErrorLabel->setText(newErrorMessage);
+ updateAccessibleNameAndDescription();
+}
+
+void FormTextInputBase::Private::updateAccessibleNameAndDescription()
+{
+ // fall back to default accessible name if accessible name wasn't set explicitly
+ if (mAccessibleName.isEmpty()) {
+ mAccessibleName = getAccessibleName(mWidget);
+ }
+ const bool errorShown = mErrorLabel && mErrorLabel->isVisible();
+
+ // Qt does not support "described-by" relations (like WCAG's "aria-describedby" relationship attribute);
+ // emulate this by setting the error message as accessible description of the input field
+ const auto description = errorShown ? mErrorLabel->text() : QString{};
+ if (mWidget && mWidget->accessibleDescription() != description) {
+ mWidget->setAccessibleDescription(description);
+ }
+
+ // Qt does not support IA2's "invalid entry" state (like WCAG's "aria-invalid" state attribute);
+ // screen readers say something like "invalid entry" if this state is set;
+ // emulate this by adding "invalid entry" to the accessible name of the input field
+ // and its label
+ const auto name = errorShown ? mAccessibleName + QLatin1String{", "} + invalidEntryText()
+ : mAccessibleName;
+ if (mLabel && mLabel->accessibleName() != name) {
+ mLabel->setAccessibleName(name);
+ }
+ if (mWidget && mWidget->accessibleName() != name) {
+ mWidget->setAccessibleName(name);
+ }
+}
+
+FormTextInputBase::FormTextInputBase()
+ : d{new Private{this}}
+{
+}
+
+FormTextInputBase::~FormTextInputBase() = default;
+
+QWidget *FormTextInputBase::widget() const
+{
+ return d->mWidget;
+}
+
+QLabel *FormTextInputBase::label() const
+{
+ return d->mLabel;
+}
+
+ErrorLabel *FormTextInputBase::errorLabel() const
+{
+ return d->mErrorLabel;
+}
+
+void FormTextInputBase::setValidator(const QValidator *validator)
+{
+ d->mValidator = validator;
+}
+
+void FormTextInputBase::setErrorMessage(const QString &text)
+{
+ if (text.isEmpty()) {
+ d->mErrorMessage = i18n("Error: The entered text is not valid.");
+ } else {
+ d->mErrorMessage = text;
+ }
+}
+
+void FormTextInputBase::setToolTip(const QString &toolTip)
+{
+ if (d->mLabel) {
+ d->mLabel->setToolTip(toolTip);
+ }
+ if (d->mWidget) {
+ d->mWidget->setToolTip(toolTip);
+ }
+}
+
+void FormTextInputBase::setWidget(QWidget *widget)
+{
+ auto parent = widget ? widget->parentWidget() : nullptr;
+ d->mWidget = widget;
+ d->mLabel = new QLabel{parent};
+ d->mErrorLabel = new ErrorLabel{parent};
+ if (d->mLabel) {
+ d->mLabel->setBuddy(d->mWidget);
+ }
+ if (d->mErrorLabel) {
+ d->mErrorLabel->setVisible(false);
+ }
+ connectWidget();
+}
+
+void FormTextInputBase::setEnabled(bool enabled)
+{
+ if (d->mLabel) {
+ d->mLabel->setEnabled(enabled);
+ }
+ if (d->mWidget) {
+ d->mWidget->setEnabled(enabled);
+ }
+ if (d->mErrorLabel) {
+ d->mErrorLabel->setVisible(enabled && !d->mErrorLabel->text().isEmpty());
+ }
+}
+
+bool FormTextInputBase::validate(const QString &text, int pos) const
+{
+ QString textCopy = text;
+ if (d->mValidator && d->mValidator->validate(textCopy, pos) != QValidator::Acceptable)
+ {
+ return false;
+ }
+ return true;
+}
+
+void FormTextInputBase::onTextChanged()
+{
+ d->mEditingInProgress = true;
+ d->updateError();
+}
+
+void FormTextInputBase::onEditingFinished()
+{
+ d->mEditingInProgress = false;
+ d->updateError();
+}
+
+}
+
+template<>
+bool Kleo::FormTextInput<QLineEdit>::hasAcceptableInput() const
+{
+ const auto w = widget();
+ return w && validate(w->text(), w->cursorPosition());
+}
+
+template<>
+void Kleo::FormTextInput<QLineEdit>::connectWidget()
+{
+ const auto w = widget();
+ QObject::connect(w, &QLineEdit::editingFinished,
+ w, [this]() { onEditingFinished(); });
+ QObject::connect(w, &QLineEdit::textChanged,
+ w, [this]() { onTextChanged(); });
+}
diff --git a/src/view/formtextinput.h b/src/view/formtextinput.h
new file mode 100644
index 000000000..8236ab6b5
--- /dev/null
+++ b/src/view/formtextinput.h
@@ -0,0 +1,177 @@
+/* view/formtextinput.h
+
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2022 g10 Code GmbH
+ SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+#pragma once
+
+#include <memory>
+
+class QLabel;
+class QLineEdit;
+class QString;
+class QValidator;
+class QWidget;
+
+namespace Kleo
+{
+class ErrorLabel;
+
+namespace _detail
+{
+class FormTextInputBase
+{
+protected:
+ FormTextInputBase();
+
+public:
+ virtual ~FormTextInputBase();
+ FormTextInputBase(const FormTextInputBase&) = delete;
+ FormTextInputBase& operator=(const FormTextInputBase&) = delete;
+ FormTextInputBase(FormTextInputBase&&) = delete;
+ FormTextInputBase& operator=(FormTextInputBase&&) = delete;
+
+ /**
+ * Returns the label associated to the controlled widget.
+ */
+ QLabel *label() const;
+
+ /**
+ * Returns the error label associated to the controlled widget.
+ */
+ ErrorLabel *errorLabel() const;
+
+ /**
+ * Sets the validator to use for validating the input.
+ *
+ * Note: If you wrap a QLineEdit, then do not set a validator (or an input mask)
+ * on it because this will break the correct displaying of the error message.
+ */
+ void setValidator(const QValidator *validator);
+
+ /**
+ * Sets the error message to display. If \p text is empty, then the default
+ * error message will be used.
+ */
+ void setErrorMessage(const QString &text);
+
+ /**
+ * Sets the tool tip of the controlled widget and its associated label.
+ */
+ void setToolTip(const QString &toolTip);
+
+ /**
+ * Enables or disables the controlled widget and its associated label.
+ * If the widget is disables, then the error label is hidden. Otherwise,
+ * the error label is shown if there is an error.
+ */
+ void setEnabled(bool enabled);
+
+ /**
+ * Returns \c true, if the input satisfies the validator.
+ * Needs to be implemented for concrete widget classes.
+ * \sa validate
+ */
+ virtual bool hasAcceptableInput() const = 0;
+
+protected:
+ /**
+ * Connects the slots \ref onTextChanged and \ref onEditingFinished to the
+ * corresponding signal of the controlled widget.
+ * Needs to be implemented for concrete widget classes.
+ */
+ virtual void connectWidget() = 0;
+
+ /**
+ * Sets the controlled widget and creates the associated labels.
+ */
+ void setWidget(QWidget *widget);
+
+ /**
+ * Returns the controlled widget.
+ */
+ QWidget *widget() const;
+
+ /**
+ * Validates \p text with the validator. Should be used when implementing
+ * \ref hasAcceptableInput.
+ */
+ bool validate(const QString &text, int pos) const;
+
+ /**
+ * This slot needs to be connected to a signal of the controlled widget
+ * that is emitted when the text changes like \ref QLineEdit::textChanged.
+ * \sa connectWidget
+ */
+ void onTextChanged();
+
+ /**
+ * This slot needs to be connected to a signal of the controlled widget
+ * that is emitted when the widget loses focus (or some user interaction
+ * signals that they want to commit the entered text) like
+ * \ref QLineEdit::editingFinished.
+ * \sa connectWidget
+ */
+ void onEditingFinished();
+
+private:
+ class Private;
+ const std::unique_ptr<Private> d;
+};
+}
+
+/**
+ * FormTextInput is a class for simplifying the management of text input widgets
+ * like QLineEdit or QTextEdit with associated label and error message for usage
+ * in form-like dialogs.
+ *
+ * Usage hints:
+ * * If you wrap a QLineEdit, then do not set a validator (or an input mask)
+ * on it. Instead set the validator on this class.
+ * If you set a validator on the QLineEdit, then showing the error message
+ * when editing is finished does not work because QLineEdit doesn't emit the
+ * editingFinished() signal if the input is not acceptable.
+ */
+template<class Widget>
+class FormTextInput : public _detail::FormTextInputBase
+{
+ /**
+ * Use \ref create to create a new instance.
+ */
+ FormTextInput() = default;
+
+public:
+ /**
+ * Creates a new instance of this class with a new instance of \p Widget.
+ */
+ static auto create(QWidget *parent)
+ {
+ std::unique_ptr<FormTextInput> self{new FormTextInput};
+ self->setWidget(new Widget{parent});
+ return self;
+ }
+
+ /**
+ * Returns the controlled widget.
+ */
+ Widget *widget() const
+ {
+ return static_cast<Widget *>(FormTextInputBase::widget());
+ }
+
+ bool hasAcceptableInput() const override;
+
+private:
+ void connectWidget() override;
+};
+
+template<>
+bool FormTextInput<QLineEdit>::hasAcceptableInput() const;
+
+template<>
+void FormTextInput<QLineEdit>::connectWidget();
+
+}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Dec 28, 10:12 PM (11 h, 52 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
35/27/d8604e16ddf7119f2e9e282a20b1

Event Timeline