save progress

This commit is contained in:
kossLAN 2025-06-17 10:23:00 -04:00
parent f0673a66a2
commit c45c04e9ac
Signed by: kossLAN
SSH key fingerprint: SHA256:bdV0x+wdQHGJ6LgmstH3KV8OpWY+OOFmJcPcB0wQPV8
15 changed files with 621 additions and 418 deletions

View file

@ -4,16 +4,15 @@ The idea is to eventually be minimal but also use material 3 design language, lo
## TODO List ## TODO List
- [x] Custom Popup Window Surface for smooth anims on top bar - [x] Custom Popup Window Surface for smooth anims on top bar
- [ ] Lockscreen - [ ] Lockscreen (WIP)
- [ ] Port visuals to more material 3 aethestic - [ ] Port visuals to more material 3 aethestic (WIP)
- [ ] Screenshot tool - [x] Screenshot tool (WIP - kinda scuffed, but is functional)
- [ ] Recording/Clip widget with gpuscreenrecorder - [ ] Recording/Clip widget with gpuscreenrecorder
- [ ] Session Manager - [ ] Session Manager
- [ ] Battery Profile Popup - [ ] Battery Profile Popup
- [ ] REDO Volume OSD - [ ] REDO Volume OSD (WIP)
- [ ] REDO Launcher (wallpaper picker, calculator, commands, etc...) - [ ] REDO Launcher (wallpaper picker, calculator, commands, etc...)
- [ ] Integrate wallpaper picker into launcher
- [ ] Music Player Popup V4 lol - [ ] Music Player Popup V4 lol
### Optionals ### Optionals
- [ ] Add toggle for floating or screen corners - [ ] Add toggle for floating or screen corners

View file

@ -2,7 +2,8 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Widgets import Quickshell.Widgets
import "battery" import "power"
import "volume"
import "systray" as SysTray import "systray" as SysTray
import "popups" as Popup import "popups" as Popup
import "mpris" as Mpris import "mpris" as Mpris
@ -99,6 +100,15 @@ PanelWindow {
Layout.fillHeight: true Layout.fillHeight: true
} }
VolumeIndicator {
id: volumeIndicator
popup: root.popup
Layout.preferredWidth: this.height
Layout.fillHeight: true
Layout.topMargin: 2
Layout.bottomMargin: 2
}
BatteryIndicator { BatteryIndicator {
id: batteryIndicator id: batteryIndicator
popup: root.popup popup: root.popup

View file

@ -1,123 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import Quickshell.Widgets
import Quickshell.Services.UPower
import "../.."
Item {
id: root
implicitWidth: height + 8 // for margin
visible: UPower.displayDevice.isLaptopBattery
required property var popup
MouseArea {
id: batteryButton
hoverEnabled: true
anchors.fill: parent
onClicked: {
if (root.popup.content == powerMenu) {
root.popup.hide();
return;
}
root.popup.set(this, powerMenu);
root.popup.show();
}
}
Item {
id: powerMenu
visible: false
implicitWidth: 250
implicitHeight: 80
MouseArea {
anchors.fill: parent
onClicked: {
console.log("why this work");
powerMenu.implicitWidth = 300;
}
}
RowLayout {
anchors.fill: parent
// placeholder for now
// Text {
// text
// }
ComboBox {
model: ["Power Save", "Balanced", "Performance"]
currentIndex: PowerProfiles.profile
onCurrentIndexChanged: PowerProfiles.profile = currentIndex
}
}
}
Rectangle {
id: highlight
color: batteryButton.containsMouse ? ShellSettings.colors["primary"] : "transparent"
// radius: width / 2
radius: 10
anchors {
fill: parent
// topMargin: 2
// bottomMargin: 2
}
Behavior on color {
ColorAnimation {
duration: 100
}
}
}
Item {
implicitWidth: parent.height
implicitHeight: parent.height
anchors.centerIn: parent
layer.enabled: true
layer.effect: OpacityMask {
source: Rectangle {
width: root.width
height: root.height
color: "white"
}
maskSource: IconImage {
implicitSize: root.width
source: "root:resources/battery/battery.svg"
}
}
Rectangle {
id: batteryBackground
color: Qt.color(ShellSettings.colors["surface"]).lighter(4)
opacity: 0.75
anchors {
fill: parent
margins: 2
}
}
Rectangle {
id: batteryPercentage
width: (parent.width - 4) * UPower.displayDevice.percentage
color: ShellSettings.colors["inverse_surface"]
anchors {
left: batteryBackground.left
top: batteryBackground.top
bottom: batteryBackground.bottom
}
}
}
}

View file

@ -1,14 +1,16 @@
import Quickshell.Widgets
import QtQuick import QtQuick
import "../../mpris" as Mpris import "../../mpris" as Mpris
import "../../widgets" as Widgets
import "../.." import "../.."
WrapperRectangle { Widgets.MaterialButton {
id: root id: root
color: button.containsMouse ? ShellSettings.colors["primary"] : "transparent"
radius: 6 radius: 6
leftMargin: 5 implicitWidth: mediaInfo.contentWidth + 8
rightMargin: 5 implicitHeight: parent.height
// onClicked: {
// popup.visible = !popup.visible;
// }
required property var bar required property var bar
property var player: Mpris.Controller.trackedPlayer property var player: Mpris.Controller.trackedPlayer
@ -16,48 +18,25 @@ WrapperRectangle {
Text { Text {
id: mediaInfo id: mediaInfo
text: root.player?.trackTitle ?? "" text: root.player?.trackTitle ?? ""
color: button.containsMouse ? ShellSettings.colors["inverse_primary"] : ShellSettings.colors["inverse_surface"] color: root.containsMouse ? ShellSettings.colors["inverse_primary"] : ShellSettings.colors["inverse_surface"]
elide: Text.ElideRight elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
font.pointSize: 11 font.pointSize: 11
anchors.verticalCenter: parent.verticalCenter anchors.centerIn: parent
MouseArea {
id: button
anchors.fill: parent
hoverEnabled: true
onClicked: {
popup.visible = !popup.visible;
}
}
WidgetWindow {
id: popup
visible: false
parentWindow: root.bar
// anchor.window: root.bar
}
// Item {
// id: menu
// visible: false
// implicitWidth: 250
// implicitHeight: 80
// }
Behavior on color { Behavior on color {
ColorAnimation { ColorAnimation {
duration: 100 duration: 200
} }
} }
} }
Behavior on color {
ColorAnimation {
duration: 100
}
}
} }
// WidgetWindow {
// id: popup
// visible: false
// parentWindow: root.bar
//
// // anchor.window: root.bar
// }

View file

@ -0,0 +1,102 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import Quickshell.Widgets
import Quickshell.Services.UPower
import "../../widgets" as Widgets
import "../.."
// todo: redo the tray icon handling
Item {
id: root
implicitWidth: height + 8 // for margin
visible: UPower.displayDevice.isLaptopBattery
required property var popup
Widgets.MaterialButton {
id: batteryButton
hoverEnabled: true
onClicked: {
if (root.popup.content == powerMenu) {
root.popup.hide();
return;
}
root.popup.set(this, powerMenu);
root.popup.show();
}
anchors {
fill: parent
margins: 1
}
Item {
implicitWidth: parent.height
implicitHeight: parent.height
anchors.centerIn: parent
layer.enabled: true
layer.effect: OpacityMask {
source: Rectangle {
width: root.width
height: root.height
color: "white"
}
maskSource: IconImage {
implicitSize: root.width
source: "root:resources/battery/battery.svg"
}
}
Rectangle {
id: batteryBackground
color: Qt.color(ShellSettings.colors["surface"]).lighter(4)
opacity: 0.75
anchors {
fill: parent
margins: 2
}
}
Rectangle {
id: batteryPercentage
width: (parent.width - 4) * UPower.displayDevice.percentage
color: ShellSettings.colors["inverse_surface"]
anchors {
left: batteryBackground.left
top: batteryBackground.top
bottom: batteryBackground.bottom
}
}
}
}
Item {
id: powerMenu
visible: false
implicitWidth: 250
implicitHeight: 80
RowLayout {
anchors.fill: parent
// ComboBox {
// model: ScriptModel {
// values: ["Power Save", "Balanced", "Performance"]
// }
//
// currentIndex: PowerProfiles.profile
// onCurrentIndexChanged: {
// PowerProfiles.profile = this.currentIndex;
// console.log(PowerProfile.toString(PowerProfiles.profile));
// }
// }
}
}
}

View file

@ -5,11 +5,11 @@ import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Widgets import Quickshell.Widgets
import Quickshell.Services.SystemTray import Quickshell.Services.SystemTray
import "../.." import "../../widgets" as Widgets
RowLayout { RowLayout {
id: root id: root
spacing: 10 spacing: 5
visible: SystemTray.items.values.length > 0 visible: SystemTray.items.values.length > 0
required property var popup required property var popup
@ -19,14 +19,13 @@ RowLayout {
delegate: Item { delegate: Item {
id: trayField id: trayField
Layout.preferredWidth: parent.height Layout.preferredWidth: parent.height
Layout.fillHeight: true Layout.fillHeight: true
required property SystemTrayItem modelData required property SystemTrayItem modelData
MouseArea { Widgets.MaterialButton {
id: trayButton id: trayButton
hoverEnabled: true hoverEnabled: true
anchors.fill: parent
onClicked: { onClicked: {
menuOpener.menu = trayField.modelData.menu; menuOpener.menu = trayField.modelData.menu;
@ -38,6 +37,25 @@ RowLayout {
root.popup.set(this, trayMenu); root.popup.set(this, trayMenu);
root.popup.show(); root.popup.show();
} }
anchors {
fill: parent
margins: 2
}
IconImage {
id: trayIcon
anchors.fill: parent
source: {
// console.log(trayField.modelData.id);
switch (trayField.modelData.id) {
case "obs":
return "image://icon/obs-tray";
default:
return trayField.modelData.icon;
}
}
}
} }
QsMenuOpener { QsMenuOpener {
@ -73,45 +91,6 @@ RowLayout {
} }
} }
} }
Rectangle {
id: trayContainer
color: trayButton.containsMouse ? ShellSettings.colors["primary"] : "transparent"
radius: width / 2
implicitHeight: parent.height
implicitWidth: parent.height
anchors {
fill: parent
margins: 1
}
IconImage {
id: trayIcon
source: {
// console.log(trayField.modelData.id);
switch (trayField.modelData.id) {
case "obs":
return "image://icon/obs-tray";
default:
return trayField.modelData.icon;
}
}
anchors {
fill: parent
margins: 1
}
}
Behavior on color {
ColorAnimation {
duration: 100
}
}
}
} }
} }
} }

View file

@ -0,0 +1,70 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import Quickshell.Services.Pipewire
import "../../widgets/" as Widgets
import "../.."
ColumnLayout {
id: root
Loader {
id: sinkLoader
active: sink
property PwNode sink: Pipewire.defaultAudioSink
sourceComponent: WrapperItem {
PwNodeLinkTracker {
id: linkTracker
node: sinkLoader.sink
}
ColumnLayout {
Repeater {
model: linkTracker.linkGroups
delegate: Loader {
id: nodeLoader
active: modelData.source !== null
Layout.preferredWidth: 350
Layout.preferredHeight: 45
required property PwLinkGroup modelData
sourceComponent: VolumeCard {
id: nodeCard
node: nodeLoader.modelData.source
text: node.properties["media.name"] ?? ""
// if icon-name is undefined, just gonna fallback on the application name
icon: IconImage {
source: {
if (nodeCard.node.properties["application.icon-name"] !== undefined)
return `image://icon/${nodeCard.node.properties["application.icon-name"]}`;
let applicationName = nodeCard.node.properties["application.name"];
return `image://icon/${applicationName?.toLowerCase() ?? "image-missing"}`;
}
}
button: Widgets.FontIconButton {
hoverEnabled: false
iconName: nodeCard.node.audio.muted ? "volume_off" : "volume_up"
checked: !nodeCard.node.audio.muted
inactiveColor: ShellSettings.colors["surface_container_highest"]
onClicked: {
nodeCard.node.audio.muted = !nodeCard.node.audio.muted;
}
}
anchors.fill: parent
}
}
}
}
}
}
}

View file

@ -0,0 +1,64 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Services.Pipewire
import "../../widgets/" as Widgets
import "../.."
ColumnLayout {
id: root
// headphones
// don't load until the node is not null
Loader {
id: sinkLoader
active: sink !== null
Layout.preferredWidth: 350
Layout.preferredHeight: 45
property PwNode sink: Pipewire.defaultAudioSink
sourceComponent: VolumeCard {
id: sinkCard
node: sinkLoader.sink
button: Widgets.FontIconButton {
hoverEnabled: false
iconName: sinkCard.node.audio.muted ? "volume_off" : "volume_up"
checked: !sinkCard.node.audio.muted
inactiveColor: ShellSettings.colors["surface_container_highest"]
onClicked: {
sinkCard.node.audio.muted = !sinkCard.node.audio.muted;
}
}
anchors.fill: parent
}
}
// microphone, same as above
Loader {
id: sourceLoader
active: source !== null
Layout.preferredWidth: 350
Layout.preferredHeight: 45
property PwNode source: Pipewire.defaultAudioSource
sourceComponent: VolumeCard {
id: sourceCard
node: sourceLoader.source
button: Widgets.FontIconButton {
hoverEnabled: false
iconName: sourceCard.node.audio.muted ? "mic_off" : "mic"
checked: !sourceCard.node.audio.muted
inactiveColor: ShellSettings.colors["surface_container_highest"]
onClicked: {
sourceCard.node.audio.muted = !sourceCard.node.audio.muted;
}
}
anchors.fill: parent
}
}
}

50
bar/volume/VolumeCard.qml Normal file
View file

@ -0,0 +1,50 @@
import QtQuick
import QtQuick.Layouts
import Quickshell.Widgets
import Quickshell.Services.Pipewire
import "../../widgets/" as Widgets
import "../.."
WrapperRectangle {
id: root
color: ShellSettings.colors["surface_container"]
radius: width / 2
margin: 6
required property PwNode node
property string text
property Component button
property Component icon
PwObjectTracker {
id: tracker
objects: [root.node]
}
RowLayout {
Widgets.MaterialSlider {
value: root.node.audio.volume ?? 0
text: root.text
icon: root.icon
onValueChanged: {
// only allow changes when the node is ready other wise you will combust
if (!root.node.ready)
return;
root.node.audio.volume = value;
}
Layout.fillWidth: true
Layout.fillHeight: true
}
Loader {
id: buttonLoader
sourceComponent: root.button
Layout.preferredWidth: this.height
Layout.fillHeight: true
}
}
}

View file

@ -0,0 +1,76 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import Quickshell.Widgets
import Quickshell.Services.Pipewire
import "../../widgets/" as Widgets
import "../.."
WrapperItem {
id: root
visible: false
ColumnLayout {
spacing: 5
// Toolbar
Rectangle {
id: toolbar
color: ShellSettings.colors["surface_container_highest"]
radius: 10
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
width: toolbar.width
height: toolbar.height
radius: toolbar.radius
color: "black"
}
}
Layout.fillWidth: true
Layout.preferredHeight: 35
RowLayout {
spacing: 0
anchors.fill: parent
Widgets.FontIconButton {
hoverEnabled: false
iconName: "headphones"
radius: 0
checked: page.currentIndex === 0
onClicked: page.currentIndex = 0
Layout.fillWidth: true
Layout.fillHeight: true
}
Widgets.FontIconButton {
hoverEnabled: false
iconName: "tune"
radius: 0
checked: page.currentIndex === 1
onClicked: page.currentIndex = 1
Layout.fillWidth: true
Layout.fillHeight: true
}
}
}
StackLayout {
id: page
currentIndex: 0
Layout.fillWidth: true
Layout.preferredHeight: currentItem ? currentItem.implicitHeight : 0
readonly property Item currentItem: children[currentIndex]
DeviceMixer {}
ApplicationMixer {}
}
}
}

View file

@ -0,0 +1,27 @@
import QtQuick
import "../../widgets/" as Widgets
Item {
id: root
required property var popup
Widgets.FontIconButton {
id: button
iconName: "volume_up"
anchors.fill: parent
onClicked: {
if (root.popup.content == volumeMenu) {
root.popup.hide();
return;
}
root.popup.set(this, volumeMenu);
root.popup.show();
}
}
VolumeControl {
id: volumeMenu
}
}

View file

@ -0,0 +1,48 @@
import QtQuick
import ".."
MaterialButton {
id: root
property real implicitSize
property string iconName: ""
property string activeIconColor: ShellSettings.colors["inverse_primary"]
property string inactiveIconColor: ShellSettings.colors["inverse_surface"]
implicitWidth: this.implicitSize
implicitHeight: this.implicitSize
Text {
id: textIcon
text: root.iconName
renderType: Text.NativeRendering
textFormat: Text.PlainText
color: root.containsMouse || root.checked ? root.activeIconColor : root.inactiveIconColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
anchors.fill: parent
font {
family: "Material Symbols Outlined"
pointSize: Math.max(parent.height * 0.60, 11)
variableAxes: {
"FILL": fill
}
}
property real fill: !root.containsMouse && !root.checked ? 0 : 1
Behavior on fill {
NumberAnimation {
duration: 200
}
}
Behavior on color {
ColorAnimation {
duration: 200
}
}
}
}

View file

@ -1,3 +1,24 @@
import QtQuick import QtQuick
import ".."
Rectangle {} MouseArea {
id: root
hoverEnabled: true
property real radius: width / 2
property bool checked: false
property var activeColor: ShellSettings.colors["primary"]
property var inactiveColor: "transparent"
Rectangle {
color: root.containsMouse || root.checked ? root.activeColor : root.inactiveColor
radius: root.radius
anchors.fill: parent
Behavior on color {
ColorAnimation {
duration: 200
}
}
}
}

105
widgets/MaterialSlider.qml Normal file
View file

@ -0,0 +1,105 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
import ".."
Slider {
id: root
value: 0.5
from: 0.0
to: 1.0
property string text
property Component icon
background: Rectangle {
id: background
implicitWidth: parent.width
implicitHeight: parent.height
width: root.availableWidth
height: implicitHeight
x: root.leftPadding
y: root.topPadding + root.availableHeight / 2 - height / 2
z: 0
color: ShellSettings.colors["surface_container_highest"]
radius: height / 2
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
width: background.implicitWidth
height: background.implicitHeight
radius: background.radius
color: "black"
}
}
Rectangle {
id: visualPos
width: root.visualPosition * (root.availableWidth - root.height) + (root.height / 2)
height: parent.height
color: ShellSettings.colors["primary"]
}
Text {
id: sliderText
text: root.text
visible: text !== ""
color: ShellSettings.colors["inverse_primary"]
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
font {
pointSize: Math.max(handle.implicitHeight * 0.35, 11)
}
anchors {
top: parent.top
bottom: parent.bottom
left: {
let visualWidth = (root.visualPosition * root.availableWidth);
if ((visualWidth / root.availableWidth) < 0.5)
return visualPos.right;
else
return parent.left;
}
right: {
let visualWidth = (root.visualPosition * root.availableWidth);
if ((visualWidth / root.availableWidth) > 0.5)
return visualPos.right;
else
return parent.right;
}
leftMargin: 20
rightMargin: 20
}
}
}
handle: Rectangle {
id: handle
color: ShellSettings.colors["primary"]
implicitWidth: root.height
implicitHeight: root.height
radius: width / 2
x: root.leftPadding + root.visualPosition * (root.availableWidth - width)
y: root.topPadding + root.availableHeight / 2 - height / 2
// icon maybe
Loader {
active: root.icon !== undefined
sourceComponent: root.icon
anchors {
fill: parent
margins: 2
}
}
}
}

View file

@ -1,204 +0,0 @@
import QtQuick
import Qt5Compat.GraphicalEffects
import Quickshell
import Quickshell.Widgets
import ".."
Item {
id: root
property string icon
property bool enabled: true
property bool highlight: true
property bool clickable: false
property bool useMask: true
property bool useVariableFill: false
property real size: 18
property real outerSize: size
property color hoverColor: ShellSettings.colors["inverse_primary"]
property color iconColor: ShellSettings.colors["primary"]
property real buttonRadius: 6
property real padding: 4
property real fillValue: 0.0
property real fillTarget: 0.0
property real fillHover: 1.0
property real fillNormal: 0.0
property int fillDuration: 300
signal clicked(var mouse)
implicitWidth: outerSize + (padding * 2)
implicitHeight: outerSize + (padding * 2)
Rectangle {
id: backgroundRect
anchors.fill: parent
radius: root.buttonRadius
color: mouseArea.containsMouse && root.highlight ? root.hoverColor : "transparent"
visible: root.highlight
Behavior on color {
ColorAnimation {
duration: 200
easing.type: Easing.InOutCubic
}
}
}
NumberAnimation {
id: fillAnimation
target: root
property: "fillValue"
duration: root.fillDuration
easing.type: Easing.OutCubic
to: root.fillTarget
}
Text {
id: variableFillIcon
visible: root.useVariableFill
anchors.centerIn: parent
font.family: "Material Symbols Outlined"
renderType: Text.NativeRendering
textFormat: Text.PlainText
font.pointSize: root.size * 0.8
text: root.icon
color: root.enabled ?? root.iconColor
opacity: root.enabled ? 1.0 : 0.5
font.variableAxes: {
"FILL": root.fillValue.toFixed(1)
}
Behavior on color {
ColorAnimation {
duration: 200
easing.type: Easing.InOutCubic
}
}
}
Item {
id: maskedIcon
visible: root.useMask && !root.useVariableFill
anchors.centerIn: parent
width: root.size
height: root.size
smooth: true
layer.enabled: true
layer.effect: OpacityMask {
source: Rectangle {
width: root.size
height: root.size
color: "white"
}
maskSource: IconImage {
mipmap: true
implicitSize: root.size
source: Quickshell.iconPath(root.icon)
opacity: root.enabled ? 1.0 : 0.5
smooth: true
}
}
transform: Translate {
x: mouseArea.containsMouse ? -1 : 0
y: mouseArea.containsMouse ? -2 : 0
Behavior on x {
NumberAnimation {
duration: 450
easing.type: Easing.OutElastic
easing.amplitude: 1.0
easing.period: 0.3
}
}
Behavior on y {
NumberAnimation {
duration: 450
easing.type: Easing.OutElastic
easing.amplitude: 1.0
easing.period: 0.3
}
}
}
Rectangle {
anchors.fill: parent
color: root.enabled ?? root.iconColor
Behavior on color {
ColorAnimation {
duration: 200
easing.type: Easing.InOutCubic
}
}
}
}
IconImage {
id: unmaskedIcon
visible: !root.useMask && !root.useVariableFill
anchors.centerIn: parent
source: Quickshell.iconPath(root.icon)
implicitSize: root.size
opacity: root.enabled ? 1.0 : 0.5
transform: Translate {
x: mouseArea.containsMouse ? -1 : 0
y: mouseArea.containsMouse ? -2 : 0
Behavior on x {
NumberAnimation {
duration: 350
easing.type: Easing.OutElastic
easing.amplitude: 1.0
easing.period: 0.6
}
}
Behavior on y {
NumberAnimation {
duration: 350
easing.type: Easing.OutElastic
easing.amplitude: 1.0
easing.period: 0.6
}
}
}
Behavior on opacity {
NumberAnimation {
duration: 200
easing.type: Easing.InOutCubic
}
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: root.clickable ? Qt.PointingHandCursor : ""
enabled: root.clickable && root.enabled
hoverEnabled: true
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
onClicked: function (mouse) {
root.clicked(mouse);
}
onContainsMouseChanged: {
if (root.useVariableFill) {
root.fillTarget = containsMouse ? root.fillHover : root.fillNormal;
fillAnimation.restart();
}
}
}
Component.onCompleted: {
if (useVariableFill) {
fillValue = fillNormal;
}
}
}