/* SPDX-FileCopyrightText: 2017 Marco Martin SPDX-FileCopyrightText: 2017 The Qt Company Ltd. SPDX-FileCopyrightText: 2021 Carl Schwan SPDX-FileCopyrightText: 2023 ivan tkachenko SPDX-License-Identifier: LGPL-3.0-only OR GPL-2.0-or-later */ pragma ComponentBehavior: Bound import QtQml.Models import QtQuick import QtQuick.Window import QtQuick.Templates as T import org.kde.kirigami as Kirigami import org.kde.sonnet as Sonnet import org.kde.desktop.private as Private import org.kde.qqc2desktopstyle.private as StylePrivate T.TextArea { id: controlRoot Kirigami.Theme.colorSet: Kirigami.Theme.View Kirigami.Theme.inherit: false implicitWidth: Math.max(contentWidth + leftPadding + rightPadding, implicitBackgroundWidth + leftInset + rightInset, placeholder.implicitWidth + leftPadding + rightPadding) implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, implicitBackgroundHeight + topInset + bottomInset, placeholder.implicitHeight + topPadding + bottomPadding) padding: 6 color: Kirigami.Theme.textColor selectionColor: Kirigami.Theme.highlightColor selectedTextColor: Kirigami.Theme.highlightedTextColor hoverEnabled: !Kirigami.Settings.tabletMode || !Kirigami.Settings.hasTransientTouchInput verticalAlignment: TextEdit.AlignTop selectByMouse: hoverEnabled cursorDelegate: !hoverEnabled ? mobileCursor : null Component { id: mobileCursor Private.MobileCursor { target: controlRoot } } onTextChanged: Private.MobileTextActionsToolBar.shouldBeVisible = false; onPressed: event => { Private.MobileTextActionsToolBar.shouldBeVisible = true; } TapHandler { enabled: controlRoot.selectByMouse acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad | PointerDevice.Stylus acceptedButtons: Qt.LeftButton | Qt.RightButton // unfortunately, taphandler's pressed event only triggers when the press is lifted // we need to use the longpress signal since it triggers when the button is first pressed longPressThreshold: 0.001 // https://invent.kde.org/qt/qt/qtdeclarative/-/commit/8f6809681ec82da783ae8dcd76fa2c209b28fde6 onLongPressed: { Private.TextFieldContextMenu.targetClick( point, controlRoot, spellcheckHighlighterInstantiator, controlRoot.positionAt(point.position.x, point.position.y), ); } } Kirigami.SpellCheck.enabled: !controlRoot.readOnly && Private.GlobalSonnetSettings.checkerEnabledByDefault Instantiator { id: spellcheckHighlighterInstantiator active: controlRoot.Kirigami.SpellCheck.enabled asynchronous: true Sonnet.SpellcheckHighlighter { active: true document: controlRoot.textDocument cursorPosition: controlRoot.cursorPosition selectionStart: controlRoot.selectionStart selectionEnd: controlRoot.selectionEnd misspelledColor: Kirigami.Theme.negativeTextColor onChangeCursorPosition: (start, end) => { controlRoot.cursorPosition = start; controlRoot.moveCursorSelection(end, TextEdit.SelectCharacters); } } } Keys.onPressed: event => { // trigger if context menu button is pressed if (controlRoot.selectByMouse) { Private.TextFieldContextMenu.targetKeyPressed(event, controlRoot) } } onPressAndHold: event => { if (hoverEnabled) { return; } forceActiveFocus(); cursorPosition = positionAt(event.x, event.y); selectWord(); } Private.MobileCursor { target: controlRoot selectionStartHandle: true readonly property rect rect: { // selectionStart is actually the "physical" start of selection, // not a "logical" one, so we have to find out the real logical // end of selection ourselves. const positionEnd = controlRoot.cursorPosition === controlRoot.selectionStart ? controlRoot.selectionEnd : controlRoot.selectionStart; return controlRoot.positionToRectangle(positionEnd); } x: rect.x y: rect.y } onFocusChanged: { if (focus) { Private.MobileTextActionsToolBar.controlRoot = controlRoot; } } Label { id: placeholder x: controlRoot.leftPadding y: controlRoot.topPadding width: controlRoot.width - (controlRoot.leftPadding + controlRoot.rightPadding) height: controlRoot.height - (controlRoot.topPadding + controlRoot.bottomPadding) text: controlRoot.placeholderText font: controlRoot.font color: Kirigami.Theme.disabledTextColor horizontalAlignment: controlRoot.horizontalAlignment verticalAlignment: controlRoot.verticalAlignment visible: !controlRoot.length && !controlRoot.preeditText && (!controlRoot.activeFocus || controlRoot.horizontalAlignment !== Qt.AlignHCenter) elide: Text.ElideRight wrapMode: Text.WordWrap } background: StylePrivate.StyleItem { control: controlRoot elementType: "edit" implicitWidth: 200 implicitHeight: 22 sunken: true hasFocus: controlRoot.activeFocus hover: controlRoot.hovered } }