diff --git a/org.kde.desktop/TextArea.qml b/org.kde.desktop/TextArea.qml --- a/org.kde.desktop/TextArea.qml +++ b/org.kde.desktop/TextArea.qml @@ -25,6 +25,7 @@ import QtQuick.Templates @QQC2_VERSION@ as T import org.kde.kirigami 2.4 as Kirigami import org.kde.qqc2desktopstyle.private 1.0 as StylePrivate +import "private" as Private T.TextArea { id: controlRoot @@ -45,12 +46,45 @@ selectionColor: Kirigami.Theme.highlightColor selectedTextColor: Kirigami.Theme.highlightedTextColor wrapMode: Text.WordWrap + hoverEnabled: !Kirigami.Settings.tabletMode verticalAlignment: TextEdit.AlignTop // 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: true + + selectByMouse: !Kirigami.Settings.tabletMode + + cursorDelegate: Kirigami.Settings.tabletMode ? mobileCursor : undefined + Component { + id: mobileCursor + Private.MobileCursor { + control: controlRoot + } + } + + onPressAndHold: { + if (!Kirigami.Settings.tabletMode) { + return; + } + forceActiveFocus(); + cursorPosition = positionAt(event.x, event.y); + selectWord(); + } + + Private.MobileCursor { + control: controlRoot + selectionStartHandle: true + property var rect: control.positionToRectangle(control.selectionStart) + x: rect.x + y: rect.y + } + + onFocusChanged: { + if (focus) { + Private.MobileTextActionsToolBar.controlRoot = controlRoot; + } + } Label { id: placeholder diff --git a/org.kde.desktop/TextField.qml b/org.kde.desktop/TextField.qml --- a/org.kde.desktop/TextField.qml +++ b/org.kde.desktop/TextField.qml @@ -26,6 +26,7 @@ import QtQuick.Templates @QQC2_VERSION@ as T import org.kde.kirigami 2.4 as Kirigami import org.kde.qqc2desktopstyle.private 1.0 as StylePrivate +import "private" as Private T.TextField { id: controlRoot @@ -46,11 +47,42 @@ selectionColor: Kirigami.Theme.highlightColor selectedTextColor: Kirigami.Theme.highlightedTextColor verticalAlignment: TextInput.AlignVCenter + 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: true + selectByMouse: !Kirigami.Settings.tabletMode + + cursorDelegate: Kirigami.Settings.tabletMode ? mobileCursor : undefined + Component { + id: mobileCursor + Private.MobileCursor { + control: controlRoot + } + } + onFocusChanged: { + if (focus) { + Private.MobileTextActionsToolBar.controlRoot = controlRoot; + } + } + + onPressAndHold: { + if (!Kirigami.Settings.tabletMode) { + return; + } + forceActiveFocus(); + cursorPosition = positionAt(event.x, event.y); + selectWord(); + } + Private.MobileCursor { + control: controlRoot + 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 + } Controls.Label { id: placeholder diff --git a/org.kde.desktop/private/MobileCursor.qml b/org.kde.desktop/private/MobileCursor.qml new file mode 100644 --- /dev/null +++ b/org.kde.desktop/private/MobileCursor.qml @@ -0,0 +1,76 @@ +/* + * 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.kirigami 2.5 as Kirigami + +Item { + id: root + width: 1 //<-important that this is actually a single device pixel + height: Kirigami.Units.gridUnit + + property Item control + + property bool selectionStartHandle: false + + visible: Kirigami.Settings.tabletMode && ((control.focus && !selectionStartHandle) || control.selectedText.length > 0) + + Rectangle { + width: Math.round(Kirigami.Units.devicePixelRatio * 3) + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + bottom: parent.bottom + } + color: Qt.tint(Kirigami.Theme.highlightColor, Qt.rgba(1,1,1,0.4)) + radius: width + Rectangle { + width: Math.round(Kirigami.Units.gridUnit/1.5) + height: width + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.bottom + } + radius: width + color: Qt.tint(Kirigami.Theme.highlightColor, Qt.rgba(1,1,1,0.4)) + } + MouseArea { + anchors { + fill: parent + margins: -Kirigami.Units.gridUnit + } + preventStealing: true + onPositionChanged: { + var pos = mapToItem(control, mouse.x, mouse.y); + pos = control.positionAt(pos.x, pos.y); + + if (control.selectedText.length > 0) { + if (selectionStartHandle) { + control.select(Math.min(pos, control.selectionEnd - 1), control.selectionEnd); + } else { + control.select(control.selectionStart, Math.max(pos, control.selectionStart + 1)); + } + } else { + control.cursorPosition = pos; + } + } + } + } +} + diff --git a/org.kde.desktop/private/MobileTextActionsToolBar.qml b/org.kde.desktop/private/MobileTextActionsToolBar.qml new file mode 100644 --- /dev/null +++ b/org.kde.desktop/private/MobileTextActionsToolBar.qml @@ -0,0 +1,83 @@ +/* + * 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.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(Kirigami.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/org.kde.desktop/private/qmldir b/org.kde.desktop/private/qmldir new file mode 100644 --- /dev/null +++ b/org.kde.desktop/private/qmldir @@ -0,0 +1,5 @@ + +singleton MobileTextActionsToolBar 1.0 MobileTextActionsToolBar.qml +DefaultListItemBackground 1.0 DefaultListItemBackground.qml +MobileCursor 1.0 MobileCursor.qml +FocusRect 1.0 FocusRect.qml