diff --git a/src/declarativeimports/plasmacomponents3/TextArea.qml b/src/declarativeimports/plasmacomponents3/TextArea.qml --- a/src/declarativeimports/plasmacomponents3/TextArea.qml +++ b/src/declarativeimports/plasmacomponents3/TextArea.qml @@ -23,6 +23,7 @@ import QtQuick.Templates @QQC2_VERSION@ as T import org.kde.plasma.core 2.0 as PlasmaCore import "private" as Private +import org.kde.kirigami 2.5 as Kirigami T.TextArea { id: control @@ -42,11 +43,45 @@ opacity: control.enabled ? 1 : 0.6 wrapMode: Text.WordWrap verticalAlignment: TextEdit.AlignTop + hoverEnabled: !Kirigami.Settings.tabletMode // Work around Qt bug where NativeRendering breaks for non-integer scale factors // https://bugreports.qt.io/browse/QTBUG-67007 renderType: Screen.devicePixelRatio % 1 !== 0 ? Text.QtRendering : Text.NativeRendering - + + selectByMouse: !Kirigami.Settings.tabletMode + + cursorDelegate: Kirigami.Settings.tabletMode ? mobileCursor : undefined + Component { + id: mobileCursor + Private.MobileCursor { + controlRoot: control + } + } + + onPressAndHold: { + if (!Kirigami.Settings.tabletMode) { + return; + } + forceActiveFocus(); + cursorPosition = positionAt(event.x, event.y); + selectWord(); + } + + Private.MobileCursor { + controlRoot: control + selectionStartHandle: true + property var rect: control.positionToRectangle(control.selectionStart) + x: rect.x + y: rect.y + } + + onFocusChanged: { + if (focus) { + Private.MobileTextActionsToolBar.controlRoot = control; + } + } + Label { id: placeholder x: control.leftPadding diff --git a/src/declarativeimports/plasmacomponents3/TextField.qml b/src/declarativeimports/plasmacomponents3/TextField.qml --- a/src/declarativeimports/plasmacomponents3/TextField.qml +++ b/src/declarativeimports/plasmacomponents3/TextField.qml @@ -23,7 +23,7 @@ import QtQuick.Templates @QQC2_VERSION@ as T import org.kde.plasma.core 2.0 as PlasmaCore import "private" as Private - +import org.kde.kirigami 2.5 as Kirigami T.TextField { id: control @@ -40,11 +40,44 @@ selectedTextColor: theme.highlightedTextColor verticalAlignment: TextInput.AlignVCenter opacity: control.enabled ? 1 : 0.6 + hoverEnabled: !Kirigami.Settings.tabletMode // Work around Qt bug where NativeRendering breaks for non-integer scale factors // https://bugreports.qt.io/browse/QTBUG-67007 renderType: Screen.devicePixelRatio % 1 !== 0 ? Text.QtRendering : Text.NativeRendering + selectByMouse: !Kirigami.Settings.tabletMode + + cursorDelegate: Kirigami.Settings.tabletMode ? mobileCursor : undefined + Component { + id: mobileCursor + Private.MobileCursor { + controlRoot: control + } + } + onFocusChanged: { + if (focus) { + Private.MobileTextActionsToolBar.controlRoot = control; + } + } + + onPressAndHold: { + if (!Kirigami.Settings.tabletMode) { + return; + } + forceActiveFocus(); + cursorPosition = positionAt(event.x, event.y); + selectWord(); + } + Private.MobileCursor { + controlRoot: control + selectionStartHandle: true + property var rect: control.positionToRectangle(control.selectionStart) + //FIXME: this magic values seem to be always valid, for every font,every dpi, every scaling + x: rect.x + 5 + y: rect.y + 6 + } + Label { id: placeholder x: control.leftPadding diff --git a/src/declarativeimports/plasmacomponents3/private/MobileCursor.qml b/src/declarativeimports/plasmacomponents3/private/MobileCursor.qml new file mode 100644 --- /dev/null +++ b/src/declarativeimports/plasmacomponents3/private/MobileCursor.qml @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2018 by Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. + */ + +import QtQuick 2.1 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.kirigami 2.5 as Kirigami + +Item { + id: root + width: 1 //<-important that this is actually a single device pixel + height: units.gridUnit + + property Item controlRoot + + property bool selectionStartHandle: false + + visible: Kirigami.Settings.tabletMode && ((controlRoot.focus && !selectionStartHandle) || controlRoot.selectedText.length > 0) + + Rectangle { + width: Math.round(units.devicePixelRatio * 3) + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + bottom: parent.bottom + } + color: Qt.tint(theme.highlightColor, Qt.rgba(1,1,1,0.4)) + radius: width + Rectangle { + width: Math.round(units.gridUnit/1.5) + height: width + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.bottom + } + radius: width + color: Qt.tint(theme.highlightColor, Qt.rgba(1,1,1,0.4)) + } + MouseArea { + anchors { + fill: parent + margins: -units.gridUnit + } + preventStealing: true + onPositionChanged: { + var pos = mapToItem(controlRoot, mouse.x, mouse.y); + pos = controlRoot.positionAt(pos.x, pos.y); + + if (controlRoot.selectedText.length > 0) { + if (selectionStartHandle) { + controlRoot.select(Math.min(pos, controlRoot.selectionEnd - 1), controlRoot.selectionEnd); + } else { + controlRoot.select(controlRoot.selectionStart, Math.max(pos, controlRoot.selectionStart + 1)); + } + } else { + controlRoot.cursorPosition = pos; + } + } + } + } +} + diff --git a/src/declarativeimports/plasmacomponents3/private/MobileTextActionsToolBar.qml b/src/declarativeimports/plasmacomponents3/private/MobileTextActionsToolBar.qml new file mode 100644 --- /dev/null +++ b/src/declarativeimports/plasmacomponents3/private/MobileTextActionsToolBar.qml @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018 by Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 2.010-1301, USA. + */ + +pragma Singleton + +import QtQuick 2.1 +import QtQuick.Layouts 1.2 +import QtQuick.Window 2.2 +import QtQuick.Controls @QQC2_VERSION@ +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.kirigami 2.5 as Kirigami + +Popup { + id: root + + property Item controlRoot + parent: controlRoot ? controlRoot.Window.contentItem : undefined + modal: false + focus: false + closePolicy: Popup.NoAutoClose + + x: controlRoot ? Math.min(Math.max(0, controlRoot.mapToItem(root.parent, controlRoot.positionToRectangle(controlRoot.selectionStart).x, 0).x - root.width/2), controlRoot.Window.contentItem.width - root.width) : 0 + + y: { + if (!controlRoot) { + return false; + } + var desiredY = controlRoot.mapToItem(root.parent, 0, controlRoot.positionToRectangle(controlRoot.selectionStart).y).y - root.height; + + if (desiredY >= 0) { + return Math.min(desiredY, controlRoot.Window.contentItem.height - root.height); + } else { + return Math.min(Math.max(0, controlRoot.mapToItem(root.parent, 0, controlRoot.positionToRectangle(controlRoot.selectionEnd).y + Math.round(units.gridUnit*1.5)).y), controlRoot.Window.contentItem.height - root.height); + } + } + + + visible: controlRoot ? Kirigami.Settings.tabletMode && (controlRoot.selectedText.length > 0 || controlRoot.canPaste) : false + + width: contentItem.implicitWidth + leftPadding + rightPadding + + contentItem: RowLayout { + ToolButton { + focusPolicy: Qt.NoFocus + icon.name: "edit-cut" + visible: controlRoot.selectedText.length > 0 + onClicked: { + controlRoot.cut(); + } + } + ToolButton { + focusPolicy: Qt.NoFocus + icon.name: "edit-copy" + visible: controlRoot.selectedText.length > 0 + onClicked: { + controlRoot.copy(); + } + } + ToolButton { + focusPolicy: Qt.NoFocus + icon.name: "edit-paste" + onClicked: { + controlRoot.paste(); + } + } + } +} + diff --git a/src/declarativeimports/plasmacomponents3/private/qmldir b/src/declarativeimports/plasmacomponents3/private/qmldir new file mode 100644 --- /dev/null +++ b/src/declarativeimports/plasmacomponents3/private/qmldir @@ -0,0 +1,7 @@ + +singleton MobileTextActionsToolBar 1.0 MobileTextActionsToolBar.qml +ButtonShadow 1.0 ButtonShadow.qml +DefaultListItemBackground 1.0 DefaultListItemBackground.qml +MobileCursor 1.0 MobileCursor.qml +RoundShadow 1.0 RoundShadow.qml +TextFieldFocus 1.0 TextFieldFocus.qml