27 Commits
Author SHA1 Message Date
Inorishio 6071223009 Merge branch 'main' into module/wifi
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 15s
JS/TS / lint (pull_request) Successful in 19s
Python / static (pull_request) Successful in 57s
Rust / fmt (pull_request) Successful in 1m9s
Rust / build (pull_request) Successful in 2m11s
C++ / build (pull_request) Successful in 2m34s
Rust / clippy (pull_request) Successful in 1m30s
Python / verify (pull_request) Successful in 2m55s
C++ / clang-tidy (pull_request) Successful in 3m59s
2026-08-16 22:57:54 +02:00
Inorishio 2d40ce33d1 Merge branch 'main' into module/wifi
C++ / fmt (pull_request) Successful in 5s
JS/TS / fmt (pull_request) Successful in 17s
JS/TS / lint (pull_request) Successful in 16s
Python / fmt (pull_request) Successful in 31s
Python / lint (pull_request) Successful in 41s
Python / test (pull_request) Successful in 1m5s
Python / typecheck (pull_request) Successful in 1m15s
Rust / clippy (pull_request) Failing after 12m43s
Rust / fmt (pull_request) Failing after 12m57s
Rust / build (pull_request) Failing after 13m33s
Python / buildcheck (pull_request) Failing after 13m45s
C++ / clang-tidy (pull_request) Failing after 14m23s
C++ / build (pull_request) Failing after 14m25s
2026-08-15 20:38:54 +02:00
zach 954dc10fbb bluetooth model delegate animations
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 19s
JS/TS / lint (pull_request) Successful in 21s
Python / fmt (pull_request) Successful in 35s
Python / lint (pull_request) Successful in 36s
Python / test (pull_request) Successful in 1m3s
Python / typecheck (pull_request) Failing after 1m4s
C++ / build (pull_request) Successful in 1m52s
Rust / build (pull_request) Successful in 1m41s
Rust / fmt (pull_request) Successful in 1m6s
Python / buildcheck (pull_request) Successful in 2m28s
Rust / clippy (pull_request) Successful in 1m55s
C++ / clang-tidy (pull_request) Successful in 3m36s
2026-07-11 14:00:08 +02:00
zach 15ccfd24c6 Merge branch 'main' into module/wifi
C++ / fmt (pull_request) Successful in 3s
JS/TS / fmt (pull_request) Successful in 15s
JS/TS / lint (pull_request) Successful in 16s
Python / fmt (pull_request) Successful in 32s
Python / lint (pull_request) Successful in 32s
Python / test (pull_request) Successful in 1m3s
Python / typecheck (pull_request) Failing after 1m3s
C++ / build (pull_request) Successful in 1m41s
Rust / build (pull_request) Successful in 1m42s
Rust / fmt (pull_request) Successful in 1m17s
Python / buildcheck (pull_request) Successful in 2m43s
Rust / clippy (pull_request) Successful in 2m7s
C++ / clang-tidy (pull_request) Successful in 3m43s
2026-07-10 18:20:25 +02:00
zach 33b08523e9 add preliminary bluetooth widget + popout
C++ / fmt (pull_request) Successful in 3s
JS/TS / fmt (pull_request) Successful in 15s
JS/TS / lint (pull_request) Successful in 17s
Python / fmt (pull_request) Successful in 35s
Python / lint (pull_request) Successful in 34s
Python / test (pull_request) Successful in 1m0s
C++ / build (pull_request) Successful in 1m46s
Rust / fmt (pull_request) Successful in 1m19s
Rust / build (pull_request) Successful in 1m54s
Python / buildcheck (pull_request) Successful in 2m42s
Rust / clippy (pull_request) Successful in 1m54s
C++ / clang-tidy (pull_request) Successful in 3m42s
2026-07-10 16:17:47 +02:00
zach 742bece30b Merge branch 'main' into module/wifi
C++ / fmt (pull_request) Successful in 7s
JS/TS / fmt (pull_request) Successful in 14s
JS/TS / lint (pull_request) Successful in 20s
Python / fmt (pull_request) Successful in 28s
Python / lint (pull_request) Successful in 29s
Python / test (pull_request) Successful in 59s
Rust / fmt (pull_request) Successful in 57s
C++ / build (pull_request) Successful in 3m47s
Rust / build (pull_request) Successful in 2m10s
Python / buildcheck (pull_request) Successful in 2m51s
Rust / clippy (pull_request) Successful in 1m32s
C++ / clang-tidy (pull_request) Successful in 5m9s
2026-07-10 15:23:23 +02:00
zach a64eadd14a feat: add password overlay for network popout + redesign
C++ / fmt (pull_request) Successful in 4s
JS/TS / fmt (pull_request) Successful in 11s
JS/TS / lint (pull_request) Successful in 24s
Python / fmt (pull_request) Successful in 30s
Python / lint (pull_request) Successful in 34s
Python / test (pull_request) Successful in 53s
C++ / build (pull_request) Successful in 1m52s
Rust / fmt (pull_request) Successful in 1m14s
Rust / build (pull_request) Successful in 1m57s
Rust / clippy (pull_request) Successful in 2m0s
Python / buildcheck (pull_request) Successful in 2m37s
C++ / clang-tidy (pull_request) Successful in 3m43s
2026-07-09 17:33:13 +02:00
zach f9eeb793db Merge branch 'main' into module/wifi
C++ / fmt (pull_request) Successful in 5s
JS/TS / fmt (pull_request) Successful in 18s
JS/TS / lint (pull_request) Successful in 19s
Python / fmt (pull_request) Successful in 32s
Python / lint (pull_request) Successful in 36s
Python / test (pull_request) Successful in 55s
C++ / build (pull_request) Successful in 1m55s
Rust / fmt (pull_request) Successful in 1m15s
Rust / build (pull_request) Successful in 1m59s
Python / buildcheck (pull_request) Successful in 2m45s
Rust / clippy (pull_request) Successful in 1m55s
C++ / clang-tidy (pull_request) Successful in 3m41s
2026-07-09 14:22:34 +02:00
zach 6bb193c78c Merge branch 'main' into module/wifi
C++ / fmt (pull_request) Successful in 5s
JS/TS / fmt (pull_request) Successful in 19s
JS/TS / lint (pull_request) Successful in 22s
Python / lint (pull_request) Successful in 33s
Python / fmt (pull_request) Successful in 36s
Python / test (pull_request) Successful in 1m5s
C++ / build (pull_request) Successful in 1m42s
Rust / fmt (pull_request) Successful in 1m11s
Rust / build (pull_request) Successful in 1m56s
Python / buildcheck (pull_request) Successful in 2m40s
Rust / clippy (pull_request) Successful in 1m48s
C++ / clang-tidy (pull_request) Successful in 3m42s
2026-07-08 22:56:46 +02:00
Inorishio aadecbfe44 Chore: created Spacer component, moved x available networks, added connected networks
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 17s
Python / test (pull_request) Successful in 59s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m31s
C++ / build (pull_request) Successful in 2m37s
2026-07-08 22:22:03 +02:00
zach 53f0aa80ae Merge branch 'main' into module/wifi
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 30s
Python / test (pull_request) Successful in 42s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m36s
C++ / build (pull_request) Successful in 2m20s
2026-07-08 13:41:27 +02:00
Inorishio d9856c9409 Chore: created NetworkItem component, renamed network header to Wifi
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 14s
Python / test (pull_request) Successful in 46s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m51s
C++ / build (pull_request) Successful in 2m36s
2026-07-02 22:46:09 +02:00
zach 8dc9753e2b feat: don't add the same network twice
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 30s
Python / lint-format (pull_request) Successful in 48s
Python / test (pull_request) Successful in 40s
C++ / build (pull_request) Successful in 2m8s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m13s
2026-07-02 22:09:25 +02:00
zach 2a4bd3dfdd chore: remove old code
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 17s
Python / lint-format (pull_request) Successful in 31s
Python / test (pull_request) Successful in 39s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m31s
C++ / build (pull_request) Successful in 2m17s
2026-07-02 21:58:01 +02:00
zach f75f51ef50 fix: sort is now correct
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 18s
Python / lint-format (pull_request) Successful in 21s
Python / test (pull_request) Successful in 48s
C++ / build (pull_request) Successful in 2m59s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m12s
2026-07-02 21:54:58 +02:00
zach e0873304d1 add sorting by strength
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 15s
Python / lint-format (pull_request) Successful in 32s
Python / test (pull_request) Successful in 39s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m45s
C++ / build (pull_request) Successful in 2m47s
2026-07-02 21:53:42 +02:00
zach 99a0155c17 Merge branch 'main' into module/wifi
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 14s
Python / test (pull_request) Successful in 46s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m30s
C++ / build (pull_request) Successful in 2m32s
2026-07-02 21:46:15 +02:00
zach f309debea5 set scannerEnabled when popout is visible + remove scan button
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 18s
Python / lint-format (pull_request) Successful in 20s
Python / test (pull_request) Successful in 47s
C++ / build (pull_request) Successful in 3m9s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m15s
2026-07-02 16:06:52 +02:00
zach 0979fd014d Merge branch 'main' into module/wifi
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 16s
Python / lint-format (pull_request) Successful in 32s
Python / test (pull_request) Successful in 38s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m49s
C++ / build (pull_request) Successful in 3m5s
2026-07-02 15:16:22 +02:00
zach 656bd0a54d Merge branch 'main' into module/wifi
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 11s
Python / lint-format (pull_request) Successful in 16s
Python / test (pull_request) Successful in 46s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m37s
C++ / build (pull_request) Successful in 2m22s
2026-06-30 22:42:51 +02:00
zach f01001dcfa merge main into module/wifi
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 9s
Python / lint-format (pull_request) Successful in 16s
Python / test (pull_request) Successful in 49s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m42s
C++ / build (pull_request) Successful in 2m28s
2026-06-30 18:15:43 +02:00
zach bc6b0d50ab Merge branch 'main' into module/wifi
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 34s
Python / lint-format (pull_request) Successful in 35s
Python / test (pull_request) Successful in 1m11s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m58s
C++ / build (pull_request) Successful in 4m31s
2026-06-29 22:10:45 +02:00
zach f27c9afc25 more methods for wifi and scanning + layout
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 15s
Python / test (pull_request) Successful in 29s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m6s
2026-06-26 15:15:03 +02:00
Inorishio 5962fc8354 Merge branch 'main' into module/wifi
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 17s
Python / lint-format (pull_request) Successful in 27s
Python / test (pull_request) Successful in 50s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m39s
2026-06-24 18:58:36 +02:00
Inorishio 1adcb9841c Added network properties, nicNames, netDevices, networkName < reminder I should use layouts.
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 16s
Python / test (pull_request) Successful in 50s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m52s
2026-06-22 23:34:58 +02:00
Inorishio 0e0f8555ed fixing singleton in helpers for network + getting output from systray 2026-06-15 20:48:01 +02:00
Inorishio 1d63e67554 removed network module and moved it to tray, have a popout window without content! everything still in wi.i.p. 2026-06-13 18:22:03 +02:00
202 changed files with 3376 additions and 4157 deletions
+9 -9
View File
@@ -27,25 +27,25 @@ AnchorAnimation {
if (type == AnchorAnim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial;
if (type == AnchorAnim.SlowSpatial)
return Tokens.anim.durations.expressiveSlowSpatial;
return Tokens.anim.durations.large;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4; // 0-7 are the 4 standard types
const idx = type % 4;
return Tokens.anim.durations[types[idx]];
}
easing: {
easing.bezierCurve: {
if (type == AnchorAnim.FastSpatial)
return Tokens.anim.expressiveFastSpatial;
return Tokens.anim.curves.expressiveFastSpatial;
if (type == AnchorAnim.DefaultSpatial)
return Tokens.anim.expressiveDefaultSpatial;
return Tokens.anim.curves.expressiveDefaultSpatial;
if (type == AnchorAnim.SlowSpatial)
return Tokens.anim.expressiveSlowSpatial;
return Tokens.anim.curves.expressiveSlowSpatial;
if (type >= AnchorAnim.StandardSmall && type <= AnchorAnim.StandardExtraLarge)
return Tokens.anim.standard;
return Tokens.anim.curves.standard;
if (type >= AnchorAnim.EmphasizedSmall && type <= AnchorAnim.EmphasizedExtraLarge)
return Tokens.anim.emphasized;
return Tokens.anim.curves.emphasized;
return Tokens.anim.expressiveDefaultSpatial;
return Tokens.anim.curves.expressiveDefaultSpatial;
}
}
+12 -12
View File
@@ -30,34 +30,34 @@ NumberAnimation {
if (type === Anim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial)
return Tokens.anim.durations.expressiveSlowSpatial;
return Tokens.anim.durations.large;
if (type === Anim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Tokens.anim.durations.expressiveDefaultEffects;
return Tokens.anim.durations.expressiveEffects;
if (type === Anim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4; // 0-7 are the 4 standard types
const idx = type % 4;
return Tokens.anim.durations[types[idx]];
}
easing: {
easing.bezierCurve: {
if (type === Anim.FastSpatial)
return Tokens.anim.expressiveFastSpatial;
return Tokens.anim.curves.expressiveFastSpatial;
if (type === Anim.DefaultSpatial)
return Tokens.anim.expressiveDefaultSpatial;
return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial)
return Tokens.anim.expressiveSlowSpatial;
return Tokens.anim.curves.expressiveSlowSpatial;
if (type === Anim.FastEffects)
return Tokens.anim.expressiveFastEffects;
return Tokens.anim.curves.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Tokens.anim.expressiveDefaultEffects;
return Tokens.anim.curves.expressiveDefaultEffects;
if (type === Anim.SlowEffects)
return Tokens.anim.expressiveSlowEffects;
return Tokens.anim.curves.expressiveSlowEffects;
if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.emphasized;
return Tokens.anim.standard;
return Tokens.anim.curves.emphasized;
return Tokens.anim.curves.standard;
}
}
+2 -2
View File
@@ -107,7 +107,7 @@ Slider {
Anim {
duration: Tokens.anim.durations.normal / 2
easing: Tokens.anim.standardAccel
easing.bezierCurve: Tokens.anim.curves.standardAccel
property: "scale"
target: icon
to: 0
@@ -119,7 +119,7 @@ Slider {
Anim {
duration: Tokens.anim.durations.normal / 2
easing: Tokens.anim.standardDecel
easing.bezierCurve: Tokens.anim.curves.standardDecel
property: "scale"
target: icon
to: 1
+2 -3
View File
@@ -1,6 +1,5 @@
import QtQuick
import ZShell.Config
import qs.Components
import qs.Services
CustomRect {
@@ -16,7 +15,7 @@ CustomRect {
property color activeOnColor
property bool checked
property real checkedRadius: Tokens.rounding.medium
property real defaultRadius: Tokens.rounding.large
property real defaultRadius: Math.min(width, height) / 2
property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1)
property color disabledOnColor: Qt.alpha(Colors.palette.m3onSurface, 0.38)
property bool fillWidth
@@ -37,7 +36,7 @@ CustomRect {
readonly property color onColor: !enabled ? disabledOnColor : internalChecked ? activeOnColor : inactiveOnColor
property real padding
readonly property alias pressed: stateLayer.pressed
property real pressedRadius: Tokens.rounding.small
property real pressedRadius: Tokens.rounding.smallest
readonly property alias radiusAnim: radiusAnim
property bool radiusMorph: true
property alias shapeMorph: stateLayer.shapeMorph
+58 -2
View File
@@ -2,6 +2,62 @@ import QtQuick
import ZShell.Config
ColorAnimation {
duration: Tokens.anim.durations.expressiveSlowEffects
easing: Tokens.anim.expressiveSlowEffects
enum Type {
StandardSmall = 0,
Standard,
StandardLarge,
StandardExtraLarge,
EmphasizedSmall,
Emphasized,
EmphasizedLarge,
EmphasizedExtraLarge,
FastSpatial,
DefaultSpatial,
SlowSpatial,
FastEffects,
DefaultEffects,
SlowEffects
}
property int type: CAnim.DefaultSpatial
duration: {
if (type < CAnim.StandardSmall || type > Anim.SlowEffects)
return Tokens.anim.durations.normal;
if (type === CAnim.FastSpatial)
return Tokens.anim.durations.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.durations.large;
if (type === CAnim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.durations.expressiveEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4;
return Tokens.anim.durations[types[idx]];
}
easing.bezierCurve: {
if (type === CAnim.FastSpatial)
return Tokens.anim.curves.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.curves.expressiveSlowSpatial;
if (type === CAnim.FastEffects)
return Tokens.anim.curves.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.curves.expressiveDefaultEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.curves.expressiveSlowEffects;
if (type >= CAnim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.curves.emphasized;
return Tokens.anim.curves.standard;
}
}
+3 -1
View File
@@ -23,7 +23,7 @@ BusyIndicator {
property real implicitSize: Tokens.font.size.normal * 3
property real internalStrokeWidth: strokeWidth
readonly property alias progress: manager.progress
property real strokeWidth: Tokens.padding.extraSmall * 0.8
property real strokeWidth: Tokens.padding.small * 0.8
property alias type: manager.indeterminateAnimationType
implicitHeight: implicitSize
@@ -34,6 +34,7 @@ BusyIndicator {
anchors.fill: parent
bgColor: root.bgColor
fgColor: root.fgColor
hasEndIndicator: false
padding: root.padding
rotation: manager.rotation
startAngle: manager.startFraction * 360
@@ -53,6 +54,7 @@ BusyIndicator {
Anim {
duration: manager.completeEndDuration * Tokens.anim.durations.scale
properties: "opacity,internalStrokeWidth"
type: Anim.DefaultEffects
}
}
+1 -1
View File
@@ -21,7 +21,7 @@ Item {
readonly property real size: Math.min(width, height)
property int spacing: Tokens.spacing.small
property int startAngle: -90
property int strokeWidth: Tokens.padding.extraSmall
property int strokeWidth: Tokens.padding.small
property int sweepAngle: 360
readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2
property real value
+1 -1
View File
@@ -23,7 +23,7 @@ CheckBox {
color: Colors.palette.m3surfaceVariant
implicitHeight: control.checkHeight
implicitWidth: control.checkWidth
radius: Tokens.rounding.small / 2
radius: Tokens.rounding.smallest / 2
CustomRect {
color: Colors.palette.m3primary
+1 -4
View File
@@ -13,13 +13,11 @@ Slider {
property bool animateWave
property color bgColor: enabled ? Colors.palette.m3secondaryContainer : Qt.alpha(Colors.palette.m3onSurface, 0.1)
readonly property bool dragging: mouse.pressed
property color fgColor: enabled ? Colors.palette.m3primary : Qt.alpha(Colors.palette.m3onSurface, 0.38)
property real filledWidth
property alias inset: inset
property color insetColor: enabled ? (inset.attached ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onPrimary) : Colors.palette.m3onSurface
property string insetIcon: ""
property bool interactionOnMove: true
property real pos: visualPosition
property int radius: Tokens.rounding.small
property int waveDuration: 1000
@@ -188,8 +186,7 @@ Slider {
onPositionChanged: e => {
dragMovement = (e.x - pressStartX) / width;
if (root.interactionOnMove)
root.interaction(posBinding.value);
root.interaction(posBinding.value);
}
onPressed: e => {
widthBehavior.enabled = false;
+2 -2
View File
@@ -38,9 +38,9 @@ DoubleSpinBox {
horizontalAlignment: TextField.AlignHCenter
implicitWidth: 65
inputMethodHints: Qt.ImhFormattedNumbersOnly
leftPadding: Tokens.padding.small
leftPadding: Tokens.padding.larger
readOnly: !root.editable
rightPadding: Tokens.padding.small
rightPadding: Tokens.padding.larger
text: root.textFromValue(root.value, root.locale)
validator: root.validator
@@ -12,14 +12,14 @@ Row {
}
property alias active: menu.active
property color color: type == SplitButton.Filled ? Colors.palette.m3primary : Colors.palette.m3secondaryContainer
property color color: type == CustomSplitButton.Filled ? Colors.palette.m3primary : Colors.palette.m3secondaryContainer
property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1)
property color disabledTextColor: Qt.alpha(Colors.palette.m3onSurface, 0.38)
readonly property alias expandBtn: expandBtn
property alias expanded: menu.expanded
property string fallbackIcon
property string fallbackText
property real horizontalPadding: Tokens.padding.medium
property real horizontalPadding: Tokens.padding.larger
readonly property alias iconLabel: iconLabel
readonly property alias label: label
readonly property alias menu: menu
@@ -27,20 +27,20 @@ Row {
property bool menuOnTop
property real minLeftWidth
readonly property alias stateLayer: stateLayer
property color textColor: type == SplitButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondaryContainer
property color textColor: type == CustomSplitButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondaryContainer
readonly property alias textRow: textRow
property int type: SplitButton.Filled
property int type: CustomSplitButton.Filled
property real verticalPadding: Tokens.padding.small
spacing: Math.floor(Tokens.spacing.extraSmall / 2)
spacing: Math.floor(Tokens.spacing.extraSmall)
CustomRect {
bottomRightRadius: Tokens.rounding.medium / 2
bottomRightRadius: Tokens.rounding.small / 2
color: !root.enabled ? root.disabledColor : root.color
implicitHeight: expandBtn.implicitHeight
implicitWidth: Math.max(root.minLeftWidth, textRow.implicitWidth + root.horizontalPadding * 2)
radius: implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
topRightRadius: Tokens.rounding.medium / 2
topRightRadius: Tokens.rounding.small / 2
StateLayer {
id: stateLayer
@@ -92,7 +92,7 @@ Row {
CustomRect {
id: expandBtn
property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) : Tokens.rounding.medium / 2
property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) : Tokens.rounding.small / 2
bottomLeftRadius: rad
color: !root.enabled ? root.disabledColor : root.color
+70
View File
@@ -0,0 +1,70 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Services
Item {
id: root
property alias active: splitButton.active
property alias buttonAlias: splitButton
property alias expanded: splitButton.expanded
property int expandedZ: 100
required property string label
property alias menuItems: splitButton.menuItems
property bool shouldBeActive: true
property alias type: splitButton.type
signal selected(item: MenuItem)
anchors.left: parent.left
anchors.right: parent.right
clip: false
implicitHeight: row.implicitHeight + Tokens.padding.smaller * 2
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 {
id: row
anchors.left: parent.left
anchors.margins: Tokens.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Tokens.spacing.normal
CustomText {
Layout.fillWidth: true
color: root.enabled ? Colors.palette.m3onSurface : Colors.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.larger
text: root.label
}
CustomSplitButton {
id: splitButton
enabled: root.enabled
type: CustomSplitButton.Filled
z: 2
menu.onItemSelected: item => {
root.selected(item);
}
stateLayer.onClicked: {
splitButton.expanded = !splitButton.expanded;
}
}
}
}
+8 -20
View File
@@ -13,12 +13,8 @@ Switch {
implicitWidth: implicitIndicatorWidth
indicator: CustomRect {
color: {
if (!root.enabled)
return root.checked ? Qt.alpha(Colors.palette.m3onSurface, 0.12) : Qt.alpha(Colors.palette.m3surfaceContainerHighest, 0.38);
return root.checked ? Colors.palette.m3primary : Colors.layer(Colors.palette.m3surfaceContainerHighest, root.cLayer);
}
implicitHeight: 14 + Tokens.padding.small * 2
color: root.checked && root.enabled ? Colors.palette.m3primary : Colors.layer(Colors.palette.m3surfaceContainerHighest, root.cLayer)
implicitHeight: Tokens.font.size.medium + Tokens.padding.normal * 2
implicitWidth: implicitHeight * 1.7
radius: Tokens.rounding.full
@@ -26,11 +22,7 @@ Switch {
readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.2 : implicitHeight
anchors.verticalCenter: parent.verticalCenter
color: {
if (!root.enabled)
return root.checked ? Qt.alpha(Colors.palette.m3surface, 0.7) : Qt.alpha(Colors.palette.m3onSurface, 0.12);
return root.checked ? Colors.palette.m3onPrimary : Colors.layer(Colors.palette.m3outline, root.cLayer + 1);
}
color: root.checked && root.enabled ? Colors.palette.m3onPrimary : Colors.layer(Colors.palette.m3outline, root.cLayer + 1)
implicitHeight: parent.implicitHeight - Tokens.padding.extraSmall
implicitWidth: nonAnimWidth
radius: Tokens.rounding.full
@@ -100,7 +92,7 @@ Switch {
anchors.centerIn: parent
asynchronous: true
height: parent.implicitHeight - Tokens.padding.medium
height: parent.implicitHeight - Tokens.padding.larger
preferredRendererType: Shape.CurveRenderer
width: height
@@ -122,16 +114,12 @@ Switch {
}
ShapePath {
capStyle: Tokens.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
capStyle: ShapePath.RoundCap
fillColor: "transparent"
startX: icon.start1.x
startY: icon.start1.y
strokeColor: {
if (!root.enabled)
return root.checked ? Colors.palette.m3outline : Colors.palette.m3surfaceContainer;
return root.checked ? Colors.palette.m3primary : Colors.palette.m3surfaceContainerHighest;
}
strokeWidth: 16 * 0.15
strokeColor: root.checked && root.enabled ? Colors.palette.m3primary : Colors.palette.m3surfaceContainerHighest
strokeWidth: Tokens.font.size.larger * 0.15
Behavior on strokeColor {
CAnim {
@@ -165,6 +153,6 @@ Switch {
component PropAnim: PropertyAnimation {
duration: Tokens.anim.durations.expressiveFastSpatial
easing: Tokens.anim.expressiveFastSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
}
}
+6 -4
View File
@@ -23,6 +23,7 @@ TextFieldBase {
property string leadingIcon
readonly property int leadingOffset: leadingIcon ? leadingIconLoader.width + leadingIconLoader.anchors.leftMargin : 0
property int radius: Tokens.rounding.small
property alias sLayer: stateLayer
readonly property real smallFontScale: smallFontSize / font.pointSize
property int smallFontSize: Tokens.font.size.small
property string supportingText
@@ -129,8 +130,8 @@ TextFieldBase {
}
AnchorAnim {
duration: Tokens.anim.durations.expressiveDefaultEffects
easing: Tokens.anim.expressiveDefaultEffects
duration: Tokens.anim.durations.expressiveEffects
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
}
}
}
@@ -140,11 +141,12 @@ TextFieldBase {
active: root.leadingIcon
anchors.left: parent.left
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.normal
anchors.verticalCenter: parent.verticalCenter
sourceComponent: MaterialIcon {
color: Colors.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.larger
text: root.leadingIcon
}
}
@@ -154,7 +156,7 @@ TextFieldBase {
active: root.trailingIcon
anchors.right: parent.right
anchors.rightMargin: Tokens.padding.small
anchors.rightMargin: Tokens.padding.normal
anchors.verticalCenter: parent.verticalCenter
sourceComponent: MaterialIcon {
+1 -1
View File
@@ -27,7 +27,7 @@ ButtonBase {
return Colors.palette.m3onPrimary;
return type === IconButton.Tonal ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onSurfaceVariant;
}
padding: type === IconButton.Text ? Tokens.padding.extraSmall / 2 : Tokens.padding.extraSmall
padding: type === IconButton.Text ? Tokens.padding.extraSmall / 2 : Tokens.padding.small
MaterialIcon {
id: label
+2 -2
View File
@@ -17,7 +17,7 @@ ButtonBase {
return Colors.palette.m3primary;
return type === TextButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondary;
}
horizontalPadding: Tokens.padding.small
horizontalPadding: Tokens.padding.larger
implicitHeight: row.implicitHeight + verticalPadding * 2
implicitWidth: row.implicitWidth + horizontalPadding * 2
inactiveColor: {
@@ -32,7 +32,7 @@ ButtonBase {
return Colors.palette.m3primary;
return type === TextButton.Filled ? Colors.palette.m3onSurface : Colors.palette.m3onSecondaryContainer;
}
verticalPadding: Tokens.padding.extraSmall
verticalPadding: Tokens.padding.small
RowLayout {
id: row
+5 -5
View File
@@ -78,7 +78,7 @@ MouseArea {
implicitHeight: column.implicitHeight + column.anchors.margins * 2
implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2)
level: 2
radius: Tokens.rounding.large
radius: Tokens.rounding.medium
x: {
watcher.transform;
const item = root.attachTo;
@@ -132,9 +132,9 @@ MouseArea {
Layout.fillWidth: true
color: Qt.alpha(Colors.palette.m3tertiaryContainer, active ? 1 : 0)
implicitHeight: menuOptionRow.implicitHeight + Tokens.padding.medium * 2
implicitWidth: menuOptionRow.implicitWidth + Tokens.padding.medium * 2
radius: menu.radius - column.anchors.margins
implicitHeight: menuOptionRow.implicitHeight + Tokens.padding.larger * 2
implicitWidth: menuOptionRow.implicitWidth + Tokens.padding.larger * 2
radius: Tokens.rounding.small
Behavior on radius {
Anim {
@@ -157,7 +157,7 @@ MouseArea {
id: menuOptionRow
anchors.fill: parent
anchors.margins: Tokens.padding.medium
anchors.margins: Tokens.padding.larger
spacing: Tokens.spacing.small
MaterialIcon {
+1 -1
View File
@@ -70,7 +70,7 @@ TextFieldBase {
id: clearIcon
anchors.right: parent.right
anchors.rightMargin: Tokens.padding.small
anchors.rightMargin: Tokens.padding.larger
anchors.verticalCenter: parent.verticalCenter
enabled: root.text
icon: "clear"
+3 -2
View File
@@ -1,8 +1,9 @@
import QtQuick
import QtQuick.Shapes
import ZShell
import ZShell.Config
import ZShell.Components
import qs.Helpers
import ZShell.Config
import qs.Services
MouseArea {
@@ -80,7 +81,7 @@ MouseArea {
alwaysRunToEnd: true
duration: Tokens.anim.durations.expressiveSlowEffects * 2
easing: Tokens.anim.standard
easing.bezierCurve: Tokens.anim.curves.standard
property: "circleRadius"
target: root
to: root.endRadius
+2 -2
View File
@@ -14,7 +14,7 @@ ButtonBase {
return Colors.palette.m3primary;
return type === TextButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondary;
}
horizontalPadding: Tokens.padding.small
horizontalPadding: Tokens.padding.normal
implicitHeight: label.implicitHeight + verticalPadding * 2
implicitWidth: label.implicitWidth + horizontalPadding * 2
inactiveColor: {
@@ -29,7 +29,7 @@ ButtonBase {
return Colors.palette.m3primary;
return type === TextButton.Filled ? Colors.palette.m3onSurface : Colors.palette.m3onSecondaryContainer;
}
verticalPadding: Tokens.padding.extraSmall
verticalPadding: Tokens.padding.small
CustomText {
id: label
+1 -1
View File
@@ -36,7 +36,7 @@ TextField {
color: Colors.palette.m3primary
implicitHeight: root.cursorRectangle.height
implicitWidth: 1.5
radius: Tokens.rounding.largeIncreased
radius: Tokens.rounding.large
x: root.cursorRectangle.x
y: root.cursorRectangle.y
+8 -8
View File
@@ -32,8 +32,8 @@ CustomRect {
return Colors.palette.m3errorContainer;
return Colors.palette.m3surface;
}
implicitHeight: layout.implicitHeight + Tokens.padding.small * 2
radius: Tokens.rounding.medium
implicitHeight: layout.implicitHeight + Tokens.padding.smaller * 2
radius: Tokens.rounding.normal
Behavior on border.color {
CAnim {
@@ -52,10 +52,10 @@ CustomRect {
id: layout
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.margins: Tokens.padding.small
anchors.rightMargin: Tokens.padding.small
spacing: Tokens.spacing.medium
anchors.leftMargin: Tokens.padding.normal
anchors.margins: Tokens.padding.smaller
anchors.rightMargin: Tokens.padding.normal
spacing: Tokens.spacing.normal
CustomRect {
color: {
@@ -67,9 +67,9 @@ CustomRect {
return Colors.palette.m3error;
return Colors.palette.m3surfaceContainerHigh;
}
implicitHeight: icon.implicitHeight + Tokens.padding.small * 2
implicitHeight: icon.implicitHeight + Tokens.padding.smaller * 2
implicitWidth: implicitHeight
radius: Tokens.rounding.medium
radius: Tokens.rounding.normal
MaterialIcon {
id: icon
+3 -3
View File
@@ -21,7 +21,7 @@ Item {
}
return h;
}
implicitWidth: Config.utilities.sizes.toastWidth - Tokens.padding.small * 2
implicitWidth: Config.utilities.sizes.toastWidth - Tokens.padding.normal * 2
Repeater {
id: repeater
@@ -82,7 +82,7 @@ Item {
Behavior on anchors.bottomMargin {
Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
}
}
Behavior on opacity {
@@ -105,7 +105,7 @@ Item {
id: initAnim
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
from: 0
properties: "opacity,scale"
target: toast
-4
View File
@@ -1,7 +1,6 @@
pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Wayland
import QtQuick
import ZShell.Config
import qs.Components
@@ -16,9 +15,6 @@ Scope {
ExclusionZone {
id: top
WlrLayershell.layer: WlrLayer.Overlay
anchors.left: true
anchors.right: true
anchors.top: true
hasBar: root.geometry.barOnTop
}
+2 -18
View File
@@ -162,19 +162,6 @@ Item {
}
}
Timer {
id: unhideTimer
interval: Config.bar.revealDelay
repeat: false
running: false
onTriggered: {
if (hoverHandler.hovered)
root.bar.isHovered = true;
}
}
HoverHandler {
id: hoverHandler
@@ -191,7 +178,7 @@ Item {
root.popouts.hasCurrent = false;
}
if (Config.bar.autoHide || root.bar.fullscreen)
if (Config.bar.autoHide)
root.bar.isHovered = false;
}
}
@@ -213,9 +200,6 @@ Item {
if (!root.visibilities.bar && Config.bar.autoHide && root.geometry.barContains(x, y, true))
root.bar.isHovered = true;
if (root.bar.fullscreen && !root.bar.isHovered)
unhideTimer.start();
if (root.panels.sidebar.offsetScale === 1) {
const showOsd = root.inRightPanel(root.panels.osdWrapper, x, y);
@@ -236,7 +220,7 @@ Item {
}
}
if (Config.dock.enable && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y))
if (Config.dock.enabled && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y))
root.visibilities.dock = true;
if (root.geometry.barContains(x, y))
+2 -2
View File
@@ -111,7 +111,7 @@ Item {
id: toasts
anchors.bottom: sidebar.visible ? parent.bottom : utilities.top
anchors.margins: Tokens.padding.small
anchors.margins: Tokens.padding.normal
anchors.right: sidebar.left
}
@@ -161,7 +161,7 @@ Item {
Behavior on offsetScale {
Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
}
}
+23 -18
View File
@@ -11,6 +11,7 @@ import ZShell.Blobs
import qs.Daemons
import qs.Components
import qs.Modules.Bar
import qs.Modules.Bar.Popouts.Network as N
import ZShell.Config
import qs.Helpers
import qs.Drawers
@@ -51,7 +52,7 @@ CustomWindow {
readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen)
property var root: Quickshell.shellDir
readonly property real sdfBorderOffset: 2 * fsTransitionProg
readonly property real shadowOpacity: 0.7 * (1 - (bar.isHovered ? 0 : fsTransitionProg))
readonly property real shadowOpacity: 0.7 * (1 - fsTransitionProg)
property color surfaceColor: Colors.tPalette.m3surface
WlrLayershell.exclusionMode: ExclusionMode.Ignore
@@ -59,7 +60,7 @@ CustomWindow {
WlrLayershell.layer: (fsTransitionProg > 0 && Config.general.showOverFullscreen) || (hasSpecialWorkspace && hasFullscreenOnNormalWs) ? WlrLayer.Overlay : WlrLayer.Top
color: "transparent"
contentItem.focus: true
mask: visibilities.isDrawing ? null : (hasFullscreen && !bar.isHovered ? emptyRegion : regions)
mask: visibilities.isDrawing ? null : (hasFullscreen ? emptyRegion : regions)
name: "Bar"
Behavior on fsTransitionProg {
@@ -118,12 +119,6 @@ CustomWindow {
x: root.width - width
y: panels.osdWrapper.y + bar.implicitHeight
}
Region {
height: geometry.horizontal ? 1 : root.screen.height
width: geometry.horizontal ? root.screen.width : 1
y: geometry.position === "bottom" ? root.screen.height - 1 : 0
}
}
Regions {
@@ -144,7 +139,17 @@ CustomWindow {
HyprlandFocusGrab {
id: focusGrab
active: visibilities.dock || visibilities.resources || visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || visibilities.clipboard || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu") && (!Config.bar.tray.showOnHover || (panels.popouts.current as StackView)?.depth > 1))
active: {
const v = visibilities;
const conf = Config;
if (!N.PopupManager.closed && panels.popouts.hasCurrent)
return true;
if ((v.launcher && conf.launcher.enabled) || (v.sidebar && conf.sidebar.enabled) || (v.resources && conf.dashboard.performance.enabled) || (v.dashboard && conf.dashboard.enabled) || v.settings || (v.clipboard && conf.clipboard.enabled) || (v.dock && conf.dock.enabled))
return true;
if (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu") && (!conf.bar.tray.showOnHover || (panels.popouts.current as StackView)?.depth > 1))
return true;
return false;
}
windows: [root]
onCleared: {
@@ -225,7 +230,7 @@ CustomWindow {
implicitHeight: panels.dashboard.height * (geometry.horizontal ? 1 + extraExtent : 1)
implicitWidth: panels.dashboard.width * (geometry.horizontal ? 1 : 1 + extraExtent)
panel: panels.dashboardWrapper
radius: Tokens.rounding.extraLarge
radius: Tokens.rounding.normal
x: panels.dashboardWrapper.x + panels.dashboard.x + geometry.insetLeft(root.borderThickness) - (geometry.horizontal ? 0 : panels.dashboard.width * extraExtent)
y: panels.dashboardWrapper.y + panels.dashboard.y + geometry.insetTop(root.borderThickness) - (geometry.horizontal && geometry.position !== "bottom" ? panels.dashboard.height * extraExtent : 0)
}
@@ -238,7 +243,7 @@ CustomWindow {
deformAmount: 0.06
implicitHeight: panels.launcher.height * (1 + extraHeight)
panel: panels.launcher
radius: Tokens.rounding.medium + (Tokens.padding.largeIncreased / 4)
radius: Tokens.rounding.smallest + 5
y: panels.launcher.y + geometry.insetTop(root.borderThickness)
}
@@ -267,7 +272,7 @@ CustomWindow {
id: notifsBg
panel: panels.notifications
radius: Tokens.rounding.large
radius: Tokens.rounding.normal
}
PanelBg {
@@ -288,7 +293,7 @@ CustomWindow {
implicitHeight: panels.popouts.height * (geometry.horizontal ? 1 + extraExtent : 1)
implicitWidth: panels.popouts.width * (geometry.horizontal ? 1 : 1 + extraExtent)
panel: panels.popoutsWrapper
radius: panels.popouts.current?.panelRadius ?? Tokens.rounding.large
radius: panels.popouts.current?.panelRadius ?? Tokens.rounding.normal
x: panels.popoutsWrapper.x + panels.popouts.x + geometry.insetLeft(root.borderThickness) - (geometry.horizontal ? 0 : panels.popouts.width * extraExtent)
y: panels.popoutsWrapper.y + panels.popouts.y + geometry.insetTop(root.borderThickness) - (geometry.barOnTop ? panels.popouts.height * extraExtent : 0)
@@ -305,7 +310,7 @@ CustomWindow {
implicitHeight: panels.resources.height
implicitWidth: panels.resources.width
panel: panels.resourcesWrapper
radius: Tokens.rounding.largeIncreased + Tokens.padding.small
radius: Tokens.rounding.large
x: panels.resourcesWrapper.x + panels.resources.x + geometry.insetLeft(root.borderThickness)
y: panels.resourcesWrapper.y + panels.resources.y + geometry.insetTop(root.borderThickness)
}
@@ -315,7 +320,7 @@ CustomWindow {
deformAmount: 0.03
panel: panels.settings
radius: Tokens.rounding.largeIncreased + Tokens.padding.small
radius: Tokens.rounding.large + Tokens.padding.normal
}
PanelBg {
@@ -323,7 +328,7 @@ CustomWindow {
deformAmount: 0.08
panel: panels.dock
radius: Tokens.rounding.medium
radius: Tokens.rounding.normal
}
PanelBg {
@@ -331,7 +336,7 @@ CustomWindow {
deformAmount: 0.08
panel: panels.drawing
radius: Tokens.rounding.medium
radius: Tokens.rounding.normal
}
PanelBg {
@@ -462,7 +467,7 @@ CustomWindow {
group: blobGroup
implicitHeight: panel.height
implicitWidth: panel.width
radius: Tokens.rounding.small
radius: Tokens.rounding.smallest
x: panel.x + geometry.insetLeft(root.borderThickness)
y: panel.y + geometry.insetTop(root.borderThickness)
}
+33
View File
@@ -0,0 +1,33 @@
import QtQuick
import QtQuick.Effects
Item {
id: root
property real radius
Rectangle {
id: shadowRect
anchors.fill: root
color: "black"
layer.enabled: true
radius: root.radius
visible: false
}
MultiEffect {
id: effects
anchors.fill: shadowRect
autoPaddingEnabled: true
maskEnabled: true
maskInverted: true
maskSource: shadowRect
shadowBlur: 2.0
shadowColor: "black"
shadowEnabled: true
shadowOpacity: 1
source: shadowRect
}
}
+8 -8
View File
@@ -18,7 +18,7 @@ ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: false
Layout.preferredWidth: centerWidth
spacing: Tokens.spacing.largeIncreased * 2
spacing: Tokens.spacing.large * 2
RowLayout {
Layout.alignment: Qt.AlignHCenter
@@ -64,7 +64,7 @@ ColumnLayout {
CustomClippingRect {
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Tokens.spacing.largeIncreased * 2
Layout.topMargin: Tokens.spacing.large * 2
color: Colors.tPalette.m3surfaceContainer
implicitHeight: root.centerWidth / 2
implicitWidth: root.centerWidth / 2
@@ -99,7 +99,7 @@ ColumnLayout {
Layout.alignment: Qt.AlignHCenter
color: Colors.tPalette.m3surfaceContainer
focus: true
implicitHeight: input.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: input.implicitHeight + Tokens.padding.small * 2
implicitWidth: root.centerWidth * 0.8
radius: Tokens.rounding.full
@@ -130,11 +130,11 @@ ColumnLayout {
id: input
anchors.fill: parent
anchors.margins: Tokens.padding.extraSmall
spacing: Tokens.spacing.medium
anchors.margins: Tokens.padding.small
spacing: Tokens.spacing.normal
Item {
implicitHeight: statusIcon.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: statusIcon.implicitHeight + Tokens.padding.small * 2
implicitWidth: implicitHeight
MaterialIcon {
@@ -174,7 +174,7 @@ ColumnLayout {
CustomRect {
color: root.greeter.buffer && !root.greeter.launching ? Colors.palette.m3primary : Colors.layer(Colors.palette.m3surfaceContainerHigh, 2)
implicitHeight: enterIcon.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: enterIcon.implicitHeight + Tokens.padding.small * 2
implicitWidth: implicitHeight
radius: Tokens.rounding.full
@@ -200,7 +200,7 @@ ColumnLayout {
Item {
Layout.fillWidth: true
Layout.topMargin: -Tokens.spacing.largeIncreased
Layout.topMargin: -Tokens.spacing.large
implicitHeight: Math.max(message.implicitHeight, stateMessage.implicitHeight)
Behavior on implicitHeight {
+11 -11
View File
@@ -30,11 +30,11 @@ NumberAnimation {
if (type === Anim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial)
return Tokens.anim.durations.expressiveSlowSpatial;
return Tokens.anim.durations.large;
if (type === Anim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Tokens.anim.durations.expressiveDefaultEffects;
return Tokens.anim.durations.expressiveEffects;
if (type === Anim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects;
@@ -42,22 +42,22 @@ NumberAnimation {
const idx = type % 4; // 0-7 are the 4 standard types
return Tokens.anim.durations[types[idx]];
}
easing: {
easing.bezierCurve: {
if (type === Anim.FastSpatial)
return Tokens.anim.expressiveFastSpatial;
return Tokens.anim.curves.expressiveFastSpatial;
if (type === Anim.DefaultSpatial)
return Tokens.anim.expressiveDefaultSpatial;
return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial)
return Tokens.anim.expressiveSlowSpatial;
return Tokens.anim.curves.expressiveSlowSpatial;
if (type === Anim.FastEffects)
return Tokens.anim.expressiveFastEffects;
return Tokens.anim.curves.expressiveFastEffects;
if (type === Anim.DefaultEffects)
return Tokens.anim.expressiveDefaultEffects;
return Tokens.anim.curves.expressiveDefaultEffects;
if (type === Anim.SlowEffects)
return Tokens.anim.expressiveSlowEffects;
return Tokens.anim.curves.expressiveSlowEffects;
if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.emphasized;
return Tokens.anim.standard;
return Tokens.anim.curves.emphasized;
return Tokens.anim.curves.standard;
}
}
+58 -2
View File
@@ -2,6 +2,62 @@ import QtQuick
import ZShell.Config
ColorAnimation {
duration: Tokens.anim.durations.expressiveSlowEffects
easing: Tokens.anim.expressiveSlowEffects
enum Type {
StandardSmall = 0,
Standard,
StandardLarge,
StandardExtraLarge,
EmphasizedSmall,
Emphasized,
EmphasizedLarge,
EmphasizedExtraLarge,
FastSpatial,
DefaultSpatial,
SlowSpatial,
FastEffects,
DefaultEffects,
SlowEffects
}
property int type: CAnim.DefaultSpatial
duration: {
if (type < CAnim.StandardSmall || type > Anim.SlowEffects)
return Tokens.anim.durations.normal;
if (type === CAnim.FastSpatial)
return Tokens.anim.durations.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.durations.large;
if (type === CAnim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.durations.expressiveEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4;
return Tokens.anim.durations[types[idx]];
}
easing.bezierCurve: {
if (type === CAnim.FastSpatial)
return Tokens.anim.curves.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.curves.expressiveSlowSpatial;
if (type === CAnim.FastEffects)
return Tokens.anim.curves.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.curves.expressiveDefaultEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.curves.expressiveSlowEffects;
if (type >= CAnim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.curves.emphasized;
return Tokens.anim.curves.standard;
}
}
+1 -1
View File
@@ -23,7 +23,7 @@ BusyIndicator {
property real implicitSize: Tokens.font.size.normal * 3
property real internalStrokeWidth: strokeWidth
readonly property alias progress: manager.progress
property real strokeWidth: Tokens.padding.extraSmall * 0.8
property real strokeWidth: Tokens.padding.small * 0.8
property alias type: manager.indeterminateAnimationType
implicitHeight: implicitSize
+1 -1
View File
@@ -21,7 +21,7 @@ Item {
readonly property real size: Math.min(width, height)
property int spacing: Tokens.spacing.small
property int startAngle: -90
property int strokeWidth: Tokens.padding.extraSmall
property int strokeWidth: Tokens.padding.small
property int sweepAngle: 360
readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2
property real value
+1 -1
View File
@@ -27,7 +27,7 @@ TextField {
color: Colors.palette.m3primary
implicitWidth: 2
radius: Tokens.rounding.medium
radius: Tokens.rounding.normal
Behavior on opacity {
Anim {
+2 -1
View File
@@ -1,4 +1,5 @@
import QtQuick
import QtQuick.Controls
import ZShell.Config
import qs.Services
@@ -10,6 +11,6 @@ TextInput {
font {
family: Config.appearance?.font.family.sans ?? "sans-serif"
hintingPreference: Font.PreferFullHinting
pixelSize: Tokens?.font.size.normal ?? 15
pixelSize: Config.appearance?.font.size.normal ?? 15
}
}
+1 -1
View File
@@ -81,7 +81,7 @@ MouseArea {
alwaysRunToEnd: true
duration: Tokens.anim.durations.expressiveSlowEffects * 2
easing: Tokens.anim.standard
easing.bezierCurve: Tokens.anim.curves.standard
property: "circleRadius"
target: root
to: root.endRadius
+7 -7
View File
@@ -11,18 +11,18 @@ RowLayout {
required property var greeter
required property real screenHeight
spacing: Tokens.spacing.largeIncreased * 2
spacing: Tokens.spacing.large * 2
ColumnLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.medium
spacing: Tokens.spacing.normal
CustomRect {
Layout.fillWidth: true
color: Colors.tPalette.m3surfaceContainer
implicitHeight: weather.implicitHeight
radius: Tokens.rounding.small
topLeftRadius: Tokens.rounding.largeIncreased
topLeftRadius: Tokens.rounding.large
WeatherInfo {
id: weather
@@ -34,7 +34,7 @@ RowLayout {
CustomClippingRect {
Layout.fillHeight: true
Layout.fillWidth: true
bottomLeftRadius: Tokens.rounding.largeIncreased
bottomLeftRadius: Tokens.rounding.large
color: Colors.tPalette.m3surfaceContainer
radius: Tokens.rounding.small
@@ -51,15 +51,15 @@ RowLayout {
ColumnLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.medium
spacing: Tokens.spacing.normal
CustomRect {
Layout.fillHeight: true
Layout.fillWidth: true
bottomRightRadius: Tokens.rounding.largeIncreased
bottomRightRadius: Tokens.rounding.large
color: Colors.tPalette.m3surfaceContainer
radius: Tokens.rounding.small
topRightRadius: Tokens.rounding.largeIncreased
topRightRadius: Tokens.rounding.large
SessionDock {
greeter: root.greeter
+5 -5
View File
@@ -43,7 +43,7 @@ Scope {
ParallelAnimation {
Anim {
duration: Tokens.anim.durations.expressiveFastSpatial
easing: Tokens.anim.expressiveFastSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
property: "scale"
target: lockContent
to: 1
@@ -65,7 +65,7 @@ Scope {
Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
property: "scale"
target: content
to: 1
@@ -74,12 +74,12 @@ Scope {
Anim {
property: "radius"
target: lockBg
to: Tokens.rounding.largeIncreased * 1.5
to: Tokens.rounding.large * 1.5
}
Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
property: "implicitWidth"
target: lockContent
to: (win.screen?.height ?? 0) * Config.lock.sizes.heightMult * Config.lock.sizes.ratio
@@ -87,7 +87,7 @@ Scope {
Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
property: "implicitHeight"
target: lockContent
to: (win.screen?.height ?? 0) * Config.lock.sizes.heightMult
+1 -1
View File
@@ -113,7 +113,7 @@ Item {
Behavior on scale {
Anim {
duration: Tokens.anim.durations.expressiveFastSpatial
easing: Tokens.anim.expressiveFastSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
}
}
+8 -8
View File
@@ -13,7 +13,7 @@ ColumnLayout {
anchors.fill: parent
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.small
spacing: Tokens.spacing.smaller
CustomText {
Layout.fillWidth: true
@@ -41,7 +41,7 @@ ColumnLayout {
}
}
sourceComponent: ColumnLayout {
spacing: Tokens.spacing.largeIncreased
spacing: Tokens.spacing.large
MaterialIcon {
Layout.alignment: Qt.AlignHCenter
@@ -79,8 +79,8 @@ ColumnLayout {
anchors.left: parent?.left
anchors.right: parent?.right
implicitHeight: row.implicitHeight + Tokens.padding.small * 2
radius: Tokens.rounding.medium - Tokens.padding.small
implicitHeight: row.implicitHeight + Tokens.padding.normal * 2
radius: Tokens.rounding.normal - Tokens.padding.smaller
StateLayer {
onClicked: {
@@ -92,8 +92,8 @@ ColumnLayout {
id: row
anchors.fill: parent
anchors.margins: Tokens.padding.small
spacing: Tokens.spacing.medium
anchors.margins: Tokens.padding.normal
spacing: Tokens.spacing.normal
MaterialIcon {
color: session.index === sessions.currentIndex ? Colors.palette.m3onPrimary : Colors.palette.m3onSurfaceVariant
@@ -129,13 +129,13 @@ ColumnLayout {
color: Colors.palette.m3primary
implicitHeight: sessions.currentItem?.implicitHeight ?? 0
implicitWidth: sessions.width
radius: Tokens.rounding.medium - Tokens.padding.small
radius: Tokens.rounding.normal - Tokens.padding.smaller
y: sessions.currentItem?.y ?? 0
Behavior on y {
Anim {
duration: Tokens.anim.durations.small
easing: Tokens.anim.expressiveDefaultEffects
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
}
}
}
+9 -9
View File
@@ -14,7 +14,7 @@ ColumnLayout {
anchors.fill: parent
anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.small
spacing: Tokens.spacing.smaller
CustomText {
Layout.fillWidth: true
@@ -42,7 +42,7 @@ ColumnLayout {
}
}
sourceComponent: ColumnLayout {
spacing: Tokens.spacing.largeIncreased
spacing: Tokens.spacing.large
MaterialIcon {
Layout.alignment: Qt.AlignHCenter
@@ -81,8 +81,8 @@ ColumnLayout {
anchors.left: parent?.left
anchors.right: parent?.right
implicitHeight: row.implicitHeight + Tokens.padding.small * 2
radius: Tokens.rounding.medium - Tokens.padding.small
implicitHeight: row.implicitHeight + Tokens.padding.normal * 2
radius: Tokens.rounding.normal - Tokens.padding.smaller
StateLayer {
onClicked: {
@@ -94,8 +94,8 @@ ColumnLayout {
id: row
anchors.fill: parent
anchors.margins: Tokens.padding.small
spacing: Tokens.spacing.medium
anchors.margins: Tokens.padding.normal
spacing: Tokens.spacing.normal
CustomClippingRect {
Layout.preferredHeight: 50
@@ -135,13 +135,13 @@ ColumnLayout {
color: Colors.palette.m3primary
implicitHeight: users.currentItem?.implicitHeight ?? 0
implicitWidth: users.width
radius: Tokens.rounding.medium - Tokens.padding.small
radius: Tokens.rounding.normal - Tokens.padding.smaller
y: users.currentItem?.y ?? 0
Behavior on y {
Anim {
duration: Tokens.anim.durations.expressiveDefaultEffects
easing: Tokens.anim.expressiveDefaultEffects
duration: Tokens.anim.durations.small
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
}
}
}
+4 -4
View File
@@ -34,7 +34,7 @@ ColumnLayout {
RowLayout {
Layout.fillWidth: true
spacing: Tokens.spacing.largeIncreased
spacing: Tokens.spacing.large
MaterialIcon {
animate: true
@@ -67,7 +67,7 @@ ColumnLayout {
}
Loader {
Layout.rightMargin: Tokens.padding.small
Layout.rightMargin: Tokens.padding.smaller
active: root.width > 400
visible: active
@@ -103,12 +103,12 @@ ColumnLayout {
Layout.bottomMargin: Tokens.padding.large * 2
Layout.fillWidth: true
Layout.topMargin: Tokens.spacing.small
Layout.topMargin: Tokens.spacing.smaller
active: root.rootHeight > 820
visible: active
sourceComponent: RowLayout {
spacing: Tokens.spacing.largeIncreased
spacing: Tokens.spacing.large
Repeater {
model: {
+70
View File
@@ -0,0 +1,70 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Components
import ZShell.Config
Singleton {
id: root
property list<var> apps: {
var map = new Map();
const pinnedApps = Config.dock?.pinnedApps ?? [];
for (const appId of pinnedApps) {
if (!map.has(appId.toLowerCase()))
map.set(appId.toLowerCase(), ({
pinned: true,
toplevels: []
}));
}
if (pinnedApps.length > 0) {
map.set("SEPARATOR", {
pinned: false,
toplevels: []
});
}
var values = [];
for (const [key, value] of map) {
values.push(appEntryComp.createObject(null, {
appId: key,
toplevels: value.toplevels,
pinned: value.pinned
}));
}
return values;
}
function isPinned(appId) {
return Config.dock.pinnedApps.indexOf(appId) !== -1;
}
function togglePin(appId) {
if (root.isPinned(appId)) {
Config.dock.pinnedApps = Config.dock.pinnedApps.filter(id => id !== appId);
} else {
Config.dock.pinnedApps = Config.dock.pinnedApps.concat([appId]);
}
}
Component {
id: appEntryComp
TaskbarAppEntry {
}
}
component TaskbarAppEntry: QtObject {
id: wrapper
required property string appId
required property bool pinned
required property list<var> toplevels
}
}
+63
View File
@@ -0,0 +1,63 @@
// FetchPresets.qml
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
Singleton {
id: root
property var parsedPresets: ({})
readonly property var presets: parsedPresets
property bool ready: false
function accents(presetName, variantName) {
const variant = parsedPresets[presetName]?.variants?.[variantName];
return variant?.accents ?? [];
}
function defaultAccent(presetName, variantName) {
const variant = parsedPresets[presetName]?.variants?.[variantName];
return variant?.default_accent ?? "";
}
function modes(presetName, variantName) {
const variant = parsedPresets[presetName]?.variants?.[variantName];
return variant?.modes ?? [];
}
function presetNames() {
return Object.keys(parsedPresets);
}
function variantNames(presetName) {
const preset = parsedPresets[presetName];
if (!preset || !preset.variants)
return [];
return Object.keys(preset.variants);
}
Process {
command: ["zshell-cli", "scheme", "list-presets", "--json"]
running: true
stdout: StdioCollector {
onStreamFinished: {
try {
const parsed = JSON.parse(text);
root.parsedPresets = parsed.presets ?? {};
root.ready = true;
} catch (e) {
console.error("Failed to parse presets JSON:", e);
}
}
}
}
}
-10
View File
@@ -77,16 +77,6 @@ Singleton {
"99": "thunderstorm"
})
function getAppCategoryIcon(name: string, fallback: string): string {
const categories = DesktopEntries.heuristicLookup(name)?.categories;
if (categories)
for (const [key, value] of Object.entries(categoryIcons))
if (categories.includes(key))
return value;
return fallback;
}
function getAppIcon(name: string, fallback: string): string {
const icon = DesktopEntries.heuristicLookup(name)?.icon;
if (fallback !== "undefined")
+114
View File
@@ -0,0 +1,114 @@
pragma Singleton
import Quickshell
import Quickshell.Networking
import QtQuick
Singleton {
id: root
property bool active: false
readonly property list<Network> connectedNetworks: networks.filter(n => n.connected)
property Network connectingNetwork
readonly property list<NetworkDevice> devices: Networking.devices.values
property Network failedNetwork
readonly property list<Network> knownNetworks: networks.filter(n => n.known && !n.connected)
readonly property list<Network> networks: {
const list = [];
for (const d of wifiDevices) {
for (const n of d.networks.values) {
if (!list.includes(n))
list.push(n);
}
}
return list;
}
property bool scanning: false
readonly property list<Network> unknownNetworks: networks.filter(n => !n.known)
readonly property list<WifiDevice> wifiDevices: devices.filter(d => wifiDevice(d))
readonly property bool wifiEnabled: Networking.wifiEnabled
signal networkConnected
function isSecure(security): bool {
return (security === WifiSecurityType.WpaPsk || security === WifiSecurityType.Wpa2Psk || security === WifiSecurityType.Sae);
}
function requestConnect(network: Network, secret = undefined): void {
connectingNetwork = network;
if (secret === undefined || secret === "") {
network.connect();
} else {
(network as WifiNetwork).connectWithPsk(secret);
}
}
function setScan(value: bool): void {
for (const d of wifiDevices) {
d.scannerEnabled = value;
}
}
function setWifi(value: bool): void {
Networking.wifiEnabled = value;
}
function wifiDevice(dev): bool {
return dev.type === DeviceType.Wifi;
}
onActiveChanged: {
for (const d of wifiDevices)
d.scannerEnabled = active;
}
Timer {
id: flushFailed
interval: 5000
running: root.failedNetwork
onTriggered: {
root.failedNetwork = null;
}
}
Timer {
id: checkConnection
interval: 500
repeat: true
running: root.connectingNetwork
onTriggered: {
var completedNetwork;
switch (root.connectingNetwork.state) {
case ConnectionState.Connecting:
break;
case ConnectionState.Connected:
completedNetwork = root.connectingNetwork;
root.networkConnected();
break;
case ConnectionState.Disconnected:
root.failedNetwork = root.connectingNetwork;
completedNetwork = root.connectingNetwork;
break;
}
if (completedNetwork) {
root.connectingNetwork = null;
}
}
}
Timer {
interval: 10000
running: checkConnection.running
onTriggered: {
root.failedNetwork = root.connectingNetwork;
root.connectingNetwork = null;
}
}
}
+1 -1
View File
@@ -391,7 +391,7 @@ Item {
tool: root.tool
visible: root.mode === "edit"
x: Math.max(8, Math.min(root.rsx + root.sw / 2 - width / 2, root.screen.width - width - 8))
y: (root.rsy + root.sh + height + Tokens.padding.small <= root.screen.height) ? root.rsy + root.sh + Tokens.padding.small : (root.rsy - height - Tokens.padding.small <= 0) ? root.rsy + root.sh - height - Tokens.padding.small : root.rsy - height - Tokens.padding.small
y: (root.rsy + root.sh + height + Tokens.padding.normal <= root.screen.height) ? root.rsy + root.sh + Tokens.padding.normal : (root.rsy - height - Tokens.padding.normal <= 0) ? root.rsy + root.sh - height - Tokens.padding.normal : root.rsy - height - Tokens.padding.normal
onCancelRequested: root.cancel()
onClearRequested: annotations.clearAll()
+4 -10
View File
@@ -49,9 +49,9 @@ CustomRect {
signal undoRequested
color: Colors.palette.m3surface
height: row.implicitHeight + Tokens.padding.small * 2
height: row.implicitHeight + Tokens.padding.normal * 2
radius: Tokens.rounding.full
width: row.implicitWidth + Tokens.padding.small * 2
width: row.implicitWidth + Tokens.padding.normal * 2
RowLayout {
id: row
@@ -73,7 +73,6 @@ CustomRect {
required property var modelData
color: root.tool === modelData.id ? "#3584e4" : "transparent"
font.pointSize: Tokens.font.size.large
icon: tool.modelData.glyph
inactiveColor: root.tool === modelData.id ? Colors.palette.m3primary : "transparent"
inactiveOnColor: root.tool === modelData.id ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
@@ -99,11 +98,11 @@ CustomRect {
model: root.colorPalette
delegate: IconButton {
readonly property real buttonSize: toolRow.implicitHeight - Tokens.padding.small
readonly property real buttonSize: toolRow.implicitHeight - Tokens.padding.normal
required property color modelData
fillWidth: false
font.pointSize: Tokens.font.size.large
font.pointSize: 0
icon: ""
implicitHeight: buttonSize
implicitWidth: buttonSize
@@ -128,7 +127,6 @@ CustomRect {
spacing: Tokens.spacing.extraSmall
IconButton {
font.pointSize: Tokens.font.size.large
icon: "undo"
inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface
@@ -140,7 +138,6 @@ CustomRect {
}
IconButton {
font.pointSize: Tokens.font.size.large
icon: "delete_history"
inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface
@@ -152,7 +149,6 @@ CustomRect {
}
IconButton {
font.pointSize: Tokens.font.size.large
icon: "content_copy"
inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface
@@ -164,7 +160,6 @@ CustomRect {
}
IconButton {
font.pointSize: Tokens.font.size.large
icon: "delete_forever"
inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface
@@ -176,7 +171,6 @@ CustomRect {
}
IconButton {
font.pointSize: Tokens.font.size.large
icon: "check"
inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface
+1 -4
View File
@@ -17,10 +17,7 @@ Singleton {
watchChanges: true
onAdapterUpdated: writeAdapter()
onFileChanged: {
reload();
Wallpapers.previewColorLock = false;
}
onFileChanged: reload()
JsonAdapter {
id: adapter
+6 -28
View File
@@ -6,7 +6,7 @@ import Quickshell.Io
import QtQuick
import ZShell.Models
import ZShell.Config
import qs.Services
import qs.Modules
import qs.Helpers
import qs.Paths
@@ -17,8 +17,6 @@ Searcher {
property alias crops: adapter.monitorCrops
readonly property string current: showPreview ? previewPath : actualCurrent
property alias monitorCrops: monitorCrops
property bool pendingPreviewClear
property bool previewColorLock
property string previewPath
property bool recentlyChanged
property bool showPreview: false
@@ -36,10 +34,9 @@ Searcher {
function preview(path: string): void {
previewPath = path;
showPreview = true;
if (Config.general.color.schemeGeneration)
previewColorsProc.running = true;
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--image-path", `${previewPath}`, "--scheme", `${Config.colors.schemeType}`, "--mode", `${Config.general.color.mode}`]);
showPreview = true;
}
function setCrop(screen: string, rect: rect, zoom: real): void {
@@ -55,6 +52,7 @@ Searcher {
height: rect.height,
zoom: zoom
};
// root.crops = updated;
}
function setWallpaper(path: string): void {
@@ -68,10 +66,8 @@ Searcher {
function stopPreview(): void {
showPreview = false;
if (previewColorLock)
pendingPreviewClear = true;
else
Colors.showPreview = false;
if (Config.general.color.schemeGeneration)
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--image-path", `${root.actualCurrent}`, "--scheme", `${Config.colors.schemeType}`, "--mode", `${Config.general.color.mode}`]);
}
extraOpts: useFuzzy ? ({}) : ({
@@ -81,11 +77,6 @@ Searcher {
list: wallpapers.entries
useFuzzy: true
onPreviewColorLockChanged: {
if (!previewColorLock && pendingPreviewClear)
Colors.showPreview = false;
}
IpcHandler {
function set(path: string): void {
root.setWallpaper(path);
@@ -127,17 +118,4 @@ Searcher {
path: Config.general.wallpaperPath
recursive: true
}
Process {
id: previewColorsProc
command: ["zshell-cli", "scheme", "generate", "-p", "-i", root.previewPath]
stdout: StdioCollector {
onStreamFinished: {
Colors.load(text, true);
Colors.showPreview = true;
}
}
}
}
+9 -20
View File
@@ -12,7 +12,6 @@ GridLayout {
required property bool fullscreen
required property bool horizontal
required property bool isHovered
required property Wrapper popouts
required property ClipWrapper popoutsWrapper
required property ShellScreen screen
@@ -93,7 +92,7 @@ GridLayout {
delegate: EntryWrapper {
HyprsunsetWidget {
horizontal: root.horizontal
visible: !root.fullscreen || root.isHovered
visible: !root.fullscreen
}
}
}
@@ -114,7 +113,7 @@ GridLayout {
Workspaces {
horizontal: root.horizontal
screen: root.screen
visible: !root.fullscreen || root.isHovered
visible: !root.fullscreen
}
}
}
@@ -127,7 +126,7 @@ GridLayout {
horizontal: root.horizontal
loader: root
popouts: root.popouts
visible: !root.fullscreen || root.isHovered
visible: !root.fullscreen
}
}
}
@@ -138,7 +137,6 @@ GridLayout {
delegate: EntryWrapper {
StatusIcons {
horizontal: root.horizontal
visible: !root.fullscreen || root.isHovered
}
}
}
@@ -150,7 +148,7 @@ GridLayout {
Resources {
horizontal: root.horizontal
visibilities: root.visibilities
visible: !root.fullscreen || root.isHovered
visible: !root.fullscreen
}
}
}
@@ -161,7 +159,7 @@ GridLayout {
delegate: EntryWrapper {
UpdatesWidget {
horizontal: root.horizontal
visible: !root.fullscreen || root.isHovered
visible: !root.fullscreen
}
}
}
@@ -174,7 +172,7 @@ GridLayout {
horizontal: root.horizontal
popouts: root.popouts
visibilities: root.visibilities
visible: !root.fullscreen || root.isHovered
visible: !root.fullscreen
}
}
}
@@ -188,7 +186,7 @@ GridLayout {
loader: root
popouts: root.popouts
visibilities: root.visibilities
visible: !root.fullscreen || root.isHovered
visible: !root.fullscreen
}
}
}
@@ -200,16 +198,7 @@ GridLayout {
WindowTitle {
bar: root
horizontal: root.horizontal
visible: !root.fullscreen || root.isHovered
}
}
}
DelegateChoice {
roleValue: "network"
delegate: EntryWrapper {
NetworkWidget {
visible: !root.fullscreen
}
}
}
@@ -220,7 +209,7 @@ GridLayout {
delegate: EntryWrapper {
MediaWidget {
horizontal: root.horizontal
visible: !root.fullscreen || root.isHovered
visible: !root.fullscreen
}
}
}
+2 -4
View File
@@ -16,12 +16,12 @@ Item {
required property bool fullscreen
readonly property bool horizontal: position !== "left"
property bool isHovered
readonly property int padding: Math.max(Tokens.padding.small, Config.bar.border)
readonly property int padding: Math.max(Tokens.padding.smaller, Config.bar.border)
required property Wrapper popouts
required property ClipWrapper popoutsWrapper
required property string position
required property ShellScreen screen
readonly property bool shouldBeVisible: (!fullscreen && (!Config.bar.autoHide || visibilities.bar)) || isHovered
readonly property bool shouldBeVisible: !fullscreen && (!Config.bar.autoHide || visibilities.bar || isHovered)
readonly property int vPadding: 6
required property PersistentProperties visibilities
@@ -79,9 +79,7 @@ Item {
sourceComponent: Bar {
fullscreen: root.fullscreen
height: root.contentThickness
horizontal: root.horizontal
isHovered: root.isHovered
popouts: root.popouts
popoutsWrapper: root.popoutsWrapper
screen: root.screen
+8 -8
View File
@@ -44,7 +44,7 @@ WidgetBase {
}
required property GridLayout loader
required property Wrapper popouts
readonly property real size: horizontal ? timeText.contentWidth + Tokens.padding.small * 2 : verticalColumn.implicitHeight + Tokens.padding.small * 2
readonly property real size: horizontal ? timeText.contentWidth + Tokens.padding.normal * 2 : verticalColumn.implicitHeight + Tokens.padding.larger * 2
required property PersistentProperties visibilities
color: visibilities.dashboard ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
@@ -57,7 +57,7 @@ WidgetBase {
anchors.centerIn: parent
color: root.contentColor
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
font: Config.appearance.font.family.mono // qmllint disable incompatible-type
height: implicitHeight
text: Time.dateStr
visible: root.horizontal
@@ -72,7 +72,7 @@ WidgetBase {
id: verticalColumn
anchors.centerIn: parent
spacing: Tokens.padding.extraSmall ?? 2
spacing: Tokens.padding.small ?? 2
visible: !root.horizontal
width: root.baseSize
@@ -84,7 +84,7 @@ WidgetBase {
Layout.alignment: Qt.AlignHCenter
color: root.contentColor
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
font: Config.appearance.font.family.mono // qmllint disable incompatible-type
text: Qt.formatDateTime(Time.date, modelData)
Behavior on color {
@@ -96,8 +96,8 @@ WidgetBase {
Rectangle {
Layout.alignment: Qt.AlignHCenter
Layout.bottomMargin: Tokens.padding.extraSmall ?? 2
Layout.topMargin: Tokens.padding.extraSmall ?? 2
Layout.bottomMargin: Tokens.padding.small ?? 2
Layout.topMargin: Tokens.padding.small ?? 2
color: root.contentColor
height: 1
implicitWidth: root.baseSize * 0.5
@@ -114,7 +114,7 @@ WidgetBase {
Layout.alignment: Qt.AlignHCenter
color: root.contentColor
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
font: Config.appearance.font.family.mono // qmllint disable incompatible-type
text: {
if (modelData.includes("h"))
return Time.hourStr;
@@ -135,7 +135,7 @@ WidgetBase {
CustomText {
Layout.alignment: Qt.AlignHCenter
color: root.contentColor
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
font: Config.appearance.font.family.mono // qmllint disable incompatible-type
text: Qt.formatDateTime(Time.date, "AP")
visible: Config.services.useTwelveHourClock && root.formatParts.timeTokens.length > 0
@@ -7,13 +7,13 @@ import qs.Helpers
Row {
id: root
property real batHeight: Tokens.padding.small * 2
property real batWidth: Tokens.padding.medium * 2
property real batHeight: Tokens.padding.smaller * 2
property real batWidth: Tokens.padding.larger * 2
required property string devState
property real nubHeight: Tokens.padding.extraSmall
property real nubHeight: Tokens.padding.small
property real nubWidth: 2
required property real percentage
property real radius: Tokens.rounding.small / 2
property real radius: Tokens.rounding.smallest / 2
spacing: 1
+6 -6
View File
@@ -12,8 +12,8 @@ WidgetBase {
readonly property string currentMedia: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
readonly property int textWidth: Math.min(metrics.width, 200)
implicitHeight: horizontal ? baseSize : layout.implicitHeight + Tokens.padding.small * 2
implicitWidth: horizontal ? layout.implicitWidth + Tokens.padding.small * 2 : baseSize
implicitHeight: horizontal ? baseSize : layout.implicitHeight + Tokens.padding.normal * 2
implicitWidth: horizontal ? layout.implicitWidth + Tokens.padding.normal * 2 : baseSize
radius: Tokens.rounding.full
Behavior on implicitHeight {
@@ -39,11 +39,11 @@ WidgetBase {
GridLayout {
id: layout
anchors.bottomMargin: root.horizontal ? 0 : Tokens.padding.small
anchors.bottomMargin: root.horizontal ? 0 : Tokens.padding.normal
anchors.fill: parent
anchors.leftMargin: root.horizontal ? Tokens.padding.small : 0
anchors.rightMargin: root.horizontal ? Tokens.padding.small : 0
anchors.topMargin: root.horizontal ? 0 : Tokens.padding.small
anchors.leftMargin: root.horizontal ? Tokens.padding.normal : 0
anchors.rightMargin: root.horizontal ? Tokens.padding.normal : 0
anchors.topMargin: root.horizontal ? 0 : Tokens.padding.normal
columns: root.horizontal ? -1 : 1
Behavior on implicitWidth {
+2 -2
View File
@@ -22,7 +22,7 @@ GridLayout {
property bool warning: percentage * 100 >= warningThreshold
property int warningThreshold: 80
columnSpacing: Tokens.spacing.medium
columnSpacing: Tokens.spacing.smaller
columns: horizontal ? -1 : 1
percentage: 0
@@ -49,7 +49,7 @@ GridLayout {
}
CustomClippingRect {
Layout.preferredHeight: root.horizontal ? icon.implicitHeight - Tokens.padding.extraSmall : 4
Layout.preferredHeight: root.horizontal ? icon.implicitHeight - Tokens.padding.small : 4
Layout.preferredWidth: root.horizontal ? 4 : icon.implicitWidth
color: Colors.layer(Colors.palette.m3surfaceContainerHigh, 2)
radius: Tokens.rounding.full
+3 -3
View File
@@ -16,8 +16,8 @@ WidgetBase {
clip: true
color: visibilities.resources ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
implicitHeight: horizontal ? baseSize : gridLayout.implicitHeight + Tokens.padding.medium * 2
implicitWidth: horizontal ? gridLayout.implicitWidth + Tokens.padding.medium * 2 : baseSize
implicitHeight: horizontal ? baseSize : gridLayout.implicitHeight + Tokens.padding.normal * 2
implicitWidth: horizontal ? gridLayout.implicitWidth + Tokens.padding.larger * 2 : baseSize
radius: Tokens.rounding.full
StateLayer {
@@ -32,7 +32,7 @@ WidgetBase {
anchors.centerIn: parent
anchors.horizontalCenterOffset: root.horizontal ? 0 : 1
anchors.verticalCenterOffset: root.horizontal ? 0 : -3
columnSpacing: Tokens.spacing.small
columnSpacing: Tokens.spacing.smaller
columns: root.horizontal ? -1 : 1
ServiceRef {
+31 -9
View File
@@ -30,8 +30,8 @@ WidgetBase {
return i;
return -1;
}
readonly property real size: horizontal ? grid.implicitWidth + grid.anchors.leftMargin + grid.anchors.rightMargin : grid.implicitHeight + grid.anchors.bottomMargin + grid.anchors.topMargin
readonly property int spacing: Tokens.spacing.medium / 2
readonly property real size: horizontal ? grid.implicitWidth + Tokens.padding.small * 2 : grid.implicitHeight + Tokens.padding.small * 2
readonly property int spacing: Tokens.spacing.normal / 2
// Entries that can shrink to nothing, spacing included
function collapsed(entry: var): bool {
@@ -40,13 +40,13 @@ WidgetBase {
return false;
}
bottomLeftRadius: horizontal ? Tokens.rounding.small / 2 : Tokens.rounding.full
bottomLeftRadius: horizontal ? Tokens.rounding.smallest / 2 : Tokens.rounding.full
color: Colors.tPalette.m3surfaceContainer
implicitHeight: horizontal ? baseSize : size
implicitWidth: horizontal ? size : baseSize
radius: Tokens.rounding.full
topLeftRadius: Tokens.rounding.small / 2
topRightRadius: horizontal ? Tokens.rounding.full : Tokens.rounding.small / 2
topLeftRadius: Tokens.rounding.smallest / 2
topRightRadius: horizontal ? Tokens.rounding.full : Tokens.rounding.smallest / 2
Behavior on implicitHeight {
enabled: !root.horizontal
@@ -64,11 +64,11 @@ WidgetBase {
GridLayout {
id: grid
anchors.bottomMargin: root.horizontal ? 0 : Tokens.padding.medium
anchors.bottomMargin: root.horizontal ? 0 : Tokens.padding.small
anchors.fill: parent
anchors.leftMargin: root.horizontal ? Tokens.padding.extraSmall : 0
anchors.rightMargin: root.horizontal ? Tokens.padding.extraSmall : 0
anchors.topMargin: root.horizontal ? 0 : Tokens.padding.extraSmall
anchors.leftMargin: root.horizontal ? Tokens.padding.small : 0
anchors.rightMargin: root.horizontal ? Tokens.padding.small : 0
anchors.topMargin: root.horizontal ? 0 : Tokens.padding.small
columns: root.horizontal ? -1 : 1
Repeater {
@@ -105,6 +105,28 @@ WidgetBase {
}
}
DelegateChoice {
roleValue: "bluetooth"
delegate: EntryWrapper {
name: "bluetooth"
BluetoothWidget {
}
}
}
DelegateChoice {
roleValue: "network"
delegate: EntryWrapper {
name: "network"
NetworkWidget {
}
}
}
DelegateChoice {
roleValue: "power"
@@ -0,0 +1,14 @@
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Services
import qs.Components
MaterialIcon {
Layout.alignment: Qt.AlignVCenter
animate: true
color: Colors.palette.m3onSurface // Network.connected ? root.textColor : Colors.palette.m3error
fill: 1
font.pointSize: Tokens.font.size.larger
text: "bluetooth"
}
@@ -0,0 +1,14 @@
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Services
import qs.Components
MaterialIcon {
Layout.alignment: Qt.AlignVCenter
animate: true
color: Colors.palette.m3onSurface // Network.connected ? root.textColor : Colors.palette.m3error
fill: 1
font.pointSize: Tokens.font.size.larger
text: "android_wifi_4_bar"
}
@@ -40,7 +40,7 @@ Item {
anchors.centerIn: parent
sourceComponent: BatteryIcon {
devState: Battery.deviceStateString.toLowerCase()
devState: Battery.deviceStateString
percentage: Battery.currentPerc
}
}
+5 -10
View File
@@ -16,26 +16,22 @@ WidgetBase {
readonly property alias items: repeater
readonly property alias layout: sysGrid
required property GridLayout loader
readonly property int padding: Tokens.padding.extraSmall
readonly property int padding: Tokens.padding.small
required property Wrapper popouts
readonly property real size: horizontal ? sysGrid.implicitWidth + sysGrid.anchors.leftMargin + sysGrid.anchors.rightMargin : sysGrid.implicitHeight + sysGrid.anchors.topMargin + sysGrid.anchors.bottomMargin
readonly property real size: horizontal ? sysGrid.implicitWidth + Tokens.padding.small : sysGrid.implicitHeight + Tokens.padding.small
bottomLeftRadius: horizontal ? Tokens.rounding.full : Tokens.rounding.small / 2
bottomRightRadius: Tokens.rounding.small / 2
bottomLeftRadius: horizontal ? Tokens.rounding.full : Tokens.rounding.smallest / 2
bottomRightRadius: Tokens.rounding.smallest / 2
color: Colors.tPalette.m3surfaceContainer
implicitHeight: horizontal ? baseSize : size
implicitWidth: horizontal ? size : baseSize
radius: Tokens.rounding.full
topRightRadius: horizontal ? Tokens.rounding.small / 2 : Tokens.rounding.full
topRightRadius: horizontal ? Tokens.rounding.smallest / 2 : Tokens.rounding.full
GridLayout {
id: sysGrid
anchors.bottomMargin: root.horizontal ? 0 : Tokens.padding.extraSmall
anchors.centerIn: parent
anchors.leftMargin: root.horizontal ? Tokens.padding.extraSmall : 0
anchors.rightMargin: root.horizontal ? Tokens.padding.extraSmall : 0
anchors.topMargin: root.horizontal ? 0 : Tokens.padding.extraSmall
columns: root.horizontal ? -1 : 1
rowSpacing: -2
@@ -50,7 +46,6 @@ WidgetBase {
required property int index
required property SystemTrayItem modelData
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
implicitHeight: 34
implicitWidth: 34
ind: index
+1 -1
View File
@@ -12,7 +12,7 @@ import qs.Services
Item {
id: root
property real activeWorkspaceMargin: Math.ceil(Tokens.padding.medium / 4)
property real activeWorkspaceMargin: Math.ceil(Tokens.padding.small / 2)
readonly property int effectiveActiveWorkspaceId: monitor?.activeWorkspace?.id ?? 1
required property bool horizontal
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen)
+35 -36
View File
@@ -15,13 +15,12 @@ import qs.Services
Item {
id: root
readonly property int panelRadius: Tokens.rounding.largeIncreased + Tokens.padding.smaller
readonly property int rounding: panelRadius - Tokens.padding.smaller
readonly property int rounding: Tokens.rounding.small - Tokens.padding.small
readonly property int topMargin: 0
required property var wrapper
implicitHeight: vol.implicitHeight + Tokens.padding.smaller * 2
implicitWidth: 500 + Tokens.padding.smaller * 2
implicitHeight: vol.implicitHeight + Tokens.padding.small * 2
implicitWidth: 500 + Tokens.padding.small * 2
CustomRect {
anchors.left: parent.left
@@ -29,7 +28,7 @@ Item {
anchors.top: parent.top
color: Colors.tPalette.m3surfaceContainer
implicitHeight: parent.implicitHeight
radius: root.rounding
radius: Tokens.rounding.small
y: parent.y
Behavior on implicitHeight {
@@ -42,7 +41,7 @@ Item {
id: vol
anchors.left: parent.left
anchors.margins: Tokens.padding.smaller
anchors.margins: Tokens.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
}
@@ -52,17 +51,17 @@ Item {
CustomRect {
Layout.fillWidth: true
Layout.preferredHeight: 65 + Tokens.spacing.small * 2
Layout.preferredHeight: 65 + Tokens.spacing.smaller * 2
Layout.topMargin: root.topMargin
color: Colors.tPalette.m3surfaceContainer
radius: root.rounding - vol.anchors.margins
radius: root.rounding
ColumnLayout {
anchors.bottomMargin: Tokens.padding.small
anchors.bottomMargin: Tokens.padding.smaller
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.rightMargin: Tokens.padding.small
anchors.topMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.larger
anchors.rightMargin: Tokens.padding.larger
anchors.topMargin: Tokens.padding.smaller
RowLayout {
Layout.fillHeight: true
@@ -83,12 +82,12 @@ Item {
}
RowLayout {
spacing: Tokens.spacing.largeIncreased
spacing: Tokens.spacing.large
CustomMouseArea {
Layout.bottomMargin: Tokens.padding.small
Layout.bottomMargin: Tokens.padding.normal
Layout.fillWidth: true
Layout.preferredHeight: Tokens.padding.medium * 3
Layout.preferredHeight: Tokens.padding.larger * 3
CustomSlider {
anchors.left: parent.left
@@ -110,7 +109,7 @@ Item {
}
CustomSwitch {
Layout.bottomMargin: Tokens.padding.small
Layout.bottomMargin: Tokens.padding.normal
checked: !Audio.muted
onToggled: {
@@ -125,10 +124,10 @@ Item {
CustomClippingRect {
Layout.fillWidth: true
Layout.preferredHeight: 65 + Tokens.spacing.small * 2
Layout.preferredHeight: 65 + Tokens.spacing.smaller * 2
Layout.topMargin: root.topMargin
color: Colors.tPalette.m3surfaceContainer
radius: root.rounding - vol.anchors.margins
radius: root.rounding
PwNodePeakMonitor {
id: sourcePeak
@@ -152,11 +151,11 @@ Item {
}
ColumnLayout {
anchors.bottomMargin: Tokens.padding.small
anchors.bottomMargin: Tokens.padding.smaller
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.rightMargin: Tokens.padding.small
anchors.topMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.larger
anchors.rightMargin: Tokens.padding.larger
anchors.topMargin: Tokens.padding.smaller
RowLayout {
Layout.fillHeight: true
@@ -177,12 +176,12 @@ Item {
}
RowLayout {
spacing: Tokens.spacing.largeIncreased
spacing: Tokens.spacing.large
CustomMouseArea {
Layout.bottomMargin: Tokens.padding.small
Layout.bottomMargin: Tokens.padding.normal
Layout.fillWidth: true
Layout.preferredHeight: Tokens.padding.medium * 3
Layout.preferredHeight: Tokens.padding.larger * 3
CustomSlider {
anchors.left: parent.left
@@ -204,7 +203,7 @@ Item {
}
CustomSwitch {
Layout.bottomMargin: Tokens.padding.small
Layout.bottomMargin: Tokens.padding.normal
checked: !Audio.sourceMuted
onToggled: {
@@ -237,10 +236,10 @@ Item {
required property var modelData
Layout.fillWidth: true
Layout.preferredHeight: 65 + Tokens.spacing.small * 2
Layout.preferredHeight: 65 + Tokens.spacing.smaller * 2
Layout.topMargin: root.topMargin
color: Colors.tPalette.m3surfaceContainer
radius: root.rounding - vol.anchors.margins
radius: root.rounding
PwNodePeakMonitor {
id: peak
@@ -272,11 +271,11 @@ Item {
}
ColumnLayout {
anchors.bottomMargin: Tokens.padding.small
anchors.bottomMargin: Tokens.padding.smaller
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.rightMargin: Tokens.padding.small
anchors.topMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.larger
anchors.rightMargin: Tokens.padding.larger
anchors.topMargin: Tokens.padding.smaller
RowLayout {
Layout.fillHeight: true
@@ -298,12 +297,12 @@ Item {
}
RowLayout {
spacing: Tokens.spacing.largeIncreased
spacing: Tokens.spacing.large
CustomMouseArea {
Layout.bottomMargin: Tokens.padding.small
Layout.bottomMargin: Tokens.padding.normal
Layout.fillWidth: true
Layout.preferredHeight: Tokens.padding.medium * 3
Layout.preferredHeight: Tokens.padding.larger * 3
CustomSlider {
anchors.left: parent.left
@@ -325,7 +324,7 @@ Item {
}
CustomSwitch {
Layout.bottomMargin: Tokens.padding.small
Layout.bottomMargin: Tokens.padding.normal
checked: !appBox.modelData.audio.muted
onToggled: {
+388
View File
@@ -0,0 +1,388 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import QtQml.Models
import Quickshell
import Quickshell.Bluetooth
import ZShell.Components
import ZShell.Config
import qs.Services
import qs.Components
import qs.Helpers
CustomClippingRect {
id: root
implicitHeight: layout.implicitHeight + layout.anchors.margins * 2
implicitWidth: 500
ColumnLayout {
id: layout
anchors.fill: parent
anchors.margins: Tokens.padding.larger
spacing: Tokens.spacing.extraSmall / 2
CustomText {
Layout.rightMargin: Tokens.padding.extraSmall
Layout.topMargin: Tokens.padding.normal
font.pointSize: Tokens.font.size.large
text: qsTr("Bluetooth")
}
Toggle {
checked: Bluetooth.defaultAdapter?.enabled ?? false // qmllint disable unresolved-type
first: true
subtext: qsTr("Toggle bluetooth device state")
text: checked ? qsTr("Enabled") : qsTr("Disabled")
onToggled: {
const adapter = Bluetooth.defaultAdapter; // qmllint disable unresolved-type
if (adapter)
adapter.enabled = checked;
}
}
Toggle {
checked: Bluetooth.defaultAdapter?.discovering ?? false // qmllint disable unresolved-type
last: rows.sortedConnected.length === 0
subtext: qsTr("Enable scanning for new devices")
text: qsTr("Discover")
onToggled: {
const adapter = Bluetooth.defaultAdapter; // qmllint disable unresolved-type
if (adapter)
adapter.discovering = checked;
}
}
ListView {
id: rows
readonly property var sortedConnected: {
const byName = (a, b) => a.name.localeCompare(b.name);
return [...Bluetooth.devices.values].filter(d => d.connected).sort(byName).slice(0, 5);
}
Layout.fillWidth: true
Layout.preferredHeight: contentHeight
interactive: false
section.property: "connected"
spacing: Tokens.spacing.extraSmall / 2
add: Transition {
Anim {
from: 0
property: "opacity"
to: 1
}
}
delegate: DelegateChooser {
role: "isDivider"
DelegateChoice {
roleValue: true
delegate: StatusDivider {
}
}
DelegateChoice {
delegate: BluetoothItem {
list: rows
width: rows.width
}
}
}
displaced: Transition {
Anim {
easing.type: Easing.OutCubic
property: "y"
}
}
model: ScriptModel {
objectProp: "address"
values: {
const byName = (a, b) => a.name.localeCompare(b.name);
return [...[...Bluetooth.devices.values].filter(d => d.connected).sort(byName).slice(0, 5),
{
isDivider: true
},
...[...Bluetooth.devices.values].filter(d => !d.connected).sort(byName).slice(0, 5)];
}
}
move: Transition {
Anim {
easing.type: Easing.OutCubic
property: "y"
}
}
remove: Transition {
Anim {
property: "opacity"
to: 0
}
}
section.delegate: Rectangle {
required property string section
color: "transparent"
height: childrenRect.height
width: ListView.view.width
CustomText {
text: parent.section
}
}
}
}
component BluetoothItem: ConnectedRect {
id: btItem
readonly property int connectedCount: rows.sortedConnected.length
readonly property bool connecting: Network.connectingNetwork === modelData
property int horizontalPadding: Tokens.padding.largeIncreased
readonly property bool inConnectedGroup: index < connectedCount
required property int index
required property ListView list
readonly property bool loading: modelData.state === BluetoothDeviceState.Connecting || modelData.state === BluetoothDeviceState.Disconnecting // qmllint disable unresolved-type
required property BluetoothDevice modelData
property int verticalPadding: Tokens.padding.smaller
first: !inConnectedGroup && index === connectedCount + 1
implicitHeight: rowLayout.implicitHeight + verticalPadding * 2
last: inConnectedGroup ? index === connectedCount - 1 : index === list.count - 1
radius: Tokens.rounding.small
Timer {
interval: 50
running: btItem.ListView.delayRemove
onTriggered: btItem.ListView.delayRemove = false
}
Connections {
function onConnectedChanged(): void {
if (!btItem.modelData.connected)
btItem.ListView.delayRemove = true;
}
function onPairedChanged(): void {
if (btItem.modelData.paired)
btItem.modelData.connect();
}
target: btItem.modelData
}
RowLayout {
id: rowLayout
anchors.fill: parent
anchors.leftMargin: btItem.horizontalPadding
anchors.rightMargin: btItem.horizontalPadding
Column {
id: column
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
Layout.leftMargin: Tokens.spacing.extraSmall
Layout.rightMargin: Tokens.spacing.extraSmall
elide: Text.ElideRight
text: btItem.modelData.name
}
CustomText {
id: subtext
anchors.left: parent.left
anchors.right: parent.right
color: Colors.palette.m3outline
elide: Text.ElideRight
font.pointSize: Tokens.font.size.small
text: btItem.modelData.connected ? (btItem.modelData.batteryAvailable ? qsTr("%1 battery left").arg(Math.round(btItem.modelData.battery * 100) + "%") : qsTr("Battery status unknown")) : btItem.modelData.address
}
}
Item {
Layout.alignment: Qt.AlignRight
implicitHeight: icon.height
implicitWidth: icon.width
MaterialIcon {
id: icon
font.pointSize: Tokens.font.size.large
opacity: btItem.connecting ? 0 : 1
text: btItem.modelData.batteryAvailable ? Icons.getBatteryIcon(btItem.modelData.battery) : "battery_unknown"
visible: btItem.modelData.state === BluetoothDeviceState.Connected // qmllint disable unresolved-type
Behavior on opacity {
Anim {
}
}
}
Loader {
active: opacity > 0
anchors.fill: parent
opacity: btItem.connecting ? 1 : 0
Behavior on opacity {
Anim {
}
}
sourceComponent: CircularIndicator {
bgColor: "transparent"
running: true
}
}
}
ButtonRow {
spacing: Tokens.spacing.small
IconTextButton {
font.pointSize: Tokens.font.size.small
icon: btItem.modelData.connected ? "link_off" : btItem.modelData.paired ? "link" : "add_link"
text: btItem.modelData.connected ? qsTr("Disconnect") : btItem.modelData.paired ? qsTr("Connect") : qsTr("Pair")
onClicked: {
if (btItem.modelData.connected)
btItem.modelData.disconnect();
else if (btItem.modelData.paired)
btItem.modelData.connect();
else if (!btItem.modelData.paired)
btItem.modelData.pair();
else if (btItem.modelData.pairing)
btItem.modelData.cancelPair();
}
}
}
}
}
component ConnectedRect: CustomRect {
id: bg
property bool first
property bool last
bottomLeftRadius: last ? Tokens.rounding.large : Tokens.rounding.extraSmall
bottomRightRadius: last ? Tokens.rounding.large : Tokens.rounding.extraSmall
color: Colors.tPalette.m3surfaceContainer
topLeftRadius: first ? Tokens.rounding.large : Tokens.rounding.extraSmall
topRightRadius: first ? Tokens.rounding.large : Tokens.rounding.extraSmall
Behavior on bottomLeftRadius {
Anim {
}
}
Behavior on bottomRightRadius {
Anim {
}
}
Behavior on topLeftRadius {
Anim {
}
}
Behavior on topRightRadius {
Anim {
}
}
}
component StatusDivider: CustomText {
bottomPadding: Tokens.spacing.extraSmall
color: Colors.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.smaller
text: {
const devices = Bluetooth.devices.values; // qmllint disable unresolved-type
const connectedCount = devices.filter(d => d.connected).length;
let available = qsTr("%1 device%2 available").arg(devices.length - connectedCount).arg(devices.length === 1 ? "" : "s");
return available;
}
topPadding: Tokens.spacing.small
}
component Toggle: CustomSwitch {
id: toggleItem
readonly property alias bg: bg
property alias first: bg.first
property alias last: bg.last
property string subtext
Layout.fillWidth: true
cLayer: 2
horizontalPadding: Tokens.padding.largeIncreased
implicitHeight: Math.max(implicitContentHeight, implicitIndicatorHeight) + verticalPadding * 2
implicitWidth: implicitContentWidth + implicitIndicatorWidth + horizontalPadding * 2
indicator.anchors.right: right
indicator.anchors.rightMargin: toggleItem.horizontalPadding
indicator.anchors.verticalCenter: verticalCenter
verticalPadding: Tokens.padding.normal
background: ConnectedRect {
id: bg
StateLayer {
id: stateLayer
manualPressOverride: toggleItem.pressed
}
}
contentItem: Item {
anchors.left: parent.left
anchors.leftMargin: toggleItem.horizontalPadding
anchors.right: toggleItem.indicator.left
anchors.rightMargin: Tokens.spacing.normal
implicitHeight: column.implicitHeight
implicitWidth: column.implicitWidth
Column {
id: column
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: 0
CustomText {
id: label
anchors.left: parent.left
anchors.right: parent.right
elide: Text.ElideRight
font: {
const f = Qt.font(label.font);
f.pointSize = Tokens.font.size.smaller;
return f;
}
text: toggleItem.text
}
CustomText {
id: subtext
anchors.left: parent.left
anchors.right: parent.right
color: Colors.palette.m3outline
elide: Text.ElideRight
font: {
const f = Qt.font(subtext.font);
f.pointSize = Tokens.font.size.small;
return f;
}
text: toggleItem.subtext
visible: toggleItem.subtext
}
}
}
onPressed: stateLayer.press(stateLayer.mouseX, stateLayer.mouseY)
}
}
+2 -3
View File
@@ -58,7 +58,7 @@ Item {
Anim {
duration: content.animLength
easing: content.animCurve
easing.bezierCurve: content.animCurve
}
}
Behavior on y {
@@ -66,7 +66,7 @@ Item {
Anim {
duration: content.animLength
easing: content.animCurve
easing.bezierCurve: content.animCurve
}
}
@@ -81,7 +81,6 @@ Item {
anchors.top: root.position === "top" ? parent.top : undefined
anchors.topMargin: (-implicitHeight - 5) * root.offsetScale
anchors.verticalCenter: root.horizontal ? undefined : parent.verticalCenter
horizontal: root.horizontal
offsetScale: root.offsetScale
screen: root.screen
}
+13 -8
View File
@@ -11,11 +11,10 @@ Item {
readonly property Item current: currentPopout?.item ?? null
readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null
required property bool horizontal
required property PopoutState popouts
implicitHeight: (currentPopout?.implicitHeight ?? 0) + Tokens.padding.smaller * 2
implicitWidth: (currentPopout?.implicitWidth ?? 0) + Tokens.padding.smaller * 2
implicitHeight: (currentPopout?.implicitHeight ?? 0) + Tokens.padding.small * 2
implicitWidth: (currentPopout?.implicitWidth ?? 0) + Tokens.padding.small * 2
Item {
id: content
@@ -70,7 +69,6 @@ Item {
name: "upower"
sourceComponent: UPowerPopout {
horizontal: root.horizontal
}
}
@@ -82,6 +80,13 @@ Item {
}
}
Popout {
name: "bluetooth"
sourceComponent: BluetoothPopout {
}
}
Popout {
name: "updates"
@@ -98,10 +103,10 @@ Item {
readonly property bool shouldBeActive: root.popouts.currentName === name
active: false
anchors.centerIn: opacity === 1 ? undefined : parent
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: opacity === 1 ? parent.top : undefined
anchors.topMargin: Tokens.padding.smaller
// anchors.horizontalCenter: parent.horizontalCenter
// anchors.top: parent.top
// anchors.topMargin: 5
anchors.centerIn: parent
opacity: 0
scale: 0.8
@@ -0,0 +1,71 @@
import QtQuick
import ZShell.Config
import qs.Services
import qs.Helpers
import qs.Components
CustomRect {
id: root
readonly property bool closing: PopupManager.closed
readonly property url currentPopup: PopupManager.currentPopup
property bool shouldBeVisible: loader.status === Loader.Ready
color: Qt.alpha(Colors.palette.m3shadow, 0.3)
opacity: shouldBeVisible && !closing ? 1 : 0
visible: opacity > 0
Behavior on opacity {
Anim {
}
}
onVisibleChanged: {
if (!visible) {
PopupManager.requestClose();
PopupManager.currentPopup = "";
}
}
CustomMouseArea {
anchors.fill: parent
hoverEnabled: true
preventStealing: true
propagateComposedEvents: false
onClicked: {
const insideItemWidth = mouseX < loader.x + loader.item.width && mouseX > loader.x;
const insideItemHeight = mouseY < loader.y + loader.item.height && mouseY > loader.y;
if (insideItemHeight && insideItemWidth)
return;
PopupManager.requestClose();
}
}
Loader {
id: loader
anchors.centerIn: parent
Connections {
function onCurrentPopupChanged(): void {
if (PopupManager.currentPopup) {
loader.setSource(PopupManager.currentPopup, PopupManager.currentPopupProps);
} else {
loader.source = null;
}
}
target: PopupManager
}
}
Connections {
function onNetworkConnected(): void {
PopupManager.requestClose();
}
target: Network
}
}
+103
View File
@@ -0,0 +1,103 @@
import Quickshell
import QtQuick
import QtQuick.Layouts
import ZShell.Components
import ZShell.Config
import qs.Services
import qs.Components
import qs.Helpers
CustomClippingRect {
id: root
required property var network
color: Colors.palette.m3surfaceContainer
implicitHeight: layout.implicitHeight + layout.anchors.margins * 2
implicitWidth: layout.implicitWidth + layout.anchors.margins * 2
radius: Tokens.rounding.large
ColumnLayout {
id: layout
anchors.fill: parent
anchors.margins: Tokens.padding.extraLarge
spacing: Tokens.spacing.normal
MaterialIcon {
Layout.alignment: Qt.AlignHCenter
font.pointSize: Tokens.font.size.extraLarge * 2
text: "lock"
}
CustomText {
Layout.alignment: Qt.AlignHCenter
color: Colors.palette.m3onSurfaceVariant
text: qsTr("Connect to %1").arg(root.network.name)
}
CustomTextField {
id: passwordField
Layout.fillWidth: true
Layout.preferredWidth: 400
echoMode: CustomTextField.Password
errorText: qsTr("Failed to connect with given password")
isError: Network.failedNetwork
leadingIcon: "lock"
passwordMaskDelay: 5000
placeholderText: qsTr("Input password")
}
ButtonRow {
id: buttonRow
Layout.fillWidth: true
spacing: Tokens.spacing.smaller
IconTextButton {
fillWidth: true
font.pointSize: Tokens.font.size.normal
icon: "close"
inactiveColor: Colors.layer(Colors.palette.m3surfaceContainerHighest, 2)
inactiveOnColor: Colors.palette.m3onSurfaceVariant
isRound: true
isToggle: false
shapeMorph: true
text: "Cancel"
onClicked: PopupManager.requestClose()
}
IconTextButton {
fillWidth: true
font.pointSize: Tokens.font.size.normal
icon: Network.connectingNetwork ? "" : "check"
inactiveColor: Network.connectingNetwork ? Colors.palette.m3primaryContainer : Network.failedNetwork ? Colors.palette.m3error : Colors.palette.m3primary
inactiveOnColor: Network.connectingNetwork ? Colors.palette.m3onPrimaryContainer : Network.failedNetwork ? Colors.palette.m3onError : Colors.palette.m3onPrimary
isRound: true
isToggle: false
shapeMorph: true
text: Network.connectingNetwork ? "" : "Apply"
onClicked: Network.requestConnect(root.network, passwordField.text)
Loader {
active: opacity > 0
anchors.centerIn: parent
opacity: Network.connectingNetwork ? 1 : 0
Behavior on opacity {
Anim {
}
}
sourceComponent: CircularIndicator {
bgColor: "transparent"
implicitSize: buttonRow.height - Tokens.padding.normal
running: true
}
}
}
}
}
}
@@ -0,0 +1,22 @@
pragma Singleton
import Quickshell
import QtQuick
Singleton {
id: root
property bool closed: true
property url currentPopup: ""
property var currentPopupProps: ({})
function requestClose(): void {
closed = true;
}
function requestOpen(source: url, properties = {}): void {
currentPopupProps = properties;
currentPopup = source;
closed = false;
}
}
+322 -16
View File
@@ -1,36 +1,342 @@
pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Networking
import QtQuick
import QtQuick.Layouts
import qs.Components
import Quickshell
import ZShell.Config
import qs.Modules
import qs.Helpers as Helpers
import qs.Services
import qs.Modules.Bar.Popouts.Network
import qs.Components
import qs.Helpers
Item {
CustomClippingRect {
id: root
required property var wrapper
ColumnLayout {
id: layout
anchors.horizontalCenter: parent.horizontalCenter
implicitHeight: networkPopContent.height + networks.implicitHeight + networkPopContent.anchors.margins + networks.anchors.margins * 2
implicitWidth: 500 + 8 * 2
radius: (20 - Tokens.padding.small) * Tokens.rounding.scale
spacing: 8
Component.onCompleted: Network.active = true
Component.onDestruction: Network.active = false
ColumnLayout {
id: networkPopContent
anchors.left: parent.left
anchors.margins: Tokens.padding.large
anchors.right: parent.right
anchors.top: parent.top
spacing: Tokens.spacing.extraSmall / 2
CustomText {
Layout.preferredHeight: visible ? implicitHeight : 0
Layout.rightMargin: Tokens.padding.extraSmall
font.pointSize: Tokens.font.size.large
text: qsTr("Wifi")
}
Toggle {
Layout.preferredHeight: visible ? implicitHeight : 0
checked: Network.wifiEnabled
first: true
last: connected.count === 0
subtext: qsTr("Toggle WiFi device state")
text: checked ? qsTr("Enabled") : qsTr("Disabled")
onToggled: Network.setWifi(checked)
}
Repeater {
model: Helpers.Network.devices
id: connected
CustomRadioButton {
id: network
visible: Network.connectedNetworks.length > 0
required property NetworkDevice modelData
model: ScriptModel {
values: [...Network.connectedNetworks].sort((a, b) => {
return b.signalStrength - a.signalStrength;
})
}
checked: Helpers.Network.activeDevice?.name === modelData.name
text: modelData.description
visible: modelData.name !== "lo"
NetworkItem {
first: false
known: true
repeater: connected
}
}
}
ColumnLayout {
id: networks
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: Tokens.padding.large
anchors.right: parent.right
anchors.top: networkPopContent.bottom
spacing: Tokens.spacing.extraSmall / 2
Spacer {
repeater: known
visible: Network.connectedNetworks.length > 0
}
CustomText {
Layout.leftMargin: Tokens.padding.normal
Layout.preferredHeight: visible ? implicitHeight : 0
color: Colors.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.small
text: Network.knownNetworks.length > 1 ? qsTr("%1 known networks available").arg(Network.knownNetworks.length) : qsTr("1 known network available") // qmllint disable missing-property
visible: Network.knownNetworks.length > 0
}
Repeater {
id: known
visible: Network.knownNetworks.length > 0
model: ScriptModel {
values: [...Network.knownNetworks].sort((a, b) => {
return b.signalStrength - a.signalStrength;
})
}
NetworkItem {
known: true
repeater: known
}
}
Spacer {
repeater: unknown
visible: Network.knownNetworks.length > 0
}
CustomText {
Layout.leftMargin: Tokens.padding.normal
Layout.preferredHeight: visible ? implicitHeight : 0
color: Colors.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.small
text: Network.unknownNetworks.length > 1 ? qsTr("%1 networks available").arg(Network.unknownNetworks.length) : qsTr("1 network available") // qmllint disable missing-property
visible: Network.unknownNetworks.length > 0
}
Repeater {
id: unknown
model: ScriptModel {
values: [...Network.unknownNetworks].sort((a, b) => {
return b.signalStrength - a.signalStrength;
})
}
NetworkItem {
known: false
repeater: unknown
}
}
}
NetworkOverlay {
anchors.fill: parent
}
component ConnectedRect: CustomRect {
id: bg
property bool first
property bool last
bottomLeftRadius: last ? Tokens.rounding.large : Tokens.rounding.extraSmall
bottomRightRadius: last ? Tokens.rounding.large : Tokens.rounding.extraSmall
color: Colors.tPalette.m3surfaceContainer
topLeftRadius: first ? Tokens.rounding.large : Tokens.rounding.extraSmall
topRightRadius: first ? Tokens.rounding.large : Tokens.rounding.extraSmall
}
component NetworkItem: ConnectedRect {
id: networkItem
readonly property bool connecting: Network.connectingNetwork === modelData
property int horizontalPadding: Tokens.padding.largeIncreased
required property int index
readonly property bool isSecure: Network.isSecure(modelData.security)
required property bool known
required property var modelData
required property Repeater repeater
Layout.fillWidth: true
Layout.preferredHeight: visible ? rowLayout.implicitHeight + Tokens.padding.smaller * 2 : 0
first: index === 0
last: index === (repeater.count - 1)
radius: Tokens.rounding.small
RowLayout {
id: rowLayout
anchors.fill: parent
anchors.leftMargin: networkItem.horizontalPadding
anchors.rightMargin: networkItem.horizontalPadding
Column {
id: column
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
Layout.leftMargin: Tokens.spacing.extraSmall
Layout.rightMargin: Tokens.spacing.extraSmall
color: networkItem.modelData.active ? Colors.palette.m3primary : Colors.palette.m3onSurface
elide: Text.ElideRight
text: networkItem.modelData.name
}
CustomText {
id: subtext
anchors.left: parent.left
anchors.right: parent.right
color: Colors.palette.m3outline
elide: Text.ElideRight
font.pointSize: Tokens.font.size.small
text: qsTr("%1 strength").arg(Math.round(networkItem.modelData.signalStrength * 100) + "%")
}
}
Item {
Layout.alignment: Qt.AlignRight
implicitHeight: icon.height
implicitWidth: icon.width
MaterialIcon {
id: icon
color: networkItem.modelData.active ? Colors.palette.m3primary : Colors.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.large
opacity: networkItem.connecting ? 0 : 1
text: Icons.getNetworkIcon(networkItem.modelData.signalStrength * 100, networkItem.isSecure)
Behavior on opacity {
Anim {
}
}
}
Loader {
active: opacity > 0
anchors.fill: parent
opacity: networkItem.connecting ? 1 : 0
Behavior on opacity {
Anim {
}
}
sourceComponent: CircularIndicator {
bgColor: "transparent"
running: true
}
}
}
}
StateLayer {
color: networkItem.modelData.active ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
onClicked: {
if (networkItem.isSecure && !networkItem.known) {
PopupManager.requestOpen(Qt.resolvedUrl("Network/PSKOverlay.qml"), {
network: networkItem.modelData
});
} else {
Network.requestConnect(networkItem.modelData);
}
}
}
}
component Spacer: Item {
id: spacer
required property Repeater repeater
Layout.preferredHeight: repeater.count > 0 ? Tokens.spacing.extraSmall : 0
}
component Toggle: CustomSwitch {
id: toggleItem
readonly property alias bg: bg
property alias first: bg.first
property alias last: bg.last
property string subtext
Layout.fillWidth: true
cLayer: 2
horizontalPadding: Tokens.padding.largeIncreased
implicitHeight: Math.max(implicitContentHeight, implicitIndicatorHeight) + verticalPadding * 2
implicitWidth: implicitContentWidth + implicitIndicatorWidth + horizontalPadding * 2
indicator.anchors.right: right
indicator.anchors.rightMargin: toggleItem.horizontalPadding
indicator.anchors.verticalCenter: verticalCenter
verticalPadding: Tokens.padding.normal
background: ConnectedRect {
id: bg
StateLayer {
id: stateLayer
manualPressOverride: toggleItem.pressed
}
}
contentItem: Item {
anchors.left: parent.left
anchors.leftMargin: toggleItem.horizontalPadding
anchors.right: toggleItem.indicator.left
anchors.rightMargin: Tokens.spacing.normal
implicitHeight: column.implicitHeight
implicitWidth: column.implicitWidth
Column {
id: column
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: 0
CustomText {
id: label
anchors.left: parent.left
anchors.right: parent.right
elide: Text.ElideRight
font: {
const f = Qt.font(label.font);
f.pointSize = Tokens.font.size.smaller;
return f;
}
text: toggleItem.text
}
CustomText {
id: subtext
anchors.left: parent.left
anchors.right: parent.right
color: Colors.palette.m3outline
elide: Text.ElideRight
font: {
const f = Qt.font(subtext.font);
f.pointSize = Tokens.font.size.small;
return f;
}
text: toggleItem.subtext
visible: toggleItem.subtext
}
}
}
onPressed: stateLayer.press(stateLayer.mouseX, stateLayer.mouseY)
}
}
+14 -14
View File
@@ -15,7 +15,7 @@ StackView {
id: root
readonly property int itemHeight: 30
readonly property int panelRadius: ((itemHeight / 2) + Tokens.padding.extraSmall) * Tokens.rounding.scale
readonly property int panelRadius: ((itemHeight / 2) + Tokens.padding.small) * Tokens.rounding.scale
required property PopoutState popouts
property int rootWidth: 0
required property QsMenuHandle trayItem
@@ -88,10 +88,10 @@ StackView {
required property QsMenuEntry modelData
Layout.fillWidth: true
Layout.leftMargin: modelData?.isSeparator ?? false ? Tokens.padding.small : 0
Layout.rightMargin: modelData?.isSeparator ?? false ? Tokens.padding.small : 0
color: modelData?.isSeparator ?? false ? Colors.palette.m3outlineVariant : "transparent"
implicitHeight: modelData?.isSeparator ?? false ? (visible ? 1 : 0) : childrenLoader.item?.implicitHeight ?? 0
Layout.leftMargin: modelData.isSeparator ? Tokens.padding.normal : 0
Layout.rightMargin: modelData.isSeparator ? Tokens.padding.normal : 0
color: modelData.isSeparator ? Colors.palette.m3outlineVariant : "transparent"
implicitHeight: modelData.isSeparator ? (visible ? 1 : 0) : childrenLoader.item.implicitHeight
implicitWidth: childrenLoader.item?.implicitWidth ?? 0
radius: Tokens.rounding.full
visible: index !== (menuOpener.children.values.length - 1) ? true : (modelData.isSeparator ? false : true)
@@ -99,18 +99,18 @@ StackView {
Loader {
id: childrenLoader
active: !item.modelData?.isSeparator ?? false
active: !item.modelData.isSeparator
anchors.fill: parent
asynchronous: true
sourceComponent: Item {
property int iconWidth: icon.active ? icon.width + Tokens.spacing.medium + icon.anchors.rightMargin : 0
property int iconWidth: icon.active ? icon.width + Tokens.spacing.normal + icon.anchors.rightMargin : 0
implicitHeight: root.itemHeight
implicitWidth: label.width + label.anchors.leftMargin * 2 + iconWidth + (expand.item?.width ?? 0)
StateLayer {
enabled: item.modelData?.enabled ?? false
enabled: item.modelData.enabled
radius: item.radius
onClicked: {
@@ -130,7 +130,7 @@ StackView {
Loader {
id: icon
active: item.modelData?.icon ?? "" !== ""
active: item.modelData.icon !== ""
anchors.right: parent.right
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
@@ -144,7 +144,7 @@ StackView {
id: iconImage
implicitSize: parent.implicitHeight
source: item.modelData?.icon ?? Qt.url("")
source: item.modelData.icon
visible: false
}
@@ -163,20 +163,20 @@ StackView {
anchors.left: parent.left
anchors.leftMargin: 10
anchors.verticalCenter: parent.verticalCenter
color: item.modelData?.enabled ?? false ? Colors.palette.m3onSurface : Colors.palette.m3outline
text: item.modelData?.text ?? ""
color: item.modelData.enabled ? Colors.palette.m3onSurface : Colors.palette.m3outline
text: item.modelData.text
}
Loader {
id: expand
active: item.modelData?.hasChildren ?? false
active: item.modelData.hasChildren
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
asynchronous: true
sourceComponent: MaterialIcon {
color: item.modelData?.enabled ?? false ? Colors.palette.m3onSurface : Colors.palette.m3outline
color: item.modelData.enabled ? Colors.palette.m3onSurface : Colors.palette.m3outline
text: "chevron_right"
}
}
+10 -18
View File
@@ -12,10 +12,9 @@ import qs.Services
Column {
id: root
required property bool horizontal
readonly property int panelRadius: ((profiles.height / 2) + Tokens.padding.extraSmall) * Tokens.rounding.scale
readonly property int panelRadius: ((profiles.height / 2) + Tokens.padding.small) * Tokens.rounding.scale
spacing: Tokens.spacing.medium
spacing: Tokens.spacing.normal
Loader {
active: Battery.isLaptop
@@ -25,13 +24,6 @@ Column {
}
}
Item {
id: padding
implicitHeight: root.horizontal ? 0 : Tokens.padding.small
implicitWidth: 1
}
Repeater {
model: Battery.allPeripherals
@@ -41,9 +33,9 @@ Column {
required property var modelData
anchors.left: parent.left
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.normal
anchors.right: parent.right
anchors.rightMargin: Tokens.padding.small
anchors.rightMargin: Tokens.padding.normal
CustomText {
Layout.fillWidth: true
@@ -75,7 +67,7 @@ Column {
}
anchors.left: parent.left
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.normal
text: Battery.isLaptop ? qsTr("Time %1: %2").arg(Battery.onBattery ? "remaining" : "until charged").arg(Battery.onBattery ? formatSeconds(Battery.timeToEmpty, "Calculating...") : formatSeconds(Battery.timeToFull, "Fully charged!")) : qsTr("Power profile: %1").arg(PowerProfile.toString(PowerProfiles.profile))
}
@@ -88,8 +80,8 @@ Column {
sourceComponent: CustomRect {
color: Colors.palette.m3error
implicitHeight: child.implicitHeight + Tokens.padding.large
implicitWidth: child.implicitWidth + Tokens.padding.small * 2
radius: Tokens.rounding.largeIncreased
implicitWidth: child.implicitWidth + Tokens.padding.larger * 2
radius: Tokens.rounding.large
Column {
id: child
@@ -146,7 +138,7 @@ Column {
anchors.horizontalCenter: parent.horizontalCenter
color: Colors.tPalette.m3surfaceContainer
implicitHeight: indicator.height + Tokens.padding.extraSmall * 2
implicitWidth: saver.implicitHeight + balance.implicitHeight + perf.implicitHeight + Tokens.padding.small * 2 + Tokens.spacing.small * 8
implicitWidth: saver.implicitHeight + balance.implicitHeight + perf.implicitHeight + Tokens.padding.larger * 2 + Tokens.spacing.small * 8
radius: Tokens.rounding.full
CustomRect {
@@ -227,8 +219,8 @@ Column {
required property string icon
required property int profile
implicitHeight: icon.implicitHeight + Tokens.padding.extraSmall
implicitWidth: icon.implicitHeight + Tokens.padding.extraSmall
implicitHeight: icon.implicitHeight + Tokens.padding.small
implicitWidth: icon.implicitHeight + Tokens.padding.small
StateLayer {
color: profiles.current === parent.icon ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
+8 -8
View File
@@ -13,13 +13,13 @@ CustomClippingRect {
id: root
readonly property bool hasUpdates: Object.keys(Updates.updates)?.length > 0
readonly property int itemHeight: 50 + Tokens.padding.small * 2
readonly property int itemHeight: 50 + Tokens.padding.smaller * 2
required property var wrapper
color: Colors.tPalette.m3surfaceContainer
implicitHeight: hasUpdates ? updatesListLoader.item?.implicitHeight + Tokens.padding.extraSmall * 2 : noUpdatesLoader.item.height
implicitWidth: hasUpdates ? updatesListLoader.item?.contentWidth + Tokens.padding.extraSmall * 2 : noUpdatesLoader.item.width
radius: Tokens.rounding.large - Tokens.padding.smaller
implicitHeight: hasUpdates ? updatesListLoader.item?.implicitHeight + Tokens.padding.small * 2 : noUpdatesLoader.item.height
implicitWidth: hasUpdates ? updatesListLoader.item?.contentWidth + Tokens.padding.small * 2 : noUpdatesLoader.item.width
radius: Tokens.rounding.small
Loader {
id: noUpdatesLoader
@@ -70,7 +70,7 @@ CustomClippingRect {
displayMarginEnd: root.itemHeight
implicitHeight: Math.min(contentHeight, (root.itemHeight + spacing) * 5 - spacing)
implicitWidth: contentWidth
spacing: Tokens.spacing.medium
spacing: Tokens.spacing.normal
delegate: CustomRect {
id: update
@@ -81,12 +81,12 @@ CustomClippingRect {
color: Colors.tPalette.m3surfaceContainer
implicitHeight: root.itemHeight
implicitWidth: 600
radius: root.radius - Tokens.padding.extraSmall
radius: Tokens.rounding.small - Tokens.padding.small
RowLayout {
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.rightMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.smaller
anchors.rightMargin: Tokens.padding.smaller
MaterialIcon {
font.pointSize: Tokens.font.size.large * 2
+4 -6
View File
@@ -8,7 +8,7 @@ import ZShell.Config
Item {
id: root
property var animCurve: Tokens.anim.expressiveDefaultSpatial
property list<real> animCurve: Tokens.anim.curves.expressiveDefaultSpatial
property int animLength: Tokens.anim.durations.expressiveDefaultSpatial
readonly property alias content: content
readonly property Item current: (content.item as Content)?.current ?? null
@@ -16,7 +16,6 @@ Item {
property alias currentName: popoutState.currentName
property string detachedMode
property alias hasCurrent: popoutState.hasCurrent
required property bool horizontal
readonly property real nonAnimHeight: content.implicitHeight || 150
readonly property real nonAnimWidth: children.find(c => c.shouldBeActive)?.implicitWidth ?? content.implicitWidth
required property real offsetScale
@@ -36,7 +35,7 @@ Item {
Anim {
duration: root.animLength
easing: root.animCurve
easing.bezierCurve: root.animCurve
}
}
Behavior on implicitWidth {
@@ -44,7 +43,7 @@ Item {
Anim {
duration: root.animLength
easing: root.animCurve
easing.bezierCurve: root.animCurve
}
}
@@ -55,11 +54,10 @@ Item {
Comp {
id: content
anchors.fill: parent
anchors.centerIn: parent
shouldBeActive: root.hasCurrent
sourceComponent: Content {
horizontal: root.horizontal
popouts: popoutState
}
}
+9 -9
View File
@@ -59,7 +59,7 @@ Item {
anchors.bottom: parent.bottom
anchors.left: entries.right
anchors.leftMargin: Tokens.spacing.medium
anchors.leftMargin: Tokens.spacing.normal
anchors.top: parent.top
color: Colors.tPalette.m3surfaceContainer
implicitWidth: ClipHistory.previewIsImage ? Math.max(Math.min(imagePreview.sourceSize.width + Tokens.padding.large * 2, Config.clipboard.sizes.previewWidth), Config.clipboard.sizes.minPreviewWidth) : Math.max(Math.min(textPreviewColumn.width + textPreviewColumn.anchors.margins * 2, Config.clipboard.sizes.previewWidth), Config.clipboard.sizes.minPreviewWidth)
@@ -75,7 +75,7 @@ Item {
anchors.left: parent.left
anchors.leftMargin: 0
anchors.margins: Tokens.padding.small
anchors.margins: Tokens.padding.normal
anchors.top: parent.top
visible: !ClipHistory.previewIsImage
@@ -90,7 +90,7 @@ Item {
required property int index
required property var modelData
spacing: Tokens.spacing.medium
spacing: Tokens.spacing.normal
CustomRect {
color: lineRow.index % 2 ? Colors.tPalette.m3surfaceContainer : "transparent"
@@ -192,7 +192,7 @@ Item {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.top: search.bottom
anchors.topMargin: Tokens.spacing.medium
anchors.topMargin: Tokens.spacing.normal
implicitWidth: Config.clipboard.sizes.width
CustomListView {
@@ -204,7 +204,7 @@ Item {
highlightRangeMode: ListView.ApplyRange
preferredHighlightBegin: 0
preferredHighlightEnd: height
spacing: Tokens.spacing.medium
spacing: Tokens.spacing.normal
CustomScrollBar.vertical: CustomScrollBar {
flickable: view
@@ -250,7 +250,7 @@ Item {
id: icon
anchors.left: parent.left
anchors.margins: Tokens.padding.small
anchors.margins: Tokens.padding.normal
anchors.verticalCenter: parent.verticalCenter
font.pointSize: Tokens.font.size.large
text: clipItem.isImage ? "image" : "text_fields"
@@ -260,7 +260,7 @@ Item {
id: text
anchors.left: icon.right
anchors.margins: Tokens.spacing.medium
anchors.margins: Tokens.spacing.normal
anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight
text: clipItem.isImage ? qsTr("Image") : ClipHistory.displayText(clipItem.modelData)
@@ -292,7 +292,7 @@ Item {
IconButton {
Layout.fillHeight: true
Layout.margins: Tokens.padding.small
Layout.margins: Tokens.padding.normal
Layout.preferredWidth: height
icon: "delete"
inactiveColor: Qt.alpha(Colors.palette.m3error, 0.8)
@@ -320,7 +320,7 @@ Item {
Behavior on y {
Anim {
duration: Tokens.anim.durations.small
easing: Tokens.anim.expressiveDefaultEffects
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
}
}
}
+3 -3
View File
@@ -15,15 +15,15 @@ Item {
required property PersistentProperties visibilities
anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
implicitHeight: content.implicitHeight + Tokens.padding.small * 2
implicitWidth: content.implicitWidth + Tokens.padding.small * 2 || 400
implicitHeight: content.implicitHeight + Tokens.padding.normal * 2
implicitWidth: content.implicitWidth + Tokens.padding.normal * 2 || 400
opacity: 1 - offsetScale
visible: offsetScale < 1
Behavior on offsetScale {
Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
}
}
+3 -3
View File
@@ -32,16 +32,16 @@ Item {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.margins: Tokens.padding.small
anchors.margins: Tokens.padding.smaller
anchors.right: parent.right
anchors.top: parent.top
color: "transparent"
radius: Tokens.rounding.extraLarge - anchors.margins
radius: Tokens.rounding.normal - anchors.margins
Item {
id: view
readonly property int currentIndex: root.dashState?.currentTab
readonly property int currentIndex: root.state.currentTab
readonly property Item currentItem: row.children[currentIndex]
anchors.fill: parent
+4 -5
View File
@@ -13,11 +13,11 @@ GridLayout {
required property PersistentProperties dashState
readonly property bool dashboardVisible: visibilities.dashboard
property int radius: Tokens.rounding.medium
property int radius: Tokens.rounding.smallest
required property PersistentProperties visibilities
columnSpacing: Tokens.spacing.small
rowSpacing: Tokens.spacing.small
columnSpacing: Tokens.spacing.smaller
rowSpacing: Tokens.spacing.smaller
ParallelAnimation {
id: openAnim
@@ -104,13 +104,12 @@ GridLayout {
}
}
CustomClippingRect {
Rect {
Layout.column: 0
Layout.columnSpan: 5
Layout.fillWidth: true
Layout.preferredHeight: media.implicitHeight
Layout.row: 2
color: Colors.tPalette.m3surfaceContainer
radius: root.radius
Media {
+4 -4
View File
@@ -132,7 +132,7 @@ CustomMouseArea {
IconButton {
icon: "chevron_left"
padding: Tokens.padding.extraSmall
padding: Tokens.padding.small
type: IconButton.Text
onClicked: root.dashState.currentDate = new Date(root.realCurrYear, root.realCurrMonth - 1, 1)
@@ -150,7 +150,7 @@ CustomMouseArea {
const now = new Date();
return root.realCurrMonth !== now.getMonth() || root.realCurrYear !== now.getFullYear();
}
radius: pressed ? Tokens.rounding.small : Tokens.rounding.largeIncreased
radius: pressed ? Tokens.rounding.small : Tokens.rounding.large
Behavior on radius {
Anim {
@@ -203,7 +203,7 @@ CustomMouseArea {
IconButton {
icon: "chevron_right"
padding: Tokens.padding.extraSmall
padding: Tokens.padding.small
type: IconButton.Text
onClicked: root.dashState.currentDate = new Date(root.realCurrYear, root.realCurrMonth + 1, 1)
@@ -259,7 +259,7 @@ CustomMouseArea {
required property var model
implicitHeight: text.implicitHeight + Tokens.padding.small * 2
implicitHeight: text.implicitHeight + Tokens.padding.normal * 2
implicitWidth: implicitHeight
CustomText {
+190 -162
View File
@@ -1,15 +1,12 @@
pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Services.Mpris
import QtQuick
import QtQuick.Layouts
import QtQuick.Shapes
import QtQuick.Effects
import ZShell.Components
import ZShell.Services
import ZShell.Config
import qs.Modules.Dashboard.Dash.Media
import qs.Daemons
import qs.Components
import qs.Helpers
@@ -17,7 +14,7 @@ import qs.Services
Item {
id: root
readonly property bool hasUnknownLength: (Players.active?.length ?? 0) > 2147483647
property real playerProgress: {
const active = Players.active;
return active?.length ? (active.position % active.length) / active.length : 0;
@@ -26,19 +23,7 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: layout.implicitHeight + layout.anchors.margins * 2
function lengthStr(length: int): string {
if (length < 0)
return "-1:-1";
const hours = Math.floor(length / 3600);
const mins = Math.floor((length % 3600) / 60);
const secs = Math.floor(length % 60).toString().padStart(2, "0");
if (hours > 0)
return `${hours}:${mins.toString().padStart(2, "0")}:${secs}`;
return `${mins}:${secs}`;
}
implicitHeight: cover.height + rowHeight * 2
Behavior on playerProgress {
Anim {
@@ -47,10 +32,11 @@ Item {
}
Timer {
running: Players.active?.isPlaying ?? false
interval: Config.dashboard.mediaUpdateInterval
triggeredOnStart: true
repeat: true
running: Players.active?.isPlaying ?? false
triggeredOnStart: true
onTriggered: Players.active?.positionChanged()
}
@@ -58,18 +44,14 @@ Item {
service: Audio.cava
}
BackgroundShapes {
anchors.fill: parent
}
Shape {
id: visualizer
readonly property int bars: Config.services.visualizerBars
property color color: Qt.alpha(Colors.palette.m3primary, 0.5)
property color fillColor: Qt.alpha(color, 0.1)
property color color: Colors.palette.m3tertiary
property color fillColor: Qt.alpha(color, 0.25)
anchors.fill: parent
anchors.fill: layout
anchors.leftMargin: -(shape.strokeWidth / 2)
layer.enabled: true
asynchronous: true
@@ -90,17 +72,17 @@ Item {
const n = values.length;
if (n < 2)
return "";
return "";
const h = root.height + shape.strokeWidth / 2;
const w = root.width + shape.strokeWidth;
const h = layout.height + shape.strokeWidth / 2;
const w = layout.width + shape.strokeWidth;
function x(i) {
return i * w / (n - 1);
}
function y(i) {
return h - (values[i] * Config.dashboard.sizes.mediaVisualizerSize) / 2;
return h - values[i] * Config.dashboard.sizes.mediaVisualizerSize;
}
let d = `M 0 ${h} `;
@@ -144,186 +126,232 @@ Item {
}
}
Shape {
preferredRendererType: Shape.CurveRenderer
ShapePath {
capStyle: Tokens.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
fillColor: "transparent"
strokeColor: Colors.layer(Colors.palette.m3surfaceContainerHigh, 2)
strokeWidth: Config.dashboard.sizes.mediaProgressThickness
Behavior on strokeColor {
CAnim {
}
}
PathAngleArc {
centerX: cover.x + cover.width / 2
centerY: cover.y + cover.height / 2
radiusX: (cover.width + Config.dashboard.sizes.mediaProgressThickness) / 2 + Tokens.spacing.small
radiusY: (cover.height + Config.dashboard.sizes.mediaProgressThickness) / 2 + Tokens.spacing.small
startAngle: -90 - Config.dashboard.sizes.mediaProgressSweep / 2
sweepAngle: Config.dashboard.sizes.mediaProgressSweep
}
}
ShapePath {
capStyle: Tokens.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
fillColor: "transparent"
strokeColor: Colors.palette.m3primary
strokeWidth: Config.dashboard.sizes.mediaProgressThickness
Behavior on strokeColor {
CAnim {
}
}
PathAngleArc {
centerX: cover.x + cover.width / 2
centerY: cover.y + cover.height / 2
radiusX: (cover.width + Config.dashboard.sizes.mediaProgressThickness) / 2 + Tokens.spacing.small
radiusY: (cover.height + Config.dashboard.sizes.mediaProgressThickness) / 2 + Tokens.spacing.small
startAngle: -90 - Config.dashboard.sizes.mediaProgressSweep / 2
sweepAngle: Config.dashboard.sizes.mediaProgressSweep * root.playerProgress
}
}
}
RowLayout {
id: layout
anchors.fill: parent
anchors.margins: Tokens.padding.large
anchors.leftMargin: Tokens.padding.extraLarge
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: root.implicitHeight
CoverVisualizer {
Layout.fillHeight: true
implicitWidth: Config.dashboard.sizes.mediaCoverArtSize
CustomClippingRect {
id: cover
Layout.alignment: Qt.AlignLeft
Layout.bottomMargin: Tokens.padding.large + Config.dashboard.sizes.mediaProgressThickness + Tokens.spacing.small
Layout.leftMargin: Tokens.padding.large + Config.dashboard.sizes.mediaProgressThickness + Tokens.spacing.small
Layout.preferredHeight: Config.dashboard.sizes.mediaCoverArtSize
Layout.preferredWidth: Config.dashboard.sizes.mediaCoverArtSize
Layout.topMargin: Tokens.padding.large + Config.dashboard.sizes.mediaProgressThickness + Tokens.spacing.small
color: Colors.tPalette.m3surfaceContainerHigh
radius: Infinity
MaterialIcon {
anchors.centerIn: parent
color: Colors.palette.m3onSurfaceVariant
font.pointSize: (parent.width * 0.4) || 1
grade: 200
text: "art_track"
}
Image {
id: image
anchors.fill: parent
asynchronous: true
fillMode: Image.PreserveAspectCrop
source: Players.active?.trackArtUrl ?? ""
sourceSize.height: Math.floor(height)
sourceSize.width: Math.floor(width)
}
}
ColumnLayout {
CustomRect {
Layout.fillWidth: true
Layout.leftMargin: Tokens.spacing.largeIncreased
Layout.rightMargin: Tokens.spacing.largeIncreased
spacing: Tokens.spacing.small
Layout.preferredHeight: childrenRect.height
MarqueeText {
id: title
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
color: Colors.palette.m3primary
font.pointSize: Tokens.font.size.normal
horizontalAlignment: Text.AlignHCenter
pauseMs: 4000
text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
implicitWidth: parent.width - Tokens.padding.large * 4
width: parent.width - Tokens.padding.large * 4
}
MarqueeText {
id: album
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: title.bottom
anchors.topMargin: Tokens.spacing.small
color: Colors.palette.m3outline
font.pointSize: Tokens.font.size.small
horizontalAlignment: Text.AlignHCenter
pauseMs: 4000
text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
implicitWidth: parent.width - Tokens.padding.large * 4
width: parent.width - Tokens.padding.large * 4
}
MarqueeText {
id: artist
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: album.bottom
anchors.topMargin: Tokens.spacing.small
color: Colors.palette.m3secondary
horizontalAlignment: Text.AlignHCenter
pauseMs: 4000
text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
implicitWidth: parent.width - Tokens.padding.large * 4
width: parent.width - Tokens.padding.large * 4
}
RowLayout {
id: positionSliderLayout
Layout.topMargin: Tokens.spacing.large
Layout.fillWidth: true
id: controls
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: artist.bottom
anchors.topMargin: Tokens.spacing.smaller
spacing: Tokens.spacing.small
TextMetrics {
id: timeMetrics
text: Players.active ? root.lengthStr(Math.max(Players.active.position, root.hasUnknownLength ? 0 : Players.active.length)).replace(/[1-9]/g, "0") : "00:00"
}
CustomText {
id: positionLabel
Layout.preferredWidth: timeMetrics.width
text: root.lengthStr(Players.active?.position ?? -1)
color: Colors.palette.m3onSurfaceVariant
font: timeMetrics.font
horizontalAlignment: Text.AlignHCenter
}
CustomSlider {
id: positionSlider
Layout.fillWidth: true
value: Players.active ? Players.active.position / (Players.active.length || 1) : 0
enabled: (Players.active?.canSeek ?? false) && !root.hasUnknownLength
wavy: true
animateWave: Players.active?.isPlaying ?? false
waveFrequency: 5
waveDuration: 2000
interactionOnMove: false
onInteraction: value => {
const active = Players.active;
if (active?.canSeek && active?.positionSupported)
active.position = value * active.length;
Control {
function onClicked(): void {
Players.active?.previous();
}
Binding {
target: positionLabel
property: "text"
value: root.lengthStr(positionSlider.pos * (Players.active?.length ?? 0))
when: positionSlider.dragging
}
}
CustomText {
Layout.preferredWidth: timeMetrics.width
text: root.hasUnknownLength ? "--:--" : root.lengthStr(Players.active?.length ?? -1)
color: Colors.palette.m3onSurfaceVariant
font: timeMetrics.font
horizontalAlignment: Text.AlignHCenter
}
}
ButtonRow {
Layout.topMargin: Tokens.spacing.largeIncreased
Layout.fillWidth: true
spacing: Tokens.spacing.extraSmall
Layout.leftMargin: positionSliderLayout.implicitWidth / 4
Layout.rightMargin: positionSliderLayout.implicitWidth / 4
IconButton {
type: IconButton.Tonal
icon: "shuffle"
isRound: true
shapeMorph: true
checked: Players.active?.shuffle ?? false
enabled: Players.active?.shuffleSupported
onClicked: Players.active.shuffle = !Players.active?.shuffle
}
IconButton {
id: previousBtn
type: IconButton.Tonal
canUse: Players.active?.canGoPrevious ?? false
icon: "skip_previous"
isRound: true
shapeMorph: true
enabled: Players.active?.canGoPrevious
onClicked: Players.active?.previous()
font.pointSize: Tokens.font.size.large
}
IconButton {
id: playPauseBtn
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
isRound: true
shapeMorph: true
fillWidth: true
checked: Players.active?.isPlaying ?? false
enabled: Players.active?.canTogglePlaying
onClicked: Players.active?.togglePlaying()
font.pointSize: Tokens.font.size.large
}
IconButton {
id: nextBtn
type: IconButton.Tonal
icon: "skip_next"
isRound: true
shapeMorph: true
enabled: Players.active?.canGoNext
onClicked: Players.active?.next()
font.pointSize: Tokens.font.size.large
}
IconButton {
type: IconButton.Tonal
icon: Players.active?.loopState === MprisLoopState.Track ? "repeat_one" : "repeat"
isRound: true
shapeMorph: true
checked: Players.active?.loopState === MprisLoopState.Track || Players.active?.loopState === MprisLoopState.Playlist
enabled: Players.active?.loopSupported
onClicked: {
const state = Players.active.loopState;
if (state === MprisLoopState.None)
Players.active.loopState = MprisLoopState.Track;
else if (state === MprisLoopState.Track)
Players.active.loopState = MprisLoopState.Playlist;
else
Players.active.loopState = MprisLoopState.None;
Control {
function onClicked(): void {
Players.active?.togglePlaying();
}
canUse: Players.active?.canTogglePlaying ?? false
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
}
Control {
function onClicked(): void {
Players.active?.next();
}
canUse: Players.active?.canGoNext ?? false
icon: "skip_next"
}
}
}
}
component Control: CustomRect {
id: control
required property bool canUse
required property string icon
property int level: 1
property string set_color: "Secondary"
function onClicked(): void {
}
Layout.preferredWidth: implicitWidth + (controlState.pressed ? Tokens.padding.normal * 2 : 0)
color: canUse ? Colors.palette[`m3${set_color.toLowerCase()}`] : Colors.palette[`m3${set_color.toLowerCase()}Container`]
implicitHeight: implicitWidth
implicitWidth: Math.max(icon.implicitHeight, icon.implicitHeight) + Tokens.padding.small
radius: Tokens.rounding.full
Behavior on Layout.preferredWidth {
Anim {
duration: Tokens.anim.durations.expressiveFastSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
}
}
Behavior on radius {
Anim {
duration: Tokens.anim.durations.expressiveFastSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
}
}
Elevation {
anchors.fill: parent
level: controlState.containsMouse && !controlState.pressed ? control.level + 1 : control.level
radius: parent.radius
z: -1
}
StateLayer {
id: controlState
color: control.canUse ? Colors.palette[`m3on${control.set_color}`] : Colors.palette[`m3on${control.set_color}Container`]
enabled: control.canUse
onClicked: {
control.onClicked();
}
// radius: Tokens.rounding.full
}
MaterialIcon {
id: icon
anchors.centerIn: parent
anchors.verticalCenterOffset: font.pointSize * 0.05
animate: true
color: control.canUse ? Colors.palette[`m3on${control.set_color}`] : Colors.palette[`m3on${control.set_color}Container`]
fill: control.canUse ? 1 : 0
font.pointSize: Tokens.font.size.large
text: control.icon
}
}
}
@@ -1,97 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import M3Shapes
import qs.Components
import qs.Services
import qs.Helpers
Item {
id: root
property int count: 14
property list<real> darkOpacities: [0.10, 0.20, 0.10, 0.20]
property list<real> lightOpacities: [0.34, 0.34, 0.08, 0.2]
property real maxRotSpeed: 12
property real maxSize: 124
property real maxSpeed: 18
property real minRotSpeed: -12
property real minSize: 36
property real minSpeed: 4
readonly property list<int> shapePool: [MaterialShape.Circle, MaterialShape.Cookie4Sided, MaterialShape.Cookie6Sided, MaterialShape.Cookie7Sided, MaterialShape.Cookie9Sided, MaterialShape.Cookie12Sided, MaterialShape.Sunny, MaterialShape.VerySunny, MaterialShape.SoftBurst, MaterialShape.Pentagon, MaterialShape.Gem, MaterialShape.Arch, MaterialShape.Arrow, MaterialShape.Pill, MaterialShape.Triangle, MaterialShape.Fan, MaterialShape.Oval]
function rand(min: real, max: real): real {
return min + Math.random() * (max - min);
}
function signedRand(min: real, max: real): real {
return rand(min, max) * (Math.random() < 0.5 ? -1 : 1);
}
Component.onCompleted: shapes.model = count
Repeater {
id: shapes
DriftingShape {
}
}
FrameAnimation {
running: root.visible && root.width > 0 && root.height > 0 && (Players.active?.isPlaying ?? false)
onTriggered: {
const dt = frameTime;
for (let i = 0; i < shapes.count; i++) {
const s = shapes.itemAt(i) as DriftingShape;
if (!s)
continue;
s.x += s.vx * dt;
s.y += s.vy * dt;
s.rotation += s.vr * dt;
if (s.x + s.width < 0)
s.x = root.width;
else if (s.x > root.width)
s.x = -s.width;
if (s.y + s.height < 0)
s.y = root.height;
else if (s.y > root.height)
s.y = -s.height;
}
}
}
component DriftingShape: MaterialShape {
id: shapeItem
readonly property int colorIdx: Math.floor(Math.random() * 4)
required property int index
property real vr: root.rand(root.minRotSpeed, root.maxRotSpeed)
property real vx: root.signedRand(root.minSpeed, root.maxSpeed)
property real vy: root.signedRand(root.minSpeed, root.maxSpeed)
color: [Colors.palette.m3primaryContainer, Colors.palette.m3secondaryContainer, Colors.palette.m3tertiaryContainer, Colors.palette.m3outlineVariant][colorIdx]
implicitSize: root.minSize + (index / root.count) * (root.maxSize - root.minSize)
opacity: Colors.light ? root.lightOpacities[colorIdx] : root.darkOpacities[colorIdx]
rotation: root.rand(0, 360)
shape: root.shapePool[Math.floor(Math.random() * root.shapePool.length)]
Behavior on color {
CAnim {
}
}
Behavior on opacity {
Anim {
type: Anim.SlowEffects
}
}
Component.onCompleted: {
x = root.rand(0, root.width - implicitSize);
y = root.rand(0, root.height - implicitSize);
}
}
}
-100
View File
@@ -1,100 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Effects
import M3Shapes
import qs.Helpers
import qs.Effects
import qs.Components
import qs.Services
Item {
id: root
property color fallbackColor: Colors.layer(Colors.palette.m3surfaceContainerHighest, 2)
property bool hadPrevious
readonly property alias shape: shape
layer.enabled: true
Behavior on fallbackColor {
CAnim {
}
}
layer.effect: MultiEffect {
blurMax: 1
shadowColor: Colors.palette.m3outline
shadowEnabled: true
shadowOpacity: 0.3
}
Item {
id: shapeWrapper
anchors.fill: parent
layer.enabled: true
opacity: root.fallbackColor.a
MaterialShape {
id: shape
color: Qt.alpha(root.fallbackColor, 1)
implicitSize: root.width
shape: MaterialShape.Cookie12Sided
Anim on rotation {
duration: 23500
easing.type: Easing.Linear
from: 360
loops: Animation.Infinite
paused: !Players.active?.isPlaying
running: true
to: 0
}
}
}
MaterialIcon {
anchors.centerIn: parent
animate: true
color: Colors.palette.m3onSurfaceVariant
grade: 200
opacity: image.status === Image.Null || image.status === Image.Error ? 1 : 0
text: image.status === Image.Error ? "broken_image" : "art_track"
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
}
Loader {
active: opacity > 0
anchors.centerIn: parent
asynchronous: true
opacity: image.status === Image.Loading ? 1 : 0
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
sourceComponent: LoadingIndicator {
color: Colors.palette.m3primaryContainer
implicitSize: root.width * 0.3
}
}
FadeImage {
id: image
anchors.fill: parent
layer.enabled: true
source: Players.getArtUrl(Players.active)
layer.effect: Mask {
maskSource: shapeWrapper
}
}
}
@@ -1,18 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import M3Shapes
import ZShell.Config
Item {
id: root
CoverArt {
id: cover
anchors.centerIn: parent
implicitHeight: Config.dashboard.sizes.mediaCoverArtSize
implicitWidth: Config.dashboard.sizes.mediaCoverArtSize
shape.shape: MaterialShape.Cookie9Sided
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: Tokens.padding.large
anchors.top: parent.top
spacing: Tokens.spacing.medium
spacing: Tokens.spacing.normal
Resource {
fgColor: Colors.palette.m3primary
+1 -1
View File
@@ -18,7 +18,7 @@ Row {
color: Colors.layer(Colors.palette.m3surfaceContainerHigh, 2)
implicitHeight: info.implicitHeight
implicitWidth: info.implicitHeight
radius: Tokens.rounding.small
radius: Tokens.rounding.smallest
MaterialIcon {
anchors.centerIn: parent
+1 -1
View File
@@ -27,7 +27,7 @@ Item {
id: info
anchors.left: icon.right
anchors.leftMargin: Tokens.spacing.largeIncreased
anchors.leftMargin: Tokens.spacing.large
anchors.verticalCenter: parent.verticalCenter
spacing: 8
+1 -1
View File
@@ -181,7 +181,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
color: "transparent"
implicitHeight: parent.height + 8 * 2
radius: Tokens.rounding.small
radius: Tokens.rounding.smallest
CustomRect {
id: stateLayer
@@ -32,7 +32,7 @@ Item {
y: root.menuY
color: Colors.tPalette.m3surface
radius: Tokens.rounding.medium
radius: Tokens.rounding.normal
implicitWidth: menuLayout.implicitWidth + padding * 2
implicitHeight: menuLayout.implicitHeight + padding * 2
@@ -48,13 +48,13 @@ Item {
CustomRect {
Layout.preferredWidth: 200
radius: popupBackground.radius - popupBackground.padding
implicitHeight: openTerminalRow.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: openTerminalRow.implicitHeight + Tokens.padding.small * 2
RowLayout {
id: openTerminalRow
spacing: 8
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.smaller
MaterialIcon { text: "terminal"; font.pointSize: 20 }
CustomText { text: "Open terminal"; Layout.fillWidth: true }
@@ -81,13 +81,13 @@ Item {
CustomRect {
Layout.fillWidth: true
radius: popupBackground.radius - popupBackground.padding
implicitHeight: settingsRow.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: settingsRow.implicitHeight + Tokens.padding.small * 2
RowLayout {
id: settingsRow
spacing: 8
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.smaller
MaterialIcon { text: "settings"; font.pointSize: 20 }
CustomText { text: "ZShell settings"; Layout.fillWidth: true }
@@ -115,13 +115,13 @@ Item {
CustomRect {
Layout.fillWidth: true
radius: popupBackground.radius - popupBackground.padding
implicitHeight: logoutRow.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: logoutRow.implicitHeight + Tokens.padding.small * 2
RowLayout {
id: logoutRow
spacing: 8
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.smaller
MaterialIcon { text: "logout"; font.pointSize: 20 }
CustomText { text: "Logout"; Layout.fillWidth: true }
@@ -148,13 +148,13 @@ Item {
// CustomRect {
// Layout.fillWidth: true
// radius: popupBackground.radius - popupBackground.padding
// implicitHeight: desktopIconsRow.implicitHeight + Tokens.padding.extraSmall * 2
// implicitHeight: desktopIconsRow.implicitHeight + Tokens.padding.small * 2
//
// RowLayout {
// id: desktopIconsRow
// spacing: 8
// anchors.fill: parent
// anchors.leftMargin: Tokens.padding.small
// anchors.leftMargin: Tokens.padding.smaller
//
// MaterialIcon { text: Config.options.background.showDesktopIcons ? "visibility_off" : "visibility"; font.pointSize: 20 }
// CustomText { text: Config.options.background.showDesktopIcons ? "Hide icons" : "Show icons"; Layout.fillWidth: true }
+12 -12
View File
@@ -43,13 +43,13 @@ Item {
CustomClippingRect {
id: popupBackground
readonly property real padding: Tokens.padding.extraSmall
readonly property real padding: Tokens.padding.small
color: Colors.tPalette.m3surface
implicitHeight: menuLayout.implicitHeight + padding * 2
implicitWidth: menuLayout.implicitWidth + padding * 2
opacity: contextMenu.visible ? 1 : 0
radius: Tokens.rounding.medium
radius: Tokens.rounding.normal
x: contextMenu.menuX
y: contextMenu.menuY
@@ -66,14 +66,14 @@ Item {
CustomRect {
Layout.preferredWidth: 160
implicitHeight: openRow.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: openRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding
RowLayout {
id: openRow
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.smaller
spacing: 8
MaterialIcon {
@@ -109,14 +109,14 @@ Item {
CustomRect {
Layout.fillWidth: true
implicitHeight: openWithRow.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: openWithRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding
RowLayout {
id: openWithRow
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.smaller
spacing: 8
MaterialIcon {
@@ -154,14 +154,14 @@ Item {
CustomRect {
Layout.fillWidth: true
implicitHeight: copyPathRow.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: copyPathRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding
RowLayout {
id: copyPathRow
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.smaller
spacing: 8
MaterialIcon {
@@ -187,7 +187,7 @@ Item {
CustomRect {
Layout.fillWidth: true
implicitHeight: renameRow.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: renameRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding
visible: contextMenu.targetPaths.length === 1
@@ -195,7 +195,7 @@ Item {
id: renameRow
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.smaller
spacing: 8
MaterialIcon {
@@ -229,14 +229,14 @@ Item {
CustomRect {
Layout.fillWidth: true
implicitHeight: deleteRow.implicitHeight + Tokens.padding.extraSmall * 2
implicitHeight: deleteRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding
RowLayout {
id: deleteRow
anchors.fill: parent
anchors.leftMargin: Tokens.padding.small
anchors.leftMargin: Tokens.padding.smaller
spacing: 8
MaterialIcon {
+2 -2
View File
@@ -205,7 +205,7 @@ Item {
anchors.margins: 4
color: "white"
opacity: root.iconsRoot.selectedIcons.includes(root.filePath) ? 0.2 : 0.0
radius: Tokens.rounding.small
radius: Tokens.rounding.smallest
Behavior on opacity {
Anim {
@@ -265,7 +265,7 @@ Item {
anchors.margins: 4
color: "white"
opacity: parent.containsMouse ? 0.1 : 0.0
radius: Tokens.rounding.small
radius: Tokens.rounding.smallest
Behavior on opacity {
Anim {
+4 -4
View File
@@ -22,10 +22,10 @@ Item {
property string draggedAppId: ""
property var draggedModelData: null
property bool dropAnimating: false
readonly property int padding: Tokens.padding.extraSmall
readonly property int padding: Tokens.padding.small
required property var panels
property var pendingCommitIds: []
readonly property int rounding: Tokens.rounding.largeIncreased
readonly property int rounding: Tokens.rounding.large
required property ShellScreen screen
required property PersistentProperties visibilities
property var visualIds: []
@@ -247,7 +247,7 @@ Item {
property bool enableAddAnimation: false
anchors.left: parent.left
anchors.margins: Tokens.padding.extraSmall
anchors.margins: Tokens.padding.small
anchors.top: parent.top
boundsBehavior: Flickable.StopAtBounds
height: Config.dock.height
@@ -255,7 +255,7 @@ Item {
interactive: !(root.dragActive || root.dropAnimating)
model: visualModel
orientation: ListView.Horizontal
spacing: Tokens.padding.small
spacing: Tokens.padding.smaller
add: Transition {
ParallelAnimation {
+1 -1
View File
@@ -23,7 +23,7 @@ CustomRect {
implicitHeight: Config.dock.height
implicitWidth: isSeparator ? 1 : implicitHeight
radius: Tokens.rounding.medium - Tokens.padding.extraSmall
radius: Tokens.rounding.normal - Tokens.padding.small
Loader {
active: !isSeparator
+2 -2
View File
@@ -5,9 +5,9 @@ import ZShell.Config
import qs.Services
CustomRect {
Layout.bottomMargin: dockRow.padding + Tokens.rounding.medium
Layout.bottomMargin: dockRow.padding + Tokens.rounding.normal
Layout.fillHeight: true
Layout.topMargin: dockRow.padding + Tokens.rounding.medium
Layout.topMargin: dockRow.padding + Tokens.rounding.normal
color: Colors.palette.m3outlineVariant
implicitWidth: 1
}
+2 -2
View File
@@ -12,7 +12,7 @@ Item {
property real offsetScale: shouldBeActive ? 0 : 1
required property var panels
required property ShellScreen screen
readonly property bool shouldBeActive: visibilities.dock && Config.dock.enable
readonly property bool shouldBeActive: visibilities.dock && Config.dock.enabled
required property PersistentProperties visibilities
anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
@@ -24,7 +24,7 @@ Item {
Behavior on offsetScale {
Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
}
}
+5 -5
View File
@@ -33,8 +33,8 @@ Item {
drawing.drawingState.penColor = Qt.hsva(huePicker.currentHue, saturationSlider.value, brightnessSlider.value, drawing.drawingState.penColor.a);
}
implicitHeight: column.height + Tokens.padding.small * 2
implicitWidth: huePicker.implicitWidth + Tokens.padding.small * 2
implicitHeight: column.height + Tokens.padding.larger * 2
implicitWidth: huePicker.implicitWidth + Tokens.padding.normal * 2
Component.onCompleted: syncFromPenColor()
@@ -97,7 +97,7 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
spacing: Tokens.spacing.medium
spacing: Tokens.spacing.normal
Repeater {
model: root.colors1
@@ -113,7 +113,7 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
spacing: Tokens.spacing.medium
spacing: Tokens.spacing.normal
Repeater {
model: root.colors2
@@ -172,7 +172,7 @@ Item {
}
IconButton {
anchors.margins: Tokens.padding.small
anchors.margins: Tokens.padding.normal
anchors.right: parent.right
anchors.top: parent.top
checked: root.wrapper.pinned
+2 -2
View File
@@ -49,13 +49,13 @@ Item {
Behavior on implicitWidth {
Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
}
}
Behavior on offsetScale {
Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
}
}
+33 -84
View File
@@ -1,36 +1,28 @@
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import ZShell.Config
import qs.Components
import qs.Services
import qs.Modules.Launcher.Items
import QtQuick
import qs.Modules.Launcher.Services
import qs.Modules.Launcher.Items
import qs.Components
import ZShell.Config
import qs.Services
CustomListView {
id: root
readonly property string displayState: stateForText(displayText)
property string displayText
readonly property string requestedState: stateForText(search.text)
required property SearchBar search
required property PersistentProperties visibilities
function resultsForText(text: string): var {
switch (stateForText(text)) {
case "actions":
return Actions.query(text);
case "calc":
return [0];
case "variant":
return SchemeVariants.query(text);
default:
return Apps.search(text);
}
}
function stateForText(text: string): string {
highlightFollowsCurrentItem: false
highlightRangeMode: ListView.ApplyRange
implicitHeight: (Config.launcher.sizes.itemHeight + spacing) * Math.min(Config.launcher.maxAppsShown, count) - spacing
orientation: Qt.Vertical
preferredHighlightBegin: 0
preferredHighlightEnd: height
spacing: Tokens.spacing.small
state: {
const text = search.text;
const prefix = Config.launcher.actionPrefix;
if (text.startsWith(prefix)) {
for (const action of ["calc", "scheme", "variant"])
@@ -42,20 +34,6 @@ CustomListView {
return "apps";
}
function syncDisplayText(): void {
if (visibilities.launcher && requestedState === displayState)
displayText = search.text;
}
highlightFollowsCurrentItem: false
highlightRangeMode: ListView.ApplyRange
implicitHeight: (Config.launcher.sizes.itemHeight + spacing) * Math.min(Config.launcher.maxAppsShown, count) - spacing
orientation: Qt.Vertical
preferredHighlightBegin: 0
preferredHighlightEnd: height
spacing: Tokens.spacing.small
state: visibilities.launcher ? requestedState : displayState
verticalLayoutDirection: ListView.BottomToTop
CustomScrollBar.vertical: CustomScrollBar {
@@ -66,21 +44,19 @@ CustomListView {
Anim {
from: 0
property: "opacity"
properties: "opacity,scale"
to: 1
type: Anim.DefaultEffects
}
}
addDisplaced: Transition {
Anim {
duration: Tokens.anim.durations.small
property: "y"
type: Anim.StandardSmall
}
Anim {
property: "opacity"
properties: "opacity,scale"
to: 1
type: Anim.DefaultEffects
}
}
displaced: Transition {
@@ -89,9 +65,8 @@ CustomListView {
}
Anim {
property: "opacity"
properties: "opacity,scale"
to: 1
type: Anim.DefaultEffects
}
}
highlight: CustomRect {
@@ -99,18 +74,18 @@ CustomListView {
implicitHeight: root.currentItem?.implicitHeight ?? 0
implicitWidth: root.width
opacity: 0.08
radius: Tokens.rounding.medium
radius: Tokens.rounding.smallest
y: root.currentItem?.y ?? 0
Behavior on y {
Anim {
duration: Tokens.anim.durations.small
easing: Tokens.anim.expressiveDefaultEffects
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
}
}
}
model: ScriptModel {
values: root.resultsForText(root.displayText)
id: model
onValuesChanged: root.currentIndex = 0
}
@@ -120,9 +95,8 @@ CustomListView {
}
Anim {
property: "opacity"
properties: "opacity,scale"
to: 1
type: Anim.DefaultEffects
}
}
remove: Transition {
@@ -130,9 +104,8 @@ CustomListView {
Anim {
from: 1
property: "opacity"
properties: "opacity,scale"
to: 0
type: Anim.DefaultEffects
}
}
states: [
@@ -140,6 +113,7 @@ CustomListView {
name: "apps"
PropertyChanges {
model.values: Apps.search(search.text)
root.delegate: appItem
}
},
@@ -147,6 +121,7 @@ CustomListView {
name: "actions"
PropertyChanges {
model.values: Actions.query(search.text)
root.delegate: actionItem
}
},
@@ -154,6 +129,7 @@ CustomListView {
name: "calc"
PropertyChanges {
model.values: [0]
root.delegate: calcItem
}
},
@@ -161,6 +137,7 @@ CustomListView {
name: "variant"
PropertyChanges {
model.values: SchemeVariants.query(search.text)
root.delegate: variantItem
}
}
@@ -170,7 +147,7 @@ CustomListView {
ParallelAnimation {
Anim {
duration: Tokens.anim.durations.small
easing: Tokens.anim.standardAccel
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
from: 1
property: "opacity"
target: root
@@ -179,7 +156,7 @@ CustomListView {
Anim {
duration: Tokens.anim.durations.small
easing: Tokens.anim.standardAccel
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
from: 1
property: "scale"
target: root
@@ -188,24 +165,14 @@ CustomListView {
}
PropertyAction {
property: "delegate"
target: root
value: null
}
ScriptAction {
script: root.displayText = root.search.text
}
PropertyAction {
property: "delegate"
target: root
properties: "values,delegate"
targets: [model, root]
}
ParallelAnimation {
Anim {
duration: Tokens.anim.durations.small
easing: Tokens.anim.standardDecel
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
from: 0
property: "opacity"
target: root
@@ -214,7 +181,7 @@ CustomListView {
Anim {
duration: Tokens.anim.durations.small
easing: Tokens.anim.standardDecel
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
from: 0.9
property: "scale"
target: root
@@ -230,8 +197,6 @@ CustomListView {
}
}
Component.onCompleted: displayText = search.text
Component {
id: appItem
@@ -263,20 +228,4 @@ CustomListView {
list: root
}
}
Connections {
function onTextChanged() {
root.syncDisplayText();
}
target: root.search
}
Connections {
function onLauncherChanged() {
root.syncDisplayText();
}
target: root.visibilities
}
}
-53
View File
@@ -1,53 +0,0 @@
import Quickshell
import QtQuick
import ZShell.Components
import ZShell.Config
import qs.Modules.Launcher.Items
import qs.Components
import qs.Helpers
CarouselView {
id: root
required property var panels
readonly property var screen: QsWindow.window?.screen
required property SearchBar search
readonly property var values: Wallpapers.query(root.search.text.split(" ").slice(1).join(" "))
required property var visibilities
currentIndex: {
const idx = Wallpapers.list.findIndex(w => w.path === Wallpapers.actualCurrent);
return idx >= 0 ? idx : 0;
}
delegateProperties: ({
visibilities: root.visibilities
})
focalWidth: Config.launcher.sizes.wallpaperWidth
glideDuration: 250
glideEasingType: Easing.OutCubic
implicitHeight: tileHeight + Tokens.spacing.small / 2 + Tokens.padding.large + Tokens.padding.small
itemSpacing: Tokens.spacing.small
maxWidth: {
if (!screen)
return 0;
const barMargins = Config.bar.border * 2;
let margins = Math.round(screen.width / 6);
if (visibilities.utilities || visibilities.sidebar)
margins = Config.sidebar.sizes.width;
return screen.width - (barMargins + margins) * 2 - Config.bar.rounding * 4;
}
minEdgeWidth: 56
model: values
tileHeight: focalWidth / 16 * 9
delegate: Component {
WallpaperTile {
}
}
Component.onDestruction: Wallpapers.stopPreview()
onCurrentItemChanged: {
if (currentItem)
Wallpapers.preview(currentItem.modelData.path);
}
}
+5 -5
View File
@@ -12,9 +12,9 @@ Item {
id: root
required property real maxHeight
readonly property int padding: Tokens.padding.largeIncreased / 4
readonly property int padding: Tokens.padding.small
required property var panels
readonly property int rounding: Tokens.rounding.largeIncreased
readonly property int rounding: Tokens.rounding.large
required property PersistentProperties visibilities
implicitHeight: search.height + listWrapper.height + padding * 2
@@ -49,9 +49,9 @@ Item {
anchors.left: parent.left
anchors.margins: root.padding
anchors.right: parent.right
bottomPadding: Tokens.padding.medium
bottomPadding: Tokens.padding.larger
placeholderText: qsTr("Type \"%1\" for commands").arg(Config.launcher.actionPrefix)
topPadding: Tokens.padding.medium
topPadding: Tokens.padding.larger
Component.onCompleted: forceActiveFocus()
Keys.onDownPressed: list.currentList?.decrementCurrentIndex()
@@ -79,7 +79,7 @@ Item {
if (currentItem) {
if (list.showWallpapers) {
if (Colors.scheme === "dynamic" && currentItem.modelData.path !== Wallpapers.actualCurrent)
Wallpapers.previewColorLock = true;
Wallpapers.previewColourLock = true;
Wallpapers.setWallpaper(currentItem.modelData.path);
root.visibilities.launcher = false;
} else if (text.startsWith(Config.launcher.actionPrefix)) {

Some files were not shown because too many files have changed in this diff Show More