diff --git a/src/declarativeimports/plasmacomponents3/TextArea.qml b/src/declarativeimports/plasmacomponents3/TextArea.qml index 8d5f969bb..b19d7667c 100644 --- a/src/declarativeimports/plasmacomponents3/TextArea.qml +++ b/src/declarativeimports/plasmacomponents3/TextArea.qml @@ -1,78 +1,113 @@ /* * Copyright 2016 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 02110-1301, USA. */ import QtQuick 2.6 import QtQuick.Window 2.2 import QtQuick.Controls @QQC2_VERSION@ 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 implicitWidth: Math.max(contentWidth + leftPadding + rightPadding, background ? background.implicitWidth : 0, placeholder.implicitWidth + leftPadding + rightPadding) implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, background ? background.implicitHeight : 0, placeholder.implicitHeight + topPadding + bottomPadding) padding: 6 color: theme.viewTextColor selectionColor: theme.highlightColor selectedTextColor: theme.highlightedTextColor 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 y: control.topPadding width: control.width - (control.leftPadding + control.rightPadding) height: control.height - (control.topPadding + control.bottomPadding) text: control.placeholderText font: control.font color: theme.viewTextColor horizontalAlignment: control.horizontalAlignment verticalAlignment: control.verticalAlignment visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) elide: Text.ElideRight } background: Item { Private.TextFieldFocus { state: control.activeFocus ? "focus" : (control.hovered ? "hover" : "hidden") anchors.fill: parent } PlasmaCore.FrameSvgItem { id: base anchors.fill: parent imagePath: "widgets/lineedit" prefix: "base" } } } diff --git a/src/declarativeimports/plasmacomponents3/TextField.qml b/src/declarativeimports/plasmacomponents3/TextField.qml index 6d833d9f8..06fa064e8 100644 --- a/src/declarativeimports/plasmacomponents3/TextField.qml +++ b/src/declarativeimports/plasmacomponents3/TextField.qml @@ -1,77 +1,110 @@ /* * Copyright 2016 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 02110-1301, USA. */ import QtQuick 2.6 import QtQuick.Window 2.2 import QtQuick.Controls @QQC2_VERSION@ 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 implicitWidth: Math.max(units.gridUnit * 8, placeholderText ? placeholder.implicitWidth + leftPadding + rightPadding : 0) || contentWidth + leftPadding + rightPadding implicitHeight: units.gridUnit * 1.6 padding: 6 color: theme.viewTextColor selectionColor: theme.highlightColor 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 y: control.topPadding width: control.width - (control.leftPadding + control.rightPadding) height: control.height - (control.topPadding + control.bottomPadding) text: control.placeholderText font: control.font color: theme.viewTextColor opacity: 0.5 horizontalAlignment: control.horizontalAlignment verticalAlignment: control.verticalAlignment visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter) elide: Text.ElideRight } background: Item { Private.TextFieldFocus { state: control.activeFocus ? "focus" : (control.hovered ? "hover" : "hidden") anchors.fill: parent } PlasmaCore.FrameSvgItem { id: base anchors.fill: parent imagePath: "widgets/lineedit" prefix: "base" } } } diff --git a/src/declarativeimports/plasmacomponents3/private/MobileCursor.qml b/src/declarativeimports/plasmacomponents3/private/MobileCursor.qml new file mode 100644 index 000000000..246e99859 --- /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 index 000000000..d4df4f1c8 --- /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 index 000000000..1a9e8d038 --- /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