1 Commits

Author SHA1 Message Date
AramJonghu d799e61c79 clang-tidy fixes incoming 2026-06-05 18:02:27 +02:00
80 changed files with 1164 additions and 2465 deletions
+1 -2
View File
@@ -24,8 +24,7 @@ CheckOptions:
readability-identifier-naming.StaticConstantCase: UPPER_CASE readability-identifier-naming.StaticConstantCase: UPPER_CASE
readability-identifier-naming.StaticConstantPrefix: k readability-identifier-naming.StaticConstantPrefix: k
readability-identifier-naming.VariableCase: camelBack readability-identifier-naming.VariableCase: camelBack
WarningsAsErrors: "*" HeaderFilterRegex: ""
HeaderFilterRegex: ".*"
FormatStyle: file FormatStyle: file
... ...
+3 -58
View File
@@ -2,62 +2,7 @@ import QtQuick
import qs.Config import qs.Config
NumberAnimation { NumberAnimation {
enum Type { duration: Appearance.anim.durations.normal
StandardSmall = 0, easing.bezierCurve: Appearance.anim.curves.standard
Standard, easing.type: Easing.BezierSpline
StandardLarge,
StandardExtraLarge,
EmphasizedSmall,
Emphasized,
EmphasizedLarge,
EmphasizedExtraLarge,
FastSpatial,
DefaultSpatial,
SlowSpatial,
FastEffects,
DefaultEffects,
SlowEffects
}
property int type: Anim.DefaultSpatial
duration: {
if (type < Anim.StandardSmall || type > Anim.SlowEffects)
return Appearance.anim.durations.normal;
if (type === Anim.FastSpatial)
return Appearance.anim.durations.expressiveFastSpatial;
if (type === Anim.DefaultSpatial)
return Appearance.anim.durations.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial)
return Appearance.anim.durations.large;
if (type === Anim.FastEffects)
return Appearance.anim.durations.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Appearance.anim.durations.expressiveEffects;
if (type === Anim.SlowEffects)
return Appearance.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4; // 0-7 are the 4 standard types
return Appearance.anim.durations[types[idx]];
}
easing.bezierCurve: {
if (type === Anim.FastSpatial)
return Appearance.anim.curves.expressiveFastSpatial;
if (type === Anim.DefaultSpatial)
return Appearance.anim.curves.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial)
return Appearance.anim.curves.expressiveSlowSpatial;
if (type === Anim.FastEffects)
return Appearance.anim.curves.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Appearance.anim.curves.expressiveDefaultEffects;
if (type === Anim.SlowEffects)
return Appearance.anim.curves.expressiveSlowEffects;
if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Appearance.anim.curves.emphasized;
return Appearance.anim.curves.standard;
}
} }
+5 -5
View File
@@ -59,15 +59,15 @@ ColumnLayout {
} }
StateLayer { StateLayer {
function onClicked(): void {
root.toggleRequested();
root.expanded = !root.expanded;
}
anchors.fill: parent anchors.fill: parent
color: DynamicColors.palette.m3onSurface color: DynamicColors.palette.m3onSurface
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
showHoverBackground: false showHoverBackground: false
onClicked: {
root.toggleRequested();
root.expanded = !root.expanded;
}
} }
} }
+3 -3
View File
@@ -23,10 +23,10 @@ Button {
} }
StateLayer { StateLayer {
radius: control.radius function onClicked(): void {
onClicked: {
control.clicked(); control.clicked();
} }
radius: control.radius
} }
} }
+4 -4
View File
@@ -33,13 +33,13 @@ RadioButton {
} }
StateLayer { StateLayer {
function onClicked(): void {
root.click();
}
anchors.margins: -7 anchors.margins: -7
color: root.checked ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3primary color: root.checked ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3primary
z: -1 z: -1
onClicked: {
root.click();
}
} }
CustomRect { CustomRect {
+32 -155
View File
@@ -1,174 +1,51 @@
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Templates import QtQuick.Templates
import ZShell.Components
import ZShell
import qs.Components
import qs.Config import qs.Config
Slider { Slider {
id: root id: root
property bool animateWave property color color: DynamicColors.palette.m3primary
property color bgColor: enabled ? DynamicColors.palette.m3secondaryContainer : Qt.alpha(DynamicColors.palette.m3onSurface, 0.1)
property color fgColor: enabled ? DynamicColors.palette.m3primary : Qt.alpha(DynamicColors.palette.m3onSurface, 0.38)
property real filledWidth
property real pos: visualPosition
property int waveDuration: 1000
property real waveFrequency: 6
property bool wavy
signal interaction(v: real)
implicitHeight: 12
implicitWidth: 200
contentItem: Item {
anchors.fill: parent
background: Item {
CustomRect { CustomRect {
id: remaining anchors.bottom: parent.bottom
anchors.bottomMargin: root.implicitHeight / 6
anchors.left: handle.right
anchors.leftMargin: Appearance.spacing.extraSmall
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
bottomLeftRadius: Appearance.rounding.extraSmall / 2
color: root.bgColor
implicitHeight: parent.height * (parent.height <= 12 ? opacity : Math.min(opacity * 2, 1))
opacity: Math.min(width, 12) / 12
radius: Appearance.rounding.small
topLeftRadius: Appearance.rounding.extraSmall / 2
}
CustomRect {
anchors.right: parent.right
anchors.rightMargin: 4 * remaining.opacity
anchors.verticalCenter: parent.verticalCenter
color: root.fgColor
implicitHeight: 4 * remaining.opacity
implicitWidth: implicitHeight
opacity: remaining.opacity
radius: Appearance.rounding.full
}
CustomRect {
id: handle
anchors.left: filled.right
anchors.leftMargin: Appearance.spacing.extraSmall
anchors.verticalCenter: parent.verticalCenter
color: root.fgColor
implicitHeight: {
const mult = parent.height <= 12 ? 3 : 1.2;
const pressMult = parent.height <= 12 ? 4 : 1.5;
return parent.height * (mouse.pressed ? pressMult : mult);
}
implicitWidth: 4
radius: Appearance.rounding.full
Behavior on implicitHeight {
Anim {
type: Anim.FastSpatial
}
}
}
Loader {
id: filled
anchors.left: parent.left anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter anchors.top: parent.top
asynchronous: true anchors.topMargin: root.implicitHeight / 6
sourceComponent: root.wavy ? waveComp : lineComp bottomRightRadius: root.implicitHeight / 6
color: root.color
implicitWidth: root.handle.x - root.implicitHeight / 6
radius: root.implicitHeight / 6
topRightRadius: root.implicitHeight / 6
} }
Component { CustomRect {
id: lineComp anchors.bottom: parent.bottom
anchors.bottomMargin: root.implicitHeight / 6
CustomRect { anchors.right: parent.right
bottomRightRadius: Appearance.rounding.extraSmall / 2 anchors.top: parent.top
color: root.fgColor anchors.topMargin: root.implicitHeight / 6
implicitHeight: root.height bottomLeftRadius: root.implicitHeight / 6
implicitWidth: root.filledWidth color: DynamicColors.tPalette.m3surfaceContainerHighest
radius: Appearance.rounding.small implicitWidth: parent.width - root.handle.x - root.handle.implicitWidth - root.implicitHeight / 6
topRightRadius: Appearance.rounding.extraSmall / 2 radius: root.implicitHeight / 6
} topLeftRadius: root.implicitHeight / 6
}
Component {
id: waveComp
WavyLine {
color: root.fgColor
frequency: root.waveFrequency
fullLength: root.width - handle.implicitWidth - handle.anchors.leftMargin
implicitHeight: lineWidth * amplitudeMultiplier * 2 + lineWidth
implicitWidth: root.filledWidth
lineWidth: root.height * 0.7
startX: x
Behavior on color {
CAnim {
}
}
Anim on waveProgress {
duration: root.waveDuration
easing.type: Easing.Linear
from: 0
loops: Animation.Infinite
paused: !root.animateWave
running: true
to: 1
}
}
} }
} }
Behavior on filledWidth { handle: CustomRect {
id: widthBehavior
Anim {
}
}
Component.onCompleted: filledWidth = Qt.binding(() => (width - handle.implicitWidth - handle.anchors.leftMargin) * pos)
Binding {
id: posBinding
property: "pos"
target: root
value: ZUtils.clamp(mouse.pressStartPos + mouse.dragMovement, 0, 1)
when: mouse.pressed
}
MouseArea {
id: mouse
property real dragMovement
property real pressStartPos
property real pressStartX
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitHeight: handle.implicitHeight color: root.color
preventStealing: true implicitHeight: root.implicitHeight
implicitWidth: root.implicitHeight / 4.5
radius: Appearance.rounding.full
x: root.visualPosition * root.availableWidth - implicitWidth / 2
onPositionChanged: e => { MouseArea {
dragMovement = (e.x - pressStartX) / width; acceptedButtons: Qt.NoButton
root.interaction(posBinding.value); anchors.fill: parent
} cursorShape: Qt.PointingHandCursor
onPressed: e => {
widthBehavior.enabled = false;
pressStartX = e.x;
pressStartPos = root.visualPosition;
}
onReleased: e => {
root.interaction(posBinding.value);
widthBehavior.enabled = true;
dragMovement = 0;
} }
} }
} }
+8 -6
View File
@@ -94,9 +94,7 @@ RowLayout {
StateLayer { StateLayer {
id: upState id: upState
color: DynamicColors.palette.m3onPrimary function onClicked(): void {
onClicked: {
let newValue = Math.min(root.max, root.value + root.step); let newValue = Math.min(root.max, root.value + root.step);
// Round to avoid floating point precision errors // Round to avoid floating point precision errors
const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0; const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0;
@@ -105,6 +103,9 @@ RowLayout {
root.displayText = newValue.toString(); root.displayText = newValue.toString();
root.valueModified(newValue); root.valueModified(newValue);
} }
color: DynamicColors.palette.m3onPrimary
onPressAndHold: timer.start() onPressAndHold: timer.start()
onReleased: timer.stop() onReleased: timer.stop()
} }
@@ -127,9 +128,7 @@ RowLayout {
StateLayer { StateLayer {
id: downState id: downState
color: DynamicColors.palette.m3onPrimary function onClicked(): void {
onClicked: {
let newValue = Math.max(root.min, root.value - root.step); let newValue = Math.max(root.min, root.value - root.step);
// Round to avoid floating point precision errors // Round to avoid floating point precision errors
const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0; const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0;
@@ -138,6 +137,9 @@ RowLayout {
root.displayText = newValue.toString(); root.displayText = newValue.toString();
root.valueModified(newValue); root.valueModified(newValue);
} }
color: DynamicColors.palette.m3onPrimary
onPressAndHold: timer.start() onPressAndHold: timer.start()
onReleased: timer.stop() onReleased: timer.stop()
} }
+66 -37
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Config import qs.Config
import qs.Helpers
Row { Row {
id: root id: root
@@ -11,46 +12,62 @@ Row {
} }
property alias active: menu.active property alias active: menu.active
property color colour: type == CustomSplitButton.Filled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3secondaryContainer property color color: type == CustomSplitButton.Filled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3secondaryContainer
property bool disabled property bool disabled
property color disabledColour: Qt.alpha(DynamicColors.palette.m3onSurface, 0.1) property color disabledColor: Qt.alpha(DynamicColors.palette.m3onSurface, 0.1)
property color disabledTextColour: Qt.alpha(DynamicColors.palette.m3onSurface, 0.38) property color disabledTextColor: Qt.alpha(DynamicColors.palette.m3onSurface, 0.38)
readonly property alias expandBtn: expandBtn
property alias expanded: menu.expanded property alias expanded: menu.expanded
property string fallbackIcon property string fallbackIcon
property string fallbackText property string fallbackText
property real horizontalPadding: Appearance.padding.larger property real horizontalPadding: Appearance.padding.normal
readonly property alias iconLabel: iconLabel property alias iconLabel: iconLabel
readonly property alias label: label property alias label: label
readonly property alias menu: menu property alias menu: menu
property alias menuItems: menu.items property alias menuItems: menu.items
property bool menuOnTop property bool menuOnTop
property real minLeftWidth property alias stateLayer: stateLayer
readonly property alias stateLayer: stateLayer property color textColor: type == CustomSplitButton.Filled ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSecondaryContainer
property color textColour: type == CustomSplitButton.Filled ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSecondaryContainer
readonly property alias textRow: textRow
property int type: CustomSplitButton.Filled property int type: CustomSplitButton.Filled
property real verticalPadding: Appearance.padding.small property real verticalPadding: Appearance.padding.smaller
spacing: Math.floor(Appearance.spacing.extraSmall) function closeDropdown(): void {
SettingsDropdowns.close(menu);
}
function openDropdown(): void {
SettingsDropdowns.open(menu, root);
}
function toggleDropdown(): void {
SettingsDropdowns.toggle(menu, root);
}
spacing: Math.floor(Appearance.spacing.small / 2)
onExpandedChanged: {
if (!expanded)
SettingsDropdowns.forget(menu);
}
CustomRect { CustomRect {
bottomRightRadius: Appearance.rounding.small / 2 bottomRightRadius: Appearance.rounding.small / 2
color: root.disabled ? root.disabledColour : root.colour color: !root.enabled ? root.disabledColor : root.color
implicitHeight: expandBtn.implicitHeight implicitHeight: expandBtn.implicitHeight
implicitWidth: Math.max(root.minLeftWidth, textRow.implicitWidth + root.horizontalPadding * 2) implicitWidth: textRow.implicitWidth + root.horizontalPadding * 2
radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale)
topRightRadius: Appearance.rounding.small / 2 topRightRadius: Appearance.rounding.small / 2
StateLayer { StateLayer {
id: stateLayer id: stateLayer
bottomRightRadius: parent.bottomRightRadius function onClicked(): void {
color: root.textColour root.active?.clicked();
disabled: root.disabled }
topRightRadius: parent.topRightRadius
onClicked: root.active?.clicked() color: root.textColor
disabled: !root.enabled
rect.bottomRightRadius: parent.bottomRightRadius
rect.topRightRadius: parent.topRightRadius
} }
RowLayout { RowLayout {
@@ -65,7 +82,7 @@ Row {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
animate: true animate: true
color: root.disabled ? root.disabledTextColour : root.textColour color: !root.enabled ? root.disabledTextColor : root.textColor
fill: 1 fill: 1
text: root.active?.activeIcon ?? root.fallbackIcon text: root.active?.activeIcon ?? root.fallbackIcon
} }
@@ -77,12 +94,12 @@ Row {
Layout.preferredWidth: implicitWidth Layout.preferredWidth: implicitWidth
animate: true animate: true
clip: true clip: true
color: root.disabled ? root.disabledTextColour : root.textColour color: !root.enabled ? root.disabledTextColor : root.textColor
text: root.active?.activeText ?? root.fallbackText text: root.active?.activeText ?? root.fallbackText
Behavior on Layout.preferredWidth { Behavior on Layout.preferredWidth {
Anim { Anim {
type: Anim.Emphasized easing.bezierCurve: Appearance.anim.curves.emphasized
} }
} }
} }
@@ -95,7 +112,7 @@ Row {
property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) : Appearance.rounding.small / 2 property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) : Appearance.rounding.small / 2
bottomLeftRadius: rad bottomLeftRadius: rad
color: root.disabled ? root.disabledColour : root.colour color: !root.enabled ? root.disabledColor : root.color
implicitHeight: expandIcon.implicitHeight + root.verticalPadding * 2 implicitHeight: expandIcon.implicitHeight + root.verticalPadding * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale)
@@ -109,12 +126,14 @@ Row {
StateLayer { StateLayer {
id: expandStateLayer id: expandStateLayer
color: root.textColour function onClicked(): void {
disabled: root.disabled root.toggleDropdown();
}
color: root.textColor
disabled: !root.enabled
rect.bottomLeftRadius: parent.bottomLeftRadius rect.bottomLeftRadius: parent.bottomLeftRadius
rect.topLeftRadius: parent.topLeftRadius rect.topLeftRadius: parent.topLeftRadius
onClicked: root.expanded = !root.expanded
} }
MaterialIcon { MaterialIcon {
@@ -122,7 +141,7 @@ Row {
anchors.centerIn: parent anchors.centerIn: parent
anchors.horizontalCenterOffset: root.expanded ? 0 : -Math.floor(root.verticalPadding / 4) anchors.horizontalCenterOffset: root.expanded ? 0 : -Math.floor(root.verticalPadding / 4)
color: root.disabled ? root.disabledTextColour : root.textColour color: !root.enabled ? root.disabledTextColor : root.textColor
rotation: root.expanded ? 180 : 0 rotation: root.expanded ? 180 : 0
text: "expand_more" text: "expand_more"
@@ -135,14 +154,24 @@ Row {
} }
} }
} }
}
Menu { Menu {
id: menu id: menu
attachSideY: root.menuOnTop ? Menu.Top : Menu.Bottom anchors.bottomMargin: Appearance.spacing.small
attachTo: expandBtn anchors.right: parent.right
marginY: Appearance.spacing.small * (root.menuOnTop ? -1 : 1) anchors.top: parent.bottom
thisSideY: root.menuOnTop ? Menu.Bottom : Menu.Top anchors.topMargin: Appearance.spacing.small
states: State {
when: root.menuOnTop
AnchorChanges {
anchors.bottom: expandBtn.top
anchors.top: undefined
target: menu
}
}
}
} }
} }
+6 -6
View File
@@ -9,6 +9,7 @@ Item {
property alias active: splitButton.active property alias active: splitButton.active
property alias buttonAlias: splitButton property alias buttonAlias: splitButton
property bool enabled: true
property alias expanded: splitButton.expanded property alias expanded: splitButton.expanded
property int expandedZ: 100 property int expandedZ: 100
required property string label required property string label
@@ -24,7 +25,7 @@ Item {
implicitHeight: row.implicitHeight + Appearance.padding.smaller * 2 implicitHeight: row.implicitHeight + Appearance.padding.smaller * 2
opacity: shouldBeActive ? 1 : 0 opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8 scale: shouldBeActive ? 1 : 0.8
z: splitButton.menu.implicitHeight > 0 ? expandedZ : 1 z: root.expanded ? expandedZ : -1
Behavior on opacity { Behavior on opacity {
Anim { Anim {
@@ -49,6 +50,7 @@ Item {
color: root.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onSurfaceVariant color: root.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.larger font.pointSize: Appearance.font.size.larger
text: root.label text: root.label
z: root.expanded ? root.expandedZ : -1
} }
CustomSplitButton { CustomSplitButton {
@@ -56,16 +58,14 @@ Item {
enabled: root.enabled enabled: root.enabled
type: CustomSplitButton.Filled type: CustomSplitButton.Filled
z: 2 z: root.expanded ? root.expandedZ : -1
menu.onItemSelected: item => { menu.onItemSelected: item => {
root.selected(item); root.selected(item);
// splitButton.closeDropdown(); splitButton.closeDropdown();
} }
stateLayer.onClicked: { stateLayer.onClicked: {
// splitButton.toggleDropdown(); splitButton.toggleDropdown();
splitButton.expanded = !splitButton.expanded;
console.log(root.z);
} }
} }
} }
+12 -14
View File
@@ -1,6 +1,6 @@
import QtQuick import QtQuick
import QtQuick.Shapes
import QtQuick.Templates import QtQuick.Templates
import QtQuick.Shapes
import qs.Config import qs.Config
Switch { Switch {
@@ -13,28 +13,26 @@ Switch {
indicator: CustomRect { indicator: CustomRect {
color: root.checked && root.enabled ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, root.cLayer) color: root.checked && root.enabled ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, root.cLayer)
implicitHeight: Appearance.font.size.medium + Appearance.padding.normal * 2 implicitHeight: 13 + 7 * 2
implicitWidth: implicitHeight * 1.7 implicitWidth: implicitHeight * 1.7
radius: Appearance.rounding.full radius: Appearance.rounding.full
CustomRect { CustomRect {
readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.2 : implicitHeight readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.3 : implicitHeight
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: root.checked && root.enabled ? DynamicColors.palette.m3onPrimary : DynamicColors.layer(DynamicColors.palette.m3outline, root.cLayer + 1) color: root.checked && root.enabled ? DynamicColors.palette.m3onPrimary : DynamicColors.layer(DynamicColors.palette.m3outline, root.cLayer + 1)
implicitHeight: parent.implicitHeight - Appearance.padding.extraSmall implicitHeight: parent.implicitHeight - 10
implicitWidth: nonAnimWidth implicitWidth: nonAnimWidth
radius: Appearance.rounding.full radius: Appearance.rounding.full
x: root.checked ? parent.implicitWidth - nonAnimWidth - Appearance.padding.extraSmall / 2 : Appearance.padding.extraSmall / 2 x: root.checked ? parent.implicitWidth - nonAnimWidth - 10 / 2 : 10 / 2
Behavior on implicitWidth { Behavior on implicitWidth {
Anim { Anim {
type: Anim.FastSpatial
} }
} }
Behavior on x { Behavior on x {
Anim { Anim {
type: Anim.FastSpatial
} }
} }
@@ -46,7 +44,6 @@ Switch {
Behavior on opacity { Behavior on opacity {
Anim { Anim {
type: Anim.DefaultEffects
} }
} }
} }
@@ -66,14 +63,14 @@ Switch {
} }
property point end2: { property point end2: {
if (root.pressed) if (root.pressed)
return Qt.point(width * 0.8, height / 2); return Qt.point(width, height / 2);
if (root.checked) if (root.checked)
return Qt.point(width * 0.85, height * 0.2); return Qt.point(width * 0.85, height * 0.2);
return Qt.point(width * 0.85, height * 0.15); return Qt.point(width * 0.85, height * 0.15);
} }
property point start1: { property point start1: {
if (root.pressed) if (root.pressed)
return Qt.point(width * 0.2, height / 2); return Qt.point(width * 0.1, height / 2);
if (root.checked) if (root.checked)
return Qt.point(width * 0.15, height / 2); return Qt.point(width * 0.15, height / 2);
return Qt.point(width * 0.15, height * 0.15); return Qt.point(width * 0.15, height * 0.15);
@@ -91,7 +88,7 @@ Switch {
anchors.centerIn: parent anchors.centerIn: parent
asynchronous: true asynchronous: true
height: parent.implicitHeight - Appearance.padding.larger height: parent.implicitHeight - Appearance.padding.small * 2
preferredRendererType: Shape.CurveRenderer preferredRendererType: Shape.CurveRenderer
width: height width: height
@@ -113,7 +110,7 @@ Switch {
} }
ShapePath { ShapePath {
capStyle: ShapePath.RoundCap capStyle: Appearance.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
fillColor: "transparent" fillColor: "transparent"
startX: icon.start1.x startX: icon.start1.x
startY: icon.start1.y startY: icon.start1.y
@@ -151,7 +148,8 @@ Switch {
} }
component PropAnim: PropertyAnimation { component PropAnim: PropertyAnimation {
duration: Appearance.anim.durations.expressiveFastSpatial duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial easing.bezierCurve: MaterialEasing.expressiveEffects
easing.type: Easing.BezierSpline
} }
} }
+1 -2
View File
@@ -1,6 +1,6 @@
import qs.Config
import QtQuick import QtQuick
import QtQuick.Effects import QtQuick.Effects
import qs.Config
RectangularShadow { RectangularShadow {
property real dp: [0, 1, 3, 6, 8, 12][level] property real dp: [0, 1, 3, 6, 8, 12][level]
@@ -13,7 +13,6 @@ RectangularShadow {
Behavior on dp { Behavior on dp {
Anim { Anim {
type: Anim.SlowEffects
} }
} }
} }
+4 -4
View File
@@ -54,14 +54,14 @@ CustomRect {
StateLayer { StateLayer {
id: stateLayer id: stateLayer
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour function onClicked(): void {
disabled: root.disabled
onClicked: {
if (root.toggle) if (root.toggle)
root.internalChecked = !root.internalChecked; root.internalChecked = !root.internalChecked;
root.clicked(); root.clicked();
} }
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
disabled: root.disabled
} }
MaterialIcon { MaterialIcon {
+69 -129
View File
@@ -2,169 +2,109 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell
import qs.Config import qs.Config
import qs.Drawers
MouseArea { Elevation {
id: root id: root
enum Side {
Top,
Bottom,
Left,
Right
}
property MenuItem active: items[0] ?? null property MenuItem active: items[0] ?? null
property int attachSideX: Menu.Right
property int attachSideY: Menu.Bottom
required property Item attachTo
property bool expanded property bool expanded
property list<MenuItem> items property list<MenuItem> items
property real marginX
property real marginY
property int thisSideX: Menu.Right
property int thisSideY: Menu.Top
signal itemSelected(item: MenuItem) signal itemSelected(item: MenuItem)
anchors.fill: parent implicitHeight: root.expanded ? column.implicitHeight + Appearance.padding.small * 2 : 0
enabled: expanded implicitWidth: Math.max(200, column.implicitWidth)
layer.enabled: opacity < 1 level: 2
opacity: expanded ? 1 : 0 opacity: root.expanded ? 1 : 0
parent: { radius: Appearance.rounding.normal
const win = QsWindow.window;
const contentWin = win as Windows;
return contentWin ? contentWin.interactionWrapper : (win as QsWindow).contentItem;
}
Behavior on implicitHeight {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Behavior on opacity { Behavior on opacity {
Anim { Anim {
type: Anim.DefaultEffects duration: Appearance.anim.durations.expressiveDefaultSpatial
} }
} }
onClicked: expanded = false CustomClippingRect {
anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainer
radius: parent.radius
TransformWatcher { ColumnLayout {
id: watcher id: column
a: root.parent anchors.left: parent.left
b: root.attachTo anchors.right: parent.right
} anchors.verticalCenter: parent.verticalCenter
spacing: 5
Elevation { Repeater {
id: menu model: root.items
implicitHeight: column.implicitHeight + column.anchors.margins * 2 CustomRect {
implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2) id: item
level: 2
radius: Appearance.rounding.medium
x: {
watcher.transform;
const item = root.attachTo;
let off = root.attachSideX === Menu.Left ? 0 : item.width;
if (root.thisSideX === Menu.Right)
off -= width;
return item.mapToItem(root.parent, off, 0).x + root.marginX;
}
y: {
watcher.transform;
const item = root.attachTo;
let off = root.attachSideY === Menu.Top ? 0 : item.height;
if (root.thisSideY === Menu.Bottom)
off -= height;
return item.mapToItem(root.parent, 0, off).y + root.marginY;
}
transform: Scale { readonly property bool active: modelData === root.active
origin.y: root.thisSideY === Menu.Bottom ? menu.height : 0 required property int index
yScale: root.expanded ? 1 : 0.1 required property MenuItem modelData
Behavior on yScale { Layout.fillWidth: true
Anim { implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.normal * 2
} implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.normal * 2
}
}
CustomRect {
anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainerLow
radius: parent.radius
ColumnLayout {
id: column
anchors.fill: parent
anchors.margins: Appearance.padding.extraSmall
spacing: Appearance.spacing.extraSmall
Repeater {
id: repeater
model: root.items
CustomRect { CustomRect {
id: item anchors.fill: parent
anchors.leftMargin: Appearance.padding.small
readonly property bool active: modelData === root.active anchors.rightMargin: Appearance.padding.small
required property int index color: Qt.alpha(DynamicColors.palette.m3secondaryContainer, active ? 1 : 0)
required property MenuItem modelData radius: Appearance.rounding.normal - Appearance.padding.small
Layout.fillWidth: true
color: Qt.alpha(DynamicColors.palette.m3tertiaryContainer, active ? 1 : 0)
implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.larger * 2
implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.larger * 2
radius: Appearance.rounding.small
Behavior on radius {
Anim {
}
}
StateLayer { StateLayer {
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurface function onClicked(): void {
disabled: !root.expanded
onClicked: {
root.itemSelected(item.modelData); root.itemSelected(item.modelData);
root.active = item.modelData; root.active = item.modelData;
item.modelData.clicked();
root.expanded = false; root.expanded = false;
} }
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
disabled: !root.expanded
}
}
RowLayout {
id: menuOptionRow
anchors.fill: parent
anchors.margins: Appearance.padding.normal
spacing: Appearance.spacing.small
MaterialIcon {
Layout.alignment: Qt.AlignVCenter
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurfaceVariant
text: item.modelData.icon
} }
RowLayout { CustomText {
id: menuOptionRow Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.text
}
anchors.fill: parent Loader {
anchors.margins: Appearance.padding.larger Layout.alignment: Qt.AlignVCenter
spacing: Appearance.spacing.small active: item.modelData.trailingIcon.length > 0
visible: active
MaterialIcon { sourceComponent: MaterialIcon {
Layout.alignment: Qt.AlignVCenter color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant text: item.modelData.trailingIcon
text: item.modelData.icon
}
CustomText {
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.text
}
Loader {
Layout.alignment: Qt.AlignVCenter
active: item.modelData.trailingIcon.length > 0
asynchronous: true
visible: active
sourceComponent: MaterialIcon {
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant
text: item.modelData.trailingIcon
}
} }
} }
} }
+69 -174
View File
@@ -1,53 +1,15 @@
import QtQuick
import QtQuick.Shapes
import ZShell
import ZShell.Components
import qs.Helpers
import qs.Config import qs.Config
import QtQuick
MouseArea { MouseArea {
id: root id: root
property alias bottomLeftRadius: base.bottomLeftRadius property color color: DynamicColors.palette.m3onSurface
property alias bottomRightRadius: base.bottomRightRadius
property real circleRadius
property alias color: base.color
property bool disabled property bool disabled
readonly property real endRadius: { property real radius: parent?.radius ?? 0
const d1 = distSq(0, 0); property alias rect: hoverLayer
const d2 = distSq(width, 0);
const d3 = distSq(0, height);
const d4 = distSq(width, height);
return (Math.sqrt(Math.max(d1, d2, d3, d4)) + (shapeMorph ? 24 : 0)) * 1.3;
}
property real endRadiusAtPress
property bool manualPressOverride
property real pressX: width / 2
property real pressY: height / 2
property alias radius: base.radius
readonly property alias rect: base
property bool shapeMorph
property bool showHoverBackground: true
property real stateOpacity: containsMouse ? 0.08 : 0
property alias topLeftRadius: base.topLeftRadius
property alias topRightRadius: base.topRightRadius
function clamp(r: real): real { function onClicked(): void {
return Math.max(0, Math.min(r, width / 2, height / 2));
}
function distSq(x: real, y: real): real {
return (pressX - x) ** 2 + (pressY - y) ** 2;
}
function press(x: real, y: real): void {
pressX = x;
pressY = y;
fadeAnim.complete();
circleRadius = 0;
circle.opacity = 0.1;
rippleAnim.restart();
endRadiusAtPress = endRadius;
} }
anchors.fill: parent anchors.fill: parent
@@ -55,146 +17,79 @@ MouseArea {
enabled: !disabled enabled: !disabled
hoverEnabled: true hoverEnabled: true
Behavior on stateOpacity { onClicked: event => !disabled && onClicked(event)
onPressed: event => {
if (disabled)
return;
rippleAnim.x = event.x;
rippleAnim.y = event.y;
const dist = (ox, oy) => ox * ox + oy * oy;
rippleAnim.radius = Math.sqrt(Math.max(dist(event.x, event.y), dist(event.x, height - event.y), dist(width - event.x, event.y), dist(width - event.x, height - event.y)));
rippleAnim.restart();
}
SequentialAnimation {
id: rippleAnim
property real radius
property real x
property real y
PropertyAction {
property: "x"
target: ripple
value: rippleAnim.x
}
PropertyAction {
property: "y"
target: ripple
value: rippleAnim.y
}
PropertyAction {
property: "opacity"
target: ripple
value: 0.08
}
Anim { Anim {
type: Anim.DefaultEffects easing.bezierCurve: MaterialEasing.standardDecel
from: 0
properties: "implicitWidth,implicitHeight"
target: ripple
to: rippleAnim.radius * 2
}
Anim {
property: "opacity"
target: ripple
to: 0
} }
} }
onCircleRadiusChanged: { CustomClippingRect {
if (!(pressed || manualPressOverride) && circleRadius > endRadiusAtPress * 0.99 && !fadeAnim.running) id: hoverLayer
fadeAnim.start();
}
onClicked: event => !disabled && onClicked(event)
onManualPressOverrideChanged: {
if (!(pressed || manualPressOverride) && circleRadius > endRadiusAtPress * 0.99 && !fadeAnim.running)
fadeAnim.start();
}
onPressed: e => press(e.x, e.y)
onPressedChanged: {
if (!(pressed || manualPressOverride) && !rippleAnim.running && circle.opacity > 0)
fadeAnim.start();
}
Anim {
id: rippleAnim
alwaysRunToEnd: true
duration: Appearance.anim.durations.expressiveSlowEffects * 2
easing.bezierCurve: Appearance.anim.curves.standard
property: "circleRadius"
target: root
to: root.endRadius
}
Anim {
id: fadeAnim
property: "opacity"
target: circle
to: 0
type: Anim.SlowEffects
}
CustomRect {
id: base
anchors.fill: parent anchors.fill: parent
bottomLeftRadius: root.parent?.bottomLeftRadius ?? radius ?? 0 border.pixelAligned: false
bottomRightRadius: root.parent?.bottomRightRadius ?? radius ?? 0 color: Qt.alpha(root.color, root.disabled ? 0 : root.pressed ? 0.1 : root.containsMouse ? 0.08 : 0)
color: DynamicColors.palette.m3onSurface radius: root.radius
opacity: root.stateOpacity
// Pick up radius from parent if it has one (parent can be anything with radius props)
// qmllint disable missing-property
radius: root.parent?.radius ?? 0
topLeftRadius: root.parent?.topLeftRadius ?? radius ?? 0
topRightRadius: root.parent?.topRightRadius ?? radius ?? 0
// qmllint enable missing-property
}
Shape { CustomRect {
id: circle id: ripple
anchors.fill: parent border.pixelAligned: false
opacity: 0 color: root.color
preferredRendererType: Shape.CurveRenderer opacity: 0
radius: Appearance.rounding.full
ShapePath { transform: Translate {
fillColor: base.color x: -ripple.width / 2
startX: root.clamp(base.topLeftRadius) y: -ripple.height / 2
startY: 0
strokeColor: "transparent"
strokeWidth: 0
fillGradient: RadialGradient {
centerRadius: root.circleRadius
centerX: root.pressX
centerY: root.pressY
focalX: centerX
focalY: centerY
GradientStop {
color: Qt.alpha(base.color, 1)
position: 0
}
GradientStop {
color: Qt.alpha(base.color, 1)
position: ZUtils.clamp(1 - 0.2 * root.endRadius / root.circleRadius, 0.01, 0.99)
}
GradientStop {
color: Qt.alpha(base.color, ZUtils.clamp((root.circleRadius / root.endRadius - 0.9) / 0.1, 0, 1))
position: 1
}
}
PathLine {
x: root.width - root.clamp(base.topRightRadius)
y: 0
}
PathArc {
radiusX: root.clamp(base.topRightRadius)
radiusY: root.clamp(base.topRightRadius)
relativeX: root.clamp(base.topRightRadius)
relativeY: root.clamp(base.topRightRadius)
}
PathLine {
x: root.width
y: root.height - root.clamp(base.bottomRightRadius)
}
PathArc {
radiusX: root.clamp(base.bottomRightRadius)
radiusY: root.clamp(base.bottomRightRadius)
relativeX: -root.clamp(base.bottomRightRadius)
relativeY: root.clamp(base.bottomRightRadius)
}
PathLine {
x: root.clamp(base.bottomLeftRadius)
y: root.height
}
PathArc {
radiusX: root.clamp(base.bottomLeftRadius)
radiusY: root.clamp(base.bottomLeftRadius)
relativeX: -root.clamp(base.bottomLeftRadius)
relativeY: -root.clamp(base.bottomLeftRadius)
}
PathLine {
x: 0
y: root.clamp(base.topLeftRadius)
}
PathArc {
radiusX: root.clamp(base.topLeftRadius)
radiusY: root.clamp(base.topLeftRadius)
x: root.clamp(base.topLeftRadius)
y: 0
} }
} }
} }
+2
View File
@@ -7,6 +7,8 @@ Singleton {
readonly property AppearanceConf.Deform deform: Config.appearance.deform readonly property AppearanceConf.Deform deform: Config.appearance.deform
readonly property AppearanceConf.FontStuff font: Config.appearance.font readonly property AppearanceConf.FontStuff font: Config.appearance.font
readonly property AppearanceConf.Padding padding: Config.appearance.padding readonly property AppearanceConf.Padding padding: Config.appearance.padding
// Literally just here to shorten accessing stuff :woe:
// Also kinda so I can keep accessing it with `Appearance.xxx` instead of `Conf.appearance.xxx`
readonly property AppearanceConf.Rounding rounding: Config.appearance.rounding readonly property AppearanceConf.Rounding rounding: Config.appearance.rounding
readonly property AppearanceConf.Spacing spacing: Config.appearance.spacing readonly property AppearanceConf.Spacing spacing: Config.appearance.spacing
readonly property AppearanceConf.Transparency transparency: Config.appearance.transparency readonly property AppearanceConf.Transparency transparency: Config.appearance.transparency
+4 -16
View File
@@ -28,13 +28,9 @@ JsonObject {
property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1] property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1] property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1] property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
property list<real> expressiveDefaultEffects: [0.34, 0.8, 0.34, 1, 1, 1]
property list<real> expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1, 1, 1] property list<real> expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1, 1, 1]
property list<real> expressiveEffects: [0.34, 0.8, 0.34, 1, 1, 1] property list<real> expressiveEffects: [0.34, 0.8, 0.34, 1, 1, 1]
property list<real> expressiveFastEffects: [0.31, 0.94, 0.34, 1, 1, 1]
property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1] property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1]
property list<real> expressiveSlowEffects: [0.34, 0.88, 0.34, 1, 1, 1]
property list<real> expressiveSlowSpatial: [0.39, 1.29, 0.35, 0.98, 1, 1]
property list<real> standard: [0.2, 0, 0, 1, 1, 1] property list<real> standard: [0.2, 0, 0, 1, 1, 1]
property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1] property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1]
property list<real> standardDecel: [0, 0, 0, 1, 1, 1] property list<real> standardDecel: [0, 0, 0, 1, 1, 1]
@@ -42,9 +38,7 @@ JsonObject {
component AnimDurations: JsonObject { component AnimDurations: JsonObject {
property int expressiveDefaultSpatial: 500 * scale property int expressiveDefaultSpatial: 500 * scale
property int expressiveEffects: 200 * scale property int expressiveEffects: 200 * scale
property int expressiveFastEffects: 150 * scale
property int expressiveFastSpatial: 350 * scale property int expressiveFastSpatial: 350 * scale
property int expressiveSlowEffects: 300 * scale
property int extraLarge: 1000 * scale property int extraLarge: 1000 * scale
property int large: 600 * scale property int large: 600 * scale
property int normal: 400 * scale property int normal: 400 * scale
@@ -63,8 +57,7 @@ JsonObject {
component FontSize: JsonObject { component FontSize: JsonObject {
property int extraLarge: 28 * scale property int extraLarge: 28 * scale
property int large: 18 * scale property int large: 18 * scale
property int larger: 16 * scale property int larger: 15 * scale
property int medium: 14 * scale
property int normal: 13 * scale property int normal: 13 * scale
property real scale: 1 property real scale: 1
property int small: 11 * scale property int small: 11 * scale
@@ -77,28 +70,23 @@ JsonObject {
} }
} }
component Padding: JsonObject { component Padding: JsonObject {
property int extraLargeIncreased: 32 * scale property int large: 15 * scale
property int extraSmall: 4 * scale property int larger: 13 * scale
property int large: 16 * scale property int normal: 9 * scale
property int larger: 12 * scale
property int normal: 8 * scale
property real scale: 1 property real scale: 1
property int small: 5 * scale property int small: 5 * scale
property int smaller: 7 * scale property int smaller: 7 * scale
property int smallest: 2 * scale property int smallest: 2 * scale
} }
component Rounding: JsonObject { component Rounding: JsonObject {
property int extraSmall: 4 * scale
property int full: 1000 * scale property int full: 1000 * scale
property int large: 24 * scale property int large: 24 * scale
property int medium: 16 * scale
property int normal: 18 * scale property int normal: 18 * scale
property real scale: 1 property real scale: 1
property int small: 12 * scale property int small: 12 * scale
property int smallest: 8 * scale property int smallest: 8 * scale
} }
component Spacing: JsonObject { component Spacing: JsonObject {
property int extraSmall: 4 * scale
property int large: 20 * scale property int large: 20 * scale
property int larger: 16 * scale property int larger: 16 * scale
property int normal: 12 * scale property int normal: 12 * scale
-25
View File
@@ -1,25 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
Variants {
model: Quickshell.screens
Scope {
id: scope
required property ShellScreen modelData
Exclusions {
bar: content.bar
screen: scope.modelData
}
Windows {
id: content
screen: scope.modelData
}
}
}
+1 -1
View File
@@ -59,7 +59,7 @@ Item {
cursorShape: (active && centroid.pressPosition.y < root.bar.implicitHeight) ? Qt.ClosedHandCursor : undefined cursorShape: (active && centroid.pressPosition.y < root.bar.implicitHeight) ? Qt.ClosedHandCursor : undefined
dragThreshold: 0 dragThreshold: 0
grabPermissions: PointerHandler.CanTakeOverFromHandlersOfSameType | PointerHandler.ApprovesTakeOverByAnything grabPermissions: PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything
maximumPointCount: 1 maximumPointCount: 1
minimumPointCount: 1 minimumPointCount: 1
target: null target: null
+362 -345
View File
@@ -9,380 +9,397 @@ import Quickshell.Hyprland
import ZShell.Blobs import ZShell.Blobs
import qs.Daemons import qs.Daemons
import qs.Components import qs.Components
import qs.Modules
import qs.Modules.Bar import qs.Modules.Bar
import qs.Config import qs.Config
import qs.Helpers import qs.Helpers
import qs.Drawers import qs.Drawers
CustomWindow { Variants {
id: root model: Quickshell.screens
readonly property alias bar: bar Scope {
readonly property bool hasFullscreen: Hypr.monitorFor(screen)?.activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen === 2) id: scope
readonly property alias interactionWrapper: interactions
property var root: Quickshell.shellDir
WlrLayershell.exclusionMode: ExclusionMode.Ignore required property var modelData
// WlrLayershell.keyboardFocus: visibilities.dock || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || visibilities.resources ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
color: "transparent"
contentItem.focus: true
mask: visibilities.isDrawing ? null : region
name: "Bar"
contentItem.Keys.onEscapePressed: { Exclusions {
if (Config.barConfig.autoHide) bar: bar
visibilities.bar = false; screen: scope.modelData
visibilities.sidebar = false;
visibilities.dashboard = false;
visibilities.osd = false;
visibilities.settings = false;
visibilities.resources = false;
}
onHasFullscreenChanged: {
visibilities.launcher = false;
visibilities.dashboard = false;
visibilities.osd = false;
visibilities.settings = false;
visibilities.resources = false;
}
Region {
id: region
height: root.height - bar.implicitHeight - Config.barConfig.border
intersection: Intersection.Xor
regions: popoutRegions.instances
width: root.width - Config.barConfig.border * 2
x: Config.barConfig.border
y: bar.implicitHeight
}
anchors {
bottom: true
left: true
right: true
top: true
}
Variants {
id: popoutRegions
model: panels.children
Region {
required property Item modelData
height: modelData.height
intersection: Intersection.Subtract
width: modelData.width
x: modelData.x + Config.barConfig.border
y: modelData.y + bar.implicitHeight
}
}
HyprlandFocusGrab {
id: focusGrab
active: visibilities.dock || visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu"))
windows: [root]
onCleared: {
visibilities.launcher = false;
visibilities.sidebar = false;
visibilities.dashboard = false;
visibilities.osd = false;
visibilities.settings = false;
visibilities.resources = false;
visibilities.dock = false;
panels.popouts.hasCurrent = false;
}
}
PersistentProperties {
id: visibilities
property bool bar
property bool dashboard
property bool dock
property bool isDrawing
property bool launcher
property bool notif: NotifServer.popups.length > 0
property bool osd
property bool resources
property bool settings
property bool sidebar
Component.onCompleted: Visibilities.load(root.screen, this)
}
IpcHandler {
function toggleLauncher(fix: string): void {
visibilities.launcher = !visibilities.launcher;
} }
target: "visibilities" CustomWindow {
} id: win
Binding { readonly property bool hasFullscreen: Hypr.monitorFor(screen)?.activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen === 2)
property: "bar" property var root: Quickshell.shellDir
target: visibilities
value: visibilities.sidebar || visibilities.dashboard || visibilities.osd || (!Config.barConfig.hideWhenNotif && visibilities.notif) || visibilities.resources || visibilities.settings || bar.isHovered
when: Config.barConfig.autoHide
}
Item { WlrLayershell.exclusionMode: ExclusionMode.Ignore
anchors.fill: parent // WlrLayershell.keyboardFocus: visibilities.dock || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || visibilities.resources ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
layer.enabled: true color: "transparent"
opacity: Appearance.transparency.enabled ? DynamicColors.transparency.base : 1 contentItem.focus: true
mask: visibilities.isDrawing ? null : region
name: "Bar"
screen: scope.modelData
layer.effect: MultiEffect { contentItem.Keys.onEscapePressed: {
blurMax: 32 if (Config.barConfig.autoHide)
shadowColor: Qt.alpha(DynamicColors.palette.m3shadow, 1) visibilities.bar = false;
shadowEnabled: true visibilities.sidebar = false;
} visibilities.dashboard = false;
visibilities.osd = false;
visibilities.settings = false;
visibilities.resources = false;
}
onHasFullscreenChanged: {
visibilities.launcher = false;
visibilities.dashboard = false;
visibilities.osd = false;
visibilities.settings = false;
visibilities.resources = false;
}
BlobGroup { Region {
id: blobGroup id: region
color: DynamicColors.palette.m3surface height: win.height - bar.implicitHeight - Config.barConfig.border
smoothing: Config.barConfig.smoothing intersection: Intersection.Xor
regions: popoutRegions.instances
width: win.width - Config.barConfig.border * 2
x: Config.barConfig.border
y: bar.implicitHeight
}
Behavior on color { anchors {
CAnim { bottom: true
left: true
right: true
top: true
}
Variants {
id: popoutRegions
model: panels.children
Region {
required property Item modelData
height: modelData.height
intersection: Intersection.Subtract
width: modelData.width
x: modelData.x + Config.barConfig.border
y: modelData.y + bar.implicitHeight
} }
} }
}
BlobInvertedRect { HyprlandFocusGrab {
anchors.fill: parent id: focusGrab
anchors.margins: -50
borderBottom: Config.barConfig.border - anchors.margins
borderLeft: Config.barConfig.border - anchors.margins
borderRight: Config.barConfig.border - anchors.margins
borderTop: bar.implicitHeight - anchors.margins
group: blobGroup
radius: Config.barConfig.rounding
}
PanelBg { active: visibilities.dock || visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu"))
id: dashBg windows: [win]
property real extraHeight: 0.2 onCleared: {
visibilities.launcher = false;
deformAmount: 0.06 visibilities.sidebar = false;
implicitHeight: panels.dashboard.height * (1 + extraHeight) visibilities.dashboard = false;
implicitWidth: panels.dashboard.width visibilities.osd = false;
panel: panels.dashboardWrapper visibilities.settings = false;
radius: Appearance.rounding.normal visibilities.resources = false;
x: panels.dashboardWrapper.x + panels.dashboard.x + Config.barConfig.border visibilities.dock = false;
y: panels.dashboardWrapper.y + panels.dashboard.y + bar.implicitHeight - panels.dashboard.height * extraHeight panels.popouts.hasCurrent = false;
}
PanelBg {
id: launcherBg
property real extraHeight: 0.2
deformAmount: 0.06
implicitHeight: panels.launcher.height * (1 + extraHeight)
panel: panels.launcher
radius: Appearance.rounding.smallest + 5
y: panels.launcher.y + bar.implicitHeight
}
PanelBg {
id: sidebarBg
bottomLeftRadius: 0
deformAmount: 0.04
exclude: panels.sidebar.offsetScale > 0.08 ? [] : [utilsBg]
implicitHeight: panel.height * (1 / rawDeformMatrix.m22) + 2
panel: panels.sidebar
}
PanelBg {
id: osdBg
deformAmount: 0.1
implicitHeight: panels.osd.height
implicitWidth: panels.osd.width
panel: panels.osdWrapper
radius: 20
x: panels.osdWrapper.x + panels.osd.x + Config.barConfig.border
y: panels.osdWrapper.y + panels.osd.y + bar.implicitHeight
}
PanelBg {
id: notifsBg
panel: panels.notifications
radius: Appearance.rounding.normal
}
PanelBg {
id: utilsBg
deformAmount: panels.sidebar.visible ? (0.1) : (0.1)
exclude: panels.sidebar.offsetScale > 0.08 ? [] : [sidebarBg]
panel: panels.utilities
topLeftRadius: 0
}
PanelBg {
id: popoutBg
property real extraHeight: panels.popouts.isDetached ? 0 : 0.2
deformAmount: panels.popouts.isDetached ? 0.05 : panels.popouts.hasCurrent ? 0.15 : 0.1
implicitHeight: panels.popouts.height * (1 + extraHeight)
implicitWidth: panels.popouts.width
panel: panels.popoutsWrapper
radius: (panels.popouts.currentName.startsWith("audio") || panels.popouts.currentName.startsWith("updates")) ? Appearance.rounding.normal : 20 * Appearance.rounding.scale
x: panels.popoutsWrapper.x + panels.popouts.x + Config.barConfig.border
y: panels.popoutsWrapper.y + panels.popouts.y + bar.implicitHeight - panels.popouts.height * extraHeight
Behavior on extraHeight {
Anim {
} }
} }
}
PanelBg { PersistentProperties {
id: resourcesBg id: visibilities
deformAmount: 0.05 property bool bar
implicitHeight: panels.resources.height property bool dashboard
implicitWidth: panels.resources.width property bool dock
panel: panels.resourcesWrapper property bool isDrawing
radius: Appearance.rounding.normal property bool launcher
x: panels.resourcesWrapper.x + panels.resources.x + Config.barConfig.border property bool notif: NotifServer.popups.length > 0
y: panels.resourcesWrapper.y + panels.resources.y + bar.implicitHeight property bool osd
} property bool resources
property bool settings
property bool sidebar
PanelBg { Component.onCompleted: Visibilities.load(scope.modelData, this)
id: settingsBg
property real extraHeight: 0.2
deformAmount: 0.03
implicitHeight: panels.settings.height * (1 + extraHeight)
implicitWidth: panels.settings.width
panel: panels.settings
radius: Appearance.rounding.large
topLeftRadius: Appearance.rounding.large + Appearance.padding.smaller
topRightRadius: Appearance.rounding.large + Appearance.padding.smaller
x: panels.settingsWrapper.x + panels.settings.x + Config.barConfig.border
y: panels.settingsWrapper.y + panels.settings.y + bar.implicitHeight - panels.settings.height * extraHeight
}
PanelBg {
id: dockBg
deformAmount: 0.08
panel: panels.dock
radius: Appearance.rounding.normal
}
PanelBg {
id: drawingBg
deformAmount: 0.08
panel: panels.drawing
radius: Appearance.rounding.normal
}
}
Loader {
id: drawingLoader
active: visibilities.isDrawing
anchors.fill: parent
sourceComponent: Drawing {
id: drawing
}
}
Loader {
id: inputLoader
active: visibilities.isDrawing
anchors.fill: parent
z: 2
sourceComponent: DrawingInput {
id: input
bar: bar
drawing: drawingLoader.item
panels: panels
popout: panels.drawing
visibilities: visibilities
}
}
Interactions {
id: interactions
anchors.fill: parent
bar: bar
drawing: drawingLoader.item
enabled: true
input: inputLoader.item
panels: panels
popouts: panels.popouts
screen: root.screen
visibilities: visibilities
Panels {
id: panels
bar: bar
drawingItem: drawingLoader.item
screen: root.screen
visibilities: visibilities
dashboard.transform: Matrix4x4 {
matrix: dashBg.deformMatrix
} }
dock.transform: Matrix4x4 {
matrix: dockBg.deformMatrix
}
launcher.transform: Matrix4x4 {
matrix: launcherBg.deformMatrix
}
notifications.transform: Matrix4x4 {
matrix: notifsBg.deformMatrix
}
osd.transform: Matrix4x4 {
matrix: osdBg.deformMatrix
}
popouts.transform: Matrix4x4 {
matrix: popoutBg.deformMatrix
}
resources.transform: Matrix4x4 {
matrix: resourcesBg.deformMatrix
}
settings.transform: Matrix4x4 {
matrix: settingsBg.deformMatrix
}
sidebar.transform: Matrix4x4 {
matrix: sidebarBg.deformMatrix
}
utilities.transform: Matrix4x4 {
matrix: utilsBg.deformMatrix
}
}
BarLoader { IpcHandler {
id: bar function toggleLauncher(fix: string): void {
visibilities.launcher = !visibilities.launcher;
}
anchors.left: parent.left target: "visibilities"
anchors.right: parent.right }
popouts: panels.popouts
popoutsWrapper: panels.popoutsWrapper Binding {
screen: root.screen property: "bar"
visibilities: visibilities target: visibilities
value: visibilities.sidebar || visibilities.dashboard || visibilities.osd || (!Config.barConfig.hideWhenNotif && visibilities.notif) || visibilities.resources || visibilities.settings || bar.isHovered
when: Config.barConfig.autoHide
}
Item {
anchors.fill: parent
layer.enabled: true
opacity: Appearance.transparency.enabled ? DynamicColors.transparency.base : 1
layer.effect: MultiEffect {
blurMax: 32
shadowColor: Qt.alpha(DynamicColors.palette.m3shadow, 1)
shadowEnabled: true
}
BlobGroup {
id: blobGroup
color: DynamicColors.palette.m3surface
smoothing: Config.barConfig.smoothing
Behavior on color {
CAnim {
}
}
}
BlobInvertedRect {
anchors.fill: parent
anchors.margins: -50
borderBottom: Config.barConfig.border - anchors.margins
borderLeft: Config.barConfig.border - anchors.margins
borderRight: Config.barConfig.border - anchors.margins
borderTop: bar.implicitHeight - anchors.margins
group: blobGroup
radius: Config.barConfig.rounding
}
PanelBg {
id: dashBg
property real extraHeight: 0.2
deformAmount: 0.06
implicitHeight: panels.dashboard.height * (1 + extraHeight)
implicitWidth: panels.dashboard.width
panel: panels.dashboardWrapper
radius: Appearance.rounding.normal
x: panels.dashboardWrapper.x + panels.dashboard.x + Config.barConfig.border
y: panels.dashboardWrapper.y + panels.dashboard.y + bar.implicitHeight - panels.dashboard.height * extraHeight
}
PanelBg {
id: launcherBg
property real extraHeight: 0.2
deformAmount: 0.06
implicitHeight: panels.launcher.height * (1 + extraHeight)
panel: panels.launcher
radius: Appearance.rounding.smallest + 5
y: panels.launcher.y + bar.implicitHeight
}
PanelBg {
id: sidebarBg
bottomLeftRadius: 0
deformAmount: 0.04
exclude: panels.sidebar.offsetScale > 0.08 ? [] : [utilsBg]
implicitHeight: panel.height * (1 / rawDeformMatrix.m22) + 2
panel: panels.sidebar
}
PanelBg {
id: osdBg
deformAmount: 0.1
implicitHeight: panels.osd.height
implicitWidth: panels.osd.width
panel: panels.osdWrapper
radius: 20
x: panels.osdWrapper.x + panels.osd.x + Config.barConfig.border
y: panels.osdWrapper.y + panels.osd.y + bar.implicitHeight
}
PanelBg {
id: notifsBg
panel: panels.notifications
radius: Appearance.rounding.normal
}
PanelBg {
id: utilsBg
deformAmount: panels.sidebar.visible ? (0.1) : (0.1)
exclude: panels.sidebar.offsetScale > 0.08 ? [] : [sidebarBg]
panel: panels.utilities
topLeftRadius: 0
}
PanelBg {
id: popoutBg
property real extraHeight: panels.popouts.isDetached ? 0 : 0.2
deformAmount: panels.popouts.isDetached ? 0.05 : panels.popouts.hasCurrent ? 0.15 : 0.1
implicitHeight: panels.popouts.height * (1 + extraHeight)
implicitWidth: panels.popouts.width
panel: panels.popoutsWrapper
radius: (panels.popouts.currentName.startsWith("audio") || panels.popouts.currentName.startsWith("updates")) ? Appearance.rounding.normal : 20 * Appearance.rounding.scale
x: panels.popoutsWrapper.x + panels.popouts.x + Config.barConfig.border
y: panels.popoutsWrapper.y + panels.popouts.y + bar.implicitHeight - panels.popouts.height * extraHeight
Behavior on extraHeight {
Anim {
}
}
}
PanelBg {
id: resourcesBg
deformAmount: 0.05
implicitHeight: panels.resources.height
implicitWidth: panels.resources.width
panel: panels.resourcesWrapper
radius: Appearance.rounding.normal
x: panels.resourcesWrapper.x + panels.resources.x + Config.barConfig.border
y: panels.resourcesWrapper.y + panels.resources.y + bar.implicitHeight
}
PanelBg {
id: settingsBg
property real extraHeight: 0.2
deformAmount: 0.03
implicitHeight: panels.settings.height * (1 + extraHeight)
implicitWidth: panels.settings.width
panel: panels.settings
radius: Appearance.rounding.large
topLeftRadius: Appearance.rounding.large + Appearance.padding.smaller
topRightRadius: Appearance.rounding.large + Appearance.padding.smaller
x: panels.settingsWrapper.x + panels.settings.x + Config.barConfig.border
y: panels.settingsWrapper.y + panels.settings.y + bar.implicitHeight - panels.settings.height * extraHeight
}
PanelBg {
id: dockBg
deformAmount: 0.08
panel: panels.dock
radius: Appearance.rounding.normal
}
PanelBg {
id: drawingBg
deformAmount: 0.08
panel: panels.drawing
radius: Appearance.rounding.normal
}
}
Loader {
id: drawingLoader
active: visibilities.isDrawing
anchors.fill: parent
z: 2
sourceComponent: Drawing {
id: drawing
}
}
Loader {
id: inputLoader
active: visibilities.isDrawing
anchors.fill: parent
z: 2
sourceComponent: DrawingInput {
id: input
bar: bar
drawing: drawingLoader.item
panels: panels
popout: panels.drawing
visibilities: visibilities
}
}
Interactions {
id: mouseArea
anchors.fill: parent
bar: bar
drawing: drawingLoader.item
enabled: true
input: inputLoader.item
panels: panels
popouts: panels.popouts
screen: scope.modelData
visibilities: visibilities
z: 1
Panels {
id: panels
bar: bar
drawingItem: drawingLoader.item
screen: scope.modelData
visibilities: visibilities
dashboard.transform: Matrix4x4 {
matrix: dashBg.deformMatrix
}
dock.transform: Matrix4x4 {
matrix: dockBg.deformMatrix
}
launcher.transform: Matrix4x4 {
matrix: launcherBg.deformMatrix
}
notifications.transform: Matrix4x4 {
matrix: notifsBg.deformMatrix
}
osd.transform: Matrix4x4 {
matrix: osdBg.deformMatrix
}
popouts.transform: Matrix4x4 {
matrix: popoutBg.deformMatrix
}
resources.transform: Matrix4x4 {
matrix: resourcesBg.deformMatrix
}
settings.transform: Matrix4x4 {
matrix: settingsBg.deformMatrix
}
sidebar.transform: Matrix4x4 {
matrix: sidebarBg.deformMatrix
}
utilities.transform: Matrix4x4 {
matrix: utilsBg.deformMatrix
}
}
BarLoader {
id: bar
anchors.left: parent.left
anchors.right: parent.right
popouts: panels.popouts
popoutsWrapper: panels.popoutsWrapper
screen: scope.modelData
visibilities: visibilities
}
}
} }
} }
+7 -7
View File
@@ -118,12 +118,12 @@ ColumnLayout {
} }
StateLayer { StateLayer {
cursorShape: Qt.IBeamCursor function onClicked(): void {
hoverEnabled: false
onClicked: {
parent.forceActiveFocus(); parent.forceActiveFocus();
} }
cursorShape: Qt.IBeamCursor
hoverEnabled: false
} }
RowLayout { RowLayout {
@@ -179,11 +179,11 @@ ColumnLayout {
radius: Appearance.rounding.full radius: Appearance.rounding.full
StateLayer { StateLayer {
color: root.greeter.buffer && !root.greeter.launching ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface function onClicked(): void {
onClicked: {
root.greeter.submit(); root.greeter.submit();
} }
color: root.greeter.buffer && !root.greeter.launching ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
} }
MaterialIcon { MaterialIcon {
+3 -58
View File
@@ -2,62 +2,7 @@ import QtQuick
import qs.Config import qs.Config
NumberAnimation { NumberAnimation {
enum Type { duration: MaterialEasing.standardTime
StandardSmall = 0, easing.bezierCurve: MaterialEasing.standard
Standard, easing.type: Easing.BezierSpline
StandardLarge,
StandardExtraLarge,
EmphasizedSmall,
Emphasized,
EmphasizedLarge,
EmphasizedExtraLarge,
FastSpatial,
DefaultSpatial,
SlowSpatial,
FastEffects,
DefaultEffects,
SlowEffects
}
property int type: Anim.DefaultSpatial
duration: {
if (type < Anim.StandardSmall || type > Anim.SlowEffects)
return Appearance.anim.durations.normal;
if (type === Anim.FastSpatial)
return Appearance.anim.durations.expressiveFastSpatial;
if (type === Anim.DefaultSpatial)
return Appearance.anim.durations.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial)
return Appearance.anim.durations.large;
if (type === Anim.FastEffects)
return Appearance.anim.durations.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Appearance.anim.durations.expressiveEffects;
if (type === Anim.SlowEffects)
return Appearance.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4; // 0-7 are the 4 standard types
return Appearance.anim.durations[types[idx]];
}
easing.bezierCurve: {
if (type === Anim.FastSpatial)
return Appearance.anim.curves.expressiveFastSpatial;
if (type === Anim.DefaultSpatial)
return Appearance.anim.curves.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial)
return Appearance.anim.curves.expressiveSlowSpatial;
if (type === Anim.FastEffects)
return Appearance.anim.curves.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Appearance.anim.curves.expressiveDefaultEffects;
if (type === Anim.SlowEffects)
return Appearance.anim.curves.expressiveSlowEffects;
if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Appearance.anim.curves.emphasized;
return Appearance.anim.curves.standard;
}
} }
+5 -5
View File
@@ -59,15 +59,15 @@ ColumnLayout {
} }
StateLayer { StateLayer {
function onClicked(): void {
root.toggleRequested();
root.expanded = !root.expanded;
}
anchors.fill: parent anchors.fill: parent
color: DynamicColors.palette.m3onSurface color: DynamicColors.palette.m3onSurface
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
showHoverBackground: false showHoverBackground: false
onClicked: {
root.toggleRequested();
root.expanded = !root.expanded;
}
} }
} }
+3 -3
View File
@@ -23,10 +23,10 @@ Button {
} }
StateLayer { StateLayer {
radius: control.radius function onClicked(): void {
onClicked: {
control.clicked(); control.clicked();
} }
radius: control.radius
} }
} }
+4 -4
View File
@@ -33,13 +33,13 @@ RadioButton {
} }
StateLayer { StateLayer {
function onClicked(): void {
root.click();
}
anchors.margins: -7 anchors.margins: -7
color: root.checked ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3primary color: root.checked ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3primary
z: -1 z: -1
onClicked: {
root.click();
}
} }
CustomRect { CustomRect {
+27 -156
View File
@@ -1,174 +1,45 @@
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Templates import QtQuick.Templates
import ZShell.Components
import ZShell
import qs.Components
import qs.Config import qs.Config
Slider { Slider {
id: root id: root
property bool animateWave background: Item {
property color bgColor: enabled ? DynamicColors.palette.m3secondaryContainer : Qt.alpha(DynamicColors.palette.m3onSurface, 0.1)
property color fgColor: enabled ? DynamicColors.palette.m3primary : Qt.alpha(DynamicColors.palette.m3onSurface, 0.38)
property real filledWidth
property real pos: visualPosition
property int waveDuration: 1000
property real waveFrequency: 6
property bool wavy
signal interaction(v: real)
implicitHeight: 12
implicitWidth: 200
contentItem: Item {
anchors.fill: parent
CustomRect { CustomRect {
id: remaining anchors.bottom: parent.bottom
anchors.left: handle.right
anchors.leftMargin: Appearance.spacing.extraSmall
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
bottomLeftRadius: Appearance.rounding.extraSmall / 2
color: root.bgColor
implicitHeight: parent.height * (parent.height <= 12 ? opacity : Math.min(opacity * 2, 1))
opacity: Math.min(width, 12) / 12
radius: Appearance.rounding.small
topLeftRadius: Appearance.rounding.extraSmall / 2
}
CustomRect {
anchors.right: parent.right
anchors.rightMargin: 4 * remaining.opacity
anchors.verticalCenter: parent.verticalCenter
color: root.fgColor
implicitHeight: 4 * remaining.opacity
implicitWidth: implicitHeight
opacity: remaining.opacity
radius: Appearance.rounding.full
}
CustomRect {
id: handle
anchors.left: filled.right
anchors.leftMargin: Appearance.spacing.extraSmall
anchors.verticalCenter: parent.verticalCenter
color: root.fgColor
implicitHeight: {
const mult = parent.height <= 12 ? 3 : 1.2;
const pressMult = parent.height <= 12 ? 4 : 1.5;
return parent.height * (mouse.pressed ? pressMult : mult);
}
implicitWidth: 4
radius: Appearance.rounding.full
Behavior on implicitHeight {
Anim {
type: Anim.FastSpatial
}
}
}
Loader {
id: filled
anchors.left: parent.left anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter anchors.top: parent.top
asynchronous: true bottomRightRadius: root.implicitHeight / 6
sourceComponent: root.wavy ? waveComp : lineComp color: DynamicColors.palette.m3primary
implicitWidth: root.handle.x - root.implicitHeight / 2
radius: Appearance.rounding.full
topRightRadius: root.implicitHeight / 6
} }
Component { CustomRect {
id: lineComp anchors.bottom: parent.bottom
anchors.right: parent.right
CustomRect { anchors.top: parent.top
bottomRightRadius: Appearance.rounding.extraSmall / 2 bottomLeftRadius: root.implicitHeight / 6
color: root.fgColor color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: root.height implicitWidth: parent.width - root.handle.x - root.handle.implicitWidth - root.implicitHeight / 2
implicitWidth: root.filledWidth radius: Appearance.rounding.full
radius: Appearance.rounding.small topLeftRadius: root.implicitHeight / 6
topRightRadius: Appearance.rounding.extraSmall / 2
}
}
Component {
id: waveComp
WavyLine {
color: root.fgColor
frequency: root.waveFrequency
fullLength: root.width - handle.implicitWidth - handle.anchors.leftMargin
implicitHeight: lineWidth * amplitudeMultiplier * 2 + lineWidth
implicitWidth: root.filledWidth
lineWidth: root.height * 0.7
startX: x
Behavior on color {
CAnim {
}
}
Anim on waveProgress {
duration: root.waveDuration
easing.type: Easing.Linear
from: 0
loops: Animation.Infinite
paused: !root.animateWave
running: true
to: 1
}
}
} }
} }
Behavior on filledWidth { handle: CustomRect {
id: widthBehavior
Anim {
}
}
Component.onCompleted: filledWidth = Qt.binding(() => (width - handle.implicitWidth - handle.anchors.leftMargin) * pos)
Binding {
id: posBinding
property: "pos"
target: root
value: ZUtils.clamp(mouse.pressStartPos + mouse.dragMovement, 0, 1)
when: mouse.pressed
}
MouseArea {
id: mouse
property real dragMovement
property real pressStartPos
property real pressStartX
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitHeight: handle.implicitHeight color: DynamicColors.palette.m3primary
preventStealing: true implicitHeight: 15
implicitWidth: 5
radius: Appearance.rounding.full
x: root.visualPosition * root.availableWidth - implicitWidth / 2
onPositionChanged: e => { MouseArea {
dragMovement = (e.x - pressStartX) / width; acceptedButtons: Qt.NoButton
root.interaction(posBinding.value); anchors.fill: parent
} cursorShape: Qt.PointingHandCursor
onPressed: e => {
widthBehavior.enabled = false;
pressStartX = e.x;
pressStartPos = root.visualPosition;
}
onReleased: e => {
root.interaction(posBinding.value);
widthBehavior.enabled = true;
dragMovement = 0;
} }
} }
} }
+13 -12
View File
@@ -28,7 +28,6 @@ RowLayout {
CustomTextField { CustomTextField {
id: textField id: textField
color: root.enabled ? DynamicColors.palette.m3onSurface : Qt.alpha(DynamicColors.palette.m3onSurface, 0.5)
implicitHeight: upButton.implicitHeight implicitHeight: upButton.implicitHeight
inputMethodHints: Qt.ImhFormattedNumbersOnly inputMethodHints: Qt.ImhFormattedNumbersOnly
leftPadding: Appearance.padding.normal leftPadding: Appearance.padding.normal
@@ -37,7 +36,7 @@ RowLayout {
text: root.isEditing ? text : root.displayText text: root.isEditing ? text : root.displayText
background: CustomRect { background: CustomRect {
color: root.enabled ? DynamicColors.tPalette.m3surfaceContainerHigh : DynamicColors.tPalette.m3surfaceContainerLow color: DynamicColors.tPalette.m3surfaceContainerHigh
implicitWidth: 100 implicitWidth: 100
radius: Appearance.rounding.full radius: Appearance.rounding.full
} }
@@ -86,7 +85,7 @@ RowLayout {
CustomRect { CustomRect {
id: upButton id: upButton
color: root.enabled ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, 1) color: DynamicColors.palette.m3primary
implicitHeight: upIcon.implicitHeight + Appearance.padding.small * 2 implicitHeight: upIcon.implicitHeight + Appearance.padding.small * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
radius: Appearance.rounding.full radius: Appearance.rounding.full
@@ -94,9 +93,7 @@ RowLayout {
StateLayer { StateLayer {
id: upState id: upState
color: DynamicColors.palette.m3onPrimary function onClicked(): void {
onClicked: {
let newValue = Math.min(root.max, root.value + root.step); let newValue = Math.min(root.max, root.value + root.step);
// Round to avoid floating point precision errors // Round to avoid floating point precision errors
const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0; const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0;
@@ -105,6 +102,9 @@ RowLayout {
root.displayText = newValue.toString(); root.displayText = newValue.toString();
root.valueModified(newValue); root.valueModified(newValue);
} }
color: DynamicColors.palette.m3onPrimary
onPressAndHold: timer.start() onPressAndHold: timer.start()
onReleased: timer.stop() onReleased: timer.stop()
} }
@@ -113,13 +113,13 @@ RowLayout {
id: upIcon id: upIcon
anchors.centerIn: parent anchors.centerIn: parent
color: root.enabled ? DynamicColors.palette.m3onPrimary : Qt.alpha(DynamicColors.palette.m3onSurface, 0.5) color: DynamicColors.palette.m3onPrimary
text: "keyboard_arrow_up" text: "keyboard_arrow_up"
} }
} }
CustomRect { CustomRect {
color: root.enabled ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, 1) color: DynamicColors.palette.m3primary
implicitHeight: downIcon.implicitHeight + Appearance.padding.small * 2 implicitHeight: downIcon.implicitHeight + Appearance.padding.small * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
radius: Appearance.rounding.full radius: Appearance.rounding.full
@@ -127,9 +127,7 @@ RowLayout {
StateLayer { StateLayer {
id: downState id: downState
color: DynamicColors.palette.m3onPrimary function onClicked(): void {
onClicked: {
let newValue = Math.max(root.min, root.value - root.step); let newValue = Math.max(root.min, root.value - root.step);
// Round to avoid floating point precision errors // Round to avoid floating point precision errors
const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0; const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0;
@@ -138,6 +136,9 @@ RowLayout {
root.displayText = newValue.toString(); root.displayText = newValue.toString();
root.valueModified(newValue); root.valueModified(newValue);
} }
color: DynamicColors.palette.m3onPrimary
onPressAndHold: timer.start() onPressAndHold: timer.start()
onReleased: timer.stop() onReleased: timer.stop()
} }
@@ -146,7 +147,7 @@ RowLayout {
id: downIcon id: downIcon
anchors.centerIn: parent anchors.centerIn: parent
color: root.enabled ? DynamicColors.palette.m3onPrimary : Qt.alpha(DynamicColors.palette.m3onSurface, 0.5) color: DynamicColors.palette.m3onPrimary
text: "keyboard_arrow_down" text: "keyboard_arrow_down"
} }
} }
+69 -36
View File
@@ -1,6 +1,7 @@
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Config import qs.Config
import qs.Helpers
Row { Row {
id: root id: root
@@ -11,46 +12,66 @@ Row {
} }
property alias active: menu.active property alias active: menu.active
property color colour: type == CustomSplitButton.Filled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3secondaryContainer property color color: type == CustomSplitButton.Filled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3secondaryContainer
property bool disabled property bool disabled
property color disabledColour: Qt.alpha(DynamicColors.palette.m3onSurface, 0.1) property color disabledColor: Qt.alpha(DynamicColors.palette.m3onSurface, 0.1)
property color disabledTextColour: Qt.alpha(DynamicColors.palette.m3onSurface, 0.38) property color disabledTextColor: Qt.alpha(DynamicColors.palette.m3onSurface, 0.38)
readonly property alias expandBtn: expandBtn
property alias expanded: menu.expanded property alias expanded: menu.expanded
property string fallbackIcon property string fallbackIcon
property string fallbackText property string fallbackText
property real horizontalPadding: Appearance.padding.larger property real horizontalPadding: Appearance.padding.normal
readonly property alias iconLabel: iconLabel property alias iconLabel: iconLabel
readonly property alias label: label property alias label: label
readonly property alias menu: menu property alias menu: menu
property alias menuItems: menu.items property alias menuItems: menu.items
property bool menuOnTop property bool menuOnTop
property real minLeftWidth property alias stateLayer: stateLayer
readonly property alias stateLayer: stateLayer property color textColor: type == CustomSplitButton.Filled ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSecondaryContainer
property color textColour: type == CustomSplitButton.Filled ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSecondaryContainer
readonly property alias textRow: textRow
property int type: CustomSplitButton.Filled property int type: CustomSplitButton.Filled
property real verticalPadding: Appearance.padding.small property real verticalPadding: Appearance.padding.smaller
spacing: Math.floor(Appearance.spacing.extraSmall) function closeDropdown(): void {
SettingsDropdowns.close(menu);
}
function openDropdown(): void {
if (root.disabled)
return;
SettingsDropdowns.open(menu, root);
}
function toggleDropdown(): void {
if (root.disabled)
return;
SettingsDropdowns.toggle(menu, root);
}
spacing: Math.floor(Appearance.spacing.small / 2)
onExpandedChanged: {
if (!expanded)
SettingsDropdowns.forget(menu);
}
CustomRect { CustomRect {
bottomRightRadius: Appearance.rounding.small / 2 bottomRightRadius: Appearance.rounding.small / 2
color: root.disabled ? root.disabledColour : root.colour color: root.disabled ? root.disabledColor : root.color
implicitHeight: expandBtn.implicitHeight implicitHeight: expandBtn.implicitHeight
implicitWidth: Math.max(root.minLeftWidth, textRow.implicitWidth + root.horizontalPadding * 2) implicitWidth: textRow.implicitWidth + root.horizontalPadding * 2
radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale)
topRightRadius: Appearance.rounding.small / 2 topRightRadius: Appearance.rounding.small / 2
StateLayer { StateLayer {
id: stateLayer id: stateLayer
bottomRightRadius: parent.bottomRightRadius function onClicked(): void {
color: root.textColour root.active?.clicked();
disabled: root.disabled }
topRightRadius: parent.topRightRadius
onClicked: root.active?.clicked() color: root.textColor
disabled: root.disabled
rect.bottomRightRadius: parent.bottomRightRadius
rect.topRightRadius: parent.topRightRadius
} }
RowLayout { RowLayout {
@@ -65,7 +86,7 @@ Row {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
animate: true animate: true
color: root.disabled ? root.disabledTextColour : root.textColour color: root.disabled ? root.disabledTextColor : root.textColor
fill: 1 fill: 1
text: root.active?.activeIcon ?? root.fallbackIcon text: root.active?.activeIcon ?? root.fallbackIcon
} }
@@ -77,12 +98,12 @@ Row {
Layout.preferredWidth: implicitWidth Layout.preferredWidth: implicitWidth
animate: true animate: true
clip: true clip: true
color: root.disabled ? root.disabledTextColour : root.textColour color: root.disabled ? root.disabledTextColor : root.textColor
text: root.active?.activeText ?? root.fallbackText text: root.active?.activeText ?? root.fallbackText
Behavior on Layout.preferredWidth { Behavior on Layout.preferredWidth {
Anim { Anim {
type: Anim.Emphasized easing.bezierCurve: Appearance.anim.curves.emphasized
} }
} }
} }
@@ -95,7 +116,7 @@ Row {
property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) : Appearance.rounding.small / 2 property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) : Appearance.rounding.small / 2
bottomLeftRadius: rad bottomLeftRadius: rad
color: root.disabled ? root.disabledColour : root.colour color: root.disabled ? root.disabledColor : root.color
implicitHeight: expandIcon.implicitHeight + root.verticalPadding * 2 implicitHeight: expandIcon.implicitHeight + root.verticalPadding * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale) radius: implicitHeight / 2 * Math.min(1, Appearance.rounding.scale)
@@ -109,12 +130,14 @@ Row {
StateLayer { StateLayer {
id: expandStateLayer id: expandStateLayer
color: root.textColour function onClicked(): void {
root.toggleDropdown();
}
color: root.textColor
disabled: root.disabled disabled: root.disabled
rect.bottomLeftRadius: parent.bottomLeftRadius rect.bottomLeftRadius: parent.bottomLeftRadius
rect.topLeftRadius: parent.topLeftRadius rect.topLeftRadius: parent.topLeftRadius
onClicked: root.expanded = !root.expanded
} }
MaterialIcon { MaterialIcon {
@@ -122,7 +145,7 @@ Row {
anchors.centerIn: parent anchors.centerIn: parent
anchors.horizontalCenterOffset: root.expanded ? 0 : -Math.floor(root.verticalPadding / 4) anchors.horizontalCenterOffset: root.expanded ? 0 : -Math.floor(root.verticalPadding / 4)
color: root.disabled ? root.disabledTextColour : root.textColour color: root.disabled ? root.disabledTextColor : root.textColor
rotation: root.expanded ? 180 : 0 rotation: root.expanded ? 180 : 0
text: "expand_more" text: "expand_more"
@@ -135,14 +158,24 @@ Row {
} }
} }
} }
}
Menu { Menu {
id: menu id: menu
attachSideY: root.menuOnTop ? Menu.Top : Menu.Bottom anchors.bottomMargin: Appearance.spacing.small
attachTo: expandBtn anchors.right: parent.right
marginY: Appearance.spacing.small * (root.menuOnTop ? -1 : 1) anchors.top: parent.bottom
thisSideY: root.menuOnTop ? Menu.Bottom : Menu.Top anchors.topMargin: Appearance.spacing.small
states: State {
when: root.menuOnTop
AnchorChanges {
anchors.bottom: expandBtn.top
anchors.top: undefined
target: menu
}
}
}
} }
} }
+8 -22
View File
@@ -8,32 +8,19 @@ Item {
id: root id: root
property alias active: splitButton.active property alias active: splitButton.active
property alias buttonAlias: splitButton property bool enabled: true
property alias expanded: splitButton.expanded property alias expanded: splitButton.expanded
property int expandedZ: 100 property int expandedZ: 100
required property string label required property string label
property alias menuItems: splitButton.menuItems property alias menuItems: splitButton.menuItems
property bool shouldBeActive: true
property alias type: splitButton.type property alias type: splitButton.type
signal selected(item: MenuItem) signal selected(item: MenuItem)
anchors.left: parent.left Layout.fillWidth: true
anchors.right: parent.right Layout.preferredHeight: row.implicitHeight + Appearance.padding.smaller * 2
clip: false clip: false
implicitHeight: row.implicitHeight + Appearance.padding.smaller * 2 z: root.expanded ? expandedZ : -1
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
z: splitButton.menu.implicitHeight > 0 ? expandedZ : 1
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
RowLayout { RowLayout {
id: row id: row
@@ -49,6 +36,7 @@ Item {
color: root.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onSurfaceVariant color: root.enabled ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.larger font.pointSize: Appearance.font.size.larger
text: root.label text: root.label
z: root.expanded ? root.expandedZ : -1
} }
CustomSplitButton { CustomSplitButton {
@@ -56,16 +44,14 @@ Item {
enabled: root.enabled enabled: root.enabled
type: CustomSplitButton.Filled type: CustomSplitButton.Filled
z: 2 z: root.expanded ? root.expandedZ : -1
menu.onItemSelected: item => { menu.onItemSelected: item => {
root.selected(item); root.selected(item);
// splitButton.closeDropdown(); splitButton.closeDropdown();
} }
stateLayer.onClicked: { stateLayer.onClicked: {
// splitButton.toggleDropdown(); splitButton.toggleDropdown();
splitButton.expanded = !splitButton.expanded;
console.log(root.z);
} }
} }
} }
+16 -18
View File
@@ -1,6 +1,6 @@
import QtQuick import QtQuick
import QtQuick.Shapes
import QtQuick.Templates import QtQuick.Templates
import QtQuick.Shapes
import qs.Config import qs.Config
Switch { Switch {
@@ -12,41 +12,38 @@ Switch {
implicitWidth: implicitIndicatorWidth implicitWidth: implicitIndicatorWidth
indicator: CustomRect { indicator: CustomRect {
color: root.checked && root.enabled ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, root.cLayer) color: root.checked ? DynamicColors.palette.m3primary : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHighest, root.cLayer)
implicitHeight: Appearance.font.size.medium + Appearance.padding.normal * 2 implicitHeight: 13 + 7 * 2
implicitWidth: implicitHeight * 1.7 implicitWidth: implicitHeight * 1.7
radius: Appearance.rounding.full radius: Appearance.rounding.full
CustomRect { CustomRect {
readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.2 : implicitHeight readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.3 : implicitHeight
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: root.checked && root.enabled ? DynamicColors.palette.m3onPrimary : DynamicColors.layer(DynamicColors.palette.m3outline, root.cLayer + 1) color: root.checked ? DynamicColors.palette.m3onPrimary : DynamicColors.layer(DynamicColors.palette.m3outline, root.cLayer + 1)
implicitHeight: parent.implicitHeight - Appearance.padding.extraSmall implicitHeight: parent.implicitHeight - 10
implicitWidth: nonAnimWidth implicitWidth: nonAnimWidth
radius: Appearance.rounding.full radius: Appearance.rounding.full
x: root.checked ? parent.implicitWidth - nonAnimWidth - Appearance.padding.extraSmall / 2 : Appearance.padding.extraSmall / 2 x: root.checked ? parent.implicitWidth - nonAnimWidth - 10 / 2 : 10 / 2
Behavior on implicitWidth { Behavior on implicitWidth {
Anim { Anim {
type: Anim.FastSpatial
} }
} }
Behavior on x { Behavior on x {
Anim { Anim {
type: Anim.FastSpatial
} }
} }
CustomRect { CustomRect {
anchors.fill: parent anchors.fill: parent
color: root.checked && root.enabled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurface color: root.checked ? DynamicColors.palette.m3primary : DynamicColors.palette.m3onSurface
opacity: root.pressed ? 0.1 : root.hovered ? 0.08 : 0 opacity: root.pressed ? 0.1 : root.hovered ? 0.08 : 0
radius: parent.radius radius: parent.radius
Behavior on opacity { Behavior on opacity {
Anim { Anim {
type: Anim.DefaultEffects
} }
} }
} }
@@ -66,14 +63,14 @@ Switch {
} }
property point end2: { property point end2: {
if (root.pressed) if (root.pressed)
return Qt.point(width * 0.8, height / 2); return Qt.point(width, height / 2);
if (root.checked) if (root.checked)
return Qt.point(width * 0.85, height * 0.2); return Qt.point(width * 0.85, height * 0.2);
return Qt.point(width * 0.85, height * 0.15); return Qt.point(width * 0.85, height * 0.15);
} }
property point start1: { property point start1: {
if (root.pressed) if (root.pressed)
return Qt.point(width * 0.2, height / 2); return Qt.point(width * 0.1, height / 2);
if (root.checked) if (root.checked)
return Qt.point(width * 0.15, height / 2); return Qt.point(width * 0.15, height / 2);
return Qt.point(width * 0.15, height * 0.15); return Qt.point(width * 0.15, height * 0.15);
@@ -91,7 +88,7 @@ Switch {
anchors.centerIn: parent anchors.centerIn: parent
asynchronous: true asynchronous: true
height: parent.implicitHeight - Appearance.padding.larger height: parent.implicitHeight - Appearance.padding.small * 2
preferredRendererType: Shape.CurveRenderer preferredRendererType: Shape.CurveRenderer
width: height width: height
@@ -113,11 +110,11 @@ Switch {
} }
ShapePath { ShapePath {
capStyle: ShapePath.RoundCap capStyle: Appearance.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
fillColor: "transparent" fillColor: "transparent"
startX: icon.start1.x startX: icon.start1.x
startY: icon.start1.y startY: icon.start1.y
strokeColor: root.checked && root.enabled ? DynamicColors.palette.m3primary : DynamicColors.palette.m3surfaceContainerHighest strokeColor: root.checked ? DynamicColors.palette.m3primary : DynamicColors.palette.m3surfaceContainerHighest
strokeWidth: Appearance.font.size.larger * 0.15 strokeWidth: Appearance.font.size.larger * 0.15
Behavior on strokeColor { Behavior on strokeColor {
@@ -151,7 +148,8 @@ Switch {
} }
component PropAnim: PropertyAnimation { component PropAnim: PropertyAnimation {
duration: Appearance.anim.durations.expressiveFastSpatial duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial easing.bezierCurve: MaterialEasing.expressiveEffects
easing.type: Easing.BezierSpline
} }
} }
-1
View File
@@ -15,7 +15,6 @@ Text {
color: DynamicColors.palette.m3onSurface color: DynamicColors.palette.m3onSurface
font.family: Appearance.font.family.sans font.family: Appearance.font.family.sans
font.pointSize: Appearance.font.size.normal font.pointSize: Appearance.font.size.normal
linkColor: DynamicColors.palette.m3onPrimaryFixedVariant
renderType: Text.NativeRendering renderType: Text.NativeRendering
textFormat: Text.PlainText textFormat: Text.PlainText
+1 -2
View File
@@ -1,6 +1,6 @@
import qs.Config
import QtQuick import QtQuick
import QtQuick.Effects import QtQuick.Effects
import qs.Config
RectangularShadow { RectangularShadow {
property real dp: [0, 1, 3, 6, 8, 12][level] property real dp: [0, 1, 3, 6, 8, 12][level]
@@ -13,7 +13,6 @@ RectangularShadow {
Behavior on dp { Behavior on dp {
Anim { Anim {
type: Anim.SlowEffects
} }
} }
} }
-33
View File
@@ -1,33 +0,0 @@
import QtQuick
import QtQuick.Controls
import qs.Config
IconButton {
id: root
required property bool shouldBeVisible
opacity: 0
scale: 0
visible: root.scale > 0
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.small
}
}
Behavior on scale {
Anim {
}
}
onShouldBeVisibleChanged: {
if (root.shouldBeVisible) {
root.opacity = 1;
root.scale = 1;
} else {
root.opacity = 0;
root.scale = 0;
}
}
}
+6 -5
View File
@@ -41,11 +41,12 @@ CustomRect {
color: type === IconButton.Text ? "transparent" : disabled ? disabledColour : internalChecked ? activeColour : inactiveColour color: type === IconButton.Text ? "transparent" : disabled ? disabledColour : internalChecked ? activeColour : inactiveColour
implicitHeight: label.implicitHeight + padding * 2 implicitHeight: label.implicitHeight + padding * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
radius: internalChecked ? 6 : (implicitHeight / 2 * Math.min(1, 1)) * Appearance.rounding.scale radius: internalChecked ? 6 : implicitHeight / 2 * Math.min(1, 1)
Behavior on radius { Behavior on radius {
Anim { Anim {
id: radiusAnim id: radiusAnim
} }
} }
@@ -54,14 +55,14 @@ CustomRect {
StateLayer { StateLayer {
id: stateLayer id: stateLayer
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour function onClicked(): void {
disabled: root.disabled
onClicked: {
if (root.toggle) if (root.toggle)
root.internalChecked = !root.internalChecked; root.internalChecked = !root.internalChecked;
root.clicked(); root.clicked();
} }
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
disabled: root.disabled
} }
MaterialIcon { MaterialIcon {
-2
View File
@@ -102,7 +102,6 @@ Item {
animate: root.animate animate: root.animate
animateProp: "opacity" animateProp: "opacity"
color: root.color color: root.color
font.pointSize: elideText.font.pointSize
text: elideText.text text: elideText.text
} }
@@ -112,7 +111,6 @@ Item {
animate: root.animate animate: root.animate
animateProp: "opacity" animateProp: "opacity"
color: root.color color: root.color
font.pointSize: elideText.font.pointSize
text: t1.text text: t1.text
x: t1.width + root.gap x: t1.width + root.gap
} }
+69 -129
View File
@@ -2,169 +2,109 @@ pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell
import qs.Config import qs.Config
import qs.Drawers
MouseArea { Elevation {
id: root id: root
enum Side {
Top,
Bottom,
Left,
Right
}
property MenuItem active: items[0] ?? null property MenuItem active: items[0] ?? null
property int attachSideX: Menu.Right
property int attachSideY: Menu.Bottom
required property Item attachTo
property bool expanded property bool expanded
property list<MenuItem> items property list<MenuItem> items
property real marginX
property real marginY
property int thisSideX: Menu.Right
property int thisSideY: Menu.Top
signal itemSelected(item: MenuItem) signal itemSelected(item: MenuItem)
anchors.fill: parent implicitHeight: root.expanded ? column.implicitHeight + Appearance.padding.small * 2 : 0
enabled: expanded implicitWidth: Math.max(200, column.implicitWidth)
layer.enabled: opacity < 1 level: 2
opacity: expanded ? 1 : 0 opacity: root.expanded ? 1 : 0
parent: { radius: Appearance.rounding.normal
const win = QsWindow.window;
const contentWin = win as Windows;
return contentWin ? contentWin.interactionWrapper : (win as QsWindow).contentItem;
}
Behavior on implicitHeight {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Behavior on opacity { Behavior on opacity {
Anim { Anim {
type: Anim.DefaultEffects duration: Appearance.anim.durations.expressiveDefaultSpatial
} }
} }
onClicked: expanded = false CustomClippingRect {
anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainer
radius: parent.radius
TransformWatcher { ColumnLayout {
id: watcher id: column
a: root.parent anchors.left: parent.left
b: root.attachTo anchors.right: parent.right
} anchors.verticalCenter: parent.verticalCenter
spacing: 5
Elevation { Repeater {
id: menu model: root.items
implicitHeight: column.implicitHeight + column.anchors.margins * 2 CustomRect {
implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2) id: item
level: 2
radius: Appearance.rounding.medium
x: {
watcher.transform;
const item = root.attachTo;
let off = root.attachSideX === Menu.Left ? 0 : item.width;
if (root.thisSideX === Menu.Right)
off -= width;
return item.mapToItem(root.parent, off, 0).x + root.marginX;
}
y: {
watcher.transform;
const item = root.attachTo;
let off = root.attachSideY === Menu.Top ? 0 : item.height;
if (root.thisSideY === Menu.Bottom)
off -= height;
return item.mapToItem(root.parent, 0, off).y + root.marginY;
}
transform: Scale { readonly property bool active: modelData === root.active
origin.y: root.thisSideY === Menu.Bottom ? menu.height : 0 required property int index
yScale: root.expanded ? 1 : 0.1 required property MenuItem modelData
Behavior on yScale { Layout.fillWidth: true
Anim { implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.normal * 2
} implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.normal * 2
}
}
CustomRect {
anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainerLow
radius: parent.radius
ColumnLayout {
id: column
anchors.fill: parent
anchors.margins: Appearance.padding.extraSmall
spacing: Appearance.spacing.extraSmall
Repeater {
id: repeater
model: root.items
CustomRect { CustomRect {
id: item anchors.fill: parent
anchors.leftMargin: Appearance.padding.small
readonly property bool active: modelData === root.active anchors.rightMargin: Appearance.padding.small
required property int index color: Qt.alpha(DynamicColors.palette.m3secondaryContainer, active ? 1 : 0)
required property MenuItem modelData radius: Appearance.rounding.normal - Appearance.padding.small
Layout.fillWidth: true
color: Qt.alpha(DynamicColors.palette.m3tertiaryContainer, active ? 1 : 0)
implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.larger * 2
implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.larger * 2
radius: Appearance.rounding.small
Behavior on radius {
Anim {
}
}
StateLayer { StateLayer {
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurface function onClicked(): void {
disabled: !root.expanded
onClicked: {
root.itemSelected(item.modelData); root.itemSelected(item.modelData);
root.active = item.modelData; root.active = item.modelData;
item.modelData.clicked();
root.expanded = false; root.expanded = false;
} }
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
disabled: !root.expanded
}
}
RowLayout {
id: menuOptionRow
anchors.fill: parent
anchors.margins: Appearance.padding.normal
spacing: Appearance.spacing.small
MaterialIcon {
Layout.alignment: Qt.AlignVCenter
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurfaceVariant
text: item.modelData.icon
} }
RowLayout { CustomText {
id: menuOptionRow Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.text
}
anchors.fill: parent Loader {
anchors.margins: Appearance.padding.larger Layout.alignment: Qt.AlignVCenter
spacing: Appearance.spacing.small active: item.modelData.trailingIcon.length > 0
visible: active
MaterialIcon { sourceComponent: MaterialIcon {
Layout.alignment: Qt.AlignVCenter color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant text: item.modelData.trailingIcon
text: item.modelData.icon
}
CustomText {
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.text
}
Loader {
Layout.alignment: Qt.AlignVCenter
active: item.modelData.trailingIcon.length > 0
asynchronous: true
visible: active
sourceComponent: MaterialIcon {
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant
text: item.modelData.trailingIcon
}
} }
} }
} }
-2
View File
@@ -29,7 +29,6 @@ Elevation {
level: root.expanded ? 2 : 0 level: root.expanded ? 2 : 0
radius: itemHeight / 2 radius: itemHeight / 2
visible: implicitHeight > 0 visible: implicitHeight > 0
z: root.expanded ? 100 : 0
Behavior on implicitHeight { Behavior on implicitHeight {
Anim { Anim {
@@ -69,7 +68,6 @@ Elevation {
anchors.fill: parent anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainer color: DynamicColors.palette.m3surfaceContainer
radius: parent.radius radius: parent.radius
z: root.z
// Main visible spinner: normal/outside text color // Main visible spinner: normal/outside text color
PathView { PathView {
+69 -174
View File
@@ -1,53 +1,15 @@
import QtQuick
import QtQuick.Shapes
import ZShell
import ZShell.Components
import qs.Helpers
import qs.Config import qs.Config
import QtQuick
MouseArea { MouseArea {
id: root id: root
property alias bottomLeftRadius: base.bottomLeftRadius property color color: DynamicColors.palette.m3onSurface
property alias bottomRightRadius: base.bottomRightRadius
property real circleRadius
property alias color: base.color
property bool disabled property bool disabled
readonly property real endRadius: { property real radius: parent?.radius ?? 0
const d1 = distSq(0, 0); property alias rect: hoverLayer
const d2 = distSq(width, 0);
const d3 = distSq(0, height);
const d4 = distSq(width, height);
return (Math.sqrt(Math.max(d1, d2, d3, d4)) + (shapeMorph ? 24 : 0)) * 1.3;
}
property real endRadiusAtPress
property bool manualPressOverride
property real pressX: width / 2
property real pressY: height / 2
property alias radius: base.radius
readonly property alias rect: base
property bool shapeMorph
property bool showHoverBackground: true
property real stateOpacity: containsMouse ? 0.08 : 0
property alias topLeftRadius: base.topLeftRadius
property alias topRightRadius: base.topRightRadius
function clamp(r: real): real { function onClicked(): void {
return Math.max(0, Math.min(r, width / 2, height / 2));
}
function distSq(x: real, y: real): real {
return (pressX - x) ** 2 + (pressY - y) ** 2;
}
function press(x: real, y: real): void {
pressX = x;
pressY = y;
fadeAnim.complete();
circleRadius = 0;
circle.opacity = 0.1;
rippleAnim.restart();
endRadiusAtPress = endRadius;
} }
anchors.fill: parent anchors.fill: parent
@@ -55,146 +17,79 @@ MouseArea {
enabled: !disabled enabled: !disabled
hoverEnabled: true hoverEnabled: true
Behavior on stateOpacity { onClicked: event => !disabled && onClicked(event)
onPressed: event => {
if (disabled)
return;
rippleAnim.x = event.x;
rippleAnim.y = event.y;
const dist = (ox, oy) => ox * ox + oy * oy;
rippleAnim.radius = Math.sqrt(Math.max(dist(event.x, event.y), dist(event.x, height - event.y), dist(width - event.x, event.y), dist(width - event.x, height - event.y)));
rippleAnim.restart();
}
SequentialAnimation {
id: rippleAnim
property real radius
property real x
property real y
PropertyAction {
property: "x"
target: ripple
value: rippleAnim.x
}
PropertyAction {
property: "y"
target: ripple
value: rippleAnim.y
}
PropertyAction {
property: "opacity"
target: ripple
value: 0.08
}
Anim { Anim {
type: Anim.DefaultEffects easing.bezierCurve: MaterialEasing.standardDecel
from: 0
properties: "implicitWidth,implicitHeight"
target: ripple
to: rippleAnim.radius * 2
}
Anim {
property: "opacity"
target: ripple
to: 0
} }
} }
onCircleRadiusChanged: { CustomClippingRect {
if (!(pressed || manualPressOverride) && circleRadius > endRadiusAtPress * 0.99 && !fadeAnim.running) id: hoverLayer
fadeAnim.start();
}
onClicked: event => !disabled && onClicked(event)
onManualPressOverrideChanged: {
if (!(pressed || manualPressOverride) && circleRadius > endRadiusAtPress * 0.99 && !fadeAnim.running)
fadeAnim.start();
}
onPressed: e => press(e.x, e.y)
onPressedChanged: {
if (!(pressed || manualPressOverride) && !rippleAnim.running && circle.opacity > 0)
fadeAnim.start();
}
Anim {
id: rippleAnim
alwaysRunToEnd: true
duration: Appearance.anim.durations.expressiveSlowEffects * 2
easing.bezierCurve: Appearance.anim.curves.standard
property: "circleRadius"
target: root
to: root.endRadius
}
Anim {
id: fadeAnim
property: "opacity"
target: circle
to: 0
type: Anim.SlowEffects
}
CustomRect {
id: base
anchors.fill: parent anchors.fill: parent
bottomLeftRadius: root.parent?.bottomLeftRadius ?? radius ?? 0 border.pixelAligned: false
bottomRightRadius: root.parent?.bottomRightRadius ?? radius ?? 0 color: Qt.alpha(root.color, root.disabled ? 0 : root.pressed ? 0.1 : root.containsMouse ? 0.08 : 0)
color: DynamicColors.palette.m3onSurface radius: root.radius
opacity: root.stateOpacity
// Pick up radius from parent if it has one (parent can be anything with radius props)
// qmllint disable missing-property
radius: root.parent?.radius ?? 0
topLeftRadius: root.parent?.topLeftRadius ?? radius ?? 0
topRightRadius: root.parent?.topRightRadius ?? radius ?? 0
// qmllint enable missing-property
}
Shape { CustomRect {
id: circle id: ripple
anchors.fill: parent border.pixelAligned: false
opacity: 0 color: root.color
preferredRendererType: Shape.CurveRenderer opacity: 0
radius: Appearance.rounding.full
ShapePath { transform: Translate {
fillColor: base.color x: -ripple.width / 2
startX: root.clamp(base.topLeftRadius) y: -ripple.height / 2
startY: 0
strokeColor: "transparent"
strokeWidth: 0
fillGradient: RadialGradient {
centerRadius: root.circleRadius
centerX: root.pressX
centerY: root.pressY
focalX: centerX
focalY: centerY
GradientStop {
color: Qt.alpha(base.color, 1)
position: 0
}
GradientStop {
color: Qt.alpha(base.color, 1)
position: ZUtils.clamp(1 - 0.2 * root.endRadius / root.circleRadius, 0.01, 0.99)
}
GradientStop {
color: Qt.alpha(base.color, ZUtils.clamp((root.circleRadius / root.endRadius - 0.9) / 0.1, 0, 1))
position: 1
}
}
PathLine {
x: root.width - root.clamp(base.topRightRadius)
y: 0
}
PathArc {
radiusX: root.clamp(base.topRightRadius)
radiusY: root.clamp(base.topRightRadius)
relativeX: root.clamp(base.topRightRadius)
relativeY: root.clamp(base.topRightRadius)
}
PathLine {
x: root.width
y: root.height - root.clamp(base.bottomRightRadius)
}
PathArc {
radiusX: root.clamp(base.bottomRightRadius)
radiusY: root.clamp(base.bottomRightRadius)
relativeX: -root.clamp(base.bottomRightRadius)
relativeY: root.clamp(base.bottomRightRadius)
}
PathLine {
x: root.clamp(base.bottomLeftRadius)
y: root.height
}
PathArc {
radiusX: root.clamp(base.bottomLeftRadius)
radiusY: root.clamp(base.bottomLeftRadius)
relativeX: -root.clamp(base.bottomLeftRadius)
relativeY: -root.clamp(base.bottomLeftRadius)
}
PathLine {
x: 0
y: root.clamp(base.topLeftRadius)
}
PathArc {
radiusX: root.clamp(base.topLeftRadius)
radiusY: root.clamp(base.topLeftRadius)
x: root.clamp(base.topLeftRadius)
y: 0
} }
} }
} }
+2 -1
View File
@@ -4,9 +4,10 @@ import Quickshell
Singleton { Singleton {
readonly property AppearanceConf.Anim anim: Config.appearance.anim readonly property AppearanceConf.Anim anim: Config.appearance.anim
readonly property AppearanceConf.Deform deform: Config.appearance.deform
readonly property AppearanceConf.FontStuff font: Config.appearance.font readonly property AppearanceConf.FontStuff font: Config.appearance.font
readonly property AppearanceConf.Padding padding: Config.appearance.padding readonly property AppearanceConf.Padding padding: Config.appearance.padding
// Literally just here to shorten accessing stuff :woe:
// Also kinda so I can keep accessing it with `Appearance.xxx` instead of `Conf.appearance.xxx`
readonly property AppearanceConf.Rounding rounding: Config.appearance.rounding readonly property AppearanceConf.Rounding rounding: Config.appearance.rounding
readonly property AppearanceConf.Spacing spacing: Config.appearance.spacing readonly property AppearanceConf.Spacing spacing: Config.appearance.spacing
readonly property AppearanceConf.Transparency transparency: Config.appearance.transparency readonly property AppearanceConf.Transparency transparency: Config.appearance.transparency
+7 -24
View File
@@ -3,8 +3,6 @@ import Quickshell.Io
JsonObject { JsonObject {
property Anim anim: Anim { property Anim anim: Anim {
} }
property Deform deform: Deform {
}
property FontStuff font: FontStuff { property FontStuff font: FontStuff {
} }
property Padding padding: Padding { property Padding padding: Padding {
@@ -28,13 +26,9 @@ JsonObject {
property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1] property list<real> emphasized: [0.05, 0, 2 / 15, 0.06, 1 / 6, 0.4, 5 / 24, 0.82, 0.25, 1, 1, 1]
property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1] property list<real> emphasizedAccel: [0.3, 0, 0.8, 0.15, 1, 1]
property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1] property list<real> emphasizedDecel: [0.05, 0.7, 0.1, 1, 1, 1]
property list<real> expressiveDefaultEffects: [0.34, 0.8, 0.34, 1, 1, 1]
property list<real> expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1, 1, 1] property list<real> expressiveDefaultSpatial: [0.38, 1.21, 0.22, 1, 1, 1]
property list<real> expressiveEffects: [0.34, 0.8, 0.34, 1, 1, 1] property list<real> expressiveEffects: [0.34, 0.8, 0.34, 1, 1, 1]
property list<real> expressiveFastEffects: [0.31, 0.94, 0.34, 1, 1, 1]
property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1] property list<real> expressiveFastSpatial: [0.42, 1.67, 0.21, 0.9, 1, 1]
property list<real> expressiveSlowEffects: [0.34, 0.88, 0.34, 1, 1, 1]
property list<real> expressiveSlowSpatial: [0.39, 1.29, 0.35, 0.98, 1, 1]
property list<real> standard: [0.2, 0, 0, 1, 1, 1] property list<real> standard: [0.2, 0, 0, 1, 1, 1]
property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1] property list<real> standardAccel: [0.3, 0, 1, 1, 1, 1]
property list<real> standardDecel: [0, 0, 0, 1, 1, 1] property list<real> standardDecel: [0, 0, 0, 1, 1, 1]
@@ -42,18 +36,13 @@ JsonObject {
component AnimDurations: JsonObject { component AnimDurations: JsonObject {
property int expressiveDefaultSpatial: 500 * scale property int expressiveDefaultSpatial: 500 * scale
property int expressiveEffects: 200 * scale property int expressiveEffects: 200 * scale
property int expressiveFastEffects: 150 * scale
property int expressiveFastSpatial: 350 * scale property int expressiveFastSpatial: 350 * scale
property int expressiveSlowEffects: 300 * scale
property int extraLarge: 1000 * scale property int extraLarge: 1000 * scale
property int large: 600 * scale property int large: 600 * scale
property int normal: 400 * scale property int normal: 400 * scale
property real scale: 1 property real scale: 1
property int small: 200 * scale property int small: 200 * scale
} }
component Deform: JsonObject {
property real scale: 1
}
component FontFamily: JsonObject { component FontFamily: JsonObject {
property string clock: "Rubik" property string clock: "Rubik"
property string material: "Material Symbols Rounded" property string material: "Material Symbols Rounded"
@@ -63,8 +52,7 @@ JsonObject {
component FontSize: JsonObject { component FontSize: JsonObject {
property int extraLarge: 28 * scale property int extraLarge: 28 * scale
property int large: 18 * scale property int large: 18 * scale
property int larger: 16 * scale property int larger: 15 * scale
property int medium: 14 * scale
property int normal: 13 * scale property int normal: 13 * scale
property real scale: 1 property real scale: 1
property int small: 11 * scale property int small: 11 * scale
@@ -77,33 +65,28 @@ JsonObject {
} }
} }
component Padding: JsonObject { component Padding: JsonObject {
property int extraLargeIncreased: 32 * scale property int large: 15 * scale
property int extraSmall: 4 * scale
property int large: 16 * scale
property int larger: 12 * scale property int larger: 12 * scale
property int normal: 8 * scale property int normal: 10 * scale
property real scale: 1 property real scale: 1
property int small: 5 * scale property int small: 5 * scale
property int smaller: 7 * scale property int smaller: 7 * scale
property int smallest: 2 * scale property int smallest: 2 * scale
} }
component Rounding: JsonObject { component Rounding: JsonObject {
property int extraSmall: 4 * scale
property int full: 1000 * scale property int full: 1000 * scale
property int large: 24 * scale property int large: 25 * scale
property int medium: 16 * scale property int normal: 17 * scale
property int normal: 18 * scale
property real scale: 1 property real scale: 1
property int small: 12 * scale property int small: 12 * scale
property int smallest: 8 * scale property int smallest: 8 * scale
} }
component Spacing: JsonObject { component Spacing: JsonObject {
property int extraSmall: 4 * scale
property int large: 20 * scale property int large: 20 * scale
property int larger: 16 * scale property int larger: 15 * scale
property int normal: 12 * scale property int normal: 12 * scale
property real scale: 1 property real scale: 1
property int small: 8 * scale property int small: 7 * scale
property int smaller: 10 * scale property int smaller: 10 * scale
} }
component Transparency: JsonObject { component Transparency: JsonObject {
-7
View File
@@ -4,11 +4,4 @@ import qs.Config
JsonObject { JsonObject {
property bool enabled: true property bool enabled: true
property int wallFadeDuration: MaterialEasing.standardTime property int wallFadeDuration: MaterialEasing.standardTime
property real alignX: 0.5
property real alignY: 0.5
property real zoom: 1.0
property real sourceClipX: 0
property real sourceClipY: 0
property real sourceClipW: 0
property real sourceClipH: 0
} }
+11 -10
View File
@@ -8,6 +8,10 @@ JsonObject {
id: "workspaces", id: "workspaces",
enabled: true enabled: true
}, },
{
id: "audio",
enabled: true
},
{ {
id: "media", id: "media",
enabled: true enabled: true
@@ -20,6 +24,10 @@ JsonObject {
id: "updates", id: "updates",
enabled: true enabled: true
}, },
{
id: "dash",
enabled: true
},
{ {
id: "spacer", id: "spacer",
enabled: true enabled: true
@@ -33,12 +41,12 @@ JsonObject {
enabled: true enabled: true
}, },
{ {
id: "hyprsunset", id: "tray",
enabled: true enabled: true
}, },
{ {
id: "tray", id: "upower",
enabled: true enabled: false
}, },
{ {
id: "network", id: "network",
@@ -54,13 +62,9 @@ JsonObject {
}, },
] ]
property int height: 34 property int height: 34
property bool hideWhenNotif: false
property Popouts popouts: Popouts { property Popouts popouts: Popouts {
} }
property int rounding: 8 property int rounding: 8
property int smoothing: 32
property Tray tray: Tray {
}
component Popouts: JsonObject { component Popouts: JsonObject {
property bool activeWindow: true property bool activeWindow: true
@@ -71,7 +75,4 @@ JsonObject {
property bool tray: true property bool tray: true
property bool upower: true property bool upower: true
} }
component Tray: JsonObject {
property int trayIconSize: 24
}
} }
-8
View File
@@ -1,13 +1,5 @@
import Quickshell.Io import Quickshell.Io
JsonObject { JsonObject {
property Presets presets: Presets {
}
property string schemeType: "vibrant" property string schemeType: "vibrant"
component Presets: JsonObject {
property string accent: ""
property string name: ""
property string variant: ""
}
} }
+7 -55
View File
@@ -4,6 +4,8 @@ import Quickshell
import Quickshell.Io import Quickshell.Io
import ZShell import ZShell
import QtQuick import QtQuick
import qs.Helpers
import qs.Paths
Singleton { Singleton {
id: root id: root
@@ -21,7 +23,6 @@ Singleton {
property alias osd: adapter.osd property alias osd: adapter.osd
property alias overview: adapter.overview property alias overview: adapter.overview
property bool recentlySaved: false property bool recentlySaved: false
property alias screenshot: adapter.screenshot
property alias services: adapter.services property alias services: adapter.services
property alias sidebar: adapter.sidebar property alias sidebar: adapter.sidebar
property alias utilities: adapter.utilities property alias utilities: adapter.utilities
@@ -47,9 +48,6 @@ Singleton {
padding: { padding: {
scale: appearance.padding.scale scale: appearance.padding.scale
}, },
deform: {
scale: appearance.deform.scale
},
font: { font: {
family: { family: {
sans: appearance.font.family.sans, sans: appearance.font.family.sans,
@@ -79,28 +77,16 @@ Singleton {
function serializeBackground(): var { function serializeBackground(): var {
return { return {
wallFadeDuration: background.wallFadeDuration, wallFadeDuration: background.wallFadeDuration,
enabled: background.enabled, enabled: background.enabled
alignX: background.alignX,
sourceClipX: background.sourceClipX,
sourceClipY: background.sourceClipY,
sourceClipW: background.sourceClipW,
sourceClipH: background.sourceClipH,
alignY: background.alignY,
zoom: background.zoom
}; };
} }
function serializeBar(): var { function serializeBar(): var {
return { return {
autoHide: barConfig.autoHide, autoHide: barConfig.autoHide,
hideWhenNotif: barConfig.hideWhenNotif,
rounding: barConfig.rounding, rounding: barConfig.rounding,
border: barConfig.border, border: barConfig.border,
smoothing: barConfig.smoothing,
height: barConfig.height, height: barConfig.height,
tray: {
trayIconSize: barConfig.tray.trayIconSize
},
popouts: { popouts: {
tray: barConfig.popouts.tray, tray: barConfig.popouts.tray,
audio: barConfig.popouts.audio, audio: barConfig.popouts.audio,
@@ -116,12 +102,7 @@ Singleton {
function serializeColors(): var { function serializeColors(): var {
return { return {
schemeType: colors.schemeType, schemeType: colors.schemeType
presets: {
name: colors.presets.name,
variant: colors.presets.variant,
accent: colors.presets.accent
}
}; };
} }
@@ -140,8 +121,7 @@ Singleton {
background: serializeBackground(), background: serializeBackground(),
launcher: serializeLauncher(), launcher: serializeLauncher(),
colors: serializeColors(), colors: serializeColors(),
dock: serializeDock(), dock: serializeDock()
screenshot: serializeScreenshot()
}; };
} }
@@ -192,16 +172,11 @@ Singleton {
return { return {
logo: general.logo, logo: general.logo,
wallpaperPath: general.wallpaperPath, wallpaperPath: general.wallpaperPath,
username: general.username,
desktopIcons: general.desktopIcons, desktopIcons: general.desktopIcons,
dateFormat: general.dateFormat,
color: { color: {
mode: general.color.mode, mode: general.color.mode,
smart: general.color.smart, smart: general.color.smart,
scheduleDark: general.color.scheduleDark,
scheduleHyprsunset: general.color.scheduleHyprsunset,
scheduleHyprsunsetStart: general.color.scheduleHyprsunsetStart,
hyprsunsetTemp: general.color.hyprsunsetTemp,
scheduleHyprsunsetEnd: general.color.scheduleHyprsunsetEnd,
schemeGeneration: general.color.schemeGeneration, schemeGeneration: general.color.schemeGeneration,
scheduleDarkStart: general.color.scheduleDarkStart, scheduleDarkStart: general.color.scheduleDarkStart,
scheduleDarkEnd: general.color.scheduleDarkEnd, scheduleDarkEnd: general.color.scheduleDarkEnd,
@@ -215,10 +190,6 @@ Singleton {
}, },
idle: { idle: {
timeouts: general.idle.timeouts timeouts: general.idle.timeouts
},
battery: {
popupThresholds: general.battery.popupThresholds,
critPerc: general.battery.critPerc
} }
}; };
} }
@@ -227,7 +198,6 @@ Singleton {
return { return {
maxAppsShown: launcher.maxAppsShown, maxAppsShown: launcher.maxAppsShown,
maxWallpapers: launcher.maxWallpapers, maxWallpapers: launcher.maxWallpapers,
uwsm: launcher.uwsm,
actionPrefix: launcher.actionPrefix, actionPrefix: launcher.actionPrefix,
specialPrefix: launcher.specialPrefix, specialPrefix: launcher.specialPrefix,
useFuzzy: { useFuzzy: {
@@ -251,8 +221,6 @@ Singleton {
return { return {
recolorLogo: lock.recolorLogo, recolorLogo: lock.recolorLogo,
enableFprint: lock.enableFprint, enableFprint: lock.enableFprint,
showNotifContent: lock.showNotifContent,
showNotifIcon: lock.showNotifIcon,
maxFprintTries: lock.maxFprintTries, maxFprintTries: lock.maxFprintTries,
blurAmount: lock.blurAmount, blurAmount: lock.blurAmount,
sizes: { sizes: {
@@ -294,24 +262,9 @@ Singleton {
}; };
} }
function serializeScreenshot(): var {
return {
enable_pp: screenshot.enable_pp,
mode: screenshot.mode,
radius: screenshot.radius,
shadow: screenshot.shadow,
rounding: screenshot.rounding,
shadow_blur: screenshot.shadow_blur,
shadow_color: screenshot.shadow_color,
shadow_offset_x: screenshot.shadow_offset_x,
shadow_offset_y: screenshot.shadow_offset_y
};
}
function serializeServices(): var { function serializeServices(): var {
return { return {
weatherLocation: services.weatherLocation, weatherLocation: services.weatherLocation,
updates: services.updates,
useFahrenheit: services.useFahrenheit, useFahrenheit: services.useFahrenheit,
ddcutilService: services.ddcutilService, ddcutilService: services.ddcutilService,
useTwelveHourClock: services.useTwelveHourClock, useTwelveHourClock: services.useTwelveHourClock,
@@ -364,6 +317,7 @@ Singleton {
ElapsedTimer { ElapsedTimer {
id: timer id: timer
} }
Timer { Timer {
@@ -461,8 +415,6 @@ Singleton {
} }
property Overview overview: Overview { property Overview overview: Overview {
} }
property Screenshot screenshot: Screenshot {
}
property Services services: Services { property Services services: Services {
} }
property SidebarConfig sidebar: SidebarConfig { property SidebarConfig sidebar: SidebarConfig {
+64 -12
View File
@@ -29,10 +29,9 @@ Singleton {
readonly property alias wallLuminance: analyser.luminance readonly property alias wallLuminance: analyser.luminance
function alterColor(c: color, a: real, layer: int): color { function alterColor(c: color, a: real, layer: int): color {
const initLuminance = getLuminance(c); const luminance = getLuminance(c);
const luminance = Math.max(initLuminance, 0.001);
const offset = (!light || layer == 1 ? 1 : -layer / 2) * (light ? 0.2 : 0.3) * (0.2 + 0.3 * (1 - transparency.base)) * (1 + wallLuminance * (light ? (layer == 1 ? 3 : 1) : 2.5)); const offset = (!light || layer == 1 ? 1 : -layer / 2) * (light ? 0.2 : 0.3) * (1 - transparency.base) * (1 + wallLuminance * (light ? (layer == 1 ? 3 : 1) : 2.5));
const scale = (luminance + offset) / luminance; const scale = (luminance + offset) / luminance;
const r = Math.max(0, Math.min(1, c.r * scale)); const r = Math.max(0, Math.min(1, c.r * scale));
const g = Math.max(0, Math.min(1, c.g * scale)); const g = Math.max(0, Math.min(1, c.g * scale));
@@ -85,10 +84,6 @@ Singleton {
Config.save(); Config.save();
} }
function swapRG(c: color): color {
return Qt.rgba(c.g, c.r, c.b, c.a);
}
FileView { FileView {
path: "/etc/zshell-greeter/scheme.json" path: "/etc/zshell-greeter/scheme.json"
watchChanges: true watchChanges: true
@@ -100,9 +95,69 @@ Singleton {
ImageAnalyser { ImageAnalyser {
id: analyser id: analyser
source: WallpaperPath.lockscreenBg source: WallpaperPath.currentWallpaperPath
} }
component M3MaccchiatoPalette: QtObject {
property color m3background: "#131317"
property color m3error: "#ffb4ab"
property color m3errorContainer: "#93000a"
property color m3inverseOnSurface: "#303034"
property color m3inversePrimary: "#525b92"
property color m3inverseSurface: "#e4e1e7"
property color m3neutral_paletteKeyColor: "#77767b"
property color m3neutral_variant_paletteKeyColor: "#767680"
property color m3onBackground: "#e4e1e7"
property color m3onError: "#690005"
property color m3onErrorContainer: "#ffdad6"
property color m3onPrimary: "#232c60"
property color m3onPrimaryContainer: "#ffffff"
property color m3onPrimaryFixed: "#0b154b"
property color m3onPrimaryFixedVariant: "#3a4378"
property color m3onSecondary: "#2c2f44"
property color m3onSecondaryContainer: "#b1b3ce"
property color m3onSecondaryFixed: "#171a2e"
property color m3onSecondaryFixedVariant: "#42455c"
property color m3onSuccess: "#213528"
property color m3onSuccessContainer: "#D1E9D6"
property color m3onSurface: "#e4e1e7"
property color m3onSurfaceVariant: "#c6c5d1"
property color m3onTertiary: "#4c1f48"
property color m3onTertiaryContainer: "#000000"
property color m3onTertiaryFixed: "#340831"
property color m3onTertiaryFixedVariant: "#66365f"
property color m3outline: "#90909a"
property color m3outlineVariant: "#46464f"
property color m3primary: "#bac3ff"
property color m3primaryContainer: "#6a73ac"
property color m3primaryFixed: "#dee0ff"
property color m3primaryFixedDim: "#bac3ff"
property color m3primary_paletteKeyColor: "#6a73ac"
property color m3scrim: "#000000"
property color m3secondary: "#c3c5e0"
property color m3secondaryContainer: "#42455c"
property color m3secondaryFixed: "#dfe1fd"
property color m3secondaryFixedDim: "#c3c5e0"
property color m3secondary_paletteKeyColor: "#72758e"
property color m3shadow: "#000000"
property color m3success: "#B5CCBA"
property color m3successContainer: "#374B3E"
property color m3surface: "#131317"
property color m3surfaceBright: "#39393d"
property color m3surfaceContainer: "#1f1f23"
property color m3surfaceContainerHigh: "#2a2a2e"
property color m3surfaceContainerHighest: "#353438"
property color m3surfaceContainerLow: "#1b1b1f"
property color m3surfaceContainerLowest: "#0e0e12"
property color m3surfaceDim: "#131317"
property color m3surfaceTint: "#bac3ff"
property color m3surfaceVariant: "#46464f"
property color m3tertiary: "#f1b3e5"
property color m3tertiaryContainer: "#b77ead"
property color m3tertiaryFixed: "#ffd7f4"
property color m3tertiaryFixedDim: "#f1b3e5"
property color m3tertiary_paletteKeyColor: "#9b6592"
}
component M3Palette: QtObject { component M3Palette: QtObject {
property color m3background: "#191114" property color m3background: "#191114"
property color m3error: "#ffb4ab" property color m3error: "#ffb4ab"
@@ -224,11 +279,8 @@ Singleton {
readonly property color m3tertiary_paletteKeyColor: root.layer(root.palette.m3tertiary_paletteKeyColor) readonly property color m3tertiary_paletteKeyColor: root.layer(root.palette.m3tertiary_paletteKeyColor)
} }
component Transparency: QtObject { component Transparency: QtObject {
readonly property real base: Math.max(0, Math.min(1, Appearance.transparency.base - (root.light ? 0.1 : 0))) readonly property real base: Appearance.transparency.base - (root.light ? 0.1 : 0)
readonly property bool enabled: Appearance.transparency.enabled readonly property bool enabled: Appearance.transparency.enabled
readonly property real layers: Appearance.transparency.layers readonly property real layers: Appearance.transparency.layers
onBaseChanged: debounceTimer.restart()
onEnabledChanged: debounceTimer.restart()
} }
} }
+1 -19
View File
@@ -4,15 +4,13 @@ import Quickshell
JsonObject { JsonObject {
property Apps apps: Apps { property Apps apps: Apps {
} }
property Battery battery: Battery {
}
property Color color: Color { property Color color: Color {
} }
property string dateFormat: "ddd d MMM - hh:mm:ss"
property bool desktopIcons: false property bool desktopIcons: false
property Idle idle: Idle { property Idle idle: Idle {
} }
property string logo: "" property string logo: ""
property string username: ""
property string wallpaperPath: Quickshell.env("HOME") + "/Pictures/Wallpapers" property string wallpaperPath: Quickshell.env("HOME") + "/Pictures/Wallpapers"
component Apps: JsonObject { component Apps: JsonObject {
@@ -21,27 +19,11 @@ JsonObject {
property list<string> playback: ["mpv"] property list<string> playback: ["mpv"]
property list<string> terminal: ["kitty"] property list<string> terminal: ["kitty"]
} }
component Battery: JsonObject {
property int critPerc: 5
property list<var> popupThresholds: [
{
perc: 20,
name: qsTr("Low battery"),
message: qsTr("Battery is low"),
icon: "battery_android_frame_2"
},
]
}
component Color: JsonObject { component Color: JsonObject {
property int hyprsunsetTemp: 5000
property string mode: "dark" property string mode: "dark"
property bool neovimColors: false property bool neovimColors: false
property bool scheduleDark: false
property int scheduleDarkEnd: 0 property int scheduleDarkEnd: 0
property int scheduleDarkStart: 0 property int scheduleDarkStart: 0
property bool scheduleHyprsunset: false
property int scheduleHyprsunsetEnd: 0
property int scheduleHyprsunsetStart: 0
property bool schemeGeneration: true property bool schemeGeneration: true
property bool smart: false property bool smart: false
} }
-1
View File
@@ -91,7 +91,6 @@ JsonObject {
property string specialPrefix: "@" property string specialPrefix: "@"
property UseFuzzy useFuzzy: UseFuzzy { property UseFuzzy useFuzzy: UseFuzzy {
} }
property bool uwsm: true
component Sizes: JsonObject { component Sizes: JsonObject {
property int itemHeight: 50 property int itemHeight: 50
-2
View File
@@ -5,8 +5,6 @@ JsonObject {
property bool enableFprint: true property bool enableFprint: true
property int maxFprintTries: 3 property int maxFprintTries: 3
property bool recolorLogo: false property bool recolorLogo: false
property bool showNotifContent: false
property bool showNotifIcon: true
property Sizes sizes: Sizes { property Sizes sizes: Sizes {
} }
-13
View File
@@ -1,13 +0,0 @@
import Quickshell.Io
JsonObject {
property bool enable_pp: true
property string mode: "manual"
property real radius: 12.0
property bool rounding: false
property bool shadow: true
property real shadow_blur: 22.0
property list<int> shadow_color: [0, 0, 0, 160]
property real shadow_offset_x: 5.0
property real shadow_offset_y: 5.0
}
-1
View File
@@ -14,7 +14,6 @@ JsonObject {
"to": "YT Music" "to": "YT Music"
} }
] ]
property bool updates: true
property bool useFahrenheit: false property bool useFahrenheit: false
property bool useTwelveHourClock: Qt.locale().timeFormat(Locale.ShortFormat).toLowerCase().includes("a") property bool useTwelveHourClock: Qt.locale().timeFormat(Locale.ShortFormat).toLowerCase().includes("a")
property int visualizerBars: 30 property int visualizerBars: 30
+1 -1
View File
@@ -83,7 +83,7 @@ ColumnLayout {
radius: Appearance.rounding.normal - Appearance.padding.smaller radius: Appearance.rounding.normal - Appearance.padding.smaller
StateLayer { StateLayer {
onClicked: { function onClicked(): void {
root.greeter.sessionIndex = index; root.greeter.sessionIndex = index;
} }
} }
+1 -1
View File
@@ -84,7 +84,7 @@ ColumnLayout {
radius: Appearance.rounding.normal - Appearance.padding.smaller radius: Appearance.rounding.normal - Appearance.padding.smaller
StateLayer { StateLayer {
onClicked: { function onClicked(): void {
root.greeter.selectUser(modelData.username); root.greeter.selectUser(modelData.username);
} }
} }
+10 -10
View File
@@ -49,11 +49,11 @@ CustomMouseArea {
StateLayer { StateLayer {
id: prevMonthStateLayer id: prevMonthStateLayer
radius: Appearance.rounding.full function onClicked(): void {
onClicked: {
root.state.currentDate = new Date(root.currYear, root.currMonth - 1, 1); root.state.currentDate = new Date(root.currYear, root.currMonth - 1, 1);
} }
radius: Appearance.rounding.full
} }
MaterialIcon { MaterialIcon {
@@ -73,6 +73,10 @@ CustomMouseArea {
implicitWidth: monthYearDisplay.implicitWidth + Appearance.padding.small * 2 implicitWidth: monthYearDisplay.implicitWidth + Appearance.padding.small * 2
StateLayer { StateLayer {
function onClicked(): void {
root.state.currentDate = new Date();
}
anchors.fill: monthYearDisplay anchors.fill: monthYearDisplay
anchors.leftMargin: -Appearance.padding.normal anchors.leftMargin: -Appearance.padding.normal
anchors.margins: -Appearance.padding.small anchors.margins: -Appearance.padding.small
@@ -82,10 +86,6 @@ CustomMouseArea {
return root.currMonth === now.getMonth() && root.currYear === now.getFullYear(); return root.currMonth === now.getMonth() && root.currYear === now.getFullYear();
} }
radius: Appearance.rounding.full radius: Appearance.rounding.full
onClicked: {
root.state.currentDate = new Date();
}
} }
CustomText { CustomText {
@@ -107,11 +107,11 @@ CustomMouseArea {
StateLayer { StateLayer {
id: nextMonthStateLayer id: nextMonthStateLayer
radius: Appearance.rounding.full function onClicked(): void {
onClicked: {
root.state.currentDate = new Date(root.currYear, root.currMonth + 1, 1); root.state.currentDate = new Date(root.currYear, root.currMonth + 1, 1);
} }
radius: Appearance.rounding.full
} }
MaterialIcon { MaterialIcon {
+4 -4
View File
@@ -295,12 +295,12 @@ Item {
StateLayer { StateLayer {
id: controlState id: controlState
color: control.canUse ? DynamicColors.palette[`m3on${control.set_color}`] : DynamicColors.palette[`m3on${control.set_color}Container`] function onClicked(): void {
disabled: !control.canUse
onClicked: {
control.onClicked(); control.onClicked();
} }
color: control.canUse ? DynamicColors.palette[`m3on${control.set_color}`] : DynamicColors.palette[`m3on${control.set_color}Container`]
disabled: !control.canUse
// radius: Appearance.rounding.full // radius: Appearance.rounding.full
} }
+3 -3
View File
@@ -15,11 +15,11 @@ Item {
implicitHeight: Config.launcher.sizes.itemHeight implicitHeight: Config.launcher.sizes.itemHeight
StateLayer { StateLayer {
radius: Appearance.rounding.smallest function onClicked(): void {
onClicked: {
root.modelData?.onClicked(root.list); root.modelData?.onClicked(root.list);
} }
radius: Appearance.rounding.smallest
} }
Item { Item {
+3 -3
View File
@@ -18,12 +18,12 @@ Item {
implicitHeight: Config.launcher.sizes.itemHeight implicitHeight: Config.launcher.sizes.itemHeight
StateLayer { StateLayer {
radius: Appearance.rounding.smallest function onClicked(): void {
onClicked: {
Apps.launch(root.modelData); Apps.launch(root.modelData);
root.visibilities.launcher = false; root.visibilities.launcher = false;
} }
radius: Appearance.rounding.smallest
} }
Item { Item {
+6 -6
View File
@@ -23,11 +23,11 @@ Item {
implicitHeight: Config.launcher.sizes.itemHeight implicitHeight: Config.launcher.sizes.itemHeight
StateLayer { StateLayer {
radius: Appearance.rounding.smallest function onClicked(): void {
onClicked: {
root.onClicked(); root.onClicked();
} }
radius: Appearance.rounding.smallest
} }
RowLayout { RowLayout {
@@ -76,12 +76,12 @@ Item {
StateLayer { StateLayer {
id: stateLayer id: stateLayer
color: DynamicColors.palette.m3onTertiary function onClicked(): void {
onClicked: {
Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.terminal, "fish", "-C", `exec qalc -i '${root.math}'`]); Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.terminal, "fish", "-C", `exec qalc -i '${root.math}'`]);
root.list.visibilities.launcher = false; root.list.visibilities.launcher = false;
} }
color: DynamicColors.palette.m3onTertiary
} }
CustomText { CustomText {
+3 -3
View File
@@ -14,11 +14,11 @@ Item {
implicitHeight: Config.launcher.sizes.itemHeight implicitHeight: Config.launcher.sizes.itemHeight
StateLayer { StateLayer {
radius: Appearance.rounding.smallest function onClicked(): void {
onClicked: {
root.modelData?.onClicked(root.list); root.modelData?.onClicked(root.list);
} }
radius: Appearance.rounding.smallest
} }
Item { Item {
+3 -3
View File
@@ -33,12 +33,12 @@ Item {
} }
StateLayer { StateLayer {
radius: Appearance.rounding.normal function onClicked(): void {
onClicked: {
Wallpapers.setWallpaper(root.modelData.path); Wallpapers.setWallpaper(root.modelData.path);
root.visibilities.launcher = false; root.visibilities.launcher = false;
} }
radius: Appearance.rounding.normal
} }
Elevation { Elevation {
+7 -7
View File
@@ -108,12 +108,12 @@ ColumnLayout {
} }
StateLayer { StateLayer {
cursorShape: Qt.IBeamCursor function onClicked(): void {
hoverEnabled: false
onClicked: {
parent.forceActiveFocus(); parent.forceActiveFocus();
} }
cursorShape: Qt.IBeamCursor
hoverEnabled: false
} }
RowLayout { RowLayout {
@@ -167,11 +167,11 @@ ColumnLayout {
radius: Appearance.rounding.full radius: Appearance.rounding.full
StateLayer { StateLayer {
color: root.lock.pam.buffer ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface function onClicked(): void {
onClicked: {
root.lock.pam.passwd.start(); root.lock.pam.passwd.start();
} }
color: root.lock.pam.buffer ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
} }
MaterialIcon { MaterialIcon {
+3 -3
View File
@@ -178,11 +178,11 @@ Item {
StateLayer { StateLayer {
id: controlState id: controlState
color: control.active ? DynamicColors.palette[`m3on${control.set_color}`] : DynamicColors.palette[`m3on${control.set_color}Container`] function onClicked(): void {
onClicked: {
control.onClicked(); control.onClicked();
} }
color: control.active ? DynamicColors.palette[`m3on${control.set_color}`] : DynamicColors.palette[`m3on${control.set_color}Container`]
} }
MaterialIcon { MaterialIcon {
+3 -3
View File
@@ -161,11 +161,11 @@ CustomRect {
} }
StateLayer { StateLayer {
color: root.urgency === "critical" ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onSurface function onClicked(): void {
onClicked: {
root.expanded = !root.expanded; root.expanded = !root.expanded;
} }
color: root.urgency === "critical" ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onSurface
} }
RowLayout { RowLayout {
+2
View File
@@ -32,6 +32,8 @@ CustomRect {
} }
StateLayer { StateLayer {
cursorShape: Qt.PointingHandCursor
onClicked: { onClicked: {
root.visibilities.sidebar = !root.visibilities.sidebar; root.visibilities.sidebar = !root.visibilities.sidebar;
} }
+8 -8
View File
@@ -307,12 +307,12 @@ CustomRect {
implicitWidth: expandIcon.height implicitWidth: expandIcon.height
StateLayer { StateLayer {
color: root.modelData.urgency === NotificationUrgency.Critical ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface function onClicked() {
radius: Appearance.rounding.full
onClicked: {
root.expanded = !root.expanded; root.expanded = !root.expanded;
} }
color: root.modelData.urgency === NotificationUrgency.Critical ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
radius: Appearance.rounding.full
} }
MaterialIcon { MaterialIcon {
@@ -434,12 +434,12 @@ CustomRect {
radius: Appearance.rounding.full radius: Appearance.rounding.full
StateLayer { StateLayer {
color: root.modelData.urgency === NotificationUrgency.Critical ? DynamicColors.palette.m3onSecondary : DynamicColors.palette.m3onSurface function onClicked(): void {
radius: Appearance.rounding.full
onClicked: {
action.modelData.invoke(); action.modelData.invoke();
} }
color: root.modelData.urgency === NotificationUrgency.Critical ? DynamicColors.palette.m3onSecondary : DynamicColors.palette.m3onSurface
radius: Appearance.rounding.full
} }
CustomText { CustomText {
@@ -78,7 +78,7 @@ Item {
StateLayer { StateLayer {
id: actionStateLayer id: actionStateLayer
onClicked: { function onClicked(): void {
if (action.modelData.isClose) { if (action.modelData.isClose) {
root.notif.close(); root.notif.close();
} else if (action.modelData.isCopy) { } else if (action.modelData.isCopy) {
+3 -3
View File
@@ -171,11 +171,11 @@ CustomRect {
radius: Appearance.rounding.full radius: Appearance.rounding.full
StateLayer { StateLayer {
color: root.urgency === NotificationUrgency.Critical ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onSurface function onClicked(): void {
onClicked: {
root.toggleExpand(!root.expanded); root.toggleExpand(!root.expanded);
} }
color: root.urgency === NotificationUrgency.Critical ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onSurface
} }
RowLayout { RowLayout {
+2 -1
View File
@@ -62,7 +62,6 @@ SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Color" sectionId: "Color"
z: 1
SettingsHeader { SettingsHeader {
name: "Color" name: "Color"
@@ -106,6 +105,7 @@ SettingsPage {
active: root.schemeTypeItem(menuItems, Config.colors.schemeType) active: root.schemeTypeItem(menuItems, Config.colors.schemeType)
enabled: Config.general.color.schemeGeneration enabled: Config.general.color.schemeGeneration
label: qsTr("Scheme type") label: qsTr("Scheme type")
z: 2
menuItems: [ menuItems: [
MenuItem { MenuItem {
@@ -250,6 +250,7 @@ SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Default Apps" sectionId: "Default Apps"
z: -1
SettingsHeader { SettingsHeader {
name: "Default Apps" name: "Default Apps"
+3 -3
View File
@@ -44,11 +44,11 @@ CustomRect {
} }
StateLayer { StateLayer {
visible: root.enabled function onClicked(): void {
onClicked: {
SettingsDropdowns.toggle(menu, root); SettingsDropdowns.toggle(menu, root);
} }
visible: root.enabled
} }
PathViewMenu { PathViewMenu {
@@ -141,14 +141,14 @@ Item {
id: zoomSlider id: zoomSlider
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: Appearance.padding.larger * 3 Layout.preferredHeight: 30
from: 1.0 from: 1.0
implicitHeight: Appearance.padding.larger * 3 implicitHeight: 30
to: 5.0 to: 5.0
value: cropRectLoader.item ? cropRectLoader.item.zoom : 1.0 value: cropRectLoader.item ? cropRectLoader.item.zoom : 1.0
onInteraction: value => { onMoved: {
delegate.zoomClipRect(1 + (value * 4)); delegate.zoomClipRect(value);
wrapper.changesMade = true; wrapper.changesMade = true;
} }
} }
+4 -4
View File
@@ -131,16 +131,16 @@ GridView {
} }
StateLayer { StateLayer {
function onClicked(): void {
Wallpapers.setWallpaper(modelData.path);
}
anchors.bottomMargin: itemMargin anchors.bottomMargin: itemMargin
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: itemMargin anchors.leftMargin: itemMargin
anchors.rightMargin: itemMargin anchors.rightMargin: itemMargin
anchors.topMargin: itemMargin anchors.topMargin: itemMargin
radius: itemRadius radius: itemRadius
onClicked: {
Wallpapers.setWallpaper(modelData.path);
}
} }
} }
Behavior on opacity { Behavior on opacity {
+31 -31
View File
@@ -19,7 +19,7 @@ Item {
required property var wrapper required property var wrapper
implicitHeight: vol.implicitHeight + Appearance.padding.small * 2 implicitHeight: vol.implicitHeight + Appearance.padding.small * 2
implicitWidth: 600 + Appearance.padding.small * 2 implicitWidth: 400 + Appearance.padding.small * 2
CustomRect { CustomRect {
anchors.left: parent.left anchors.left: parent.left
@@ -52,7 +52,7 @@ Item {
CustomRect { CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 65 + Appearance.spacing.smaller * 2 Layout.preferredHeight: 50 + Appearance.spacing.smaller * 2
Layout.topMargin: root.topMargin Layout.topMargin: root.topMargin
color: DynamicColors.tPalette.m3surfaceContainer color: DynamicColors.tPalette.m3surfaceContainer
radius: root.rounding radius: root.rounding
@@ -62,15 +62,15 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: Appearance.padding.larger anchors.leftMargin: Appearance.padding.normal
anchors.top: parent.top anchors.top: parent.top
implicitWidth: childrenRect.width implicitWidth: childrenRect.width
CustomRect { CustomRect {
anchors.centerIn: parent anchors.centerIn: parent
color: Audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary color: Audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: 54 implicitHeight: 40
implicitWidth: 54 implicitWidth: 40
radius: Appearance.rounding.full radius: Appearance.rounding.full
MaterialIcon { MaterialIcon {
@@ -78,7 +78,7 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
animate: true animate: true
color: Audio.muted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary color: Audio.muted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
font.pointSize: Appearance.font.size.extraLarge font.pointSize: 22
text: Audio.muted ? "volume_off" : "volume_up" text: Audio.muted ? "volume_off" : "volume_up"
} }
@@ -98,7 +98,7 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: Appearance.padding.smallest anchors.bottomMargin: Appearance.padding.smallest
anchors.left: sinkIcon.right anchors.left: sinkIcon.right
anchors.leftMargin: Appearance.spacing.larger anchors.leftMargin: Appearance.spacing.normal
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Appearance.padding.large anchors.rightMargin: Appearance.padding.large
anchors.top: parent.top anchors.top: parent.top
@@ -122,14 +122,14 @@ Item {
} }
CustomMouseArea { CustomMouseArea {
Layout.bottomMargin: Appearance.padding.normal Layout.bottomMargin: 5
Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: Appearance.padding.larger * 3
CustomSlider { CustomSlider {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
fgColor: Audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary color: Audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: parent.height implicitHeight: parent.height
value: Audio.volume value: Audio.volume
@@ -138,7 +138,7 @@ Item {
} }
} }
onInteraction: value => Audio.setVolume(value) onMoved: Audio.setVolume(value)
} }
} }
} }
@@ -146,7 +146,7 @@ Item {
CustomClippingRect { CustomClippingRect {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 65 + Appearance.spacing.smaller * 2 Layout.preferredHeight: 50 + Appearance.spacing.smaller * 2
Layout.topMargin: root.topMargin Layout.topMargin: root.topMargin
color: DynamicColors.tPalette.m3surfaceContainer color: DynamicColors.tPalette.m3surfaceContainer
radius: root.rounding radius: root.rounding
@@ -178,15 +178,15 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: Appearance.padding.larger anchors.leftMargin: Appearance.padding.normal
anchors.top: parent.top anchors.top: parent.top
implicitWidth: childrenRect.width implicitWidth: childrenRect.width
CustomRect { CustomRect {
anchors.centerIn: parent anchors.centerIn: parent
color: Audio.sourceMuted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary color: Audio.sourceMuted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: 54 implicitHeight: 40
implicitWidth: 54 implicitWidth: 40
radius: Appearance.rounding.full radius: Appearance.rounding.full
MaterialIcon { MaterialIcon {
@@ -194,7 +194,7 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
animate: true animate: true
color: Audio.sourceMuted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary color: Audio.sourceMuted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
font.pointSize: Appearance.font.size.extraLarge font.pointSize: 22
text: Audio.sourceMuted ? "mic_off" : "mic" text: Audio.sourceMuted ? "mic_off" : "mic"
} }
@@ -214,7 +214,7 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: Appearance.padding.smallest anchors.bottomMargin: Appearance.padding.smallest
anchors.left: sourceIcon.right anchors.left: sourceIcon.right
anchors.leftMargin: Appearance.spacing.larger anchors.leftMargin: Appearance.spacing.normal
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Appearance.padding.large anchors.rightMargin: Appearance.padding.large
anchors.top: parent.top anchors.top: parent.top
@@ -238,14 +238,14 @@ Item {
} }
CustomMouseArea { CustomMouseArea {
Layout.bottomMargin: Appearance.padding.normal Layout.bottomMargin: 5
Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: Appearance.padding.larger * 3
CustomSlider { CustomSlider {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
fgColor: Audio.sourceMuted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary color: Audio.sourceMuted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: parent.height implicitHeight: parent.height
value: Audio.sourceVolume value: Audio.sourceVolume
@@ -254,7 +254,7 @@ Item {
} }
} }
onInteraction: value => Audio.setSourceVolume(value) onMoved: Audio.setSourceVolume(value)
} }
} }
} }
@@ -280,7 +280,7 @@ Item {
required property var modelData required property var modelData
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: 65 + Appearance.spacing.smaller * 2 Layout.preferredHeight: 50 + Appearance.spacing.smaller * 2
Layout.topMargin: root.topMargin Layout.topMargin: root.topMargin
color: DynamicColors.tPalette.m3surfaceContainer color: DynamicColors.tPalette.m3surfaceContainer
radius: root.rounding radius: root.rounding
@@ -312,15 +312,15 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: Appearance.padding.larger anchors.leftMargin: Appearance.padding.normal
anchors.top: parent.top anchors.top: parent.top
implicitWidth: childrenRect.width implicitWidth: childrenRect.width
CustomRect { CustomRect {
anchors.centerIn: parent anchors.centerIn: parent
color: appBox.modelData.audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary color: appBox.modelData.audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: 54 implicitHeight: 40
implicitWidth: 54 implicitWidth: 40
radius: Appearance.rounding.full radius: Appearance.rounding.full
MaterialIcon { MaterialIcon {
@@ -329,7 +329,7 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
animate: true animate: true
color: appBox.modelData.audio.muted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary color: appBox.modelData.audio.muted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
font.pointSize: Appearance.font.size.extraLarge font.pointSize: 22
text: appBox.modelData.audio.muted ? "volume_off" : "volume_up" text: appBox.modelData.audio.muted ? "volume_off" : "volume_up"
} }
@@ -356,7 +356,7 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: Appearance.padding.smallest anchors.bottomMargin: Appearance.padding.smallest
anchors.left: appBoxIcon.right anchors.left: appBoxIcon.right
anchors.leftMargin: Appearance.spacing.larger anchors.leftMargin: Appearance.spacing.normal
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Appearance.padding.large anchors.rightMargin: Appearance.padding.large
anchors.top: parent.top anchors.top: parent.top
@@ -381,18 +381,18 @@ Item {
} }
CustomMouseArea { CustomMouseArea {
Layout.bottomMargin: Appearance.padding.normal Layout.bottomMargin: 5
Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: Appearance.padding.larger * 3
CustomSlider { CustomSlider {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
fgColor: appBox.modelData.audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary color: appBox.modelData.audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: parent.height implicitHeight: parent.height
value: appBox.modelData.audio.volume value: appBox.modelData.audio.volume
onInteraction: value => { onMoved: {
Audio.setStreamVolume(appBox.modelData, value); Audio.setStreamVolume(appBox.modelData, value);
} }
} }
+8 -8
View File
@@ -103,10 +103,7 @@ StackView {
implicitHeight: 30 implicitHeight: 30
StateLayer { StateLayer {
disabled: !item.modelData.enabled function onClicked(): void {
radius: item.radius
onClicked: {
const entry = item.modelData; const entry = item.modelData;
if (entry.hasChildren) { if (entry.hasChildren) {
root.rootWidth = root.biggestWidth; root.rootWidth = root.biggestWidth;
@@ -120,6 +117,9 @@ StackView {
root.popouts.hasCurrent = false; root.popouts.hasCurrent = false;
} }
} }
disabled: !item.modelData.enabled
radius: item.radius
} }
Loader { Loader {
@@ -217,13 +217,13 @@ StackView {
radius: Appearance.rounding.full radius: Appearance.rounding.full
StateLayer { StateLayer {
color: DynamicColors.palette.m3onSecondaryContainer function onClicked(): void {
radius: parent.radius
onClicked: {
root.pop(); root.pop();
root.biggestWidth = root.rootWidth; root.biggestWidth = root.rootWidth;
} }
color: DynamicColors.palette.m3onSecondaryContainer
radius: parent.radius
} }
} }
+4 -4
View File
@@ -153,12 +153,12 @@ Item {
implicitWidth: icon.implicitHeight + 5 * 2 implicitWidth: icon.implicitHeight + 5 * 2
StateLayer { StateLayer {
color: profiles.current === parent.icon ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface function onClicked(): void {
radius: Appearance.rounding.full
onClicked: {
PowerProfiles.profile = parent.profile; PowerProfiles.profile = parent.profile;
} }
color: profiles.current === parent.icon ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
radius: Appearance.rounding.full
} }
MaterialIcon { MaterialIcon {
-1
View File
@@ -45,7 +45,6 @@ qml_module(ZShell
requests.hpp requests.cpp requests.hpp requests.cpp
toaster.hpp toaster.cpp toaster.hpp toaster.cpp
qalculator.hpp qalculator.cpp qalculator.hpp qalculator.cpp
zutils.hpp zutils.cpp
LIBRARIES LIBRARIES
Qt::Gui Qt::Gui
Qt::Quick Qt::Quick
-1
View File
@@ -2,7 +2,6 @@ qml_module(ZShell-components
URI ZShell.Components URI ZShell.Components
SOURCES SOURCES
lazylistview.hpp lazylistview.cpp lazylistview.hpp lazylistview.cpp
wavyline.hpp wavyline.cpp
LIBRARIES LIBRARIES
Qt::Quick Qt::Quick
) )
-255
View File
@@ -1,255 +0,0 @@
#include "wavyline.hpp"
#include <qpainter.h>
#include <qpainterpath.h>
namespace ZShell::controls {
WavyLine::WavyLine(QQuickItem* parent)
: QQuickPaintedItem(parent)
, m_lineWidth(4)
, m_amplitudeMultiplier(0.5)
, m_frequency(6)
, m_startX(0)
, m_fullLength(0)
, m_color(Qt::white)
, m_waveProgress(0)
, m_pathType(Linear)
, m_startAngle(0)
, m_fullAngle(360)
, m_radius(-1)
, m_value(1)
, m_startAngleRad(0)
, m_fullAngleRad(2 * M_PI) {
setAntialiasing(true);
}
int WavyLine::lineWidth() const {
return m_lineWidth;
}
void WavyLine::setLineWidth(int lineWidth) {
if (m_lineWidth != lineWidth) {
m_lineWidth = lineWidth;
emit lineWidthChanged();
update();
}
}
qreal WavyLine::amplitudeMultiplier() const {
return m_amplitudeMultiplier;
}
void WavyLine::setAmplitudeMultiplier(qreal amplitudeMultiplier) {
if (!qFuzzyCompare(m_amplitudeMultiplier + 1.0, amplitudeMultiplier + 1.0)) {
m_amplitudeMultiplier = amplitudeMultiplier;
emit amplitudeMultiplierChanged();
update();
}
}
int WavyLine::frequency() const {
return m_frequency;
}
void WavyLine::setFrequency(int frequency) {
if (m_frequency != frequency) {
m_frequency = frequency;
emit frequencyChanged();
update();
}
}
qreal WavyLine::startX() const {
return m_startX;
}
void WavyLine::setStartX(qreal startX) {
if (!qFuzzyCompare(m_startX + 1.0, startX + 1.0)) {
m_startX = startX;
emit startXChanged();
update();
}
}
qreal WavyLine::fullLength() const {
return m_fullLength;
}
void WavyLine::setFullLength(qreal fullLength) {
if (!qFuzzyCompare(m_fullLength + 1.0, fullLength + 1.0)) {
m_fullLength = fullLength;
emit fullLengthChanged();
update();
}
}
QColor WavyLine::color() const {
return m_color;
}
void WavyLine::setColor(const QColor& color) {
if (m_color != color) {
m_color = color;
emit colorChanged();
update();
}
}
qreal WavyLine::waveProgress() const {
return m_waveProgress;
}
void WavyLine::setWaveProgress(qreal progress) {
if (!qFuzzyCompare(m_waveProgress + 1.0, progress + 1.0)) {
m_waveProgress = progress;
emit waveProgressChanged();
update();
}
}
WavyLine::PathType WavyLine::pathType() const {
return m_pathType;
}
void WavyLine::setPathType(PathType pathType) {
if (m_pathType != pathType) {
m_pathType = pathType;
emit pathTypeChanged();
update();
}
}
qreal WavyLine::startAngle() const {
return m_startAngle;
}
void WavyLine::setStartAngle(qreal startAngle) {
if (!qFuzzyCompare(m_startAngle + 1.0, startAngle + 1.0)) {
m_startAngle = startAngle;
m_startAngleRad = startAngle * M_PI / 180.0;
emit startAngleChanged();
update();
}
}
qreal WavyLine::fullAngle() const {
return m_fullAngle;
}
void WavyLine::setFullAngle(qreal fullAngle) {
if (!qFuzzyCompare(m_fullAngle + 1.0, fullAngle + 1.0)) {
m_fullAngle = fullAngle;
m_fullAngleRad = fullAngle * M_PI / 180.0;
emit fullAngleChanged();
update();
}
}
qreal WavyLine::radius() const {
return m_radius;
}
void WavyLine::setRadius(qreal radius) {
if (!qFuzzyCompare(m_radius + 1.0, radius + 1.0)) {
m_radius = radius;
emit radiusChanged();
update();
}
}
qreal WavyLine::value() const {
return m_value;
}
void WavyLine::setValue(qreal value) {
if (!qFuzzyCompare(m_value + 1.0, value + 1.0)) {
m_value = value;
emit valueChanged();
update();
}
}
void WavyLine::paint(QPainter* painter) {
painter->setRenderHint(QPainter::Antialiasing);
painter->setPen(QPen(m_color, m_lineWidth, Qt::SolidLine, Qt::RoundCap));
if (m_pathType == Arc) {
paintArc(painter);
} else {
paintLinear(painter);
}
}
void WavyLine::paintLinear(QPainter* painter) {
const auto amplitude = m_lineWidth * m_amplitudeMultiplier;
const auto phase = m_waveProgress * 2 * M_PI;
const auto centerY = height() / 2;
const auto len = m_fullLength > 0 ? m_fullLength : 1;
const auto start = m_lineWidth / 2.0;
const auto fullEnd = width() - m_lineWidth / 2.0;
const auto drawEnd = start + (fullEnd - start) * m_value;
QPainterPath path;
bool first = true;
for (int x = m_lineWidth / 2; x <= drawEnd; ++x) {
const auto theta = m_frequency * 2 * M_PI * (x + m_startX) / len + phase;
const auto waveY = centerY + amplitude * qSin(theta);
if (first) {
path.moveTo(x, waveY);
first = false;
} else {
path.lineTo(x, waveY);
}
}
painter->drawPath(path);
}
void WavyLine::paintArc(QPainter* painter) {
if (m_fullAngleRad <= 0) {
return;
}
const auto amplitude = m_lineWidth * m_amplitudeMultiplier;
const auto cx = width() / 2.0;
const auto cy = height() / 2.0;
const auto radius = m_radius > 0 ? m_radius : (qMin(width(), height()) - m_lineWidth - 2 * amplitude) / 2.0;
if (radius <= 0) {
return;
}
const auto phase = m_waveProgress * 2 * M_PI;
const auto arcLen = radius * m_fullAngleRad;
const auto len = m_fullLength > 0 ? m_fullLength : arcLen;
const auto drawAngleRad = m_fullAngleRad * m_value;
if (drawAngleRad <= 0) {
return;
}
const auto N = qMax(64, qCeil(radius * drawAngleRad));
const auto dTheta = drawAngleRad / N;
QPainterPath path;
for (int i = 0; i <= N; ++i) {
const auto theta = m_startAngleRad + i * dTheta;
const auto s = i * dTheta * radius;
const auto phi = m_frequency * 2 * M_PI * (s + m_startX) / len + phase;
const auto r = radius + amplitude * qSin(phi);
const auto px = cx + r * qCos(theta);
const auto py = cy + r * qSin(theta);
if (i == 0) {
path.moveTo(px, py);
} else {
path.lineTo(px, py);
}
}
painter->drawPath(path);
}
} // namespace ZShell::controls
-107
View File
@@ -1,107 +0,0 @@
#pragma once
#include <qqmlintegration.h>
#include <qquickpainteditem.h>
namespace ZShell::controls {
class WavyLine : public QQuickPaintedItem {
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(int lineWidth READ lineWidth WRITE setLineWidth NOTIFY lineWidthChanged FINAL)
Q_PROPERTY(qreal amplitudeMultiplier READ amplitudeMultiplier WRITE setAmplitudeMultiplier NOTIFY
amplitudeMultiplierChanged FINAL)
Q_PROPERTY(int frequency READ frequency WRITE setFrequency NOTIFY frequencyChanged FINAL)
Q_PROPERTY(qreal startX READ startX WRITE setStartX NOTIFY startXChanged FINAL)
Q_PROPERTY(qreal fullLength READ fullLength WRITE setFullLength NOTIFY fullLengthChanged FINAL)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL)
Q_PROPERTY(qreal waveProgress READ waveProgress WRITE setWaveProgress NOTIFY waveProgressChanged FINAL)
Q_PROPERTY(PathType pathType READ pathType WRITE setPathType NOTIFY pathTypeChanged FINAL)
Q_PROPERTY(qreal startAngle READ startAngle WRITE setStartAngle NOTIFY startAngleChanged FINAL)
Q_PROPERTY(qreal fullAngle READ fullAngle WRITE setFullAngle NOTIFY fullAngleChanged FINAL)
Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged FINAL)
Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged FINAL)
public:
enum PathType {
Linear,
Arc
};
Q_ENUM(PathType)
explicit WavyLine(QQuickItem* parent = nullptr);
[[nodiscard]] int lineWidth() const;
void setLineWidth(int lineWidth);
[[nodiscard]] qreal amplitudeMultiplier() const;
void setAmplitudeMultiplier(qreal amplitudeMultiplier);
[[nodiscard]] int frequency() const;
void setFrequency(int frequency);
[[nodiscard]] qreal startX() const;
void setStartX(qreal startX);
[[nodiscard]] qreal fullLength() const;
void setFullLength(qreal fullLength);
[[nodiscard]] QColor color() const;
void setColor(const QColor& color);
[[nodiscard]] qreal waveProgress() const;
void setWaveProgress(qreal progress);
[[nodiscard]] PathType pathType() const;
void setPathType(PathType pathType);
[[nodiscard]] qreal startAngle() const;
void setStartAngle(qreal startAngle);
[[nodiscard]] qreal fullAngle() const;
void setFullAngle(qreal fullAngle);
[[nodiscard]] qreal radius() const;
void setRadius(qreal radius);
[[nodiscard]] qreal value() const;
void setValue(qreal value);
void paint(QPainter* painter) override;
signals:
void lineWidthChanged();
void amplitudeMultiplierChanged();
void frequencyChanged();
void startXChanged();
void fullLengthChanged();
void colorChanged();
void waveProgressChanged();
void pathTypeChanged();
void startAngleChanged();
void fullAngleChanged();
void radiusChanged();
void valueChanged();
private:
void paintLinear(QPainter* painter);
void paintArc(QPainter* painter);
int m_lineWidth;
qreal m_amplitudeMultiplier;
int m_frequency;
qreal m_startX;
qreal m_fullLength;
QColor m_color;
qreal m_waveProgress;
PathType m_pathType;
qreal m_startAngle;
qreal m_fullAngle;
qreal m_radius;
qreal m_value;
qreal m_startAngleRad;
qreal m_fullAngleRad;
};
} // namespace ZShell::controls
+2 -1
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <cstdint>
#include <qobject.h> #include <qobject.h>
#include <qqmlintegration.h> #include <qqmlintegration.h>
#include <qqmllist.h> #include <qqmllist.h>
@@ -20,7 +21,7 @@ Q_PROPERTY(int timeout READ timeout CONSTANT)
Q_PROPERTY(Type type READ type CONSTANT) Q_PROPERTY(Type type READ type CONSTANT)
public: public:
enum class Type { enum class Type: std::uint8_t {
Info = 0, Info = 0,
Success, Success,
Warning, Warning,
-145
View File
@@ -1,145 +0,0 @@
#include "zutils.hpp"
#include <QtConcurrent/qtconcurrentrun.h>
#include <QtQuick/qquickitemgrabresult.h>
#include <QtQuick/qquickwindow.h>
#include <qdir.h>
#include <qfileinfo.h>
#include <qfuturewatcher.h>
#include <qloggingcategory.h>
#include <qqmlengine.h>
Q_LOGGING_CATEGORY(lcZUtils, "ZShell.cutils", QtInfoMsg)
namespace ZShell {
void ZUtils::saveItem(QQuickItem* target, const QUrl& path) {
this->saveItem(target, path, QRect(), QJSValue(), QJSValue());
}
void ZUtils::saveItem(QQuickItem* target, const QUrl& path, const QRect& rect) {
this->saveItem(target, path, rect, QJSValue(), QJSValue());
}
void ZUtils::saveItem(QQuickItem* target, const QUrl& path, QJSValue onSaved) {
this->saveItem(target, path, QRect(), onSaved, QJSValue());
}
void ZUtils::saveItem(QQuickItem* target, const QUrl& path, QJSValue onSaved, QJSValue onFailed) {
this->saveItem(target, path, QRect(), onSaved, onFailed);
}
void ZUtils::saveItem(QQuickItem* target, const QUrl& path, const QRect& rect, QJSValue onSaved) {
this->saveItem(target, path, rect, onSaved, QJSValue());
}
void ZUtils::saveItem(QQuickItem* target, const QUrl& path, const QRect& rect, QJSValue onSaved, QJSValue onFailed) {
if (!target) {
qCWarning(lcZUtils) << "saveItem: a target is required";
return;
}
if (!path.isLocalFile()) {
qCWarning(lcZUtils) << "saveItem:" << path << "is not a local file";
return;
}
if (!target->window()) {
qCWarning(lcZUtils) << "saveItem: unable to save target" << target << "without a window";
return;
}
auto scaledRect = rect;
const qreal scale = target->window()->devicePixelRatio();
if (rect.isValid() && !qFuzzyCompare(scale + 1.0, 2.0)) {
scaledRect =
QRectF(rect.left() * scale, rect.top() * scale, rect.width() * scale, rect.height() * scale).toRect();
}
const QSharedPointer<const QQuickItemGrabResult> grabResult = target->grabToImage();
QObject::connect(grabResult.data(), &QQuickItemGrabResult::ready, this,
[grabResult, scaledRect, path, onSaved, onFailed, this]() {
const auto future = QtConcurrent::run([=]() {
QImage image = grabResult->image();
if (scaledRect.isValid()) {
image = image.copy(scaledRect);
}
const QString file = path.toLocalFile();
const QString parent = QFileInfo(file).absolutePath();
return QDir().mkpath(parent) && image.save(file);
});
auto* watcher = new QFutureWatcher<bool>(this);
auto* engine = qmlEngine(this);
QObject::connect(watcher, &QFutureWatcher<bool>::finished, this, [=]() {
if (watcher->result()) {
if (onSaved.isCallable()) {
QJSValueList args = { QJSValue(path.toLocalFile()) };
if (engine) {
args << engine->toScriptValue(QVariant::fromValue(path));
}
onSaved.call(args);
}
} else {
qCWarning(lcZUtils) << "saveItem: failed to save" << path;
if (onFailed.isCallable()) {
if (engine) {
onFailed.call({ engine->toScriptValue(QVariant::fromValue(path)) });
} else {
onFailed.call();
}
}
}
watcher->deleteLater();
});
watcher->setFuture(future);
});
}
bool ZUtils::copyFile(const QUrl& source, const QUrl& target, bool overwrite) {
if (!source.isLocalFile()) {
qCWarning(lcZUtils) << "copyFile: source" << source << "is not a local file";
return false;
}
if (!target.isLocalFile()) {
qCWarning(lcZUtils) << "copyFile: target" << target << "is not a local file";
return false;
}
if (overwrite && QFile::exists(target.toLocalFile())) {
if (!QFile::remove(target.toLocalFile())) {
qCWarning(lcZUtils) << "copyFile: overwrite was specified but failed to remove" << target.toLocalFile();
return false;
}
}
return QFile::copy(source.toLocalFile(), target.toLocalFile());
}
bool ZUtils::deleteFile(const QUrl& path) {
if (!path.isLocalFile()) {
qCWarning(lcZUtils) << "deleteFile: path" << path << "is not a local file";
return false;
}
return QFile::remove(path.toLocalFile());
}
QString ZUtils::toLocalFile(const QUrl& url) {
if (!url.isLocalFile()) {
qCWarning(lcZUtils) << "toLocalFile: given url is not a local file" << url;
return QString();
}
return url.toLocalFile();
}
qreal ZUtils::clamp(qreal value, qreal min, qreal max) {
return qBound(min, value, max);
}
} // namespace ZShell
-31
View File
@@ -1,31 +0,0 @@
#pragma once
#include <QtQuick/qquickitem.h>
#include <qobject.h>
#include <qqmlintegration.h>
namespace ZShell {
class ZUtils : public QObject {
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
public:
// clang-format off
Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path);
Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, const QRect& rect);
Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, QJSValue onSaved);
Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, QJSValue onSaved, QJSValue onFailed);
Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, const QRect& rect, QJSValue onSaved);
Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, const QRect& rect, QJSValue onSaved, QJSValue onFailed);
// clang-format on
Q_INVOKABLE static bool copyFile(const QUrl& source, const QUrl& target, bool overwrite = true);
Q_INVOKABLE static bool deleteFile(const QUrl& path);
Q_INVOKABLE static QString toLocalFile(const QUrl& url);
Q_INVOKABLE static qreal clamp(qreal value, qreal min, qreal max);
};
} // namespace ZShell
+1 -2
View File
@@ -4,7 +4,6 @@
//@ pragma Env QSG_NO_VSYNC=1 //@ pragma Env QSG_NO_VSYNC=1
//@ pragma Env QS_NO_RELOAD_POPUP=1 //@ pragma Env QS_NO_RELOAD_POPUP=1
//@ pragma Env QT_SCALE_FACTOR_ROUNDING_POLICY=Round //@ pragma Env QT_SCALE_FACTOR_ROUNDING_POLICY=Round
//@ pragma DefaultEnv QT_QUICK_FLICKABLE_WHEEL_DECELERATION=10000
//@ pragma DropExpensiveFonts //@ pragma DropExpensiveFonts
import Quickshell import Quickshell
import Quickshell.Services.UPower import Quickshell.Services.UPower
@@ -23,7 +22,7 @@ ShellRoot {
settings.watchFiles: true settings.watchFiles: true
Drawers { Windows {
} }
Wallpaper { Wallpaper {