Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a01c4b472
|
||
|
|
9271fa47bc
|
@@ -9,7 +9,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
static:
|
static:
|
||||||
runs-on: debian
|
runs-on: debian
|
||||||
container: node:26-trixie-slim
|
container: python:3.13-slim
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
verify:
|
verify:
|
||||||
if: always()
|
if: always()
|
||||||
runs-on: debian
|
runs-on: debian
|
||||||
container: node:26-trixie-slim
|
container: python:3.13-slim
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ CustomRect {
|
|||||||
property color activeOnColor
|
property color activeOnColor
|
||||||
property bool checked
|
property bool checked
|
||||||
property real checkedRadius: Tokens.rounding.medium
|
property real checkedRadius: Tokens.rounding.medium
|
||||||
property real defaultRadius: Math.min(width, height) / 2
|
property real defaultRadius: Tokens.rounding.large
|
||||||
property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1)
|
property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1)
|
||||||
property color disabledOnColor: Qt.alpha(Colors.palette.m3onSurface, 0.38)
|
property color disabledOnColor: Qt.alpha(Colors.palette.m3onSurface, 0.38)
|
||||||
property bool fillWidth
|
property bool fillWidth
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ BusyIndicator {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
bgColor: root.bgColor
|
bgColor: root.bgColor
|
||||||
fgColor: root.fgColor
|
fgColor: root.fgColor
|
||||||
hasEndIndicator: false
|
|
||||||
padding: root.padding
|
padding: root.padding
|
||||||
rotation: manager.rotation
|
rotation: manager.rotation
|
||||||
startAngle: manager.startFraction * 360
|
startAngle: manager.startFraction * 360
|
||||||
@@ -54,7 +53,6 @@ BusyIndicator {
|
|||||||
Anim {
|
Anim {
|
||||||
duration: manager.completeEndDuration * Tokens.anim.durations.scale
|
duration: manager.completeEndDuration * Tokens.anim.durations.scale
|
||||||
properties: "opacity,internalStrokeWidth"
|
properties: "opacity,internalStrokeWidth"
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,11 @@ Slider {
|
|||||||
|
|
||||||
property bool animateWave
|
property bool animateWave
|
||||||
property color bgColor: enabled ? Colors.palette.m3secondaryContainer : Qt.alpha(Colors.palette.m3onSurface, 0.1)
|
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 color fgColor: enabled ? Colors.palette.m3primary : Qt.alpha(Colors.palette.m3onSurface, 0.38)
|
||||||
property real filledWidth
|
property real filledWidth
|
||||||
property alias inset: inset
|
property alias inset: inset
|
||||||
property color insetColor: enabled ? (inset.attached ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onPrimary) : Colors.palette.m3onSurface
|
property color insetColor: enabled ? (inset.attached ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onPrimary) : Colors.palette.m3onSurface
|
||||||
property string insetIcon: ""
|
property string insetIcon: ""
|
||||||
property bool interactionOnMove: true
|
|
||||||
property real pos: visualPosition
|
property real pos: visualPosition
|
||||||
property int radius: Tokens.rounding.small
|
property int radius: Tokens.rounding.small
|
||||||
property int waveDuration: 1000
|
property int waveDuration: 1000
|
||||||
@@ -141,7 +139,7 @@ Slider {
|
|||||||
CAnim {
|
CAnim {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NumberAnimation on waveProgress {
|
Anim on waveProgress {
|
||||||
duration: root.waveDuration
|
duration: root.waveDuration
|
||||||
easing.type: Easing.Linear
|
easing.type: Easing.Linear
|
||||||
from: 0
|
from: 0
|
||||||
@@ -188,8 +186,7 @@ Slider {
|
|||||||
|
|
||||||
onPositionChanged: e => {
|
onPositionChanged: e => {
|
||||||
dragMovement = (e.x - pressStartX) / width;
|
dragMovement = (e.x - pressStartX) / width;
|
||||||
if (root.interactionOnMove)
|
root.interaction(posBinding.value);
|
||||||
root.interaction(posBinding.value);
|
|
||||||
}
|
}
|
||||||
onPressed: e => {
|
onPressed: e => {
|
||||||
widthBehavior.enabled = false;
|
widthBehavior.enabled = false;
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ TextFieldBase {
|
|||||||
property string leadingIcon
|
property string leadingIcon
|
||||||
readonly property int leadingOffset: leadingIcon ? leadingIconLoader.width + leadingIconLoader.anchors.leftMargin : 0
|
readonly property int leadingOffset: leadingIcon ? leadingIconLoader.width + leadingIconLoader.anchors.leftMargin : 0
|
||||||
property int radius: Tokens.rounding.small
|
property int radius: Tokens.rounding.small
|
||||||
property alias sLayer: stateLayer
|
|
||||||
readonly property real smallFontScale: smallFontSize / font.pointSize
|
readonly property real smallFontScale: smallFontSize / font.pointSize
|
||||||
property int smallFontSize: Tokens.font.size.small
|
property int smallFontSize: Tokens.font.size.small
|
||||||
property string supportingText
|
property string supportingText
|
||||||
@@ -146,7 +145,6 @@ TextFieldBase {
|
|||||||
|
|
||||||
sourceComponent: MaterialIcon {
|
sourceComponent: MaterialIcon {
|
||||||
color: Colors.palette.m3onSurfaceVariant
|
color: Colors.palette.m3onSurfaceVariant
|
||||||
font.pointSize: Tokens.font.size.larger
|
|
||||||
text: root.leadingIcon
|
text: root.leadingIcon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+130
-148
@@ -18,14 +18,13 @@ Item {
|
|||||||
property real leftFadeStrength: overflowing && leftFadeEnabled ? fadeStrengthMoving : fadeStrengthIdle
|
property real leftFadeStrength: overflowing && leftFadeEnabled ? fadeStrengthMoving : fadeStrengthIdle
|
||||||
property int leftFadeWidth: 28
|
property int leftFadeWidth: 28
|
||||||
property bool marqueeEnabled: true
|
property bool marqueeEnabled: true
|
||||||
readonly property bool overflowing: metrics.width > content.width
|
readonly property bool overflowing: metrics.width > root.width
|
||||||
property int pauseMs: 1200
|
property int pauseMs: 1200
|
||||||
property real pixelsPerSecond: 40
|
property real pixelsPerSecond: 40
|
||||||
property real rightFadeStrength: overflowing ? fadeStrengthMoving : fadeStrengthIdle
|
property real rightFadeStrength: overflowing ? fadeStrengthMoving : fadeStrengthIdle
|
||||||
property int rightFadeWidth: 28
|
property int rightFadeWidth: 28
|
||||||
property bool sliding: false
|
property bool sliding: false
|
||||||
property alias text: elideText.text
|
property alias text: elideText.text
|
||||||
property bool vertical: false
|
|
||||||
|
|
||||||
function durationForDistance(px): int {
|
function durationForDistance(px): int {
|
||||||
return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000));
|
return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000));
|
||||||
@@ -42,9 +41,8 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clip: false
|
clip: true
|
||||||
implicitHeight: vertical ? elideText.implicitWidth : elideText.implicitHeight
|
implicitHeight: elideText.implicitHeight
|
||||||
implicitWidth: vertical ? elideText.implicitHeight : elideText.implicitWidth
|
|
||||||
|
|
||||||
Behavior on leftFadeStrength {
|
Behavior on leftFadeStrength {
|
||||||
Anim {
|
Anim {
|
||||||
@@ -55,187 +53,171 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onHeightChanged: resetMarquee()
|
|
||||||
onTextChanged: resetMarquee()
|
onTextChanged: resetMarquee()
|
||||||
onVerticalChanged: resetMarquee()
|
|
||||||
onVisibleChanged: if (!visible)
|
onVisibleChanged: if (!visible)
|
||||||
resetMarquee()
|
resetMarquee()
|
||||||
onWidthChanged: resetMarquee()
|
onWidthChanged: resetMarquee()
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: metrics
|
||||||
|
|
||||||
|
font: elideText.font
|
||||||
|
text: elideText.text
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: elideText
|
||||||
|
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
animate: root.animate
|
||||||
|
animateProp: "scale,opacity"
|
||||||
|
color: root.color
|
||||||
|
elide: Text.ElideNone
|
||||||
|
visible: !root.overflowing
|
||||||
|
width: root.width
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: content
|
id: marqueeViewport
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.fill: parent
|
||||||
height: root.vertical ? root.width : root.height
|
clip: true
|
||||||
width: root.vertical ? root.height : root.width
|
layer.enabled: true
|
||||||
|
visible: root.overflowing
|
||||||
|
|
||||||
transform: Rotation {
|
layer.effect: OpacityMask {
|
||||||
angle: root.vertical ? -90 : 0
|
maskSource: rightFadeMask
|
||||||
origin.x: content.width / 2
|
|
||||||
origin.y: content.height / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
TextMetrics {
|
|
||||||
id: metrics
|
|
||||||
|
|
||||||
font: elideText.font
|
|
||||||
text: elideText.text
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
id: elideText
|
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
animate: root.animate
|
|
||||||
animateProp: "scale,opacity"
|
|
||||||
color: root.color
|
|
||||||
elide: Text.ElideNone
|
|
||||||
visible: !root.overflowing
|
|
||||||
width: content.width
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: marqueeViewport
|
id: strip
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
clip: false
|
height: t1.implicitHeight
|
||||||
layer.enabled: true
|
width: t1.width + root.gap + t2.width
|
||||||
visible: root.overflowing
|
x: 0
|
||||||
|
|
||||||
layer.effect: OpacityMask {
|
CustomText {
|
||||||
maskSource: rightFadeMask
|
id: t1
|
||||||
|
|
||||||
|
animate: root.animate
|
||||||
|
animateProp: "opacity"
|
||||||
|
color: root.color
|
||||||
|
font.pointSize: elideText.font.pointSize
|
||||||
|
text: elideText.text
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
CustomText {
|
||||||
id: strip
|
id: t2
|
||||||
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
animate: root.animate
|
||||||
height: t1.implicitHeight
|
animateProp: "opacity"
|
||||||
width: t1.width + root.gap + t2.width
|
color: root.color
|
||||||
x: 0
|
font.pointSize: elideText.font.pointSize
|
||||||
|
text: t1.text
|
||||||
|
x: t1.width + root.gap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CustomText {
|
SequentialAnimation {
|
||||||
id: t1
|
id: marqueeAnim
|
||||||
|
|
||||||
animate: root.animate
|
running: false
|
||||||
animateProp: "opacity"
|
|
||||||
color: root.color
|
|
||||||
font.pointSize: elideText.font.pointSize
|
|
||||||
text: elideText.text
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
onFinished: pauseTimer.restart()
|
||||||
id: t2
|
|
||||||
|
|
||||||
animate: root.animate
|
ScriptAction {
|
||||||
animateProp: "opacity"
|
script: {
|
||||||
color: root.color
|
root.sliding = true;
|
||||||
font.pointSize: elideText.font.pointSize
|
root.leftFadeEnabled = true;
|
||||||
text: t1.text
|
|
||||||
x: t1.width + root.gap
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SequentialAnimation {
|
Anim {
|
||||||
id: marqueeAnim
|
duration: root.durationForDistance(t1.width)
|
||||||
|
easing.bezierCurve: Easing.Linear
|
||||||
|
easing.type: Easing.Linear
|
||||||
|
from: 0
|
||||||
|
property: "x"
|
||||||
|
target: strip
|
||||||
|
to: -t1.width
|
||||||
|
}
|
||||||
|
|
||||||
running: false
|
ScriptAction {
|
||||||
|
script: {
|
||||||
onFinished: pauseTimer.restart()
|
root.leftFadeEnabled = false;
|
||||||
|
|
||||||
ScriptAction {
|
|
||||||
script: {
|
|
||||||
root.sliding = true;
|
|
||||||
root.leftFadeEnabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
duration: root.durationForDistance(t1.width)
|
|
||||||
easing.bezierCurve: Easing.Linear
|
|
||||||
easing.type: Easing.Linear
|
|
||||||
from: 0
|
|
||||||
property: "x"
|
|
||||||
target: strip
|
|
||||||
to: -t1.width
|
|
||||||
}
|
|
||||||
|
|
||||||
ScriptAction {
|
|
||||||
script: {
|
|
||||||
root.leftFadeEnabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
duration: root.durationForDistance(root.gap)
|
|
||||||
easing.bezierCurve: Easing.Linear
|
|
||||||
easing.type: Easing.Linear
|
|
||||||
from: -t1.width
|
|
||||||
property: "x"
|
|
||||||
target: strip
|
|
||||||
to: -(t1.width + root.gap)
|
|
||||||
}
|
|
||||||
|
|
||||||
ScriptAction {
|
|
||||||
script: {
|
|
||||||
root.sliding = false;
|
|
||||||
strip.x = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Anim {
|
||||||
id: pauseTimer
|
duration: root.durationForDistance(root.gap)
|
||||||
|
easing.bezierCurve: Easing.Linear
|
||||||
|
easing.type: Easing.Linear
|
||||||
|
from: -t1.width
|
||||||
|
property: "x"
|
||||||
|
target: strip
|
||||||
|
to: -(t1.width + root.gap)
|
||||||
|
}
|
||||||
|
|
||||||
interval: root.pauseMs
|
ScriptAction {
|
||||||
repeat: false
|
script: {
|
||||||
running: true
|
root.sliding = false;
|
||||||
|
strip.x = 0;
|
||||||
onTriggered: {
|
|
||||||
if (root.marqueeEnabled)
|
|
||||||
marqueeAnim.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Timer {
|
||||||
id: rightFadeMask
|
id: pauseTimer
|
||||||
|
|
||||||
readonly property real fadeStartPos: {
|
interval: root.pauseMs
|
||||||
const w = Math.max(1, width);
|
repeat: false
|
||||||
return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w));
|
running: true
|
||||||
|
|
||||||
|
onTriggered: {
|
||||||
|
if (root.marqueeEnabled)
|
||||||
|
marqueeAnim.start();
|
||||||
}
|
}
|
||||||
readonly property real leftFadeEndPos: {
|
}
|
||||||
const w = Math.max(1, width);
|
}
|
||||||
return Math.max(0, Math.min(1, root.leftFadeWidth / w));
|
|
||||||
|
Rectangle {
|
||||||
|
id: rightFadeMask
|
||||||
|
|
||||||
|
readonly property real fadeStartPos: {
|
||||||
|
const w = Math.max(1, width);
|
||||||
|
return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w));
|
||||||
|
}
|
||||||
|
readonly property real leftFadeEndPos: {
|
||||||
|
const w = Math.max(1, width);
|
||||||
|
return Math.max(0, Math.min(1, root.leftFadeWidth / w));
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors.fill: marqueeViewport
|
||||||
|
layer.enabled: true
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
orientation: Gradient.Horizontal
|
||||||
|
|
||||||
|
GradientStop {
|
||||||
|
color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength)
|
||||||
|
position: 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors.fill: marqueeViewport
|
GradientStop {
|
||||||
layer.enabled: true
|
color: Qt.rgba(1, 1, 1, 1.0)
|
||||||
visible: false
|
position: rightFadeMask.leftFadeEndPos
|
||||||
|
}
|
||||||
|
|
||||||
gradient: Gradient {
|
GradientStop {
|
||||||
orientation: Gradient.Horizontal
|
color: Qt.rgba(1, 1, 1, 1.0)
|
||||||
|
position: rightFadeMask.fadeStartPos
|
||||||
|
}
|
||||||
|
|
||||||
GradientStop {
|
GradientStop {
|
||||||
color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength)
|
color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength)
|
||||||
position: 0.0
|
position: 1.0
|
||||||
}
|
|
||||||
|
|
||||||
GradientStop {
|
|
||||||
color: Qt.rgba(1, 1, 1, 1.0)
|
|
||||||
position: rightFadeMask.leftFadeEndPos
|
|
||||||
}
|
|
||||||
|
|
||||||
GradientStop {
|
|
||||||
color: Qt.rgba(1, 1, 1, 1.0)
|
|
||||||
position: rightFadeMask.fadeStartPos
|
|
||||||
}
|
|
||||||
|
|
||||||
GradientStop {
|
|
||||||
color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength)
|
|
||||||
position: 1.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -126,7 +126,7 @@ MouseArea {
|
|||||||
CustomRect {
|
CustomRect {
|
||||||
id: item
|
id: item
|
||||||
|
|
||||||
readonly property bool active: modelData === root?.active
|
readonly property bool active: modelData === root.active
|
||||||
required property int index
|
required property int index
|
||||||
required property MenuItem modelData
|
required property MenuItem modelData
|
||||||
|
|
||||||
@@ -163,19 +163,19 @@ MouseArea {
|
|||||||
MaterialIcon {
|
MaterialIcon {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurfaceVariant
|
color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurfaceVariant
|
||||||
text: item.modelData?.icon ?? ""
|
text: item.modelData.icon
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomText {
|
CustomText {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurface
|
color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurface
|
||||||
text: item.modelData?.text ?? ""
|
text: item.modelData.text
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
active: item.modelData?.trailingIcon.length > 0
|
active: item.modelData.trailingIcon.length > 0
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
visible: active
|
visible: active
|
||||||
|
|
||||||
|
|||||||
+2
-33
@@ -11,46 +11,15 @@ Variants {
|
|||||||
|
|
||||||
required property ShellScreen modelData
|
required property ShellScreen modelData
|
||||||
|
|
||||||
function rebuild(): void {
|
|
||||||
loader.active = false;
|
|
||||||
loader.active = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
LazyLoader {
|
|
||||||
id: loader
|
|
||||||
|
|
||||||
active: true
|
|
||||||
|
|
||||||
Drawer {
|
|
||||||
screen: scope.modelData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
function onConfigPositionChanged(): void {
|
|
||||||
Qt.callLater(scope.rebuild);
|
|
||||||
}
|
|
||||||
|
|
||||||
target: (loader.item as Drawer)?.geometry ?? null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component Drawer: Scope {
|
|
||||||
id: drawer
|
|
||||||
|
|
||||||
readonly property alias geometry: content.geometry
|
|
||||||
required property ShellScreen screen
|
|
||||||
|
|
||||||
Exclusions {
|
Exclusions {
|
||||||
bar: content.bar
|
bar: content.bar
|
||||||
geometry: content.geometry
|
screen: scope.modelData
|
||||||
screen: drawer.screen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Windows {
|
Windows {
|
||||||
id: content
|
id: content
|
||||||
|
|
||||||
screen: drawer.screen
|
screen: scope.modelData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import qs.Modules.Bar as Bar
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
required property Bar.BarLoader bar
|
|
||||||
readonly property real barClamped: bar.clampedExtent
|
|
||||||
readonly property real barExtent: bar.extent
|
|
||||||
readonly property bool barOnBottom: position === "bottom"
|
|
||||||
readonly property bool barOnLeft: position === "left"
|
|
||||||
readonly property bool barOnTop: position === "top"
|
|
||||||
required property string configPosition
|
|
||||||
readonly property bool horizontal: position !== "left"
|
|
||||||
readonly property string position: configPosition === "top" || configPosition === "bottom" ? configPosition : "left"
|
|
||||||
required property var win
|
|
||||||
|
|
||||||
function axisPos(x: real, y: real): real {
|
|
||||||
return horizontal ? x : y;
|
|
||||||
}
|
|
||||||
|
|
||||||
function barContains(x: real, y: real, clamped = false): bool {
|
|
||||||
const extent = clamped ? barClamped : barExtent;
|
|
||||||
if (barOnTop)
|
|
||||||
return y < extent;
|
|
||||||
if (barOnBottom)
|
|
||||||
return y > win.height - extent;
|
|
||||||
return x < extent;
|
|
||||||
}
|
|
||||||
|
|
||||||
function insetBottom(border: real, clamped = false): real {
|
|
||||||
return barOnBottom ? (clamped ? barClamped : barExtent) : border;
|
|
||||||
}
|
|
||||||
|
|
||||||
function insetLeft(border: real, clamped = false): real {
|
|
||||||
return barOnLeft ? (clamped ? barClamped : barExtent) : border;
|
|
||||||
}
|
|
||||||
|
|
||||||
function insetTop(border: real, clamped = false): real {
|
|
||||||
return barOnTop ? (clamped ? barClamped : barExtent) : border;
|
|
||||||
}
|
|
||||||
|
|
||||||
function inwardDrag(dragX: real, dragY: real): real {
|
|
||||||
if (barOnTop)
|
|
||||||
return dragY;
|
|
||||||
if (barOnBottom)
|
|
||||||
return -dragY;
|
|
||||||
return dragX;
|
|
||||||
}
|
|
||||||
|
|
||||||
onConfigPositionChanged: {
|
|
||||||
if (!["left", "top", "bottom"].includes(configPosition))
|
|
||||||
console.warn(`Invalid bar position '${configPosition}', falling back to left`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-11
@@ -1,7 +1,6 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Components
|
import qs.Components
|
||||||
@@ -10,24 +9,19 @@ Scope {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property Item bar
|
required property Item bar
|
||||||
required property EdgeGeometry geometry
|
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
|
|
||||||
ExclusionZone {
|
ExclusionZone {
|
||||||
id: top
|
id: top
|
||||||
|
|
||||||
WlrLayershell.layer: WlrLayer.Overlay
|
|
||||||
anchors.left: true
|
|
||||||
anchors.right: true
|
|
||||||
anchors.top: true
|
anchors.top: true
|
||||||
hasBar: root.geometry.barOnTop
|
exclusiveZone: root.bar.exclusiveZone
|
||||||
}
|
}
|
||||||
|
|
||||||
ExclusionZone {
|
ExclusionZone {
|
||||||
id: left
|
id: left
|
||||||
|
|
||||||
anchors.left: true
|
anchors.left: true
|
||||||
hasBar: root.geometry.barOnLeft
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExclusionZone {
|
ExclusionZone {
|
||||||
@@ -40,7 +34,6 @@ Scope {
|
|||||||
id: bottom
|
id: bottom
|
||||||
|
|
||||||
anchors.bottom: true
|
anchors.bottom: true
|
||||||
hasBar: root.geometry.barOnBottom
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
@@ -51,9 +44,7 @@ Scope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
component ExclusionZone: CustomWindow {
|
component ExclusionZone: CustomWindow {
|
||||||
property bool hasBar
|
exclusiveZone: Config.bar.border
|
||||||
|
|
||||||
exclusiveZone: hasBar ? root.bar.exclusiveZone : Config.bar.border
|
|
||||||
implicitHeight: 1
|
implicitHeight: 1
|
||||||
implicitWidth: 1
|
implicitWidth: 1
|
||||||
name: "Bar-Exclusion"
|
name: "Bar-Exclusion"
|
||||||
|
|||||||
+24
-42
@@ -3,7 +3,7 @@ import QtQuick
|
|||||||
import qs.Components
|
import qs.Components
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
import qs.Modules.Bar.Popouts
|
import qs.Modules as BarPopouts
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -12,47 +12,43 @@ Item {
|
|||||||
required property real borderThickness
|
required property real borderThickness
|
||||||
property bool dashboardShortcutActive
|
property bool dashboardShortcutActive
|
||||||
required property Drawing drawing
|
required property Drawing drawing
|
||||||
required property EdgeGeometry geometry
|
|
||||||
property bool osdShortcutActive
|
property bool osdShortcutActive
|
||||||
required property Panels panels
|
required property Panels panels
|
||||||
required property Wrapper popouts
|
required property BarPopouts.Wrapper popouts
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
property bool singleGestureTriggered: false
|
property bool singleGestureTriggered: false
|
||||||
property bool utilitiesShortcutActive
|
property bool utilitiesShortcutActive
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
function inBottomPanel(panel: Item, x: real, y: real): bool {
|
function inBottomPanel(panel: Item, x: real, y: real): bool {
|
||||||
const panelHeight = panel.height * (1 - (panel.offsetScale ?? 0));
|
return y > root.height - panel.height - Config.bar.border && withinPanelWidth(panel, x, y);
|
||||||
return y > root.height - (panelHeight + geometry.insetBottom(borderThickness)) && withinPanelWidth(panel, x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function inLeftPanel(panel: Item, x: real, y: real): bool {
|
function inLeftPanel(panel: Item, x: real, y: real): bool {
|
||||||
return x < panel.x + panel.width + geometry.insetLeft(borderThickness) && withinPanelHeight(panel, x, y);
|
return x < panel.x + panel.width + Config.bar.border && withinPanelHeight(panel, x, y);
|
||||||
}
|
|
||||||
|
|
||||||
function inPopoutArea(x: real, y: real): bool {
|
|
||||||
const panel = panels.popoutsWrapper;
|
|
||||||
if (!geometry.horizontal)
|
|
||||||
return inLeftPanel(panel, x, y);
|
|
||||||
return withinPanelWidth(panel, x, y) && withinPanelHeight(panel, x, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function inRightPanel(panel: Item, x: real, y: real): bool {
|
function inRightPanel(panel: Item, x: real, y: real): bool {
|
||||||
return x > panel.x + geometry.insetLeft(borderThickness) && withinPanelHeight(panel, x, y);
|
return x > panel.x - Config.bar.border && withinPanelHeight(panel, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
function inTopPanel(panel: Item, x: real, y: real): bool {
|
function inTopPanel(panel: Item, x: real, y: real): bool {
|
||||||
const panelHeight = panel.height * (1 - (panel.offsetScale ?? 0));
|
return y < bar.implicitHeight + panel.height && withinPanelWidth(panel, x, y);
|
||||||
return y < geometry.insetTop(borderThickness) + panelHeight && withinPanelWidth(panel, x, y);
|
}
|
||||||
|
|
||||||
|
function onWheel(event: WheelEvent): void {
|
||||||
|
if (event.x < bar.implicitWidth) {
|
||||||
|
bar.handleWheel(event.y, event.angleDelta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function withinPanelHeight(panel: Item, x: real, y: real): bool {
|
function withinPanelHeight(panel: Item, x: real, y: real): bool {
|
||||||
const panelY = panel.y + geometry.insetTop(borderThickness);
|
const panelY = panel.y + bar.implicitHeight;
|
||||||
return y >= panelY && y <= panelY + panel.height;
|
return y >= panelY && y <= panelY + panel.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
function withinPanelWidth(panel: Item, x: real, y: real): bool {
|
function withinPanelWidth(panel: Item, x: real, y: real): bool {
|
||||||
const panelX = panel.x + geometry.insetLeft(borderThickness);
|
const panelX = panel.x + root.borderThickness;
|
||||||
return x >= panelX && x <= panelX + panel.width;
|
return x >= panelX && x <= panelX + panel.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +81,7 @@ Item {
|
|||||||
if (root.singleGestureTriggered)
|
if (root.singleGestureTriggered)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (root.geometry.insetTop(root.borderThickness) > centroid.pressPosition.y) {
|
if (centroid.pressPosition.y < root.bar.implicitHeight) {
|
||||||
if (dragY > 20) {
|
if (dragY > 20) {
|
||||||
root.visibilities.settings = true;
|
root.visibilities.settings = true;
|
||||||
root.singleGestureTriggered = true;
|
root.singleGestureTriggered = true;
|
||||||
@@ -95,10 +91,10 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (centroid.pressPosition.y > root.screen.height - root.geometry.insetBottom(root.borderThickness) && centroid.pressPosition.x < root.screen.width / 5 && dragY < -50)
|
if (centroid.pressPosition.y > root.screen.height - Config.bar.border && centroid.pressPosition.x < root.screen.width / 5 && dragY < -50)
|
||||||
root.visibilities.clipboard = true;
|
root.visibilities.clipboard = true;
|
||||||
|
|
||||||
if (!Config.dock.hoverToReveal && centroid.pressPosition.y > root.screen.height - root.geometry.insetTop(root.borderThickness) && centroid.pressPosition.x > root.screen.width / 5 && !root.visibilities.launcher)
|
if (!Config.dock.hoverToReveal && centroid.pressPosition.y > root.screen.height - root.bar.implicitHeight && centroid.pressPosition.x > root.screen.width / 5 && !root.visibilities.launcher)
|
||||||
if (dragY < -10) {
|
if (dragY < -10) {
|
||||||
root.visibilities.dock = true;
|
root.visibilities.dock = true;
|
||||||
root.singleGestureTriggered = true;
|
root.singleGestureTriggered = true;
|
||||||
@@ -162,19 +158,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: unhideTimer
|
|
||||||
|
|
||||||
interval: Config.bar.revealDelay
|
|
||||||
repeat: false
|
|
||||||
running: false
|
|
||||||
|
|
||||||
onTriggered: {
|
|
||||||
if (hoverHandler.hovered)
|
|
||||||
root.bar.isHovered = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
id: hoverHandler
|
id: hoverHandler
|
||||||
|
|
||||||
@@ -191,7 +174,7 @@ Item {
|
|||||||
root.popouts.hasCurrent = false;
|
root.popouts.hasCurrent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.bar.autoHide || root.bar.fullscreen)
|
if (Config.bar.autoHide)
|
||||||
root.bar.isHovered = false;
|
root.bar.isHovered = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,12 +193,9 @@ Item {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!root.visibilities.bar && Config.bar.autoHide && root.geometry.barContains(x, y, true))
|
if (!root.visibilities.bar && Config.bar.autoHide && y < root.bar.implicitHeight)
|
||||||
root.bar.isHovered = true;
|
root.bar.isHovered = true;
|
||||||
|
|
||||||
if (root.bar.fullscreen && !root.bar.isHovered)
|
|
||||||
unhideTimer.start();
|
|
||||||
|
|
||||||
if (root.panels.sidebar.offsetScale === 1) {
|
if (root.panels.sidebar.offsetScale === 1) {
|
||||||
const showOsd = root.inRightPanel(root.panels.osdWrapper, x, y);
|
const showOsd = root.inRightPanel(root.panels.osdWrapper, x, y);
|
||||||
|
|
||||||
@@ -236,11 +216,11 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.dock.enabled && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y))
|
if (Config.dock.enable && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y))
|
||||||
root.visibilities.dock = true;
|
root.visibilities.dock = true;
|
||||||
|
|
||||||
if (root.geometry.barContains(x, y))
|
if (y < root.bar.implicitHeight)
|
||||||
root.bar.checkPopout(root.geometry.axisPos(x, y));
|
root.bar.checkPopout(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,6 +298,8 @@ Item {
|
|||||||
root.visibilities.sidebar = false;
|
root.visibilities.sidebar = false;
|
||||||
root.panels.popouts.hasCurrent = false;
|
root.panels.popouts.hasCurrent = false;
|
||||||
root.visibilities.launcher = false;
|
root.visibilities.launcher = false;
|
||||||
|
} else {
|
||||||
|
Config.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-19
@@ -1,7 +1,7 @@
|
|||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Modules.Bar.Popouts as Popouts
|
import qs.Modules as Modules
|
||||||
import qs.Modules.Notifications as Notifications
|
import qs.Modules.Notifications as Notifications
|
||||||
import qs.Modules.Notifications.Sidebar as Sidebar
|
import qs.Modules.Notifications.Sidebar as Sidebar
|
||||||
import qs.Modules.Notifications.Sidebar.Utils as Utils
|
import qs.Modules.Notifications.Sidebar.Utils as Utils
|
||||||
@@ -27,7 +27,6 @@ Item {
|
|||||||
readonly property alias dock: dock
|
readonly property alias dock: dock
|
||||||
readonly property alias drawing: drawing
|
readonly property alias drawing: drawing
|
||||||
required property var drawingItem
|
required property var drawingItem
|
||||||
required property EdgeGeometry geometry
|
|
||||||
readonly property alias launcher: launcher
|
readonly property alias launcher: launcher
|
||||||
readonly property alias notifications: notifications
|
readonly property alias notifications: notifications
|
||||||
readonly property alias osd: osd
|
readonly property alias osd: osd
|
||||||
@@ -44,26 +43,24 @@ Item {
|
|||||||
readonly property alias utilities: utilities
|
readonly property alias utilities: utilities
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
anchors.bottomMargin: geometry.insetBottom(borderThickness)
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: geometry.insetLeft(borderThickness)
|
|
||||||
anchors.margins: borderThickness
|
anchors.margins: borderThickness
|
||||||
anchors.topMargin: geometry.insetTop(borderThickness)
|
anchors.topMargin: bar.implicitHeight
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: resourcesWrapper
|
id: resourcesWrapper
|
||||||
|
|
||||||
anchors.bottom: root.geometry.position === "bottom" ? parent.bottom : undefined
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: root.geometry.position !== "bottom" ? parent.top : undefined
|
anchors.top: parent.top
|
||||||
clip: true
|
clip: true
|
||||||
implicitHeight: root.geometry.horizontal ? resources.implicitHeight * (1 - resources.offsetScale) : resources.implicitHeight
|
implicitHeight: resources.implicitHeight * (1 - resources.offsetScale)
|
||||||
implicitWidth: root.geometry.horizontal ? resources.implicitWidth : resources.implicitWidth * (1 - resources.offsetScale)
|
implicitWidth: resources.implicitWidth
|
||||||
|
|
||||||
Resources.Wrapper {
|
Resources.Wrapper {
|
||||||
id: resources
|
id: resources
|
||||||
|
|
||||||
position: root.geometry.position
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,11 +96,11 @@ Item {
|
|||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
}
|
}
|
||||||
|
|
||||||
Popouts.ClipWrapper {
|
Modules.ClipWrapper {
|
||||||
id: popouts
|
id: popouts
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
borderThickness: root.borderThickness
|
borderThickness: root.borderThickness
|
||||||
position: root.geometry.position
|
|
||||||
screen: root.screen
|
screen: root.screen
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,13 +147,11 @@ Item {
|
|||||||
|
|
||||||
property real offsetScale: dashboard.shouldBeActive ? 0 : 1
|
property real offsetScale: dashboard.shouldBeActive ? 0 : 1
|
||||||
|
|
||||||
anchors.bottom: root.geometry.barOnLeft || root.geometry.barOnBottom ? parent.bottom : undefined
|
anchors.right: parent.right
|
||||||
anchors.left: root.geometry.barOnLeft ? parent.left : undefined
|
anchors.top: parent.top
|
||||||
anchors.right: root.geometry.barOnLeft ? undefined : parent.right
|
|
||||||
anchors.top: root.geometry.barOnBottom || root.geometry.barOnLeft ? undefined : parent.top
|
|
||||||
clip: true
|
clip: true
|
||||||
implicitHeight: root.geometry.horizontal ? dashboard.implicitHeight * (1 - offsetScale) : dashboard.implicitHeight
|
implicitHeight: dashboard.implicitHeight * (1 - offsetScale)
|
||||||
implicitWidth: root.geometry.horizontal ? dashboard.implicitWidth : dashboard.implicitWidth * (1 - offsetScale)
|
implicitWidth: dashboard.implicitWidth
|
||||||
|
|
||||||
Behavior on offsetScale {
|
Behavior on offsetScale {
|
||||||
Anim {
|
Anim {
|
||||||
@@ -168,8 +163,10 @@ Item {
|
|||||||
Dashboard.Wrapper {
|
Dashboard.Wrapper {
|
||||||
id: dashboard
|
id: dashboard
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: (-implicitHeight - 5) * offsetScale
|
||||||
offsetScale: dashboardWrapper.offsetScale
|
offsetScale: dashboardWrapper.offsetScale
|
||||||
position: root.geometry.position
|
|
||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-13
@@ -7,18 +7,17 @@ import qs.Modules.Bar as Bar
|
|||||||
Region {
|
Region {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
// required property Bar.BarLoader bar
|
required property Bar.BarLoader bar
|
||||||
readonly property real borderThickness: win.borderThickness
|
readonly property real borderThickness: win.borderThickness
|
||||||
required property EdgeGeometry geometry
|
|
||||||
readonly property alias menuPopoutRegion: menuPopoutRegion
|
readonly property alias menuPopoutRegion: menuPopoutRegion
|
||||||
required property Panels panels
|
required property Panels panels
|
||||||
required property var win
|
required property var win
|
||||||
|
|
||||||
height: win.height - geometry.insetTop(borderThickness, true) - geometry.insetBottom(borderThickness, true) - win.dragMaskPadding * 2
|
height: win.height - bar.implicitHeight - win.borderThickness - win.dragMaskPadding * 2
|
||||||
intersection: Intersection.Xor
|
intersection: Intersection.Xor
|
||||||
width: win.width - geometry.insetLeft(borderThickness, true) * 2 - win.dragMaskPadding * 2
|
width: win.width - win.borderThickness * 2 - win.dragMaskPadding * 2
|
||||||
x: geometry.insetLeft(borderThickness, true) + win.dragMaskPadding
|
x: win.borderThickness + win.dragMaskPadding
|
||||||
y: geometry.insetTop(borderThickness, true) + win.dragMaskPadding
|
y: bar.implicitHeight + win.dragMaskPadding
|
||||||
|
|
||||||
R {
|
R {
|
||||||
panel: root.panels.dashboardWrapper
|
panel: root.panels.dashboardWrapper
|
||||||
@@ -42,21 +41,17 @@ Region {
|
|||||||
}
|
}
|
||||||
|
|
||||||
R {
|
R {
|
||||||
height: panel.height + root.geometry.insetTop(root.borderThickness)
|
|
||||||
panel: root.panels.notifications
|
panel: root.panels.notifications
|
||||||
y: 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
R {
|
R {
|
||||||
height: panel.height * (1 - root.panels.utilities.offsetScale) + root.geometry.insetBottom(root.borderThickness)
|
height: panel.height * (1 - root.panels.utilities.offsetScale) + root.borderThickness
|
||||||
panel: root.panels.utilities
|
panel: root.panels.utilities
|
||||||
y: root.win.height - height
|
y: root.win.height - height
|
||||||
}
|
}
|
||||||
|
|
||||||
R {
|
R {
|
||||||
height: root.geometry.horizontal ? panel.height * (1 - root.panels.popoutsWrapper.offsetScale) : panel.height
|
|
||||||
panel: root.panels.popoutsWrapper
|
panel: root.panels.popoutsWrapper
|
||||||
width: root.geometry.horizontal ? panel.width : panel.width * (1 - root.panels.popoutsWrapper.offsetScale)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
R {
|
R {
|
||||||
@@ -87,7 +82,7 @@ Region {
|
|||||||
height: panel.height
|
height: panel.height
|
||||||
intersection: Intersection.Subtract
|
intersection: Intersection.Subtract
|
||||||
width: panel.width
|
width: panel.width
|
||||||
x: panel.x + root.geometry.insetLeft(root.borderThickness)
|
x: panel.x + root.borderThickness
|
||||||
y: panel.y + root.geometry.insetTop(root.borderThickness)
|
y: panel.y + root.bar.implicitHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-59
@@ -11,7 +11,6 @@ import ZShell.Blobs
|
|||||||
import qs.Daemons
|
import qs.Daemons
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Modules.Bar
|
import qs.Modules.Bar
|
||||||
import qs.Modules.Bar.Popouts.Network as N
|
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
import qs.Drawers
|
import qs.Drawers
|
||||||
@@ -34,7 +33,6 @@ CustomWindow {
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
property real fsTransitionProg: hasFullscreen ? 1 : 0
|
property real fsTransitionProg: hasFullscreen ? 1 : 0
|
||||||
readonly property alias geometry: geometry
|
|
||||||
readonly property bool hasFullscreen: {
|
readonly property bool hasFullscreen: {
|
||||||
if (hasSpecialWorkspace) {
|
if (hasSpecialWorkspace) {
|
||||||
const specialName = monitor?.lastIpcObject.specialWorkspace?.name;
|
const specialName = monitor?.lastIpcObject.specialWorkspace?.name;
|
||||||
@@ -52,7 +50,7 @@ CustomWindow {
|
|||||||
readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen)
|
readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen)
|
||||||
property var root: Quickshell.shellDir
|
property var root: Quickshell.shellDir
|
||||||
readonly property real sdfBorderOffset: 2 * fsTransitionProg
|
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
|
property color surfaceColor: Colors.tPalette.m3surface
|
||||||
|
|
||||||
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
WlrLayershell.exclusionMode: ExclusionMode.Ignore
|
||||||
@@ -60,7 +58,7 @@ CustomWindow {
|
|||||||
WlrLayershell.layer: (fsTransitionProg > 0 && Config.general.showOverFullscreen) || (hasSpecialWorkspace && hasFullscreenOnNormalWs) ? WlrLayer.Overlay : WlrLayer.Top
|
WlrLayershell.layer: (fsTransitionProg > 0 && Config.general.showOverFullscreen) || (hasSpecialWorkspace && hasFullscreenOnNormalWs) ? WlrLayer.Overlay : WlrLayer.Top
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
contentItem.focus: true
|
contentItem.focus: true
|
||||||
mask: visibilities.isDrawing ? null : (hasFullscreen && !bar.isHovered ? emptyRegion : regions)
|
mask: visibilities.isDrawing ? null : (hasFullscreen ? emptyRegion : regions)
|
||||||
name: "Bar"
|
name: "Bar"
|
||||||
|
|
||||||
Behavior on fsTransitionProg {
|
Behavior on fsTransitionProg {
|
||||||
@@ -97,21 +95,13 @@ CustomWindow {
|
|||||||
panels.popouts.hasCurrent = false;
|
panels.popouts.hasCurrent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeGeometry {
|
|
||||||
id: geometry
|
|
||||||
|
|
||||||
bar: bar
|
|
||||||
configPosition: Config.bar.position
|
|
||||||
win: root
|
|
||||||
}
|
|
||||||
|
|
||||||
Region {
|
Region {
|
||||||
id: emptyRegion
|
id: emptyRegion
|
||||||
|
|
||||||
height: panels.notifications.height
|
height: panels.notifications.height
|
||||||
width: panels.notifications.width
|
width: panels.notifications.width
|
||||||
x: panels.notifications.x + geometry.insetLeft(root.borderThickness)
|
x: panels.notifications.x + root.borderThickness
|
||||||
y: panels.notifications.y + geometry.insetTop(root.borderThickness)
|
y: panels.notifications.y + bar.implicitHeight
|
||||||
|
|
||||||
Region {
|
Region {
|
||||||
height: panels.osd.height
|
height: panels.osd.height
|
||||||
@@ -119,18 +109,12 @@ CustomWindow {
|
|||||||
x: root.width - width
|
x: root.width - width
|
||||||
y: panels.osdWrapper.y + bar.implicitHeight
|
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 {
|
Regions {
|
||||||
id: regions
|
id: regions
|
||||||
|
|
||||||
geometry: geometry
|
bar: bar
|
||||||
panels: panels
|
panels: panels
|
||||||
win: root
|
win: root
|
||||||
}
|
}
|
||||||
@@ -145,17 +129,7 @@ CustomWindow {
|
|||||||
HyprlandFocusGrab {
|
HyprlandFocusGrab {
|
||||||
id: focusGrab
|
id: focusGrab
|
||||||
|
|
||||||
active: {
|
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))
|
||||||
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]
|
windows: [root]
|
||||||
|
|
||||||
onCleared: {
|
onCleared: {
|
||||||
@@ -219,10 +193,10 @@ CustomWindow {
|
|||||||
BlobInvertedRect {
|
BlobInvertedRect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: -50
|
anchors.margins: -50
|
||||||
borderBottom: geometry.insetBottom(root.borderThickness) - anchors.margins - root.sdfBorderOffset
|
borderBottom: root.borderThickness - anchors.margins - root.sdfBorderOffset
|
||||||
borderLeft: geometry.insetLeft(root.borderThickness) - anchors.margins - root.sdfBorderOffset
|
borderLeft: root.borderThickness - anchors.margins - root.sdfBorderOffset
|
||||||
borderRight: root.borderThickness - anchors.margins - root.sdfBorderOffset
|
borderRight: root.borderThickness - anchors.margins - root.sdfBorderOffset
|
||||||
borderTop: geometry.insetTop(root.borderThickness) - anchors.margins - root.sdfBorderOffset
|
borderTop: bar.implicitHeight - anchors.margins - root.sdfBorderOffset
|
||||||
group: blobGroup
|
group: blobGroup
|
||||||
radius: root.borderRounding
|
radius: root.borderRounding
|
||||||
}
|
}
|
||||||
@@ -230,15 +204,15 @@ CustomWindow {
|
|||||||
PanelBg {
|
PanelBg {
|
||||||
id: dashBg
|
id: dashBg
|
||||||
|
|
||||||
property real extraExtent: 0.2
|
property real extraHeight: 0.2
|
||||||
|
|
||||||
deformAmount: 0.06
|
deformAmount: 0.06
|
||||||
implicitHeight: panels.dashboard.height * (geometry.horizontal ? 1 + extraExtent : 1)
|
implicitHeight: panels.dashboard.height * (1 + extraHeight)
|
||||||
implicitWidth: panels.dashboard.width * (geometry.horizontal ? 1 : 1 + extraExtent)
|
implicitWidth: panels.dashboard.width
|
||||||
panel: panels.dashboardWrapper
|
panel: panels.dashboardWrapper
|
||||||
radius: Tokens.rounding.normal
|
radius: Tokens.rounding.normal
|
||||||
x: panels.dashboardWrapper.x + panels.dashboard.x + geometry.insetLeft(root.borderThickness) - (geometry.horizontal ? 0 : panels.dashboard.width * extraExtent)
|
x: panels.dashboardWrapper.x + panels.dashboard.x + root.borderThickness
|
||||||
y: panels.dashboardWrapper.y + panels.dashboard.y + geometry.insetTop(root.borderThickness) - (geometry.horizontal && geometry.position !== "bottom" ? panels.dashboard.height * extraExtent : 0)
|
y: panels.dashboardWrapper.y + panels.dashboard.y + bar.implicitHeight - panels.dashboard.height * extraHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelBg {
|
PanelBg {
|
||||||
@@ -250,7 +224,7 @@ CustomWindow {
|
|||||||
implicitHeight: panels.launcher.height * (1 + extraHeight)
|
implicitHeight: panels.launcher.height * (1 + extraHeight)
|
||||||
panel: panels.launcher
|
panel: panels.launcher
|
||||||
radius: Tokens.rounding.smallest + 5
|
radius: Tokens.rounding.smallest + 5
|
||||||
y: panels.launcher.y + geometry.insetTop(root.borderThickness)
|
y: panels.launcher.y + bar.implicitHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelBg {
|
PanelBg {
|
||||||
@@ -271,7 +245,8 @@ CustomWindow {
|
|||||||
implicitWidth: panels.osd.width
|
implicitWidth: panels.osd.width
|
||||||
panel: panels.osdWrapper
|
panel: panels.osdWrapper
|
||||||
radius: 20
|
radius: 20
|
||||||
x: panels.osdWrapper.x + panels.osd.x + geometry.insetLeft(root.borderThickness)
|
x: panels.osdWrapper.x + panels.osd.x + root.borderThickness
|
||||||
|
y: panels.osdWrapper.y + panels.osd.y + bar.implicitHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelBg {
|
PanelBg {
|
||||||
@@ -293,17 +268,17 @@ CustomWindow {
|
|||||||
PanelBg {
|
PanelBg {
|
||||||
id: popoutBg
|
id: popoutBg
|
||||||
|
|
||||||
property real extraExtent: 0.2
|
property real extraHeight: 0.2
|
||||||
|
|
||||||
deformAmount: panels.popouts.currentName.startsWith("traymenu") ? 0.15 : 0.08
|
deformAmount: panels.popouts.currentName.startsWith("traymenu") ? 0.15 : 0.08
|
||||||
implicitHeight: panels.popouts.height * (geometry.horizontal ? 1 + extraExtent : 1)
|
implicitHeight: panels.popouts.height * (1 + extraHeight)
|
||||||
implicitWidth: panels.popouts.width * (geometry.horizontal ? 1 : 1 + extraExtent)
|
implicitWidth: panels.popouts.width
|
||||||
panel: panels.popoutsWrapper
|
panel: panels.popoutsWrapper
|
||||||
radius: panels.popouts.current?.panelRadius ?? Tokens.rounding.normal
|
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)
|
x: panels.popoutsWrapper.x + panels.popouts.x + root.borderThickness
|
||||||
y: panels.popoutsWrapper.y + panels.popouts.y + geometry.insetTop(root.borderThickness) - (geometry.barOnTop ? panels.popouts.height * extraExtent : 0)
|
y: panels.popoutsWrapper.y + panels.popouts.y + bar.implicitHeight - panels.popouts.height * extraHeight
|
||||||
|
|
||||||
Behavior on extraExtent {
|
Behavior on extraHeight {
|
||||||
Anim {
|
Anim {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,8 +292,8 @@ CustomWindow {
|
|||||||
implicitWidth: panels.resources.width
|
implicitWidth: panels.resources.width
|
||||||
panel: panels.resourcesWrapper
|
panel: panels.resourcesWrapper
|
||||||
radius: Tokens.rounding.large
|
radius: Tokens.rounding.large
|
||||||
x: panels.resourcesWrapper.x + panels.resources.x + geometry.insetLeft(root.borderThickness)
|
x: panels.resourcesWrapper.x + panels.resources.x + root.borderThickness
|
||||||
y: panels.resourcesWrapper.y + panels.resources.y + geometry.insetTop(root.borderThickness)
|
y: panels.resourcesWrapper.y + panels.resources.y + bar.implicitHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelBg {
|
PanelBg {
|
||||||
@@ -396,7 +371,6 @@ CustomWindow {
|
|||||||
borderThickness: root.borderLayoutThickness
|
borderThickness: root.borderLayoutThickness
|
||||||
drawing: drawing
|
drawing: drawing
|
||||||
enabled: true
|
enabled: true
|
||||||
geometry: geometry
|
|
||||||
panels: panels
|
panels: panels
|
||||||
popouts: panels.popouts
|
popouts: panels.popouts
|
||||||
screen: root.screen
|
screen: root.screen
|
||||||
@@ -408,7 +382,6 @@ CustomWindow {
|
|||||||
bar: bar
|
bar: bar
|
||||||
borderThickness: root.borderThickness
|
borderThickness: root.borderThickness
|
||||||
drawingItem: drawing
|
drawingItem: drawing
|
||||||
geometry: geometry
|
|
||||||
screen: root.screen
|
screen: root.screen
|
||||||
visibilities: visibilities
|
visibilities: visibilities
|
||||||
|
|
||||||
@@ -450,18 +423,14 @@ CustomWindow {
|
|||||||
BarLoader {
|
BarLoader {
|
||||||
id: bar
|
id: bar
|
||||||
|
|
||||||
anchors.bottom: geometry.barOnBottom ? parent.bottom : undefined
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: geometry.barOnBottom ? undefined : parent.top
|
anchors.right: parent.right
|
||||||
enabled: !visibilities.isDrawing
|
enabled: !visibilities.isDrawing
|
||||||
fullscreen: root.hasFullscreen
|
fullscreen: root.hasFullscreen
|
||||||
height: geometry.horizontal ? implicitHeight : parent.height
|
|
||||||
popouts: panels.popouts
|
popouts: panels.popouts
|
||||||
popoutsWrapper: panels.popoutsWrapper
|
popoutsWrapper: panels.popoutsWrapper
|
||||||
position: geometry.position
|
|
||||||
screen: root.screen
|
screen: root.screen
|
||||||
visibilities: visibilities
|
visibilities: visibilities
|
||||||
width: geometry.horizontal ? parent.width : implicitWidth
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,7 +443,7 @@ CustomWindow {
|
|||||||
implicitHeight: panel.height
|
implicitHeight: panel.height
|
||||||
implicitWidth: panel.width
|
implicitWidth: panel.width
|
||||||
radius: Tokens.rounding.smallest
|
radius: Tokens.rounding.smallest
|
||||||
x: panel.x + geometry.insetLeft(root.borderThickness)
|
x: panel.x + root.borderThickness
|
||||||
y: panel.y + geometry.insetTop(root.borderThickness)
|
y: panel.y + bar.implicitHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
@@ -10,6 +11,6 @@ TextInput {
|
|||||||
font {
|
font {
|
||||||
family: Config.appearance?.font.family.sans ?? "sans-serif"
|
family: Config.appearance?.font.family.sans ?? "sans-serif"
|
||||||
hintingPreference: Font.PreferFullHinting
|
hintingPreference: Font.PreferFullHinting
|
||||||
pixelSize: Tokens?.font.size.normal ?? 15
|
pixelSize: Config.appearance?.font.size.normal ?? 15
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-51
@@ -1,8 +1,9 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
import QtQuick
|
import ZShell.Config
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
@@ -77,6 +78,16 @@ Singleton {
|
|||||||
"99": "thunderstorm"
|
"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 {
|
function getAppIcon(name: string, fallback: string): string {
|
||||||
const icon = DesktopEntries.heuristicLookup(name)?.icon;
|
const icon = DesktopEntries.heuristicLookup(name)?.icon;
|
||||||
if (fallback !== "undefined")
|
if (fallback !== "undefined")
|
||||||
@@ -84,15 +95,6 @@ Singleton {
|
|||||||
return Quickshell.iconPath(icon);
|
return Quickshell.iconPath(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBatteryIcon(percentage: real, charging = false): string {
|
|
||||||
if (percentage === 1)
|
|
||||||
return charging ? "battery_charging_full" : "battery_full";
|
|
||||||
let level = Math.floor(percentage * 7);
|
|
||||||
if (charging && (level === 4 || level === 1))
|
|
||||||
level--;
|
|
||||||
return charging ? `battery_charging_${(level + 3) * 10}` : `battery_${level}_bar`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBluetoothIcon(icon: string): string {
|
function getBluetoothIcon(icon: string): string {
|
||||||
if (icon.includes("headset") || icon.includes("headphones"))
|
if (icon.includes("headset") || icon.includes("headphones"))
|
||||||
return "headphones";
|
return "headphones";
|
||||||
@@ -166,32 +168,6 @@ Singleton {
|
|||||||
return "chat";
|
return "chat";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSpecialWsIcon(name: string): string {
|
|
||||||
name = name.toLowerCase().slice("special:".length);
|
|
||||||
|
|
||||||
if (name === "special")
|
|
||||||
return "star";
|
|
||||||
if (name === "communication")
|
|
||||||
return "forum";
|
|
||||||
if (name === "music")
|
|
||||||
return "music_cast";
|
|
||||||
if (name === "todo")
|
|
||||||
return "checklist";
|
|
||||||
if (name === "sysmon")
|
|
||||||
return "monitor_heart";
|
|
||||||
return name[0].toUpperCase();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTrayIcon(id: string, icon: string): string {
|
|
||||||
if (icon.includes("?path=")) {
|
|
||||||
const [name, path] = icon.split("?path=");
|
|
||||||
const file = name.slice(name.lastIndexOf("/") + 1);
|
|
||||||
const themed = Quickshell.iconPath(file, true);
|
|
||||||
icon = themed ? themed : Qt.resolvedUrl(`${path}/${file}`);
|
|
||||||
}
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVolumeIcon(volume: real, isMuted: bool): string {
|
function getVolumeIcon(volume: real, isMuted: bool): string {
|
||||||
if (isMuted)
|
if (isMuted)
|
||||||
return "no_sound";
|
return "no_sound";
|
||||||
@@ -207,19 +183,4 @@ Singleton {
|
|||||||
return weatherIcons[code];
|
return weatherIcons[code];
|
||||||
return "air";
|
return "air";
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchIconConfig(name: string, iconConfig: var): bool {
|
|
||||||
if (!iconConfig.icon)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (iconConfig.regex) {
|
|
||||||
const re = new RegExp(iconConfig.regex, iconConfig.flags ?? "");
|
|
||||||
if (re.test(name))
|
|
||||||
return true;
|
|
||||||
} else if (iconConfig.name === name) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,114 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -73,6 +73,7 @@ Singleton {
|
|||||||
|
|
||||||
Config.dock.pinnedApps = pinnedApps;
|
Config.dock.pinnedApps = pinnedApps;
|
||||||
root.unpinnedOrder = visibleUnpinned.concat(root.unpinnedOrder.map(normalizeId).filter(id => !pinnedApps.includes(id) && !visibleUnpinned.includes(id)));
|
root.unpinnedOrder = visibleUnpinned.concat(root.unpinnedOrder.map(normalizeId).filter(id => !pinnedApps.includes(id) && !visibleUnpinned.includes(id)));
|
||||||
|
Config.saveNoToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPinned(appId) {
|
function isPinned(appId) {
|
||||||
|
|||||||
+41
-8
@@ -11,8 +11,8 @@ Singleton {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property int availableUpdates: 0
|
property int availableUpdates: 0
|
||||||
|
property string cmd: ""
|
||||||
property bool commandReady
|
property bool commandReady
|
||||||
property bool hasHelper
|
|
||||||
property bool loaded
|
property bool loaded
|
||||||
property double now: Date.now()
|
property double now: Date.now()
|
||||||
property var updates: ({})
|
property var updates: ({})
|
||||||
@@ -38,12 +38,18 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function performPackageUpdate(pkg: string): void {
|
function performPackageUpdate(pkg: string): void {
|
||||||
pkgUpdateProc.command = ["pkexec", "pacman", "--noconfirm", "-Sy", pkg];
|
if (root.cmd === "pacman")
|
||||||
|
pkgUpdateProc.command = ["pkexec", root.cmd, "--noconfirm", "-Sy", pkg];
|
||||||
|
else
|
||||||
|
pkgUpdateProc.command = [root.cmd, "--noconfirm", "--sudo", "pkexec", "-Sy", pkg];
|
||||||
pkgUpdateProc.running = true;
|
pkgUpdateProc.running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function performSystemUpdate(): void {
|
function performSystemUpdate(): void {
|
||||||
sysUpdateProc.command = ["pkexec", "pacman", "--noconfirm", "-Syu"];
|
if (root.cmd === "pacman")
|
||||||
|
sysUpdateProc.command = ["pkexec", root.cmd, "--noconfirm", "-Syu"];
|
||||||
|
else
|
||||||
|
sysUpdateProc.command = [root.cmd, "--noconfirm", "--sudo", "pkexec", "-Syu"];
|
||||||
sysUpdateProc.running = true;
|
sysUpdateProc.running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +87,7 @@ Singleton {
|
|||||||
Process {
|
Process {
|
||||||
id: cmdDetect
|
id: cmdDetect
|
||||||
|
|
||||||
command: ["sh", "-c", "command -v checkupdates"]
|
command: ["sh", "-c", "command -v checkupdates || command -v yay || command -v paru"]
|
||||||
running: true
|
running: true
|
||||||
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
@@ -90,20 +96,47 @@ Singleton {
|
|||||||
let helper;
|
let helper;
|
||||||
|
|
||||||
if (cmd.length > 0) {
|
if (cmd.length > 0) {
|
||||||
helper = true;
|
helper = cmd.split("/").pop();
|
||||||
} else {
|
} else {
|
||||||
helper = false;
|
helper = "pacman";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (helper === "checkupdates") {
|
||||||
|
updatesProc.command = [helper];
|
||||||
|
} else {
|
||||||
|
updatesProc.command = [helper, "-Qu"];
|
||||||
}
|
}
|
||||||
root.hasHelper = helper;
|
|
||||||
root.commandReady = true;
|
root.commandReady = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: updateCmdDetect
|
||||||
|
|
||||||
|
command: ["sh", "-c", "command -v yay || command -v paru"]
|
||||||
|
running: true
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
const cmd = this.text.trim();
|
||||||
|
let helper;
|
||||||
|
|
||||||
|
if (cmd.length > 0) {
|
||||||
|
helper = cmd.split("/").pop();
|
||||||
|
} else {
|
||||||
|
helper = "pacman";
|
||||||
|
}
|
||||||
|
|
||||||
|
root.cmd = helper;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: updatesProc
|
id: updatesProc
|
||||||
|
|
||||||
command: root.hasHelper ? ["checkupdates"] : []
|
command: []
|
||||||
running: false
|
running: false
|
||||||
|
|
||||||
stdout: StdioCollector {
|
stdout: StdioCollector {
|
||||||
|
|||||||
@@ -17,10 +17,7 @@ Singleton {
|
|||||||
watchChanges: true
|
watchChanges: true
|
||||||
|
|
||||||
onAdapterUpdated: writeAdapter()
|
onAdapterUpdated: writeAdapter()
|
||||||
onFileChanged: {
|
onFileChanged: reload()
|
||||||
reload();
|
|
||||||
Wallpapers.previewColorLock = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonAdapter {
|
JsonAdapter {
|
||||||
id: adapter
|
id: adapter
|
||||||
|
|||||||
+6
-28
@@ -6,7 +6,7 @@ import Quickshell.Io
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import ZShell.Models
|
import ZShell.Models
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Services
|
import qs.Modules
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
import qs.Paths
|
import qs.Paths
|
||||||
|
|
||||||
@@ -17,8 +17,6 @@ Searcher {
|
|||||||
property alias crops: adapter.monitorCrops
|
property alias crops: adapter.monitorCrops
|
||||||
readonly property string current: showPreview ? previewPath : actualCurrent
|
readonly property string current: showPreview ? previewPath : actualCurrent
|
||||||
property alias monitorCrops: monitorCrops
|
property alias monitorCrops: monitorCrops
|
||||||
property bool pendingPreviewClear
|
|
||||||
property bool previewColorLock
|
|
||||||
property string previewPath
|
property string previewPath
|
||||||
property bool recentlyChanged
|
property bool recentlyChanged
|
||||||
property bool showPreview: false
|
property bool showPreview: false
|
||||||
@@ -36,10 +34,9 @@ Searcher {
|
|||||||
|
|
||||||
function preview(path: string): void {
|
function preview(path: string): void {
|
||||||
previewPath = path;
|
previewPath = path;
|
||||||
showPreview = true;
|
|
||||||
|
|
||||||
if (Config.general.color.schemeGeneration)
|
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 {
|
function setCrop(screen: string, rect: rect, zoom: real): void {
|
||||||
@@ -55,6 +52,7 @@ Searcher {
|
|||||||
height: rect.height,
|
height: rect.height,
|
||||||
zoom: zoom
|
zoom: zoom
|
||||||
};
|
};
|
||||||
|
// root.crops = updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setWallpaper(path: string): void {
|
function setWallpaper(path: string): void {
|
||||||
@@ -68,10 +66,8 @@ Searcher {
|
|||||||
|
|
||||||
function stopPreview(): void {
|
function stopPreview(): void {
|
||||||
showPreview = false;
|
showPreview = false;
|
||||||
if (previewColorLock)
|
if (Config.general.color.schemeGeneration)
|
||||||
pendingPreviewClear = true;
|
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--image-path", `${root.actualCurrent}`, "--scheme", `${Config.colors.schemeType}`, "--mode", `${Config.general.color.mode}`]);
|
||||||
else
|
|
||||||
Colors.showPreview = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extraOpts: useFuzzy ? ({}) : ({
|
extraOpts: useFuzzy ? ({}) : ({
|
||||||
@@ -81,11 +77,6 @@ Searcher {
|
|||||||
list: wallpapers.entries
|
list: wallpapers.entries
|
||||||
useFuzzy: true
|
useFuzzy: true
|
||||||
|
|
||||||
onPreviewColorLockChanged: {
|
|
||||||
if (!previewColorLock && pendingPreviewClear)
|
|
||||||
Colors.showPreview = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IpcHandler {
|
IpcHandler {
|
||||||
function set(path: string): void {
|
function set(path: string): void {
|
||||||
root.setWallpaper(path);
|
root.setWallpaper(path);
|
||||||
@@ -127,17 +118,4 @@ Searcher {
|
|||||||
path: Config.general.wallpaperPath
|
path: Config.general.wallpaperPath
|
||||||
recursive: true
|
recursive: true
|
||||||
}
|
}
|
||||||
|
|
||||||
Process {
|
|
||||||
id: previewColorsProc
|
|
||||||
|
|
||||||
command: ["zshell-cli", "scheme", "generate", "-p", "-i", root.previewPath]
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
Colors.load(text, true);
|
|
||||||
Colors.showPreview = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-52
@@ -3,29 +3,24 @@ pragma ComponentBehavior: Bound
|
|||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import qs.Modules
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Modules.Bar.Components
|
import qs.Modules.SysTray
|
||||||
import qs.Modules.Bar.Popouts
|
import qs.Modules.Network
|
||||||
|
import qs.Modules.Updates
|
||||||
|
|
||||||
GridLayout {
|
RowLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property bool fullscreen
|
required property bool fullscreen
|
||||||
required property bool horizontal
|
|
||||||
required property bool isHovered
|
|
||||||
required property Wrapper popouts
|
required property Wrapper popouts
|
||||||
required property ClipWrapper popoutsWrapper
|
required property ClipWrapper popoutsWrapper
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
readonly property int vPadding: 6
|
readonly property int vPadding: 6
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
function axisCenterOf(item: Item): real {
|
function checkPopout(x: real): void {
|
||||||
const c = item.mapToItem(root, item.implicitWidth / 2, item.implicitHeight / 2);
|
const ch = childAt(x, height / 2) as EntryWrapper;
|
||||||
return horizontal ? c.x : c.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkPopout(pos: real): void {
|
|
||||||
const ch = (horizontal ? childAt(pos, height / 2) : childAt(width / 2, pos)) as EntryWrapper;
|
|
||||||
const id = ch?.entryId;
|
const id = ch?.entryId;
|
||||||
|
|
||||||
if (!ch || id === undefined) {
|
if (!ch || id === undefined) {
|
||||||
@@ -39,21 +34,26 @@ GridLayout {
|
|||||||
|
|
||||||
if (id === "statusIcons" && Config.bar.popouts.statusIcons) {
|
if (id === "statusIcons" && Config.bar.popouts.statusIcons) {
|
||||||
const items = (ch.item as StatusIcons).items;
|
const items = (ch.item as StatusIcons).items;
|
||||||
const icon = horizontal ? items.childAt(mapToItem(items, pos, 0).x, items.height / 2) : items.childAt(items.width / 2, mapToItem(items, 0, pos).y);
|
const localX = mapToItem(items, x, 0).x;
|
||||||
|
const icon = items.childAt(localX, items.height / 2);
|
||||||
if (icon) {
|
if (icon) {
|
||||||
popouts.currentName = icon.name;
|
popouts.currentName = icon.name;
|
||||||
popouts.currentCenter = Qt.binding(() => axisCenterOf(icon));
|
popouts.currentCenter = Qt.binding(() => icon.mapToItem(root, icon.implicitWidth / 2, 0).x);
|
||||||
popouts.hasCurrent = true;
|
popouts.hasCurrent = true;
|
||||||
}
|
}
|
||||||
} else if (id === "tray" && Config.bar.popouts.tray && Config.bar.tray.showOnHover) {
|
} else if (id === "tray" && Config.bar.popouts.tray && Config.bar.tray.showOnHover) {
|
||||||
const tray = ch.item as TrayIcons;
|
const tray = ch.item as TrayIcons;
|
||||||
const layout = tray.layout;
|
const layout = tray.layout;
|
||||||
const trayItem = horizontal ? layout.childAt(mapToItem(layout, pos, 0).x, layout.height / 2) : layout.childAt(tray.width / 2, mapToItem(layout, 0, pos).y);
|
const localX = mapToItem(layout, x, 0).x;
|
||||||
|
const trayItem = layout.childAt(localX, layout.height / 2);
|
||||||
|
|
||||||
if (trayItem) {
|
if (trayItem) {
|
||||||
const idx = trayItem.index;
|
const idx = trayItem.index;
|
||||||
popouts.currentName = `traymenu${idx}`;
|
popouts.currentName = `traymenu${idx}`;
|
||||||
popouts.currentCenter = Qt.binding(() => axisCenterOf(trayItem));
|
popouts.currentCenter = Qt.binding(() => {
|
||||||
|
const it = tray.items.itemAt(idx);
|
||||||
|
return it ? it.mapToItem(root, it.implicitWidth / 2, 0).x : popouts.currentCenter;
|
||||||
|
});
|
||||||
popouts.hasCurrent = true;
|
popouts.hasCurrent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,19 +63,12 @@ GridLayout {
|
|||||||
|
|
||||||
if (id === "updates") {
|
if (id === "updates") {
|
||||||
popouts.currentName = "updates";
|
popouts.currentName = "updates";
|
||||||
popouts.currentCenter = Qt.binding(() => axisCenterOf(ch.item as Item));
|
popouts.currentCenter = Qt.binding(() => ch.item.mapToItem(root, (ch.item as Item).implicitWidth / 2, 0).x);
|
||||||
popouts.hasCurrent = true;
|
popouts.hasCurrent = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function entryAt(pos: real): string {
|
spacing: Tokens.spacing.small
|
||||||
const ch = (horizontal ? childAt(pos, height / 2) : childAt(width / 2, pos)) as EntryWrapper;
|
|
||||||
return ch?.entryId ?? "";
|
|
||||||
}
|
|
||||||
|
|
||||||
columnSpacing: Tokens.spacing.small
|
|
||||||
columns: horizontal ? -1 : 1
|
|
||||||
rowSpacing: Tokens.spacing.small
|
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: repeater
|
id: repeater
|
||||||
@@ -92,8 +85,7 @@ GridLayout {
|
|||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
HyprsunsetWidget {
|
HyprsunsetWidget {
|
||||||
horizontal: root.horizontal
|
visible: !root.fullscreen
|
||||||
visible: !root.fullscreen || root.isHovered
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,8 +94,7 @@ GridLayout {
|
|||||||
roleValue: "spacer"
|
roleValue: "spacer"
|
||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
Layout.fillHeight: !root.horizontal
|
Layout.fillWidth: true
|
||||||
Layout.fillWidth: root.horizontal
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,9 +103,8 @@ GridLayout {
|
|||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
Workspaces {
|
Workspaces {
|
||||||
horizontal: root.horizontal
|
|
||||||
screen: root.screen
|
screen: root.screen
|
||||||
visible: !root.fullscreen || root.isHovered
|
visible: !root.fullscreen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,10 +114,9 @@ GridLayout {
|
|||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
TrayIcons {
|
TrayIcons {
|
||||||
horizontal: root.horizontal
|
|
||||||
loader: root
|
loader: root
|
||||||
popouts: root.popouts
|
popouts: root.popouts
|
||||||
visible: !root.fullscreen || root.isHovered
|
visible: !root.fullscreen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,8 +126,6 @@ GridLayout {
|
|||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
StatusIcons {
|
StatusIcons {
|
||||||
horizontal: root.horizontal
|
|
||||||
visible: !root.fullscreen || root.isHovered
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,9 +135,8 @@ GridLayout {
|
|||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
Resources {
|
Resources {
|
||||||
horizontal: root.horizontal
|
|
||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
visible: !root.fullscreen || root.isHovered
|
visible: !root.fullscreen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,8 +146,7 @@ GridLayout {
|
|||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
UpdatesWidget {
|
UpdatesWidget {
|
||||||
horizontal: root.horizontal
|
visible: !root.fullscreen
|
||||||
visible: !root.fullscreen || root.isHovered
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,10 +156,9 @@ GridLayout {
|
|||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
NotifBell {
|
NotifBell {
|
||||||
horizontal: root.horizontal
|
|
||||||
popouts: root.popouts
|
popouts: root.popouts
|
||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
visible: !root.fullscreen || root.isHovered
|
visible: !root.fullscreen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,11 +168,10 @@ GridLayout {
|
|||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
Clock {
|
Clock {
|
||||||
horizontal: root.horizontal
|
|
||||||
loader: root
|
loader: root
|
||||||
popouts: root.popouts
|
popouts: root.popouts
|
||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
visible: !root.fullscreen || root.isHovered
|
visible: !root.fullscreen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,8 +182,16 @@ GridLayout {
|
|||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
WindowTitle {
|
WindowTitle {
|
||||||
bar: root
|
bar: root
|
||||||
horizontal: root.horizontal
|
visible: !root.fullscreen
|
||||||
visible: !root.fullscreen || root.isHovered
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: "network"
|
||||||
|
|
||||||
|
delegate: EntryWrapper {
|
||||||
|
NetworkWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,8 +201,7 @@ GridLayout {
|
|||||||
|
|
||||||
delegate: EntryWrapper {
|
delegate: EntryWrapper {
|
||||||
MediaWidget {
|
MediaWidget {
|
||||||
horizontal: root.horizontal
|
visible: !root.fullscreen
|
||||||
visible: !root.fullscreen || root.isHovered
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,11 +214,9 @@ GridLayout {
|
|||||||
default property Item item
|
default property Item item
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
|
||||||
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
Layout.bottomMargin: !root.horizontal && index === repeater.count - 1 ? root.vPadding : 0
|
Layout.leftMargin: index === 0 ? root.vPadding : (entryId === "statusIcons") ? -root.spacing + Tokens.spacing.extraSmall : 0
|
||||||
Layout.leftMargin: root.horizontal && index === 0 ? root.vPadding : (entryId === "statusIcons" && root.horizontal) ? -root.rowSpacing + Tokens.spacing.extraSmall : 0
|
Layout.rightMargin: index === repeater.count - 1 ? root.vPadding : 0
|
||||||
Layout.rightMargin: root.horizontal && index === repeater.count - 1 ? root.vPadding : 0
|
|
||||||
Layout.topMargin: !root.horizontal && index === 0 ? root.vPadding : (entryId === "statusIcons" && !root.horizontal) ? -root.columnSpacing + Tokens.spacing.extraSmall : 0
|
|
||||||
children: item
|
children: item
|
||||||
implicitHeight: item?.implicitHeight ?? 0
|
implicitHeight: item?.implicitHeight ?? 0
|
||||||
implicitWidth: item?.implicitWidth ?? 0
|
implicitWidth: item?.implicitWidth ?? 0
|
||||||
|
|||||||
+21
-29
@@ -1,48 +1,45 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import ZShell.Config
|
import QtQuick.Layouts
|
||||||
import qs.Modules.Bar.Popouts
|
|
||||||
import qs.Components
|
import qs.Components
|
||||||
|
import qs.Modules
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Modules.SysTray
|
||||||
|
import qs.Modules.SysTray.Widgets
|
||||||
|
import qs.Modules.Network
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property int clampedExtent: Math.max(Config.bar.border, extent)
|
readonly property int contentHeight: Config.bar.height + padding * 2
|
||||||
readonly property int contentThickness: Math.floor(Math.max(Config.bar.height, Tokens.bar.innerSize * (horizontal ? 1 : 1.5))) + padding * 2
|
readonly property int exclusiveZone: Config.bar.autoHide ? Config.bar.border : contentHeight
|
||||||
readonly property int exclusiveZone: Config.bar.autoHide ? Config.bar.border : contentThickness
|
|
||||||
property real extent: fullscreen ? 0 : Config.bar.border
|
|
||||||
required property bool fullscreen
|
required property bool fullscreen
|
||||||
readonly property bool horizontal: position !== "left"
|
|
||||||
property bool isHovered
|
property bool isHovered
|
||||||
readonly property int padding: Math.max(Tokens.padding.smaller, Config.bar.border)
|
readonly property int padding: Math.max(Tokens.padding.smaller, Config.bar.border)
|
||||||
required property Wrapper popouts
|
required property Wrapper popouts
|
||||||
required property ClipWrapper popoutsWrapper
|
required property ClipWrapper popoutsWrapper
|
||||||
required property string position
|
|
||||||
required property ShellScreen screen
|
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
|
readonly property int vPadding: 6
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
function checkPopout(pos: real): void {
|
function checkPopout(x: real): void {
|
||||||
(content.item as Bar)?.checkPopout(pos);
|
content.item?.checkPopout(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
function entryAt(pos: real): string {
|
implicitHeight: fullscreen ? 0 : Config.bar.border
|
||||||
return (content.item as Bar)?.entryAt(pos) ?? "";
|
visible: height > Config.bar.border
|
||||||
}
|
|
||||||
|
|
||||||
implicitHeight: extent
|
|
||||||
implicitWidth: extent
|
|
||||||
visible: extent > Config.bar.border
|
|
||||||
|
|
||||||
states: State {
|
states: State {
|
||||||
name: "visible"
|
name: "visible"
|
||||||
when: root.shouldBeVisible
|
when: root.shouldBeVisible
|
||||||
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
root.extent: root.contentThickness
|
root.implicitHeight: root.contentHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
transitions: [
|
transitions: [
|
||||||
@@ -51,7 +48,7 @@ Item {
|
|||||||
to: "visible"
|
to: "visible"
|
||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
property: "extent"
|
property: "implicitHeight"
|
||||||
target: root
|
target: root
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -60,7 +57,7 @@ Item {
|
|||||||
to: ""
|
to: ""
|
||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
property: "extent"
|
property: "implicitHeight"
|
||||||
target: root
|
target: root
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,18 +67,13 @@ Item {
|
|||||||
id: content
|
id: content
|
||||||
|
|
||||||
active: root.shouldBeVisible || root.visible
|
active: root.shouldBeVisible || root.visible
|
||||||
anchors.bottom: root.position !== "bottom" ? parent.bottom : undefined
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: root.horizontal ? parent.left : undefined
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: root.position !== "top" ? parent.top : undefined
|
|
||||||
height: root.contentThickness
|
|
||||||
width: root.contentThickness
|
|
||||||
|
|
||||||
sourceComponent: Bar {
|
sourceComponent: Bar {
|
||||||
fullscreen: root.fullscreen
|
fullscreen: root.fullscreen
|
||||||
height: root.contentThickness
|
height: root.contentHeight
|
||||||
horizontal: root.horizontal
|
|
||||||
isHovered: root.isHovered
|
|
||||||
popouts: root.popouts
|
popouts: root.popouts
|
||||||
popoutsWrapper: root.popoutsWrapper
|
popoutsWrapper: root.popoutsWrapper
|
||||||
screen: root.screen
|
screen: root.screen
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import Quickshell
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import ZShell.Config
|
|
||||||
import qs.Modules.Bar.Popouts
|
|
||||||
import qs.Modules.Bar.Components.Common
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Components
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
WidgetBase {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
readonly property color contentColor: visibilities.dashboard ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
|
||||||
readonly property string effectiveFormat: {
|
|
||||||
let fmt = Config.general.dateFormat;
|
|
||||||
if (!root.horizontal)
|
|
||||||
fmt = fmt.replace("dddd", "ddd");
|
|
||||||
return fmt;
|
|
||||||
}
|
|
||||||
readonly property var formatParts: {
|
|
||||||
const segments = root.effectiveFormat.split(" - ");
|
|
||||||
let datePart = "";
|
|
||||||
let timePart = "";
|
|
||||||
|
|
||||||
if (segments.length > 1) {
|
|
||||||
datePart = segments[0];
|
|
||||||
timePart = segments[1];
|
|
||||||
} else if (/[hms]/.test(segments[0])) {
|
|
||||||
timePart = segments[0];
|
|
||||||
} else {
|
|
||||||
datePart = segments[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
const dateTokens = datePart.trim().length ? datePart.trim().split(/\s+/) : [];
|
|
||||||
const timeTokens = timePart.trim().length ? timePart.trim().split(":") : [];
|
|
||||||
|
|
||||||
return {
|
|
||||||
dateTokens: dateTokens,
|
|
||||||
timeTokens: timeTokens
|
|
||||||
};
|
|
||||||
}
|
|
||||||
required property GridLayout loader
|
|
||||||
required property Wrapper popouts
|
|
||||||
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
|
|
||||||
implicitHeight: horizontal ? baseSize : size
|
|
||||||
implicitWidth: horizontal ? size : baseSize
|
|
||||||
radius: Tokens.rounding.full
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
id: timeText
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
color: root.contentColor
|
|
||||||
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
|
|
||||||
height: implicitHeight
|
|
||||||
text: Time.dateStr
|
|
||||||
visible: root.horizontal
|
|
||||||
|
|
||||||
Behavior on color {
|
|
||||||
CAnim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: verticalColumn
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
spacing: Tokens.padding.small ?? 2
|
|
||||||
visible: !root.horizontal
|
|
||||||
width: root.baseSize
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: root.formatParts.dateTokens
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
required property string modelData
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
color: root.contentColor
|
|
||||||
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
|
|
||||||
text: Qt.formatDateTime(Time.date, modelData)
|
|
||||||
|
|
||||||
Behavior on color {
|
|
||||||
CAnim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
Layout.bottomMargin: Tokens.padding.small ?? 2
|
|
||||||
Layout.topMargin: Tokens.padding.small ?? 2
|
|
||||||
color: root.contentColor
|
|
||||||
height: 1
|
|
||||||
implicitWidth: root.baseSize * 0.5
|
|
||||||
opacity: 0.4
|
|
||||||
radius: 1
|
|
||||||
visible: root.formatParts.dateTokens.length > 0 && root.formatParts.timeTokens.length > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: root.formatParts.timeTokens
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
required property string modelData
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
color: root.contentColor
|
|
||||||
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
|
|
||||||
text: {
|
|
||||||
if (modelData.includes("h"))
|
|
||||||
return Time.hourStr;
|
|
||||||
if (modelData.includes("m"))
|
|
||||||
return Time.minuteStr;
|
|
||||||
if (modelData.includes("s"))
|
|
||||||
return Time.secondStr;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on color {
|
|
||||||
CAnim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
|
||||||
color: root.contentColor
|
|
||||||
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
|
|
||||||
text: Qt.formatDateTime(Time.date, "AP")
|
|
||||||
visible: Config.services.useTwelveHourClock && root.formatParts.timeTokens.length > 0
|
|
||||||
|
|
||||||
Behavior on color {
|
|
||||||
CAnim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StateLayer {
|
|
||||||
acceptedButtons: Qt.LeftButton
|
|
||||||
color: root.contentColor
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
root.visibilities.dashboard = !root.visibilities.dashboard;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import ZShell.Config
|
|
||||||
import qs.Components
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
CustomRect {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
readonly property int baseSize: horizontal ? Math.max(Config.bar.height, Tokens.bar.innerSize) : Math.max(Config.bar.height, Math.floor(Tokens.bar.innerSize * 1.5))
|
|
||||||
required property bool horizontal
|
|
||||||
|
|
||||||
color: Colors.tPalette.m3surfaceContainer
|
|
||||||
implicitHeight: horizontal ? baseSize : width
|
|
||||||
implicitWidth: horizontal ? height : baseSize
|
|
||||||
radius: Tokens.rounding.full
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import ZShell.Config
|
|
||||||
import qs.Components
|
|
||||||
import qs.Modules.Bar.Components.Common
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
WidgetBase {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
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.normal * 2
|
|
||||||
implicitWidth: horizontal ? layout.implicitWidth + Tokens.padding.normal * 2 : baseSize
|
|
||||||
radius: Tokens.rounding.full
|
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
|
||||||
enabled: !root.horizontal
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on implicitWidth {
|
|
||||||
enabled: root.horizontal
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextMetrics {
|
|
||||||
id: metrics
|
|
||||||
|
|
||||||
font: mediatext.font
|
|
||||||
text: mediatext.text
|
|
||||||
}
|
|
||||||
|
|
||||||
GridLayout {
|
|
||||||
id: layout
|
|
||||||
|
|
||||||
anchors.bottomMargin: root.horizontal ? 0 : Tokens.padding.normal
|
|
||||||
anchors.fill: parent
|
|
||||||
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 {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
|
|
||||||
animate: true
|
|
||||||
color: Players.active?.isPlaying ? Colors.palette.m3primary : Colors.palette.m3onSurface
|
|
||||||
font.pointSize: Tokens.font.size.larger
|
|
||||||
text: Players.active?.isPlaying ? "music_note" : "music_off"
|
|
||||||
}
|
|
||||||
|
|
||||||
MarqueeText {
|
|
||||||
id: mediatext
|
|
||||||
|
|
||||||
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
|
|
||||||
animate: true
|
|
||||||
color: Players.active?.isPlaying ? Colors.palette.m3primary : Colors.palette.m3onSurface
|
|
||||||
font.pointSize: Tokens.font.size.normal
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
implicitHeight: root.horizontal ? root.implicitHeight : root.textWidth
|
|
||||||
implicitWidth: root.horizontal ? root.textWidth : root.implicitWidth
|
|
||||||
marqueeEnabled: false
|
|
||||||
pauseMs: 4000
|
|
||||||
text: root.currentMedia
|
|
||||||
vertical: !root.horizontal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomMouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
|
|
||||||
onContainsMouseChanged: {
|
|
||||||
if (!containsMouse) {
|
|
||||||
mediatext.marqueeEnabled = false;
|
|
||||||
} else {
|
|
||||||
mediatext.marqueeEnabled = true;
|
|
||||||
mediatext.anim.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import ZShell.Config
|
|
||||||
import qs.Components
|
|
||||||
import qs.Modules.Bar.Components.Common
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
WidgetBase {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
property int countUpdates: Updates.availableUpdates
|
|
||||||
property color textColor: Colors.palette.m3onSurface
|
|
||||||
|
|
||||||
color: Colors.tPalette.m3surfaceContainer
|
|
||||||
implicitHeight: horizontal ? baseSize : content.implicitHeight + Tokens.spacing.small
|
|
||||||
implicitWidth: horizontal ? content.implicitWidth + Tokens.spacing.small * 2 : baseSize
|
|
||||||
radius: Tokens.rounding.full
|
|
||||||
|
|
||||||
GridLayout {
|
|
||||||
id: content
|
|
||||||
|
|
||||||
anchors.centerIn: parent
|
|
||||||
columnSpacing: Tokens.spacing.small
|
|
||||||
columns: root.horizontal ? -1 : 1
|
|
||||||
rowSpacing: -Tokens.spacing.extraSmall / 2
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
|
|
||||||
font.pointSize: root.horizontal ? Tokens.font.size.larger : Tokens.font.size.large
|
|
||||||
text: "package_2"
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
|
||||||
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
|
|
||||||
color: root.textColor
|
|
||||||
font.pointSize: Tokens.font.size.normal
|
|
||||||
text: root.countUpdates
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import ZShell.Config
|
|
||||||
import qs.Components
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
required property var bar
|
|
||||||
property color color: Colors.palette.m3primary
|
|
||||||
property Title current: text1
|
|
||||||
required property bool horizontal
|
|
||||||
// readonly property int maxWidth: 300
|
|
||||||
readonly property int maxSize: {
|
|
||||||
const otherModules = bar.children.filter(c => c.enabled && c.entryId && c.item !== this && c.entryId !== "spacer");
|
|
||||||
const otherSize = otherModules.reduce((acc, curr) => acc + (horizontal ? (curr.item?.nonAnimWidth ?? curr.width ?? 0) : (curr.item.nonAnimHeight ?? curr.height ?? 0)), 0);
|
|
||||||
return horizontal ? (bar.width - otherSize - bar.columnSpacing * (bar.children.length - 1) - bar.vPadding * 2) : (bar.height - otherSize - bar.rowSpacing * (bar.children.length - 1) - bar.vPadding * 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
clip: true
|
|
||||||
implicitHeight: horizontal ? current.implicitHeight : current.implicitWidth + current.anchors.topMargin
|
|
||||||
implicitWidth: horizontal ? current.implicitWidth + current.anchors.leftMargin : current.implicitHeight + current.anchors.topMargin
|
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
|
||||||
enabled: !root.horizontal
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on implicitWidth {
|
|
||||||
enabled: root.horizontal
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Title {
|
|
||||||
id: text1
|
|
||||||
}
|
|
||||||
|
|
||||||
Title {
|
|
||||||
id: text2
|
|
||||||
}
|
|
||||||
|
|
||||||
TextMetrics {
|
|
||||||
id: metrics
|
|
||||||
|
|
||||||
elide: Qt.ElideRight
|
|
||||||
elideWidth: root.maxSize - (root.horizontal ? root.current.anchors.leftMargin : 0)
|
|
||||||
font.family: "Rubik"
|
|
||||||
font.pointSize: Tokens.font.size.normal
|
|
||||||
text: Hypr.activeToplevel?.title ?? qsTr("Desktop")
|
|
||||||
|
|
||||||
onElideWidthChanged: root.current.text = elidedText
|
|
||||||
onTextChanged: {
|
|
||||||
const next = root.current === text1 ? text2 : text1;
|
|
||||||
next.text = elidedText;
|
|
||||||
root.current = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component Title: CustomText {
|
|
||||||
id: text
|
|
||||||
|
|
||||||
anchors.horizontalCenter: root.horizontal ? undefined : parent.horizontalCenter
|
|
||||||
anchors.left: root.horizontal ? parent.left : undefined
|
|
||||||
anchors.leftMargin: root.horizontal ? Tokens.spacing.small : 0
|
|
||||||
anchors.top: root.horizontal ? undefined : parent.top
|
|
||||||
anchors.topMargin: root.horizontal ? 0 : Tokens.spacing.small
|
|
||||||
anchors.verticalCenter: root.horizontal ? parent.verticalCenter : undefined
|
|
||||||
color: root.color
|
|
||||||
font.family: metrics.font.family
|
|
||||||
font.pointSize: metrics.font.pointSize
|
|
||||||
height: root.horizontal ? implicitHeight : implicitWidth
|
|
||||||
opacity: root.current === this ? 1 : 0
|
|
||||||
width: root.horizontal ? implicitWidth : implicitHeight
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transform: [
|
|
||||||
Translate {
|
|
||||||
x: !root.horizontal ? -text.implicitWidth + text.implicitHeight : 0
|
|
||||||
},
|
|
||||||
Rotation {
|
|
||||||
angle: root.horizontal ? 0 : 270
|
|
||||||
origin.x: text.implicitHeight / 2
|
|
||||||
origin.y: text.implicitHeight / 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,385 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
readonly property list<var> btConnected: Bluetooth.devices.values.filter(d => d.connected)
|
|
||||||
|
|
||||||
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: root.btConnected.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
|
|
||||||
|
|
||||||
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: root.btConnected.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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import Quickshell
|
|
||||||
import qs.Components
|
|
||||||
import ZShell.Config
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
required property real borderThickness
|
|
||||||
readonly property alias content: content
|
|
||||||
readonly property bool horizontal: position !== "left"
|
|
||||||
// property real offsetScale: y > 0 || content.hasCurrent ? 0 : 1
|
|
||||||
property real offsetScale: {
|
|
||||||
if (content.hasCurrent)
|
|
||||||
return 0;
|
|
||||||
if (position === "top")
|
|
||||||
return y > 0 ? 0 : 1;
|
|
||||||
if (position === "bottom")
|
|
||||||
return 1;
|
|
||||||
return x > 0 ? 0 : 1;
|
|
||||||
}
|
|
||||||
required property string position
|
|
||||||
required property ShellScreen screen
|
|
||||||
|
|
||||||
anchors.bottom: position === "bottom" ? parent.bottom : undefined
|
|
||||||
clip: true
|
|
||||||
implicitHeight: horizontal ? content.implicitHeight * (1 - offsetScale) : content.implicitHeight
|
|
||||||
implicitWidth: horizontal ? content.implicitWidth : content.implicitWidth * (1 - offsetScale)
|
|
||||||
visible: width > 0 && height > 0
|
|
||||||
x: {
|
|
||||||
if (!horizontal)
|
|
||||||
return 0;
|
|
||||||
const off = content.currentCenter - borderThickness - content.nonAnimWidth / 2;
|
|
||||||
const diff = parent.width - Math.floor(off + content.nonAnimWidth);
|
|
||||||
if (diff < 0)
|
|
||||||
return off + diff;
|
|
||||||
return Math.floor(Math.max(off, 0));
|
|
||||||
}
|
|
||||||
y: {
|
|
||||||
if (horizontal)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const off = content.currentCenter - borderThickness - content.nonAnimHeight / 2;
|
|
||||||
const diff = parent.height - Math.floor(off + content.nonAnimHeight);
|
|
||||||
if (diff < 0)
|
|
||||||
return off + diff;
|
|
||||||
return Math.max(off, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on offsetScale {
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on x {
|
|
||||||
enabled: !root.horizontal || root.offsetScale < 1
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
duration: content.animLength
|
|
||||||
easing.bezierCurve: content.animCurve
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on y {
|
|
||||||
enabled: root.horizontal || root.offsetScale < 1
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
duration: content.animLength
|
|
||||||
easing.bezierCurve: content.animCurve
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Wrapper {
|
|
||||||
id: content
|
|
||||||
|
|
||||||
anchors.bottom: root.position === "bottom" ? parent.bottom : undefined
|
|
||||||
anchors.bottomMargin: (-implicitHeight - 5) * root.offsetScale
|
|
||||||
anchors.horizontalCenter: root.horizontal ? parent.horizontalCenter : undefined
|
|
||||||
anchors.left: root.horizontal ? undefined : parent.left
|
|
||||||
anchors.leftMargin: (-implicitWidth - 5) * root.offsetScale
|
|
||||||
anchors.top: root.position === "top" ? parent.top : undefined
|
|
||||||
anchors.topMargin: (-implicitHeight - 5) * root.offsetScale
|
|
||||||
anchors.verticalCenter: root.horizontal ? undefined : parent.verticalCenter
|
|
||||||
offsetScale: root.offsetScale
|
|
||||||
screen: root.screen
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,362 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import Quickshell
|
|
||||||
import ZShell.Components
|
|
||||||
import ZShell.Config
|
|
||||||
import qs.Services
|
|
||||||
import qs.Modules.Bar.Popouts.Network
|
|
||||||
import qs.Components
|
|
||||||
import qs.Helpers
|
|
||||||
|
|
||||||
CustomClippingRect {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
required property var wrapper
|
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
implicitHeight: networkPopContent.height + networkPopContent.anchors.margins * 2
|
|
||||||
implicitWidth: 500 + 8 * 2
|
|
||||||
radius: (20 - Tokens.padding.small) * Tokens.rounding.scale
|
|
||||||
|
|
||||||
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: Network.connectedNetworks.length === 0
|
|
||||||
subtext: qsTr("Toggle WiFi device state")
|
|
||||||
text: checked ? qsTr("Enabled") : qsTr("Disabled")
|
|
||||||
|
|
||||||
onToggled: Network.setWifi(checked)
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
id: rows
|
|
||||||
|
|
||||||
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: NetworkItem {
|
|
||||||
list: rows
|
|
||||||
width: rows.width
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
displaced: Transition {
|
|
||||||
Anim {
|
|
||||||
easing.type: Easing.OutCubic
|
|
||||||
property: "y"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
model: ScriptModel {
|
|
||||||
values: {
|
|
||||||
const byStrengthName = (a, b) => b.signalStrength - a.signalStrength || a.name.localeCompare(b.name);
|
|
||||||
const cNetworks = [...Network.connectedNetworks];
|
|
||||||
const kNetworks = [...Network.knownNetworks];
|
|
||||||
const uNetworks = [...Network.unknownNetworks];
|
|
||||||
|
|
||||||
return [...cNetworks.sort(byStrengthName), ...(kNetworks.length > 0 ? [
|
|
||||||
{
|
|
||||||
isDivider: true,
|
|
||||||
type: "known"
|
|
||||||
},
|
|
||||||
...kNetworks.sort(byStrengthName)] : []), ...(uNetworks.length > 0 ? [
|
|
||||||
{
|
|
||||||
isDivider: true,
|
|
||||||
type: "unknown"
|
|
||||||
},
|
|
||||||
...uNetworks.sort(byStrengthName)] : [])];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 int connectedCount: Network.connectedNetworks.length
|
|
||||||
readonly property bool connecting: Network.connectingNetwork === modelData
|
|
||||||
property int horizontalPadding: Tokens.padding.largeIncreased
|
|
||||||
readonly property bool inConnectedGroup: index < connectedCount
|
|
||||||
// sectioning first / last item in list reminder
|
|
||||||
// if index === network.connectedNetworks.length - 1
|
|
||||||
// if index === network.connectedNetworks.length - 1 + network.knownNetworks.length - 2
|
|
||||||
// if index === network.connectedNetworks.length - 1 + network.knownNetworks.length
|
|
||||||
// list.model.values.length - 1
|
|
||||||
required property int index
|
|
||||||
readonly property bool isSecure: Network.isSecure(modelData.security)
|
|
||||||
required property ListView list
|
|
||||||
required property var modelData
|
|
||||||
property int verticalPadding: Tokens.padding.smaller
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
first: !inConnectedGroup && index === connectedCount + 1
|
|
||||||
implicitHeight: rowLayout.implicitHeight + verticalPadding * 2
|
|
||||||
last: inConnectedGroup ? index === connectedCount - 1 : index === list.count - 1
|
|
||||||
radius: Tokens.rounding.small
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
id: rowLayout
|
|
||||||
|
|
||||||
Layout.preferredHeight: visible ? rowLayout.implicitHeight + Tokens.padding.smaller * 2 : 0
|
|
||||||
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: networkItem.modelData.connected ? qsTr("Connected: %1 strength").arg(Math.round(networkItem.modelData.signalStrength * 100) + "%") : 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 StatusDivider: CustomText {
|
|
||||||
required property var modelData
|
|
||||||
|
|
||||||
bottomPadding: Tokens.spacing.extraSmall
|
|
||||||
color: Colors.palette.m3onSurfaceVariant
|
|
||||||
font.pointSize: Tokens.font.size.smaller
|
|
||||||
text: {
|
|
||||||
if (modelData.type === "known") {
|
|
||||||
const count = Network.knownNetworks.filter(n => !n.connected).length;
|
|
||||||
|
|
||||||
return qsTr("%1 known network%2").arg(count).arg(count === 1 ? "" : "s");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modelData.type === "unknown") {
|
|
||||||
const count = Network.unknownNetworks.filter(n => !n.connected).length;
|
|
||||||
|
|
||||||
return qsTr("%1 network%2 available").arg(count).arg(count === 1 ? "" : "s");
|
|
||||||
}
|
|
||||||
|
|
||||||
return qsTr("object unknown");
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import qs.Components
|
||||||
|
import ZShell.Config
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property real borderThickness
|
||||||
|
readonly property alias content: content
|
||||||
|
property real offsetScale: y > 0 || content.hasCurrent ? 0 : 1
|
||||||
|
required property ShellScreen screen
|
||||||
|
|
||||||
|
clip: true
|
||||||
|
implicitHeight: content.implicitHeight * (1 - offsetScale)
|
||||||
|
implicitWidth: content.implicitWidth
|
||||||
|
visible: width > 0 && height > 0
|
||||||
|
x: {
|
||||||
|
const off = content.currentCenter - borderThickness - content.nonAnimWidth / 2;
|
||||||
|
const diff = parent.width - Math.floor(off + content.nonAnimWidth);
|
||||||
|
if (diff < 0)
|
||||||
|
return off + diff;
|
||||||
|
return Math.floor(Math.max(off, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on offsetScale {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Behavior on x {
|
||||||
|
enabled: root.offsetScale < 1
|
||||||
|
|
||||||
|
Anim {
|
||||||
|
duration: content.animLength
|
||||||
|
easing.bezierCurve: content.animCurve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Behavior on y {
|
||||||
|
Anim {
|
||||||
|
duration: content.animLength
|
||||||
|
easing.bezierCurve: content.animCurve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Wrapper {
|
||||||
|
id: content
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: (-implicitHeight - 5) * root.offsetScale
|
||||||
|
offsetScale: root.offsetScale
|
||||||
|
screen: root.screen
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Modules
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Components
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property RowLayout loader
|
||||||
|
required property Wrapper popouts
|
||||||
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
|
color: visibilities.dashboard ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
|
||||||
|
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
|
||||||
|
implicitWidth: timeText.contentWidth + Tokens.padding.normal * 2
|
||||||
|
radius: Tokens.rounding.full
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: timeText
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: root.visibilities.dashboard ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||||
|
font: Config.appearance.font.family.mono
|
||||||
|
text: Time.dateStr
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
CAnim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
color: root.visibilities.dashboard ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
root.visibilities.dashboard = !root.visibilities.dashboard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,10 @@ import Quickshell.Services.SystemTray
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Components
|
import qs.Components
|
||||||
|
import qs.Modules.WSOverview
|
||||||
|
import qs.Modules.Network
|
||||||
|
import qs.Modules.SysTray.Popouts
|
||||||
|
import qs.Modules.Updates
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -80,13 +84,6 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Popout {
|
|
||||||
name: "bluetooth"
|
|
||||||
|
|
||||||
sourceComponent: BluetoothPopout {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Popout {
|
Popout {
|
||||||
name: "updates"
|
name: "updates"
|
||||||
|
|
||||||
@@ -103,10 +100,10 @@ Item {
|
|||||||
readonly property bool shouldBeActive: root.popouts.currentName === name
|
readonly property bool shouldBeActive: root.popouts.currentName === name
|
||||||
|
|
||||||
active: false
|
active: false
|
||||||
anchors.centerIn: opacity === 1 ? undefined : parent
|
// anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
// anchors.top: parent.top
|
||||||
anchors.top: opacity === 1 ? parent.top : undefined
|
// anchors.topMargin: 5
|
||||||
anchors.topMargin: 5
|
anchors.centerIn: parent
|
||||||
opacity: 0
|
opacity: 0
|
||||||
scale: 0.8
|
scale: 0.8
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ Item {
|
|||||||
Item {
|
Item {
|
||||||
id: view
|
id: view
|
||||||
|
|
||||||
readonly property int currentIndex: root.dashState?.currentTab
|
readonly property int currentIndex: root.state.currentTab
|
||||||
readonly property Item currentItem: row.children[currentIndex]
|
readonly property Item currentItem: row.children[currentIndex]
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|||||||
+151
-144
@@ -1,12 +1,10 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.Mpris
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Shapes
|
import QtQuick.Shapes
|
||||||
import QtQuick.Effects
|
import QtQuick.Effects
|
||||||
import ZShell.Components
|
|
||||||
import ZShell.Services
|
import ZShell.Services
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Daemons
|
import qs.Daemons
|
||||||
@@ -16,7 +14,7 @@ import qs.Services
|
|||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
readonly property bool hasUnknownLength: (Players.active?.length ?? 0) > 2147483647
|
|
||||||
property real playerProgress: {
|
property real playerProgress: {
|
||||||
const active = Players.active;
|
const active = Players.active;
|
||||||
return active?.length ? (active.position % active.length) / active.length : 0;
|
return active?.length ? (active.position % active.length) / active.length : 0;
|
||||||
@@ -25,19 +23,7 @@ Item {
|
|||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
implicitHeight: layout.implicitHeight
|
implicitHeight: cover.height + rowHeight * 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}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on playerProgress {
|
Behavior on playerProgress {
|
||||||
Anim {
|
Anim {
|
||||||
@@ -46,10 +32,11 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
running: Players.active?.isPlaying ?? false
|
|
||||||
interval: Config.dashboard.mediaUpdateInterval
|
interval: Config.dashboard.mediaUpdateInterval
|
||||||
triggeredOnStart: true
|
|
||||||
repeat: true
|
repeat: true
|
||||||
|
running: Players.active?.isPlaying ?? false
|
||||||
|
triggeredOnStart: true
|
||||||
|
|
||||||
onTriggered: Players.active?.positionChanged()
|
onTriggered: Players.active?.positionChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +72,7 @@ Item {
|
|||||||
const n = values.length;
|
const n = values.length;
|
||||||
|
|
||||||
if (n < 2)
|
if (n < 2)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
const h = layout.height + shape.strokeWidth / 2;
|
const h = layout.height + shape.strokeWidth / 2;
|
||||||
const w = layout.width + shape.strokeWidth;
|
const w = layout.width + shape.strokeWidth;
|
||||||
@@ -139,11 +126,58 @@ 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 {
|
RowLayout {
|
||||||
id: layout
|
id: layout
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
implicitHeight: root.implicitHeight
|
||||||
|
|
||||||
CustomClippingRect {
|
CustomClippingRect {
|
||||||
id: cover
|
id: cover
|
||||||
@@ -177,174 +211,147 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
CustomRect {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.leftMargin: Tokens.spacing.large
|
|
||||||
Layout.rightMargin: Tokens.spacing.large
|
|
||||||
Layout.preferredHeight: childrenRect.height
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
|
||||||
spacing: Tokens.spacing.normal
|
|
||||||
|
|
||||||
MarqueeText {
|
MarqueeText {
|
||||||
id: title
|
id: title
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: parent.top
|
||||||
color: Colors.palette.m3primary
|
color: Colors.palette.m3primary
|
||||||
font.pointSize: Tokens.font.size.normal
|
font.pointSize: Tokens.font.size.normal
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
pauseMs: 4000
|
pauseMs: 4000
|
||||||
text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
|
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 {
|
MarqueeText {
|
||||||
id: album
|
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
|
color: Colors.palette.m3outline
|
||||||
font.pointSize: Tokens.font.size.small
|
font.pointSize: Tokens.font.size.small
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
pauseMs: 4000
|
pauseMs: 4000
|
||||||
text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
|
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 {
|
MarqueeText {
|
||||||
id: artist
|
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
|
color: Colors.palette.m3secondary
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
pauseMs: 4000
|
pauseMs: 4000
|
||||||
text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
|
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 {
|
RowLayout {
|
||||||
id: positionSliderLayout
|
id: controls
|
||||||
Layout.topMargin: Tokens.spacing.extraLargeIncreased
|
|
||||||
Layout.fillWidth: true
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: artist.bottom
|
||||||
|
anchors.topMargin: Tokens.spacing.smaller
|
||||||
spacing: Tokens.spacing.small
|
spacing: Tokens.spacing.small
|
||||||
|
|
||||||
TextMetrics {
|
Control {
|
||||||
id: timeMetrics
|
function onClicked(): void {
|
||||||
|
Players.active?.previous();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
Binding {
|
|
||||||
target: positionLabel
|
|
||||||
property: "text"
|
|
||||||
value: root.lengthStr(positionSlider.pos * (Players.active?.length ?? 0))
|
|
||||||
when: positionSlider.dragging
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CustomText {
|
canUse: Players.active?.canGoPrevious ?? false
|
||||||
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
|
|
||||||
implicitWidth: Math.round(implicitHeight * 0.9)
|
|
||||||
}
|
|
||||||
|
|
||||||
IconButton {
|
|
||||||
id: previousBtn
|
|
||||||
|
|
||||||
type: IconButton.Tonal
|
|
||||||
icon: "skip_previous"
|
icon: "skip_previous"
|
||||||
isRound: true
|
|
||||||
shapeMorph: true
|
|
||||||
enabled: Players.active?.canGoPrevious
|
|
||||||
onClicked: Players.active?.previous()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IconButton {
|
Control {
|
||||||
id: playPauseBtn
|
function onClicked(): void {
|
||||||
|
Players.active?.togglePlaying();
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
IconButton {
|
|
||||||
id: nextBtn
|
|
||||||
|
|
||||||
type: IconButton.Tonal
|
|
||||||
icon: "skip_next"
|
|
||||||
isRound: true
|
|
||||||
shapeMorph: true
|
|
||||||
enabled: Players.active?.canGoNext
|
|
||||||
onClicked: Players.active?.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
implicitWidth: Math.round(implicitHeight * 0.9)
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,9 @@ Item {
|
|||||||
}
|
}
|
||||||
readonly property real nonAnimHeight: state === "visible" ? (content.item?.nonAnimHeight ?? 0) : 0
|
readonly property real nonAnimHeight: state === "visible" ? (content.item?.nonAnimHeight ?? 0) : 0
|
||||||
required property real offsetScale
|
required property real offsetScale
|
||||||
required property string position
|
|
||||||
readonly property bool shouldBeActive: root.visibilities.dashboard && Config.dashboard.enabled
|
readonly property bool shouldBeActive: root.visibilities.dashboard && Config.dashboard.enabled
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
anchors.bottom: position === "bottom" ? parent.bottom : undefined
|
|
||||||
anchors.bottomMargin: position === "bottom" ? (-implicitHeight - 5) * offsetScale : 0
|
|
||||||
anchors.left: position === "left" ? parent.left : undefined
|
|
||||||
anchors.leftMargin: position === "left" ? (-implicitWidth - 5) * offsetScale : 0
|
|
||||||
anchors.top: position === "top" ? parent.top : undefined
|
|
||||||
anchors.topMargin: position === "top" ? (-implicitHeight - 5) * offsetScale : 0
|
|
||||||
implicitHeight: content.implicitHeight
|
implicitHeight: content.implicitHeight
|
||||||
implicitWidth: content.implicitWidth || 854
|
implicitWidth: content.implicitWidth || 854
|
||||||
opacity: 1 - offsetScale
|
opacity: 1 - offsetScale
|
||||||
@@ -35,11 +28,8 @@ Item {
|
|||||||
id: content
|
id: content
|
||||||
|
|
||||||
active: root.shouldBeActive || root.visible
|
active: root.shouldBeActive || root.visible
|
||||||
anchors.bottom: root.position === "top" ? parent.bottom : undefined
|
anchors.bottom: parent.bottom
|
||||||
anchors.horizontalCenter: root.position !== "left" ? parent.horizontalCenter : undefined
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.right: root.position !== "left" ? undefined : parent.right
|
|
||||||
anchors.top: root.position === "bottom" ? parent.top : undefined
|
|
||||||
anchors.verticalCenter: root.position === "left" ? undefined : parent.verticalCenter
|
|
||||||
|
|
||||||
sourceComponent: Content {
|
sourceComponent: Content {
|
||||||
dashState: root.dashState
|
dashState: root.dashState
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Item {
|
|||||||
property real offsetScale: shouldBeActive ? 0 : 1
|
property real offsetScale: shouldBeActive ? 0 : 1
|
||||||
required property var panels
|
required property var panels
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
readonly property bool shouldBeActive: visibilities.dock && Config.dock.enabled
|
readonly property bool shouldBeActive: visibilities.dock && Config.dock.enable
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
|
anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import ZShell.Config
|
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Modules.Bar.Components.Common
|
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
|
import ZShell.Config
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
WidgetBase {
|
CustomRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool tempEnabled: Hyprsunset.enabled
|
property bool tempEnabled: Hyprsunset.enabled
|
||||||
|
|
||||||
color: root.tempEnabled ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
|
color: root.tempEnabled ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
|
||||||
|
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
|
||||||
|
implicitWidth: implicitHeight
|
||||||
radius: Tokens.rounding.full
|
radius: Tokens.rounding.full
|
||||||
|
|
||||||
StateLayer {
|
StateLayer {
|
||||||
@@ -25,7 +26,6 @@ WidgetBase {
|
|||||||
animate: true
|
animate: true
|
||||||
color: root.tempEnabled ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
color: root.tempEnabled ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||||
fill: root.tempEnabled ? 1 : 0
|
fill: root.tempEnabled ? 1 : 0
|
||||||
font.pointSize: Tokens.font.size.larger
|
|
||||||
text: root.tempEnabled ? "lightbulb" : "light_off"
|
text: root.tempEnabled ? "lightbulb" : "light_off"
|
||||||
|
|
||||||
Behavior on fill {
|
Behavior on fill {
|
||||||
@@ -1,36 +1,28 @@
|
|||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import ZShell.Config
|
import QtQuick
|
||||||
import qs.Components
|
|
||||||
import qs.Services
|
|
||||||
import qs.Modules.Launcher.Items
|
|
||||||
import qs.Modules.Launcher.Services
|
import qs.Modules.Launcher.Services
|
||||||
|
import qs.Modules.Launcher.Items
|
||||||
|
import qs.Components
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
CustomListView {
|
CustomListView {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property string displayState: stateForText(displayText)
|
|
||||||
property string displayText
|
|
||||||
readonly property string requestedState: stateForText(search.text)
|
|
||||||
required property SearchBar search
|
required property SearchBar search
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
function resultsForText(text: string): var {
|
highlightFollowsCurrentItem: false
|
||||||
switch (stateForText(text)) {
|
highlightRangeMode: ListView.ApplyRange
|
||||||
case "actions":
|
implicitHeight: (Config.launcher.sizes.itemHeight + spacing) * Math.min(Config.launcher.maxAppsShown, count) - spacing
|
||||||
return Actions.query(text);
|
orientation: Qt.Vertical
|
||||||
case "calc":
|
preferredHighlightBegin: 0
|
||||||
return [0];
|
preferredHighlightEnd: height
|
||||||
case "variant":
|
spacing: Tokens.spacing.small
|
||||||
return SchemeVariants.query(text);
|
state: {
|
||||||
default:
|
const text = search.text;
|
||||||
return Apps.search(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function stateForText(text: string): string {
|
|
||||||
const prefix = Config.launcher.actionPrefix;
|
const prefix = Config.launcher.actionPrefix;
|
||||||
if (text.startsWith(prefix)) {
|
if (text.startsWith(prefix)) {
|
||||||
for (const action of ["calc", "scheme", "variant"])
|
for (const action of ["calc", "scheme", "variant"])
|
||||||
@@ -42,20 +34,6 @@ CustomListView {
|
|||||||
|
|
||||||
return "apps";
|
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
|
verticalLayoutDirection: ListView.BottomToTop
|
||||||
|
|
||||||
CustomScrollBar.vertical: CustomScrollBar {
|
CustomScrollBar.vertical: CustomScrollBar {
|
||||||
@@ -66,21 +44,19 @@ CustomListView {
|
|||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
from: 0
|
from: 0
|
||||||
property: "opacity"
|
properties: "opacity,scale"
|
||||||
to: 1
|
to: 1
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addDisplaced: Transition {
|
addDisplaced: Transition {
|
||||||
Anim {
|
Anim {
|
||||||
|
duration: Tokens.anim.durations.small
|
||||||
property: "y"
|
property: "y"
|
||||||
type: Anim.StandardSmall
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
property: "opacity"
|
properties: "opacity,scale"
|
||||||
to: 1
|
to: 1
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
displaced: Transition {
|
displaced: Transition {
|
||||||
@@ -89,9 +65,8 @@ CustomListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
property: "opacity"
|
properties: "opacity,scale"
|
||||||
to: 1
|
to: 1
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
highlight: CustomRect {
|
highlight: CustomRect {
|
||||||
@@ -110,7 +85,7 @@ CustomListView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
values: root.resultsForText(root.displayText)
|
id: model
|
||||||
|
|
||||||
onValuesChanged: root.currentIndex = 0
|
onValuesChanged: root.currentIndex = 0
|
||||||
}
|
}
|
||||||
@@ -120,9 +95,8 @@ CustomListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
property: "opacity"
|
properties: "opacity,scale"
|
||||||
to: 1
|
to: 1
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
remove: Transition {
|
remove: Transition {
|
||||||
@@ -130,9 +104,8 @@ CustomListView {
|
|||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
from: 1
|
from: 1
|
||||||
property: "opacity"
|
properties: "opacity,scale"
|
||||||
to: 0
|
to: 0
|
||||||
type: Anim.DefaultEffects
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
states: [
|
states: [
|
||||||
@@ -140,6 +113,7 @@ CustomListView {
|
|||||||
name: "apps"
|
name: "apps"
|
||||||
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
|
model.values: Apps.search(search.text)
|
||||||
root.delegate: appItem
|
root.delegate: appItem
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -147,6 +121,7 @@ CustomListView {
|
|||||||
name: "actions"
|
name: "actions"
|
||||||
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
|
model.values: Actions.query(search.text)
|
||||||
root.delegate: actionItem
|
root.delegate: actionItem
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -154,6 +129,7 @@ CustomListView {
|
|||||||
name: "calc"
|
name: "calc"
|
||||||
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
|
model.values: [0]
|
||||||
root.delegate: calcItem
|
root.delegate: calcItem
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -161,6 +137,7 @@ CustomListView {
|
|||||||
name: "variant"
|
name: "variant"
|
||||||
|
|
||||||
PropertyChanges {
|
PropertyChanges {
|
||||||
|
model.values: SchemeVariants.query(search.text)
|
||||||
root.delegate: variantItem
|
root.delegate: variantItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,7 +147,7 @@ CustomListView {
|
|||||||
ParallelAnimation {
|
ParallelAnimation {
|
||||||
Anim {
|
Anim {
|
||||||
duration: Tokens.anim.durations.small
|
duration: Tokens.anim.durations.small
|
||||||
easing.bezierCurve: Tokens.anim.curves.standardAccel
|
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
|
||||||
from: 1
|
from: 1
|
||||||
property: "opacity"
|
property: "opacity"
|
||||||
target: root
|
target: root
|
||||||
@@ -179,7 +156,7 @@ CustomListView {
|
|||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
duration: Tokens.anim.durations.small
|
duration: Tokens.anim.durations.small
|
||||||
easing.bezierCurve: Tokens.anim.curves.standardAccel
|
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
|
||||||
from: 1
|
from: 1
|
||||||
property: "scale"
|
property: "scale"
|
||||||
target: root
|
target: root
|
||||||
@@ -188,24 +165,14 @@ CustomListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PropertyAction {
|
PropertyAction {
|
||||||
property: "delegate"
|
properties: "values,delegate"
|
||||||
target: root
|
targets: [model, root]
|
||||||
value: null
|
|
||||||
}
|
|
||||||
|
|
||||||
ScriptAction {
|
|
||||||
script: root.displayText = root.search.text
|
|
||||||
}
|
|
||||||
|
|
||||||
PropertyAction {
|
|
||||||
property: "delegate"
|
|
||||||
target: root
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ParallelAnimation {
|
ParallelAnimation {
|
||||||
Anim {
|
Anim {
|
||||||
duration: Tokens.anim.durations.small
|
duration: Tokens.anim.durations.small
|
||||||
easing.bezierCurve: Tokens.anim.curves.standardDecel
|
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
|
||||||
from: 0
|
from: 0
|
||||||
property: "opacity"
|
property: "opacity"
|
||||||
target: root
|
target: root
|
||||||
@@ -214,7 +181,7 @@ CustomListView {
|
|||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
duration: Tokens.anim.durations.small
|
duration: Tokens.anim.durations.small
|
||||||
easing.bezierCurve: Tokens.anim.curves.standardDecel
|
easing.bezierCurve: Tokens.anim.curves.expressiveEffects
|
||||||
from: 0.9
|
from: 0.9
|
||||||
property: "scale"
|
property: "scale"
|
||||||
target: root
|
target: root
|
||||||
@@ -230,8 +197,6 @@ CustomListView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: displayText = search.text
|
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: appItem
|
id: appItem
|
||||||
|
|
||||||
@@ -263,20 +228,4 @@ CustomListView {
|
|||||||
list: root
|
list: root
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
function onTextChanged() {
|
|
||||||
root.syncDisplayText();
|
|
||||||
}
|
|
||||||
|
|
||||||
target: root.search
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
function onLauncherChanged() {
|
|
||||||
root.syncDisplayText();
|
|
||||||
}
|
|
||||||
|
|
||||||
target: root.visibilities
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.normal
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -79,7 +79,7 @@ Item {
|
|||||||
if (currentItem) {
|
if (currentItem) {
|
||||||
if (list.showWallpapers) {
|
if (list.showWallpapers) {
|
||||||
if (Colors.scheme === "dynamic" && currentItem.modelData.path !== Wallpapers.actualCurrent)
|
if (Colors.scheme === "dynamic" && currentItem.modelData.path !== Wallpapers.actualCurrent)
|
||||||
Wallpapers.previewColorLock = true;
|
Wallpapers.previewColourLock = true;
|
||||||
Wallpapers.setWallpaper(currentItem.modelData.path);
|
Wallpapers.setWallpaper(currentItem.modelData.path);
|
||||||
root.visibilities.launcher = false;
|
root.visibilities.launcher = false;
|
||||||
} else if (text.startsWith(Config.launcher.actionPrefix)) {
|
} else if (text.startsWith(Config.launcher.actionPrefix)) {
|
||||||
|
|||||||
@@ -110,9 +110,9 @@ Item {
|
|||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
width: root.implicitWidth
|
|
||||||
|
|
||||||
sourceComponent: CarouselView {
|
sourceComponent: WallpaperList {
|
||||||
|
content: root.content
|
||||||
panels: root.panels
|
panels: root.panels
|
||||||
search: root.search
|
search: root.search
|
||||||
visibilities: root.visibilities
|
visibilities: root.visibilities
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import ZShell.Models
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Modules
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property FileSystemEntry modelData
|
||||||
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
|
implicitHeight: image.height + label.height + Tokens.spacing.small / 2 + Tokens.padding.large + Tokens.padding.normal
|
||||||
|
implicitWidth: image.width + Tokens.padding.larger * 2
|
||||||
|
opacity: 0
|
||||||
|
scale: 0.5
|
||||||
|
z: PathView.z ?? 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Behavior on scale {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
scale = Qt.binding(() => PathView.isCurrentItem ? 1 : PathView.onPath ? 0.8 : 0);
|
||||||
|
opacity = Qt.binding(() => PathView.onPath ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
radius: Tokens.rounding.normal
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
Wallpapers.setWallpaper(root.modelData.path);
|
||||||
|
root.visibilities.launcher = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Elevation {
|
||||||
|
anchors.fill: image
|
||||||
|
level: 4
|
||||||
|
opacity: root.PathView.isCurrentItem ? 1 : 0
|
||||||
|
radius: image.radius
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomClippingRect {
|
||||||
|
id: image
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
|
implicitHeight: implicitWidth / 16 * 9
|
||||||
|
implicitWidth: Config.launcher.sizes.wallpaperWidth
|
||||||
|
radius: Tokens.rounding.small
|
||||||
|
y: Tokens.padding.large
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color: Colors.tPalette.m3outline
|
||||||
|
font.pointSize: Tokens.font.size.extraLarge * 2
|
||||||
|
font.weight: 600
|
||||||
|
text: "image"
|
||||||
|
}
|
||||||
|
|
||||||
|
CachingImage {
|
||||||
|
anchors.fill: parent
|
||||||
|
cache: true
|
||||||
|
path: root.modelData.path
|
||||||
|
smooth: !root.PathView.view.moving
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: label
|
||||||
|
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: image.bottom
|
||||||
|
anchors.topMargin: Tokens.spacing.small / 2
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.pointSize: Tokens.font.size.normal
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
renderType: Text.QtRendering
|
||||||
|
text: root.modelData.relativePath
|
||||||
|
width: image.width - Tokens.padding.normal * 2
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
import Quickshell
|
|
||||||
import QtQuick
|
|
||||||
import ZShell.Config
|
|
||||||
import qs.Components
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
required property bool isCurrent
|
|
||||||
required property var modelData // FileSystemEntry-like {path, relativePath}
|
|
||||||
required property real tileHeight
|
|
||||||
required property real tileWidth
|
|
||||||
required property PersistentProperties visibilities
|
|
||||||
|
|
||||||
signal requestActivate
|
|
||||||
|
|
||||||
implicitHeight: tileHeight + Tokens.padding.large * 2
|
|
||||||
implicitWidth: tileWidth
|
|
||||||
|
|
||||||
CustomClippingRect {
|
|
||||||
id: image
|
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
color: Colors.tPalette.m3surfaceContainer
|
|
||||||
implicitHeight: root.tileHeight
|
|
||||||
implicitWidth: root.tileWidth
|
|
||||||
radius: Tokens.rounding.small
|
|
||||||
y: Tokens.padding.large
|
|
||||||
|
|
||||||
MaterialIcon {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
color: Colors.tPalette.m3outline
|
|
||||||
font.pointSize: Tokens.font.size.extraLarge * 2
|
|
||||||
font.weight: 600
|
|
||||||
text: "image"
|
|
||||||
}
|
|
||||||
|
|
||||||
CachingImage {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.top: parent.top
|
|
||||||
cache: true
|
|
||||||
fillMode: Image.PreserveAspectCrop
|
|
||||||
height: root.tileHeight
|
|
||||||
path: root.modelData ? root.modelData.path : ""
|
|
||||||
smooth: root.isCurrent
|
|
||||||
sourceSize.height: root.tileHeight
|
|
||||||
sourceSize.width: root.tileHeight * (16 / 9)
|
|
||||||
width: root.tileHeight * (16 / 9)
|
|
||||||
}
|
|
||||||
|
|
||||||
StateLayer {
|
|
||||||
onClicked: root.requestActivate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -82,6 +82,7 @@ Searcher {
|
|||||||
list.visibilities.launcher = false;
|
list.visibilities.launcher = false;
|
||||||
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--scheme", variant]);
|
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--scheme", variant]);
|
||||||
Config.colors.schemeType = variant;
|
Config.colors.schemeType = variant;
|
||||||
|
Config.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import qs.Components
|
||||||
|
import qs.Helpers
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Modules.Launcher.Items
|
||||||
|
|
||||||
|
PathView {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var content
|
||||||
|
readonly property int itemWidth: Config.launcher.sizes.wallpaperWidth * 0.9 + Tokens.padding.larger * 2
|
||||||
|
readonly property int numItems: {
|
||||||
|
const screen = QsWindow.window?.screen;
|
||||||
|
if (!screen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Screen width - 4x outer rounding - 2x max side thickness (cause centered)
|
||||||
|
const barMargins = panels.bar.implicitWidth;
|
||||||
|
let outerMargins = 0;
|
||||||
|
if ((visibilities.utilities || visibilities.sidebar) && panels.utilities.implicitWidth > outerMargins)
|
||||||
|
outerMargins = panels.utilities.implicitWidth;
|
||||||
|
const maxWidth = screen.width - Config.bar.rounding * 4 - (barMargins + outerMargins) * 2;
|
||||||
|
|
||||||
|
if (maxWidth <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const maxItemsOnScreen = Math.floor(maxWidth / itemWidth);
|
||||||
|
const visible = Math.min(maxItemsOnScreen, Config.launcher.maxWallpapers, scriptModel.values.length);
|
||||||
|
|
||||||
|
if (visible === 2)
|
||||||
|
return 1;
|
||||||
|
if (visible > 1 && visible % 2 === 0)
|
||||||
|
return visible - 1;
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
required property var panels
|
||||||
|
required property SearchBar search
|
||||||
|
required property var visibilities
|
||||||
|
|
||||||
|
cacheItemCount: 4
|
||||||
|
highlightRangeMode: PathView.StrictlyEnforceRange
|
||||||
|
implicitWidth: Math.min(numItems, count) * itemWidth
|
||||||
|
pathItemCount: numItems
|
||||||
|
preferredHighlightBegin: 0.5
|
||||||
|
preferredHighlightEnd: 0.5
|
||||||
|
snapMode: PathView.SnapToItem
|
||||||
|
|
||||||
|
delegate: WallpaperItem {
|
||||||
|
visibilities: root.visibilities
|
||||||
|
}
|
||||||
|
model: ScriptModel {
|
||||||
|
id: scriptModel
|
||||||
|
|
||||||
|
readonly property string search: root.search.text.split(" ").slice(1).join(" ")
|
||||||
|
|
||||||
|
values: Wallpapers.query(search)
|
||||||
|
|
||||||
|
onValuesChanged: root.currentIndex = search ? 0 : values.findIndex(w => w.path === Wallpapers.actualCurrent)
|
||||||
|
}
|
||||||
|
path: Path {
|
||||||
|
startY: root.height / 2
|
||||||
|
|
||||||
|
PathAttribute {
|
||||||
|
name: "z"
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
PathLine {
|
||||||
|
relativeY: 0
|
||||||
|
x: root.width / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
PathAttribute {
|
||||||
|
name: "z"
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
PathLine {
|
||||||
|
relativeY: 0
|
||||||
|
x: root.width
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: currentIndex = Wallpapers.list.findIndex(w => w.path === Wallpapers.actualCurrent)
|
||||||
|
Component.onDestruction: Wallpapers.stopPreview()
|
||||||
|
onCurrentItemChanged: {
|
||||||
|
if (currentItem)
|
||||||
|
Wallpapers.preview(currentItem.modelData.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Components
|
||||||
|
import qs.Daemons
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
readonly property string currentMedia: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
|
||||||
|
readonly property int textWidth: Math.min(metrics.width, 200)
|
||||||
|
|
||||||
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
|
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
|
||||||
|
implicitWidth: layout.implicitWidth + Tokens.padding.normal * 2
|
||||||
|
radius: Tokens.rounding.full
|
||||||
|
|
||||||
|
Behavior on implicitWidth {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: metrics
|
||||||
|
|
||||||
|
font: mediatext.font
|
||||||
|
text: mediatext.text
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
Behavior on implicitWidth {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
animate: true
|
||||||
|
color: Players.active?.isPlaying ? Colors.palette.m3primary : Colors.palette.m3onSurface
|
||||||
|
font.pointSize: Tokens.font.size.larger
|
||||||
|
text: Players.active?.isPlaying ? "music_note" : "music_off"
|
||||||
|
}
|
||||||
|
|
||||||
|
MarqueeText {
|
||||||
|
id: mediatext
|
||||||
|
|
||||||
|
Layout.preferredWidth: root.textWidth
|
||||||
|
animate: true
|
||||||
|
color: Players.active?.isPlaying ? Colors.palette.m3primary : Colors.palette.m3onSurface
|
||||||
|
font.pointSize: Tokens.font.size.normal
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
marqueeEnabled: false
|
||||||
|
pauseMs: 4000
|
||||||
|
text: root.currentMedia
|
||||||
|
width: root.textWidth
|
||||||
|
|
||||||
|
CustomMouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
onContainsMouseChanged: {
|
||||||
|
if (!containsMouse) {
|
||||||
|
mediatext.marqueeEnabled = false;
|
||||||
|
} else {
|
||||||
|
mediatext.marqueeEnabled = true;
|
||||||
|
mediatext.anim.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Networking
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Components
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Modules
|
||||||
|
import qs.Helpers as Helpers
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var wrapper
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: Helpers.Network.devices
|
||||||
|
|
||||||
|
CustomRadioButton {
|
||||||
|
id: network
|
||||||
|
|
||||||
|
required property NetworkDevice modelData
|
||||||
|
|
||||||
|
checked: Helpers.Network.activeDevice?.name === modelData.name
|
||||||
|
text: modelData.description
|
||||||
|
visible: modelData.name !== "lo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Modules.Bar.Components.Common
|
|
||||||
import qs.Modules.Bar.Popouts
|
|
||||||
import qs.Daemons
|
import qs.Daemons
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
WidgetBase {
|
CustomRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property Wrapper popouts
|
required property Wrapper popouts
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
color: visibilities.sidebar ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
|
color: visibilities.sidebar ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
|
||||||
|
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
|
||||||
|
implicitWidth: implicitHeight
|
||||||
radius: Tokens.rounding.full
|
radius: Tokens.rounding.full
|
||||||
|
|
||||||
MaterialIcon {
|
MaterialIcon {
|
||||||
@@ -22,6 +22,7 @@ WidgetBase {
|
|||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
color: root.visibilities.sidebar ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
color: root.visibilities.sidebar ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||||
fill: root.visibilities.sidebar ? 1 : 0
|
fill: root.visibilities.sidebar ? 1 : 0
|
||||||
|
font.family: "Material Symbols Rounded"
|
||||||
font.pointSize: Tokens.font.size.larger
|
font.pointSize: Tokens.font.size.larger
|
||||||
text: NotifServer.list.length ? "\uf4fe" : "\ue7f4"
|
text: NotifServer.list.length ? "\uf4fe" : "\ue7f4"
|
||||||
|
|
||||||
@@ -464,7 +464,11 @@ CustomRect {
|
|||||||
|
|
||||||
enabled: root.expanded
|
enabled: root.expanded
|
||||||
fillWidth: true
|
fillWidth: true
|
||||||
font.pointSize: Tokens.font.size.small
|
font: {
|
||||||
|
const f = Qt.font(font);
|
||||||
|
f.pointSize = Tokens.font.size.small;
|
||||||
|
return f;
|
||||||
|
}
|
||||||
implicitWidth: label.implicitWidth
|
implicitWidth: label.implicitWidth
|
||||||
inactiveColor: root.modelData.urgency === NotificationUrgency.Critical ? Colors.palette.m3secondary : Colors.layer(Colors.palette.m3surfaceContainerHighest, 2)
|
inactiveColor: root.modelData.urgency === NotificationUrgency.Critical ? Colors.palette.m3secondary : Colors.layer(Colors.palette.m3surfaceContainerHighest, 2)
|
||||||
inactiveOnColor: root.modelData.urgency === NotificationUrgency.Critical ? Colors.palette.m3onSecondary : Colors.palette.m3onSurfaceVariant
|
inactiveOnColor: root.modelData.urgency === NotificationUrgency.Critical ? Colors.palette.m3onSecondary : Colors.palette.m3onSurfaceVariant
|
||||||
|
|||||||
@@ -5,14 +5,13 @@ import qs.Components
|
|||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
GridLayout {
|
RowLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property color accentColor: warning ? Colors.palette.m3error : mainColor
|
property color accentColor: warning ? Colors.palette.m3error : mainColor
|
||||||
property real animatedPercentage: 0
|
property real animatedPercentage: 0
|
||||||
readonly property real arcStartAngle: 0.75 * Math.PI
|
readonly property real arcStartAngle: 0.75 * Math.PI
|
||||||
readonly property real arcSweep: 1.5 * Math.PI
|
readonly property real arcSweep: 1.5 * Math.PI
|
||||||
required property bool horizontal
|
|
||||||
property string icon
|
property string icon
|
||||||
required property color iconColor
|
required property color iconColor
|
||||||
required property color mainColor
|
required property color mainColor
|
||||||
@@ -22,9 +21,8 @@ GridLayout {
|
|||||||
property bool warning: percentage * 100 >= warningThreshold
|
property bool warning: percentage * 100 >= warningThreshold
|
||||||
property int warningThreshold: 80
|
property int warningThreshold: 80
|
||||||
|
|
||||||
columnSpacing: Tokens.spacing.smaller
|
|
||||||
columns: horizontal ? -1 : 1
|
|
||||||
percentage: 0
|
percentage: 0
|
||||||
|
spacing: Tokens.spacing.smaller
|
||||||
|
|
||||||
Behavior on animatedPercentage {
|
Behavior on animatedPercentage {
|
||||||
Anim {
|
Anim {
|
||||||
@@ -49,8 +47,8 @@ GridLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CustomClippingRect {
|
CustomClippingRect {
|
||||||
Layout.preferredHeight: root.horizontal ? icon.implicitHeight - Tokens.padding.small : 4
|
Layout.preferredHeight: root.height - Tokens.padding.small
|
||||||
Layout.preferredWidth: root.horizontal ? 4 : icon.implicitWidth
|
Layout.preferredWidth: 4
|
||||||
color: Colors.layer(Colors.palette.m3surfaceContainerHigh, 2)
|
color: Colors.layer(Colors.palette.m3surfaceContainerHigh, 2)
|
||||||
radius: Tokens.rounding.full
|
radius: Tokens.rounding.full
|
||||||
|
|
||||||
@@ -59,11 +57,9 @@ GridLayout {
|
|||||||
|
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: root.horizontal ? parent.right : undefined
|
anchors.right: parent.right
|
||||||
anchors.top: root.horizontal ? undefined : parent.top
|
|
||||||
color: root.mainColor
|
color: root.mainColor
|
||||||
implicitHeight: root.horizontal ? Math.ceil(root.percentage * parent.height) : 0
|
implicitHeight: Math.ceil(root.percentage * parent.height)
|
||||||
implicitWidth: root.horizontal ? 0 : Math.ceil(root.percentage * parent.width)
|
|
||||||
|
|
||||||
// Behavior on implicitHeight {
|
// Behavior on implicitHeight {
|
||||||
// Anim {
|
// Anim {
|
||||||
@@ -6,18 +6,18 @@ import QtQuick.Layouts
|
|||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import ZShell.Services
|
import ZShell.Services
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Modules.Bar.Components.Common
|
import qs.Modules
|
||||||
import qs.Components
|
import qs.Components
|
||||||
|
|
||||||
WidgetBase {
|
CustomRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
color: visibilities.resources ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
|
color: visibilities.resources ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
|
||||||
implicitHeight: horizontal ? baseSize : gridLayout.implicitHeight + Tokens.padding.normal * 2
|
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
|
||||||
implicitWidth: horizontal ? gridLayout.implicitWidth + Tokens.padding.larger * 2 : baseSize
|
implicitWidth: rowLayout.implicitWidth + Tokens.padding.larger * 2
|
||||||
radius: Tokens.rounding.full
|
radius: Tokens.rounding.full
|
||||||
|
|
||||||
StateLayer {
|
StateLayer {
|
||||||
@@ -26,14 +26,13 @@ WidgetBase {
|
|||||||
onClicked: root.visibilities.resources = !root.visibilities.resources
|
onClicked: root.visibilities.resources = !root.visibilities.resources
|
||||||
}
|
}
|
||||||
|
|
||||||
GridLayout {
|
RowLayout {
|
||||||
id: gridLayout
|
id: rowLayout
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
anchors.horizontalCenterOffset: root.horizontal ? 0 : 1
|
anchors.horizontalCenterOffset: -2
|
||||||
anchors.verticalCenterOffset: root.horizontal ? 0 : -3
|
implicitHeight: root.implicitHeight
|
||||||
columnSpacing: Tokens.spacing.smaller
|
spacing: Tokens.spacing.smaller
|
||||||
columns: root.horizontal ? -1 : 1
|
|
||||||
|
|
||||||
ServiceRef {
|
ServiceRef {
|
||||||
service: Gpu
|
service: Gpu
|
||||||
@@ -49,9 +48,7 @@ WidgetBase {
|
|||||||
|
|
||||||
Resource {
|
Resource {
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
Layout.fillHeight: root.horizontal
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: !root.horizontal
|
|
||||||
horizontal: root.horizontal
|
|
||||||
icon: "memory"
|
icon: "memory"
|
||||||
iconColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
iconColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||||
mainColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3primary
|
mainColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3primary
|
||||||
@@ -60,9 +57,7 @@ WidgetBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Resource {
|
Resource {
|
||||||
Layout.fillHeight: root.horizontal
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: !root.horizontal
|
|
||||||
horizontal: root.horizontal
|
|
||||||
icon: "memory_alt"
|
icon: "memory_alt"
|
||||||
iconColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
iconColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||||
mainColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3secondary
|
mainColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3secondary
|
||||||
@@ -71,9 +66,7 @@ WidgetBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Resource {
|
Resource {
|
||||||
Layout.fillHeight: root.horizontal
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: !root.horizontal
|
|
||||||
horizontal: root.horizontal
|
|
||||||
icon: "gamepad"
|
icon: "gamepad"
|
||||||
iconColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
iconColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||||
mainColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3tertiary
|
mainColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3tertiary
|
||||||
@@ -81,9 +74,7 @@ WidgetBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Resource {
|
Resource {
|
||||||
Layout.fillHeight: root.horizontal
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: !root.horizontal
|
|
||||||
horizontal: root.horizontal
|
|
||||||
icon: "developer_board"
|
icon: "developer_board"
|
||||||
iconColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
iconColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||||
mainColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3primary
|
mainColor: root.visibilities.resources ? Colors.palette.m3onPrimary : Colors.palette.m3primary
|
||||||
@@ -10,16 +10,10 @@ Item {
|
|||||||
|
|
||||||
readonly property real nonAnimHeight: content.item?.nonAnimHeight ?? 0
|
readonly property real nonAnimHeight: content.item?.nonAnimHeight ?? 0
|
||||||
property real offsetScale: shouldBeActive ? 0 : 1
|
property real offsetScale: shouldBeActive ? 0 : 1
|
||||||
required property string position
|
|
||||||
readonly property bool shouldBeActive: root.visibilities.resources
|
readonly property bool shouldBeActive: root.visibilities.resources
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
|
|
||||||
anchors.bottom: position === "bottom" ? parent.bottom : undefined
|
anchors.topMargin: (-implicitHeight - 5) * offsetScale
|
||||||
anchors.bottomMargin: position === "bottom" ? (-implicitHeight - 5) * offsetScale : 0
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: position === "left" ? (-implicitWidth - 5) * offsetScale : 0
|
|
||||||
anchors.top: position !== "bottom" ? parent.top : undefined
|
|
||||||
anchors.topMargin: position === "top" ? (-implicitHeight - 5) * offsetScale : 0
|
|
||||||
clip: true
|
clip: true
|
||||||
implicitHeight: content.implicitHeight
|
implicitHeight: content.implicitHeight
|
||||||
implicitWidth: content.implicitWidth || 854 // Hard coded fallback for first open
|
implicitWidth: content.implicitWidth || 854 // Hard coded fallback for first open
|
||||||
@@ -37,11 +31,7 @@ Item {
|
|||||||
id: content
|
id: content
|
||||||
|
|
||||||
active: root.shouldBeActive || root.visible
|
active: root.shouldBeActive || root.visible
|
||||||
anchors.bottom: root.position === "top" ? parent.bottom : undefined
|
anchors.centerIn: parent
|
||||||
anchors.horizontalCenter: root.position !== "left" ? parent.horizontalCenter : undefined
|
|
||||||
anchors.right: root.position !== "left" ? undefined : parent.right
|
|
||||||
anchors.top: root.position === "bottom" ? parent.top : undefined
|
|
||||||
anchors.verticalCenter: root.position === "left" ? undefined : parent.verticalCenter
|
|
||||||
|
|
||||||
sourceComponent: Content {
|
sourceComponent: Content {
|
||||||
wrapper: root
|
wrapper: root
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ pragma Singleton
|
|||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import ZShell.Config
|
|
||||||
import qs.Components
|
import qs.Components
|
||||||
|
import ZShell.Config
|
||||||
import qs.Modules.Settings.Common
|
import qs.Modules.Settings.Common
|
||||||
import qs.Modules.Settings.Pages
|
import qs.Modules.Settings.Pages
|
||||||
import qs.Modules.Settings.Pages.Wallpaper
|
import qs.Modules.Settings.Pages.Wallpaper
|
||||||
@@ -45,11 +45,7 @@ QtObject {
|
|||||||
|
|
||||||
// Connectivity
|
// Connectivity
|
||||||
Component {
|
Component {
|
||||||
StackPage {
|
PlaceholderComp {
|
||||||
Component {
|
|
||||||
NetworkPage {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Component {
|
Component {
|
||||||
|
|||||||
@@ -1,240 +0,0 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import QtQuick
|
|
||||||
import QtQuick.Layouts
|
|
||||||
import Quickshell
|
|
||||||
import ZShell.Config
|
|
||||||
import qs.Modules.Settings.Common
|
|
||||||
import qs.Modules.Bar.Popouts.Network
|
|
||||||
import qs.Components
|
|
||||||
import qs.Helpers
|
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
PageBase {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
title: qsTr("Network")
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: networkContent
|
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.top: parent.top
|
|
||||||
spacing: Tokens.spacing.extraSmall / 2
|
|
||||||
width: root.cappedWidth
|
|
||||||
|
|
||||||
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 {
|
|
||||||
id: connected
|
|
||||||
|
|
||||||
visible: Network.connectedNetworks.length > 0
|
|
||||||
|
|
||||||
model: ScriptModel {
|
|
||||||
values: [...Network.connectedNetworks].sort((a, b) => {
|
|
||||||
return b.signalStrength - a.signalStrength;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkItem {
|
|
||||||
first: false
|
|
||||||
known: true
|
|
||||||
repeater: connected
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,9 +8,7 @@ PageBase {
|
|||||||
readonly property var builtinIcons: ({
|
readonly property var builtinIcons: ({
|
||||||
audio: qsTr("Speakers"),
|
audio: qsTr("Speakers"),
|
||||||
microphone: qsTr("Microphone"),
|
microphone: qsTr("Microphone"),
|
||||||
power: qsTr("Battery"),
|
power: qsTr("Battery")
|
||||||
network: qsTr("Network"),
|
|
||||||
bluetooth: qsTr("Bluetooth")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
isSubPage: true
|
isSubPage: true
|
||||||
@@ -93,15 +91,5 @@ PageBase {
|
|||||||
|
|
||||||
onToggled: Config.bar.popouts.statusIcons = checked
|
onToggled: Config.bar.popouts.statusIcons = checked
|
||||||
}
|
}
|
||||||
|
|
||||||
ToggleRow {
|
|
||||||
checked: Config.bar.popouts.network
|
|
||||||
last: true
|
|
||||||
settingAnchor: "bar-status-network-popout"
|
|
||||||
subtext: qsTr("Show a details popout when hovering the network icon")
|
|
||||||
text: qsTr("Network popout on hover")
|
|
||||||
|
|
||||||
onToggled: Config.bar.popouts.network = checked
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ pragma ComponentBehavior: Bound
|
|||||||
|
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Components
|
|
||||||
import qs.Modules.Settings.Common
|
import qs.Modules.Settings.Common
|
||||||
|
|
||||||
PageBase {
|
PageBase {
|
||||||
@@ -26,6 +25,7 @@ PageBase {
|
|||||||
ToggleRow {
|
ToggleRow {
|
||||||
checked: Config.bar.autoHide
|
checked: Config.bar.autoHide
|
||||||
first: true
|
first: true
|
||||||
|
last: true
|
||||||
settingAnchor: "bar-autohide"
|
settingAnchor: "bar-autohide"
|
||||||
subtext: qsTr("Hide the bar, reveal on hover")
|
subtext: qsTr("Hide the bar, reveal on hover")
|
||||||
text: qsTr("Auto hide")
|
text: qsTr("Auto hide")
|
||||||
@@ -33,55 +33,6 @@ PageBase {
|
|||||||
onToggled: Config.bar.autoHide = checked
|
onToggled: Config.bar.autoHide = checked
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectRow {
|
|
||||||
active: Config.bar.position === "top" ? menuItems[0] : Config.bar.position === "left" ? menuItems[1] : menuItems[2]
|
|
||||||
settingAnchor: "bar-position"
|
|
||||||
subtext: qsTr("Change which edge the bar appears on")
|
|
||||||
text: qsTr("Position")
|
|
||||||
|
|
||||||
menuItems: [
|
|
||||||
MenuItem {
|
|
||||||
icon: "build"
|
|
||||||
text: qsTr("Top")
|
|
||||||
value: "top"
|
|
||||||
},
|
|
||||||
MenuItem {
|
|
||||||
icon: "rotate_auto"
|
|
||||||
text: qsTr("Left")
|
|
||||||
value: "left"
|
|
||||||
},
|
|
||||||
MenuItem {
|
|
||||||
icon: "rotate_auto"
|
|
||||||
text: qsTr("Bottom")
|
|
||||||
value: "bottom"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
onSelected: item => Config.bar.position = item.value
|
|
||||||
}
|
|
||||||
|
|
||||||
ToggleRow {
|
|
||||||
checked: Config.bar.fullscreenReveal
|
|
||||||
settingAnchor: "bar-fullscreen-reveal"
|
|
||||||
subtext: qsTr("Hover top edge to show bar in fullscreen")
|
|
||||||
text: qsTr("Reveal on edge")
|
|
||||||
|
|
||||||
onToggled: Config.bar.fullscreenReveal = checked
|
|
||||||
}
|
|
||||||
|
|
||||||
SpinRow {
|
|
||||||
from: 0
|
|
||||||
last: true
|
|
||||||
settingAnchor: "bar-reveal-delay"
|
|
||||||
stepSize: 100
|
|
||||||
subtext: qsTr("The delay before bar is revealed when cursor is at edge")
|
|
||||||
text: qsTr("Reveal delay")
|
|
||||||
to: 2000
|
|
||||||
value: Config.bar.revealDelay
|
|
||||||
|
|
||||||
onMoved: v => Config.bar.revealDelay = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
SectionHeader {
|
SectionHeader {
|
||||||
text: qsTr("Components")
|
text: qsTr("Components")
|
||||||
|
|||||||
@@ -70,7 +70,10 @@ PageBase {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
onSelected: item => Config.screenshot.mode = item.value
|
onSelected: item => {
|
||||||
|
Config.screenshot.mode = item.value;
|
||||||
|
Config.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionHeader {
|
SectionHeader {
|
||||||
|
|||||||
@@ -40,19 +40,40 @@ PageBase {
|
|||||||
id: localWalls
|
id: localWalls
|
||||||
|
|
||||||
model: {
|
model: {
|
||||||
const walls = [...Wallpapers.list];
|
const walls = Wallpapers.list;
|
||||||
var baseDir = Paths.wallsdir;
|
var baseDir = Paths.wallsdir;
|
||||||
walls.sort((a, b) => ((a.parentDir === baseDir) - (b.parentDir === baseDir)) || a.name.localeCompare(b.name));
|
const categories = {};
|
||||||
while (walls.length < 4)
|
const list = [];
|
||||||
walls.push(null);
|
for (const w of walls) {
|
||||||
|
var parentDir = w.parentDir;
|
||||||
|
if (!parentDir.endsWith("/"))
|
||||||
|
parentDir = parentDir + "/";
|
||||||
|
|
||||||
return walls;
|
if (!baseDir.endsWith("/"))
|
||||||
|
baseDir = baseDir + "/";
|
||||||
|
|
||||||
|
if (parentDir !== baseDir) {
|
||||||
|
const category = Wallpapers.getCategoryFor(w);
|
||||||
|
if (category && (!(category in categories) || categories[category].name.localeCompare(w.name) > 0))
|
||||||
|
categories[category] = w;
|
||||||
|
} else {
|
||||||
|
list.push(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.push(...Object.values(categories));
|
||||||
|
list.sort((a, b) => ((a.parentDir === baseDir) - (b.parentDir === baseDir)) || a.name.localeCompare(b.name));
|
||||||
|
while (list.length < 4)
|
||||||
|
list.push(null);
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
WallItem {
|
WallItem {
|
||||||
required property FileSystemEntry modelData
|
required property FileSystemEntry modelData
|
||||||
|
|
||||||
enabled: modelData
|
enabled: modelData
|
||||||
|
|
||||||
|
// Empty placeholders for sizing
|
||||||
opacity: modelData ? 1 : 0
|
opacity: modelData ? 1 : 0
|
||||||
source: String(modelData?.path ?? "")
|
source: String(modelData?.path ?? "")
|
||||||
|
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ PageBase {
|
|||||||
onApplySettings: (start, end) => {
|
onApplySettings: (start, end) => {
|
||||||
Config.general.color.scheduleDarkStart = start;
|
Config.general.color.scheduleDarkStart = start;
|
||||||
Config.general.color.scheduleDarkEnd = end;
|
Config.general.color.scheduleDarkEnd = end;
|
||||||
|
Config.save();
|
||||||
ModeScheduler.checkStartup();
|
ModeScheduler.checkStartup();
|
||||||
PopupManager.requestClose();
|
PopupManager.requestClose();
|
||||||
}
|
}
|
||||||
@@ -145,6 +146,7 @@ PageBase {
|
|||||||
onApplySettings: (start, end) => {
|
onApplySettings: (start, end) => {
|
||||||
Config.general.color.scheduleHyprsunsetStart = start;
|
Config.general.color.scheduleHyprsunsetStart = start;
|
||||||
Config.general.color.scheduleHyprsunsetEnd = end;
|
Config.general.color.scheduleHyprsunsetEnd = end;
|
||||||
|
Config.save();
|
||||||
Hyprsunset.checkStartup();
|
Hyprsunset.checkStartup();
|
||||||
PopupManager.requestClose();
|
PopupManager.requestClose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
pragma ComponentBehavior: Bound
|
|
||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real offsetScale: shouldBeActive ? 0 : 1
|
property real offsetScale: shouldBeActive ? 0 : 1
|
||||||
required property var panels
|
required property var panels
|
||||||
property string queuedMode: "wallpaper"
|
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
readonly property bool shouldBeActive: visibilities.settings
|
readonly property bool shouldBeActive: visibilities.settings
|
||||||
required property PersistentProperties visibilities
|
required property PersistentProperties visibilities
|
||||||
@@ -39,7 +37,7 @@ Item {
|
|||||||
|
|
||||||
sourceComponent: Content {
|
sourceComponent: Content {
|
||||||
sState.animatingContainer: content.opacity < 1
|
sState.animatingContainer: content.opacity < 1
|
||||||
sState.currentPageIdx: ["wallpaper"].indexOf(root.queuedMode)
|
sState.currentPageIdx: ["wallpaper"][0]
|
||||||
sState.screen: root.screen
|
sState.screen: root.screen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import QtQuick
|
|||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell.Services.UPower
|
import Quickshell.Services.UPower
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Modules.Bar.Components.Common
|
import qs.Modules.SysTray.Common
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Services
|
import qs.Services
|
||||||
@@ -3,14 +3,13 @@ pragma ComponentBehavior: Bound
|
|||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import ZShell.Config
|
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
import qs.Modules.Bar.Components.StatusIcons
|
import qs.Modules.SysTray.Widgets
|
||||||
import qs.Modules.Bar.Components.Common
|
import ZShell.Config
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
WidgetBase {
|
CustomClippingRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property int firstPresent: {
|
readonly property int firstPresent: {
|
||||||
@@ -22,7 +21,7 @@ WidgetBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Index of the first/last entry that isn't collapsed, for edge margin gating
|
// Index of the first/last entry that isn't collapsed, for edge margin gating
|
||||||
readonly property alias items: grid
|
readonly property alias items: row
|
||||||
readonly property int lastPresent: {
|
readonly property int lastPresent: {
|
||||||
const values = model.values;
|
const values = model.values;
|
||||||
for (let i = values.length - 1; i >= 0; i--)
|
for (let i = values.length - 1; i >= 0; i--)
|
||||||
@@ -30,7 +29,6 @@ WidgetBase {
|
|||||||
return i;
|
return i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
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
|
readonly property int spacing: Tokens.spacing.normal / 2
|
||||||
|
|
||||||
// Entries that can shrink to nothing, spacing included
|
// Entries that can shrink to nothing, spacing included
|
||||||
@@ -40,36 +38,19 @@ WidgetBase {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bottomLeftRadius: horizontal ? Tokens.rounding.smallest / 2 : Tokens.rounding.full
|
bottomLeftRadius: Tokens.rounding.smallest / 2
|
||||||
color: Colors.tPalette.m3surfaceContainer
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
implicitHeight: horizontal ? baseSize : size
|
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
|
||||||
implicitWidth: horizontal ? size : baseSize
|
implicitWidth: row.implicitWidth + Tokens.padding.small * 2
|
||||||
radius: Tokens.rounding.full
|
radius: Tokens.rounding.full
|
||||||
topLeftRadius: Tokens.rounding.smallest / 2
|
topLeftRadius: Tokens.rounding.smallest / 2
|
||||||
topRightRadius: horizontal ? Tokens.rounding.full : Tokens.rounding.smallest / 2
|
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
RowLayout {
|
||||||
enabled: !root.horizontal
|
id: row
|
||||||
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on implicitWidth {
|
|
||||||
enabled: root.horizontal
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GridLayout {
|
|
||||||
id: grid
|
|
||||||
|
|
||||||
anchors.bottomMargin: root.horizontal ? 0 : Tokens.padding.small
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.leftMargin: root.horizontal ? Tokens.padding.small : 0
|
anchors.leftMargin: Tokens.padding.small
|
||||||
anchors.rightMargin: root.horizontal ? Tokens.padding.small : 0
|
anchors.rightMargin: Tokens.padding.small
|
||||||
anchors.topMargin: root.horizontal ? 0 : Tokens.padding.small
|
|
||||||
columns: root.horizontal ? -1 : 1
|
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: ScriptModel {
|
model: ScriptModel {
|
||||||
@@ -88,7 +69,6 @@ WidgetBase {
|
|||||||
name: "audio"
|
name: "audio"
|
||||||
|
|
||||||
AudioWidget {
|
AudioWidget {
|
||||||
horizontal: root.horizontal
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,29 +80,6 @@ WidgetBase {
|
|||||||
name: "audio"
|
name: "audio"
|
||||||
|
|
||||||
MicWidget {
|
MicWidget {
|
||||||
horizontal: root.horizontal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: "bluetooth"
|
|
||||||
|
|
||||||
delegate: EntryWrapper {
|
|
||||||
name: "bluetooth"
|
|
||||||
|
|
||||||
BluetoothWidget {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DelegateChoice {
|
|
||||||
roleValue: "network"
|
|
||||||
|
|
||||||
delegate: EntryWrapper {
|
|
||||||
name: "network"
|
|
||||||
|
|
||||||
NetworkWidget {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,10 +109,8 @@ WidgetBase {
|
|||||||
property real rightGap: present && index !== root.firstPresent ? margin : 0
|
property real rightGap: present && index !== root.firstPresent ? margin : 0
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
Layout.bottomMargin: root.horizontal ? 0 : Math.round(rightGap)
|
Layout.leftMargin: Math.round(leftGap)
|
||||||
Layout.leftMargin: root.horizontal ? Math.round(leftGap) : 0
|
Layout.rightMargin: Math.round(rightGap)
|
||||||
Layout.rightMargin: root.horizontal ? Math.round(rightGap) : 0
|
|
||||||
Layout.topMargin: root.horizontal ? 0 : Math.round(leftGap)
|
|
||||||
children: item
|
children: item
|
||||||
implicitHeight: item?.implicitHeight ?? 0
|
implicitHeight: item?.implicitHeight ?? 0
|
||||||
implicitWidth: item?.implicitWidth ?? 0
|
implicitWidth: item?.implicitWidth ?? 0
|
||||||
@@ -3,37 +3,33 @@ pragma ComponentBehavior: Bound
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell.Services.SystemTray
|
import Quickshell.Services.SystemTray
|
||||||
import ZShell.Config
|
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Modules.Bar.Components.Common
|
import ZShell.Config
|
||||||
import qs.Modules.Bar.Components.Tray
|
import qs.Modules.SysTray.Widgets
|
||||||
import qs.Modules.Bar.Popouts
|
import qs.Modules
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
WidgetBase {
|
CustomClippingRect {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property alias items: repeater
|
readonly property alias items: repeater
|
||||||
readonly property alias layout: sysGrid
|
readonly property alias layout: sysRow
|
||||||
required property GridLayout loader
|
required property RowLayout loader
|
||||||
readonly property int padding: Tokens.padding.small
|
readonly property int padding: Tokens.padding.small
|
||||||
required property Wrapper popouts
|
required property Wrapper popouts
|
||||||
readonly property real size: horizontal ? sysGrid.implicitWidth + Tokens.padding.small : sysGrid.implicitHeight + Tokens.padding.small
|
|
||||||
|
|
||||||
bottomLeftRadius: horizontal ? Tokens.rounding.full : Tokens.rounding.smallest / 2
|
|
||||||
bottomRightRadius: Tokens.rounding.smallest / 2
|
bottomRightRadius: Tokens.rounding.smallest / 2
|
||||||
color: Colors.tPalette.m3surfaceContainer
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
implicitHeight: horizontal ? baseSize : size
|
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
|
||||||
implicitWidth: horizontal ? size : baseSize
|
implicitWidth: sysRow.implicitWidth + Tokens.padding.small * 2
|
||||||
radius: Tokens.rounding.full
|
radius: Tokens.rounding.full
|
||||||
topRightRadius: horizontal ? Tokens.rounding.smallest / 2 : Tokens.rounding.full
|
topRightRadius: Tokens.rounding.smallest / 2
|
||||||
|
|
||||||
GridLayout {
|
RowLayout {
|
||||||
id: sysGrid
|
id: sysRow
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
columns: root.horizontal ? -1 : 1
|
spacing: 0
|
||||||
rowSpacing: -2
|
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: repeater
|
id: repeater
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick
|
import QtQuick
|
||||||
|
import QtQuick.VectorImage
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Services.SystemTray
|
import Quickshell.Services.SystemTray
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
import qs.Modules.Bar.Popouts
|
import qs.Modules
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Services
|
import qs.Services
|
||||||
@@ -12,10 +13,10 @@ Item {
|
|||||||
id: root
|
id: root
|
||||||
|
|
||||||
property bool current: popouts.currentName.startsWith(`traymenu${ind}`) && popouts.hasCurrent
|
property bool current: popouts.currentName.startsWith(`traymenu${ind}`) && popouts.hasCurrent
|
||||||
readonly property real dpr: Hypr.monitorFor(loader?.screen).scale
|
readonly property real dpr: Hypr.monitorFor(loader.screen).scale
|
||||||
required property int ind
|
required property int ind
|
||||||
required property SystemTrayItem item
|
required property SystemTrayItem item
|
||||||
required property GridLayout loader
|
required property RowLayout loader
|
||||||
required property Wrapper popouts
|
required property Wrapper popouts
|
||||||
|
|
||||||
function resolveIcon(app: string, icon: string): string {
|
function resolveIcon(app: string, icon: string): string {
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell.Services.SystemTray
|
||||||
|
import qs.Components
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Modules.SysTray.Widgets
|
||||||
|
import qs.Modules
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
readonly property alias items: repeater
|
||||||
|
required property RowLayout loader
|
||||||
|
required property Wrapper popouts
|
||||||
|
|
||||||
|
function closestRowChild(row, x) {
|
||||||
|
let child = row.childAt(x, row.height / 2);
|
||||||
|
if (child)
|
||||||
|
return child;
|
||||||
|
|
||||||
|
let closest = null;
|
||||||
|
let closestDistance = Infinity;
|
||||||
|
|
||||||
|
for (let i = 0; i < row.children.length; ++i) {
|
||||||
|
let c = row.children[i];
|
||||||
|
|
||||||
|
if (!c.visible || c.width <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let centerX = c.x + c.width / 2;
|
||||||
|
let dist = Math.abs(x - centerX);
|
||||||
|
|
||||||
|
if (dist < closestDistance) {
|
||||||
|
closestDistance = dist;
|
||||||
|
closest = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return closest;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHoveredSubItem(localX, localY) {
|
||||||
|
let modPos = mapToItem(sysTrayMod, localX, localY);
|
||||||
|
if (sysTrayMod.contains(Qt.point(modPos.x, modPos.y))) {
|
||||||
|
let modRowPos = sysTrayMod.mapToItem(sysIcons, modPos.x, modPos.y);
|
||||||
|
let child = closestRowChild(sysIcons, modRowPos.x);
|
||||||
|
if (child) {
|
||||||
|
if (child.objectName === "audio" && Config.bar.popouts.audio)
|
||||||
|
return {
|
||||||
|
id: "audio",
|
||||||
|
item: child
|
||||||
|
};
|
||||||
|
if (child.objectName === "microphone" && Config.bar.popouts.audio)
|
||||||
|
return {
|
||||||
|
id: "audio",
|
||||||
|
item: child
|
||||||
|
};
|
||||||
|
if (child.objectName === "upower" && Config.bar.popouts.upower)
|
||||||
|
return {
|
||||||
|
id: "upower",
|
||||||
|
item: child
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let trayPos = mapToItem(sysTray, localX, localY);
|
||||||
|
if (Config.bar.tray.showOnHover && sysTray.contains(Qt.point(trayPos.x, trayPos.y))) {
|
||||||
|
let trayRowPos = sysTray.mapToItem(sysRow, trayPos.x, trayPos.y);
|
||||||
|
let child = sysRow.childAt(trayRowPos.x, trayRowPos.y);
|
||||||
|
if (child && child.hasOwnProperty("ind")) {
|
||||||
|
return {
|
||||||
|
id: `traymenu${child.ind}`,
|
||||||
|
item: child
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
height: Config.bar.height + Tokens.padding.smallest * 2
|
||||||
|
spacing: Tokens.padding.small
|
||||||
|
width: sysTray.implicitWidth + sysTrayMod.implicitWidth + Tokens.padding.small
|
||||||
|
|
||||||
|
CustomClippingRect {
|
||||||
|
id: sysTray
|
||||||
|
|
||||||
|
Layout.fillHeight: true
|
||||||
|
bottomRightRadius: Tokens.rounding.smallest / 2
|
||||||
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
|
implicitWidth: sysRow.width + Tokens.padding.small * 2
|
||||||
|
radius: Tokens.rounding.full
|
||||||
|
topRightRadius: Tokens.rounding.smallest / 2
|
||||||
|
|
||||||
|
Row {
|
||||||
|
id: sysRow
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: repeater
|
||||||
|
|
||||||
|
model: SystemTray.items
|
||||||
|
|
||||||
|
TrayItem {
|
||||||
|
id: trayItem
|
||||||
|
|
||||||
|
required property int index
|
||||||
|
required property SystemTrayItem modelData
|
||||||
|
|
||||||
|
implicitHeight: 34
|
||||||
|
implicitWidth: 34
|
||||||
|
ind: index
|
||||||
|
item: modelData
|
||||||
|
loader: root.loader
|
||||||
|
popouts: root.popouts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomClippingRect {
|
||||||
|
id: sysTrayMod
|
||||||
|
|
||||||
|
Layout.fillHeight: true
|
||||||
|
bottomLeftRadius: Tokens.rounding.smallest / 2
|
||||||
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
|
implicitWidth: sysIcons.implicitWidth + Tokens.padding.smaller + Tokens.padding.normal
|
||||||
|
radius: Tokens.rounding.full
|
||||||
|
topLeftRadius: Tokens.rounding.smallest / 2
|
||||||
|
|
||||||
|
StatusIcons {
|
||||||
|
id: sysIcons
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Tokens.padding.smaller
|
||||||
|
anchors.rightMargin: Tokens.padding.normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-3
@@ -1,15 +1,16 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import ZShell.Config
|
import Quickshell.Io
|
||||||
|
import Quickshell.Services.Pipewire
|
||||||
import qs.Daemons
|
import qs.Daemons
|
||||||
|
import qs.Modules
|
||||||
|
import ZShell.Config
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
MaterialIcon {
|
MaterialIcon {
|
||||||
id: speaker
|
id: speaker
|
||||||
|
|
||||||
required property bool horizontal
|
|
||||||
|
|
||||||
animate: true
|
animate: true
|
||||||
color: Audio.muted ? Colors.palette.m3error : Colors.palette.m3onSurface
|
color: Audio.muted ? Colors.palette.m3error : Colors.palette.m3onSurface
|
||||||
fill: 1
|
fill: 1
|
||||||
+4
-3
@@ -1,15 +1,16 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import ZShell.Config
|
import Quickshell.Io
|
||||||
|
import Quickshell.Services.Pipewire
|
||||||
import qs.Daemons
|
import qs.Daemons
|
||||||
|
import qs.Modules
|
||||||
|
import ZShell.Config
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
MaterialIcon {
|
MaterialIcon {
|
||||||
id: mic
|
id: mic
|
||||||
|
|
||||||
required property bool horizontal
|
|
||||||
|
|
||||||
animate: true
|
animate: true
|
||||||
color: (Audio.sourceMuted ?? false) ? Colors.palette.m3error : Colors.palette.m3onSurface
|
color: (Audio.sourceMuted ?? false) ? Colors.palette.m3error : Colors.palette.m3onSurface
|
||||||
fill: 1
|
fill: 1
|
||||||
+5
-6
@@ -1,8 +1,7 @@
|
|||||||
import Quickshell.Services.UPower
|
import Quickshell.Services.UPower
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import ZShell.Config
|
import qs.Modules.SysTray.Common
|
||||||
import qs.Modules.Bar.Components.Common
|
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
|
|
||||||
@@ -13,6 +12,7 @@ Item {
|
|||||||
|
|
||||||
implicitHeight: currentItem?.implicitHeight ?? 0
|
implicitHeight: currentItem?.implicitHeight ?? 0
|
||||||
implicitWidth: currentItem?.implicitWidth ?? 0
|
implicitWidth: currentItem?.implicitWidth ?? 0
|
||||||
|
visible: opacity > 0
|
||||||
|
|
||||||
Behavior on Layout.preferredHeight {
|
Behavior on Layout.preferredHeight {
|
||||||
Anim {
|
Anim {
|
||||||
@@ -48,12 +48,12 @@ Item {
|
|||||||
Loader {
|
Loader {
|
||||||
id: peripheralIconLoader
|
id: peripheralIconLoader
|
||||||
|
|
||||||
active: (Battery.lowestPeripheral?.isPresent ?? false) && !batteryIconLoader.active
|
active: Battery.lowestPeripheral.isPresent && !batteryIconLoader.active
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
|
|
||||||
sourceComponent: BatteryIcon {
|
sourceComponent: BatteryIcon {
|
||||||
devState: Battery.lowestPeripheral?.state ?? ""
|
devState: Battery.lowestPeripheral.state
|
||||||
percentage: Battery.lowestPeripheral?.percentage ?? 0
|
percentage: Battery.lowestPeripheral.percentage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +67,6 @@ Item {
|
|||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
animate: true
|
animate: true
|
||||||
fill: 1
|
fill: 1
|
||||||
font.pointSize: Tokens.font.size.larger
|
|
||||||
text: {
|
text: {
|
||||||
if (PowerProfiles.profile === PowerProfile.PowerSaver)
|
if (PowerProfiles.profile === PowerProfile.PowerSaver)
|
||||||
return "energy_savings_leaf";
|
return "energy_savings_leaf";
|
||||||
@@ -78,6 +78,8 @@ CustomClippingRect {
|
|||||||
required property var modelData
|
required property var modelData
|
||||||
readonly property list<string> sections: modelData.update.split(" ")
|
readonly property list<string> sections: modelData.update.split(" ")
|
||||||
|
|
||||||
|
// anchors.left: parent.left
|
||||||
|
// anchors.right: parent.right
|
||||||
color: Colors.tPalette.m3surfaceContainer
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
implicitHeight: root.itemHeight
|
implicitHeight: root.itemHeight
|
||||||
implicitWidth: 600
|
implicitWidth: 600
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Components
|
||||||
|
import qs.Modules
|
||||||
|
import qs.Helpers
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property int countUpdates: Updates.availableUpdates
|
||||||
|
property color textColor: Colors.palette.m3onSurface
|
||||||
|
|
||||||
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
|
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
|
||||||
|
implicitWidth: contentRow.implicitWidth + Tokens.spacing.small * 2
|
||||||
|
radius: Tokens.rounding.full
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: contentRow
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
spacing: Tokens.spacing.small
|
||||||
|
|
||||||
|
MaterialIcon {
|
||||||
|
font.pointSize: Tokens.font.size.larger
|
||||||
|
text: "package_2"
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
color: root.textColor
|
||||||
|
font.pointSize: Tokens.font.size.normal
|
||||||
|
text: root.countUpdates
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import Quickshell
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Components
|
||||||
|
import qs.Modules
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property ShellScreen screen
|
||||||
|
required property Item wrapper
|
||||||
|
|
||||||
|
implicitHeight: layout.implicitHeight + 16
|
||||||
|
implicitWidth: layout.implicitWidth + 16
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
columnSpacing: 8
|
||||||
|
rowSpacing: 8
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: Hypr.workspaces
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
id: workspacePreview
|
||||||
|
|
||||||
|
required property HyprlandWorkspace modelData
|
||||||
|
|
||||||
|
Layout.preferredHeight: 180 + 10
|
||||||
|
Layout.preferredWidth: 320 + 10
|
||||||
|
border.color: "white"
|
||||||
|
border.width: 1
|
||||||
|
radius: Tokens.rounding.smallest
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: workspacePreview.modelData.toplevels
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: preview
|
||||||
|
|
||||||
|
property rect appPosition: {
|
||||||
|
let {
|
||||||
|
at: [cx, cy],
|
||||||
|
size: [cw, ch]
|
||||||
|
} = modelData.lastIpcObject;
|
||||||
|
|
||||||
|
cx -= modelData.monitor.x;
|
||||||
|
cy -= modelData.monitor.y;
|
||||||
|
|
||||||
|
return Qt.rect((cx / 8), (cy / 8), (cw / 8), (ch / 8));
|
||||||
|
}
|
||||||
|
required property HyprlandToplevel modelData
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 5
|
||||||
|
|
||||||
|
CustomRect {
|
||||||
|
border.color: Colors.tPalette.m3outline
|
||||||
|
border.width: 1
|
||||||
|
implicitHeight: preview.appPosition.height
|
||||||
|
implicitWidth: preview.appPosition.width
|
||||||
|
radius: Tokens.rounding.smallest / 2
|
||||||
|
x: preview.appPosition.x
|
||||||
|
y: preview.appPosition.y - 3.4
|
||||||
|
|
||||||
|
ScreencopyView {
|
||||||
|
id: previewCopy
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
captureSource: preview.modelData.wayland
|
||||||
|
live: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,46 +5,103 @@ import Quickshell.Hyprland
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Helpers
|
import qs.Helpers
|
||||||
|
import ZShell.Config
|
||||||
import ZShell.Internal
|
import ZShell.Internal
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property bool completed
|
||||||
|
property real cropHeight: displayData?.height ?? 1.0
|
||||||
|
property real cropWidth: displayData?.width ?? 1.0
|
||||||
|
property real cropX: displayData?.x ?? 0.0
|
||||||
|
property real cropY: displayData?.y ?? 0.0
|
||||||
|
property WallpaperImage current
|
||||||
readonly property var displayData: Wallpapers.getCrop(screen.name)
|
readonly property var displayData: Wallpapers.getCrop(screen.name)
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
property size screenResolution: Qt.size(screen.width * screenScale, screen.height * screenScale)
|
property size screenResolution: Qt.size(screen.width * screenScale, screen.height * screenScale)
|
||||||
property real screenScale: Hyprland.monitorFor(screen).scale
|
property real screenScale: Hyprland.monitorFor(screen).scale
|
||||||
|
property string source: Wallpapers.current
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
Component.onCompleted: Hyprland.refreshMonitors()
|
Component.onCompleted: {
|
||||||
|
Hyprland.refreshMonitors();
|
||||||
|
|
||||||
WallpaperImage {
|
if (source)
|
||||||
id: img
|
Qt.callLater(() => {
|
||||||
|
current = imgComp.createObject(this, {
|
||||||
|
source
|
||||||
|
});
|
||||||
|
completed = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onSourceChanged: {
|
||||||
|
if (!source)
|
||||||
|
current = null;
|
||||||
|
else
|
||||||
|
current = imgComp.createObject(this, {
|
||||||
|
source: source
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
anchors.fill: parent
|
Component {
|
||||||
cropHeight: root.displayData?.height ?? 1.0
|
id: imgComp
|
||||||
cropWidth: root.displayData?.width ?? 1.0
|
|
||||||
cropX: root.displayData?.x ?? 0.0
|
|
||||||
cropY: root.displayData?.y ?? 0.0
|
|
||||||
fadeDuration: 150
|
|
||||||
screenResolution: root.screenResolution
|
|
||||||
source: Wallpapers.current
|
|
||||||
|
|
||||||
Behavior on cropHeight {
|
WallpaperImage {
|
||||||
Anim {
|
id: img
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
cropHeight: root.cropHeight
|
||||||
|
cropWidth: root.cropWidth
|
||||||
|
cropX: root.cropX
|
||||||
|
cropY: root.cropY
|
||||||
|
opacity: 0
|
||||||
|
screenResolution: root.screenResolution
|
||||||
|
source: root.source
|
||||||
|
|
||||||
|
Behavior on cropHeight {
|
||||||
|
Anim {
|
||||||
|
id: heightAnim
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Behavior on cropWidth {
|
||||||
Behavior on cropWidth {
|
Anim {
|
||||||
Anim {
|
id: widthAnim
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Behavior on cropX {
|
||||||
Behavior on cropX {
|
Anim {
|
||||||
Anim {
|
id: xAnim
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Behavior on cropY {
|
||||||
Behavior on cropY {
|
Anim {
|
||||||
Anim {
|
id: yAnim
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Anim on opacity {
|
||||||
|
id: anim
|
||||||
|
|
||||||
|
from: 0
|
||||||
|
running: false
|
||||||
|
to: 1
|
||||||
|
type: Anim.SlowEffects
|
||||||
|
}
|
||||||
|
|
||||||
|
onStatusChanged: {
|
||||||
|
if (status === Image.Ready) {
|
||||||
|
anim.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: destroyTimer
|
||||||
|
|
||||||
|
interval: anim.duration * 2
|
||||||
|
running: root.current !== img && root.current?.status === Image.Ready
|
||||||
|
|
||||||
|
onTriggered: Qt.callLater(() => img.destroy())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import qs.Components
|
||||||
|
import ZShell.Config
|
||||||
|
import qs.Helpers
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var bar
|
||||||
|
property color colour: Colors.palette.m3primary
|
||||||
|
property Title current: text1
|
||||||
|
// readonly property int maxWidth: 300
|
||||||
|
readonly property int maxWidth: {
|
||||||
|
const otherModules = bar.children.filter(c => c.enabled && c.id && c.item !== this && c.id !== "spacer");
|
||||||
|
const otherWidth = otherModules.reduce((acc, curr) => {
|
||||||
|
return acc + (curr.item?.nonAnimWidth ?? curr.width ?? 0);
|
||||||
|
}, 0);
|
||||||
|
return bar.width - otherWidth - bar.spacing * (bar.children.length - 1) - bar.vPadding * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
clip: true
|
||||||
|
implicitHeight: current.implicitHeight
|
||||||
|
implicitWidth: Math.min(current.implicitWidth, root.maxWidth)
|
||||||
|
|
||||||
|
Behavior on implicitWidth {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Title {
|
||||||
|
id: text1
|
||||||
|
}
|
||||||
|
|
||||||
|
Title {
|
||||||
|
id: text2
|
||||||
|
}
|
||||||
|
|
||||||
|
TextMetrics {
|
||||||
|
id: metrics
|
||||||
|
|
||||||
|
elide: Qt.ElideRight
|
||||||
|
elideWidth: root.maxWidth
|
||||||
|
font.family: "Rubik"
|
||||||
|
font.pointSize: Tokens.font.size.normal
|
||||||
|
text: Hypr.activeToplevel?.title ?? qsTr("Desktop")
|
||||||
|
|
||||||
|
onElideWidthChanged: root.current.text = elidedText
|
||||||
|
onTextChanged: {
|
||||||
|
const next = root.current === text1 ? text2 : text1;
|
||||||
|
next.text = elidedText;
|
||||||
|
root.current = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component Title: CustomText {
|
||||||
|
id: text
|
||||||
|
|
||||||
|
anchors.leftMargin: 7
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
color: root.colour
|
||||||
|
font.family: metrics.font.family
|
||||||
|
font.pointSize: metrics.font.pointSize
|
||||||
|
height: implicitHeight
|
||||||
|
opacity: root.current === this ? 1 : 0
|
||||||
|
width: implicitWidth
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
Anim {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,10 +2,10 @@ pragma ComponentBehavior: Bound
|
|||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Effects
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
import ZShell.Config
|
import ZShell.Config
|
||||||
import qs.Modules.Bar.Components.Workspaces
|
|
||||||
import qs.Components
|
import qs.Components
|
||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
@@ -14,57 +14,41 @@ Item {
|
|||||||
|
|
||||||
property real activeWorkspaceMargin: Math.ceil(Tokens.padding.small / 2)
|
property real activeWorkspaceMargin: Math.ceil(Tokens.padding.small / 2)
|
||||||
readonly property int effectiveActiveWorkspaceId: monitor?.activeWorkspace?.id ?? 1
|
readonly property int effectiveActiveWorkspaceId: monitor?.activeWorkspace?.id ?? 1
|
||||||
required property bool horizontal
|
|
||||||
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen)
|
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen)
|
||||||
required property ShellScreen screen
|
required property ShellScreen screen
|
||||||
readonly property real shortSize: Math.max(Config.bar.height, Tokens.bar.innerSize)
|
property int workspaceButtonWidth: bgRect.implicitHeight - root.activeWorkspaceMargin * 2
|
||||||
readonly property real size: (workspaceButtonWidth * workspacesShown) + activeWorkspaceMargin * 2
|
|
||||||
property int workspaceButtonWidth: (horizontal ? bgRect.implicitHeight : bgRect.implicitWidth) - root.activeWorkspaceMargin * 2
|
|
||||||
property int workspaceIndexInGroup: (effectiveActiveWorkspaceId - 1) % root.workspacesShown
|
property int workspaceIndexInGroup: (effectiveActiveWorkspaceId - 1) % root.workspacesShown
|
||||||
readonly property list<var> workspaces: Hyprland.workspaces.values.filter(w => w.monitor === root.monitor)
|
readonly property list<var> workspaces: Hyprland.workspaces.values.filter(w => w.monitor === root.monitor)
|
||||||
readonly property int workspacesShown: workspaces.length
|
readonly property int workspacesShown: workspaces.length
|
||||||
|
|
||||||
implicitHeight: horizontal ? shortSize : size
|
height: implicitHeight
|
||||||
implicitWidth: horizontal ? size : shortSize
|
implicitHeight: Config.bar.height + Tokens.padding.smaller * 2
|
||||||
|
implicitWidth: (root.workspaceButtonWidth * root.workspacesShown) + root.activeWorkspaceMargin * 2
|
||||||
|
|
||||||
Behavior on implicitHeight {
|
|
||||||
enabled: !root.horizontal
|
|
||||||
|
|
||||||
Anim {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Behavior on implicitWidth {
|
Behavior on implicitWidth {
|
||||||
enabled: root.horizontal
|
|
||||||
|
|
||||||
Anim {
|
Anim {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomRect {
|
CustomRect {
|
||||||
// qmllint disable Quick.anchor-combinations
|
|
||||||
id: bgRect
|
id: bgRect
|
||||||
|
|
||||||
anchors.bottom: root.horizontal ? undefined : parent.bottom
|
anchors.left: parent.left
|
||||||
anchors.horizontalCenter: root.horizontal ? undefined : parent.horizontalCenter
|
anchors.right: parent.right
|
||||||
anchors.left: root.horizontal ? parent.left : undefined
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: root.horizontal ? parent.right : undefined
|
|
||||||
anchors.top: root.horizontal ? undefined : parent.top
|
|
||||||
anchors.verticalCenter: root.horizontal ? parent.verticalCenter : undefined
|
|
||||||
color: Colors.tPalette.m3surfaceContainer
|
color: Colors.tPalette.m3surfaceContainer
|
||||||
implicitHeight: root.horizontal ? root.implicitHeight : 0
|
implicitHeight: root.implicitHeight - ((Tokens.padding.small - 1) * 2)
|
||||||
implicitWidth: root.horizontal ? 0 : root.implicitWidth
|
|
||||||
radius: height / 2
|
radius: height / 2
|
||||||
|
|
||||||
// qmllint enable Quick.anchor-combinations
|
|
||||||
Grid {
|
Grid {
|
||||||
id: grid
|
id: grid
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: root.activeWorkspaceMargin
|
anchors.margins: root.activeWorkspaceMargin
|
||||||
columnSpacing: 0
|
columnSpacing: 0
|
||||||
columns: root.horizontal ? root.workspacesShown : 1
|
columns: root.workspacesShown
|
||||||
rowSpacing: 0
|
rowSpacing: 0
|
||||||
rows: root.horizontal ? 1 : root.workspacesShown
|
rows: 1
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root.workspaces
|
model: root.workspaces
|
||||||
@@ -90,7 +74,7 @@ Item {
|
|||||||
color: Colors.palette.m3onSecondaryContainer
|
color: Colors.palette.m3onSecondaryContainer
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
text: button.modelData?.name ?? ""
|
text: button.modelData.name
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,15 +94,13 @@ Item {
|
|||||||
property real indicatorPosition: Math.min(idxPair.idx1, idxPair.idx2) * root.workspaceButtonWidth + root.activeWorkspaceMargin
|
property real indicatorPosition: Math.min(idxPair.idx1, idxPair.idx2) * root.workspaceButtonWidth + root.activeWorkspaceMargin
|
||||||
property real indicatorThickness: root.workspaceButtonWidth
|
property real indicatorThickness: root.workspaceButtonWidth
|
||||||
|
|
||||||
anchors.horizontalCenter: root.horizontal ? undefined : parent.horizontalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.verticalCenter: root.horizontal ? parent.verticalCenter : undefined
|
|
||||||
clip: true
|
clip: true
|
||||||
color: Colors.palette.m3primary
|
color: Colors.palette.m3primary
|
||||||
implicitHeight: root.horizontal ? indicatorThickness : indicatorLength
|
implicitHeight: indicatorThickness
|
||||||
implicitWidth: root.horizontal ? indicatorLength : indicatorThickness
|
implicitWidth: indicatorLength
|
||||||
radius: Tokens.rounding.full
|
radius: Tokens.rounding.full
|
||||||
x: root.horizontal ? indicatorPosition : 0
|
x: indicatorPosition
|
||||||
y: root.horizontal ? 0 : indicatorPosition
|
|
||||||
|
|
||||||
AnimatedTabIndexPair {
|
AnimatedTabIndexPair {
|
||||||
id: idxPair
|
id: idxPair
|
||||||
@@ -132,8 +114,7 @@ Item {
|
|||||||
implicitWidth: grid.width
|
implicitWidth: grid.width
|
||||||
source: grid
|
source: grid
|
||||||
sourceColor: Colors.palette.m3onSurface
|
sourceColor: Colors.palette.m3onSurface
|
||||||
x: root.horizontal ? -indicator.x + 3 : 0
|
x: -indicator.x + 3
|
||||||
y: root.horizontal ? 0 : -indicator.y + 3
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ Item {
|
|||||||
Comp {
|
Comp {
|
||||||
id: content
|
id: content
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.centerIn: parent
|
||||||
shouldBeActive: root.hasCurrent
|
shouldBeActive: root.hasCurrent
|
||||||
|
|
||||||
sourceComponent: Content {
|
sourceComponent: Content {
|
||||||
@@ -4,7 +4,6 @@ qml_module(ZShell-components
|
|||||||
lazylistview.hpp lazylistview.cpp
|
lazylistview.hpp lazylistview.cpp
|
||||||
wavyline.hpp wavyline.cpp
|
wavyline.hpp wavyline.cpp
|
||||||
buttonrow.hpp buttonrow.cpp
|
buttonrow.hpp buttonrow.cpp
|
||||||
carouselview.hpp carouselview.cpp
|
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
Qt::Quick
|
Qt::Quick
|
||||||
)
|
)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,255 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QQmlParserStatus>
|
|
||||||
#include <QElapsedTimer>
|
|
||||||
#include <QEasingCurve>
|
|
||||||
#include <QList>
|
|
||||||
#include <QPointF>
|
|
||||||
#include <QQuickItem>
|
|
||||||
#include <QQmlComponent>
|
|
||||||
#include <QQmlEngine>
|
|
||||||
#include <QVariantAnimation>
|
|
||||||
#include <QVariantList>
|
|
||||||
#include <QVector>
|
|
||||||
#include <qtypes.h>
|
|
||||||
#include <qvectornd.h>
|
|
||||||
|
|
||||||
namespace ZShell::components {
|
|
||||||
|
|
||||||
class CarouselView : public QQuickItem {
|
|
||||||
Q_OBJECT
|
|
||||||
QML_ELEMENT
|
|
||||||
|
|
||||||
Q_PROPERTY(
|
|
||||||
QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY
|
|
||||||
delegateChanged)
|
|
||||||
Q_PROPERTY(QVariantList model READ model WRITE setModel NOTIFY modelChanged)
|
|
||||||
|
|
||||||
Q_PROPERTY(
|
|
||||||
qreal focalWidth READ focalWidth WRITE setFocalWidth NOTIFY
|
|
||||||
focalWidthChanged)
|
|
||||||
Q_PROPERTY(
|
|
||||||
qreal minEdgeWidth READ minEdgeWidth WRITE setMinEdgeWidth NOTIFY
|
|
||||||
minEdgeWidthChanged)
|
|
||||||
Q_PROPERTY(
|
|
||||||
qreal itemSpacing READ itemSpacing WRITE setItemSpacing NOTIFY
|
|
||||||
itemSpacingChanged)
|
|
||||||
Q_PROPERTY(
|
|
||||||
qreal tileHeight READ tileHeight WRITE setTileHeight NOTIFY
|
|
||||||
tileHeightChanged)
|
|
||||||
Q_PROPERTY(
|
|
||||||
qreal maxWidth READ maxWidth WRITE setMaxWidth NOTIFY maxWidthChanged)
|
|
||||||
|
|
||||||
Q_PROPERTY(
|
|
||||||
int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY
|
|
||||||
currentIndexChanged)
|
|
||||||
|
|
||||||
Q_PROPERTY(
|
|
||||||
QQuickItem* currentItem READ currentItem NOTIFY currentItemChanged)
|
|
||||||
|
|
||||||
Q_PROPERTY(
|
|
||||||
int glideDuration READ glideDuration WRITE setGlideDuration NOTIFY
|
|
||||||
glideDurationChanged)
|
|
||||||
Q_PROPERTY(
|
|
||||||
QEasingCurve::Type glideEasingType READ glideEasingType WRITE
|
|
||||||
setGlideEasingType NOTIFY glideEasingTypeChanged)
|
|
||||||
|
|
||||||
Q_PROPERTY(
|
|
||||||
QVariantMap delegateProperties READ delegateProperties WRITE
|
|
||||||
setDelegateProperties NOTIFY delegatePropertiesChanged)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit CarouselView(QQuickItem* parent = nullptr);
|
|
||||||
~CarouselView() override;
|
|
||||||
|
|
||||||
QQmlComponent* delegate() const { return m_delegate; }
|
|
||||||
void setDelegate(QQmlComponent* c);
|
|
||||||
|
|
||||||
QVariantList model() const { return m_model; }
|
|
||||||
void setModel(const QVariantList& m);
|
|
||||||
|
|
||||||
qreal focalWidth() const { return m_focalWidth; }
|
|
||||||
void setFocalWidth(qreal v);
|
|
||||||
|
|
||||||
qreal minEdgeWidth() const { return m_minEdgeWidth; }
|
|
||||||
void setMinEdgeWidth(qreal v);
|
|
||||||
|
|
||||||
qreal itemSpacing() const { return m_itemSpacing; }
|
|
||||||
void setItemSpacing(qreal v);
|
|
||||||
|
|
||||||
qreal tileHeight() const { return m_tileHeight; }
|
|
||||||
void setTileHeight(qreal v);
|
|
||||||
|
|
||||||
qreal maxWidth() const { return m_maxWidth; }
|
|
||||||
void setMaxWidth(qreal v);
|
|
||||||
|
|
||||||
int currentIndex() const { return m_currentRealIndex; }
|
|
||||||
void setCurrentIndex(int idx);
|
|
||||||
|
|
||||||
QQuickItem* currentItem() const { return m_currentItem; }
|
|
||||||
|
|
||||||
int glideDuration() const { return m_glideDuration; }
|
|
||||||
void setGlideDuration(int v);
|
|
||||||
|
|
||||||
QEasingCurve::Type glideEasingType() const { return m_glideEasingType; }
|
|
||||||
void setGlideEasingType(QEasingCurve::Type t);
|
|
||||||
|
|
||||||
QVariantMap delegateProperties() const { return m_delegateProperties; }
|
|
||||||
void setDelegateProperties(const QVariantMap& v);
|
|
||||||
|
|
||||||
Q_INVOKABLE void goToIndex(int realIndex);
|
|
||||||
Q_INVOKABLE void incrementCurrentIndex();
|
|
||||||
Q_INVOKABLE void decrementCurrentIndex();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void delegateChanged();
|
|
||||||
void modelChanged();
|
|
||||||
void focalWidthChanged();
|
|
||||||
void minEdgeWidthChanged();
|
|
||||||
void itemSpacingChanged();
|
|
||||||
void tileHeightChanged();
|
|
||||||
void maxWidthChanged();
|
|
||||||
void currentIndexChanged();
|
|
||||||
void currentItemChanged();
|
|
||||||
void glideDurationChanged();
|
|
||||||
void glideEasingTypeChanged();
|
|
||||||
void delegatePropertiesChanged();
|
|
||||||
|
|
||||||
void activated(int realIndex, QVariant modelData);
|
|
||||||
void previewIndexChanged(int realIndex, QVariant modelData);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void classBegin() override;
|
|
||||||
void componentComplete() override;
|
|
||||||
bool childMouseEventFilter(QQuickItem* item, QEvent* event) override;
|
|
||||||
void geometryChange(const QRectF& newGeo, const QRectF& oldGeo) override;
|
|
||||||
void mousePressEvent(QMouseEvent* event) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent* event) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
|
||||||
void mouseUngrabEvent() override;
|
|
||||||
void wheelEvent(QWheelEvent* event) override;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void handleDelegateActivate();
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Arrangement {
|
|
||||||
int n = 0;
|
|
||||||
qreal width = 0;
|
|
||||||
qreal outerSpacing = 0;
|
|
||||||
|
|
||||||
QVector<qreal> sizes;
|
|
||||||
QVector<qreal> centers;
|
|
||||||
|
|
||||||
qreal effectiveExtraWidth = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Slot {
|
|
||||||
QQuickItem* item = nullptr;
|
|
||||||
int virtualIndex = 0;
|
|
||||||
int realIndex = -1;
|
|
||||||
bool active = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct VelocitySample {
|
|
||||||
qint64 t;
|
|
||||||
qreal x;
|
|
||||||
};
|
|
||||||
|
|
||||||
void rebuildArrangement();
|
|
||||||
void relayout();
|
|
||||||
|
|
||||||
Arrangement arrangementForCount(int n) const;
|
|
||||||
|
|
||||||
int layoutCapacityForWidth(qreal width) const;
|
|
||||||
qreal targetWidthForMaxWidth(qreal maxWidth) const;
|
|
||||||
|
|
||||||
void updateSlotContent(Slot& slot, int virtualIndex);
|
|
||||||
|
|
||||||
void positionSlot(const Slot& slot) const;
|
|
||||||
|
|
||||||
void applyPropertiesToItem(QQuickItem* item, int realIndex) const;
|
|
||||||
|
|
||||||
qreal pitch() const { return m_focalWidth + m_itemSpacing; }
|
|
||||||
|
|
||||||
qreal contentXForIndex(qreal index) const;
|
|
||||||
int indexForContentX(qreal x) const;
|
|
||||||
qreal snapTargetX(qreal x) const;
|
|
||||||
|
|
||||||
void snapToNearest();
|
|
||||||
void glideTo(qreal dest);
|
|
||||||
void cancelAnimations();
|
|
||||||
|
|
||||||
qreal keylineSize(int io) const;
|
|
||||||
qreal sampleSize(qreal childLoc) const;
|
|
||||||
qreal continuousIndex() const;
|
|
||||||
|
|
||||||
int realIndexOf(int virtualIndex) const;
|
|
||||||
|
|
||||||
void updateCurrentIndexFromContentX(bool emitPreview);
|
|
||||||
|
|
||||||
void updateCurrentItem();
|
|
||||||
|
|
||||||
void wrapContentIfNeeded();
|
|
||||||
void centerInstantlyOnReal(int realIndex);
|
|
||||||
|
|
||||||
QQuickItem* acquireItem();
|
|
||||||
void releaseAllItems();
|
|
||||||
|
|
||||||
void addVelocitySample(qint64 t, qreal x);
|
|
||||||
qreal sampledVelocity() const;
|
|
||||||
|
|
||||||
void notifyCurrentIndexChanged();
|
|
||||||
void notifyCurrentItemChanged();
|
|
||||||
void notifyPreviewIndexChanged(int realIndex);
|
|
||||||
|
|
||||||
QQmlComponent* m_delegate = nullptr;
|
|
||||||
QVariantList m_model;
|
|
||||||
QVariantMap m_delegateProperties;
|
|
||||||
|
|
||||||
qreal m_focalWidth = 0;
|
|
||||||
qreal m_minEdgeWidth = 56;
|
|
||||||
qreal m_itemSpacing = 8;
|
|
||||||
qreal m_tileHeight = 0;
|
|
||||||
qreal m_maxWidth = 0;
|
|
||||||
|
|
||||||
Arrangement m_arrangement;
|
|
||||||
|
|
||||||
int m_layoutCapacity = 0;
|
|
||||||
|
|
||||||
qreal m_contentX = 0;
|
|
||||||
int m_currentVirtualIndex = 0;
|
|
||||||
int m_currentRealIndex = -1;
|
|
||||||
int m_previewRealIndex = -1;
|
|
||||||
|
|
||||||
QQuickItem* m_currentItem = nullptr;
|
|
||||||
|
|
||||||
int m_centerBlockStart = 0;
|
|
||||||
|
|
||||||
QList<Slot> m_slots;
|
|
||||||
|
|
||||||
int m_glideDuration = 250;
|
|
||||||
QEasingCurve::Type m_glideEasingType = QEasingCurve::OutCubic;
|
|
||||||
QVariantAnimation* m_glideAnim = nullptr;
|
|
||||||
|
|
||||||
bool m_dragging = false;
|
|
||||||
bool m_dragActive = false;
|
|
||||||
|
|
||||||
QPointF m_pressPos;
|
|
||||||
qreal m_pressContentX = 0;
|
|
||||||
|
|
||||||
QElapsedTimer m_dragTimer;
|
|
||||||
|
|
||||||
QVector<VelocitySample> m_velocitySamples;
|
|
||||||
static constexpr qint64 kVelocitySampleWindowMs = 80;
|
|
||||||
|
|
||||||
QVariantAnimation* m_flickAnim = nullptr;
|
|
||||||
|
|
||||||
bool m_completed = false;
|
|
||||||
int m_pendingCurrentIndex = -1;
|
|
||||||
|
|
||||||
bool m_initializedLayout = false;
|
|
||||||
bool m_relayoutQueued = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ZShell::components
|
|
||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include "configlist.hpp"
|
#include "configlist.hpp"
|
||||||
#include "configobject.hpp"
|
#include "configobject.hpp"
|
||||||
#include <qcontainerfwd.h>
|
|
||||||
#include <qhashfunctions.h>
|
|
||||||
#include <qqmlregistration.h>
|
#include <qqmlregistration.h>
|
||||||
|
|
||||||
namespace ZShell::config {
|
namespace ZShell::config {
|
||||||
@@ -63,7 +61,6 @@ class Bar : public ConfigObject {
|
|||||||
CFG_PROPERTY(int, revealDelay, 100)
|
CFG_PROPERTY(int, revealDelay, 100)
|
||||||
CFG_PROPERTY(int, rounding, 14)
|
CFG_PROPERTY(int, rounding, 14)
|
||||||
CFG_PROPERTY(int, smoothing, 32)
|
CFG_PROPERTY(int, smoothing, 32)
|
||||||
CFG_PROPERTY(QString, position, QStringLiteral("top"))
|
|
||||||
CONFIG_SUBOBJECT(Tray, tray)
|
CONFIG_SUBOBJECT(Tray, tray)
|
||||||
CONFIG_LIST(
|
CONFIG_LIST(
|
||||||
EntryList,
|
EntryList,
|
||||||
|
|||||||
@@ -61,8 +61,6 @@ Config::Config(QObject* parent)
|
|||||||
m_reloadTimer.setInterval(50);
|
m_reloadTimer.setInterval(50);
|
||||||
connect(&m_reloadTimer, &QTimer::timeout, this, &Config::reloadAsync);
|
connect(&m_reloadTimer, &QTimer::timeout, this, &Config::reloadAsync);
|
||||||
|
|
||||||
connectAutoSave(this);
|
|
||||||
|
|
||||||
connect(
|
connect(
|
||||||
&m_watcher,
|
&m_watcher,
|
||||||
&QFileSystemWatcher::directoryChanged,
|
&QFileSystemWatcher::directoryChanged,
|
||||||
@@ -95,31 +93,15 @@ QString Config::filePath() const {
|
|||||||
|
|
||||||
void Config::loadSync() {
|
void Config::loadSync() {
|
||||||
m_loading = true;
|
m_loading = true;
|
||||||
|
|
||||||
QFile f(filePath());
|
QFile f(filePath());
|
||||||
QJsonObject before;
|
|
||||||
|
|
||||||
bool existed = false;
|
|
||||||
|
|
||||||
if (f.open(QIODevice::ReadOnly)) {
|
if (f.open(QIODevice::ReadOnly)) {
|
||||||
const auto doc = QJsonDocument::fromJson(f.readAll());
|
const auto doc = QJsonDocument::fromJson(f.readAll());
|
||||||
if (doc.isObject()) {
|
if (doc.isObject()) loadFromJson(QJsonValue(doc.object()));
|
||||||
before = doc.object();
|
|
||||||
existed = true;
|
|
||||||
} else {
|
|
||||||
qInfo() << "Config: existing config at" << filePath()
|
|
||||||
<< "is empty or not a valid JSON object - using defaults";
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
qInfo() << "Config: no existing config at" << filePath()
|
qInfo() << "Config: no existing config at" << filePath()
|
||||||
<< "- using defaults";
|
<< "- using defaults";
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFromJson(QJsonValue(before));
|
|
||||||
m_loading = false;
|
m_loading = false;
|
||||||
|
|
||||||
const auto after = toJson().toObject();
|
|
||||||
if (!existed || after != before) saveNow();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::updateWatch() {
|
void Config::updateWatch() {
|
||||||
@@ -164,21 +146,27 @@ void Config::loadAsync() {
|
|||||||
|
|
||||||
if (f.open(QIODevice::ReadOnly)) {
|
if (f.open(QIODevice::ReadOnly)) {
|
||||||
const auto doc = QJsonDocument::fromJson(f.readAll());
|
const auto doc = QJsonDocument::fromJson(f.readAll());
|
||||||
const bool valid = doc.isObject();
|
|
||||||
const QJsonObject before = valid ? doc.object() : QJsonObject();
|
|
||||||
|
|
||||||
QMetaObject::invokeMethod(
|
if (doc.isObject()) {
|
||||||
this,
|
QMetaObject::invokeMethod(
|
||||||
[this, valid, before]() {
|
this,
|
||||||
loadFromJson(QJsonValue(before));
|
[this, doc]() {
|
||||||
m_loading = false;
|
loadFromJson(QJsonValue(doc.object()));
|
||||||
|
m_loading = false;
|
||||||
|
|
||||||
const auto after = toJson().toObject();
|
if (m_reloadPending) m_reloadTimer.start();
|
||||||
if (!valid || after != before) saveNow();
|
},
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
} else {
|
||||||
|
QMetaObject::invokeMethod(
|
||||||
|
this,
|
||||||
|
[this]() {
|
||||||
|
m_loading = false;
|
||||||
|
|
||||||
if (m_reloadPending) m_reloadTimer.start();
|
if (m_reloadPending) m_reloadTimer.start();
|
||||||
},
|
},
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qInfo() << "Config: failed to reload from" << filePath()
|
qInfo() << "Config: failed to reload from" << filePath()
|
||||||
<< "- using in-memory values";
|
<< "- using in-memory values";
|
||||||
@@ -244,15 +232,6 @@ void Config::saveNow() {
|
|||||||
flushAsync();
|
flushAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::connectAutoSave(ConfigNode* node) {
|
|
||||||
connect(node, &ConfigNode::propertiesChanged, this, [this] {
|
|
||||||
scheduleSave();
|
|
||||||
});
|
|
||||||
|
|
||||||
for (auto* child : node->childNodes())
|
|
||||||
connectAutoSave(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Config::writeAtomically(const QByteArray& data) {
|
bool Config::writeAtomically(const QByteArray& data) {
|
||||||
QSaveFile f(filePath());
|
QSaveFile f(filePath());
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ class Config : public ConfigObject {
|
|||||||
void updateWatch();
|
void updateWatch();
|
||||||
void loadSync();
|
void loadSync();
|
||||||
void loadAsync();
|
void loadAsync();
|
||||||
void connectAutoSave(ConfigNode* node);
|
|
||||||
|
|
||||||
QTimer m_saveTimer;
|
QTimer m_saveTimer;
|
||||||
QTimer m_reloadTimer;
|
QTimer m_reloadTimer;
|
||||||
|
|||||||
@@ -79,14 +79,13 @@ void ConfigList::loadFromJson(const QJsonValue& json) {
|
|||||||
if (!json.isArray()) {
|
if (!json.isArray()) {
|
||||||
qCWarning(
|
qCWarning(
|
||||||
lcConfig,
|
lcConfig,
|
||||||
"Option '%s' must be a list, resetting to default",
|
"Option '%s' must be a list, ignoring",
|
||||||
qUtf8Printable(propertyPath()));
|
qUtf8Printable(propertyPath()));
|
||||||
|
m_rejectedJson = json;
|
||||||
resetToDefaults();
|
|
||||||
materializeDefaults();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_rejectedJson = QJsonValue::Undefined;
|
||||||
populate(json.toArray());
|
populate(json.toArray());
|
||||||
m_loaded = true;
|
m_loaded = true;
|
||||||
}
|
}
|
||||||
@@ -94,11 +93,12 @@ void ConfigList::loadFromJson(const QJsonValue& json) {
|
|||||||
QJsonValue ConfigList::toJson() const {
|
QJsonValue ConfigList::toJson() const {
|
||||||
if (m_loaded) return elementsToJson();
|
if (m_loaded) return elementsToJson();
|
||||||
|
|
||||||
return QJsonValue::Undefined;
|
return m_rejectedJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigList::clearLoadedKeys() {
|
void ConfigList::clearLoadedKeys() {
|
||||||
m_loaded = false;
|
m_loaded = false;
|
||||||
|
m_rejectedJson = QJsonValue::Undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList ConfigList::unknownKeys() const {
|
QStringList ConfigList::unknownKeys() const {
|
||||||
@@ -113,15 +113,6 @@ QStringList ConfigList::unknownKeys() const {
|
|||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigList::materializeDefaults() {
|
|
||||||
for (auto* const item : m_items)
|
|
||||||
item->materializeDefaults();
|
|
||||||
|
|
||||||
if (m_global) return;
|
|
||||||
|
|
||||||
m_loaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigList::resyncFromGlobal() {
|
void ConfigList::resyncFromGlobal() {
|
||||||
syncValuesFromGlobal();
|
syncValuesFromGlobal();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class ConfigList : public ConfigNode {
|
|||||||
[[nodiscard]] QJsonValue toJson() const override;
|
[[nodiscard]] QJsonValue toJson() const override;
|
||||||
void clearLoadedKeys() override;
|
void clearLoadedKeys() override;
|
||||||
[[nodiscard]] QStringList unknownKeys() const override;
|
[[nodiscard]] QStringList unknownKeys() const override;
|
||||||
void materializeDefaults() override;
|
|
||||||
void resyncFromGlobal() override;
|
void resyncFromGlobal() override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@@ -72,6 +71,7 @@ class ConfigList : public ConfigNode {
|
|||||||
QJsonArray m_defaults;
|
QJsonArray m_defaults;
|
||||||
QList<ConfigObject*> m_items;
|
QList<ConfigObject*> m_items;
|
||||||
bool m_loaded = false;
|
bool m_loaded = false;
|
||||||
|
QJsonValue m_rejectedJson = QJsonValue::Undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ZShell::config
|
} // namespace ZShell::config
|
||||||
@@ -103,6 +103,7 @@ class ConfigList : public ConfigNode {
|
|||||||
} \
|
} \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define CONFIG_LIST(Type, name, ...) \
|
#define CONFIG_LIST(Type, name, ...) \
|
||||||
Q_PROPERTY(ZShell::config::Type* name READ name CONSTANT) \
|
Q_PROPERTY(ZShell::config::Type* name READ name CONSTANT) \
|
||||||
\
|
\
|
||||||
@@ -114,8 +115,6 @@ class ConfigList : public ConfigNode {
|
|||||||
private: \
|
private: \
|
||||||
Type* m_##name = new Type(this __VA_OPT__(, __VA_ARGS__));
|
Type* m_##name = new Type(this __VA_OPT__(, __VA_ARGS__));
|
||||||
|
|
||||||
#define LIST_ENTRY(id, enabled) \
|
|
||||||
vmap({{"id", QString::fromUtf8(#id)}, {"enabled", enabled}})
|
|
||||||
|
|
||||||
namespace ZShell::config {
|
namespace ZShell::config {
|
||||||
|
|
||||||
@@ -137,3 +136,6 @@ class ListEntry : public ConfigObject {
|
|||||||
CONFIG_LIST_TYPE(ListEntry, EntryList)
|
CONFIG_LIST_TYPE(ListEntry, EntryList)
|
||||||
|
|
||||||
} // namespace ZShell::config
|
} // namespace ZShell::config
|
||||||
|
|
||||||
|
#define LIST_ENTRY(id, enabled) \
|
||||||
|
vmap({{"id", QString::fromUtf8(#id)}, {"enabled", enabled}})
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ class ConfigNode : public QObject {
|
|||||||
[[nodiscard]] virtual QStringList unknownKeys() const = 0;
|
[[nodiscard]] virtual QStringList unknownKeys() const = 0;
|
||||||
[[nodiscard]] virtual QList<ConfigNode*> childNodes() const;
|
[[nodiscard]] virtual QList<ConfigNode*> childNodes() const;
|
||||||
|
|
||||||
virtual void materializeDefaults() = 0;
|
|
||||||
|
|
||||||
void syncFromGlobal(ConfigNode* global);
|
void syncFromGlobal(ConfigNode* global);
|
||||||
virtual void resyncFromGlobal() = 0;
|
virtual void resyncFromGlobal() = 0;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user