Warning, /office/klevernotes/src/contents/ui/dialogs/todoDialog/TextAreaDelegate.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 // SPDX-FileCopyrightText: 2023 Louis Schul <schul9louis@gmail.com>
0003
0004 // BASED ON FormTextFieldDelegate :
0005 /*
0006 * Copyright 2022 Carl Schwan <carl@carlschwan.eu>
0007 * SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009
0010 import QtQuick 2.15
0011 import QtQuick.Controls 2.15
0012 import QtQuick.Layouts 1.15
0013
0014 import org.kde.kirigami 2.19 as Kirigami
0015 import org.kde.kirigamiaddons.formcard 1.0
0016
0017 AbstractFormDelegate {
0018 id: root
0019
0020 /**
0021 * @brief A label containing primary text that appears above and
0022 * to the left the text field.
0023 */
0024 required property string label
0025
0026 /**
0027 * @brief set the maximum length of the text inside the TextField if maxLength > 0
0028 */
0029 property int maximumLength: 0
0030
0031 /**
0032 * @brief This hold the activeFocus state of the internal TextField.
0033 */
0034 property alias fieldActiveFocus: textArea.activeFocus
0035
0036 /**
0037 * @brief This hold the `readOnly` state of the internal TextField.
0038 */
0039 property alias readOnly: textArea.readOnly
0040
0041 /**
0042 * @brief This property holds the `inputMethodHints` of the
0043 * internal TextField.
0044 *
0045 * This consists of hints on the expected content or behavior of
0046 * the text field, be it sensitive data, in a date format, or whether
0047 * the characters will be hidden, for example.
0048 *
0049 * @see <a href="https://doc.qt.io/qt-6/qml-qtquick-textinput.html#inputMethodHints-prop">TextInput.inputMethodHints</a>
0050 */
0051 property alias inputMethodHints: textArea.inputMethodHints
0052
0053 /**
0054 * @brief This property holds the `wrapMode` of the
0055 * internal TextArea.
0056 *
0057 * @see <a href="https://doc.qt.io/qt-6/qml-qtquick-textedit.html#wrapMode-prop">TextEdit.wrapMode</a>
0058 */
0059 property alias wrapMode: textArea.wrapMode
0060
0061 /**
0062 * @brief This property holds the `placeholderText` of the
0063 * internal TextField.
0064 *
0065 * This consists of secondary text shown by default on the text field
0066 * if no text has been written in it.
0067 */
0068 property alias placeholderText: textArea.placeholderText
0069
0070 /**
0071 * @brief This property holds the current status message type of
0072 * the text field.
0073 *
0074 * This consists of an inline message with a colorful background
0075 * and an appropriate icon.
0076 *
0077 * The status property will affect the color of ::statusMessage used.
0078 *
0079 * Accepted values:
0080 * - `Kirigami.MessageType.Information` (blue color)
0081 * - `Kirigami.MessageType.Positive` (green color)
0082 * - `Kirigami.MessageType.Warning` (orange color)
0083 * - `Kirigami.MessageType.Error` (red color)
0084 *
0085 * default: `Kirigami.MessageType.Information` if ::statusMessage is set,
0086 * nothing otherwise.
0087 *
0088 * @see Kirigami.MessageType
0089 */
0090 property var status: Kirigami.MessageType.Information
0091
0092 /**
0093 * @brief This property holds the current status message of
0094 * the text field.
0095 *
0096 * If this property is not set, no ::status will be shown.
0097 */
0098 property string statusMessage: ""
0099
0100 /**
0101 * @This signal is emitted when the Return or Enter key is pressed.
0102 *
0103 * Note that if there is a validator or inputMask set on the text input,
0104 * the signal will only be emitted if the input is in an acceptable
0105 * state.
0106 */
0107 signal accepted();
0108
0109 /**
0110 * @brief This signal is emitted when the Return or Enter key is pressed
0111 * or the text input loses focus.
0112 *
0113 * Note that if there is a validator or inputMask set on the text input
0114 * and enter/return is pressed, this signal will only be emitted if
0115 * the input follows the inputMask and the validator returns an
0116 * acceptable state.
0117 */
0118 signal editingFinished();
0119
0120 /**
0121 * @brief This signal is emitted whenever the text is edited.
0122 *
0123 * Unlike textChanged(), this signal is not emitted when the text
0124 * is changed programmatically, for example, by changing the
0125 * value of the text property or by calling ::clear().
0126 */
0127 signal textEdited();
0128
0129 background: null
0130
0131 contentItem: ColumnLayout {
0132 spacing: Kirigami.Units.smallSpacing
0133
0134 RowLayout {
0135 spacing: Kirigami.Units.largeSpacing
0136
0137 Label {
0138 text: label
0139 elide: Text.ElideRight
0140 color: root.enabled ? Kirigami.Theme.textColor : Kirigami.Theme.disabledTextColor
0141 wrapMode: Text.Wrap
0142 maximumLineCount: 2
0143
0144 Layout.fillWidth: true
0145 }
0146 Label {
0147 text: metrics.label(textArea.text.length, root.maximumLength)
0148 font: Kirigami.Theme.smallFont
0149 color: textArea.text.length === root.maximumLength
0150 ? Kirigami.Theme.neutralTextColor
0151 : Kirigami.Theme.textColor
0152
0153 horizontalAlignment: Text.AlignRight
0154 visible: root.maximumLength > 0
0155
0156 Layout.margins: Kirigami.Units.smallSpacing
0157 Layout.preferredWidth: metrics.advanceWidth
0158
0159 TextMetrics {
0160 id: metrics
0161
0162 text: label(root.maximumLength, root.maximumLength)
0163 font: Kirigami.Theme.smallFont
0164
0165 function label(current: int, maximum: int): string {
0166 return i18nc("@label %1 is current text length, %2 is maximum length of text field", "%1/%2", current, maximum)
0167 }
0168 }
0169 }
0170 }
0171
0172 ScrollView {
0173 Layout.fillWidth: true
0174 Layout.fillHeight: true
0175
0176 TextArea {
0177 id: textArea
0178
0179 text: root.text
0180 placeholderText: root.placeholderText
0181 activeFocusOnTab: false
0182
0183 Accessible.description: label
0184
0185 onTextChanged: {
0186 if (0 < root.maximumLength && root.maximumLength < text.length) {
0187 const excess = text.length - root.maximumLength
0188
0189 let newCursorPosition = cursorPosition
0190 let oldCursorPosition = newCursorPosition - excess
0191
0192 if (newCursorPosition < oldCursorPosition) {
0193 newCursorPosition = oldCursorPosition
0194 oldCursorPosition = cursorPosition
0195 }
0196
0197 const a = text.substring(0, oldCursorPosition);
0198 const b = text.substring(newCursorPosition);
0199 text = a + b
0200
0201 cursorPosition = oldCursorPosition
0202 }
0203 root.text = text
0204 }
0205 onEditingFinished: {
0206 root.editingFinished()
0207 }
0208 }
0209 }
0210
0211 Kirigami.InlineMessage {
0212 id: formErrorHandler
0213
0214 text: root.statusMessage
0215 type: root.status
0216 visible: root.statusMessage.length > 0
0217
0218 Layout.fillWidth: true
0219 Layout.topMargin: visible ? Kirigami.Units.smallSpacing : 0
0220 }
0221 }
0222
0223 Accessible.role: Accessible.EditableText
0224
0225 onActiveFocusChanged: { // propagate focus to the text field
0226 if (activeFocus) {
0227 textArea.forceActiveFocus();
0228 }
0229 }
0230 onClicked: {
0231 textArea.forceActiveFocus()
0232 }
0233
0234 /**
0235 * @brief Clears the contents of the text input and resets partial
0236 * text input from an input method.
0237 */
0238 function clear() {
0239 textArea.clear();
0240 }
0241
0242 /**
0243 * Inserts text into the TextInput at position.
0244 */
0245 function insert(position: int, text: string) {
0246 textArea.insert(position, text);
0247 }
0248 }