Compare commits

..

4 Commits

37 changed files with 1137 additions and 386 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
launcher/launcher_state.json

View File

@@ -12,6 +12,9 @@ PanelWindow {
readonly property var cfg: Cfg.Config readonly property var cfg: Cfg.Config
readonly property real barEdgePad: cfg.frameVariant === "bar" ? (isTop ? cfg.frameBarPadTop : cfg.frameBarPadBottom) : 0
readonly property real barRoundPad: cfg.frameVariant === "bar" ? Math.min(cfg.radius, cfg.barHeight / 2) : 0
color: "transparent" color: "transparent"
anchors { anchors {
top: isTop top: isTop
@@ -19,15 +22,21 @@ PanelWindow {
left: true left: true
right: true right: true
} }
implicitHeight: cfg.barHeight implicitHeight: cfg.barHeight + barEdgePad
WlrLayershell.layer: WlrLayer.Top WlrLayershell.layer: WlrLayer.Top
WlrLayershell.namespace: "main-shell-bar" WlrLayershell.namespace: "main-shell-bar"
WlrLayershell.exclusiveZone: cfg.barHeight WlrLayershell.exclusiveZone: cfg.barHeight + barEdgePad
Item { Item {
id: animatedWrapper id: animatedWrapper
anchors.fill: parent anchors {
fill: parent
topMargin: isTop ? barEdgePad : 0
bottomMargin: !isTop ? barEdgePad : 0
leftMargin: 0
rightMargin: 0
}
opacity: 0 opacity: 0
scale: 0.95 scale: 0.95
@@ -66,8 +75,8 @@ PanelWindow {
Item { Item {
id: barContent id: barContent
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: cfg.margin anchors.leftMargin: cfg.margin + barRoundPad
anchors.rightMargin: cfg.margin anchors.rightMargin: cfg.margin + barRoundPad
function bindModule(item, side) { function bindModule(item, side) {
item.height = Qt.binding(() => barContent.height - 12) item.height = Qt.binding(() => barContent.height - 12)
@@ -78,6 +87,7 @@ PanelWindow {
"targetScreen": barWindow.modelData, "targetScreen": barWindow.modelData,
"barHeight": cfg.barHeight, "barHeight": cfg.barHeight,
"barMargin": cfg.margin, "barMargin": cfg.margin,
"barEdgePad": barEdgePad,
"barSide": side, "barSide": side,
"menuWindow": barWindow "menuWindow": barWindow
} }

View File

@@ -16,7 +16,9 @@ ModuleChip {
id: configWriter id: configWriter
} }
width: chipRow.implicitWidth + 24 width: cryptoIcon.visible
? (12 + cryptoIcon.implicitWidth + 7 + chipRow.implicitWidth + 12)
: (chipRow.implicitWidth + 24)
radius: panelRadius radius: panelRadius
chipColor: t.cryptoBg chipColor: t.cryptoBg
@@ -152,6 +154,7 @@ ModuleChip {
if (root.localPairs.length <= 1) return if (root.localPairs.length <= 1) return
root.activeCoinIndex = (root.activeCoinIndex - 1 + root.localPairs.length) % root.localPairs.length root.activeCoinIndex = (root.activeCoinIndex - 1 + root.localPairs.length) % root.localPairs.length
root._applyFromCache() root._applyFromCache()
root._restartTyping()
rotateTimer.restart() rotateTimer.restart()
} }
@@ -159,6 +162,7 @@ ModuleChip {
if (root.localPairs.length <= 1) return if (root.localPairs.length <= 1) return
root.activeCoinIndex = (root.activeCoinIndex + 1) % root.localPairs.length root.activeCoinIndex = (root.activeCoinIndex + 1) % root.localPairs.length
root._applyFromCache() root._applyFromCache()
root._restartTyping()
rotateTimer.restart() rotateTimer.restart()
} }
@@ -184,6 +188,51 @@ ModuleChip {
sparklineData = entry.sparkline || [] sparklineData = entry.sparkline || []
change7d = entry.change7d || 0 change7d = entry.change7d || 0
hasError = false hasError = false
root._restartTyping()
}
property bool _typing: false
property int _typedLabel: 0
property int _typedValue: 0
property int _typedIcon: 0
function _restartTyping() {
typeAnim.stop()
_typing = true
_typedLabel = 0
_typedValue = 0
_typedIcon = 0
typeAnimLabel.to = (root.coinSymbol + "/" + root.displayCurrency.toUpperCase() + ": ").length
typeAnimValue.to = (root.hasError ? "err" : root.price < 0 ? "…" : root.compactPrice(root.price)).length
typeAnimIcon.to = (root.price >= 0 ? 1 : 0)
typeAnim.start()
}
SequentialAnimation {
id: typeAnim
onStopped: { root._typing = false }
NumberAnimation {
id: typeAnimLabel
target: root
property: "_typedLabel"
duration: 200
easing.type: Easing.Linear
}
NumberAnimation {
id: typeAnimValue
target: root
property: "_typedValue"
duration: 200
easing.type: Easing.Linear
}
NumberAnimation {
id: typeAnimIcon
target: root
property: "_typedIcon"
duration: 50
easing.type: Easing.Linear
}
} }
function fetchPrice() { function fetchPrice() {
@@ -291,9 +340,26 @@ ModuleChip {
onLocalRefreshSecChanged: refreshTimer.restart() onLocalRefreshSecChanged: refreshTimer.restart()
onLocalRotateSecChanged: rotateTimer.restart() onLocalRotateSecChanged: rotateTimer.restart()
Text {
id: cryptoIcon
visible: root.localShowIcon
text: "󰿤"
color: t.cryptoIcon
font.pixelSize: 14
anchors {
left: parent.left
leftMargin: 12
verticalCenter: parent.verticalCenter
}
}
RowLayout { RowLayout {
id: chipRow id: chipRow
anchors.centerIn: parent anchors {
left: cryptoIcon.visible ? cryptoIcon.right : parent.left
leftMargin: cryptoIcon.visible ? 7 : 12
verticalCenter: parent.verticalCenter
}
spacing: 0 spacing: 0
SequentialAnimation on opacity { SequentialAnimation on opacity {
@@ -310,35 +376,65 @@ ModuleChip {
} }
} }
Text { Item {
visible: root.localShowIcon implicitWidth: labelSizer.implicitWidth
text: "󰿤" implicitHeight: labelSizer.implicitHeight
color: t.cryptoIcon
font.pixelSize: 14 Text {
Layout.alignment: Qt.AlignVCenter id: labelSizer
Layout.rightMargin: 7 text: root.coinSymbol + "/" + root.displayCurrency.toUpperCase() + ": "
color: "transparent"
font.pixelSize: 12
font.bold: true
verticalAlignment: Text.AlignVCenter
}
Text {
text: root._typing
? (root.coinSymbol + "/" + root.displayCurrency.toUpperCase() + ": ").substring(0, root._typedLabel)
: root.coinSymbol + "/" + root.displayCurrency.toUpperCase() + ": "
color: t.cryptoLabel
font.pixelSize: 12
font.bold: true
verticalAlignment: Text.AlignVCenter
anchors.fill: labelSizer
}
}
Item {
implicitWidth: valueSizer.implicitWidth
implicitHeight: valueSizer.implicitHeight
Text {
id: valueSizer
text: root.hasError ? "err" : root.price < 0 ? "…" : root.compactPrice(root.price)
color: "transparent"
font.pixelSize: 13
font.bold: true
verticalAlignment: Text.AlignVCenter
}
Text {
text: root._typing
? (root.hasError ? "err" : root.price < 0 ? "…" : root.compactPrice(root.price)).substring(0, root._typedValue)
: root.hasError ? "err" : root.price < 0 ? "…" : root.compactPrice(root.price)
color: t.cryptoValue
font.pixelSize: 13
font.bold: true
verticalAlignment: Text.AlignVCenter
anchors.fill: valueSizer
}
} }
Text { Text {
text: root.coinSymbol + "/" + root.displayCurrency.toUpperCase() + ": " visible: root._typing || root.price >= 0
color: t.cryptoLabel text: root._typing
font.pixelSize: 12 ? (root.price >= 0 ? (root.change24h >= 0 ? "▲" : "▼") : "").substring(0, root._typedIcon)
verticalAlignment: Text.AlignVCenter : (root.price >= 0 ? (root.change24h >= 0 ? "▲" : "▼") : "")
}
Text {
text: root.hasError ? "err" : root.price < 0 ? "…" : root.compactPrice(root.price)
color: t.cryptoValue
font.pixelSize: 13
font.bold: true
verticalAlignment: Text.AlignVCenter
}
Text {
visible: root.price >= 0
text: root.change24h >= 0 ? "▲" : "▼"
color: root.change24h >= 0 ? (t.cryptoUp) : (t.cryptoDown) color: root.change24h >= 0 ? (t.cryptoUp) : (t.cryptoDown)
font.pixelSize: 9 font.pixelSize: 9
font.bold: true
renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: 4 Layout.leftMargin: 4
@@ -495,6 +591,7 @@ ModuleChip {
color: root.change24h >= 0 ? (t.cryptoUp) : (t.cryptoDown) color: root.change24h >= 0 ? (t.cryptoUp) : (t.cryptoDown)
font.pixelSize: 11 font.pixelSize: 11
font.bold: true font.bold: true
renderType: Text.NativeRendering
} }
} }
} }
@@ -516,7 +613,7 @@ ModuleChip {
property string value: "" property string value: ""
Layout.fillWidth: true Layout.fillWidth: true
Text { text: label; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true } Text { text: label; color: t.cryptoPopupDim; font.pixelSize: 12; Layout.fillWidth: true }
Text { text: value; color: t.cryptoPopupText; font.pixelSize: 12; font.bold: true; font.family: "monospace" } Text { text: value; color: t.cryptoPopupText; font.pixelSize: 12; font.bold: true; font.family: "monospace"; renderType: Text.NativeRendering }
} }
StatRow { label: "Rank"; value: root.rank > 0 ? "#" + root.rank : "—" } StatRow { label: "Rank"; value: root.rank > 0 ? "#" + root.rank : "—" }
@@ -552,6 +649,7 @@ ModuleChip {
text: "24h Range" text: "24h Range"
color: t.cryptoPopupDim color: t.cryptoPopupDim
font.pixelSize: 12 font.pixelSize: 12
renderType: Text.NativeRendering
Layout.fillWidth: true Layout.fillWidth: true
} }
Text { Text {
@@ -559,6 +657,7 @@ ModuleChip {
text: ((root.price - root.low24h) / (root.high24h - root.low24h) * 100).toFixed(1) + "% of range" text: ((root.price - root.low24h) / (root.high24h - root.low24h) * 100).toFixed(1) + "% of range"
color: t.cryptoPopupDim color: t.cryptoPopupDim
font.pixelSize: 11 font.pixelSize: 11
renderType: Text.NativeRendering
} }
} }
@@ -595,6 +694,7 @@ ModuleChip {
color: t.cryptoDown color: t.cryptoDown
font.pixelSize: 10 font.pixelSize: 10
font.family: "monospace" font.family: "monospace"
renderType: Text.NativeRendering
} }
Item { Layout.fillWidth: true } Item { Layout.fillWidth: true }
Text { Text {
@@ -602,6 +702,7 @@ ModuleChip {
color: t.cryptoUp color: t.cryptoUp
font.pixelSize: 10 font.pixelSize: 10
font.family: "monospace" font.family: "monospace"
renderType: Text.NativeRendering
} }
} }
} }

View File

@@ -46,7 +46,7 @@ ModuleChip {
signal dismissed(string toastId) signal dismissed(string toastId)
width: parent ? parent.width : 350 width: parent ? parent.width : 400
height: toastCard.height height: toastCard.height
property real progressVal: 1.0 property real progressVal: 1.0
@@ -65,12 +65,12 @@ ModuleChip {
NumberAnimation { NumberAnimation {
target: slideTranslate; property: "x" target: slideTranslate; property: "x"
from: toastRoot.slideX; to: 0 from: toastRoot.slideX; to: 0
duration: 320; easing.type: Easing.OutCubic duration: 380; easing.type: Easing.OutCubic
} }
NumberAnimation { NumberAnimation {
target: bubbleScale; property: "yScale" target: bubbleScale; property: "yScale"
from: 0; to: 1 from: 0; to: 1
duration: 280; easing.type: Easing.OutBack duration: 320; easing.type: Easing.OutBack
} }
} }
@@ -112,7 +112,7 @@ ModuleChip {
Rectangle { Rectangle {
id: toastCard id: toastCard
width: parent.width width: parent.width
height: toastContent.implicitHeight + (toastRoot.urgency === NotificationUrgency.Low ? 30 : 24) height: toastContent.implicitHeight + (toastRoot.urgency === NotificationUrgency.Low ? 31 : 25)
radius: 16 radius: 16
color: cardHover.hovered ? toastRoot.t.notifToastBgHover : toastRoot.t.notifToastBg color: cardHover.hovered ? toastRoot.t.notifToastBgHover : toastRoot.t.notifToastBg
@@ -121,19 +121,46 @@ ModuleChip {
: (cardHover.hovered ? toastRoot.t.notifBorderActive : toastRoot.t.notifToastBorder) : (cardHover.hovered ? toastRoot.t.notifBorderActive : toastRoot.t.notifToastBorder)
border.width: Cfg.Config.popupBorderWidth border.width: Cfg.Config.popupBorderWidth
Behavior on color { ColorAnimation { duration: 150; easing.type: Easing.OutCubic } } Behavior on color { ColorAnimation { duration: 180; easing.type: Easing.OutCubic } }
Behavior on border.color { ColorAnimation { duration: 150 } } Behavior on border.color { ColorAnimation { duration: 180 } }
// Subtle outer glow for critical notifications
Rectangle {
visible: toastRoot.urgency === NotificationUrgency.Critical
anchors.fill: parent
anchors.margins: -3
radius: parent.radius + 3
color: "transparent"
border.color: Qt.rgba(toastRoot.t.notifUrgencyCritical.r, toastRoot.t.notifUrgencyCritical.g, toastRoot.t.notifUrgencyCritical.b, 0.22)
border.width: 2
z: -1
}
HoverHandler { id: cardHover } HoverHandler { id: cardHover }
TapHandler { onTapped: toastRoot.triggerDismiss() } TapHandler { onTapped: toastRoot.triggerDismiss() }
// Left accent bar — wider with a soft glow backing
Rectangle {
id: accentGlow
width: 8
height: Math.max(18, toastCard.height - 25)
radius: 4
anchors {
left: parent.left
leftMargin: 7
verticalCenter: parent.verticalCenter
}
color: Qt.rgba(toastRoot.urgencyColor(toastRoot.urgency).r,
toastRoot.urgencyColor(toastRoot.urgency).g,
toastRoot.urgencyColor(toastRoot.urgency).b, 0.18)
}
Rectangle { Rectangle {
width: 4 width: 4
height: Math.max(16, toastCard.height - 24) height: Math.max(18, toastCard.height - 25)
radius: 2 radius: 2
anchors { anchors {
left: parent.left left: parent.left
leftMargin: 10 leftMargin: 9
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
} }
color: toastRoot.urgencyColor(toastRoot.urgency) color: toastRoot.urgencyColor(toastRoot.urgency)
@@ -145,20 +172,20 @@ ModuleChip {
left: parent.left left: parent.left
right: parent.right right: parent.right
top: parent.top top: parent.top
leftMargin: 24 leftMargin: 25
rightMargin: 12 rightMargin: 13
topMargin: 12 topMargin: 13
} }
spacing: 4 spacing: 5
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: 6 spacing: 7
Text { Text {
text: toastRoot.urgencyIcon(toastRoot.urgency) text: toastRoot.urgencyIcon(toastRoot.urgency)
color: toastRoot.urgencyColor(toastRoot.urgency) color: toastRoot.urgencyColor(toastRoot.urgency)
font.pixelSize: 12 font.pixelSize: 11
font.bold: true font.bold: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
renderType: Text.NativeRendering renderType: Text.NativeRendering
@@ -166,10 +193,10 @@ ModuleChip {
Text { Text {
text: toastRoot.appName text: toastRoot.appName
color: toastRoot.t.notifToastAppName color: toastRoot.t.notifToastAppName
font.pixelSize: 12 font.pixelSize: 10
font.bold: true font.bold: true
font.capitalization: Font.AllUppercase font.capitalization: Font.AllUppercase
font.letterSpacing: 0.4 font.letterSpacing: 0.8
Layout.fillWidth: true Layout.fillWidth: true
elide: Text.ElideRight elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
@@ -178,17 +205,18 @@ ModuleChip {
Text { Text {
text: toastRoot.timeStr text: toastRoot.timeStr
color: toastRoot.t.notifToastDim color: toastRoot.t.notifToastDim
font.pixelSize: 11 font.pixelSize: 10
font.bold: true
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
Rectangle { Rectangle {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
width: 20; height: 20; radius: 8 width: 18; height: 18; radius: 10
color: closeHover.hovered ? toastRoot.t.notifHistoryHover : "transparent" color: closeHover.hovered
Behavior on color { ColorAnimation { duration: 100 } } ? Qt.rgba(1, 1, 1, 0.1)
: "transparent"
Behavior on color { ColorAnimation { duration: 120 } }
Text { Text {
anchors.centerIn: parent anchors.centerIn: parent
@@ -218,16 +246,15 @@ ModuleChip {
Text { Text {
text: toastRoot.body text: toastRoot.body
color: toastRoot.t.notifToastDim color: toastRoot.t.notifToastDim
font.pixelSize: 12 font.pixelSize: 11
font.bold: true
Layout.fillWidth: true Layout.fillWidth: true
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
maximumLineCount: 3 maximumLineCount: 3
elide: Text.ElideRight elide: Text.ElideRight
textFormat: Text.PlainText textFormat: Text.PlainText
visible: toastRoot.body !== "" visible: toastRoot.body !== ""
Layout.bottomMargin: toastRoot.urgency === NotificationUrgency.Low ? 6 : 0 Layout.bottomMargin: toastRoot.urgency === NotificationUrgency.Low ? 6 : 0
lineHeight: 1.2 lineHeight: 1.35
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
} }
@@ -236,9 +263,9 @@ ModuleChip {
visible: toastRoot.urgency === NotificationUrgency.Low && toastRoot.timeout > 0 visible: toastRoot.urgency === NotificationUrgency.Low && toastRoot.timeout > 0
anchors { anchors {
left: parent.left; right: parent.right; bottom: parent.bottom left: parent.left; right: parent.right; bottom: parent.bottom
margins: 10; bottomMargin: 10 margins: 13; bottomMargin: 10
} }
height: 4 height: 2
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
@@ -250,6 +277,7 @@ ModuleChip {
height: parent.height height: parent.height
radius: 2 radius: 2
color: toastRoot.t.notifProgressFill color: toastRoot.t.notifProgressFill
Behavior on width { NumberAnimation { duration: 80; easing.type: Easing.Linear } }
} }
} }
} }
@@ -271,7 +299,7 @@ ModuleChip {
signal dismissed(int itemIndex) signal dismissed(int itemIndex)
height: histItemContent.implicitHeight + 16 height: histItemContent.implicitHeight + 18
radius: 10 radius: 10
clip: true clip: true
color: histItemHover.hovered ? histRoot.t.notifHistoryHover : "transparent" color: histItemHover.hovered ? histRoot.t.notifHistoryHover : "transparent"
@@ -282,25 +310,35 @@ ModuleChip {
SequentialAnimation { SequentialAnimation {
id: dismissAnim id: dismissAnim
ParallelAnimation { ParallelAnimation {
NumberAnimation { target: histRoot; property: "opacity"; to: 0; duration: 150; easing.type: Easing.OutCubic } NumberAnimation { target: histRoot; property: "opacity"; to: 0; duration: 180; easing.type: Easing.OutCubic }
NumberAnimation { target: histRoot; property: "scale"; to: 0.95; duration: 150; easing.type: Easing.OutCubic } NumberAnimation { target: histRoot; property: "scale"; to: 0.94; duration: 180; easing.type: Easing.OutCubic }
} }
NumberAnimation { target: histRoot; property: "height"; to: 0; duration: 150; easing.type: Easing.InOutQuad } NumberAnimation { target: histRoot; property: "height"; to: 0; duration: 160; easing.type: Easing.InOutQuad }
ScriptAction { script: histRoot.dismissed(histRoot.itemIndex) } ScriptAction { script: histRoot.dismissed(histRoot.itemIndex) }
} }
// Glow backing behind accent bar
Rectangle {
width: 7
height: Math.max(13, histRoot.height - 16)
radius: 3
anchors { left: parent.left; leftMargin: 6; verticalCenter: parent.verticalCenter }
color: Qt.rgba(histRoot.urgencyColor(histRoot.urgency).r,
histRoot.urgencyColor(histRoot.urgency).g,
histRoot.urgencyColor(histRoot.urgency).b, 0.15)
}
Rectangle { Rectangle {
width: 3 width: 3
height: Math.max(10, histRoot.height - 16) height: Math.max(13, histRoot.height - 16)
radius: 1.5 radius: 2
anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter } anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter }
color: histRoot.urgencyColor(histRoot.urgency) color: histRoot.urgencyColor(histRoot.urgency)
} }
Rectangle { Rectangle {
anchors { right: parent.right; top: parent.top; margins: 6 } anchors { right: parent.right; top: parent.top; margins: 6 }
width: 18; height: 18; radius: 8 width: 18; height: 18; radius: 9
color: histCloseHover.hovered ? histRoot.t.notifHistoryHover : "transparent" color: histCloseHover.hovered ? Qt.rgba(1, 1, 1, 0.1) : "transparent"
opacity: histItemHover.hovered ? 1 : 0 opacity: histItemHover.hovered ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 150 } } Behavior on opacity { NumberAnimation { duration: 150 } }
Behavior on color { ColorAnimation { duration: 150 } } Behavior on color { ColorAnimation { duration: 150 } }
@@ -311,40 +349,39 @@ ModuleChip {
} }
Text { Text {
anchors { right: parent.right; rightMargin: 6; top: parent.top; topMargin: 8 } anchors { right: parent.right; rightMargin: 8; top: parent.top; topMargin: 8 }
text: histRoot.timeStr text: histRoot.timeStr
color: histRoot.t.notifToastDim color: histRoot.t.notifToastDim
font.pixelSize: 10 font.pixelSize: 10
font.bold: true
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering renderType: Text.NativeRendering
opacity: histItemHover.hovered ? 0 : 1 opacity: histItemHover.hovered ? 0 : 0.8
Behavior on opacity { NumberAnimation { duration: 150 } } Behavior on opacity { NumberAnimation { duration: 150 } }
} }
ColumnLayout { ColumnLayout {
id: histItemContent id: histItemContent
anchors { left: parent.left; right: parent.right; top: parent.top; leftMargin: 20; rightMargin: 40; topMargin: 8 } anchors { left: parent.left; right: parent.right; top: parent.top; leftMargin: 21; rightMargin: 39; topMargin: 8 }
spacing: 2 spacing: 2
RowLayout { RowLayout {
Layout.fillWidth: true; spacing: 5 Layout.fillWidth: true; spacing: 5
Text { text: histRoot.urgencyIcon(histRoot.urgency); color: histRoot.urgencyColor(histRoot.urgency); font.pixelSize: 10; font.bold: true; Layout.alignment: Qt.AlignVCenter; renderType: Text.NativeRendering } Text { text: histRoot.urgencyIcon(histRoot.urgency); color: histRoot.urgencyColor(histRoot.urgency); font.pixelSize: 10; font.bold: true; Layout.alignment: Qt.AlignVCenter; renderType: Text.NativeRendering }
Text { Text {
text: histRoot.appName; color: histRoot.t.notifToastAppName; font.pixelSize: 11; font.bold: true text: histRoot.appName; color: histRoot.t.notifToastAppName; font.pixelSize: 10; font.bold: true
font.capitalization: Font.AllUppercase; font.letterSpacing: 0.4; Layout.fillWidth: true; elide: Text.ElideRight; verticalAlignment: Text.AlignVCenter font.capitalization: Font.AllUppercase; font.letterSpacing: 0.6; Layout.fillWidth: true; elide: Text.ElideRight; verticalAlignment: Text.AlignVCenter
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
} }
Text { Text {
text: histRoot.summary; color: histRoot.t.notifToastText; font.pixelSize: 12; font.bold: true text: histRoot.summary; color: histRoot.t.notifToastText; font.pixelSize: 13; font.bold: true
Layout.fillWidth: true; elide: Text.ElideRight; textFormat: Text.PlainText; visible: histRoot.summary !== "" Layout.fillWidth: true; elide: Text.ElideRight; textFormat: Text.PlainText; visible: histRoot.summary !== ""
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
Text { Text {
text: histRoot.body; color: histRoot.t.notifToastDim; font.pixelSize: 11; font.bold: true; Layout.fillWidth: true text: histRoot.body; color: histRoot.t.notifToastDim; font.pixelSize: 10; Layout.fillWidth: true
wrapMode: Text.WordWrap; maximumLineCount: 2; elide: Text.ElideRight; textFormat: Text.PlainText; visible: histRoot.body !== ""; lineHeight: 1.2 wrapMode: Text.WordWrap; maximumLineCount: 2; elide: Text.ElideRight; textFormat: Text.PlainText; visible: histRoot.body !== ""; lineHeight: 1.3
renderType: Text.NativeRendering renderType: Text.NativeRendering
} }
} }
@@ -395,9 +432,9 @@ ModuleChip {
visible: root.unreadCount > 0 visible: root.unreadCount > 0
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
width: Math.max(14, badgeLabel.implicitWidth + 6) width: Math.max(16, badgeLabel.implicitWidth + 8)
height: 14 height: 16
radius: 7 radius: 8
color: t.notifBadgeBg color: t.notifBadgeBg
Behavior on width { NumberAnimation { duration: 150; easing.type: Easing.OutCubic } } Behavior on width { NumberAnimation { duration: 150; easing.type: Easing.OutCubic } }
@@ -495,7 +532,7 @@ ModuleChip {
readonly property bool atBottom: pos === "bottomleft" || pos === "bottomright" readonly property bool atBottom: pos === "bottomleft" || pos === "bottomright"
anchors { top: true; bottom: true; right: atRight; left: !atRight } anchors { top: true; bottom: true; right: atRight; left: !atRight }
implicitWidth: 350 + root.barMargin + toastPad implicitWidth: 344 + root.barMargin + toastPad
WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "main-shell-notifications-toasts" WlrLayershell.namespace: "main-shell-notifications-toasts"
@@ -505,15 +542,15 @@ ModuleChip {
mask: Region { item: toastCol } mask: Region { item: toastCol }
readonly property bool shareEdge: (root.isTop && !atBottom) || (!root.isTop && atBottom) readonly property bool shareEdge: (root.isTop && !atBottom) || (!root.isTop && atBottom)
readonly property int edgeGap: shareEdge ? root.barMargin + root.barHeight + 10 : root.barMargin + 10 readonly property int edgeGap: shareEdge ? root.barMargin + root.barHeight + root.barEdgePad + 10 : root.barMargin + 10
readonly property int toastPad: root.barMargin + Cfg.Config.frameBorderWidth + Cfg.Config.notifToastEdgePad readonly property int toastPad: root.barMargin + Cfg.Config.frameBorderWidth + Cfg.Config.notifToastEdgePad
Column { Column {
id: toastCol id: toastCol
x: toastLayer.atRight ? root.barMargin : toastLayer.toastPad x: toastLayer.atRight ? root.barMargin : toastLayer.toastPad
y: !toastLayer.atBottom ? toastLayer.edgeGap : parent.height - toastLayer.edgeGap - toastCol.height y: !toastLayer.atBottom ? toastLayer.edgeGap : parent.height - toastLayer.edgeGap - toastCol.height
spacing: 8 spacing: 10
width: 350 width: 332
Repeater { Repeater {
model: activeToasts model: activeToasts
@@ -566,7 +603,7 @@ ModuleChip {
Item { Item {
id: histClipContainer id: histClipContainer
readonly property int cardW: 340 readonly property int cardW: 352
readonly property int screenPad: root.barMargin + 10 readonly property int screenPad: root.barMargin + 10
x: { x: {
@@ -577,9 +614,9 @@ ModuleChip {
anchors.top: root.isTop ? parent.top : undefined anchors.top: root.isTop ? parent.top : undefined
anchors.bottom: root.isTop ? undefined : parent.bottom anchors.bottom: root.isTop ? undefined : parent.bottom
anchors.topMargin: root.isTop ? (root.barHeight + 10) : 0 anchors.topMargin: root.isTop ? (root.barHeight + root.barEdgePad + 12) : 0
anchors.bottomMargin: root.isTop ? 0 : (root.barHeight + 10) anchors.bottomMargin: root.isTop ? 0 : (root.barHeight + root.barEdgePad + 12)
height: parent.height - root.barHeight - 10 height: parent.height - root.barHeight - root.barEdgePad - 12
clip: true clip: true
@@ -588,7 +625,7 @@ ModuleChip {
popupOpen: historyPopup.popupOpen popupOpen: historyPopup.popupOpen
isTop: root.isTop isTop: root.isTop
animEnabled: historyPopup.visible animEnabled: historyPopup.visible
height: Math.min(histHeader.implicitHeight + 56 + (notifHistory.count > 0 ? histCol.implicitHeight : 90), 520) height: Math.min(histHeader.implicitHeight + 58 + (notifHistory.count > 0 ? histCol.implicitHeight : 94), 480)
color: t.notifHistoryBg color: t.notifHistoryBg
radius: Cfg.Config.popupRadius radius: Cfg.Config.popupRadius
@@ -598,25 +635,27 @@ ModuleChip {
RowLayout { RowLayout {
id: histHeader id: histHeader
anchors { left: parent.left; right: parent.right; top: parent.top } anchors { left: parent.left; right: parent.right; top: parent.top }
anchors.topMargin: 20; anchors.leftMargin: 20; anchors.rightMargin: 20 anchors.topMargin: 16; anchors.leftMargin: 16; anchors.rightMargin: 16
spacing: 10 spacing: 10
Text { text: "󰂚"; color: t.notifToastAppName; font.pixelSize: 18; font.bold: true; Layout.alignment: Qt.AlignVCenter; renderType: Text.NativeRendering } Text { text: "󰂚"; color: t.notifToastAppName; font.pixelSize: 18; font.bold: true; Layout.alignment: Qt.AlignVCenter; renderType: Text.NativeRendering }
Text { Text {
text: "Notifications"; color: t.notifToastAppName; font.pixelSize: 15; font.bold: true text: "Notifications"; color: t.notifToastAppName; font.pixelSize: 14; font.bold: true
Layout.fillWidth: true; Layout.alignment: Qt.AlignVCenter; renderType: Text.NativeRendering Layout.fillWidth: true; Layout.alignment: Qt.AlignVCenter; renderType: Text.NativeRendering
} }
Rectangle { Rectangle {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
width: dndRow.implicitWidth + 16 width: dndRow.implicitWidth + 19
height: 24 height: 25
radius: 8 radius: 13
color: root.doNotDisturb color: root.doNotDisturb
? Qt.rgba(t.notifDnd.r, t.notifDnd.g, t.notifDnd.b, 0.18) ? Qt.rgba(t.notifDnd.r, t.notifDnd.g, t.notifDnd.b, 0.18)
: (dndHover.hovered ? t.notifHistoryHover : "transparent") : (dndHover.hovered ? t.notifHistoryHover : "transparent")
border.color: root.doNotDisturb ? t.notifDnd : "transparent" border.color: root.doNotDisturb
border.width: Cfg.Config.popupBorderWidth ? Qt.rgba(t.notifDnd.r, t.notifDnd.g, t.notifDnd.b, 0.55)
: Qt.rgba(1, 1, 1, 0.08)
border.width: 1
Behavior on color { ColorAnimation { duration: 150 } } Behavior on color { ColorAnimation { duration: 150 } }
Behavior on border.color { ColorAnimation { duration: 150 } } Behavior on border.color { ColorAnimation { duration: 150 } }
@@ -627,7 +666,7 @@ ModuleChip {
Text { Text {
text: "󰂛" text: "󰂛"
color: root.doNotDisturb ? t.notifDnd : t.notifToastDim color: root.doNotDisturb ? t.notifDnd : t.notifToastDim
font.pixelSize: 12 font.pixelSize: 11
font.bold: true font.bold: true
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
Behavior on color { ColorAnimation { duration: 150 } } Behavior on color { ColorAnimation { duration: 150 } }
@@ -636,7 +675,7 @@ ModuleChip {
Text { Text {
text: root.doNotDisturb ? "On" : "Off" text: root.doNotDisturb ? "On" : "Off"
color: root.doNotDisturb ? t.notifDnd : t.notifToastDim color: root.doNotDisturb ? t.notifDnd : t.notifToastDim
font.pixelSize: 11 font.pixelSize: 10
font.bold: true font.bold: true
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
Behavior on color { ColorAnimation { duration: 150 } } Behavior on color { ColorAnimation { duration: 150 } }
@@ -651,13 +690,15 @@ ModuleChip {
Rectangle { Rectangle {
visible: notifHistory.count > 0 visible: notifHistory.count > 0
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
width: clearText.implicitWidth + 16 width: clearText.implicitWidth + 19
height: 24 height: 25
radius: 8 radius: 13
color: clearHover.hovered ? t.notifHistoryHover : "transparent" color: clearHover.hovered ? t.notifHistoryHover : "transparent"
border.color: Qt.rgba(1, 1, 1, 0.08)
border.width: 1
Behavior on color { ColorAnimation { duration: 150 } } Behavior on color { ColorAnimation { duration: 150 } }
Text { id: clearText; anchors.centerIn: parent; text: "Clear all"; color: t.notifToastDim; font.pixelSize: 11; font.bold: true; renderType: Text.NativeRendering } Text { id: clearText; anchors.centerIn: parent; text: "Clear all"; color: t.notifToastDim; font.pixelSize: 10; font.bold: true; renderType: Text.NativeRendering }
HoverHandler { id: clearHover; cursorShape: Qt.PointingHandCursor } HoverHandler { id: clearHover; cursorShape: Qt.PointingHandCursor }
TapHandler { onTapped: clearAllAnim.start() } TapHandler { onTapped: clearAllAnim.start() }
} }
@@ -666,7 +707,7 @@ ModuleChip {
Rectangle { Rectangle {
id: histDivider id: histDivider
anchors { left: parent.left; right: parent.right; top: histHeader.bottom } anchors { left: parent.left; right: parent.right; top: histHeader.bottom }
anchors.topMargin: 12; height: 1; color: t.notifSeparator anchors.topMargin: 10; height: 1; color: t.notifSeparator; opacity: 0.6
} }
SequentialAnimation { SequentialAnimation {
@@ -674,11 +715,11 @@ ModuleChip {
ParallelAnimation { ParallelAnimation {
NumberAnimation { NumberAnimation {
target: histCol; property: "opacity" target: histCol; property: "opacity"
to: 0; duration: 220; easing.type: Easing.OutCubic to: 0; duration: 240; easing.type: Easing.OutCubic
} }
NumberAnimation { NumberAnimation {
target: clearShift; property: "y" target: clearShift; property: "y"
to: -16; duration: 220; easing.type: Easing.OutCubic to: -20; duration: 240; easing.type: Easing.OutCubic
} }
} }
ScriptAction { ScriptAction {
@@ -693,7 +734,7 @@ ModuleChip {
Flickable { Flickable {
id: histFlick id: histFlick
anchors { left: parent.left; right: parent.right; top: histDivider.bottom; bottom: parent.bottom } anchors { left: parent.left; right: parent.right; top: histDivider.bottom; bottom: parent.bottom }
anchors.leftMargin: 2; anchors.rightMargin: 8 anchors.leftMargin: 4; anchors.rightMargin: 6
anchors.topMargin: 6; anchors.bottomMargin: 8; clip: true anchors.topMargin: 6; anchors.bottomMargin: 8; clip: true
contentHeight: histCol.implicitHeight contentHeight: histCol.implicitHeight
flickableDirection: Flickable.VerticalFlick flickableDirection: Flickable.VerticalFlick
@@ -703,14 +744,14 @@ ModuleChip {
id: histCol id: histCol
opacity: 1 opacity: 1
transform: Translate { id: clearShift; y: 0 } transform: Translate { id: clearShift; y: 0 }
width: histFlick.width; spacing: 2; topPadding: 4; bottomPadding: 4; leftPadding: 2; rightPadding: 8 width: histFlick.width; spacing: 2; topPadding: 2; bottomPadding: 2; leftPadding: 4; rightPadding: 6
Item { Item {
width: histCol.width - 16; height: 90; visible: notifHistory.count === 0 width: histCol.width - 16; height: 94; visible: notifHistory.count === 0
ColumnLayout { ColumnLayout {
anchors.centerIn: parent; spacing: 8 anchors.centerIn: parent; spacing: 8
Text { text: "󰂚"; color: t.notifHistoryEmpty; font.pixelSize: 30; font.bold: true; Layout.alignment: Qt.AlignHCenter; renderType: Text.NativeRendering } Text { text: "󰂚"; color: t.notifHistoryEmpty; font.pixelSize: 29; font.bold: true; Layout.alignment: Qt.AlignHCenter; renderType: Text.NativeRendering; opacity: 0.5 }
Text { text: "No notifications"; color: t.notifHistoryEmpty; font.pixelSize: 12; font.bold: true; Layout.alignment: Qt.AlignHCenter; renderType: Text.NativeRendering } Text { text: "No notifications"; color: t.notifHistoryEmpty; font.pixelSize: 13; font.bold: true; Layout.alignment: Qt.AlignHCenter; renderType: Text.NativeRendering; opacity: 0.5 }
} }
} }

View File

@@ -367,9 +367,9 @@ ModuleChip {
anchors.top: root.isTop ? parent.top : undefined anchors.top: root.isTop ? parent.top : undefined
anchors.bottom: root.isTop ? undefined : parent.bottom anchors.bottom: root.isTop ? undefined : parent.bottom
anchors.topMargin: root.isTop ? (Cfg.Config.barHeight + 8) : 0 anchors.topMargin: root.isTop ? (Cfg.Config.barHeight + root.barEdgePad + 8) : 0
anchors.bottomMargin: root.isTop ? 0 : (Cfg.Config.barHeight + 8) anchors.bottomMargin: root.isTop ? 0 : (Cfg.Config.barHeight + root.barEdgePad + 8)
height: parent.height - Cfg.Config.barHeight - 8 height: parent.height - Cfg.Config.barHeight - root.barEdgePad - 8
PopupCard { PopupCard {
id: menuCard id: menuCard

View File

@@ -10,6 +10,7 @@ Rectangle {
property var targetScreen: null property var targetScreen: null
property int barHeight: Cfg.Config.barHeight property int barHeight: Cfg.Config.barHeight
property int barMargin: Cfg.Config.margin property int barMargin: Cfg.Config.margin
property int barEdgePad: Cfg.Config.frameVariant === "bar" ? (Cfg.Config.barPosition === "top" ? Cfg.Config.frameBarPadTop : Cfg.Config.frameBarPadBottom) : 0
readonly property var t: Cfg.Config.theme readonly property var t: Cfg.Config.theme
property bool moduleEnabled: true property bool moduleEnabled: true

View File

@@ -21,7 +21,13 @@ PanelWindow {
property bool popupOpen: false property bool popupOpen: false
property real popupCenterX: -1 property real popupCenterX: -1
function _doOpen() { hideTimer.stop(); visible = true; popupOpen = true } function _doOpen() {
hideTimer.stop()
if (chipRoot) {
popupCenterX = chipRoot.mapToItem(null, 0, 0).x + chipRoot.width / 2
}
visible = true; popupOpen = true
}
function open() { function open() {
_doOpen() _doOpen()
} }
@@ -56,9 +62,9 @@ PanelWindow {
anchors.top: chipRoot && chipRoot.isTop ? parent.top : undefined anchors.top: chipRoot && chipRoot.isTop ? parent.top : undefined
anchors.bottom: chipRoot && chipRoot.isTop ? undefined : parent.bottom anchors.bottom: chipRoot && chipRoot.isTop ? undefined : parent.bottom
anchors.topMargin: chipRoot && chipRoot.isTop ? (chipRoot.barHeight + 10) : 0 anchors.topMargin: chipRoot && chipRoot.isTop ? (chipRoot.barHeight + chipRoot.barEdgePad + 10) : 0
anchors.bottomMargin: chipRoot && chipRoot.isTop ? 0 : (chipRoot.barHeight + 10) anchors.bottomMargin: chipRoot && chipRoot.isTop ? 0 : (chipRoot.barHeight + chipRoot.barEdgePad + 10)
height: chipRoot ? parent.height - chipRoot.barHeight - 10 : parent.height height: chipRoot ? parent.height - chipRoot.barHeight - chipRoot.barEdgePad - 10 : parent.height
clip: true clip: true
} }

View File

@@ -6,7 +6,7 @@ import "themes"
QtObject { QtObject {
id: root id: root
readonly property var theme: Tranquil readonly property var theme: Snowy
// ──────────────────────────────────────────────────────────────────────── // ────────────────────────────────────────────────────────────────────────
// Widgets // Widgets
@@ -21,12 +21,19 @@ QtObject {
// ──────────────────────────────────────────────────────────────────────── // ────────────────────────────────────────────────────────────────────────
// BAR // BAR
// ──────────────────────────────────────────────────────────────────────── // ────────────────────────────────────────────────────────────────────────
property string barPosition: "bottom"
property int barHeight: 35
property int margin: 15
property int radius: 20
// ────────────────────────────────────────────────────────────────────────
// FRAME
// ────────────────────────────────────────────────────────────────────────
property string frameVariant: "bar" // "card" or "bar"
property int frameBorderWidth: 3
property int frameBarPadTop: 5 // bar variant: padding from top edge
property int frameBarPadBottom: 5 // bar variant: padding from bottom edge
// ── Position & Dimensions ─────────────────────────────────────────────────
property string barPosition: "bottom"
property int barHeight: 35
property int margin: 15
property int radius: 20
// ── Module Lists ────────────────────────────────────────────────────────── // ── Module Lists ──────────────────────────────────────────────────────────
property var leftModules: ["Logo", "Stats", "Crypto"] property var leftModules: ["Logo", "Stats", "Crypto"]
@@ -91,10 +98,7 @@ QtObject {
property int volumeInputMax: 200 property int volumeInputMax: 200
// ────────────────────────────────────────────────────────────────────────
// FRAME
// ────────────────────────────────────────────────────────────────────────
property int frameBorderWidth: 3
// ──────────────────────────────────────────────────────────────────────── // ────────────────────────────────────────────────────────────────────────
// NOTIFICATIONS // NOTIFICATIONS
@@ -114,8 +118,6 @@ QtObject {
// ──────────────────────────────────────────────────────────────────────── // ────────────────────────────────────────────────────────────────────────
// LAUNCHER // LAUNCHER
// ──────────────────────────────────────────────────────────────────────── // ────────────────────────────────────────────────────────────────────────
property string launcherScript: Quickshell.env("HOME") + "/.config/quickshell/launcher/launcher.sh"
property string launcherCacheDir: "/tmp/qs_launcher"
property bool launcherCloseOnClickOutside: true property bool launcherCloseOnClickOutside: true
property bool launcherSelectFirst: false property bool launcherSelectFirst: false
property bool launcherMipmapIcons: false property bool launcherMipmapIcons: false
@@ -138,7 +140,7 @@ QtObject {
// //
// This list is the *default*; pairs can be added/removed live in the // This list is the *default*; pairs can be added/removed live in the
// Settings popup and those changes are persisted across restarts. // Settings popup and those changes are persisted across restarts.
property var cryptoPairs: [{ coin: "bitcoin", currency: "usd" }, { coin: "ethereum", currency: "eur" }, { coin: "monero", currency: "usd" }, { coin: "bitcoin", currency: "eur" }, { coin: "bitcoin", currency: "brl" }, { coin: "ethereum", currency: "usd" }] property var cryptoPairs: [{ coin: "bitcoin", currency: "usd" }, { coin: "ethereum", currency: "eur" }, { coin: "monero", currency: "usd" }, { coin: "bitcoin", currency: "eur" }, { coin: "bitcoin", currency: "brl" }, { coin: "ethereum", currency: "usd" }, { coin: "zcash", currency: "usd" }]
// ── Compact label decimals ──────────────────────────────────────────────── // ── Compact label decimals ────────────────────────────────────────────────
// 0 → "80k" // 0 → "80k"

View File

@@ -207,6 +207,8 @@ QtObject {
readonly property color launcherPill: "#4481c7c7" readonly property color launcherPill: "#4481c7c7"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22cbdc3d" readonly property color launcherHover: "#22cbdc3d"
readonly property color launcherSelected: "#44cbdc3d" readonly property color launcherSelected: "#44cbdc3d"

View File

@@ -207,6 +207,8 @@ QtObject {
readonly property color launcherPill: "#441e3a5f" readonly property color launcherPill: "#441e3a5f"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#2200d9ff" readonly property color launcherHover: "#2200d9ff"
readonly property color launcherSelected: "#4400d9ff" readonly property color launcherSelected: "#4400d9ff"

View File

@@ -215,6 +215,8 @@ QtObject {
readonly property color launcherPill: "#444a5d6e" readonly property color launcherPill: "#444a5d6e"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#33f2b425" readonly property color launcherHover: "#33f2b425"
readonly property color launcherSelected: "#44c19375" readonly property color launcherSelected: "#44c19375"

View File

@@ -207,6 +207,8 @@ QtObject {
readonly property color launcherPill: "#444a5d6e" readonly property color launcherPill: "#444a5d6e"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22ebc6a0" readonly property color launcherHover: "#22ebc6a0"
readonly property color launcherSelected: "#44ebc6a0" readonly property color launcherSelected: "#44ebc6a0"

View File

@@ -215,6 +215,8 @@ QtObject {
readonly property color launcherPill: "#44614d4a" readonly property color launcherPill: "#44614d4a"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22e0533c" readonly property color launcherHover: "#22e0533c"
readonly property color launcherSelected: "#44e0533c" readonly property color launcherSelected: "#44e0533c"

View File

@@ -207,6 +207,8 @@ QtObject {
readonly property color launcherPill: "#444a566e" readonly property color launcherPill: "#444a566e"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22f0a1ba" readonly property color launcherHover: "#22f0a1ba"
readonly property color launcherSelected: "#44f0a1ba" readonly property color launcherSelected: "#44f0a1ba"

View File

@@ -207,6 +207,8 @@ QtObject {
readonly property color launcherPill: "#443d4a6d" readonly property color launcherPill: "#443d4a6d"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22bdf0ff" readonly property color launcherHover: "#22bdf0ff"
readonly property color launcherSelected: "#44bdf0ff" readonly property color launcherSelected: "#44bdf0ff"

View File

@@ -218,6 +218,8 @@ QtObject {
readonly property color launcherPill: "#44284038" readonly property color launcherPill: "#44284038"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#224a8c5c" readonly property color launcherHover: "#224a8c5c"
readonly property color launcherSelected: "#444a8c5c" readonly property color launcherSelected: "#444a8c5c"

View File

@@ -216,6 +216,8 @@ QtObject {
readonly property color launcherPill: "#444a5d6e" readonly property color launcherPill: "#444a5d6e"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22c19375" readonly property color launcherHover: "#22c19375"
readonly property color launcherSelected: "#44c19375" readonly property color launcherSelected: "#44c19375"

View File

@@ -215,6 +215,8 @@ QtObject {
readonly property color launcherPill: "#442e7d32" readonly property color launcherPill: "#442e7d32"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22ff5722" readonly property color launcherHover: "#22ff5722"
readonly property color launcherSelected: "#44ff5722" readonly property color launcherSelected: "#44ff5722"

View File

@@ -218,6 +218,8 @@ QtObject {
readonly property color launcherPill: "#44203060" readonly property color launcherPill: "#44203060"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22b068d8" readonly property color launcherHover: "#22b068d8"
readonly property color launcherSelected: "#44b068d8" readonly property color launcherSelected: "#44b068d8"

View File

@@ -208,6 +208,8 @@ QtObject {
readonly property color launcherPill: "#44565f89" readonly property color launcherPill: "#44565f89"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22ffb86c" readonly property color launcherHover: "#22ffb86c"
readonly property color launcherSelected: "#44ffb86c" readonly property color launcherSelected: "#44ffb86c"

View File

@@ -207,6 +207,8 @@ QtObject {
readonly property color launcherPill: "#4431748f" readonly property color launcherPill: "#4431748f"
readonly property color launcherText: "#ffe0def4" readonly property color launcherText: "#ffe0def4"
readonly property color launcherDim: "#ff6e6a86" readonly property color launcherDim: "#ff6e6a86"
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: "#ff9ccfd8" readonly property color launcherAccent: "#ff9ccfd8"
readonly property color launcherHover: "#4431748f" readonly property color launcherHover: "#4431748f"
readonly property color launcherSelected: "#6631748f" readonly property color launcherSelected: "#6631748f"

View File

@@ -218,6 +218,8 @@ QtObject {
readonly property color launcherPill: "#444a4068" readonly property color launcherPill: "#444a4068"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#224ec0b8" readonly property color launcherHover: "#224ec0b8"
readonly property color launcherSelected: "#444ec0b8" readonly property color launcherSelected: "#444ec0b8"

View File

@@ -17,5 +17,7 @@ singleton Autumn 1.0 autumn.qml
singleton Pinkie 1.0 pinkie.qml singleton Pinkie 1.0 pinkie.qml
singleton Lowlight 1.0 lowlight.qml singleton Lowlight 1.0 lowlight.qml
singleton Tranquil 1.0 tranquil.qml singleton Tranquil 1.0 tranquil.qml
singleton Snowy 1.0 snowy.qml

369
config/themes/snowy.qml Normal file
View File

@@ -0,0 +1,369 @@
pragma Singleton
import QtQuick
import Quickshell
QtObject {
id: theme
// ── Wallpaper ──────────────────────────────────────────────────────────────
readonly property string wallpaper: Quickshell.env("HOME") + "/.config/quickshell/wallpapers/snowy.jpg"
// ── Base Backgrounds ───────────────────────────────────────────────────────
readonly property color bg: "#cc0f1120" // Deep mountain shadow night
readonly property color bgPanel: "transparent"
readonly property color bgPopup: "#cc0f1120" // Deep slate valley dark
readonly property color bgFrame: bg
// ── Separators ────────────────────────────────────────────────────────────
readonly property color separator: "#334a5270" // Cool blue-grey ridge line
// ── Text ──────────────────────────────────────────────────────────────────
readonly property color textMain: "#ffe8eaf0" // Snow highlight white
readonly property color textDim: "#996a7090" // Hazy blue-grey mist
// ── Accent & Borders ──────────────────────────────────────────────────────
readonly property color accent: "#ffc4889e" // Alpenglow rose-mauve
readonly property color border: "transparent"
readonly property color frameBorder: "transparent"
readonly property color borderPopup: "transparent"
// ── Logo Module ────────────────────────────────────────────────────────
readonly property color logoBg: bgPanel
readonly property color logoBgHover: "#22ffffff"
readonly property color logoBorder: border
readonly property color logoBorderActive: accent
readonly property color logoIcon: textMain
readonly property color logoIconActive: accent
// ── Mpris Module ──────────────────────────────────────────────────────────
readonly property color mprisAccent: accent
readonly property color mprisTextMain: textMain
readonly property color mprisTextDim: textDim
readonly property color mprisTrackColor: statsTrackColor
readonly property color mprisButtonText: bgPopup
readonly property color mprisAlbumBg: Qt.alpha(accent, 0.08)
readonly property color mprisAlbumBorder: Qt.alpha(accent, 0.15)
readonly property color mprisBtnBg: Qt.alpha(accent, 0.10)
readonly property color mprisBtnBgHover: Qt.alpha(accent, 0.22)
readonly property color mprisBtnBorder: Qt.alpha(accent, 0.20)
readonly property color mprisBtnBorderHover: Qt.alpha(accent, 0.45)
readonly property color mprisBtnIcon: accent
readonly property color mprisBtnIconHover: Qt.lighter(accent, 1.3)
// ── Stats Module (Variation: Alpine Pulse) ────────────────────────────────
readonly property color statsBg: bgPanel
readonly property color statsBorder: border
readonly property color statsCpuColor: "#ffc4845a" // Sunlit amber rock face
readonly property color statsMemColor: "#ff8ab4d4" // Glacial sky blue
readonly property color statsDiskColor: "#ff94c4b8" // Frozen teal snowmelt
readonly property color statsTrackColor: "#15ffffff"
readonly property color statsCpuTempColor: "#ffcb6080" // Deep alpenglow crimson
readonly property color statsGpuColor: "#ffb09ad4" // Twilight lavender peak
// ── SysInfo Module ────────────────────────────────────────────────────────
readonly property color sysInfoAccent: accent
readonly property color sysInfoTextMain: textMain
readonly property color sysInfoTextDim: textDim
readonly property color sysInfoCpuColor: statsCpuColor
readonly property color sysInfoMemColor: statsMemColor
readonly property color sysInfoDiskColor: statsDiskColor
readonly property color sysInfoCpuTempColor: statsCpuTempColor
readonly property color sysInfoGpuColor: statsGpuColor
readonly property color sysInfoTrackColor: statsTrackColor
// ── Volume Module (Variation: Frozen Dusk) ────────────────────────────────
readonly property color volBg: bgPanel
readonly property color volBgHover: "#224a5270"
readonly property color volBorder: border
readonly property color volBorderHover: "#ff73d0ff" // Luminous sky blue
readonly property color volPopupBg: bgPopup
readonly property color volPopupBorder: borderPopup
readonly property color volIcon: "#ff73d0ff" // Luminous sky blue
readonly property color volIconMuted: "#ff4a5270" // Deep slate mute
readonly property color volTrack: "#22ffffff"
readonly property color volHandle: accent
readonly property color volHandleBorder: "#33ffffff"
readonly property color volMuteBg: "#33cb6080"
readonly property color volPickerHover: "#15c4889e"
// ── Volume Limit Buttons ────────────────────────────────────────────────
readonly property color volLimitBtn: "transparent"
readonly property color volLimitBtnHover: "#22c4889e"
readonly property color volLimitBtnPress: accent
readonly property color volOutputLimitBtnPress: accent
readonly property color volInputLimitBtnPress: statusInfo
readonly property color volOutputLimitBtnHover: Qt.alpha(accent, 0.08)
readonly property color volInputLimitBtnHover: Qt.alpha(statusInfo, 0.08)
// ── Clock Module ───────────────────────────────────────────────────────────
readonly property color clockBg: bgPanel
readonly property color clockBgHover: "#11ffffff"
readonly property color clockBorder: border
readonly property color clockBorderHover: accent
readonly property color clockTime: textMain
readonly property color clockSeconds: "#ffc4889e" // Alpenglow rose
readonly property color clockIcon: accent
// ── Battery Module ────────────────────────────────────────────────────────
readonly property color batteryFull: accent
readonly property color batteryCharging: accent
readonly property color batteryCritical: statusErr
readonly property color batteryLow: statusWarn
readonly property color batteryIcon: clockIcon
readonly property color batBg: bgPanel
readonly property color batBgHover: "#11ffffff"
readonly property color batBorder: border
readonly property color batBorderHover: accent
readonly property color batText: textMain
readonly property color batPopupBg: bgPopup
readonly property color batPopupBorder: borderPopup
readonly property color batPopupSeparator: separator
readonly property color batPopupHeader: "#ffc4889e" // Alpenglow rose
readonly property color batPopupText: textMain
readonly property color batPopupDim: textDim
readonly property color batProgressTrack: separator
readonly property color batProfileActiveText: bg
// ── Network Module ────────────────────────────────────────────────────────
readonly property color netBg: bgPanel
readonly property color netBgHover: "#11ffffff"
readonly property color netBorder: border
readonly property color netBorderHover: accent
readonly property color netText: textMain
readonly property color netPopupBg: bgPopup
readonly property color netPopupBorder: borderPopup
readonly property color netPopupSeparator: separator
readonly property color netPopupHeader: "#ffc4889e" // Alpenglow rose
readonly property color netPopupText: textMain
readonly property color netPopupDim: textDim
readonly property color netFieldBg: "#22ffffff"
readonly property color netCancelBgHover: "#22ffffff"
readonly property color netConnectText: "#ff0f1120"
readonly property color netApActiveBg: Qt.alpha(accent, 0.15)
readonly property color netApHoverBg: calArrowBgHover
readonly property color netDisconnectBg: Qt.alpha(statusErr, 0.18)
readonly property color netDisconnectBorder: Qt.alpha(statusErr, 0.45)
readonly property color netWiredOkBg: Qt.alpha(statusOk, 0.12)
readonly property color netWiredErrBg: Qt.alpha(statusErr, 0.12)
readonly property color netWiredOkBorder: Qt.alpha(statusOk, 0.4)
readonly property color netWiredErrBorder: Qt.alpha(statusErr, 0.4)
readonly property color netWifiIconOk: "#ff87d97c" // Vibrant meadow green
readonly property color netWifiIconErr: "#ffcb6080" // Alpenglow crimson
readonly property color netEthIconOk: "#ff87d97c" // Vibrant meadow green
readonly property color netEthIconErr: "#ffcb6080"
// ── Calendar Popup ─────────────────────────────────────────────────────────
readonly property color calCardBg: bgPopup
readonly property color calCardBorder: borderPopup
readonly property color calSeparator: separator
readonly property color calTodayBg: accent
readonly property color borderToday: accent
readonly property color todayText: "#ffffffff"
readonly property color clockPopupHeader: "#ffc4889e" // Alpenglow rose
readonly property color clockPopupText: textMain
readonly property color clockPopupDim: textDim
readonly property color clockPopupDate: textMain
readonly property color clockPopupUtc: textDim
readonly property color calArrowIcon: textDim
readonly property color calArrowIconHover: "#ffc4889e" // Alpenglow rose on hover
readonly property color calArrowBg: "transparent"
readonly property color calArrowBgHover: "#22c4889e" // Soft rose tint
readonly property color calArrowBgPress: "#ffc4889e" // Full alpenglow
// ── Weather Module ──────────────────────────────────────────────────────
readonly property color weatherAccent: accent
readonly property color weatherTextMain: textMain
readonly property color weatherTextDim: textDim
readonly property color weatherTempColor: "#ffcb6080" // Alpenglow crimson
readonly property color weatherFeelsColor: "#ffb09ad4" // Twilight lavender
readonly property color weatherHumidColor: "#ff8ab4d4" // Glacial sky blue
readonly property color weatherWindColor: "#ff94c4b8" // Frozen teal
// ── Workspace Module ───────────────────────────────────────────────────────
readonly property color wsPanelBg: bgPanel
readonly property color wsPanelBorder: "transparent"
readonly property color wsActiveBg: accent
readonly property color wsInactiveBg: "#15ffffff"
readonly property color wsHoverBg: "#334a5270"
readonly property color wsActiveText: "#ff0f1120"
readonly property color wsInactiveText: textMain
readonly property color wsHoverText: "#ffffffff"
readonly property color wsMagicActiveBg: "#ff8ab4d4" // Glacial blue magic
readonly property color wsMagicActiveText: wsActiveText
// ── Tray Module ────────────────────────────────────────────────────────────
readonly property color trayBg: bgPanel
readonly property color trayBgHover: "#11ffffff"
readonly property color trayBorder: border
readonly property color trayBorderHover: "#22ffffff"
readonly property color trayIcon: textMain
// ── Tray Context Menu ──────────────────────────────────────────────────────
readonly property color trayMenuBg: bgPopup
readonly property color trayMenuBorder: borderPopup
readonly property color trayMenuText: textMain
readonly property color trayMenuDim: textDim
readonly property color trayMenuHover: "#22c4889e" // Soft alpenglow rose tint
readonly property color trayMenuCheck: accent
readonly property color trayMenuSeparator: separator
// ── Launcher (Variation: Summit Mist) ─────────────────────────────────────
readonly property color launcherBg: bgPopup
readonly property color launcherBorder: borderPopup
readonly property color launcherInput: "#44080a12"
readonly property color launcherInputBorderFocus: accent
readonly property color launcherPill: "#444a5270"
readonly property color launcherText: textMain
readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent
readonly property color launcherHover: "#22c4889e"
readonly property color launcherSelected: "#44c4889e"
readonly property color launcherModeActiveText: "#ffffffff"
readonly property color launcherModeActiveBg: accent
// ── Status Colors ──────────────────────────────────────────────────────────
readonly property color statusOk: "#ff87d97c" // Vibrant meadow green
readonly property color statusWarn: "#ffc4845a" // Sunlit amber rock
readonly property color statusErr: "#ffcb6080" // Alpenglow crimson
readonly property color statusInfo: "#ff73d0ff" // Luminous sky blue
// ── Notifications Module ───────────────────────────────────────────────────
readonly property color notifBg: bgPanel
readonly property color notifBgHover: "#11ffffff"
readonly property color notifBorder: border
readonly property color notifBorderActive: accent
readonly property color notifIcon: textMain
readonly property color notifIconActive: accent
readonly property color notifBadgeBg: statusErr
readonly property color notifBadgeText: "#ffffffff"
readonly property color notifSeparator: separator
readonly property color notifDnd: separator
// ── Toast cards (Variation: Alpenglow) ────────────────────────────────────
readonly property color notifToastBg: bgPopup
readonly property color notifToastBgHover: "#22ffffff"
readonly property color notifToastBorder: borderPopup
readonly property color notifToastText: textMain
readonly property color notifToastDim: textDim
readonly property color notifToastAppName: accent
// ── Urgency colours ────────────────────────────────────────────────────────
readonly property color notifUrgencyCritical: statusErr
readonly property color notifUrgencyNormal: accent
readonly property color notifUrgencyLow: textDim
// ── Progress bar ───────────────────────────────────────────────────────────
readonly property color notifProgressBg: "#22ffffff"
readonly property color notifProgressFill: accent
// ── History popup ──────────────────────────────────────────────────────────
readonly property color notifHistoryBg: bgPopup
readonly property color notifHistoryBorder: borderPopup
readonly property color notifHistoryHover: "#11c4889e"
readonly property color notifHistoryEmpty: textDim
// ── BgDate Module ──────────────────────────────────────────────────────────
readonly property color bgDateText: "#ffffffff" // Pure snow white
readonly property color bgDateShadow: "#88000000" // Deep mountain shadow
readonly property color bgDateSecondsText: bgDateText
// ── Crypto Module ──────────────────────────────────────────────────────────
readonly property color cryptoBg: bgPanel
readonly property color cryptoBgHover: "#15ffffff"
readonly property color cryptoBorder: border
readonly property color cryptoBorderHover: accent
readonly property color cryptoIcon: accent
readonly property color cryptoLabel: textDim
readonly property color cryptoValue: textMain
readonly property color cryptoUp: "#ff87d97c" // ▲ vibrant meadow green
readonly property color cryptoDown: "#ffcb6080" // ▼ alpenglow crimson
// Popup card
readonly property color cryptoPopupBg: bgPopup
readonly property color cryptoPopupBorder: borderPopup
readonly property color cryptoPopupHeader: "#ffc4889e" // Alpenglow rose
readonly property color cryptoPopupText: textMain
readonly property color cryptoPopupDim: textDim
// Tinted surfaces
readonly property color cryptoUpBg: Qt.rgba(cryptoUp.r, cryptoUp.g, cryptoUp.b, 0.13)
readonly property color cryptoDownBg: Qt.rgba(cryptoDown.r, cryptoDown.g, cryptoDown.b, 0.13)
readonly property color cryptoChipRemoveBg: Qt.rgba(cryptoDown.r, cryptoDown.g, cryptoDown.b, 0.27)
readonly property color cryptoApplyIdleBg: Qt.rgba(accent.r, accent.g, accent.b, 0.20)
readonly property color cryptoFieldBg: "#15ffffff"
readonly property color cryptoFieldBgFocus: "#22ffffff"
readonly property color cryptoRangeTrack: "#1affffff"
readonly property color cryptoTextOnAccent: "#ff0f1120"
readonly property color cryptoPlaceholder: Qt.rgba(textDim.r, textDim.g, textDim.b, 0.33)
// ── Polkit Dialog ──────────────────────────────────────────────────────────
// Overlay
readonly property color polkitOverlayBg: "#bb000000" // dim backdrop
// Card chrome
readonly property color polkitCardBg: bgPopup
readonly property color polkitCardBorder: border
// Lock icon
readonly property color polkitIconBg: "#1ec4889e" // translucent rose fill
readonly property color polkitIconBorder: "#44c4889e" // rose ring
readonly property color polkitIconColor: accent // glyph — alpenglow rose
// Text hierarchy
readonly property color polkitTitle: textMain
readonly property color polkitMessage: "#cce8eaf0" // slightly dimmed snow white
// Action-ID pill
readonly property color polkitPillBg: "#1a4a5270" // muted slate tint
readonly property color polkitPillText: "#666a7090" // dim blue-grey label
// Divider
readonly property color polkitDivider: "#334a5270"
// Supplementary message — error state
readonly property color polkitSuppErrBg: "#1acb6080" // translucent crimson fill
readonly property color polkitSuppErrBorder: "#44cb6080" // crimson ring
readonly property color polkitSuppErrText: statusErr
// Supplementary message — info / ok state
readonly property color polkitSuppOkBg: "#1aa8c4a0" // translucent pine fill
readonly property color polkitSuppOkBorder: "#44a8c4a0" // pine ring
readonly property color polkitSuppOkText: statusOk
// Fields
readonly property color polkitFieldBg: "#44080a12" // deep dark fill
readonly property color polkitFieldBorder: "#22ffffff" // inactive border
readonly property color polkitFieldBorderFocus: accent // focused border — alpenglow rose
// Identity selector
readonly property color polkitUserLabel: "#996a7090" // "User:" prefix
readonly property color polkitUserValue: accent
// Input prompt
readonly property color polkitInputPrompt: "#886a7090"
// TextInput
readonly property color polkitInputText: textMain
readonly property color polkitInputSelection: "#55c4889e" // rose selection highlight
readonly property color polkitInputSelectedText: bg
// Eye toggle
readonly property color polkitEyeIcon: "#666a7090"
readonly property color polkitEyeIconHover: accent
// Authenticate button
readonly property color polkitAuthBg: "#ddc4889e" // slightly-muted rose fill
readonly property color polkitAuthBgHover: accent // full alpenglow on hover
readonly property color polkitAuthText: bg
// Cancel button
readonly property color polkitCancelBg: "#0dffffff"
readonly property color polkitCancelBgHover: "#22ffffff"
readonly property color polkitCancelBorder: "#22ffffff"
readonly property color polkitCancelText: "#cce8eaf0"
}

View File

@@ -207,6 +207,8 @@ QtObject {
readonly property color launcherPill: "#44ffb7ce" readonly property color launcherPill: "#44ffb7ce"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22ff7eb9" readonly property color launcherHover: "#22ff7eb9"
readonly property color launcherSelected: "#44ff7eb9" readonly property color launcherSelected: "#44ff7eb9"

View File

@@ -219,6 +219,8 @@ QtObject {
readonly property color launcherPill: "#444a3d6e" readonly property color launcherPill: "#444a3d6e"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: textDim readonly property color launcherDim: textDim
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#22b09de8" readonly property color launcherHover: "#22b09de8"
readonly property color launcherSelected: "#44b09de8" readonly property color launcherSelected: "#44b09de8"

View File

@@ -216,6 +216,8 @@ QtObject {
readonly property color launcherPill: "#444a5d6e" readonly property color launcherPill: "#444a5d6e"
readonly property color launcherText: textMain readonly property color launcherText: textMain
readonly property color launcherDim: "#ff92979b" readonly property color launcherDim: "#ff92979b"
readonly property color launcherStar: launcherDim
readonly property color launcherStarHover: accent
readonly property color launcherAccent: accent readonly property color launcherAccent: accent
readonly property color launcherHover: "#2289b4fa" readonly property color launcherHover: "#2289b4fa"
readonly property color launcherSelected: "#4489b4fa" readonly property color launcherSelected: "#4489b4fa"

View File

@@ -3,8 +3,8 @@ import QtQuick.Layouts
import QtQuick.Controls import QtQuick.Controls
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
import Quickshell.Io
import Quickshell.Hyprland import Quickshell.Hyprland
import Quickshell.Io
import "../config" as Cfg import "../config" as Cfg
import "../components" import "../components"
@@ -13,13 +13,86 @@ PanelWindow {
id: root id: root
property bool isTop: true property bool isTop: true
property int barHeight: Cfg.Config.barHeight readonly property int barEdgePad: Cfg.Config.frameVariant === "bar" ? (isTop ? Cfg.Config.frameBarPadTop : Cfg.Config.frameBarPadBottom) : 0
property int barHeight: Cfg.Config.barHeight + barEdgePad
property int barMargin: Cfg.Config.margin property int barMargin: Cfg.Config.margin
readonly property var t: Cfg.Config.theme readonly property var t: Cfg.Config.theme
readonly property int launcherGap: 12 readonly property int launcherGap: 12
property var allItems: []
property var favoriteIds: []
property var accessCounts: ({})
property bool _loaded: false
readonly property string _statePath: Quickshell.env("HOME") + "/.config/quickshell/launcher/launcher_state.json"
function buildItems() {
const apps = DesktopEntries.applications.values
const items = []
for (let i = 0; i < apps.length; i++) {
const e = apps[i]
items.push({
name: e.name,
exec: e.execString,
id: e.id,
icon: e.icon,
entry: e,
actions: e.actions
})
}
items.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()))
root.allItems = items
}
Component.onCompleted: buildItems()
Connections {
target: DesktopEntries
function onApplicationsChanged() { root.buildItems() }
}
FileView {
id: stateFile
path: root._statePath
printErrors: false
watchChanges: true
onFileChanged: reload()
onAdapterUpdated: writeAdapter()
adapter: JsonAdapter {
id: stateAdapter
property list<string> favorites: []
property var access: ({})
}
onLoaded: {
root.favoriteIds = stateAdapter.favorites
root.accessCounts = stateAdapter.access
root._loaded = true
}
onLoadFailed: {
root._loaded = true
}
}
function toggleFavorite(itemId) {
const arr = root.favoriteIds.slice()
const idx = arr.indexOf(itemId)
if (idx >= 0)
arr.splice(idx, 1)
else
arr.push(itemId)
root.favoriteIds = arr
stateAdapter.favorites = root.favoriteIds
}
function incrementAccess(itemId) {
const counts = Object.assign({}, root.accessCounts)
counts[itemId] = (counts[itemId] || 0) + 1
root.accessCounts = counts
stateAdapter.access = root.accessCounts
}
GlobalShortcut { GlobalShortcut {
id: launcherShortcut id: launcherShortcut
name: "toggle" name: "toggle"
@@ -29,17 +102,67 @@ PanelWindow {
property bool _isOpen: false property bool _isOpen: false
readonly property bool isOpen: _isOpen readonly property bool isOpen: _isOpen
property bool _keyboardNav: false property bool _keyboardNav: false
property var allItems: [] property string _expandingActions: ""
property bool loading: false property string _savedExpandId: ""
property int lastCacheUpdate: 0 property real _savedContentY: 0
property bool _pendingRestore: false
property bool _inRestore: false
property string expandedItemId: ""
readonly property int defaultIndex: Cfg.Config.launcherSelectFirst ? 0 : -1 readonly property int defaultIndex: Cfg.Config.launcherSelectFirst ? 0 : -1
readonly property var filteredItems: { readonly property var filteredItems: {
const q = searchInput.text.toLowerCase() const q = searchInput.text.toLowerCase()
if (!q) return allItems.slice(0, 80) let filtered
return allItems.filter(i => i.name.toLowerCase().includes(q)) if (!q) {
filtered = allItems.slice(0, 80)
} else {
filtered = allItems.filter(i => i.name.toLowerCase().startsWith(q))
}
const favs = filtered.filter(i => root.favoriteIds.includes(i.id))
let rest = filtered.filter(i => !root.favoriteIds.includes(i.id))
rest.sort((a, b) => (root.accessCounts[b.id] || 0) - (root.accessCounts[a.id] || 0))
const result = []
function pushItem(item) {
result.push(Object.assign({}, item, { isHeader: false, isAction: false }))
if (root.expandedItemId && item.id === root.expandedItemId && item.actions && item.actions.length > 0) {
for (let j = 0; j < item.actions.length; j++) {
const a = item.actions[j]
result.push({
isHeader: false,
isAction: true,
name: a.name,
id: item.id + ":" + a.id,
icon: a.icon,
actionObj: a
})
}
}
}
if (favs.length > 0) {
result.push({ isHeader: true, section: "Favorites" })
for (let i = 0; i < favs.length; i++)
pushItem(favs[i])
}
if (rest.length > 0) {
result.push({ isHeader: true, section: "All Applications" })
for (let i = 0; i < rest.length; i++)
pushItem(rest[i])
}
return result
}
function skipHeader(idx, dir) {
while (idx >= 0 && idx < root.filteredItems.length) {
const item = root.filteredItems[idx]
if (item && !item.isHeader) return idx
idx += dir
}
return -1
} }
function toggle() { function toggle() {
@@ -56,14 +179,16 @@ PanelWindow {
closeTimer.stop() closeTimer.stop()
visible = true visible = true
_isOpen = true _isOpen = true
expandedItemId = ""
searchInput.text = "" searchInput.text = ""
resultsList.currentIndex = root.defaultIndex resultsList.currentIndex = root.defaultIndex
loadItems() Qt.callLater(() => resultsList.positionViewAtBeginning())
Qt.callLater(() => searchInput.forceActiveFocus()) Qt.callLater(() => searchInput.forceActiveFocus())
} }
function close() { function close() {
_isOpen = false _isOpen = false
expandedItemId = ""
closeTimer.restart() closeTimer.restart()
} }
@@ -74,76 +199,18 @@ PanelWindow {
} }
} }
function loadItems() {
loading = true
var now = Date.now()
var staleMs = 300000
if (now - lastCacheUpdate < staleMs) {
readCache()
return
}
readCache()
lastCacheUpdate = now
updateProc.command = [Cfg.Config.launcherScript, "--update-only"]
updateProc.running = true
}
function readCache() {
const path = Cfg.Config.launcherCacheDir + "/drun.txt"
dataProc.rawOutput = ""
dataProc.command = ["cat", path]
dataProc.running = true
}
function shellQuote(str) {
return "'" + str.replace(/'/g, "'\\''") + "'"
}
function parseExec(str) {
const args = []
let current = ""
let inSingle = false
let inDouble = false
for (let i = 0; i < str.length; i++) {
const ch = str[i]
if (inSingle) {
if (ch === "'") inSingle = false
else current += ch
} else if (inDouble) {
if (ch === '"') inDouble = false
else current += ch
} else if (ch === "'") {
inSingle = true
} else if (ch === '"') {
inDouble = true
} else if (/\s/.test(ch)) {
if (current.length > 0) {
args.push(current)
current = ""
}
} else {
current += ch
}
}
if (current.length > 0) args.push(current)
return args
}
function launch(item) { function launch(item) {
if (!item || !item.exec) return if (!item || !item.entry) return
item.entry.execute()
console.log("Launching: " + item.name)
root.incrementAccess(item.id)
close()
}
let cleanExec = item.exec.replace(/%[fFuUik]/g, "").trim() function executeAction(item) {
const logPath = "/tmp/qml_launch.log" if (!item || !item.actionObj) return
item.actionObj.execute()
const args = parseExec(cleanExec) console.log("Executing action: " + item.name)
const cmd = args.map(a => shellQuote(a)).join(" ") + " > " + shellQuote(logPath) + " 2>&1 < /dev/null &"
launchProc.command = ["sh", "-c", cmd]
launchProc.running = true
console.log("Launching: " + cleanExec)
close() close()
} }
@@ -162,37 +229,9 @@ PanelWindow {
PopupHideTimer { PopupHideTimer {
id: closeTimer id: closeTimer
onTriggered: { onTriggered: root.visible = false
root.visible = false
root.allItems = []
}
} }
Process {
id: updateProc
onRunningChanged: if (!running) root.readCache()
}
Process {
id: dataProc
property string rawOutput: ""
stdout: SplitParser { onRead: data => dataProc.rawOutput += data + "\n" }
onRunningChanged: {
if (!running && rawOutput) {
const lines = rawOutput.trim().split("\n")
const items = []
for (let i = 0; i < lines.length; i++) {
const p = lines[i].split("\t")
if (p.length >= 3) items.push({ name: p[0], exec: p[1], id: p[2], icon: p[3] || "" })
}
root.allItems = items
root.loading = false
}
}
}
Process { id: launchProc }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
@@ -222,7 +261,7 @@ PanelWindow {
height: targetHeight height: targetHeight
Behavior on height { Behavior on height {
enabled: root._isOpen enabled: root._isOpen
NumberAnimation { duration: 154; easing.type: Easing.OutCubic } NumberAnimation { duration: 80; easing.type: Easing.OutCubic }
} }
radius: Cfg.Config.popupRadius radius: Cfg.Config.popupRadius
@@ -265,32 +304,72 @@ PanelWindow {
verticalAlignment: TextInput.AlignVCenter verticalAlignment: TextInput.AlignVCenter
selectionColor: t.launcherAccent selectionColor: t.launcherAccent
onTextChanged: resultsList.currentIndex = root.defaultIndex onTextChanged: {
resultsList.currentIndex = root.defaultIndex
root.expandedItemId = ""
}
Keys.onReturnPressed: { Keys.onReturnPressed: {
if (root.filteredItems.length > 0) { const idx = root.skipHeader(Math.max(0, resultsList.currentIndex), 1)
root.launch(root.filteredItems[Math.max(0, resultsList.currentIndex)]) if (idx < 0) return
const item = root.filteredItems[idx]
if (item.isAction)
root.executeAction(item)
else
root.launch(item)
}
Keys.onTabPressed: (event) => {
event.accepted = true
root._keyboardNav = true
const idx = root.skipHeader(Math.max(0, resultsList.currentIndex), 1)
if (idx < 0) return
const item = root.filteredItems[idx]
if (!item || item.isHeader || item.isAction) return
root._savedContentY = resultsList.contentY
root._savedExpandId = item.id
root._expandingActions = item.id
if (root.expandedItemId === item.id) {
root._pendingRestore = true
root.expandedItemId = ""
} else if (item.actions && item.actions.length > 0) {
root._pendingRestore = true
root.expandedItemId = item.id
} }
Qt.callLater(() => {
for (let i = 0; i < resultsList.count; i++) {
const it = root.filteredItems[i]
if (it.id === item.id && !it.isAction && !it.isHeader) {
resultsList.currentIndex = i
resultsList.positionViewAtIndex(i, ListView.Contain)
break
}
}
})
} }
Keys.onDownPressed: { Keys.onDownPressed: {
root._keyboardNav = true root._keyboardNav = true
if (resultsList.currentIndex < 0) { var next = resultsList.currentIndex < 0 ? 0 : resultsList.currentIndex + 1
resultsList.currentIndex = 0; if (next >= resultsList.count) next = resultsList.count - 1
} else { next = root.skipHeader(next, 1)
resultsList.currentIndex = Math.min(resultsList.currentIndex + 1, resultsList.count - 1) if (next < 0) next = root.skipHeader(0, 1)
if (next >= 0) {
resultsList.currentIndex = next
resultsList.positionViewAtIndex(next, ListView.Contain)
} }
resultsList.positionViewAtIndex(resultsList.currentIndex, ListView.Contain)
} }
Keys.onUpPressed: { Keys.onUpPressed: {
root._keyboardNav = true root._keyboardNav = true
if (resultsList.currentIndex < 0) { var next = resultsList.currentIndex < 0 ? resultsList.count - 1 : resultsList.currentIndex - 1
resultsList.currentIndex = resultsList.count - 1; if (next < 0) next = 0
} else { next = root.skipHeader(next, -1)
resultsList.currentIndex = Math.max(resultsList.currentIndex - 1, 0) if (next < 0) next = root.skipHeader(resultsList.count - 1, -1)
if (next >= 0) {
resultsList.currentIndex = next
resultsList.positionViewAtIndex(next, ListView.Contain)
} }
resultsList.positionViewAtIndex(resultsList.currentIndex, ListView.Contain)
} }
} }
} }
@@ -301,40 +380,117 @@ PanelWindow {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: listHeight Layout.preferredHeight: listHeight
property int listHeight: Math.min(contentHeight, 400) // Avoid reacting to contentHeight changes from lazy delegate
Behavior on listHeight { // instantiation during scroll — only animate on model count changes.
NumberAnimation { duration: 154; easing.type: Easing.OutCubic } property int listHeight: 0
NumberAnimation {
id: listHeightAnim
target: resultsList
property: "listHeight"
duration: 80
easing.type: Easing.OutCubic
} }
function _syncListHeight() {
var h = Math.min(contentHeight, 400)
if (h === listHeight) return
listHeightAnim.stop()
listHeightAnim.from = listHeight
listHeightAnim.to = h
listHeightAnim.start()
}
onCountChanged: Qt.callLater(_syncListHeight)
Component.onCompleted: Qt.callLater(_syncListHeight)
clip: true clip: true
model: root.filteredItems model: root.filteredItems
currentIndex: root.defaultIndex currentIndex: root.defaultIndex
spacing: 2 spacing: 2
snapMode: ListView.NoSnap
highlightRangeMode: ListView.NoHighlightRange
cacheBuffer: 400
reuseItems: true
pixelAligned: false
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.VerticalFlick
onModelChanged: currentIndex = root.defaultIndex onModelChanged: {
if (root._expandingActions !== "") {
root._expandingActions = ""
if (root._savedExpandId !== "") {
Qt.callLater(() => {
for (let i = 0; i < resultsList.count; i++) {
const it = root.filteredItems[i]
if (it.id === root._savedExpandId && !it.isAction && !it.isHeader) {
resultsList.currentIndex = i
resultsList.positionViewAtIndex(i, ListView.Contain)
break
}
}
root._pendingRestore = false
root._savedExpandId = ""
})
} else {
root._pendingRestore = false
}
} else {
currentIndex = root.defaultIndex
for (let i = 0; i < count; i++) {
const md = root.filteredItems[i]
if (md && !md.isHeader && !md.isAction) {
currentIndex = i
break
}
}
Qt.callLater(() => positionViewAtBeginning())
}
}
ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded } ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded }
add: Transition { Connections {
NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 100; easing.type: Easing.InQuad } target: resultsList
function onContentYChanged() {
if (root._pendingRestore && !root._inRestore && Math.abs(resultsList.contentY - root._savedContentY) > 1) {
root._inRestore = true
resultsList.contentY = root._savedContentY
root._inRestore = false
}
}
} }
delegate: Rectangle { delegate: Rectangle {
id: itemDelegate
width: resultsList.width width: resultsList.width
height: 38 height: 38
radius: 8 radius: modelData.isHeader ? 0 : 8
property bool hovered: false color: modelData.isHeader ? "transparent"
: (starHovered || hovered) ? t.launcherHover
color: hovered ? t.launcherHover
: (resultsList.currentIndex === index && index !== -1 : (resultsList.currentIndex === index && index !== -1
? t.launcherSelected : "transparent") ? t.launcherSelected : "transparent")
clip: modelData.isAction
property bool hovered: false
property bool starHovered: false
Text {
visible: modelData.isHeader
anchors { left: parent.left; leftMargin: 12; verticalCenter: parent.verticalCenter }
text: modelData.section || ""
color: t.launcherDim
font.pixelSize: 13
font.weight: Font.Bold
}
RowLayout { RowLayout {
visible: !modelData.isHeader
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 12 anchors.leftMargin: modelData.isAction ? 28 : 12
anchors.rightMargin: 12 anchors.rightMargin: 12
spacing: 12 spacing: 12
Item { Item {
visible: !modelData.isAction
width: 22; height: 22 width: 22; height: 22
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
@@ -359,20 +515,87 @@ PanelWindow {
} }
Text { Text {
text: modelData.name visible: modelData.isAction
color: t.launcherText text: ""
color: t.launcherDim
font.pixelSize: 14 font.pixelSize: 14
Layout.alignment: Qt.AlignVCenter
}
Text {
text: modelData.name
color: modelData.isAction ? t.launcherDim : t.launcherText
font.pixelSize: modelData.isAction ? 13 : 14
Layout.fillWidth: true Layout.fillWidth: true
elide: Text.ElideRight elide: Text.ElideRight
} }
Text {
visible: !modelData.isAction && modelData.actions && modelData.actions.length > 0
text: root.expandedItemId === modelData.id ? "▲" : "▼"
color: t.launcherDim
font.pixelSize: 9
Layout.alignment: Qt.AlignVCenter
}
Item {
visible: !modelData.isAction
width: 26; height: 26
Layout.alignment: Qt.AlignVCenter
Text {
id: starText
anchors.centerIn: parent
text: root.favoriteIds.includes(modelData.id) ? "★" : "☆"
font.pixelSize: 18
readonly property bool isFav: root.favoriteIds.includes(modelData.id)
color: starHovered ? t.launcherStarHover
: (isFav ? t.launcherAccent : t.launcherStar)
Behavior on color {
ColorAnimation { duration: 180; easing.type: Easing.OutCubic }
}
}
}
} }
MouseArea { MouseArea {
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onEntered: parent.hovered = true onEntered: parent.hovered = true
onExited: parent.hovered = false onExited: { parent.hovered = false; parent.starHovered = false }
onClicked: root.launch(modelData) onPositionChanged: mouse => {
parent.starHovered = !modelData.isHeader && !modelData.isAction && (mouse.x >= width - 46)
}
onClicked: mouse => {
if (modelData.isHeader) return
if (mouse.button === Qt.RightButton) {
if (!modelData.isAction && modelData.actions && modelData.actions.length > 0) {
root._savedContentY = resultsList.contentY
root._savedExpandId = modelData.id
root._expandingActions = modelData.id
root._pendingRestore = true
if (root.expandedItemId === modelData.id)
root.expandedItemId = ""
else
root.expandedItemId = modelData.id
}
return
}
if (modelData.isAction) {
root.executeAction(modelData)
return
}
if (mouse.x >= width - 46)
root.toggleFavorite(modelData.id)
else
root.launch(modelData)
}
} }
} }
} }

View File

@@ -1,103 +0,0 @@
#!/usr/bin/env bash
CACHE_DIR="/tmp/qs_launcher"
DRUN_CACHE="$CACHE_DIR/drun.txt"
RUN_CACHE="$CACHE_DIR/run.txt"
mkdir -p "$CACHE_DIR"
get_desktop_files() {
IFS=':' read -ra DIRS <<< \
"${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
for dir in "${DIRS[@]}"; do
APP_DIR="$dir/applications"
[ -d "$APP_DIR" ] || continue
find "$APP_DIR" \
-maxdepth 1 \
-name "*.desktop" \
2>/dev/null
done | while read -r f; do
name=$(
grep -m1 '^Name=' "$f" \
| cut -d= -f2-
)
exec=$(
grep -m1 '^Exec=' "$f" \
| cut -d= -f2- \
| sed 's/%[fFuUik]//g'
)
type=$(
grep -m1 '^Type=' "$f" \
| cut -d= -f2-
)
nodisplay=$(
grep -m1 '^NoDisplay=' "$f" \
| cut -d= -f2- \
| tr '[:upper:]' '[:lower:]'
)
icon=$(
grep -m1 '^Icon=' "$f" \
| cut -d= -f2-
)
[[ "$type" == "Application" ]] || continue
[[ "$nodisplay" != "true" ]] || continue
[[ -n "$name" ]] || continue
printf "%s\t%s\t%s\t%s\n" \
"$name" \
"$exec" \
"$(basename "$f" .desktop)" \
"$icon"
done
}
get_binaries() {
compgen -c \
| sort -u \
| head -600 \
| awk '{
print $1 "\t" $1 "\t" $1
}'
}
sort_and_dedup() {
sort -f -t$'\t' -k1,1 \
| awk -F'\t' '!seen[$1]++'
}
build_drun() {
get_desktop_files | sort_and_dedup
}
build_run() {
{ get_desktop_files; get_binaries; } | sort_and_dedup
}
update_cache() {
build_drun > "$DRUN_CACHE.tmp"
build_run > "$RUN_CACHE.tmp"
mv "$DRUN_CACHE.tmp" "$DRUN_CACHE"
mv "$RUN_CACHE.tmp" "$RUN_CACHE"
}
if [ "$1" == "--update-only" ]; then
update_cache
exit 0
fi

View File

@@ -39,7 +39,7 @@ ShellRoot {
// ── Spacing Gap: Top / Bottom ──────────────────────────────────────── // ── Spacing Gap: Top / Bottom ────────────────────────────────────────
Variants { Variants {
model: Quickshell.screens model: Cfg.Config.frameVariant === "bar" ? [] : Quickshell.screens
PanelWindow { PanelWindow {
required property var modelData required property var modelData
screen: modelData screen: modelData
@@ -59,7 +59,7 @@ ShellRoot {
// ── Spacing Gap: Left ──────────────────────────────────────────────── // ── Spacing Gap: Left ────────────────────────────────────────────────
Variants { Variants {
model: Quickshell.screens model: Cfg.Config.frameVariant === "bar" ? [] : Quickshell.screens
PanelWindow { PanelWindow {
required property var modelData required property var modelData
screen: modelData screen: modelData
@@ -74,7 +74,7 @@ ShellRoot {
// ── Spacing Gap: Right ─────────────────────────────────────────────── // ── Spacing Gap: Right ───────────────────────────────────────────────
Variants { Variants {
model: Quickshell.screens model: Cfg.Config.frameVariant === "bar" ? [] : Quickshell.screens
PanelWindow { PanelWindow {
required property var modelData required property var modelData
screen: modelData screen: modelData
@@ -161,6 +161,36 @@ ShellRoot {
var ctx = getContext("2d") var ctx = getContext("2d")
ctx.clearRect(0, 0, width, height) ctx.clearRect(0, 0, width, height)
if (Cfg.Config.frameVariant === "bar") {
var barW = width - Cfg.Config.margin * 2
var barH = Cfg.Config.barHeight
var barX = Cfg.Config.margin
var barY = root.isTop ? Cfg.Config.frameBarPadTop : height - Cfg.Config.frameBarPadBottom - barH
var r = Math.min(Cfg.Config.radius, barH / 2)
ctx.fillStyle = root.frameBackground
ctx.beginPath()
ctx.moveTo(barX + r, barY)
ctx.lineTo(barX + barW - r, barY)
ctx.arcTo(barX + barW, barY, barX + barW, barY + r, r)
ctx.lineTo(barX + barW, barY + barH - r)
ctx.arcTo(barX + barW, barY + barH, barX + barW - r, barY + barH, r)
ctx.lineTo(barX + r, barY + barH)
ctx.arcTo(barX, barY + barH, barX, barY + barH - r, r)
ctx.lineTo(barX, barY + r)
ctx.arcTo(barX, barY, barX + r, barY, r)
ctx.closePath()
ctx.fill()
if (Cfg.Config.frameBorderWidth > 0) {
ctx.lineWidth = Cfg.Config.frameBorderWidth
ctx.strokeStyle = root.frameBorderColor
ctx.stroke()
}
return
}
var mT = root.isTop ? Cfg.Config.barHeight : Cfg.Config.margin var mT = root.isTop ? Cfg.Config.barHeight : Cfg.Config.margin
var mB = root.isTop ? Cfg.Config.margin : Cfg.Config.barHeight var mB = root.isTop ? Cfg.Config.margin : Cfg.Config.barHeight
var r = Cfg.Config.radius var r = Cfg.Config.radius

BIN
wallpapers/snowy.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

View File

@@ -29,8 +29,9 @@ PanelWindow {
readonly property var t: Cfg.Config.theme readonly property var t: Cfg.Config.theme
readonly property bool isTop: Cfg.Config.barPosition === "top" readonly property bool isTop: Cfg.Config.barPosition === "top"
readonly property int frameTop: isTop ? Cfg.Config.barHeight : Cfg.Config.margin readonly property int barEdgePad: Cfg.Config.frameVariant === "bar" ? (isTop ? Cfg.Config.frameBarPadTop : Cfg.Config.frameBarPadBottom) : 0
readonly property int frameBot: isTop ? Cfg.Config.margin : Cfg.Config.barHeight readonly property int frameTop: isTop ? Cfg.Config.barHeight + barEdgePad : Cfg.Config.margin
readonly property int frameBot: isTop ? Cfg.Config.margin : Cfg.Config.barHeight + barEdgePad
readonly property int inset: Cfg.Config.margin + Cfg.Config.frameBorderWidth + 8 readonly property int inset: Cfg.Config.margin + Cfg.Config.frameBorderWidth + 8
readonly property int sbWidth: 260 readonly property int sbWidth: 260
readonly property bool isLeft: Cfg.Config.sideBarPosition === "left" readonly property bool isLeft: Cfg.Config.sideBarPosition === "left"

View File

@@ -47,6 +47,7 @@ Rectangle {
: root.t.mprisTextDim : root.t.mprisTextDim
) )
font.pixelSize: primary ? 22 : 18 font.pixelSize: primary ? 22 : 18
font.weight: Font.Bold
Behavior on color { ColorAnimation { duration: 150 } } Behavior on color { ColorAnimation { duration: 150 } }
} }

View File

@@ -132,6 +132,7 @@ Item {
text: "󰎆" text: "󰎆"
color: root.t.mprisAccent color: root.t.mprisAccent
font.pixelSize: 18 font.pixelSize: 18
font.weight: Font.Bold
} }
} }
@@ -144,7 +145,7 @@ Item {
text: root.activePlayer ? root.formatIdentity(root.activePlayer.identity) : "No media" text: root.activePlayer ? root.formatIdentity(root.activePlayer.identity) : "No media"
color: root.t.mprisTextMain color: root.t.mprisTextMain
font.pixelSize: 13 font.pixelSize: 13
font.weight: Font.DemiBold font.weight: Font.Bold
elide: Text.ElideRight elide: Text.ElideRight
Layout.fillWidth: true Layout.fillWidth: true
} }
@@ -152,6 +153,7 @@ Item {
text: root.playbackStatusText() text: root.playbackStatusText()
color: root.t.mprisTextDim color: root.t.mprisTextDim
font.pixelSize: 10 font.pixelSize: 10
font.weight: Font.Bold
opacity: 0.75 opacity: 0.75
} }
} }
@@ -204,6 +206,7 @@ Item {
text: "󰝚" text: "󰝚"
color: root.t.mprisAccent color: root.t.mprisAccent
font.pixelSize: 28 font.pixelSize: 28
font.weight: Font.Bold
visible: root.activePlayer && (root.activePlayer.trackArtUrl === "" || !albumArt.visible) visible: root.activePlayer && (root.activePlayer.trackArtUrl === "" || !albumArt.visible)
} }
} }
@@ -217,7 +220,7 @@ Item {
text: root.activePlayer ? (root.activePlayer.trackTitle || "Unknown Title") : "" text: root.activePlayer ? (root.activePlayer.trackTitle || "Unknown Title") : ""
color: root.t.mprisTextMain color: root.t.mprisTextMain
font.pixelSize: 13 font.pixelSize: 13
font.weight: Font.Medium font.weight: Font.Bold
elide: Text.ElideRight elide: Text.ElideRight
maximumLineCount: 2 maximumLineCount: 2
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
@@ -228,6 +231,7 @@ Item {
text: root.activePlayer ? (root.activePlayer.trackArtist || "Unknown Artist") : "" text: root.activePlayer ? (root.activePlayer.trackArtist || "Unknown Artist") : ""
color: root.t.mprisTextDim color: root.t.mprisTextDim
font.pixelSize: 11 font.pixelSize: 11
font.weight: Font.Bold
elide: Text.ElideRight elide: Text.ElideRight
Layout.fillWidth: true Layout.fillWidth: true
} }
@@ -236,6 +240,7 @@ Item {
text: root.activePlayer ? (root.activePlayer.trackAlbum || "") : "" text: root.activePlayer ? (root.activePlayer.trackAlbum || "") : ""
color: root.t.mprisTextDim color: root.t.mprisTextDim
font.pixelSize: 10 font.pixelSize: 10
font.weight: Font.Bold
opacity: 0.7 opacity: 0.7
elide: Text.ElideRight elide: Text.ElideRight
visible: root.activePlayer && root.activePlayer.trackAlbum !== "" visible: root.activePlayer && root.activePlayer.trackAlbum !== ""
@@ -277,6 +282,7 @@ Item {
text: root.activePlayer ? root.formatDuration(root.activePlayer.position) : "0:00" text: root.activePlayer ? root.formatDuration(root.activePlayer.position) : "0:00"
color: root.t.mprisTextDim color: root.t.mprisTextDim
font.pixelSize: 9 font.pixelSize: 9
font.weight: Font.Bold
Layout.alignment: Qt.AlignLeft Layout.alignment: Qt.AlignLeft
} }
@@ -286,6 +292,7 @@ Item {
text: root.activePlayer ? root.formatDuration(root.activePlayer.length) : "0:00" text: root.activePlayer ? root.formatDuration(root.activePlayer.length) : "0:00"
color: root.t.mprisTextDim color: root.t.mprisTextDim
font.pixelSize: 9 font.pixelSize: 9
font.weight: Font.Bold
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
} }
} }
@@ -302,6 +309,7 @@ Item {
text: root.volumeIcon() text: root.volumeIcon()
color: root.activePlayer && root.activePlayer.volume > 0 ? root.t.mprisAccent : root.t.mprisTextDim color: root.activePlayer && root.activePlayer.volume > 0 ? root.t.mprisAccent : root.t.mprisTextDim
font.pixelSize: 16 font.pixelSize: 16
font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }

View File

@@ -243,6 +243,7 @@ ColumnLayout {
text: "󰌽" text: "󰌽"
color: root.t.sysInfoAccent color: root.t.sysInfoAccent
font.pixelSize: 20 font.pixelSize: 20
font.weight: Font.Bold
} }
} }
@@ -255,7 +256,7 @@ ColumnLayout {
text: root.osName text: root.osName
color: root.t.sysInfoTextMain color: root.t.sysInfoTextMain
font.pixelSize: 13 font.pixelSize: 13
font.weight: Font.DemiBold font.weight: Font.Bold
elide: Text.ElideRight elide: Text.ElideRight
Layout.fillWidth: true Layout.fillWidth: true
} }
@@ -263,6 +264,7 @@ ColumnLayout {
text: root.kernelVer text: root.kernelVer
color: root.t.sysInfoTextDim color: root.t.sysInfoTextDim
font.pixelSize: 10 font.pixelSize: 10
font.weight: Font.Bold
opacity: 0.75 opacity: 0.75
elide: Text.ElideRight elide: Text.ElideRight
Layout.fillWidth: true Layout.fillWidth: true
@@ -421,6 +423,7 @@ ColumnLayout {
text: "󰅐" text: "󰅐"
color: root.t.sysInfoAccent color: root.t.sysInfoAccent
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
} }
} }
@@ -428,6 +431,7 @@ ColumnLayout {
text: "Uptime" text: "Uptime"
color: root.t.sysInfoTextDim color: root.t.sysInfoTextDim
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@@ -436,7 +440,7 @@ ColumnLayout {
text: root.uptimeStr text: root.uptimeStr
color: root.t.sysInfoTextMain color: root.t.sysInfoTextMain
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Medium font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }
@@ -458,6 +462,7 @@ ColumnLayout {
text: "" text: ""
color: root.t.sysInfoAccent color: root.t.sysInfoAccent
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
} }
} }
@@ -465,6 +470,7 @@ ColumnLayout {
text: "Kernel" text: "Kernel"
color: root.t.sysInfoTextDim color: root.t.sysInfoTextDim
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@@ -473,7 +479,7 @@ ColumnLayout {
text: root.kernelVer text: root.kernelVer
color: root.t.sysInfoTextMain color: root.t.sysInfoTextMain
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Medium font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }
@@ -515,6 +521,7 @@ ColumnLayout {
: "󰂃" : "󰂃"
color: parent.battIconColor color: parent.battIconColor
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
} }
} }
@@ -522,6 +529,7 @@ ColumnLayout {
text: "Battery" text: "Battery"
color: root.t.sysInfoTextDim color: root.t.sysInfoTextDim
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@@ -530,6 +538,7 @@ ColumnLayout {
text: Math.round(root.battPct) + "%" text: Math.round(root.battPct) + "%"
color: root.t.sysInfoTextMain color: root.t.sysInfoTextMain
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }
@@ -575,6 +584,7 @@ ColumnLayout {
text: root.netOnline ? "󰤨" : "󰤭" text: root.netOnline ? "󰤨" : "󰤭"
color: root.netOnline ? root.t.statusOk : root.t.sysInfoTextDim color: root.netOnline ? root.t.statusOk : root.t.sysInfoTextDim
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
} }
} }
@@ -582,6 +592,7 @@ ColumnLayout {
text: "Network" text: "Network"
color: root.t.sysInfoTextDim color: root.t.sysInfoTextDim
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@@ -590,7 +601,7 @@ ColumnLayout {
text: root.netOnline ? "Connected" : "Offline" text: root.netOnline ? "Connected" : "Offline"
color: root.netOnline ? root.t.statusOk : root.t.statusErr color: root.netOnline ? root.t.statusOk : root.t.statusErr
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Medium font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }

View File

@@ -42,6 +42,7 @@ Item {
text: root.icon text: root.icon
color: root.iconColor color: root.iconColor
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
} }
} }
@@ -49,6 +50,7 @@ Item {
text: root.label text: root.label
color: root.dimColor color: root.dimColor
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@@ -57,7 +59,7 @@ Item {
text: root.value text: root.value
color: root.textColor color: root.textColor
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Medium font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }

View File

@@ -88,6 +88,7 @@ Item {
text: root.icon text: root.icon
color: root.t.weatherAccent color: root.t.weatherAccent
font.pixelSize: 18 font.pixelSize: 18
font.weight: Font.Bold
} }
} }
@@ -100,7 +101,7 @@ Item {
text: root.condition text: root.condition
color: root.t.weatherTextMain color: root.t.weatherTextMain
font.pixelSize: 13 font.pixelSize: 13
font.weight: Font.DemiBold font.weight: Font.Bold
elide: Text.ElideRight elide: Text.ElideRight
Layout.fillWidth: true Layout.fillWidth: true
} }
@@ -108,6 +109,7 @@ Item {
text: root.location text: root.location
color: root.t.weatherTextDim color: root.t.weatherTextDim
font.pixelSize: 10 font.pixelSize: 10
font.weight: Font.Bold
opacity: 0.75 opacity: 0.75
elide: Text.ElideRight elide: Text.ElideRight
Layout.fillWidth: true Layout.fillWidth: true
@@ -130,6 +132,7 @@ Item {
text: "󰑐" text: "󰑐"
color: refreshMouse.containsMouse ? root.t.weatherAccent : root.t.weatherTextDim color: refreshMouse.containsMouse ? root.t.weatherAccent : root.t.weatherTextDim
font.pixelSize: 14 font.pixelSize: 14
font.weight: Font.Bold
Behavior on color { ColorAnimation { duration: 150 } } Behavior on color { ColorAnimation { duration: 150 } }
RotationAnimator { RotationAnimator {
@@ -183,6 +186,7 @@ Item {
text: "󰔄" text: "󰔄"
color: root.t.weatherTempColor color: root.t.weatherTempColor
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
} }
} }
@@ -190,6 +194,7 @@ Item {
text: "Temperature" text: "Temperature"
color: root.t.weatherTextDim color: root.t.weatherTextDim
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@@ -198,7 +203,7 @@ Item {
text: root.temp text: root.temp
color: root.t.weatherTextMain color: root.t.weatherTextMain
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Medium font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }
@@ -220,6 +225,7 @@ Item {
text: "󰔄" text: "󰔄"
color: root.t.weatherFeelsColor color: root.t.weatherFeelsColor
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
} }
} }
@@ -227,6 +233,7 @@ Item {
text: "Feels like" text: "Feels like"
color: root.t.weatherTextDim color: root.t.weatherTextDim
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@@ -235,7 +242,7 @@ Item {
text: root.feelsLike text: root.feelsLike
color: root.t.weatherTextMain color: root.t.weatherTextMain
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Medium font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }
@@ -257,6 +264,7 @@ Item {
text: "󰃚" text: "󰃚"
color: root.t.weatherHumidColor color: root.t.weatherHumidColor
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
} }
} }
@@ -264,6 +272,7 @@ Item {
text: "Humidity" text: "Humidity"
color: root.t.weatherTextDim color: root.t.weatherTextDim
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@@ -272,7 +281,7 @@ Item {
text: root.humidity text: root.humidity
color: root.t.weatherTextMain color: root.t.weatherTextMain
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Medium font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }
@@ -294,6 +303,7 @@ Item {
text: "󰖝" text: "󰖝"
color: root.t.weatherWindColor color: root.t.weatherWindColor
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
} }
} }
@@ -301,6 +311,7 @@ Item {
text: "Wind" text: "Wind"
color: root.t.weatherTextDim color: root.t.weatherTextDim
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
@@ -309,7 +320,7 @@ Item {
text: root.wind text: root.wind
color: root.t.weatherTextMain color: root.t.weatherTextMain
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Medium font.weight: Font.Bold
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
} }
} }