1/* 2 SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org> 3 4 SPDX-License-Identifier: LGPL-2.0-or-later 5*/ 6 7import QtQuick 2.6 8import QtQuick.Window 2.2 9import QtQuick.Controls @QQC2_VERSION@ 10import QtQuick.Templates @QQC2_VERSION@ as T 11import org.kde.plasma.core 2.0 as PlasmaCore 12import org.kde.kconfig 1.0 13import "private" as Private 14import org.kde.kirigami 2.5 as Kirigami 15import "mobiletextselection" as MobileTextSelection 16 17T.TextField { 18 id: control 19 20 /** 21 * Whether the button to clear the text from TextField is visible. 22 * @since 5.73 23 */ 24 property bool clearButtonShown: false 25 26 /** 27 * Whether to show a button that allows the user to reveal the password in 28 * plain text. This only makes sense if the echoMode is set to Password. 29 * @since 5.73 30 */ 31 property bool revealPasswordButtonShown: false 32 33 // this takes into account kiosk restriction 34 readonly property bool __effectiveRevealPasswordButtonShown: revealPasswordButtonShown 35 && KAuthorized.authorize("lineedit_reveal_password") 36 && (echoMode == TextInput.Normal || control.text.length > 0) 37 38 // Can't guarantee that background will always be present or have the margins property 39 readonly property bool __hasBackgroundAndMargins: background && background.hasOwnProperty("margins") 40 41 // TextField doesn't have this property by default for whatever reason 42 property bool visualFocus: control.activeFocus && ( 43 control.focusReason == Qt.TabFocusReason || 44 control.focusReason == Qt.BacktabFocusReason || 45 control.focusReason == Qt.ShortcutFocusReason 46 ) 47 48 /* It might be preferable to do background width OR content width if we 49 * want content to stay within the background rather than expanding the 50 * control, but this is maintaining compatibility with the pre-existing 51 * behavior. Use the following 2 lines if you want text to stay within the 52 * background: 53 implicitBackgroundWidth + leftInset + rightInset 54 || Math.ceil(Math.max(contentWidth, placeholder.implicitWidth)) + leftPadding + rightPadding 55 */ 56 implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, 57 Math.ceil(Math.max(contentWidth, placeholder.implicitWidth)) + leftPadding + rightPadding) 58 implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, 59 contentHeight + topPadding + bottomPadding, 60 placeholder.implicitHeight + topPadding + bottomPadding) 61 62 leftPadding: (__hasBackgroundAndMargins ? background.margins.left : 0) + (control.mirrored ? inlineButtonRow.width : 0) 63 topPadding: __hasBackgroundAndMargins ? background.margins.top : 0 64 rightPadding: (__hasBackgroundAndMargins ? background.margins.right : 0) + (control.mirrored ? 0 : inlineButtonRow.width) 65 bottomPadding: __hasBackgroundAndMargins ? background.margins.bottom : 0 66 67 PlasmaCore.ColorScope.inherit: !background || !background.visible 68 PlasmaCore.ColorScope.colorGroup: PlasmaCore.Theme.ViewColorGroup 69 70 color: control.backgroundVisible ? PlasmaCore.Theme.viewTextColor : PlasmaCore.ColorScope.textColor 71 selectionColor: control.backgroundVisible ? PlasmaCore.Theme.viewFocusColor : PlasmaCore.ColorScope.highlightColor 72 selectedTextColor: control.backgroundVisible ? PlasmaCore.Theme.viewHighlightedTextColor : PlasmaCore.ColorScope.highlightedTextColor 73 placeholderTextColor: PlasmaCore.Theme.disabledTextColor 74 75 verticalAlignment: TextInput.AlignVCenter 76 // Manually setting this fixes alignment in RTL layouts 77 horizontalAlignment: TextInput.AlignLeft 78 opacity: control.enabled ? 1 : 0.6 79 hoverEnabled: !Kirigami.Settings.tabletMode 80 81 // Work around Qt bug where NativeRendering breaks for non-integer scale factors 82 // https://bugreports.qt.io/browse/QTBUG-70481 83 renderType: Screen.devicePixelRatio % 1 !== 0 ? Text.QtRendering : Text.NativeRendering 84 85 selectByMouse: !Kirigami.Settings.tabletMode 86 87 cursorDelegate: Kirigami.Settings.tabletMode ? mobileCursor : null 88 Component { 89 id: mobileCursor 90 MobileTextSelection.MobileCursor { 91 target: control 92 } 93 } 94 onFocusChanged: { 95 if (focus) { 96 MobileTextSelection.MobileTextActionsToolBar.controlRoot = control; 97 } 98 } 99 100 onTextChanged: MobileTextSelection.MobileTextActionsToolBar.shouldBeVisible = false; 101 onPressed: MobileTextSelection.MobileTextActionsToolBar.shouldBeVisible = true; 102 103 onPressAndHold: { 104 if (!Kirigami.Settings.tabletMode) { 105 return; 106 } 107 forceActiveFocus(); 108 cursorPosition = positionAt(event.x, event.y); 109 selectWord(); 110 } 111 MobileTextSelection.MobileCursor { 112 target: control 113 selectionStartHandle: true 114 property var rect: target.positionToRectangle(target.selectionStart) 115 //FIXME: this magic values seem to be always valid, for every font,every dpi, every scaling 116 x: rect.x + 5 117 y: rect.y + 6 118 } 119 120 Label { 121 id: placeholder 122 enabled: false 123 x: control.leftPadding 124 y: control.topPadding 125 width: control.availableWidth 126 height: control.availableHeight 127 128 text: control.placeholderText 129 font: control.font 130 color: control.placeholderTextColor 131 horizontalAlignment: control.horizontalAlignment 132 verticalAlignment: control.verticalAlignment 133 visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) 134 elide: Text.ElideRight 135 renderType: control.renderType 136 } 137 138 Row { 139 id: inlineButtonRow 140 anchors.right: control.right 141 anchors.rightMargin: control.__hasBackgroundAndMargins ? background.margins.right : 0 142 anchors.verticalCenter: control.verticalCenter 143 144 PlasmaCore.IconItem { 145 id: showPasswordButton 146 source: __effectiveRevealPasswordButtonShown ? (control.echoMode === TextInput.Normal ? "visibility": "hint") : "" 147 height: PlasmaCore.Units.iconSizes.small 148 width: height 149 opacity: (__effectiveRevealPasswordButtonShown && control.enabled) ? 1 : 0 150 visible: opacity > 0 151 Behavior on opacity { 152 NumberAnimation { 153 duration: PlasmaCore.Units.longDuration 154 easing.type: Easing.InOutQuad 155 } 156 } 157 MouseArea { 158 anchors.fill: parent 159 enabled: __effectiveRevealPasswordButtonShown 160 onClicked: { 161 control.echoMode = (control.echoMode == TextInput.Normal ? TextInput.Password : TextInput.Normal) 162 control.forceActiveFocus() 163 } 164 } 165 } 166 167 PlasmaCore.IconItem { 168 id: clearButton 169 //ltr confusingly refers to the direction of the arrow in the icon, not the text direction which it should be used in 170 source: clearButtonShown ? (LayoutMirroring.enabled ? "edit-clear-locationbar-ltr" : "edit-clear-locationbar-rtl") : "" 171 height: PlasmaCore.Units.iconSizes.small 172 width: height 173 opacity: (control.length > 0 && clearButtonShown && control.enabled) ? 1 : 0 174 visible: opacity > 0 175 Behavior on opacity { 176 NumberAnimation { 177 duration: PlasmaCore.Units.longDuration 178 easing.type: Easing.InOutQuad 179 } 180 } 181 MouseArea { 182 anchors.fill: parent 183 onClicked: { 184 control.clear() 185 control.forceActiveFocus() 186 } 187 } 188 } 189 } 190 191 background: PlasmaCore.FrameSvgItem { 192 implicitWidth: PlasmaCore.Units.gridUnit * 8 + margins.left + margins.right 193 implicitHeight: PlasmaCore.Units.gridUnit + margins.top + margins.bottom 194 imagePath: "widgets/lineedit" 195 prefix: "base" 196 197 PlasmaCore.FrameSvgItem { 198 anchors { 199 fill: parent 200 leftMargin: -margins.left 201 topMargin: -margins.top 202 rightMargin: -margins.right 203 bottomMargin: -margins.bottom 204 } 205 imagePath: "widgets/lineedit" 206 prefix: "hover" 207 visible: opacity > 0 208 opacity: control.hovered 209 Behavior on opacity { 210 enabled: control.hovered 211 NumberAnimation { 212 duration: PlasmaCore.Units.longDuration 213 easing.type: Easing.OutCubic 214 } 215 } 216 } 217 PlasmaCore.FrameSvgItem { 218 z: lineEditSvg.hasElement("hint-focus-over-base") ? 0 : -1 219 anchors { 220 fill: parent 221 leftMargin: -margins.left 222 topMargin: -margins.top 223 rightMargin: -margins.right 224 bottomMargin: -margins.bottom 225 } 226 imagePath: "widgets/lineedit" 227 prefix: control.visualFocus && lineEditSvg.hasElement("focusframe-center") ? "focusframe" : "focus" 228 visible: opacity > 0 229 opacity: control.visualFocus || control.activeFocus 230 Behavior on opacity { 231 NumberAnimation { 232 duration: PlasmaCore.Units.longDuration 233 easing.type: Easing.OutCubic 234 } 235 } 236 } 237 } 238 239 PlasmaCore.Svg { 240 id: lineEditSvg 241 imagePath: "widgets/lineedit" 242 } 243} 244