1 Commits

Author SHA1 Message Date
AramJonghu d799e61c79 clang-tidy fixes incoming 2026-06-05 18:02:27 +02:00
82 changed files with 1322 additions and 2765 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
} }
} }
-18
View File
@@ -3,29 +3,11 @@ import QtQuick
ListView { ListView {
id: root id: root
property bool doneFakeFlick
maximumFlickVelocity: 3000 maximumFlickVelocity: 3000
rebound: Transition { rebound: Transition {
onRunningChanged: {
if (!running && !root.doneFakeFlick) {
root.doneFakeFlick = true;
root.flick(1, 1);
root.flick(-1, -1);
Qt.callLater(() => root.cancelFlick());
}
}
Anim { Anim {
properties: "x,y" properties: "x,y"
} }
} }
Timer {
interval: 10
running: root.doneFakeFlick
onTriggered: root.doneFakeFlick = false
}
} }
+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 {
+14 -18
View File
@@ -1,6 +1,6 @@
import qs.Config
import QtQuick import QtQuick
import QtQuick.Templates import QtQuick.Templates
import qs.Config
ScrollBar { ScrollBar {
id: root id: root
@@ -12,7 +12,7 @@ ScrollBar {
property real nonAnimPosition property real nonAnimPosition
property bool shouldBeActive property bool shouldBeActive
implicitWidth: mouse.containsMouse ? Appearance.padding.extraSmall * 2 : Appearance.padding.extraSmall implicitWidth: 8
contentItem: CustomRect { contentItem: CustomRect {
anchors.left: parent.left anchors.left: parent.left
@@ -33,7 +33,6 @@ ScrollBar {
Behavior on opacity { Behavior on opacity {
Anim { Anim {
type: Anim.DefaultEffects
} }
} }
@@ -41,16 +40,9 @@ ScrollBar {
id: mouse id: mouse
acceptedButtons: Qt.NoButton acceptedButtons: Qt.NoButton
anchors.bottom: parent.bottom anchors.fill: parent
anchors.right: parent.right
anchors.top: parent.top
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
hoverEnabled: true hoverEnabled: true
implicitWidth: Appearance.padding.extraSmall * 2
}
}
Behavior on implicitWidth {
Anim {
} }
} }
Behavior on position { Behavior on position {
@@ -94,19 +86,23 @@ ScrollBar {
// Sync nonAnimPosition with flickable when not animating // Sync nonAnimPosition with flickable when not animating
Connections { Connections {
function onContentYChanged() { function onContentYChanged() {
if (!root.animating && !fullMouse.pressed) { if (!animating && !fullMouse.pressed) {
root._updatingFromFlickable = true; _updatingFromFlickable = true;
const contentHeight = root.flickable.contentHeight; const contentHeight = flickable.contentHeight;
const height = root.flickable.height; const height = flickable.height;
if (contentHeight > height) { if (contentHeight > height) {
root.nonAnimPosition = Math.max(0, Math.min(1, root.flickable.contentY / (contentHeight - height))); nonAnimPosition = Math.max(0, Math.min(1, flickable.contentY / (contentHeight - height)));
} else { } else {
root.nonAnimPosition = 0; nonAnimPosition = 0;
} }
root._updatingFromFlickable = false; _updatingFromFlickable = false;
} }
} }
target: flickable
}
Connections {
function onMovingChanged(): void { function onMovingChanged(): void {
if (root.flickable.moving) if (root.flickable.moving)
root.shouldBeActive = true; root.shouldBeActive = true;
+30 -178
View File
@@ -1,199 +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 alias inset: inset
property color insetColor: enabled ? (inset.attached ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onPrimary) : DynamicColors.palette.m3onSurface
property string insetIcon: ""
property real pos: visualPosition
property int radius: Appearance.rounding.small
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.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: root.radius
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 t = ZUtils.clamp((parent.height - 12) / 16, 0, 1);
const lerp = (a, b) => a + (b - a) * t;
return parent.height * (mouse.pressed ? lerp(3.5, 1.5) : lerp(3, 1.2));
}
implicitWidth: 4
radius: Appearance.rounding.full
Behavior on implicitHeight {
Anim {
type: Anim.FastSpatial
}
}
}
Loader {
id: filled
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
asynchronous: true
sourceComponent: root.wavy ? waveComp : lineComp
}
MaterialIcon {
id: inset
readonly property bool attached: root.pos < 0.1
property real dockT: attached ? 1 : 0
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: root.implicitHeight / 6
anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top
color: root.insetColor anchors.topMargin: root.implicitHeight / 6
font.pixelSize: Appearance.font.size.smaller * 2 bottomRightRadius: root.implicitHeight / 6
text: root.insetIcon color: root.color
verticalAlignment: Text.AlignVCenter implicitWidth: root.handle.x - root.implicitHeight / 6
visible: !root.wavy && root.insetIcon !== "" radius: root.implicitHeight / 6
x: Appearance.spacing.extraSmall + dockT * (handle.x + Appearance.spacing.small) topRightRadius: root.implicitHeight / 6
Behavior on dockT {
Anim {
} }
}
}
Component {
id: lineComp
CustomRect { CustomRect {
bottomRightRadius: Appearance.rounding.extraSmall / 2 anchors.bottom: parent.bottom
color: root.fgColor anchors.bottomMargin: root.implicitHeight / 6
implicitHeight: root.height anchors.right: parent.right
implicitWidth: root.filledWidth anchors.top: parent.top
radius: root.radius anchors.topMargin: root.implicitHeight / 6
topRightRadius: Appearance.rounding.extraSmall / 2 bottomLeftRadius: root.implicitHeight / 6
color: DynamicColors.tPalette.m3surfaceContainerHighest
implicitWidth: parent.width - root.handle.x - root.handle.implicitWidth - root.implicitHeight / 6
radius: root.implicitHeight / 6
topLeftRadius: root.implicitHeight / 6
} }
} }
handle: CustomRect {
Component { anchors.verticalCenter: parent.verticalCenter
id: waveComp color: root.color
implicitHeight: root.implicitHeight
WavyLine { implicitWidth: root.implicitHeight / 4.5
color: root.fgColor radius: Appearance.rounding.full
frequency: root.waveFrequency x: root.visualPosition * root.availableWidth - implicitWidth / 2
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 {
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 { MouseArea {
id: mouse acceptedButtons: Qt.NoButton
anchors.fill: parent
property real dragMovement cursorShape: Qt.PointingHandCursor
property real pressStartPos
property real pressStartX
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
implicitHeight: handle.implicitHeight
preventStealing: true
onPositionChanged: e => {
dragMovement = (e.x - pressStartX) / width;
root.interaction(posBinding.value);
}
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()
} }
+64 -35
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 {
+36 -96
View File
@@ -2,107 +2,49 @@ 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 {
TransformWatcher {
id: watcher
a: root.parent
b: root.attachTo
}
Elevation {
id: menu
implicitHeight: column.implicitHeight + column.anchors.margins * 2
implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2)
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 {
origin.y: root.thisSideY === Menu.Bottom ? menu.height : 0
yScale: root.expanded ? 1 : 0.1
Behavior on yScale {
Anim {
}
}
}
CustomRect {
anchors.fill: parent anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainerLow color: DynamicColors.palette.m3surfaceContainer
radius: parent.radius radius: parent.radius
ColumnLayout { ColumnLayout {
id: column id: column
anchors.fill: parent anchors.left: parent.left
anchors.margins: Appearance.padding.extraSmall anchors.right: parent.right
spacing: Appearance.spacing.extraSmall anchors.verticalCenter: parent.verticalCenter
spacing: 5
Repeater { Repeater {
id: repeater
model: root.items model: root.items
CustomRect { CustomRect {
@@ -113,56 +55,55 @@ MouseArea {
required property MenuItem modelData required property MenuItem modelData
Layout.fillWidth: true Layout.fillWidth: true
color: Qt.alpha(DynamicColors.palette.m3tertiaryContainer, active ? 1 : 0) implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.normal * 2
implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.larger * 2 implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.normal * 2
implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.larger * 2
radius: Appearance.rounding.small
Behavior on radius { CustomRect {
Anim { anchors.fill: parent
} anchors.leftMargin: Appearance.padding.small
} anchors.rightMargin: Appearance.padding.small
color: Qt.alpha(DynamicColors.palette.m3secondaryContainer, active ? 1 : 0)
radius: Appearance.rounding.normal - Appearance.padding.small
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 { RowLayout {
id: menuOptionRow id: menuOptionRow
anchors.fill: parent anchors.fill: parent
anchors.margins: Appearance.padding.larger anchors.margins: Appearance.padding.normal
spacing: Appearance.spacing.small spacing: Appearance.spacing.small
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurfaceVariant
text: item.modelData.icon text: item.modelData.icon
} }
CustomText { CustomText {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true Layout.fillWidth: true
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurface color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.text text: item.modelData.text
} }
Loader { Loader {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
active: item.modelData.trailingIcon.length > 0 active: item.modelData.trailingIcon.length > 0
asynchronous: true
visible: active visible: active
sourceComponent: MaterialIcon { sourceComponent: MaterialIcon {
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.trailingIcon text: item.modelData.trailingIcon
} }
} }
@@ -172,4 +113,3 @@ MouseArea {
} }
} }
} }
}
+64 -169
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 {
Anim {
type: Anim.DefaultEffects
}
}
onCircleRadiusChanged: {
if (!(pressed || manualPressOverride) && circleRadius > endRadiusAtPress * 0.99 && !fadeAnim.running)
fadeAnim.start();
}
onClicked: event => !disabled && onClicked(event) onClicked: event => !disabled && onClicked(event)
onManualPressOverrideChanged: { onPressed: event => {
if (!(pressed || manualPressOverride) && circleRadius > endRadiusAtPress * 0.99 && !fadeAnim.running) if (disabled)
fadeAnim.start(); return;
}
onPressed: e => press(e.x, e.y) rippleAnim.x = event.x;
onPressedChanged: { rippleAnim.y = event.y;
if (!(pressed || manualPressOverride) && !rippleAnim.running && circle.opacity > 0)
fadeAnim.start(); 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();
} }
Anim { SequentialAnimation {
id: rippleAnim id: rippleAnim
alwaysRunToEnd: true property real radius
duration: Appearance.anim.durations.expressiveSlowEffects * 2 property real x
easing.bezierCurve: Appearance.anim.curves.standard property real y
property: "circleRadius"
target: root PropertyAction {
to: root.endRadius 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 {
id: fadeAnim easing.bezierCurve: MaterialEasing.standardDecel
from: 0
property: "opacity" properties: "implicitWidth,implicitHeight"
target: circle target: ripple
to: 0 to: rippleAnim.radius * 2
type: Anim.SlowEffects
} }
Anim {
property: "opacity"
target: ripple
to: 0
}
}
CustomClippingRect {
id: hoverLayer
anchors.fill: parent
border.pixelAligned: false
color: Qt.alpha(root.color, root.disabled ? 0 : root.pressed ? 0.1 : root.containsMouse ? 0.08 : 0)
radius: root.radius
CustomRect { CustomRect {
id: base id: ripple
anchors.fill: parent border.pixelAligned: false
bottomLeftRadius: root.parent?.bottomLeftRadius ?? radius ?? 0 color: root.color
bottomRightRadius: root.parent?.bottomRightRadius ?? radius ?? 0
color: DynamicColors.palette.m3onSurface
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 {
id: circle
anchors.fill: parent
opacity: 0 opacity: 0
preferredRendererType: Shape.CurveRenderer 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
+29 -12
View File
@@ -9,17 +9,29 @@ 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
Scope {
id: scope
required property var modelData
Exclusions {
bar: bar
screen: scope.modelData
}
CustomWindow {
id: win
readonly property alias bar: bar
readonly property bool hasFullscreen: Hypr.monitorFor(screen)?.activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen === 2) readonly property bool hasFullscreen: Hypr.monitorFor(screen)?.activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen === 2)
readonly property alias interactionWrapper: interactions
property var root: Quickshell.shellDir property var root: Quickshell.shellDir
WlrLayershell.exclusionMode: ExclusionMode.Ignore WlrLayershell.exclusionMode: ExclusionMode.Ignore
@@ -28,6 +40,7 @@ CustomWindow {
contentItem.focus: true contentItem.focus: true
mask: visibilities.isDrawing ? null : region mask: visibilities.isDrawing ? null : region
name: "Bar" name: "Bar"
screen: scope.modelData
contentItem.Keys.onEscapePressed: { contentItem.Keys.onEscapePressed: {
if (Config.barConfig.autoHide) if (Config.barConfig.autoHide)
@@ -49,10 +62,10 @@ CustomWindow {
Region { Region {
id: region id: region
height: root.height - bar.implicitHeight - Config.barConfig.border height: win.height - bar.implicitHeight - Config.barConfig.border
intersection: Intersection.Xor intersection: Intersection.Xor
regions: popoutRegions.instances regions: popoutRegions.instances
width: root.width - Config.barConfig.border * 2 width: win.width - Config.barConfig.border * 2
x: Config.barConfig.border x: Config.barConfig.border
y: bar.implicitHeight y: bar.implicitHeight
} }
@@ -84,7 +97,7 @@ CustomWindow {
id: focusGrab id: focusGrab
active: visibilities.dock || visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu")) active: visibilities.dock || visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu"))
windows: [root] windows: [win]
onCleared: { onCleared: {
visibilities.launcher = false; visibilities.launcher = false;
@@ -112,7 +125,7 @@ CustomWindow {
property bool settings property bool settings
property bool sidebar property bool sidebar
Component.onCompleted: Visibilities.load(root.screen, this) Component.onCompleted: Visibilities.load(scope.modelData, this)
} }
IpcHandler { IpcHandler {
@@ -297,6 +310,7 @@ CustomWindow {
active: visibilities.isDrawing active: visibilities.isDrawing
anchors.fill: parent anchors.fill: parent
z: 2
sourceComponent: Drawing { sourceComponent: Drawing {
id: drawing id: drawing
@@ -322,7 +336,7 @@ CustomWindow {
} }
Interactions { Interactions {
id: interactions id: mouseArea
anchors.fill: parent anchors.fill: parent
bar: bar bar: bar
@@ -331,15 +345,16 @@ CustomWindow {
input: inputLoader.item input: inputLoader.item
panels: panels panels: panels
popouts: panels.popouts popouts: panels.popouts
screen: root.screen screen: scope.modelData
visibilities: visibilities visibilities: visibilities
z: 1
Panels { Panels {
id: panels id: panels
bar: bar bar: bar
drawingItem: drawingLoader.item drawingItem: drawingLoader.item
screen: root.screen screen: scope.modelData
visibilities: visibilities visibilities: visibilities
dashboard.transform: Matrix4x4 { dashboard.transform: Matrix4x4 {
@@ -381,10 +396,12 @@ CustomWindow {
anchors.right: parent.right anchors.right: parent.right
popouts: panels.popouts popouts: panels.popouts
popoutsWrapper: panels.popoutsWrapper popoutsWrapper: panels.popoutsWrapper
screen: root.screen screen: scope.modelData
visibilities: visibilities visibilities: visibilities
} }
} }
}
}
component PanelBg: BlobRect { component PanelBg: BlobRect {
property real deformAmount: 0.15 property real deformAmount: 0.15
+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 {
+26 -155
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 {
id: lineComp
CustomRect { CustomRect {
bottomRightRadius: Appearance.rounding.extraSmall / 2 anchors.bottom: parent.bottom
color: root.fgColor anchors.right: parent.right
implicitHeight: root.height anchors.top: parent.top
implicitWidth: root.filledWidth bottomLeftRadius: root.implicitHeight / 6
radius: Appearance.rounding.small color: DynamicColors.tPalette.m3surfaceContainer
topRightRadius: Appearance.rounding.extraSmall / 2 implicitWidth: parent.width - root.handle.x - root.handle.implicitWidth - root.implicitHeight / 2
radius: Appearance.rounding.full
topLeftRadius: root.implicitHeight / 6
} }
} }
handle: CustomRect {
Component { anchors.verticalCenter: parent.verticalCenter
id: waveComp color: DynamicColors.palette.m3primary
implicitHeight: 15
WavyLine { implicitWidth: 5
color: root.fgColor radius: Appearance.rounding.full
frequency: root.waveFrequency x: root.visualPosition * root.availableWidth - implicitWidth / 2
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 {
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 { MouseArea {
id: mouse acceptedButtons: Qt.NoButton
anchors.fill: parent
property real dragMovement cursorShape: Qt.PointingHandCursor
property real pressStartPos
property real pressStartX
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
implicitHeight: handle.implicitHeight
preventStealing: true
onPositionChanged: e => {
dragMovement = (e.x - pressStartX) / width;
root.interaction(posBinding.value);
}
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"
} }
} }
+67 -34
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
} }
+36 -96
View File
@@ -2,107 +2,49 @@ 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 {
TransformWatcher {
id: watcher
a: root.parent
b: root.attachTo
}
Elevation {
id: menu
implicitHeight: column.implicitHeight + column.anchors.margins * 2
implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2)
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 {
origin.y: root.thisSideY === Menu.Bottom ? menu.height : 0
yScale: root.expanded ? 1 : 0.1
Behavior on yScale {
Anim {
}
}
}
CustomRect {
anchors.fill: parent anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainerLow color: DynamicColors.palette.m3surfaceContainer
radius: parent.radius radius: parent.radius
ColumnLayout { ColumnLayout {
id: column id: column
anchors.fill: parent anchors.left: parent.left
anchors.margins: Appearance.padding.extraSmall anchors.right: parent.right
spacing: Appearance.spacing.extraSmall anchors.verticalCenter: parent.verticalCenter
spacing: 5
Repeater { Repeater {
id: repeater
model: root.items model: root.items
CustomRect { CustomRect {
@@ -113,56 +55,55 @@ MouseArea {
required property MenuItem modelData required property MenuItem modelData
Layout.fillWidth: true Layout.fillWidth: true
color: Qt.alpha(DynamicColors.palette.m3tertiaryContainer, active ? 1 : 0) implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.normal * 2
implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.larger * 2 implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.normal * 2
implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.larger * 2
radius: Appearance.rounding.small
Behavior on radius { CustomRect {
Anim { anchors.fill: parent
} anchors.leftMargin: Appearance.padding.small
} anchors.rightMargin: Appearance.padding.small
color: Qt.alpha(DynamicColors.palette.m3secondaryContainer, active ? 1 : 0)
radius: Appearance.rounding.normal - Appearance.padding.small
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 { RowLayout {
id: menuOptionRow id: menuOptionRow
anchors.fill: parent anchors.fill: parent
anchors.margins: Appearance.padding.larger anchors.margins: Appearance.padding.normal
spacing: Appearance.spacing.small spacing: Appearance.spacing.small
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurfaceVariant
text: item.modelData.icon text: item.modelData.icon
} }
CustomText { CustomText {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true Layout.fillWidth: true
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurface color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.text text: item.modelData.text
} }
Loader { Loader {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
active: item.modelData.trailingIcon.length > 0 active: item.modelData.trailingIcon.length > 0
asynchronous: true
visible: active visible: active
sourceComponent: MaterialIcon { sourceComponent: MaterialIcon {
color: item.active ? DynamicColors.palette.m3onTertiaryContainer : DynamicColors.palette.m3onSurfaceVariant color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.trailingIcon text: item.modelData.trailingIcon
} }
} }
@@ -172,4 +113,3 @@ MouseArea {
} }
} }
} }
}
-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 {
+64 -169
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 {
Anim {
type: Anim.DefaultEffects
}
}
onCircleRadiusChanged: {
if (!(pressed || manualPressOverride) && circleRadius > endRadiusAtPress * 0.99 && !fadeAnim.running)
fadeAnim.start();
}
onClicked: event => !disabled && onClicked(event) onClicked: event => !disabled && onClicked(event)
onManualPressOverrideChanged: { onPressed: event => {
if (!(pressed || manualPressOverride) && circleRadius > endRadiusAtPress * 0.99 && !fadeAnim.running) if (disabled)
fadeAnim.start(); return;
}
onPressed: e => press(e.x, e.y) rippleAnim.x = event.x;
onPressedChanged: { rippleAnim.y = event.y;
if (!(pressed || manualPressOverride) && !rippleAnim.running && circle.opacity > 0)
fadeAnim.start(); 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();
} }
Anim { SequentialAnimation {
id: rippleAnim id: rippleAnim
alwaysRunToEnd: true property real radius
duration: Appearance.anim.durations.expressiveSlowEffects * 2 property real x
easing.bezierCurve: Appearance.anim.curves.standard property real y
property: "circleRadius"
target: root PropertyAction {
to: root.endRadius 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 {
id: fadeAnim easing.bezierCurve: MaterialEasing.standardDecel
from: 0
property: "opacity" properties: "implicitWidth,implicitHeight"
target: circle target: ripple
to: 0 to: rippleAnim.radius * 2
type: Anim.SlowEffects
} }
Anim {
property: "opacity"
target: ripple
to: 0
}
}
CustomClippingRect {
id: hoverLayer
anchors.fill: parent
border.pixelAligned: false
color: Qt.alpha(root.color, root.disabled ? 0 : root.pressed ? 0.1 : root.containsMouse ? 0.08 : 0)
radius: root.radius
CustomRect { CustomRect {
id: base id: ripple
anchors.fill: parent border.pixelAligned: false
bottomLeftRadius: root.parent?.bottomLeftRadius ?? radius ?? 0 color: root.color
bottomRightRadius: root.parent?.bottomRightRadius ?? radius ?? 0
color: DynamicColors.palette.m3onSurface
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 {
id: circle
anchors.fill: parent
opacity: 0 opacity: 0
preferredRendererType: Shape.CurveRenderer 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 -158
View File
@@ -1,7 +1,6 @@
import Quickshell import Quickshell
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Controls
import qs.Modules.Settings.Controls import qs.Modules.Settings.Controls
import qs.Config import qs.Config
import qs.Components import qs.Components
@@ -63,7 +62,6 @@ SettingsPage {
SettingsSection { SettingsSection {
sectionId: "Color" sectionId: "Color"
z: 1
SettingsHeader { SettingsHeader {
name: "Color" name: "Color"
@@ -107,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 {
@@ -239,162 +238,6 @@ SettingsPage {
shouldBeActive: Config.general.color.schemeGeneration ? 1 : 0 shouldBeActive: Config.general.color.schemeGeneration ? 1 : 0
} }
// Item {
// id: timeInput
//
// readonly property bool highlighted: SettingsHighlight.highlightedSetting === name
// property string name
// property var object
// property list<string> settings
// property bool shouldBeActive: true
//
// function commitChoice(choice: int, setting: string): void {
// timeInput.object[setting] = choice;
// Config.save();
// }
//
// function formattedValue(setting: string): string {
// const value = timeInput.object[setting];
//
// if (value === null || value === undefined)
// return "";
//
// return String(value);
// }
//
// function hourToAmPm(hour) {
// var h = Number(hour) % 24;
// var d = new Date(2000, 0, 1, h, 0, 0);
// return Qt.formatTime(d, "h AP");
// }
//
// anchors.left: parent.left
// anchors.right: parent.right
// implicitHeight: shouldBeActive ? row.implicitHeight + Appearance.padding.smaller * 2 : 0
// opacity: shouldBeActive ? 1 : 0
// scale: shouldBeActive ? 1 : 0.8
// visible: opacity > 0
//
// Behavior on opacity {
// Anim {
// }
// }
// Behavior on scale {
// Anim {
// }
// }
// Behavior on y {
// Anim {
// }
// }
//
// Rectangle {
// anchors.fill: parent
// anchors.margins: -Appearance.padding.smaller
// color: DynamicColors.palette.m3primaryContainer
// opacity: timeInput.highlighted ? 0.5 : 0
// radius: Appearance.rounding.small
//
// Behavior on opacity {
// Anim {
// duration: Appearance.anim.durations.normal
// }
// }
// }
//
// RowLayout {
// id: row
//
// anchors.left: parent.left
// anchors.margins: Appearance.padding.small
// anchors.right: parent.right
// anchors.verticalCenter: parent.verticalCenter
//
// ColumnLayout {
// Layout.fillHeight: true
// Layout.fillWidth: true
//
// CustomText {
// id: text
//
// Layout.alignment: Qt.AlignLeft
// Layout.fillWidth: true
// font.pointSize: Appearance.font.size.larger
// text: timeInput.name
// }
//
// CustomText {
// Layout.alignment: Qt.AlignLeft
// color: DynamicColors.palette.m3onSurfaceVariant
// font.pointSize: Appearance.font.size.normal
// text: qsTr("Dark mode will turn on at %1, and turn off at %2.").arg(timeInput.hourToAmPm(timeInput.object[timeInput.settings[0]])).arg(timeInput.hourToAmPm(timeInput.object[timeInput.settings[1]]))
// }
// }
//
// ColumnLayout {
// id: optionLayout
//
// Layout.fillHeight: true
// Layout.preferredWidth: 100
//
// RowLayout {
// Layout.preferredWidth: optionLayout.width
//
// CustomText {
// Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
// Layout.fillWidth: true
// text: qsTr("Enabled: ")
// }
//
// CustomSwitch {
// id: enabledSwitch
//
// Layout.alignment: Qt.AlignRight | Qt.AlignHCenter
// checked: timeInput.object[timeInput.settings[2]]
//
// onToggled: {
// timeInput.object[timeInput.settings[2]] = checked;
// Config.save();
// }
// }
// }
//
// RowLayout {
// Layout.preferredWidth: optionLayout.width
//
// CustomText {
// Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter
// Layout.fillWidth: true
// text: qsTr("Start: ")
// }
//
// CustomRect {
// Layout.preferredHeight: 72
// Layout.preferredWidth: 96
// color: startHourField.focus ? DynamicColors.palette.m3primaryContainer : DynamicColors.palette.m3surfaceContainer
//
// CustomTextField {
// id: startHourField
//
// function convertHour(timeValue: int): int {
// return Math.floor(timeValue / 60);
// }
//
// function convertMinute(timeValue: int): int {
// return timeValue % 60;
// }
//
// anchors.fill: parent
// font.family: "Roboto"
// font.pixelSize: 57
// text: convertHour(Config.general.color.scheduleDarkStart)
// }
// }
// }
// }
// }
// }
Separator { Separator {
} }
@@ -407,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 {
+151 -89
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: 500 + Appearance.padding.small * 2 implicitWidth: 400 + Appearance.padding.small * 2
CustomRect { CustomRect {
anchors.left: parent.left anchors.left: parent.left
@@ -52,16 +52,56 @@ 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
Item {
id: sinkIcon
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.normal
anchors.top: parent.top
implicitWidth: childrenRect.width
CustomRect {
anchors.centerIn: parent
color: Audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: 40
implicitWidth: 40
radius: Appearance.rounding.full
MaterialIcon {
anchors.alignWhenCentered: false
anchors.centerIn: parent
animate: true
color: Audio.muted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
font.pointSize: 22
text: Audio.muted ? "volume_off" : "volume_up"
}
StateLayer {
color: Audio.muted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
onClicked: {
const audio = Audio.sink?.audio;
if (audio)
audio.muted = !audio.muted;
}
}
}
}
ColumnLayout { ColumnLayout {
anchors.bottomMargin: Appearance.padding.smaller anchors.bottom: parent.bottom
anchors.fill: parent anchors.bottomMargin: Appearance.padding.smallest
anchors.leftMargin: Appearance.padding.larger anchors.left: sinkIcon.right
anchors.rightMargin: Appearance.padding.larger anchors.leftMargin: Appearance.spacing.normal
anchors.right: parent.right
anchors.rightMargin: Appearance.padding.large
anchors.top: parent.top
anchors.topMargin: Appearance.padding.smaller anchors.topMargin: Appearance.padding.smaller
RowLayout { RowLayout {
@@ -71,33 +111,26 @@ Item {
CustomText { CustomText {
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.fillWidth: true Layout.fillWidth: true
text: "Output volume" text: "Output Volume"
} }
CustomText { CustomText {
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
color: Qt.alpha(DynamicColors.palette.m3onSurface, 0.7)
font.bold: true font.bold: true
text: qsTr("%1").arg(Audio.muted ? qsTr("Muted") : `${Math.round(Audio.volume * 100)}%`) text: qsTr("%1").arg(Audio.muted ? qsTr("Muted") : `${Math.round(Audio.volume * 100)}%`)
} }
} }
RowLayout {
spacing: Appearance.spacing.large
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
bgColor: Audio.muted ? Qt.alpha(DynamicColors.palette.m3errorContainer, 0.5) : DynamicColors.palette.m3secondaryContainer color: Audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
fgColor: Audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: parent.height implicitHeight: parent.height
insetColor: Audio.muted ? (inset.attached ? DynamicColors.palette.m3onErrorContainer : DynamicColors.palette.m3onError) : (inset.attached ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onPrimary)
insetIcon: Audio.muted || Audio.volume < 0.001 ? "volume_off" : "volume_up"
value: Audio.volume value: Audio.volume
Behavior on value { Behavior on value {
@@ -105,19 +138,7 @@ Item {
} }
} }
onInteraction: value => Audio.setVolume(value) onMoved: Audio.setVolume(value)
}
}
CustomSwitch {
Layout.bottomMargin: Appearance.padding.normal
checked: !Audio.muted
onToggled: {
const audio = Audio.sink?.audio;
if (audio)
audio.muted = !audio.muted;
}
} }
} }
} }
@@ -125,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
@@ -152,11 +173,51 @@ Item {
} }
} }
Item {
id: sourceIcon
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.normal
anchors.top: parent.top
implicitWidth: childrenRect.width
CustomRect {
anchors.centerIn: parent
color: Audio.sourceMuted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: 40
implicitWidth: 40
radius: Appearance.rounding.full
MaterialIcon {
anchors.alignWhenCentered: false
anchors.centerIn: parent
animate: true
color: Audio.sourceMuted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
font.pointSize: 22
text: Audio.sourceMuted ? "mic_off" : "mic"
}
StateLayer {
color: Audio.sourceMuted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
onClicked: {
const audio = Audio.source?.audio;
if (audio)
audio.muted = !audio.muted;
}
}
}
}
ColumnLayout { ColumnLayout {
anchors.bottomMargin: Appearance.padding.smaller anchors.bottom: parent.bottom
anchors.fill: parent anchors.bottomMargin: Appearance.padding.smallest
anchors.leftMargin: Appearance.padding.larger anchors.left: sourceIcon.right
anchors.rightMargin: Appearance.padding.larger anchors.leftMargin: Appearance.spacing.normal
anchors.right: parent.right
anchors.rightMargin: Appearance.padding.large
anchors.top: parent.top
anchors.topMargin: Appearance.padding.smaller anchors.topMargin: Appearance.padding.smaller
RowLayout { RowLayout {
@@ -166,33 +227,26 @@ Item {
CustomText { CustomText {
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.fillWidth: true Layout.fillWidth: true
text: "Input volume" text: "Input Volume"
} }
CustomText { CustomText {
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
color: Qt.alpha(DynamicColors.palette.m3onSurface, 0.7)
font.bold: true font.bold: true
text: qsTr("%1").arg(Audio.sourceMuted ? qsTr("Muted") : `${Math.round(Audio.sourceVolume * 100)}%`) text: qsTr("%1").arg(Audio.sourceMuted ? qsTr("Muted") : `${Math.round(Audio.sourceVolume * 100)}%`)
} }
} }
RowLayout {
spacing: Appearance.spacing.large
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
bgColor: Audio.sourceMuted ? Qt.alpha(DynamicColors.palette.m3errorContainer, 0.5) : DynamicColors.palette.m3secondaryContainer color: Audio.sourceMuted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
fgColor: Audio.sourceMuted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: parent.height implicitHeight: parent.height
insetColor: Audio.sourceMuted ? (inset.attached ? DynamicColors.palette.m3onErrorContainer : DynamicColors.palette.m3onError) : (inset.attached ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onPrimary)
insetIcon: Audio.sourceMuted || Audio.sourceVolume < 0.001 ? "mic_off" : "mic"
value: Audio.sourceVolume value: Audio.sourceVolume
Behavior on value { Behavior on value {
@@ -200,19 +254,7 @@ Item {
} }
} }
onInteraction: value => Audio.setSourceVolume(value) onMoved: Audio.setSourceVolume(value)
}
}
CustomSwitch {
Layout.bottomMargin: Appearance.padding.normal
checked: !Audio.sourceMuted
onToggled: {
const audio = Audio.source?.audio;
if (audio)
audio.muted = !audio.muted;
}
} }
} }
} }
@@ -238,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
@@ -265,6 +307,43 @@ Item {
} }
} }
Item {
id: appBoxIcon
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.normal
anchors.top: parent.top
implicitWidth: childrenRect.width
CustomRect {
anchors.centerIn: parent
color: appBox.modelData.audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: 40
implicitWidth: 40
radius: Appearance.rounding.full
MaterialIcon {
id: icon
anchors.centerIn: parent
animate: true
color: appBox.modelData.audio.muted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
font.pointSize: 22
text: appBox.modelData.audio.muted ? "volume_off" : "volume_up"
}
StateLayer {
color: appBox.modelData.audio.muted ? DynamicColors.palette.m3onError : DynamicColors.palette.m3onPrimary
radius: Appearance.rounding.full
onClicked: {
appBox.modelData.audio.muted = !appBox.modelData.audio.muted;
}
}
}
}
TextMetrics { TextMetrics {
id: metrics id: metrics
@@ -274,10 +353,13 @@ Item {
} }
ColumnLayout { ColumnLayout {
anchors.bottomMargin: Appearance.padding.smaller anchors.bottom: parent.bottom
anchors.fill: parent anchors.bottomMargin: Appearance.padding.smallest
anchors.leftMargin: Appearance.padding.larger anchors.left: appBoxIcon.right
anchors.rightMargin: Appearance.padding.larger anchors.leftMargin: Appearance.spacing.normal
anchors.right: parent.right
anchors.rightMargin: Appearance.padding.large
anchors.top: parent.top
anchors.topMargin: Appearance.padding.smaller anchors.topMargin: Appearance.padding.smaller
RowLayout { RowLayout {
@@ -293,45 +375,25 @@ Item {
CustomText { CustomText {
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
color: Qt.alpha(DynamicColors.palette.m3onSurface, 0.7)
font.bold: true font.bold: true
text: qsTr("%1").arg(appBox.modelData.audio.muted ? qsTr("Muted") : `${Math.round(appBox.modelData.audio.volume * 100)}%`) text: qsTr("%1").arg(appBox.modelData.audio.muted ? qsTr("Muted") : `${Math.round(appBox.modelData.audio.volume * 100)}%`)
} }
} }
RowLayout {
spacing: Appearance.spacing.large
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
bgColor: appBox.modelData.audio.muted ? Qt.alpha(DynamicColors.palette.m3errorContainer, 0.5) : DynamicColors.palette.m3secondaryContainer color: appBox.modelData.audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
fgColor: appBox.modelData.audio.muted ? DynamicColors.palette.m3error : DynamicColors.palette.m3primary
implicitHeight: parent.height implicitHeight: parent.height
insetColor: appBox.modelData.audio.muted ? (inset.attached ? DynamicColors.palette.m3onErrorContainer : DynamicColors.palette.m3onError) : (inset.attached ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onPrimary)
insetIcon: appBox.modelData.audio.muted || appBox.modelData.audio.volume < 0.001 ? "volume_off" : "volume_up"
value: appBox.modelData.audio.volume value: appBox.modelData.audio.volume
Behavior on value { onMoved: {
Anim { Audio.setStreamVolume(appBox.modelData, value);
}
}
onInteraction: value => Audio.setStreamVolume(appBox.modelData, value)
}
}
CustomSwitch {
Layout.bottomMargin: Appearance.padding.normal
checked: !appBox.modelData.audio.muted
onToggled: {
appBox.modelData.audio.muted = !appBox.modelData.audio.muted;
} }
} }
} }
+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 {