components: Introduce ExtendedAbstractButton, port homescreen to it

This commit is contained in:
Devin Lin 2022-06-21 18:38:21 -04:00
parent d158549525
commit 9922c8d5d2
10 changed files with 161 additions and 77 deletions

View file

@ -69,6 +69,7 @@ void MobileShellPlugin::registerTypes(const char *uri)
// /components // /components
qmlRegisterType(resolvePath("components/BaseItem.qml"), uri, 1, 0, "BaseItem"); 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"); qmlRegisterSingletonType(resolvePath("components/Haptics.qml"), uri, 1, 0, "Haptics");
qmlRegisterType(resolvePath("components/StartupFeedback.qml"), uri, 1, 0, "StartupFeedback"); qmlRegisterType(resolvePath("components/StartupFeedback.qml"), uri, 1, 0, "StartupFeedback");
qmlRegisterType(resolvePath("components/VelocityCalculator.qml"), uri, 1, 0, "VelocityCalculator"); qmlRegisterType(resolvePath("components/VelocityCalculator.qml"), uri, 1, 0, "VelocityCalculator");

View file

@ -0,0 +1,65 @@
// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
// 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;
}
}
}
}

View file

@ -21,6 +21,7 @@
<file>qml/actiondrawer/PortraitContentContainer.qml</file> <file>qml/actiondrawer/PortraitContentContainer.qml</file>
<file>qml/components/BaseItem.qml</file> <file>qml/components/BaseItem.qml</file>
<file>qml/components/ExtendedAbstractButton.qml</file>
<file>qml/components/Haptics.qml</file> <file>qml/components/Haptics.qml</file>
<file>qml/components/HapticsEffectWrapper.qml</file> <file>qml/components/HapticsEffectWrapper.qml</file>
<file>qml/components/MarqueeLabel.qml</file> <file>qml/components/MarqueeLabel.qml</file>

View file

@ -63,7 +63,6 @@ QHash<int, QByteArray> ApplicationListModel::roleNames() const
void ApplicationListModel::sycocaDbChanged() void ApplicationListModel::sycocaDbChanged()
{ {
m_applicationList.clear();
loadApplications(); loadApplications();
} }

View file

@ -100,7 +100,7 @@ ContainmentLayoutManager.ItemContainer {
} }
} }
contentItem: MouseArea { contentItem: MobileShell.ExtendedAbstractButton {
id: mouseArea id: mouseArea
// grow/shrink animation // grow/shrink animation
@ -187,7 +187,7 @@ ContainmentLayoutManager.ItemContainer {
// darken effect when hovered/pressed // darken effect when hovered/pressed
layer { layer {
enabled: mouseArea.pressed || mouseArea.containsMouse enabled: mouseArea.pressed || mouseArea.hovered
effect: ColorOverlay { effect: ColorOverlay {
color: Qt.rgba(0, 0, 0, 0.3) color: Qt.rgba(0, 0, 0, 0.3)
} }

View file

@ -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.containmentlayoutmanager 1.0 as ContainmentLayoutManager
import org.kde.plasma.private.mobileshell 1.0 as MobileShell import org.kde.plasma.private.mobileshell 1.0 as MobileShell
MouseArea { MobileShell.ExtendedAbstractButton {
id: delegate id: delegate
width: GridView.view.cellWidth width: GridView.view.cellWidth
height: GridView.view.cellHeight height: GridView.view.cellHeight
@ -129,7 +129,7 @@ MouseArea {
// darken effect when hovered/pressed // darken effect when hovered/pressed
layer { layer {
enabled: delegate.pressed || delegate.containsMouse enabled: delegate.pressed || delegate.hovered
effect: ColorOverlay { effect: ColorOverlay {
color: Qt.rgba(0, 0, 0, 0.3) color: Qt.rgba(0, 0, 0, 0.3)
} }

View file

@ -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.containmentlayoutmanager 1.0 as ContainmentLayoutManager
import org.kde.plasma.private.mobileshell 1.0 as MobileShell import org.kde.plasma.private.mobileshell 1.0 as MobileShell
MouseArea { MobileShell.ExtendedAbstractButton {
id: delegate id: delegate
property int reservedSpaceForLabel property int reservedSpaceForLabel
property alias iconItem: icon property alias iconItem: icon
@ -45,7 +45,7 @@ MouseArea {
Rectangle { Rectangle {
anchors.fill: parent 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 { Behavior on color {
ColorAnimation { duration: PlasmaCore.Units.shortDuration } ColorAnimation { duration: PlasmaCore.Units.shortDuration }
} }

View file

@ -38,7 +38,6 @@ QHash<int, QByteArray> ApplicationListModel::roleNames() const
void ApplicationListModel::sycocaDbChanged() void ApplicationListModel::sycocaDbChanged()
{ {
m_applicationList.clear();
loadApplications(); loadApplications();
} }

View file

@ -17,7 +17,7 @@ import org.kde.phone.homescreen.halcyon 1.0 as Halcyon
import org.kde.kirigami 2.19 as Kirigami import org.kde.kirigami 2.19 as Kirigami
MouseArea { MobileShell.ExtendedAbstractButton {
id: delegate id: delegate
property alias iconItem: icon property alias iconItem: icon
@ -44,11 +44,15 @@ MouseArea {
application.runApplication(); application.runApplication();
} }
onPressAndHold: { function openContextMenu() {
dialogLoader.active = true; dialogLoader.active = true;
dialogLoader.item.open(); dialogLoader.item.open();
} }
hoverEnabled: true
onPressAndHold: openContextMenu()
onRightClickPressed: openContextMenu()
onClicked: { onClicked: {
// launch app // launch app
if (application.running) { if (application.running) {
@ -57,7 +61,6 @@ MouseArea {
delegate.launch(delegate.x + (PlasmaCore.Units.smallSpacing * 2), delegate.y + (PlasmaCore.Units.smallSpacing * 2), icon.source, applicationName, applicationStorageId); delegate.launch(delegate.x + (PlasmaCore.Units.smallSpacing * 2), delegate.y + (PlasmaCore.Units.smallSpacing * 2), icon.source, applicationName, applicationStorageId);
} }
} }
hoverEnabled: true
Loader { Loader {
id: dialogLoader id: dialogLoader
@ -65,6 +68,7 @@ MouseArea {
sourceComponent: PlasmaComponents.Menu { sourceComponent: PlasmaComponents.Menu {
title: label.text title: label.text
closePolicy: PlasmaComponents.Menu.CloseOnReleaseOutside | PlasmaComponents.Menu.CloseOnEscape
PlasmaComponents.MenuItem { PlasmaComponents.MenuItem {
icon.name: "emblem-favorite" icon.name: "emblem-favorite"
@ -77,80 +81,83 @@ MouseArea {
} }
} }
Rectangle { background: Rectangle {
anchors.fill: parent
radius: height / 2 radius: height / 2
color: delegate.pressed ? Qt.rgba(255, 255, 255, 0.2) : (delegate.hovered ? Qt.rgba(255, 255, 255, 0.1) : "transparent")
color: delegate.pressed ? Qt.rgba(255, 255, 255, 0.2) : (delegate.containsMouse ? Qt.rgba(255, 255, 255, 0.1) : "transparent")
} }
RowLayout { contentItem: Item {
anchors { implicitHeight: rowLayout.height + rowLayout.anchors.topMargin + rowLayout.anchors.bottomMargin
fill: parent implicitWidth: rowLayout.width + rowLayout.anchors.rightMargin + rowLayout.anchors.leftMargin
leftMargin: PlasmaCore.Units.smallSpacing * 2
topMargin: PlasmaCore.Units.smallSpacing
rightMargin: PlasmaCore.Units.smallSpacing * 2
bottomMargin: PlasmaCore.Units.smallSpacing
}
spacing: 0
PlasmaCore.IconItem { RowLayout {
id: icon 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
Layout.alignment: Qt.AlignLeft PlasmaCore.IconItem {
Layout.minimumWidth: Layout.minimumHeight id: icon
Layout.preferredWidth: Layout.minimumHeight
Layout.minimumHeight: parent.height
Layout.preferredHeight: Layout.minimumHeight
usesPlasmaTheme: false Layout.alignment: Qt.AlignLeft
source: applicationIcon Layout.minimumWidth: Layout.minimumHeight
Layout.preferredWidth: Layout.minimumHeight
Layout.minimumHeight: parent.height
Layout.preferredHeight: Layout.minimumHeight
Rectangle { usesPlasmaTheme: false
anchors { source: applicationIcon
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 PlasmaComponents.Label {
layer.effect: DropShadow { id: label
verticalOffset: 1 visible: text.length > 0
radius: 4
samples: 6
color: Qt.rgba(0, 0, 0, 0.5)
}
}
PlasmaComponents.Label { Layout.fillWidth: true
id: label Layout.leftMargin: PlasmaCore.Units.smallSpacing * 2
visible: text.length > 0 Layout.rightMargin: PlasmaCore.Units.largeSpacing
wrapMode: Text.WordWrap
maximumLineCount: 1
elide: Text.ElideRight
Layout.fillWidth: true text: applicationName
Layout.leftMargin: PlasmaCore.Units.smallSpacing * 2
Layout.rightMargin: PlasmaCore.Units.largeSpacing
wrapMode: Text.WordWrap
maximumLineCount: 1
elide: Text.ElideRight
text: applicationName font.pointSize: PlasmaCore.Theme.defaultFont.pointSize
font.weight: Font.Bold
color: "white"
font.pointSize: PlasmaCore.Theme.defaultFont.pointSize layer.enabled: true
font.weight: Font.Bold layer.effect: DropShadow {
color: "white" verticalOffset: 1
radius: 4
layer.enabled: true samples: 6
layer.effect: DropShadow { color: Qt.rgba(0, 0, 0, 0.5)
verticalOffset: 1 }
radius: 4
samples: 6
color: Qt.rgba(0, 0, 0, 0.5)
} }
} }
} }

View file

@ -20,7 +20,7 @@ import org.kde.phone.homescreen.halcyon 1.0 as Halcyon
import org.kde.kirigami 2.19 as Kirigami import org.kde.kirigami 2.19 as Kirigami
MouseArea { MobileShell.ExtendedAbstractButton {
id: delegate id: delegate
width: GridView.view.cellWidth width: GridView.view.cellWidth
height: GridView.view.cellHeight height: GridView.view.cellHeight
@ -34,11 +34,16 @@ MouseArea {
signal launch(int x, int y, var source, string title, string storageId) signal launch(int x, int y, var source, string title, string storageId)
onPressAndHold: { function openContextMenu() {
dialogLoader.active = true; dialogLoader.active = true;
dialogLoader.item.open(); dialogLoader.item.open();
} }
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onPressAndHold: openContextMenu()
onRightClickPressed: openContextMenu()
function launchApp() { function launchApp() {
// launch app // launch app
if (application.running) { if (application.running) {
@ -54,6 +59,7 @@ MouseArea {
sourceComponent: PlasmaComponents.Menu { sourceComponent: PlasmaComponents.Menu {
title: label.text title: label.text
closePolicy: PlasmaComponents.Menu.CloseOnReleaseOutside | PlasmaComponents.Menu.CloseOnEscape
PlasmaComponents.MenuItem { PlasmaComponents.MenuItem {
icon.name: "emblem-favorite" icon.name: "emblem-favorite"
@ -102,8 +108,6 @@ MouseArea {
} }
} }
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onPressedChanged: { onPressedChanged: {
if (pressed) { if (pressed) {
growAnim.stop(); growAnim.stop();
@ -147,6 +151,14 @@ MouseArea {
height: width height: width
color: theme.highlightColor 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 { PlasmaComponents.Label {