From 9922c8d5d23df5538e2cc7fcbddace28e49cf144 Mon Sep 17 00:00:00 2001 From: Devin Lin Date: Tue, 21 Jun 2022 18:38:21 -0400 Subject: [PATCH] components: Introduce ExtendedAbstractButton, port homescreen to it --- components/mobileshell/mobileshellplugin.cpp | 1 + .../qml/components/ExtendedAbstractButton.qml | 65 +++++++++ components/mobileshell/resources.qrc | 1 + .../default/applicationlistmodel.cpp | 1 - .../package/contents/ui/HomeDelegate.qml | 4 +- .../ui/appdrawer/DrawerGridDelegate.qml | 4 +- .../ui/appdrawer/DrawerListDelegate.qml | 4 +- .../halcyon/applicationlistmodel.cpp | 1 - .../contents/ui/DrawerListDelegate.qml | 137 +++++++++--------- .../package/contents/ui/GridAppDelegate.qml | 20 ++- 10 files changed, 161 insertions(+), 77 deletions(-) create mode 100644 components/mobileshell/qml/components/ExtendedAbstractButton.qml diff --git a/components/mobileshell/mobileshellplugin.cpp b/components/mobileshell/mobileshellplugin.cpp index 7ec6efae..0da279fc 100644 --- a/components/mobileshell/mobileshellplugin.cpp +++ b/components/mobileshell/mobileshellplugin.cpp @@ -69,6 +69,7 @@ void MobileShellPlugin::registerTypes(const char *uri) // /components qmlRegisterType(resolvePath("components/BaseItem.qml"), uri, 1, 0, "BaseItem"); + qmlRegisterType(resolvePath("components/ExtendedAbstractButton.qml"), uri, 1, 0, "ExtendedAbstractButton"); qmlRegisterSingletonType(resolvePath("components/Haptics.qml"), uri, 1, 0, "Haptics"); qmlRegisterType(resolvePath("components/StartupFeedback.qml"), uri, 1, 0, "StartupFeedback"); qmlRegisterType(resolvePath("components/VelocityCalculator.qml"), uri, 1, 0, "VelocityCalculator"); diff --git a/components/mobileshell/qml/components/ExtendedAbstractButton.qml b/components/mobileshell/qml/components/ExtendedAbstractButton.qml new file mode 100644 index 00000000..fb9a8c48 --- /dev/null +++ b/components/mobileshell/qml/components/ExtendedAbstractButton.qml @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: 2022 Devin Lin +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick 2.15 +import QtQuick.Controls 2.15 as QQC2 + +/** + * This component is an AbstractButton with some added functionality to simulate a MouseArea. + * + * The hovered property of AbstractButton is much more accurate than the containsMouse property of MouseArea, + * and so this is useful for creating custom buttons. + */ + +QQC2.AbstractButton { + id: root + + /** + * The cursor shape when the mouse is over the button. + */ + property alias cursorShape: mouseArea.cursorShape + + /** + * This property holds the elapsed time in milliseconds before pressAndHold is emitted. + */ + property real pressAndHoldInterval: 1000 + + /** + * Signal that is emitted when the button has been held for a certain amount of time. + */ + signal pressAndHold() + + /** + * Signal that is emitted when the right click button is pressed. + */ + signal rightClickPressed() + + Timer { + id: timer + interval: pressAndHoldInterval + repeat: false + running: false + onTriggered: root.pressAndHold() + } + + onPressedChanged: { + if (pressed) { + timer.restart(); + } else { + timer.stop(); + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + acceptedButtons: Qt.LeftButton | Qt.RightButton + onPressed: { + if (mouse.button === Qt.RightButton) { + root.rightClickPressed(); + } else { + mouse.accepted = false; + } + } + } +} diff --git a/components/mobileshell/resources.qrc b/components/mobileshell/resources.qrc index df7b502a..ca8a5ffb 100644 --- a/components/mobileshell/resources.qrc +++ b/components/mobileshell/resources.qrc @@ -21,6 +21,7 @@ qml/actiondrawer/PortraitContentContainer.qml qml/components/BaseItem.qml + qml/components/ExtendedAbstractButton.qml qml/components/Haptics.qml qml/components/HapticsEffectWrapper.qml qml/components/MarqueeLabel.qml diff --git a/containments/homescreens/default/applicationlistmodel.cpp b/containments/homescreens/default/applicationlistmodel.cpp index ffcb0347..73e22510 100644 --- a/containments/homescreens/default/applicationlistmodel.cpp +++ b/containments/homescreens/default/applicationlistmodel.cpp @@ -63,7 +63,6 @@ QHash ApplicationListModel::roleNames() const void ApplicationListModel::sycocaDbChanged() { - m_applicationList.clear(); loadApplications(); } diff --git a/containments/homescreens/default/package/contents/ui/HomeDelegate.qml b/containments/homescreens/default/package/contents/ui/HomeDelegate.qml index ac268166..3cd3756a 100644 --- a/containments/homescreens/default/package/contents/ui/HomeDelegate.qml +++ b/containments/homescreens/default/package/contents/ui/HomeDelegate.qml @@ -100,7 +100,7 @@ ContainmentLayoutManager.ItemContainer { } } - contentItem: MouseArea { + contentItem: MobileShell.ExtendedAbstractButton { id: mouseArea // grow/shrink animation @@ -187,7 +187,7 @@ ContainmentLayoutManager.ItemContainer { // darken effect when hovered/pressed layer { - enabled: mouseArea.pressed || mouseArea.containsMouse + enabled: mouseArea.pressed || mouseArea.hovered effect: ColorOverlay { color: Qt.rgba(0, 0, 0, 0.3) } diff --git a/containments/homescreens/default/package/contents/ui/appdrawer/DrawerGridDelegate.qml b/containments/homescreens/default/package/contents/ui/appdrawer/DrawerGridDelegate.qml index 3b777d07..9f8d1497 100644 --- a/containments/homescreens/default/package/contents/ui/appdrawer/DrawerGridDelegate.qml +++ b/containments/homescreens/default/package/contents/ui/appdrawer/DrawerGridDelegate.qml @@ -17,7 +17,7 @@ import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager import org.kde.plasma.private.mobileshell 1.0 as MobileShell -MouseArea { +MobileShell.ExtendedAbstractButton { id: delegate width: GridView.view.cellWidth height: GridView.view.cellHeight @@ -129,7 +129,7 @@ MouseArea { // darken effect when hovered/pressed layer { - enabled: delegate.pressed || delegate.containsMouse + enabled: delegate.pressed || delegate.hovered effect: ColorOverlay { color: Qt.rgba(0, 0, 0, 0.3) } diff --git a/containments/homescreens/default/package/contents/ui/appdrawer/DrawerListDelegate.qml b/containments/homescreens/default/package/contents/ui/appdrawer/DrawerListDelegate.qml index e3a02b45..2444e788 100644 --- a/containments/homescreens/default/package/contents/ui/appdrawer/DrawerListDelegate.qml +++ b/containments/homescreens/default/package/contents/ui/appdrawer/DrawerListDelegate.qml @@ -18,7 +18,7 @@ import org.kde.kquickcontrolsaddons 2.0 import org.kde.plasma.private.containmentlayoutmanager 1.0 as ContainmentLayoutManager import org.kde.plasma.private.mobileshell 1.0 as MobileShell -MouseArea { +MobileShell.ExtendedAbstractButton { id: delegate property int reservedSpaceForLabel property alias iconItem: icon @@ -45,7 +45,7 @@ MouseArea { Rectangle { anchors.fill: parent - color: delegate.pressed ? Qt.rgba(255, 255, 255, 0.2) : (delegate.containsMouse ? Qt.rgba(255, 255, 255, 0.05) : "transparent") + color: delegate.pressed ? Qt.rgba(255, 255, 255, 0.2) : (delegate.hovered ? Qt.rgba(255, 255, 255, 0.05) : "transparent") Behavior on color { ColorAnimation { duration: PlasmaCore.Units.shortDuration } } diff --git a/containments/homescreens/halcyon/applicationlistmodel.cpp b/containments/homescreens/halcyon/applicationlistmodel.cpp index ce8276ad..70b99c5b 100644 --- a/containments/homescreens/halcyon/applicationlistmodel.cpp +++ b/containments/homescreens/halcyon/applicationlistmodel.cpp @@ -38,7 +38,6 @@ QHash ApplicationListModel::roleNames() const void ApplicationListModel::sycocaDbChanged() { - m_applicationList.clear(); loadApplications(); } diff --git a/containments/homescreens/halcyon/package/contents/ui/DrawerListDelegate.qml b/containments/homescreens/halcyon/package/contents/ui/DrawerListDelegate.qml index d01fe7ab..357a55ff 100644 --- a/containments/homescreens/halcyon/package/contents/ui/DrawerListDelegate.qml +++ b/containments/homescreens/halcyon/package/contents/ui/DrawerListDelegate.qml @@ -17,7 +17,7 @@ import org.kde.phone.homescreen.halcyon 1.0 as Halcyon import org.kde.kirigami 2.19 as Kirigami -MouseArea { +MobileShell.ExtendedAbstractButton { id: delegate property alias iconItem: icon @@ -44,10 +44,14 @@ MouseArea { application.runApplication(); } - onPressAndHold: { + function openContextMenu() { dialogLoader.active = true; dialogLoader.item.open(); } + + hoverEnabled: true + onPressAndHold: openContextMenu() + onRightClickPressed: openContextMenu() onClicked: { // launch app @@ -57,7 +61,6 @@ MouseArea { delegate.launch(delegate.x + (PlasmaCore.Units.smallSpacing * 2), delegate.y + (PlasmaCore.Units.smallSpacing * 2), icon.source, applicationName, applicationStorageId); } } - hoverEnabled: true Loader { id: dialogLoader @@ -65,6 +68,7 @@ MouseArea { sourceComponent: PlasmaComponents.Menu { title: label.text + closePolicy: PlasmaComponents.Menu.CloseOnReleaseOutside | PlasmaComponents.Menu.CloseOnEscape PlasmaComponents.MenuItem { icon.name: "emblem-favorite" @@ -77,80 +81,83 @@ MouseArea { } } - Rectangle { - anchors.fill: parent - - radius: height / 2 - - color: delegate.pressed ? Qt.rgba(255, 255, 255, 0.2) : (delegate.containsMouse ? Qt.rgba(255, 255, 255, 0.1) : "transparent") + background: Rectangle { + radius: height / 2 + color: delegate.pressed ? Qt.rgba(255, 255, 255, 0.2) : (delegate.hovered ? Qt.rgba(255, 255, 255, 0.1) : "transparent") } - RowLayout { - anchors { - fill: parent - leftMargin: PlasmaCore.Units.smallSpacing * 2 - topMargin: PlasmaCore.Units.smallSpacing - rightMargin: PlasmaCore.Units.smallSpacing * 2 - bottomMargin: PlasmaCore.Units.smallSpacing - } - spacing: 0 + contentItem: Item { + implicitHeight: rowLayout.height + rowLayout.anchors.topMargin + rowLayout.anchors.bottomMargin + implicitWidth: rowLayout.width + rowLayout.anchors.rightMargin + rowLayout.anchors.leftMargin + + RowLayout { + id: rowLayout + anchors { + fill: parent + leftMargin: PlasmaCore.Units.smallSpacing * 2 + topMargin: PlasmaCore.Units.smallSpacing + rightMargin: PlasmaCore.Units.smallSpacing * 2 + bottomMargin: PlasmaCore.Units.smallSpacing + } + spacing: 0 - PlasmaCore.IconItem { - id: icon + PlasmaCore.IconItem { + id: icon - Layout.alignment: Qt.AlignLeft - Layout.minimumWidth: Layout.minimumHeight - Layout.preferredWidth: Layout.minimumHeight - Layout.minimumHeight: parent.height - Layout.preferredHeight: Layout.minimumHeight + Layout.alignment: Qt.AlignLeft + Layout.minimumWidth: Layout.minimumHeight + Layout.preferredWidth: Layout.minimumHeight + Layout.minimumHeight: parent.height + Layout.preferredHeight: Layout.minimumHeight - usesPlasmaTheme: false - source: applicationIcon + usesPlasmaTheme: false + source: applicationIcon - Rectangle { - anchors { - horizontalCenter: parent.horizontalCenter - bottom: parent.bottom + Rectangle { + anchors { + horizontalCenter: parent.horizontalCenter + bottom: parent.bottom + } + visible: application ? application.running : false + radius: width + width: PlasmaCore.Units.smallSpacing + height: width + color: PlasmaCore.Theme.highlightColor + } + + layer.enabled: true + layer.effect: DropShadow { + verticalOffset: 1 + radius: 4 + samples: 6 + color: Qt.rgba(0, 0, 0, 0.5) } - visible: application.running - radius: width - width: PlasmaCore.Units.smallSpacing - height: width - color: PlasmaCore.Theme.highlightColor } - - layer.enabled: true - layer.effect: DropShadow { - verticalOffset: 1 - radius: 4 - samples: 6 - color: Qt.rgba(0, 0, 0, 0.5) - } - } - PlasmaComponents.Label { - id: label - visible: text.length > 0 + PlasmaComponents.Label { + id: label + visible: text.length > 0 - Layout.fillWidth: true - Layout.leftMargin: PlasmaCore.Units.smallSpacing * 2 - Layout.rightMargin: PlasmaCore.Units.largeSpacing - wrapMode: Text.WordWrap - maximumLineCount: 1 - elide: Text.ElideRight + Layout.fillWidth: true + Layout.leftMargin: PlasmaCore.Units.smallSpacing * 2 + Layout.rightMargin: PlasmaCore.Units.largeSpacing + wrapMode: Text.WordWrap + maximumLineCount: 1 + elide: Text.ElideRight - text: applicationName + text: applicationName - font.pointSize: PlasmaCore.Theme.defaultFont.pointSize - font.weight: Font.Bold - color: "white" - - layer.enabled: true - layer.effect: DropShadow { - verticalOffset: 1 - radius: 4 - samples: 6 - color: Qt.rgba(0, 0, 0, 0.5) + font.pointSize: PlasmaCore.Theme.defaultFont.pointSize + font.weight: Font.Bold + color: "white" + + layer.enabled: true + layer.effect: DropShadow { + verticalOffset: 1 + radius: 4 + samples: 6 + color: Qt.rgba(0, 0, 0, 0.5) + } } } } diff --git a/containments/homescreens/halcyon/package/contents/ui/GridAppDelegate.qml b/containments/homescreens/halcyon/package/contents/ui/GridAppDelegate.qml index 1833bf34..dd676b87 100644 --- a/containments/homescreens/halcyon/package/contents/ui/GridAppDelegate.qml +++ b/containments/homescreens/halcyon/package/contents/ui/GridAppDelegate.qml @@ -20,7 +20,7 @@ import org.kde.phone.homescreen.halcyon 1.0 as Halcyon import org.kde.kirigami 2.19 as Kirigami -MouseArea { +MobileShell.ExtendedAbstractButton { id: delegate width: GridView.view.cellWidth height: GridView.view.cellHeight @@ -34,11 +34,16 @@ MouseArea { signal launch(int x, int y, var source, string title, string storageId) - onPressAndHold: { + function openContextMenu() { dialogLoader.active = true; dialogLoader.item.open(); } + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + onPressAndHold: openContextMenu() + onRightClickPressed: openContextMenu() + function launchApp() { // launch app if (application.running) { @@ -54,6 +59,7 @@ MouseArea { sourceComponent: PlasmaComponents.Menu { title: label.text + closePolicy: PlasmaComponents.Menu.CloseOnReleaseOutside | PlasmaComponents.Menu.CloseOnEscape PlasmaComponents.MenuItem { icon.name: "emblem-favorite" @@ -102,8 +108,6 @@ MouseArea { } } - cursorShape: Qt.PointingHandCursor - hoverEnabled: true onPressedChanged: { if (pressed) { growAnim.stop(); @@ -147,6 +151,14 @@ MouseArea { height: width color: theme.highlightColor } + + // darken effect when hovered/pressed + layer { + enabled: delegate.pressed || delegate.hovered + effect: ColorOverlay { + color: Qt.rgba(0, 0, 0, 0.3) + } + } } PlasmaComponents.Label {