Merge pull request #16 from Zacharias-Brohn/horizontal-media-widget
Horizontal media widget
This commit was merged in pull request #16.
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
[General]
|
||||||
|
FunctionsSpacing=true
|
||||||
|
IndentWidth=4
|
||||||
|
MaxColumnWidth=-1
|
||||||
|
NewlineType=native
|
||||||
|
NormalizeOrder=true
|
||||||
|
ObjectsSpacing=true
|
||||||
|
SemicolonRule=always
|
||||||
|
SortImports=false
|
||||||
|
UseTabs=true
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,15 +80,23 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
implicitHeight: root.implicitHeight
|
||||||
|
|
||||||
CustomClippingRect {
|
CustomClippingRect {
|
||||||
id: cover
|
id: cover
|
||||||
|
|
||||||
anchors.left: parent.left
|
Layout.alignment: Qt.AlignLeft
|
||||||
anchors.margins: Appearance.padding.large + Config.dashboard.sizes.mediaProgressThickness + Appearance.spacing.small
|
Layout.bottomMargin: Appearance.padding.large + Config.dashboard.sizes.mediaProgressThickness + Appearance.spacing.small
|
||||||
anchors.right: parent.right
|
Layout.leftMargin: Appearance.padding.large + Config.dashboard.sizes.mediaProgressThickness + Appearance.spacing.small
|
||||||
anchors.top: parent.top
|
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
|
color: DynamicColors.tPalette.m3surfaceContainerHigh
|
||||||
implicitHeight: width
|
|
||||||
radius: Infinity
|
radius: Infinity
|
||||||
|
|
||||||
MaterialIcon {
|
MaterialIcon {
|
||||||
@@ -111,24 +114,26 @@ Item {
|
|||||||
asynchronous: true
|
asynchronous: true
|
||||||
fillMode: Image.PreserveAspectCrop
|
fillMode: Image.PreserveAspectCrop
|
||||||
source: Players.active?.trackArtUrl ?? ""
|
source: Players.active?.trackArtUrl ?? ""
|
||||||
sourceSize.height: height
|
sourceSize.height: Math.floor(height)
|
||||||
sourceSize.width: width
|
sourceSize.width: Math.floor(width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomText {
|
CustomRect {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
|
||||||
|
MarqueeText {
|
||||||
id: title
|
id: title
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: cover.bottom
|
anchors.top: parent.top
|
||||||
anchors.topMargin: Appearance.spacing.normal
|
|
||||||
animate: true
|
|
||||||
color: DynamicColors.palette.m3primary
|
color: DynamicColors.palette.m3primary
|
||||||
elide: Text.ElideRight
|
|
||||||
font.pointSize: Appearance.font.size.normal
|
font.pointSize: Appearance.font.size.normal
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
pauseMs: 4000
|
||||||
text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
|
text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
|
||||||
width: parent.implicitWidth - Appearance.padding.large * 2
|
width: parent.width - Appearance.padding.large * 4
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomText {
|
CustomText {
|
||||||
@@ -143,7 +148,6 @@ Item {
|
|||||||
font.pointSize: Appearance.font.size.small
|
font.pointSize: Appearance.font.size.small
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
|
text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
|
||||||
width: parent.implicitWidth - Appearance.padding.large * 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomText {
|
CustomText {
|
||||||
@@ -157,7 +161,6 @@ Item {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
|
text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
|
||||||
width: parent.implicitWidth - Appearance.padding.large * 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
@@ -195,6 +198,8 @@ Item {
|
|||||||
icon: "skip_next"
|
icon: "skip_next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
component Control: CustomRect {
|
component Control: CustomRect {
|
||||||
id: control
|
id: control
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 {
|
|
||||||
}
|
|
||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user