File indexing completed on 2024-06-16 04:56:14
0001 /* view/formtextinput.h 0002 0003 This file is part of Kleopatra, the KDE keymanager 0004 SPDX-FileCopyrightText: 2022 g10 Code GmbH 0005 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #pragma once 0010 0011 #include <QString> 0012 0013 #include <memory> 0014 0015 class QLabel; 0016 class QLineEdit; 0017 class QValidator; 0018 class QWidget; 0019 0020 namespace Kleo 0021 { 0022 class ErrorLabel; 0023 0024 namespace _detail 0025 { 0026 class FormTextInputBase 0027 { 0028 protected: 0029 FormTextInputBase(); 0030 0031 public: 0032 virtual ~FormTextInputBase(); 0033 FormTextInputBase(const FormTextInputBase &) = delete; 0034 FormTextInputBase &operator=(const FormTextInputBase &) = delete; 0035 FormTextInputBase(FormTextInputBase &&) = delete; 0036 FormTextInputBase &operator=(FormTextInputBase &&) = delete; 0037 0038 /** 0039 * Returns the label associated to the controlled widget. Use it to add 0040 * the label to a layout, but do not use it to set properties of the label 0041 * for which this class provides setters. 0042 */ 0043 QLabel *label() const; 0044 0045 /** 0046 * Returns the hint label associated to the controlled widget. 0047 */ 0048 QLabel *hintLabel() const; 0049 0050 /** 0051 * Returns the error label associated to the controlled widget. 0052 */ 0053 ErrorLabel *errorLabel() const; 0054 0055 /** 0056 * Sets \p text as text of the label and \p accessibleName as alternative 0057 * text for assistive tools. If \p accessibleName is empty, then \p text is 0058 * used instead. Both texts must be plain text. 0059 * 0060 * Note: If input is required, then the label is annotated appropriately. 0061 */ 0062 void setLabelText(const QString &text, const QString &accessibleName = {}); 0063 0064 /** 0065 * Sets \p text as hint text for this input field and \p accessibleDescription 0066 * as alternative text for assistive tools. If \p accessibleDescription is 0067 * empty, then \p text is used instead. Both texts must be plain text. 0068 */ 0069 void setHint(const QString &text, const QString &accessibleDescription = {}); 0070 0071 /** 0072 * Marks this input field as required. 0073 */ 0074 void setIsRequired(bool required); 0075 0076 /** 0077 * Returns \c true, if this field needs to be filled out. 0078 */ 0079 bool isRequired() const; 0080 0081 /** 0082 * Sets the validator to use for validating the input. 0083 * 0084 * Note: If you wrap a QLineEdit, then do not set a validator (or an input mask) 0085 * on it because this will break the correct displaying of the error message. 0086 */ 0087 void setValidator(const std::shared_ptr<QValidator> &validator); 0088 0089 /** 0090 * Sets \p text as error message to display if a value is required for the 0091 * input field, but if no value has been entered. If \p text is empty, then 0092 * a default message will be used. Both texts must be plain text. 0093 * The optional \p accessibleText is used as alternative text for assistive 0094 * tools. 0095 */ 0096 void setValueRequiredErrorMessage(const QString &text, const QString &accessibleText = {}); 0097 0098 /** 0099 * Sets \p text as error message to display if the entered value is not accepted 0100 * by the validator. If \p text is empty, then a default message will be used. 0101 * The optional \p accessibleText is used as alternative text for assistive 0102 * tools. Both texts must be plain text. 0103 */ 0104 void setInvalidEntryErrorMessage(const QString &text, const QString &accessibleText = {}); 0105 0106 /** 0107 * Sets the tool tip of the controlled widget and its associated label. 0108 */ 0109 void setToolTip(const QString &toolTip); 0110 0111 /** 0112 * Enables or disables the controlled widget and its associated label. 0113 * If the widget is disables, then the error label is hidden. Otherwise, 0114 * the error label is shown if there is an error. 0115 */ 0116 void setEnabled(bool enabled); 0117 0118 /** 0119 * Returns the currently shown error message for this input field. 0120 */ 0121 QString currentError() const; 0122 0123 /** 0124 * Returns \c true, if the input has a value. This function is used to 0125 * check required input fields for non-empty user input. 0126 * Needs to be implemented for concrete widget classes. 0127 * \sa validate 0128 */ 0129 virtual bool hasValue() const = 0; 0130 0131 /** 0132 * Returns \c true, if the input satisfies the validator. 0133 * Needs to be implemented for concrete widget classes. 0134 * \sa validate 0135 */ 0136 virtual bool hasAcceptableInput() const = 0; 0137 0138 protected: 0139 /** 0140 * Connects the slots \ref onTextChanged and \ref onEditingFinished to the 0141 * corresponding signal of the controlled widget. 0142 * Needs to be implemented for concrete widget classes. 0143 */ 0144 virtual void connectWidget() = 0; 0145 0146 /** 0147 * Sets the controlled widget and creates the associated labels. 0148 */ 0149 void setWidget(QWidget *widget); 0150 0151 /** 0152 * Returns the controlled widget. 0153 */ 0154 QWidget *widget() const; 0155 0156 /** 0157 * Validates \p text with the validator. Should be used when implementing 0158 * \ref hasAcceptableInput. 0159 */ 0160 bool validate(const QString &text, int pos) const; 0161 0162 /** 0163 * This slot needs to be connected to a signal of the controlled widget 0164 * that is emitted when the text changes like \ref QLineEdit::textChanged. 0165 * \sa connectWidget 0166 */ 0167 void onTextChanged(); 0168 0169 /** 0170 * This slot needs to be connected to a signal of the controlled widget 0171 * that is emitted when the widget loses focus (or some user interaction 0172 * signals that they want to commit the entered text) like 0173 * \ref QLineEdit::editingFinished. 0174 * \sa connectWidget 0175 */ 0176 void onEditingFinished(); 0177 0178 private: 0179 class Private; 0180 const std::unique_ptr<Private> d; 0181 }; 0182 } 0183 0184 /** 0185 * FormTextInput is a class for simplifying the management of text input widgets 0186 * like QLineEdit or QTextEdit with associated label and error message for usage 0187 * in form-like dialogs. 0188 * 0189 * Usage hints: 0190 * * If you wrap a QLineEdit, then do not set a validator (or an input mask) 0191 * on it. Instead set the validator on this class. 0192 * If you set a validator on the QLineEdit, then showing the error message 0193 * when editing is finished does not work because QLineEdit doesn't emit the 0194 * editingFinished() signal if the input is not acceptable. 0195 */ 0196 template<class Widget> 0197 class FormTextInput : public _detail::FormTextInputBase 0198 { 0199 /** 0200 * Use \ref create to create a new instance. 0201 */ 0202 FormTextInput() = default; 0203 0204 public: 0205 /** 0206 * Creates a new instance of this class with a new instance of \p Widget. 0207 */ 0208 static auto create(QWidget *parent) 0209 { 0210 std::unique_ptr<FormTextInput> self{new FormTextInput}; 0211 self->setWidget(new Widget{parent}); 0212 return self; 0213 } 0214 0215 /** 0216 * Returns the controlled widget. 0217 */ 0218 Widget *widget() const 0219 { 0220 return static_cast<Widget *>(FormTextInputBase::widget()); 0221 } 0222 0223 bool hasValue() const override; 0224 0225 bool hasAcceptableInput() const override; 0226 0227 private: 0228 void connectWidget() override; 0229 }; 0230 0231 template<> 0232 bool FormTextInput<QLineEdit>::hasValue() const; 0233 0234 template<> 0235 bool FormTextInput<QLineEdit>::hasAcceptableInput() const; 0236 0237 template<> 0238 void FormTextInput<QLineEdit>::connectWidget(); 0239 0240 }