Horizontal media widget #16

Merged
Zacharias-Brohn merged 8 commits from horizontal-media-widget into settingsWindow 2026-02-25 21:59:57 +01:00
31 changed files with 906 additions and 803 deletions
+10
View File
@@ -0,0 +1,10 @@
[General]
FunctionsSpacing=true
IndentWidth=4
MaxColumnWidth=-1
NewlineType=native
NormalizeOrder=true
ObjectsSpacing=true
SemicolonRule=always
SortImports=false
UseTabs=true
+135
View File
@@ -0,0 +1,135 @@
import QtQuick
import QtQuick.Layouts
import qs.Config
ColumnLayout {
id: root
default property alias content: contentColumn.data
property string description: ""
property bool expanded: false
property bool nested: false
property bool showBackground: false
required property string title
signal toggleRequested
Layout.fillWidth: true
spacing: Appearance.spacing.small
Item {
id: sectionHeaderItem
Layout.fillWidth: true
Layout.preferredHeight: Math.max(titleRow.implicitHeight + Appearance.padding.normal * 2, 48)
RowLayout {
id: titleRow
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.normal
anchors.right: parent.right
anchors.rightMargin: Appearance.padding.normal
anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.normal
CustomText {
font.pointSize: Appearance.font.size.larger
font.weight: 500
text: root.title
}
Item {
Layout.fillWidth: true
}
MaterialIcon {
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.normal
rotation: root.expanded ? 180 : 0
text: "expand_more"
Behavior on rotation {
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
}
StateLayer {
function onClicked(): void {
root.toggleRequested();
root.expanded = !root.expanded;
}
anchors.fill: parent
color: DynamicColors.palette.m3onSurface
radius: Appearance.rounding.normal
showHoverBackground: false
}
}
Item {
id: contentWrapper
Layout.fillWidth: true
Layout.preferredHeight: root.expanded ? (contentColumn.implicitHeight + Appearance.spacing.small * 2) : 0
clip: true
Behavior on Layout.preferredHeight {
Anim {
easing.bezierCurve: Appearance.anim.curves.standard
}
}
CustomRect {
id: backgroundRect
anchors.fill: parent
color: DynamicColors.transparency.enabled ? DynamicColors.layer(DynamicColors.palette.m3surfaceContainer, root.nested ? 3 : 2) : (root.nested ? DynamicColors.palette.m3surfaceContainerHigh : DynamicColors.palette.m3surfaceContainer)
opacity: root.showBackground && root.expanded ? 1.0 : 0.0
radius: Appearance.rounding.normal
visible: root.showBackground
Behavior on opacity {
Anim {
easing.bezierCurve: Appearance.anim.curves.standard
}
}
}
ColumnLayout {
id: contentColumn
anchors.bottomMargin: Appearance.spacing.small
anchors.left: parent.left
anchors.leftMargin: Appearance.padding.normal
anchors.right: parent.right
anchors.rightMargin: Appearance.padding.normal
opacity: root.expanded ? 1.0 : 0.0
spacing: Appearance.spacing.small
y: Appearance.spacing.small
Behavior on opacity {
Anim {
easing.bezierCurve: Appearance.anim.curves.standard
}
}
CustomText {
id: descriptionText
Layout.bottomMargin: root.description !== "" ? Appearance.spacing.small : 0
Layout.fillWidth: true
Layout.topMargin: root.description !== "" ? Appearance.spacing.smaller : 0
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.small
text: root.description
visible: root.description !== ""
wrapMode: Text.Wrap
}
}
}
}
+166
View File
@@ -0,0 +1,166 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import qs.Config
RowLayout {
id: root
property string displayText: root.value.toString()
property bool isEditing: false
property real max: Infinity
property real min: -Infinity
property alias repeatRate: timer.interval
property real step: 1
property real value
signal valueModified(value: real)
spacing: Appearance.spacing.small
onValueChanged: {
if (!root.isEditing) {
root.displayText = root.value.toString();
}
}
CustomTextField {
id: textField
inputMethodHints: Qt.ImhFormattedNumbersOnly
leftPadding: Appearance.padding.normal
padding: Appearance.padding.small
rightPadding: Appearance.padding.normal
text: root.isEditing ? text : root.displayText
background: CustomRect {
color: DynamicColors.tPalette.m3surfaceContainerHigh
implicitWidth: 100
radius: Appearance.rounding.small
}
validator: DoubleValidator {
bottom: root.min
decimals: root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0
top: root.max
}
onAccepted: {
const numValue = parseFloat(text);
if (!isNaN(numValue)) {
const clampedValue = Math.max(root.min, Math.min(root.max, numValue));
root.value = clampedValue;
root.displayText = clampedValue.toString();
root.valueModified(clampedValue);
} else {
text = root.displayText;
}
root.isEditing = false;
}
onActiveFocusChanged: {
if (activeFocus) {
root.isEditing = true;
} else {
root.isEditing = false;
root.displayText = root.value.toString();
}
}
onEditingFinished: {
if (text !== root.displayText) {
const numValue = parseFloat(text);
if (!isNaN(numValue)) {
const clampedValue = Math.max(root.min, Math.min(root.max, numValue));
root.value = clampedValue;
root.displayText = clampedValue.toString();
root.valueModified(clampedValue);
} else {
text = root.displayText;
}
}
root.isEditing = false;
}
}
CustomRect {
color: DynamicColors.palette.m3primary
implicitHeight: upIcon.implicitHeight + Appearance.padding.small * 2
implicitWidth: implicitHeight
radius: Appearance.rounding.small
StateLayer {
id: upState
function onClicked(): void {
let newValue = Math.min(root.max, root.value + root.step);
// Round to avoid floating point precision errors
const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0;
newValue = Math.round(newValue * Math.pow(10, decimals)) / Math.pow(10, decimals);
root.value = newValue;
root.displayText = newValue.toString();
root.valueModified(newValue);
}
color: DynamicColors.palette.m3onPrimary
onPressAndHold: timer.start()
onReleased: timer.stop()
}
MaterialIcon {
id: upIcon
anchors.centerIn: parent
color: DynamicColors.palette.m3onPrimary
text: "keyboard_arrow_up"
}
}
CustomRect {
color: DynamicColors.palette.m3primary
implicitHeight: downIcon.implicitHeight + Appearance.padding.small * 2
implicitWidth: implicitHeight
radius: Appearance.rounding.small
StateLayer {
id: downState
function onClicked(): void {
let newValue = Math.max(root.min, root.value - root.step);
// Round to avoid floating point precision errors
const decimals = root.step < 1 ? Math.max(1, Math.ceil(-Math.log10(root.step))) : 0;
newValue = Math.round(newValue * Math.pow(10, decimals)) / Math.pow(10, decimals);
root.value = newValue;
root.displayText = newValue.toString();
root.valueModified(newValue);
}
color: DynamicColors.palette.m3onPrimary
onPressAndHold: timer.start()
onReleased: timer.stop()
}
MaterialIcon {
id: downIcon
anchors.centerIn: parent
color: DynamicColors.palette.m3onPrimary
text: "keyboard_arrow_down"
}
}
Timer {
id: timer
interval: 100
repeat: true
triggeredOnStart: true
onTriggered: {
if (upState.pressed)
upState.onClicked();
else if (downState.pressed)
downState.onClicked();
}
}
}
+202
View File
@@ -0,0 +1,202 @@
import QtQuick
import QtQuick.Effects
Item {
id: root
property color color: DynamicColors.palette.m3onSurface
property int fadeStrengthAnimMs: 180
property real fadeStrengthIdle: 0.0
property real fadeStrengthMoving: 1.0
property alias font: elideText.font
property int gap: 40
property alias horizontalAlignment: elideText.horizontalAlignment
property bool leftFadeEnabled: false
property real leftFadeStrength: overflowing && leftFadeEnabled
? fadeStrengthMoving : fadeStrengthIdle
property int leftFadeWidth: 28
property bool marqueeEnabled: true
readonly property bool overflowing: metrics.width > root.width
property int pauseMs: 1200
property real pixelsPerSecond: 40
property real rightFadeStrength: overflowing ? fadeStrengthMoving :
fadeStrengthIdle
property int rightFadeWidth: 28
property bool sliding: false
property alias text: elideText.text
function durationForDistance(px): int {
return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000));
}
clip: true
implicitHeight: elideText.implicitHeight
Behavior on leftFadeStrength {
Anim {
}
}
Behavior on rightFadeStrength {
Anim {
}
}
onTextChanged: strip.x = 0
onVisibleChanged: if (!visible)
strip.x = 0
onWidthChanged: strip.x = 0
TextMetrics {
id: metrics
font: elideText.font
text: elideText.text
}
CustomText {
id: elideText
anchors.verticalCenter: parent.verticalCenter
color: root.color
elide: Text.ElideRight
visible: !root.overflowing
width: root.width
}
Item {
id: marqueeViewport
anchors.fill: parent
clip: true
layer.enabled: true
visible: root.overflowing
layer.effect: OpacityMask {
maskSource: rightFadeMask
}
Item {
id: strip
anchors.verticalCenter: parent.verticalCenter
height: t1.implicitHeight
width: t1.width + root.gap + t2.width
x: 0
CustomText {
id: t1
color: root.color
text: elideText.text
}
CustomText {
id: t2
color: root.color
text: t1.text
x: t1.width + root.gap
}
}
SequentialAnimation {
id: marqueeAnim
loops: Animation.Infinite
running: root.marqueeEnabled && root.overflowing && root.visible
ScriptAction {
script: {
strip.x = 0;
root.sliding = false;
root.leftFadeEnabled = false;
}
}
PauseAnimation {
duration: root.pauseMs
}
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;
}
}
}
}
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
}
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
}
}
}
}
+107
View File
@@ -0,0 +1,107 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import qs.Config
Elevation {
id: root
property MenuItem active: items[0] ?? null
property bool expanded
property list<MenuItem> items
signal itemSelected(item: MenuItem)
implicitHeight: root.expanded ? column.implicitHeight : 0
implicitWidth: Math.max(200, column.implicitWidth)
level: 2
opacity: root.expanded ? 1 : 0
radius: Appearance.rounding.small / 2
Behavior on implicitHeight {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
Behavior on opacity {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
}
}
CustomClippingRect {
anchors.fill: parent
color: DynamicColors.palette.m3surfaceContainer
radius: parent.radius
ColumnLayout {
id: column
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
Repeater {
model: root.items
CustomRect {
id: item
readonly property bool active: modelData === root.active
required property int index
required property MenuItem modelData
Layout.fillWidth: true
color: Qt.alpha(DynamicColors.palette.m3secondaryContainer, active ? 1 : 0)
implicitHeight: menuOptionRow.implicitHeight + Appearance.padding.normal * 2
implicitWidth: menuOptionRow.implicitWidth + Appearance.padding.normal * 2
StateLayer {
function onClicked(): void {
root.itemSelected(item.modelData);
root.active = item.modelData;
root.expanded = false;
}
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
disabled: !root.expanded
}
RowLayout {
id: menuOptionRow
anchors.fill: parent
anchors.margins: Appearance.padding.normal
spacing: Appearance.spacing.small
MaterialIcon {
Layout.alignment: Qt.AlignVCenter
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurfaceVariant
text: item.modelData.icon
}
CustomText {
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.text
}
Loader {
Layout.alignment: Qt.AlignVCenter
active: item.modelData.trailingIcon.length > 0
visible: active
sourceComponent: MaterialIcon {
color: item.active ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
text: item.modelData.trailingIcon
}
}
}
}
}
}
}
}
+12
View File
@@ -0,0 +1,12 @@
import QtQuick
QtObject {
property string activeIcon: icon
property string activeText: text
property string icon
required property string text
property string trailingIcon
property var value
signal clicked
}
+50
View File
@@ -0,0 +1,50 @@
import QtQuick
import QtQuick.Layouts
import qs.Config
CustomRect {
id: root
required property string label
required property real max
required property real min
property var onValueModified: function (value) {}
property real step: 1
required property real value
Layout.fillWidth: true
color: DynamicColors.layer(DynamicColors.palette.m3surfaceContainer, 2)
implicitHeight: row.implicitHeight + Appearance.padding.large * 2
radius: Appearance.rounding.normal
Behavior on implicitHeight {
Anim {
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Appearance.padding.large
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Appearance.spacing.normal
CustomText {
Layout.fillWidth: true
text: root.label
}
CustomSpinBox {
max: root.max
min: root.min
step: root.step
value: root.value
onValueModified: value => {
root.onValueModified(value);
}
}
}
}
+13 -6
View File
@@ -205,6 +205,7 @@ Singleton {
return { return {
expire: notifs.expire, expire: notifs.expire,
defaultExpireTimeout: notifs.defaultExpireTimeout, defaultExpireTimeout: notifs.defaultExpireTimeout,
appNotifCooldown: notifs.appNotifCooldown,
clearThreshold: notifs.clearThreshold, clearThreshold: notifs.clearThreshold,
expandThreshold: notifs.expandThreshold, expandThreshold: notifs.expandThreshold,
actionOnClick: notifs.actionOnClick, actionOnClick: notifs.actionOnClick,
@@ -306,7 +307,8 @@ Singleton {
fileView.setText(JSON.stringify(config, null, 4)); fileView.setText(JSON.stringify(config, null, 4));
} catch (e) { } catch (e) {
Toaster.toast(qsTr("Failed to serialize config"), e.message, "settings_alert", Toast.Error); Toaster.toast(qsTr("Failed to serialize config"), e.message,
"settings_alert", Toast.Error);
} }
} }
} }
@@ -337,7 +339,8 @@ Singleton {
} }
onLoadFailed: err => { onLoadFailed: err => {
if (err !== FileViewError.FileNotFound) if (err !== FileViewError.FileNotFound)
Toaster.toast(qsTr("Failed to read config"), FileViewError.toString(err), "settings_alert", Toast.Warning); Toaster.toast(qsTr("Failed to read config"), FileViewError.toString(err),
"settings_alert", Toast.Warning);
} }
onLoaded: { onLoaded: {
ModeScheduler.checkStartup(); ModeScheduler.checkStartup();
@@ -346,15 +349,19 @@ Singleton {
const elapsed = timer.elapsedMs(); const elapsed = timer.elapsedMs();
if (adapter.utilities.toasts.configLoaded && !root.recentlySaved) { if (adapter.utilities.toasts.configLoaded && !root.recentlySaved) {
Toaster.toast(qsTr("Config loaded"), qsTr("Config loaded in %1ms").arg(elapsed), "rule_settings"); Toaster.toast(qsTr("Config loaded"), qsTr("Config loaded in %1ms").arg(
elapsed), "rule_settings");
} else if (adapter.utilities.toasts.configLoaded && root.recentlySaved) { } else if (adapter.utilities.toasts.configLoaded && root.recentlySaved) {
Toaster.toast(qsTr("Config saved"), qsTr("Config reloaded in %1ms").arg(elapsed), "settings_alert"); Toaster.toast(qsTr("Config saved"), qsTr("Config reloaded in %1ms").arg(
elapsed), "settings_alert");
} }
} catch (e) { } catch (e) {
Toaster.toast(qsTr("Failed to load config"), e.message, "settings_alert", Toast.Error); Toaster.toast(qsTr("Failed to load config"), e.message, "settings_alert",
Toast.Error);
} }
} }
onSaveFailed: err => Toaster.toast(qsTr("Failed to save config"), FileViewError.toString(err), "settings_alert", Toast.Error) onSaveFailed: err => Toaster.toast(qsTr("Failed to save config"),
FileViewError.toString(err), "settings_alert", Toast.Error)
JsonAdapter { JsonAdapter {
id: adapter id: adapter
+1
View File
@@ -2,6 +2,7 @@ import Quickshell.Io
JsonObject { JsonObject {
property bool actionOnClick: false property bool actionOnClick: false
property int appNotifCooldown: 0
property real clearThreshold: 0.3 property real clearThreshold: 0.3
property int defaultExpireTimeout: 5000 property int defaultExpireTimeout: 5000
property int expandThreshold: 20 property int expandThreshold: 20
+25 -1
View File
@@ -16,6 +16,7 @@ import qs.Config
Singleton { Singleton {
id: root id: root
readonly property var appCooldownMap: new Map()
property alias dnd: props.dnd property alias dnd: props.dnd
property list<Notif> list: [] property list<Notif> list: []
property bool loaded property bool loaded
@@ -23,6 +24,27 @@ Singleton {
readonly property list<Notif> popups: list.filter(n => n.popup) readonly property list<Notif> popups: list.filter(n => n.popup)
property alias server: server property alias server: server
function shouldThrottle(appName: string): bool {
if (props.dnd)
return false;
const key = (appName || "unknown").trim().toLowerCase();
const cooldownSec = Config.notifs.appNotifCooldown;
const cooldownMs = Math.max(0, cooldownSec * 1000);
if (cooldownMs <= 0)
return true;
const now = Date.now();
const until = appCooldownMap.get(key) ?? 0;
if (now < until)
return false;
appCooldownMap.set(key, now + cooldownMs);
return true;
}
onListChanged: { onListChanged: {
if (loaded) { if (loaded) {
saveTimer.restart(); saveTimer.restart();
@@ -77,8 +99,10 @@ Singleton {
onNotification: notif => { onNotification: notif => {
notif.tracked = true; notif.tracked = true;
const is_popup = root.shouldThrottle(notif.appName);
const comp = notifComp.createObject(root, { const comp = notifComp.createObject(root, {
popup: !props.dnd, popup: is_popup,
notification: notif notification: notif
}); });
root.list = [comp, ...root.list]; root.list = [comp, ...root.list];
+11 -9
View File
@@ -8,7 +8,8 @@ import qs.Modules.Notifications.Sidebar.Utils as Utils
import qs.Modules.Dashboard as Dashboard import qs.Modules.Dashboard as Dashboard
import qs.Modules.Osd as Osd import qs.Modules.Osd as Osd
import qs.Modules.Launcher as Launcher import qs.Modules.Launcher as Launcher
import qs.Modules.Settings as Settings
// import qs.Modules.Settings as Settings
Shape { Shape {
id: root id: root
@@ -22,7 +23,8 @@ Shape {
anchors.topMargin: bar.implicitHeight anchors.topMargin: bar.implicitHeight
preferredRendererType: Shape.CurveRenderer preferredRendererType: Shape.CurveRenderer
Component.onCompleted: console.log(root.bar.implicitHeight, root.bar.anchors.topMargin) Component.onCompleted: console.log(root.bar.implicitHeight,
root.bar.anchors.topMargin)
Osd.Background { Osd.Background {
startX: root.width - root.panels.sidebar.width startX: root.width - root.panels.sidebar.width
@@ -72,11 +74,11 @@ Shape {
wrapper: root.panels.sidebar wrapper: root.panels.sidebar
} }
Settings.Background { // Settings.Background {
id: settings // id: settings
//
startX: (root.width - wrapper.width) / 2 - rounding // startX: (root.width - wrapper.width) / 2 - rounding
startY: 0 // startY: 0
wrapper: root.panels.settings // wrapper: root.panels.settings
} // }
} }
+4 -4
View File
@@ -28,7 +28,7 @@ Variants {
property bool trayMenuVisible: false property bool trayMenuVisible: false
WlrLayershell.exclusionMode: ExclusionMode.Ignore WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.keyboardFocus: visibilities.launcher || visibilities.sidebar || visibilities.dashboard ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None WlrLayershell.keyboardFocus: visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
WlrLayershell.namespace: "ZShell-Bar" WlrLayershell.namespace: "ZShell-Bar"
color: "transparent" color: "transparent"
contentItem.focus: true contentItem.focus: true
@@ -37,8 +37,6 @@ Variants {
mask: Region { mask: Region {
id: region id: region
property list<Region> nullRegions: []
height: bar.screen.height - backgroundRect.implicitHeight height: bar.screen.height - backgroundRect.implicitHeight
intersection: Intersection.Xor intersection: Intersection.Xor
regions: popoutRegions.instances regions: popoutRegions.instances
@@ -53,6 +51,7 @@ Variants {
visibilities.sidebar = false; visibilities.sidebar = false;
visibilities.dashboard = false; visibilities.dashboard = false;
visibilities.osd = false; visibilities.osd = false;
visibilities.settings = false;
} }
PanelWindow { PanelWindow {
@@ -98,7 +97,7 @@ Variants {
HyprlandFocusGrab { HyprlandFocusGrab {
id: focusGrab id: focusGrab
active: visibilities.launcher || visibilities.sidebar || visibilities.dashboard || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu")) active: visibilities.launcher || visibilities.sidebar || visibilities.dashboard || visibilities.settings || (panels.popouts.hasCurrent && panels.popouts.currentName.startsWith("traymenu"))
windows: [bar] windows: [bar]
onCleared: { onCleared: {
@@ -106,6 +105,7 @@ Variants {
visibilities.sidebar = false; visibilities.sidebar = false;
visibilities.dashboard = false; visibilities.dashboard = false;
visibilities.osd = false; visibilities.osd = false;
visibilities.settings = false;
panels.popouts.hasCurrent = false; panels.popouts.hasCurrent = false;
} }
} }
+12 -11
View File
@@ -9,7 +9,7 @@ import qs.Modules.Dashboard as Dashboard
import qs.Modules.Osd as Osd import qs.Modules.Osd as Osd
import qs.Components.Toast as Toasts import qs.Components.Toast as Toasts
import qs.Modules.Launcher as Launcher import qs.Modules.Launcher as Launcher
import qs.Modules.Settings as Settings // import qs.Modules.Settings as Settings
import qs.Config import qs.Config
Item { Item {
@@ -22,7 +22,7 @@ Item {
readonly property alias osd: osd readonly property alias osd: osd
readonly property alias popouts: popouts readonly property alias popouts: popouts
required property ShellScreen screen required property ShellScreen screen
readonly property alias settings: settings // readonly property alias settings: settings
readonly property alias sidebar: sidebar readonly property alias sidebar: sidebar
readonly property alias toasts: toasts readonly property alias toasts: toasts
readonly property alias utilities: utilities readonly property alias utilities: utilities
@@ -30,7 +30,8 @@ Item {
anchors.fill: parent anchors.fill: parent
// anchors.margins: 8 // anchors.margins: 8
anchors.topMargin: Config.barConfig.autoHide && !visibilities.bar ? 0 : bar.implicitHeight anchors.topMargin: Config.barConfig.autoHide && !visibilities.bar ? 0 :
bar.implicitHeight
Behavior on anchors.topMargin { Behavior on anchors.topMargin {
Anim { Anim {
@@ -117,12 +118,12 @@ Item {
visibilities: root.visibilities visibilities: root.visibilities
} }
Settings.Wrapper { // Settings.Wrapper {
id: settings // id: settings
//
anchors.horizontalCenter: parent.horizontalCenter // anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top // anchors.top: parent.top
panels: root // panels: root
visibilities: root.visibilities // visibilities: root.visibilities
} // }
} }
+10 -9
View File
@@ -11,12 +11,11 @@ Item {
id: root id: root
property color barColor: DynamicColors.palette.m3primary property color barColor: DynamicColors.palette.m3primary
property bool expanded: false
property color textColor: DynamicColors.palette.m3onSurface property color textColor: DynamicColors.palette.m3onSurface
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.top: parent.top anchors.top: parent.top
implicitWidth: expanded ? 300 : 150 implicitWidth: 150
Behavior on implicitWidth { Behavior on implicitWidth {
NumberAnimation { NumberAnimation {
@@ -49,16 +48,18 @@ Item {
} }
RowLayout { RowLayout {
anchors { id: layout
fill: parent
leftMargin: 10 anchors.left: parent.left
rightMargin: 15 anchors.leftMargin: Appearance.padding.small
} anchors.right: parent.right
anchors.rightMargin: Appearance.padding.small * 2
anchors.verticalCenter: parent.verticalCenter
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: Audio.muted ? DynamicColors.palette.m3error : root.textColor color: Audio.muted ? DynamicColors.palette.m3error : root.textColor
font.pixelSize: 18 font.pointSize: 14
text: Audio.muted ? "volume_off" : "volume_up" text: Audio.muted ? "volume_off" : "volume_up"
} }
@@ -91,7 +92,7 @@ Item {
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: (Audio.sourceMuted ?? false) ? DynamicColors.palette.m3error : root.textColor color: (Audio.sourceMuted ?? false) ? DynamicColors.palette.m3error : root.textColor
font.pixelSize: 18 font.pointSize: 14
text: Audio.sourceMuted ? "mic_off" : "mic" text: Audio.sourceMuted ? "mic_off" : "mic"
} }
+5 -18
View File
@@ -3,7 +3,6 @@ import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Helpers import qs.Helpers
import qs.Components import qs.Components
import qs.Paths
import qs.Modules import qs.Modules
import qs.Config import qs.Config
import qs.Modules.Dashboard.Dash import qs.Modules.Dashboard.Dash
@@ -86,18 +85,6 @@ GridLayout {
} }
} }
// Rect {
// Layout.row: 1
// Layout.preferredWidth: dateTime.implicitWidth
// Layout.fillHeight: true
//
// radius: root.radius
//
// DateTime {
// id: dateTime
// }
// }
Rect { Rect {
Layout.column: 0 Layout.column: 0
Layout.columnSpan: 3 Layout.columnSpan: 3
@@ -128,11 +115,11 @@ GridLayout {
} }
Rect { Rect {
Layout.column: 5 Layout.column: 0
Layout.fillHeight: true Layout.columnSpan: 5
Layout.preferredWidth: media.implicitWidth Layout.fillWidth: true
Layout.row: 0 Layout.preferredHeight: media.implicitHeight
Layout.rowSpan: 2 Layout.row: 2
radius: root.radius radius: root.radius
Media { Media {
+108 -103
View File
@@ -1,12 +1,10 @@
import ZShell.Services
import QtQuick import QtQuick
import QtQuick.Layouts
import QtQuick.Shapes import QtQuick.Shapes
import qs.Daemons import qs.Daemons
import qs.Components import qs.Components
import qs.Config import qs.Config
import qs.Helpers import qs.Helpers
import qs.Modules
import qs.Paths
Item { Item {
id: root id: root
@@ -15,10 +13,11 @@ Item {
const active = Players.active; const active = Players.active;
return active?.length ? active.position / active.length : 0; return active?.length ? active.position / active.length : 0;
} }
property int rowHeight: Appearance.padding.large + Config.dashboard.sizes.mediaProgressThickness + Appearance.spacing.small
anchors.bottom: parent.bottom anchors.left: parent.left
anchors.top: parent.top anchors.right: parent.right
implicitWidth: Config.dashboard.sizes.mediaWidth implicitHeight: cover.height + rowHeight * 2
Behavior on playerProgress { Behavior on playerProgress {
Anim { Anim {
@@ -35,10 +34,6 @@ Item {
onTriggered: Players.active?.positionChanged() onTriggered: Players.active?.positionChanged()
} }
ServiceRef {
service: Audio.beatTracker
}
Shape { Shape {
preferredRendererType: Shape.CurveRenderer preferredRendererType: Shape.CurveRenderer
@@ -85,114 +80,124 @@ Item {
} }
} }
CustomClippingRect { RowLayout {
id: cover id: layout
anchors.left: parent.left anchors.left: parent.left
anchors.margins: Appearance.padding.large + Config.dashboard.sizes.mediaProgressThickness + Appearance.spacing.small
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top implicitHeight: root.implicitHeight
color: DynamicColors.tPalette.m3surfaceContainerHigh
implicitHeight: width
radius: Infinity
MaterialIcon { CustomClippingRect {
anchors.centerIn: parent id: cover
color: DynamicColors.palette.m3onSurfaceVariant
font.pointSize: (parent.width * 0.4) || 1
grade: 200
text: "art_track"
}
Image { Layout.alignment: Qt.AlignLeft
id: image Layout.bottomMargin: Appearance.padding.large + Config.dashboard.sizes.mediaProgressThickness + Appearance.spacing.small
Layout.leftMargin: Appearance.padding.large + Config.dashboard.sizes.mediaProgressThickness + Appearance.spacing.small
Layout.preferredHeight: Config.dashboard.sizes.mediaCoverArtSize
Layout.preferredWidth: Config.dashboard.sizes.mediaCoverArtSize
Layout.topMargin: Appearance.padding.large + Config.dashboard.sizes.mediaProgressThickness + Appearance.spacing.small
color: DynamicColors.tPalette.m3surfaceContainerHigh
radius: Infinity
anchors.fill: parent MaterialIcon {
asynchronous: true anchors.centerIn: parent
fillMode: Image.PreserveAspectCrop color: DynamicColors.palette.m3onSurfaceVariant
source: Players.active?.trackArtUrl ?? "" font.pointSize: (parent.width * 0.4) || 1
sourceSize.height: height grade: 200
sourceSize.width: width text: "art_track"
}
}
CustomText {
id: title
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: cover.bottom
anchors.topMargin: Appearance.spacing.normal
animate: true
color: DynamicColors.palette.m3primary
elide: Text.ElideRight
font.pointSize: Appearance.font.size.normal
horizontalAlignment: Text.AlignHCenter
text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
width: parent.implicitWidth - Appearance.padding.large * 2
}
CustomText {
id: album
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: title.bottom
anchors.topMargin: Appearance.spacing.small
animate: true
color: DynamicColors.palette.m3outline
elide: Text.ElideRight
font.pointSize: Appearance.font.size.small
horizontalAlignment: Text.AlignHCenter
text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
width: parent.implicitWidth - Appearance.padding.large * 2
}
CustomText {
id: artist
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: album.bottom
anchors.topMargin: Appearance.spacing.small
animate: true
color: DynamicColors.palette.m3secondary
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
width: parent.implicitWidth - Appearance.padding.large * 2
}
Row {
id: controls
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: artist.bottom
anchors.topMargin: Appearance.spacing.smaller
spacing: Appearance.spacing.small
Control {
function onClicked(): void {
Players.active?.previous();
} }
canUse: Players.active?.canGoPrevious ?? false Image {
icon: "skip_previous" id: image
anchors.fill: parent
asynchronous: true
fillMode: Image.PreserveAspectCrop
source: Players.active?.trackArtUrl ?? ""
sourceSize.height: Math.floor(height)
sourceSize.width: Math.floor(width)
}
} }
Control { CustomRect {
function onClicked(): void { Layout.fillWidth: true
Players.active?.togglePlaying(); Layout.preferredHeight: childrenRect.height
MarqueeText {
id: title
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
color: DynamicColors.palette.m3primary
font.pointSize: Appearance.font.size.normal
horizontalAlignment: Text.AlignHCenter
pauseMs: 4000
text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
width: parent.width - Appearance.padding.large * 4
} }
canUse: Players.active?.canTogglePlaying ?? false CustomText {
icon: Players.active?.isPlaying ? "pause" : "play_arrow" id: album
}
Control { anchors.horizontalCenter: parent.horizontalCenter
function onClicked(): void { anchors.top: title.bottom
Players.active?.next(); anchors.topMargin: Appearance.spacing.small
animate: true
color: DynamicColors.palette.m3outline
elide: Text.ElideRight
font.pointSize: Appearance.font.size.small
horizontalAlignment: Text.AlignHCenter
text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
} }
canUse: Players.active?.canGoNext ?? false CustomText {
icon: "skip_next" id: artist
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: album.bottom
anchors.topMargin: Appearance.spacing.small
animate: true
color: DynamicColors.palette.m3secondary
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
}
Row {
id: controls
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: artist.bottom
anchors.topMargin: Appearance.spacing.smaller
spacing: Appearance.spacing.small
Control {
function onClicked(): void {
Players.active?.previous();
}
canUse: Players.active?.canGoPrevious ?? false
icon: "skip_previous"
}
Control {
function onClicked(): void {
Players.active?.togglePlaying();
}
canUse: Players.active?.canTogglePlaying ?? false
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
}
Control {
function onClicked(): void {
Players.active?.next();
}
canUse: Players.active?.canGoNext ?? false
icon: "skip_next"
}
}
} }
} }
+2 -2
View File
@@ -13,7 +13,7 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.top: parent.top anchors.top: parent.top
implicitWidth: 25 implicitWidth: 30
CustomRect { CustomRect {
anchors.bottomMargin: 3 anchors.bottomMargin: 3
@@ -30,7 +30,7 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
color: iconColor color: iconColor
font.family: "Material Symbols Rounded" font.family: "Material Symbols Rounded"
font.pixelSize: 20 font.pointSize: 16
text: HasNotifications.hasNotifications ? "\uf4fe" : "\ue7f4" text: HasNotifications.hasNotifications ? "\uf4fe" : "\ue7f4"
Behavior on color { Behavior on color {
+7 -8
View File
@@ -14,7 +14,7 @@ Item {
clip: true clip: true
implicitHeight: 34 implicitHeight: 34
implicitWidth: rowLayout.implicitWidth + rowLayout.anchors.leftMargin + rowLayout.anchors.rightMargin implicitWidth: rowLayout.implicitWidth + Appearance.padding.small * 2
Rectangle { Rectangle {
id: backgroundRect id: backgroundRect
@@ -37,19 +37,18 @@ Item {
RowLayout { RowLayout {
id: rowLayout id: rowLayout
anchors.fill: parent anchors.centerIn: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
spacing: 6 spacing: 6
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: DynamicColors.palette.m3onSurface color: DynamicColors.palette.m3onSurface
font.pixelSize: 18 font.pointSize: 14
text: "memory_alt" text: "memory_alt"
} }
Resource { Resource {
Layout.alignment: Qt.AlignVCenter
mainColor: DynamicColors.palette.m3primary mainColor: DynamicColors.palette.m3primary
percentage: ResourceUsage.memoryUsedPercentage percentage: ResourceUsage.memoryUsedPercentage
warningThreshold: 95 warningThreshold: 95
@@ -58,7 +57,7 @@ Item {
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: DynamicColors.palette.m3onSurface color: DynamicColors.palette.m3onSurface
font.pixelSize: 18 font.pointSize: 14
text: "memory" text: "memory"
} }
@@ -71,7 +70,7 @@ Item {
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: DynamicColors.palette.m3onSurface color: DynamicColors.palette.m3onSurface
font.pixelSize: 18 font.pointSize: 14
text: "gamepad" text: "gamepad"
} }
@@ -83,7 +82,7 @@ Item {
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: DynamicColors.palette.m3onSurface color: DynamicColors.palette.m3onSurface
font.pixelSize: 18 font.pointSize: 14
text: "developer_board" text: "developer_board"
} }
-66
View File
@@ -1,66 +0,0 @@
import QtQuick
import QtQuick.Shapes
import qs.Components
import qs.Config
ShapePath {
id: root
readonly property bool flatten: wrapper.height < rounding * 2
readonly property real rounding: 8
readonly property real roundingY: flatten ? wrapper.height / 2 : rounding
required property Wrapper wrapper
fillColor: DynamicColors.palette.m3surface
strokeWidth: -1
Behavior on fillColor {
CAnim {
}
}
PathArc {
radiusX: root.rounding
radiusY: Math.min(root.roundingY, root.wrapper.height)
relativeX: root.rounding
relativeY: root.roundingY
}
PathLine {
relativeX: 0
relativeY: root.wrapper.height - root.roundingY * 2
}
PathArc {
direction: PathArc.Counterclockwise
radiusX: root.rounding
radiusY: Math.min(root.rounding, root.wrapper.height)
relativeX: root.rounding
relativeY: root.roundingY
}
PathLine {
relativeX: root.wrapper.width - root.rounding * 2
relativeY: 0
}
PathArc {
direction: PathArc.Counterclockwise
radiusX: root.rounding
radiusY: Math.min(root.rounding, root.wrapper.height)
relativeX: root.rounding
relativeY: -root.roundingY
}
PathLine {
relativeX: 0
relativeY: -(root.wrapper.height - root.roundingY * 2)
}
PathArc {
radiusX: root.rounding
radiusY: Math.min(root.rounding, root.wrapper.height)
relativeX: root.rounding
relativeY: -root.roundingY
}
}
-178
View File
@@ -1,178 +0,0 @@
pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Modules as Modules
import qs.Config
import qs.Helpers
Item {
id: root
required property Item content
implicitHeight: clayout.contentHeight + Appearance.padding.smaller * 2
implicitWidth: clayout.contentWidth + Appearance.padding.smaller * 2
ListModel {
id: listModel
ListElement {
icon: "settings"
name: "General"
}
ListElement {
icon: "wallpaper"
name: "Wallpaper"
}
ListElement {
icon: "settop_component"
name: "Bar"
}
ListElement {
icon: "lock"
name: "Lockscreen"
}
ListElement {
icon: "build_circle"
name: "Services"
}
ListElement {
icon: "notifications"
name: "Notifications"
}
ListElement {
icon: "view_sidebar"
name: "Sidebar"
}
ListElement {
icon: "handyman"
name: "Utilities"
}
ListElement {
icon: "dashboard"
name: "Dashboard"
}
ListElement {
icon: "colors"
name: "Appearance"
}
ListElement {
icon: "display_settings"
name: "On screen display"
}
ListElement {
icon: "rocket_launch"
name: "Launcher"
}
ListElement {
icon: "colors"
name: "Colors"
}
}
CustomRect {
anchors.fill: parent
color: DynamicColors.tPalette.m3surfaceContainer
radius: 4
CustomListView {
id: clayout
anchors.centerIn: parent
contentHeight: contentItem.childrenRect.height
contentWidth: contentItem.childrenRect.width
highlightFollowsCurrentItem: false
implicitHeight: contentItem.childrenRect.height
implicitWidth: contentItem.childrenRect.width
model: listModel
spacing: 5
delegate: Category {
}
highlight: CustomRect {
color: DynamicColors.palette.m3primary
implicitHeight: clayout.currentItem?.implicitHeight ?? 0
implicitWidth: clayout.width
radius: 4
y: clayout.currentItem?.y ?? 0
Behavior on y {
Anim {
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.expressiveEffects
}
}
}
}
}
component Category: CustomRect {
id: categoryItem
required property string icon
required property int index
required property string name
implicitHeight: 42
implicitWidth: 200
radius: 4
RowLayout {
id: layout
anchors.left: parent.left
anchors.margins: Appearance.padding.smaller
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
MaterialIcon {
id: icon
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillHeight: true
Layout.preferredWidth: icon.contentWidth
color: categoryItem.index === clayout.currentIndex ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
font.pointSize: 22
text: categoryItem.icon
verticalAlignment: Text.AlignVCenter
}
CustomText {
id: text
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillHeight: true
Layout.fillWidth: true
Layout.leftMargin: Appearance.spacing.normal
color: categoryItem.index === clayout.currentIndex ? DynamicColors.palette.m3onPrimary : DynamicColors.palette.m3onSurface
text: categoryItem.name
verticalAlignment: Text.AlignVCenter
}
}
StateLayer {
id: layer
onClicked: {
root.content.currentCategory = categoryItem.name.toLowerCase();
clayout.currentIndex = categoryItem.index;
}
}
}
}
@@ -1,66 +0,0 @@
import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Modules as Modules
import qs.Modules.Settings.Controls
import qs.Config
import qs.Helpers
CustomRect {
id: root
ColumnLayout {
id: clayout
anchors.left: parent.left
anchors.right: parent.right
CustomRect {
Layout.fillWidth: true
Layout.preferredHeight: colorLayout.implicitHeight
color: DynamicColors.tPalette.m3surfaceContainer
ColumnLayout {
id: colorLayout
anchors.left: parent.left
anchors.margins: Appearance.padding.large
anchors.right: parent.right
Settings {
name: "smth"
}
SettingSwitch {
name: "wallust"
object: Config.general.color
setting: "wallust"
}
}
}
}
component Settings: CustomRect {
id: settingsItem
required property string name
Layout.preferredHeight: 42
Layout.preferredWidth: 200
radius: 4
CustomText {
id: text
anchors.left: parent.left
anchors.margins: Appearance.padding.smaller
anchors.right: parent.right
font.bold: true
font.pointSize: 32
text: settingsItem.name
verticalAlignment: Text.AlignVCenter
}
}
}
@@ -1,13 +0,0 @@
import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Modules as Modules
import qs.Config
import qs.Helpers
CustomRect {
id: root
}
-55
View File
@@ -1,55 +0,0 @@
import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Modules as Modules
import qs.Config
import qs.Helpers
CustomRect {
id: root
ColumnLayout {
id: clayout
anchors.fill: parent
Settings {
name: "apps"
}
Item {
}
}
component Settings: CustomRect {
id: settingsItem
required property string name
implicitHeight: 42
implicitWidth: 200
radius: 4
RowLayout {
id: layout
anchors.left: parent.left
anchors.margins: Appearance.padding.smaller
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
CustomText {
id: text
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.fillHeight: true
Layout.fillWidth: true
Layout.leftMargin: Appearance.spacing.normal
text: settingsItem.name
verticalAlignment: Text.AlignVCenter
}
}
}
}
-102
View File
@@ -1,102 +0,0 @@
import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Controls
import qs.Components
import qs.Modules as Modules
import qs.Modules.Settings.Categories as Cat
import qs.Config
import qs.Helpers
Item {
id: root
property string currentCategory: "general"
readonly property real nonAnimHeight: view.implicitHeight + viewWrapper.anchors.margins * 2
readonly property real nonAnimWidth: view.implicitWidth + 500 + viewWrapper.anchors.margins * 2
required property PersistentProperties visibilities
implicitHeight: nonAnimHeight
implicitWidth: nonAnimWidth
Connections {
function onCurrentCategoryChanged() {
stack.pop();
if (currentCategory === "general") {
stack.push(general);
} else if (currentCategory === "wallpaper") {
stack.push(background);
} else if (currentCategory === "appearance") {
stack.push(appearance);
}
}
target: root
}
ClippingRectangle {
id: viewWrapper
anchors.fill: parent
anchors.margins: Appearance.padding.smaller
color: "transparent"
Item {
id: view
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.top: parent.top
implicitHeight: layout.implicitHeight
implicitWidth: layout.implicitWidth
Categories {
id: layout
anchors.fill: parent
content: root
}
}
CustomClippingRect {
id: categoryContent
anchors.bottom: parent.bottom
anchors.left: view.right
anchors.leftMargin: Appearance.spacing.smaller
anchors.right: parent.right
anchors.top: parent.top
color: DynamicColors.tPalette.m3surfaceContainer
radius: 4
StackView {
id: stack
anchors.fill: parent
anchors.margins: Appearance.padding.smaller
initialItem: general
}
}
}
Component {
id: general
Cat.General {
}
}
Component {
id: background
Cat.Background {
}
}
Component {
id: appearance
Cat.Appearance {
}
}
}
@@ -1,36 +0,0 @@
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Config
RowLayout {
id: root
required property string name
required property var object
required property string setting
Layout.fillWidth: true
Layout.preferredHeight: 42
CustomText {
id: text
Layout.alignment: Qt.AlignLeft
Layout.fillWidth: true
font.pointSize: 16
text: root.name
}
CustomSwitch {
id: cswitch
Layout.alignment: Qt.AlignRight
checked: root.object[root.setting]
onToggled: {
root.object[root.setting] = checked;
Config.save();
}
}
}
-11
View File
@@ -1,11 +0,0 @@
import Quickshell
import Quickshell.Widgets
import QtQuick
import QtQuick.Layouts
import qs.Components
import qs.Modules as Modules
import qs.Config
import qs.Helpers
Item {
}
-61
View File
@@ -1,61 +0,0 @@
import Quickshell
import QtQuick
import qs.Components
import qs.Config
import qs.Helpers
Item {
id: root
required property var panels
required property PersistentProperties visibilities
implicitHeight: 0
implicitWidth: content.implicitWidth
visible: height > 0
states: State {
name: "visible"
when: root.visibilities.settings
PropertyChanges {
root.implicitHeight: content.implicitHeight
}
}
transitions: [
Transition {
from: ""
to: "visible"
Anim {
duration: MaterialEasing.expressiveEffectsTime
easing.bezierCurve: MaterialEasing.expressiveEffects
property: "implicitHeight"
target: root
}
},
Transition {
from: "visible"
to: ""
Anim {
easing.bezierCurve: MaterialEasing.expressiveEffects
property: "implicitHeight"
target: root
}
}
]
Loader {
id: content
active: true
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
visible: true
sourceComponent: Content {
visibilities: root.visibilities
}
}
}
+11 -33
View File
@@ -12,62 +12,40 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.top: parent.top anchors.top: parent.top
implicitWidth: textMetrics.width + contentRow.spacing + 30 implicitWidth: contentRow.childrenRect.width + Appearance.spacing.smaller
Rectangle { CustomRect {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: DynamicColors.tPalette.m3surfaceContainer color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: 22 implicitHeight: 22
radius: height / 2 radius: height / 2
Behavior on color {
CAnim {
}
}
} }
RowLayout { RowLayout {
id: contentRow id: contentRow
spacing: 10 anchors.centerIn: parent
implicitHeight: 22
spacing: Appearance.spacing.small
anchors { MaterialIcon {
fill: parent Layout.alignment: Qt.AlignVCenter
leftMargin: 5 font.pointSize: 14
rightMargin: 5 text: "package_2"
}
Text {
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
color: root.textColor
font.family: "Material Symbols Rounded"
font.pixelSize: 18
text: "\uf569"
Behavior on color {
CAnim {
}
}
} }
TextMetrics { TextMetrics {
id: textMetrics id: textMetrics
font.pixelSize: 16
text: root.countUpdates text: root.countUpdates
} }
Text { CustomText {
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
color: root.textColor color: root.textColor
font.pointSize: 12
text: textMetrics.text text: textMetrics.text
Behavior on color {
CAnim {
}
}
} }
} }
} }
Binary file not shown.
+15 -11
View File
@@ -1,19 +1,23 @@
# Ideas/Features # Ideas/Features
- [x] Media showing; what song/media is playing?
- [x] Brightness control for Laptops.
- [x] Battery icon for Laptops. Broken?
- [ ] Change volume for `$BROWSER` environment variable? Most general media source apart from separate music/video players. - [ ] Change volume for `$BROWSER` environment variable? Most general media source apart from separate music/video players.
- [ ] Quick toggle for BT, WiFi (modules in the tray do this too)
- [x] Auto hide unless on mouse hover. Also implement bar changes to mute/volume to show notif or show bar for a couple seconds.
- [x] Maybe already possible; have keybinds to show certain menus. I do not want to touch my mouse to see notifications for example. Not everything in the bar needs this, but some would be good to have.
- [x] Pressing ESC or some obvious button to close nc.
- [x] Another branch for development, hold off big changes so that a working bar or if there are big config changes.
# Stupid idea's from Daivin # Stupid idea's from Daivin
- [ ] An on screen pencil to draw on your screen :). - [ ] An on screen pencil to draw on your screen :).
- [ ] Audio module + cava / audio wave ;) ( Don't make it into minecraft blocks - [ ] Audio module + cava / audio wave ;) ( Don't make it into minecraft blocks
but aan actual wave) but aan actual wave) -- Probably not planned
- [ ] Update module: When there is 1 package it still looks extremely off - [ ] Bluetooth device battery view -- Not planned ( Don't have a bluetooth
- [ ] Bluetooth device battery view receiver )
# Completed features
- [x] Auto hide unless on mouse hover. Also implement bar changes to mute/volume to show notif or show bar for a couple seconds.
- [x] Maybe already possible; have keybinds to show certain menus. I do not want to touch my mouse to see notifications for example. Not everything in the bar needs this, but some would be good to have.
- [x] Pressing ESC or some obvious button to close nc.
- [x] Another branch for development, hold off big changes so that a working bar or if there are big config changes.
- [x] Media showing; what song/media is playing?
- [x] Brightness control for Laptops.
- [x] Battery icon for Laptops. Broken?
- [x] Quick toggle for BT, WiFi (modules in the tray do this too)
- [x] Update module: When there is 1 package it still looks extremely off
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB