Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34306970
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
23 KB
Subscribers
None
View Options
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
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Dec 28, 10:12 PM (4 h, 28 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
35/27/d8604e16ddf7119f2e9e282a20b1
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment