diff --git a/org.kde.desktop/ComboBox.qml b/org.kde.desktop/ComboBox.qml index dfb5ac5..a5c5d9a 100644 --- a/org.kde.desktop/ComboBox.qml +++ b/org.kde.desktop/ComboBox.qml @@ -1,244 +1,247 @@ /* * Copyright 2017 Marco Martin * Copyright 2017 The Qt Company Ltd. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPLv3 included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 3 requirements * will be met: https://www.gnu.org/licenses/lgpl.html. * * GNU General Public License Usage * Alternatively, this file may be used under the terms of the GNU * General Public License version 2.0 or later as published by the Free * Software Foundation and appearing in the file LICENSE.GPL included in * the packaging of this file. Please review the following information to * ensure the GNU General Public License version 2.0 requirements will be * met: http://www.gnu.org/licenses/gpl-2.0.html. */ import QtQuick 2.6 import QtQuick.Window 2.2 import QtQuick.Templates @QQC2_VERSION@ as T import QtQuick.Controls @QQC2_VERSION@ as Controls import org.kde.qqc2desktopstyle.private 1.0 as StylePrivate import QtGraphicalEffects 1.0 import org.kde.kirigami 2.4 as Kirigami import "private" as Private T.ComboBox { id: controlRoot @DISABLE_UNDER_QQC2_2_4@ palette: Kirigami.Theme.palette //NOTE: typeof necessary to not have warnings on Qt 5.7 Kirigami.Theme.colorSet: typeof(editable) != "undefined" && editable ? Kirigami.Theme.View : Kirigami.Theme.Button Kirigami.Theme.inherit: false implicitWidth: Math.max(200, background.implicitWidth + leftPadding + rightPadding) implicitHeight: background.implicitHeight baselineOffset: contentItem.y + contentItem.baselineOffset hoverEnabled: true padding: 5 leftPadding: controlRoot.editable && controlRoot.mirrored ? 24 : padding rightPadding: controlRoot.editable && !controlRoot.mirrored ? 24 : padding delegate: ItemDelegate { width: controlRoot.popup.width text: controlRoot.textRole ? (Array.isArray(controlRoot.model) ? modelData[controlRoot.textRole] : model[controlRoot.textRole]) : modelData highlighted: mouseArea.pressed ? listView.currentIndex == index : controlRoot.highlightedIndex == index property bool separatorVisible: false Kirigami.Theme.colorSet: controlRoot.Kirigami.Theme.inherit ? controlRoot.Kirigami.Theme.colorSet : Kirigami.Theme.View Kirigami.Theme.inherit: controlRoot.Kirigami.Theme.inherit onClicked: { controlRoot.currentIndex = index; controlRoot.popup.visible = false; } } indicator: Item {} contentItem: MouseArea { id: mouseArea anchors.fill: parent acceptedButtons: Qt.LeftButton preventStealing: true property int indexUnderMouse: -1 onWheel: { if (wheel.pixelDelta.y < 0 || wheel.angleDelta.y < 0) { controlRoot.currentIndex = Math.min(controlRoot.currentIndex + 1, delegateModel.count -1); } else { controlRoot.currentIndex = Math.max(controlRoot.currentIndex - 1, 0); } controlRoot.activated(controlRoot.currentIndex); } onPressed: { indexUnderMouse = -1; listView.currentIndex = controlRoot.highlightedIndex controlRoot.down = true; controlRoot.pressed = true; controlRoot.popup.visible = !controlRoot.popup.visible; } onReleased: { if (!containsMouse) { controlRoot.down = false; controlRoot.pressed = false; controlRoot.popup.visible = false; } if (indexUnderMouse > -1) { controlRoot.currentIndex = indexUnderMouse; controlRoot.activated(indexUnderMouse); } } onCanceled: { controlRoot.down = false; controlRoot.pressed = false; } onPositionChanged: { var pos = listView.mapFromItem(this, mouse.x, mouse.y); indexUnderMouse = listView.indexAt(pos.x, pos.y); listView.currentIndex = indexUnderMouse; } Connections { target: popup onClosed: { controlRoot.down = false; controlRoot.pressed = false; } } T.TextField { id: textField padding: 0 anchors { fill:parent leftMargin: controlRoot.leftPadding rightMargin: controlRoot.rightPadding topMargin: controlRoot.topPadding bottomMargin: controlRoot.bottomPadding } text: controlRoot.editable ? controlRoot.editText : controlRoot.displayText enabled: controlRoot.editable autoScroll: controlRoot.editable readOnly: controlRoot.down visible: typeof(controlRoot.editable) != "undefined" && controlRoot.editable inputMethodHints: controlRoot.inputMethodHints validator: controlRoot.validator // 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 color: controlRoot.enabled ? Kirigami.Theme.textColor : Kirigami.Theme.disabledTextColor selectionColor: Kirigami.Theme.highlightColor selectedTextColor: Kirigami.Theme.highlightedTextColor selectByMouse: !Kirigami.Settings.tabletMode cursorDelegate: Kirigami.Settings.tabletMode ? mobileCursor : null font: controlRoot.font horizontalAlignment: Text.AlignLeft verticalAlignment: Text.AlignVCenter opacity: controlRoot.enabled ? 1 : 0.3 onFocusChanged: { if (focus) { Private.MobileTextActionsToolBar.controlRoot = textField; } } + onTextChanged: Private.MobileTextActionsToolBar.shouldBeVisible = false; + onPressed: Private.MobileTextActionsToolBar.shouldBeVisible = true; + onPressAndHold: { if (!Kirigami.Settings.tabletMode) { return; } forceActiveFocus(); cursorPosition = positionAt(event.x, event.y); selectWord(); } } } Component { id: mobileCursor Private.MobileCursor { target: textField } } Private.MobileCursor { target: textField selectionStartHandle: true property var rect: target.positionToRectangle(target.selectionStart) x: rect.x + 5 y: rect.y + 6 } background: StylePrivate.StyleItem { id: styleitem control: controlRoot elementType: "combobox" anchors.fill: parent hover: controlRoot.hovered || controlRoot.pressed on: controlRoot.pressed hasFocus: controlRoot.activeFocus enabled: controlRoot.enabled // contentHeight as in QComboBox magic numbers taken from QQC1 style contentHeight: Math.max(Math.ceil(textHeight("")), 14) + 2 text: controlRoot.displayText properties: { "editable" : control.editable } } popup: T.Popup { y: controlRoot.height width: Math.max(controlRoot.width, 150) implicitHeight: contentItem.implicitHeight topMargin: 6 bottomMargin: 6 Kirigami.Theme.colorSet: Kirigami.Theme.View Kirigami.Theme.inherit: controlRoot.Kirigami.Theme.inherit modal: true contentItem: ListView { id: listView // this causes us to load at least one delegate // this is essential in guessing the contentHeight // which is needed to initially resize the popup cacheBuffer: 1 implicitHeight: contentHeight model: controlRoot.delegateModel delegate: controlRoot.delegate currentIndex: controlRoot.highlightedIndex highlightRangeMode: ListView.ApplyRange highlightMoveDuration: 0 T.ScrollBar.vertical: Controls.ScrollBar { } } background: Rectangle { anchors { fill: parent margins: -1 } radius: 2 color: Kirigami.Theme.backgroundColor property color borderColor: Kirigami.Theme.textColor border.color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3) layer.enabled: true layer.effect: DropShadow { transparentBorder: true radius: 8 samples: 8 horizontalOffset: 0 verticalOffset: 2 color: Qt.rgba(0, 0, 0, 0.3) } } } } diff --git a/org.kde.desktop/TextArea.qml b/org.kde.desktop/TextArea.qml index 3d4d453..628037a 100644 --- a/org.kde.desktop/TextArea.qml +++ b/org.kde.desktop/TextArea.qml @@ -1,116 +1,119 @@ /* * Copyright 2017 Marco Martin * Copyright 2017 The Qt Company Ltd. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPLv3 included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 3 requirements * will be met: https://www.gnu.org/licenses/lgpl.html. * * GNU General Public License Usage * Alternatively, this file may be used under the terms of the GNU * General Public License version 2.0 or later as published by the Free * Software Foundation and appearing in the file LICENSE.GPL included in * the packaging of this file. Please review the following information to * ensure the GNU General Public License version 2.0 requirements will be * met: http://www.gnu.org/licenses/gpl-2.0.html. */ import QtQuick 2.6 import QtQuick.Window 2.1 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 @DISABLE_UNDER_QQC2_2_4@ palette: Kirigami.Theme.palette Kirigami.Theme.colorSet: Kirigami.Theme.View Kirigami.Theme.inherit: false 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: Kirigami.Theme.textColor 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: !Kirigami.Settings.tabletMode cursorDelegate: Kirigami.Settings.tabletMode ? mobileCursor : null Component { id: mobileCursor Private.MobileCursor { target: controlRoot } } + onTextChanged: Private.MobileTextActionsToolBar.shouldBeVisible = false; + onPressed: Private.MobileTextActionsToolBar.shouldBeVisible = true; + onPressAndHold: { if (!Kirigami.Settings.tabletMode) { return; } forceActiveFocus(); cursorPosition = positionAt(event.x, event.y); selectWord(); } Private.MobileCursor { target: controlRoot selectionStartHandle: true property var rect: target.positionToRectangle(target.selectionStart) 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 } background: StylePrivate.StyleItem { id: style control: controlRoot elementType: "edit" implicitWidth: 200 implicitHeight: 22 sunken: true hasFocus: controlRoot.activeFocus hover: controlRoot.hovered } } diff --git a/org.kde.desktop/TextField.qml b/org.kde.desktop/TextField.qml index 3d372a6..e4ecbf7 100644 --- a/org.kde.desktop/TextField.qml +++ b/org.kde.desktop/TextField.qml @@ -1,112 +1,115 @@ /* * Copyright 2017 Marco Martin * Copyright 2017 The Qt Company Ltd. * * GNU Lesser General Public License Usage * Alternatively, this file may be used under the terms of the GNU Lesser * General Public License version 3 as published by the Free Software * Foundation and appearing in the file LICENSE.LGPLv3 included in the * packaging of this file. Please review the following information to * ensure the GNU Lesser General Public License version 3 requirements * will be met: https://www.gnu.org/licenses/lgpl.html. * * GNU General Public License Usage * Alternatively, this file may be used under the terms of the GNU * General Public License version 2.0 or later as published by the Free * Software Foundation and appearing in the file LICENSE.GPL included in * the packaging of this file. Please review the following information to * ensure the GNU General Public License version 2.0 requirements will be * met: http://www.gnu.org/licenses/gpl-2.0.html. */ import QtQuick 2.6 import QtQuick.Window 2.1 import QtQuick.Controls @QQC2_VERSION@ as Controls 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 @DISABLE_UNDER_QQC2_2_4@ palette: Kirigami.Theme.palette Kirigami.Theme.colorSet: Kirigami.Theme.View Kirigami.Theme.inherit: false implicitWidth: Math.max(200, placeholderText ? placeholder.implicitWidth + leftPadding + rightPadding : 0) || contentWidth + leftPadding + rightPadding implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, background ? background.implicitHeight : 0, placeholder.implicitHeight + topPadding + bottomPadding) padding: 6 color: controlRoot.enabled ? Kirigami.Theme.textColor : Kirigami.Theme.disabledTextColor 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: !Kirigami.Settings.tabletMode cursorDelegate: Kirigami.Settings.tabletMode ? mobileCursor : null Component { id: mobileCursor Private.MobileCursor { target: controlRoot } } onFocusChanged: { if (focus) { Private.MobileTextActionsToolBar.controlRoot = controlRoot; } } + onTextChanged: Private.MobileTextActionsToolBar.shouldBeVisible = false; + onPressed: Private.MobileTextActionsToolBar.shouldBeVisible = true; + onPressAndHold: { if (!Kirigami.Settings.tabletMode) { return; } forceActiveFocus(); cursorPosition = positionAt(event.x, event.y); selectWord(); } Private.MobileCursor { target: controlRoot selectionStartHandle: true property var rect: controlRoot.positionToRectangle(controlRoot.selectionStart) x: rect.x + target.padding y: rect.y + target.padding } Controls.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 } background: StylePrivate.StyleItem { id: style control: controlRoot elementType: "edit" sunken: true hasFocus: controlRoot.activeFocus hover: controlRoot.hovered } } diff --git a/org.kde.desktop/private/MobileCursor.qml b/org.kde.desktop/private/MobileCursor.qml index dbd7f99..93c8565 100644 --- a/org.kde.desktop/private/MobileCursor.qml +++ b/org.kde.desktop/private/MobileCursor.qml @@ -1,76 +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.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 target property bool selectionStartHandle: false visible: Kirigami.Settings.tabletMode && ((target.activeFocus && !selectionStartHandle) || target.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 + visible: MobileTextActionsToolBar.shouldBeVisible 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(target, mouse.x, mouse.y); pos = target.positionAt(pos.x, pos.y); if (target.selectedText.length > 0) { if (selectionStartHandle) { target.select(Math.min(pos, target.selectionEnd - 1), target.selectionEnd); } else { target.select(target.selectionStart, Math.max(pos, target.selectionStart + 1)); } } else { target.cursorPosition = pos; } } } } } diff --git a/org.kde.desktop/private/MobileTextActionsToolBar.qml b/org.kde.desktop/private/MobileTextActionsToolBar.qml index e1e0043..7ab1c1b 100644 --- a/org.kde.desktop/private/MobileTextActionsToolBar.qml +++ b/org.kde.desktop/private/MobileTextActionsToolBar.qml @@ -1,83 +1,85 @@ /* * 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 + property bool shouldBeVisible: false 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 + visible: controlRoot ? shouldBeVisible && 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 + visible: controlRoot.selectedText.length > 0 && (!controlRoot.hasOwnProperty("echoMode") || controlRoot.echoMode === TextInput.Normal) onClicked: { controlRoot.cut(); } } ToolButton { focusPolicy: Qt.NoFocus icon.name: "edit-copy" - visible: controlRoot.selectedText.length > 0 + visible: controlRoot.selectedText.length > 0 && (!controlRoot.hasOwnProperty("echoMode") || controlRoot.echoMode === TextInput.Normal) onClicked: { controlRoot.copy(); } } ToolButton { focusPolicy: Qt.NoFocus icon.name: "edit-paste" + visible: controlRoot.canPaste onClicked: { controlRoot.paste(); } } } }