diff --git a/bar/modules/Battery.qml b/bar/modules/Battery.qml index 4971521..c30d4a5 100644 --- a/bar/modules/Battery.qml +++ b/bar/modules/Battery.qml @@ -385,7 +385,7 @@ ModuleChip { property bool isActive: interactive && (root.pp.profile === profileValue) height: 38 - radius: 10 + radius: 8 color: isActive ? root.iconColor : Qt.rgba(root.iconColor.r, root.iconColor.g, root.iconColor.b, (profileHover.containsMouse && interactive) ? 0.14 : 0.06) diff --git a/bar/modules/Clock.qml b/bar/modules/Clock.qml index b41cd28..cff9713 100644 --- a/bar/modules/Clock.qml +++ b/bar/modules/Clock.qml @@ -89,7 +89,7 @@ ModuleChip { id: navBtn required property int direction - width: 26; height: 26; radius: 6 + width: 26; height: 26; radius: 8 color: btnMouse.containsMouse ? (btnMouse.pressed ? root.t.calArrowBgPress : root.t.calArrowBgHover) diff --git a/bar/modules/Crypto.qml b/bar/modules/Crypto.qml index fc0afcd..9a817f4 100644 --- a/bar/modules/Crypto.qml +++ b/bar/modules/Crypto.qml @@ -40,6 +40,7 @@ ModuleChip { property string localVsCur: "usd" property int localDecimals: cfg.cryptoDecimals property int localRefreshSec: cfg.cryptoRefreshSec + property int localRotateSec: cfg.cryptoRotateSec property bool localShowIcon: cfg.cryptoShowIcon function resolveWithPersistence() { @@ -49,6 +50,7 @@ ModuleChip { root.activeCoinIndex = 0 root.localDecimals = cfg.cryptoDecimals root.localRefreshSec = cfg.cryptoRefreshSec + root.localRotateSec = cfg.cryptoRotateSec root.localShowIcon = cfg.cryptoShowIcon } @@ -56,6 +58,7 @@ ModuleChip { const pairs = root.localPairs const decimals = Math.round(root.localDecimals) const refreshSec = Math.round(root.localRefreshSec) + const rotateSec = Math.round(root.localRotateSec) const showIcon = root.localShowIcon const pairsQml = "[" + pairs.map(p => @@ -64,7 +67,8 @@ ModuleChip { configWriter.writeInts([ { key: "cryptoDecimals", value: decimals }, - { key: "cryptoRefreshSec", value: refreshSec } + { key: "cryptoRefreshSec", value: refreshSec }, + { key: "cryptoRotateSec", value: rotateSec } ]) configWriter.writeBool("cryptoShowIcon", showIcon) configWriter.writeArray("cryptoPairs", pairsQml) @@ -87,6 +91,10 @@ ModuleChip { property bool loading: false property bool loadingVisible: false property bool hasError: false + property var sparklineData: [] + property real change7d: 0 + property var _priceCache: ({}) + property int _fetchGen: 0 Timer { id: minLoadTimer @@ -140,66 +148,148 @@ ModuleChip { return val.slice(0, maxLen).replace(/[\x00-\x1f\x7f-\x9f]/g, "") } + function rotatePrev() { + if (root.localPairs.length <= 1) return + root.activeCoinIndex = (root.activeCoinIndex - 1 + root.localPairs.length) % root.localPairs.length + root._applyFromCache() + rotateTimer.restart() + } + + function rotateNext() { + if (root.localPairs.length <= 1) return + root.activeCoinIndex = (root.activeCoinIndex + 1) % root.localPairs.length + root._applyFromCache() + rotateTimer.restart() + } + + function _applyFromCache() { + var key = root.localCoinId + "_" + root.localActiveCurrency + var entry = root._priceCache[key] + if (!entry) { console.log("Crypto: no cache entry for", key); return } + console.log("Crypto: applying", key, "price=" + entry.price) + price = entry.price + change24h = entry.change24h + high24h = entry.high24h + low24h = entry.low24h + marketCap = entry.marketCap + volume24h = entry.volume24h + rank = entry.rank + circulatingSupply = entry.circulatingSupply + ath = entry.ath + athChange = entry.athChange + coinSymbol = safeString(entry.symbol, 8, root.localCoinId).toUpperCase() + coinName = safeString(entry.name, 50, "") + lastUpdated = new Date().toLocaleTimeString(Qt.locale(), "HH:mm:ss") + root.displayCurrency = root.localActiveCurrency + sparklineData = entry.sparkline || [] + change7d = entry.change7d || 0 + hasError = false + } + function fetchPrice() { - if (loading) return loading = true hasError = false + _fetchGen++ + var myGen = _fetchGen - const url = - "https://api.coingecko.com/api/v3/coins/markets" + - "?vs_currency=" + encodeURIComponent(localActiveCurrency || "usd") + - "&ids=" + encodeURIComponent(localCoinId || "bitcoin") + - "&order=market_cap_desc&per_page=1&page=1" + - "&sparkline=false&price_change_percentage=24h" - - const xhr = new XMLHttpRequest() - xhr.timeout = 15000 - xhr.onreadystatechange = function () { - if (xhr.readyState !== XMLHttpRequest.DONE) return - loading = false - if (xhr.status !== 200) { hasError = true; return } - try { - const text = xhr.responseText - if (text.length > 65536) { hasError = true; return } - const data = JSON.parse(text) - if (!Array.isArray(data) || data.length === 0) { hasError = true; return } - const coin = data[0] - if (typeof coin !== "object" || coin === null) { hasError = true; return } - price = safeNumber(coin.current_price, -1) - change24h = safeNumber(coin.price_change_percentage_24h, 0) - high24h = safeNumber(coin.high_24h, 0) - low24h = safeNumber(coin.low_24h, 0) - marketCap = safeNumber(coin.market_cap, 0) - volume24h = safeNumber(coin.total_volume, 0) - rank = Math.trunc(safeNumber(coin.market_cap_rank, 0)) - circulatingSupply = safeNumber(coin.circulating_supply, 0) - ath = safeNumber(coin.ath, 0) - athChange = safeNumber(coin.ath_change_percentage, 0) - coinSymbol = safeString(coin.symbol, 8, localCoinId).toUpperCase() - coinName = safeString(coin.name, 50, "") - lastUpdated = new Date().toLocaleTimeString(Qt.locale(), "HH:mm:ss") - root.displayCurrency = root.localActiveCurrency - root.activeCoinIndex = (root.activeCoinIndex + 1) % Math.max(1, root.localPairs.length) - } catch (_) { - hasError = true - } + var coinGroups = {} + for (var i = 0; i < root.localPairs.length; i++) { + var p = root.localPairs[i] + if (!coinGroups[p.currency]) coinGroups[p.currency] = [] + var coinList = coinGroups[p.currency] + if (coinList.indexOf(p.coin) === -1) coinList.push(p.coin) + } + + var currencies = Object.keys(coinGroups) + var pending = currencies.length + + if (pending === 0) { loading = false; hasError = true; return } + + for (var ci = 0; ci < currencies.length; ci++) { + var cur = currencies[ci] + var ids = coinGroups[cur].join(",") + + var url = + "https://api.coingecko.com/api/v3/coins/markets" + + "?vs_currency=" + encodeURIComponent(cur || "usd") + + "&ids=" + encodeURIComponent(ids) + + "&order=market_cap_desc&per_page=250&page=1" + + "&sparkline=true&price_change_percentage=24h,7d" + + var xhr = new XMLHttpRequest() + xhr._currency = cur + xhr.timeout = 15000 + xhr.onreadystatechange = (function(xhr, cur, myGen) { + return function() { + if (myGen !== root._fetchGen) return + if (xhr.readyState !== XMLHttpRequest.DONE) return + if (xhr.status !== 200) { hasError = true } + else { + try { + var text = xhr.responseText + if (text.length <= 65536) { + var data = JSON.parse(text) + if (Array.isArray(data)) { + for (var di = 0; di < data.length; di++) { + var coin = data[di] + var key = coin.id + "_" + cur + console.log("Crypto: cache", key, "price=" + coin.current_price) + root._priceCache[key] = { + price: safeNumber(coin.current_price, -1), + change24h: safeNumber(coin.price_change_percentage_24h, 0), + high24h: safeNumber(coin.high_24h, 0), + low24h: safeNumber(coin.low_24h, 0), + marketCap: safeNumber(coin.market_cap, 0), + volume24h: safeNumber(coin.total_volume, 0), + rank: Math.trunc(safeNumber(coin.market_cap_rank, 0)), + circulatingSupply: safeNumber(coin.circulating_supply, 0), + ath: safeNumber(coin.ath, 0), + athChange: safeNumber(coin.ath_change_percentage, 0), + symbol: safeString(coin.symbol, 8, coin.id), + name: safeString(coin.name, 50, ""), + sparkline: (coin.sparkline_in_7d && Array.isArray(coin.sparkline_in_7d.price)) + ? coin.sparkline_in_7d.price : [], + change7d: safeNumber(coin.price_change_percentage_7d_in_currency, 0) + } + } + } + } + } catch (_) {} + } + if (--pending <= 0) { + loading = false + root._applyFromCache() + } + } + })(xhr, cur, myGen) + + xhr.open("GET", url) + xhr.setRequestHeader("Accept", "application/json") + xhr.send() } - xhr.open("GET", url) - xhr.setRequestHeader("Accept", "application/json") - xhr.send() } Component.onCompleted: { resolveWithPersistence(); fetchPrice() } + Timer { + id: rotateTimer + interval: root.localRotateSec * 1000 + running: root.localRotateSec > 0 && root.localPairs.length > 1 + repeat: true + onTriggered: root.rotateNext() + } + Timer { id: refreshTimer interval: root.localRefreshSec * 1000 running: true repeat: true + triggeredOnStart: true onTriggered: root.fetchPrice() } onLocalRefreshSecChanged: refreshTimer.restart() + onLocalRotateSecChanged: rotateTimer.restart() RowLayout { id: chipRow @@ -277,36 +367,64 @@ ModuleChip { Rectangle { Layout.fillWidth: true - height: 30 - radius: 10 + height: 36 + radius: 12 color: t.cryptoFieldBg RowLayout { anchors.fill: parent - anchors.margins: 3 - spacing: 3 + anchors.margins: 4 + spacing: 4 component TabBtn: Rectangle { required property string label required property int tabIndex + property string icon: "" Layout.fillWidth: true - height: 24 - radius: 8 + height: 28 + radius: 9 readonly property bool active: cryptoPopup.activeTab === tabIndex + color: active ? (t.accent) : (tm.containsMouse ? (t.cryptoFieldBgFocus) : "transparent") - Behavior on color { ColorAnimation { duration: 130 } } + Behavior on color { ColorAnimation { duration: 150 } } - Text { + border.color: active ? Qt.rgba(1, 1, 1, 0.18) : "transparent" + border.width: 1 + Behavior on border.color { ColorAnimation { duration: 150 } } + + scale: tm.pressed ? 0.93 : 1.0 + Behavior on scale { NumberAnimation { duration: 90; easing.type: Easing.OutQuad } } + + Row { anchors.centerIn: parent - text: parent.label - color: parent.active ? (t.cryptoTextOnAccent) : (t.cryptoPopupDim) - font.pixelSize: 11 - font.bold: parent.active - Behavior on color { ColorAnimation { duration: 130 } } + spacing: 5 + + Text { + anchors.verticalCenter: parent.verticalCenter + visible: parent.parent.icon !== "" + text: parent.parent.icon + color: parent.parent.active ? (t.cryptoTextOnAccent) : (t.cryptoPopupDim) + font.pixelSize: 11 + opacity: parent.parent.active ? 1.0 : 0.7 + Behavior on color { ColorAnimation { duration: 150 } } + Behavior on opacity { NumberAnimation { duration: 150 } } + } + + Text { + anchors.verticalCenter: parent.verticalCenter + text: parent.parent.label + color: parent.parent.active ? (t.cryptoTextOnAccent) : (t.cryptoPopupDim) + font.pixelSize: 12 + font.bold: parent.parent.active + font.letterSpacing: parent.parent.active ? 0.4 : 0.0 + Behavior on color { ColorAnimation { duration: 150 } } + Behavior on font.letterSpacing { NumberAnimation { duration: 150 } } + } } + MouseArea { id: tm anchors.fill: parent; hoverEnabled: true @@ -315,8 +433,8 @@ ModuleChip { } } - TabBtn { label: "Price"; tabIndex: 0 } - TabBtn { label: "Settings"; tabIndex: 1 } + TabBtn { label: "Price"; icon: "󰕾"; tabIndex: 0 } + TabBtn { label: "Settings"; icon: "󰒓"; tabIndex: 1 } } } @@ -490,6 +608,113 @@ ModuleChip { Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator } + ColumnLayout { + Layout.fillWidth: true + spacing: 5 + + RowLayout { + Layout.fillWidth: true + Text { + text: "7d Chart" + color: t.cryptoPopupDim + font.pixelSize: 12 + Layout.fillWidth: true + } + Rectangle { + visible: root.sparklineData.length > 1 + width: badge7d.implicitWidth + 12 + height: 20; radius: 10 + color: root.change7d >= 0 ? (t.cryptoUpBg) : (t.cryptoDownBg) + Text { + id: badge7d + anchors.centerIn: parent + text: (root.change7d >= 0 ? "▲ +" : "▼ ") + root.change7d.toFixed(2) + "%" + color: root.change7d >= 0 ? (t.cryptoUp) : (t.cryptoDown) + font.pixelSize: 10 + font.bold: true + } + } + } + + Canvas { + id: sparklineCanvas + Layout.fillWidth: true + height: 52 + + property var prices: root.sparklineData + property bool isUp: root.change7d >= 0 + property string upColor: t.cryptoUp || "#4ade80" + property string downColor: t.cryptoDown || "#f87171" + + onPricesChanged: requestPaint() + onIsUpChanged: requestPaint() + onUpColorChanged: requestPaint() + onDownColorChanged:requestPaint() + + onPaint: { + var ctx = getContext("2d") + ctx.clearRect(0, 0, width, height) + var pts = prices + if (!pts || pts.length < 2) { + ctx.fillStyle = Qt.rgba(1, 1, 1, 0.06) + ctx.beginPath() + ctx.roundedRect(0, 0, width, height, 6, 6) + ctx.fill() + return + } + var minP = pts[0], maxP = pts[0] + for (var i = 1; i < pts.length; i++) { + if (pts[i] < minP) minP = pts[i] + if (pts[i] > maxP) maxP = pts[i] + } + var range = maxP - minP + if (range === 0) range = 1 + var pad = 4, pw = width - pad * 2, ph = height - pad * 2 + var lineColor = isUp ? upColor : downColor + + ctx.beginPath() + for (var j = 0; j < pts.length; j++) { + var x = pad + (j / (pts.length - 1)) * pw + var y = pad + ph - ((pts[j] - minP) / range) * ph + if (j === 0) ctx.moveTo(x, y) + else ctx.lineTo(x, y) + } + ctx.lineTo(pad + pw, pad + ph) + ctx.lineTo(pad, pad + ph) + ctx.closePath() + var grad = ctx.createLinearGradient(0, 0, 0, height) + grad.addColorStop(0, Qt.rgba( + isUp ? 0.29 : 0.97, + isUp ? 0.87 : 0.44, + isUp ? 0.50 : 0.44, 0.22)) + grad.addColorStop(1, Qt.rgba(0, 0, 0, 0)) + ctx.fillStyle = grad + ctx.fill() + + ctx.beginPath() + for (var k = 0; k < pts.length; k++) { + var lx = pad + (k / (pts.length - 1)) * pw + var ly = pad + ph - ((pts[k] - minP) / range) * ph + if (k === 0) ctx.moveTo(lx, ly) + else ctx.lineTo(lx, ly) + } + ctx.strokeStyle = lineColor + ctx.lineWidth = 1.5 + ctx.lineJoin = "round" + ctx.stroke() + + var lx2 = pad + pw + var ly2 = pad + ph - ((pts[pts.length - 1] - minP) / range) * ph + ctx.beginPath() + ctx.arc(lx2, ly2, 3, 0, Math.PI * 2) + ctx.fillStyle = lineColor + ctx.fill() + } + } + } + + Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator } + RowLayout { Layout.fillWidth: true @@ -500,6 +725,50 @@ ModuleChip { Layout.fillWidth: true } + Rectangle { + visible: root.localPairs.length > 1 + width: 26; height: 26; radius: 8 + color: prevMouse.containsMouse + ? (prevMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) + : "transparent" + Behavior on color { ColorAnimation { duration: 120 } } + + Text { + anchors.centerIn: parent + text: "‹" + color: t.cryptoIcon + font.pixelSize: 14 + } + + MouseArea { + id: prevMouse + anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor + onClicked: root.rotatePrev() + } + } + + Rectangle { + visible: root.localPairs.length > 1 + width: 26; height: 26; radius: 8 + color: nextMouse.containsMouse + ? (nextMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) + : "transparent" + Behavior on color { ColorAnimation { duration: 120 } } + + Text { + anchors.centerIn: parent + text: "›" + color: t.cryptoIcon + font.pixelSize: 14 + } + + MouseArea { + id: nextMouse + anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor + onClicked: root.rotateNext() + } + } + Rectangle { id: refreshBtn width: 26; height: 26; radius: 8 @@ -540,6 +809,7 @@ ModuleChip { ColumnLayout { id: settingsContent width: tabContainer.width + height: tabContainer.height x: cryptoPopup.activeTab === 1 ? 0 : tabContainer.width opacity: cryptoPopup.activeTab === 1 ? 1.0 : 0.0 Behavior on x { NumberAnimation { duration: 260; easing.type: Easing.OutCubic } } @@ -650,7 +920,7 @@ ModuleChip { ColumnLayout { Layout.fillWidth: true - spacing: 4 + spacing: 8 Text { text: "Pairs to cycle" @@ -661,11 +931,11 @@ ModuleChip { ColumnLayout { Layout.fillWidth: true - spacing: 4 + spacing: 8 Item { Layout.fillWidth: true - height: 24 + height: 28 clip: true Rectangle { @@ -756,6 +1026,7 @@ ModuleChip { root.localPairs = arr if (root.activeCoinIndex >= arr.length) root.activeCoinIndex = 0 + root.fetchPrice() } } } @@ -885,41 +1156,51 @@ ModuleChip { root.localPairs = root.localPairs.concat([{ coin: c, currency: cur }]) addCoinInput.text = "" addCurrencyInput.text = "" - } - } - } - } - - Rectangle { - width: 30; height: 30; radius: 8 - color: addPairMouse.containsMouse - ? (addPairMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) - : (t.cryptoFieldBg) - Behavior on color { ColorAnimation { duration: 100 } } - Text { - anchors.centerIn: parent; text: "+" - font.pixelSize: 14; font.bold: true - color: t.cryptoPopupText - } - MouseArea { - id: addPairMouse - anchors.fill: parent; hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: { - const c = addCoinInput.text.trim().toLowerCase() - const cur = addCurrencyInput.text.trim().toLowerCase() || root.localVsCur - if (c !== "") { - root.localPairs = root.localPairs.concat([{ coin: c, currency: cur }]) - addCoinInput.text = "" - addCurrencyInput.text = "" + root.fetchPrice() } } } } } } + + Rectangle { + Layout.fillWidth: true + Layout.topMargin: 4 + height: 32; radius: 9 + color: addPairMouse.containsMouse + ? (addPairMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) + : (t.cryptoApplyIdleBg) + Behavior on color { ColorAnimation { duration: 130 } } + Text { + anchors.centerIn: parent + text: "+ Add Pair" + color: addPairMouse.containsMouse ? (t.cryptoTextOnAccent) : (t.cryptoPopupText) + font.pixelSize: 12; font.bold: true + Behavior on color { ColorAnimation { duration: 130 } } + } + MouseArea { + id: addPairMouse + anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor + onClicked: { + const c = addCoinInput.text.trim().toLowerCase() + const cur = addCurrencyInput.text.trim().toLowerCase() || root.localVsCur + if (c !== "") { + root.localPairs = root.localPairs.concat([{ coin: c, currency: cur }]) + addCoinInput.text = "" + addCurrencyInput.text = "" + root.fetchPrice() + } + } + } + } + } + Item { Layout.fillHeight: true } + + Rectangle { Layout.fillWidth: true; height: 1; color: t.calSeparator } + StepRow { label: "Decimals in label" value: root.localDecimals @@ -1015,6 +1296,93 @@ ModuleChip { } } + RowLayout { + Layout.fillWidth: true + + Text { + text: "Rotate (seconds)" + color: t.cryptoPopupDim + font.pixelSize: 12 + Layout.fillWidth: true + } + + Rectangle { + width: 24; height: 24; radius: 7 + color: rotDecMouse.containsMouse + ? (rotDecMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) + : (t.cryptoFieldBg) + Behavior on color { ColorAnimation { duration: 100 } } + Text { anchors.centerIn: parent; text: "−"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText } + MouseArea { + id: rotDecMouse + anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor + onClicked: if (root.localRotateSec > 1) root.localRotateSec -= 1 + } + } + + Rectangle { + width: 54; height: 24; radius: 6 + color: rotateInput.activeFocus ? (t.cryptoFieldBgFocus) : (t.cryptoFieldBg) + border.color: rotateInput.activeFocus ? (t.accent) : "transparent" + border.width: 1 + Behavior on color { ColorAnimation { duration: 120 } } + Behavior on border.color { ColorAnimation { duration: 120 } } + + TextInput { + id: rotateInput + anchors { fill: parent; leftMargin: 6; rightMargin: 6; topMargin: 4; bottomMargin: 4 } + text: root.localRotateSec.toString() + color: t.cryptoPopupText + font.pixelSize: 12 + font.bold: true + font.family: "monospace" + selectionColor: t.accent + horizontalAlignment: TextInput.AlignHCenter + inputMethodHints: Qt.ImhDigitsOnly + validator: IntValidator { bottom: 1; top: 600 } + clip: true + + onActiveFocusChanged: if (!activeFocus) { + const v = parseInt(text) + if (!isNaN(v) && v >= 1 && v <= 600) + root.localRotateSec = v + else + text = root.localRotateSec.toString() + } + onAccepted: { + const v = parseInt(text) + if (!isNaN(v) && v >= 1 && v <= 600) + root.localRotateSec = v + else + text = root.localRotateSec.toString() + focus = false + } + + Connections { + target: root + function onLocalRotateSecChanged() { + if (!rotateInput.activeFocus) + rotateInput.text = root.localRotateSec.toString() + } + } + } + } + + Rectangle { + width: 24; height: 24; radius: 7 + color: rotIncMouse.containsMouse + ? (rotIncMouse.pressed ? (t.accent) : (t.cryptoFieldBgFocus)) + : (t.cryptoFieldBg) + Behavior on color { ColorAnimation { duration: 100 } } + Text { anchors.centerIn: parent; text: "+"; font.pixelSize: 14; font.bold: true; color: t.cryptoPopupText } + MouseArea { + id: rotIncMouse + anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor + onClicked: if (root.localRotateSec < 600) root.localRotateSec += 1 + } + } + } + ToggleRow { label: "Show icon on bar" checked: root.localShowIcon @@ -1047,9 +1415,7 @@ ModuleChip { id: applyMouse anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor onClicked: { - root.price = -1 root.activeCoinIndex = 0 - root.coinSymbol = root.localCoinId.toUpperCase().slice(0, 4) root.persistSettings() root.fetchPrice() cryptoPopup.activeTab = 0 @@ -1057,30 +1423,6 @@ ModuleChip { } } - Text { - Layout.alignment: Qt.AlignHCenter - text: "Reset to defaults" - color: t.cryptoPopupDim - font.pixelSize: 11 - font.underline: true - - MouseArea { - anchors.fill: parent; cursorShape: Qt.PointingHandCursor - onClicked: { - root.localPairs = Array.isArray(cfg.cryptoPairs) && cfg.cryptoPairs.length > 0 ? cfg.cryptoPairs : [{ coin: "bitcoin", currency: "usd" }] - root.localVsCur = "usd" - root.displayCurrency = root.localPairs.length > 0 ? root.localPairs[0].currency : "usd" - root.activeCoinIndex = 0 - root.localDecimals = cfg.cryptoDecimals - root.localRefreshSec = cfg.cryptoRefreshSec - root.localShowIcon = cfg.cryptoShowIcon - root.persistSettings() - root.price = -1 - cryptoPopup.activeTab = 0 - } - } - } - Item { height: 2 } } } diff --git a/bar/modules/Network.qml b/bar/modules/Network.qml index b411e1c..2f3a9da 100644 --- a/bar/modules/Network.qml +++ b/bar/modules/Network.qml @@ -306,7 +306,7 @@ ModuleChip { Layout.fillWidth: true height: 50 - radius: 10 + radius: 8 color: { var active = modelData.connected || false if (active) return root.t.netApActiveBg @@ -407,7 +407,7 @@ ModuleChip { visible: root.wifiUp Layout.fillWidth: true Layout.topMargin: 4 - height: 36; radius: 10 + height: 36; radius: 8 color: discoHover.hovered ? root.t.netDisconnectBg : "transparent" border.color: root.t.netDisconnectBorder diff --git a/bar/modules/Notifications.qml b/bar/modules/Notifications.qml index 4cba989..67f40bd 100644 --- a/bar/modules/Notifications.qml +++ b/bar/modules/Notifications.qml @@ -186,7 +186,7 @@ ModuleChip { Rectangle { Layout.alignment: Qt.AlignVCenter - width: 20; height: 20; radius: 10 + width: 20; height: 20; radius: 8 color: closeHover.hovered ? toastRoot.t.notifHistoryHover : "transparent" Behavior on color { ColorAnimation { duration: 100 } } @@ -298,9 +298,9 @@ ModuleChip { } Rectangle { - anchors { right: parent.right; top: parent.top; margins: 6 } - width: 18; height: 18; radius: 9 - color: histCloseHover.hovered ? histRoot.t.notifHistoryHover : "transparent" + anchors { right: parent.right; top: parent.top; margins: 6 } + width: 18; height: 18; radius: 8 + color: histCloseHover.hovered ? histRoot.t.notifHistoryHover : "transparent" opacity: histItemHover.hovered ? 1 : 0 Behavior on opacity { NumberAnimation { duration: 150 } } Behavior on color { ColorAnimation { duration: 150 } } @@ -611,7 +611,7 @@ ModuleChip { Layout.alignment: Qt.AlignVCenter width: dndRow.implicitWidth + 16 height: 24 - radius: 12 + radius: 8 color: root.doNotDisturb ? Qt.rgba(t.notifDnd.r, t.notifDnd.g, t.notifDnd.b, 0.18) : (dndHover.hovered ? t.notifHistoryHover : "transparent") @@ -653,7 +653,7 @@ ModuleChip { Layout.alignment: Qt.AlignVCenter width: clearText.implicitWidth + 16 height: 24 - radius: 12 + radius: 8 color: clearHover.hovered ? t.notifHistoryHover : "transparent" Behavior on color { ColorAnimation { duration: 150 } } diff --git a/bar/modules/Stats.qml b/bar/modules/Stats.qml index 8848a8c..a9d5300 100644 --- a/bar/modules/Stats.qml +++ b/bar/modules/Stats.qml @@ -28,6 +28,8 @@ ModuleChip { property real cpuVal: 0 property real memVal: 0 property real diskVal: 0 + property real cpuTemp: -1 + property real gpuTemp: -1 Timer { interval: 2000 @@ -39,7 +41,20 @@ ModuleChip { Process { id: statsProc - command: ["sh", "-c", "top -bn1 | awk '/^%Cpu/ {print 100-$8}'; free | awk '/Mem:/ {print ($2-$7)/$2 * 100}'; df / --output=pcent | tail -1 | tr -dc '0-9'"] + command: ["sh", "-c", + "top -bn1 | awk '/^%Cpu/ {print 100-$8}'; " + + "free | awk '/Mem:/ {print ($2-$7)/$2 * 100}'; " + + "df / --output=pcent | tail -1 | awk '{print $1}'; " + + "ct=-1; for d in /sys/class/hwmon/hwmon*; do " + + "n=$(cat $d/name 2>/dev/null); " + + "if echo \"$n\" | grep -qiE 'coretemp|k10temp|cpu_thermal'; then " + + "ct=$(( $(cat $d/temp1_input 2>/dev/null) / 1000 )); break; " + + "fi; done; echo $ct; " + + "gt=-1; for d in /sys/class/hwmon/hwmon*; do " + + "n=$(cat $d/name 2>/dev/null); " + + "if echo \"$n\" | grep -qiE 'amdgpu|radeon'; then " + + "gt=$(( $(cat $d/temp1_input 2>/dev/null) / 1000 )); break; " + + "fi; done; echo $gt"] property string rawOutput: "" stdout: SplitParser { onRead: data => { statsProc.rawOutput += data + "\n" } @@ -47,10 +62,12 @@ ModuleChip { onRunningChanged: { if (!statsProc.running && statsProc.rawOutput) { const lines = statsProc.rawOutput.trim().split("\n") - if (lines.length >= 3) { + if (lines.length >= 5) { let v = parseFloat(lines[0]); root.cpuVal = isNaN(v) ? 0 : v v = parseFloat(lines[1]); root.memVal = isNaN(v) ? 0 : v v = parseFloat(lines[2]); root.diskVal = isNaN(v) ? 0 : v + v = parseFloat(lines[3]); root.cpuTemp = isNaN(v) ? -1 : v + v = parseFloat(lines[4]); root.gpuTemp = isNaN(v) ? -1 : v } statsProc.rawOutput = "" } @@ -63,9 +80,11 @@ ModuleChip { property real value: 0.0 property string icon: "" + property string label: "" property real iconXOff: 0 property color ringColor: Cfg.Config.theme.accent property color trackColor: Cfg.Config.theme.statsTrackColor + property string labelSuffix:"%" Behavior on value { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } @@ -75,7 +94,7 @@ ModuleChip { Text { id: leftPct - text: Math.round(ring.value) + "%" + text: Math.round(ring.value) + ring.labelSuffix color: ring.ringColor font.pixelSize: Cfg.Config.statsRingFontSize font.bold: true @@ -148,7 +167,7 @@ ModuleChip { Text { id: rightPct - text: Math.round(ring.value) + "%" + text: Math.round(ring.value) + ring.labelSuffix color: ring.ringColor font.pixelSize: Cfg.Config.statsRingFontSize font.bold: true @@ -171,25 +190,51 @@ ModuleChip { spacing: 8 StatRing { + visible: Cfg.Config.statsShowCpu value: root.cpuVal icon: "󰍛" + label: "CPU" iconXOff: 0.3 ringColor: root.t.statsCpuColor trackColor: root.t.statsTrackColor } StatRing { + visible: Cfg.Config.statsShowMem value: root.memVal icon: "󰑭" + label: "RAM" ringColor: root.t.statsMemColor trackColor: root.t.statsTrackColor } StatRing { + visible: Cfg.Config.statsShowDisk value: root.diskVal icon: "󰒋" + label: "DISK" ringColor: root.t.statsDiskColor trackColor: root.t.statsTrackColor } + + StatRing { + visible: Cfg.Config.statsShowCpuTemp && root.cpuTemp >= 0 + value: root.cpuTemp + icon: "󰔄" + label: "CPU°C" + ringColor: root.t.statsCpuTempColor + trackColor: root.t.statsTrackColor + labelSuffix: "°C" + } + + StatRing { + visible: Cfg.Config.statsShowGpuTemp && root.gpuTemp >= 0 + value: root.gpuTemp + icon: "󰾲" + label: "GPU°C" + ringColor: root.t.statsGpuColor + trackColor: root.t.statsTrackColor + labelSuffix: "°C" + } } } diff --git a/bar/modules/Tray.qml b/bar/modules/Tray.qml index f95163a..3307809 100644 --- a/bar/modules/Tray.qml +++ b/bar/modules/Tray.qml @@ -247,7 +247,7 @@ ModuleChip { visible: !isSep anchors.fill: parent anchors.margins: 2 - radius: 10 + radius: 8 readonly property bool active: menuMouse.containsMouse || (submenuCard.visible && trayMenuPopup._submenuParentRef === menuItem) diff --git a/bar/modules/Volume.qml b/bar/modules/Volume.qml index 30f5986..35c3a45 100644 --- a/bar/modules/Volume.qml +++ b/bar/modules/Volume.qml @@ -165,7 +165,7 @@ ModuleChip { Rectangle { id: volCard width: parent.width - height: popupCol.implicitHeight + 32 + height: popupCol.implicitHeight + 30 anchors.top: root.isTop ? parent.top : undefined anchors.bottom: root.isTop ? undefined : parent.bottom @@ -196,8 +196,8 @@ ModuleChip { id: popupCol anchors { left: parent.left; right: parent.right; top: parent.top } anchors.margins: 16 - anchors.topMargin: 18 - spacing: 14 + anchors.topMargin: 16 + spacing: 16 VolumeSection { id: outputSection @@ -251,7 +251,7 @@ ModuleChip { Text { text: "Volume Limits" color: root.t.textDim - font.pixelSize: 10 + font.pixelSize: 11 font.bold: true font.capitalization: Font.AllUppercase Layout.fillWidth: true @@ -292,14 +292,14 @@ ModuleChip { onIncrement: root.inputMaxVolume = Math.min(300, root.inputMaxVolume + 10) } } - Item { height: 2 } + Item { height: 0 } } } } component VolumeSection: ColumnLayout { id: vs - spacing: 8 + spacing: 11 required property string label required property string icon required property color iconColor @@ -336,7 +336,7 @@ ModuleChip { Text { text: vs.label color: vs.textColor - font.pixelSize: 13 + font.pixelSize: 14 font.bold: true Layout.fillWidth: true renderType: Text.NativeRendering @@ -344,7 +344,7 @@ ModuleChip { Text { text: vs.muted ? "muted" : vs.volume + "%" color: vs.muted ? vs.dimColor : vs.textColor - font.pixelSize: 12 + font.pixelSize: 13 font.bold: !vs.muted horizontalAlignment: Text.AlignHCenter Layout.preferredWidth: 44 @@ -352,7 +352,7 @@ ModuleChip { } Rectangle { - width: 22; height: 22; radius: 6 + width: 24; height: 24; radius: 8 color: muteHover.hovered ? (vs.muted ? "#33ffffff" : "#22ffffff") : (vs.muted ? root.t.volMuteBg : "transparent") border.color: vs.muted ? vs.accentColor : vs.dimColor border.width: Cfg.Config.popupBorderWidth @@ -372,15 +372,16 @@ ModuleChip { Item { id: sliderItem Layout.fillWidth: true - height: 22 + height: 28 Rectangle { anchors.verticalCenter: parent.verticalCenter - width: parent.width; height: Cfg.Config.volumeSliderHeight; radius: 2 + width: parent.width; height: 6; radius: 3 color: vs.trackColor Rectangle { width: Math.min(parent.width, parent.width * (vs.volume / Math.max(1, vs.maxVolume))) height: parent.height; radius: parent.radius color: vs.muted ? vs.dimColor : vs.accentColor + Behavior on width { NumberAnimation { duration: 60; easing.type: Easing.OutCubic } } } } @@ -427,7 +428,7 @@ ModuleChip { } Rectangle { - width: 20; height: 20; radius: 5 + width: 24; height: 24; radius: 8 color: chevHover.hovered ? "#22ffffff" : "transparent" border.color: vs.pickerOpen ? vs.accentColor : root.t.volPopupBorder border.width: Cfg.Config.popupBorderWidth @@ -502,7 +503,7 @@ ModuleChip { component LimitRow: RowLayout { id: lr - spacing: 8 + spacing: 10 required property string icon required property color iconColor required property string labelText @@ -519,7 +520,7 @@ ModuleChip { signal decrement() signal increment() - Text { text: lr.icon; color: lr.iconColor; font.pixelSize: 13; font.bold: true; renderType: Text.NativeRendering } + Text { text: lr.icon; color: lr.iconColor; font.pixelSize: 16; font.bold: true; renderType: Text.NativeRendering } Text { text: lr.labelText color: lr.textColor @@ -531,7 +532,7 @@ ModuleChip { Rectangle { id: decBtn - width: 22; height: 22; radius: 5 + width: 24; height: 24; radius: 8 color: decMa.containsMouse ? (decMa.pressed ? lr.btnPress : lr.btnHover) : lr.btnIdle @@ -568,7 +569,7 @@ ModuleChip { Rectangle { id: incBtn - width: 22; height: 22; radius: 5 + width: 24; height: 24; radius: 8 color: incMa.containsMouse ? (incMa.pressed ? lr.btnPress : lr.btnHover) : lr.btnIdle diff --git a/components/HoverButton.qml b/components/HoverButton.qml index 57941f0..c89ad18 100644 --- a/components/HoverButton.qml +++ b/components/HoverButton.qml @@ -10,14 +10,18 @@ Rectangle { property color borderHoverColor: "transparent" property real pressScale: 0.97 property int animDuration: 150 + property int btnRadius: 8 + property int btnBorderWidth: 1 readonly property bool hovered: _hover.hovered readonly property bool pressed: _tap.pressed signal clicked() + radius: root.btnRadius color: pressed ? pressColor : (hovered ? hoverColor : idleColor) border.color: hovered ? borderHoverColor : borderIdleColor + border.width: root.btnBorderWidth scale: pressed ? pressScale : 1.0 diff --git a/config/config.qml b/config/config.qml index eed94d4..f5d3538 100644 --- a/config/config.qml +++ b/config/config.qml @@ -6,12 +6,16 @@ import "themes" QtObject { id: root - readonly property var theme: Goldencity + readonly property var theme: Lowlight // ──────────────────────────────────────────────────────────────────────── // Widgets // ──────────────────────────────────────────────────────────────────────── property bool enableBgDate: true + property bool sideBarSysInfo: true + property bool sideBarMpris: true + property bool sideBarWeather: true + property string sideBarPosition: "right" // "left" or "right" property bool enablePolkit: true // ──────────────────────────────────────────────────────────────────────── @@ -19,7 +23,7 @@ QtObject { // ──────────────────────────────────────────────────────────────────────── // ── Position & Dimensions ───────────────────────────────────────────────── - property string barPosition: "bottom" + property string barPosition: "top" property int barHeight: 35 property int margin: 15 property int radius: 20 @@ -70,6 +74,11 @@ QtObject { property string statsLabelPosition: "right" // If true, percentage labels are visible on startup without clicking. property bool statsStartExpanded: false + property bool statsShowCpu: true + property bool statsShowMem: true + property bool statsShowDisk: true + property bool statsShowCpuTemp: true + property bool statsShowGpuTemp: true // ── Volume Module ───────────────────────────────────────────────────────── property bool volumeShakeEnabled: true // rotation shake for volume chip @@ -115,11 +124,11 @@ QtObject { // ──────────────────────────────────────────────────────────────────────── // ── Coin/currency pairs to cycle ────────────────────────────────────────── - // Each entry is a { coin, currency } object. The bar chip rotates to the - // next pair after each successful CoinGecko fetch. + // Each entry is a { coin, currency } object. The bar chip fetches one pair + // per timer tick and auto-rotates to the next after each successful fetch. // - // coin – CoinGecko coin ID (find them at https://api.coingecko.com/api/v3/coins/list) - // currency – any quote currency CoinGecko supports: "usd", "eur", "brl", "btc", … + // coin – CoinGecko coin ID, e.g. "bitcoin", "monero", "solana" + // currency – quote currency: "usd", "eur", "brl", "btc", "eth", … // // Single pair → [{ coin: "bitcoin", currency: "usd" }] // Three pairs → [{ coin: "bitcoin", currency: "usd" }, @@ -128,7 +137,7 @@ QtObject { // // This list is the *default*; pairs can be added/removed live in the // Settings popup and those changes are persisted across restarts. - property var cryptoPairs: [{ coin: "bitcoin", currency: "usd" }, { coin: "ethereum", currency: "eur" }, { coin: "monero", 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" }] // ── Compact label decimals ──────────────────────────────────────────────── // 0 → "80k" @@ -137,12 +146,22 @@ QtObject { property int cryptoDecimals: 2 // ── Poll interval ───────────────────────────────────────────────────────── - // Seconds between CoinGecko requests. Free tier allows ~30 req/min. - // With multiple pairs each refresh fetches one pair then advances the index, - // so the effective per-pair interval is: cryptoRefreshSec × cryptoPairs.length + // Seconds between CoinGecko requests. Each tick fetches one pair + // and advances to the next in the cycle. Free tier allows ~30 req/min. property int cryptoRefreshSec: 120 + // ── Bar rotate interval ──────────────────────────────────────────────────── + // Seconds between auto-rotating the displayed pair. 0 = disabled. + // Uses cached data (no API call), instant switching. + property int cryptoRotateSec: 10 + // ── Bar chip icon ───────────────────────────────────────────────────────── // Show the coin icon glyph ("󰿤") on the bar chip. property bool cryptoShowIcon: true + + // ──────────────────────────────────────────────────────────────────────── + // WEATHER + // ──────────────────────────────────────────────────────────────────────── + property string weatherLocation: "" // city name, e.g. "London" or "New+York"; empty → auto-detect from IP + property int weatherRefreshMin: 30 // update interval in minutes } diff --git a/config/themes/aero.qml b/config/themes/aero.qml index a1ecb6d..4b037b9 100644 --- a/config/themes/aero.qml +++ b/config/themes/aero.qml @@ -36,6 +36,21 @@ QtObject { 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 (Aurora Tones) ─────────────────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -43,7 +58,20 @@ QtObject { readonly property color statsMemColor: "#4db6ac" // Teal readonly property color statsDiskColor: "#81d4fa" // Sky blue readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ff7986cb" // Soft indigo + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Glass Water) ─────────────────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#2281c7c7" @@ -133,6 +161,15 @@ QtObject { readonly property color clockPopupText: textMain readonly property color clockPopupDim: textDim + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/aurora.qml b/config/themes/aurora.qml index 846e124..36cd15f 100644 --- a/config/themes/aurora.qml +++ b/config/themes/aurora.qml @@ -36,6 +36,21 @@ QtObject { 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: Cosmic Cyan) ────────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -43,7 +58,20 @@ QtObject { readonly property color statsMemColor: "#ffbc7fff" // Trail violet readonly property color statsDiskColor: "#ff7fbaff" // Sky blue readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ffa6e3a1" // Aurora green + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Comet Purple) ──────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#223d4e6d" @@ -133,6 +161,15 @@ QtObject { readonly property color clockPopupText: textMain readonly property color clockPopupDim: textDim + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/autumn.qml b/config/themes/autumn.qml index 9924a87..c6a7e0f 100644 --- a/config/themes/autumn.qml +++ b/config/themes/autumn.qml @@ -37,6 +37,21 @@ QtObject { 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: Skyline Pulse) ─────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -44,7 +59,20 @@ QtObject { readonly property color statsMemColor: "#ff8f1018" // Building window blue readonly property color statsDiskColor: "#ff5b6b1f" // Teal office light readonly property color statsTrackColor: "#15f1dfbf" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ffe05230" // Terracotta + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Hazy Dusk) ────────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#33f2b425" @@ -141,6 +169,15 @@ QtObject { readonly property color calArrowBgHover: "#33f2b425" // Hovered button — soft gold tint readonly property color calArrowBgPress: "#ffffa51f" // Pressed button — full horizon gold + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/beach.qml b/config/themes/beach.qml index 2c94134..80a36a1 100644 --- a/config/themes/beach.qml +++ b/config/themes/beach.qml @@ -36,6 +36,21 @@ QtObject { 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: Shoreline Tones) ────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -43,7 +58,20 @@ QtObject { readonly property color statsMemColor: "#ff8fa3b0" // Ocean mist readonly property color statsDiskColor: "#ffc2d1d9" // Bright sky blue readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ffe5c687" // Warm sand gold + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Deep Water) ────────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#224a5d6e" @@ -133,6 +161,15 @@ QtObject { readonly property color clockPopupText: textMain readonly property color clockPopupDim: textDim + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/boat.qml b/config/themes/boat.qml index fbd5d92..8857899 100644 --- a/config/themes/boat.qml +++ b/config/themes/boat.qml @@ -37,6 +37,21 @@ QtObject { 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: Crimson Horizon Pulse) ─────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -44,7 +59,20 @@ QtObject { readonly property color statsMemColor: "#ff4e618d" // Twilight sky deep blue readonly property color statsDiskColor: "#fffca352" // Warm cabin lamp glow readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ff3a7ca5" // Ocean blue + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Lone Boat Dusk) ───────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#22614d4a" @@ -141,6 +169,15 @@ QtObject { readonly property color calArrowBgHover: "#22e0533c" // Soft sunset tint readonly property color calArrowBgPress: "#ffe0533c" + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/colorful.qml b/config/themes/colorful.qml index b04f098..f41d2e4 100644 --- a/config/themes/colorful.qml +++ b/config/themes/colorful.qml @@ -36,6 +36,21 @@ QtObject { 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: Alpenglow) ──────────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -43,7 +58,20 @@ QtObject { readonly property color statsMemColor: "#ffffcc99" // Horizon orange readonly property color statsDiskColor: "#ff8da0c4" // Water blue readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ffb3e59f" // Mint green + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Frozen Lake) ───────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#224a566e" @@ -133,6 +161,15 @@ QtObject { readonly property color clockPopupText: textMain readonly property color clockPopupDim: textDim + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" @@ -240,6 +277,12 @@ QtObject { readonly property color cryptoPopupText: textMain readonly property color cryptoPopupDim: textDim + readonly property color cryptoFieldBg: "#15ffffff" + readonly property color cryptoFieldBgFocus: "#22ffffff" + readonly property color cryptoRangeTrack: "#1affffff" + readonly property color cryptoTextOnAccent: "#ff0c0e12" + readonly property color cryptoPlaceholder: Qt.rgba(textDim.r, textDim.g, textDim.b, 0.33) + // Tinted surfaces (derived from main colours) 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) diff --git a/config/themes/cosmic.qml b/config/themes/cosmic.qml index b3de876..8d6a9d5 100644 --- a/config/themes/cosmic.qml +++ b/config/themes/cosmic.qml @@ -36,6 +36,21 @@ QtObject { 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: Comet Trail) ────────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -43,7 +58,20 @@ QtObject { readonly property color statsMemColor: "#ffcfb3ff" // Nebula purple readonly property color statsDiskColor: "#ffffc2e0" // Horizon pink readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ffffb8d0" // Cosmic pink + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Nebula Purple) ─────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#224a527a" @@ -133,6 +161,15 @@ QtObject { readonly property color clockPopupText: textMain readonly property color clockPopupDim: textDim + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/everforest.qml b/config/themes/everforest.qml index a6b0e5c..2d5ef66 100644 --- a/config/themes/everforest.qml +++ b/config/themes/everforest.qml @@ -9,26 +9,27 @@ QtObject { readonly property string wallpaper: Quickshell.env("HOME") + "/.config/quickshell/wallpapers/wallpaper.jpg" // ── Base Backgrounds ─────────────────────────────────────────────────────── - readonly property color bg: "#aa0a1410" + readonly property color bg: "#cc070e08" // Near-black deep forest shadow readonly property color bgPanel: "transparent" - readonly property color bgPopup: bg + readonly property color bgPopup: "#cc070e08" // Deep undergrowth dark readonly property color bgFrame: bg // ── Separators ──────────────────────────────────────────────────────────── - readonly property color separator: "#33ffffff" + readonly property color separator: "#33284038" // Dark muted forest green // ── Text ────────────────────────────────────────────────────────────────── - readonly property color textMain: "#ffdce3de" - readonly property color textDim: "#d97a9480" + readonly property color textMain: "#ffe8f0ea" // Cool near-white (droplet highlight) + readonly property color textDim: "#997a9080" // Muted sage-gray readonly property color todayText: "#ffffffff" // ── Accent & Borders ────────────────────────────────────────────────────── - readonly property color accent: "#ff4a8c5c" + readonly property color accent: "#ff4a8c5c" // Muted forest green readonly property color border: "transparent" - readonly property color borderPopup: "#ff2d4032" + readonly property color frameBorder: "transparent" + readonly property color borderPopup: "transparent" readonly property color borderToday: accent - // ── ArchLogo Module ──────────────────────────────────────────────────────── + // ── Logo Module ──────────────────────────────────────────────────────── readonly property color logoBg: bgPanel readonly property color logoBgHover: "#22ffffff" readonly property color logoBorder: border @@ -36,32 +37,62 @@ QtObject { readonly property color logoIcon: textMain readonly property color logoIconActive: accent - // ── Stats Module ─────────────────────────────────────────────────────────── - readonly property color statsBg: bgPanel - readonly property color statsBorder: border - readonly property color statsCpuColor: "#ff83c092" - readonly property color statsMemColor: "#ff83c092" - readonly property color statsDiskColor: "#ff83c092" - readonly property color statsTrackColor: "#28ffffff" - // ── Volume Module ────────────────────────────────────────────────────────── + // ── 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: Forest Floor) ──────────────────────────────── + readonly property color statsBg: bgPanel + readonly property color statsBorder: border + readonly property color statsCpuColor: "#ffc07848" // Warm amber (earth/stem) + readonly property color statsMemColor: "#ff4a8c5c" // Muted forest green + readonly property color statsDiskColor: "#ff78a870" // Mid sage green + readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#ffcc6a40" // Warm orange-red + readonly property color statsGpuColor: "#ff50a898" // Cool aqua (droplet reflection) + + + // ── 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: Rain on Leaves) ───────────────────────────── readonly property color volBg: bgPanel - readonly property color volBgHover: "#22ffffff" + readonly property color volBgHover: "#22284038" readonly property color volBorder: border - readonly property color volBorderHover: accent + readonly property color volBorderHover: "#ff50a898" readonly property color volPopupBg: bgPopup readonly property color volPopupBorder: borderPopup - readonly property color volIcon: textMain - readonly property color volIconMuted: textDim + readonly property color volIcon: "#ff50a898" // Cool aqua + readonly property color volIconMuted: "#ff3a5040" readonly property color volTrack: "#22ffffff" readonly property color volHandle: accent readonly property color volHandleBorder: "#33ffffff" - readonly property color volMuteBg: "#22ffffff" - readonly property color volPickerHover: "#15ffffff" + readonly property color volMuteBg: "#33a85838" + readonly property color volPickerHover: "#154a8c5c" // ── Volume Limit Buttons ──────────────────────────────────────────────── readonly property color volLimitBtn: "transparent" - readonly property color volLimitBtnHover: "#22ffffff" + readonly property color volLimitBtnHover: "#224a8c5c" readonly property color volLimitBtnPress: accent readonly property color volOutputLimitBtnPress: accent readonly property color volInputLimitBtnPress: statusInfo @@ -70,12 +101,12 @@ QtObject { // ── Clock Module ─────────────────────────────────────────────────────────── readonly property color clockBg: bgPanel - readonly property color clockBgHover: "#22ffffff" + readonly property color clockBgHover: "#11ffffff" readonly property color clockBorder: border readonly property color clockBorderHover: accent readonly property color clockTime: textMain - readonly property color clockSeconds: textMain - readonly property color clockIcon: textMain + readonly property color clockSeconds: "#ff4a8c5c" // Muted forest green + readonly property color clockIcon: accent // ── Battery Module ──────────────────────────────────────────────────────── readonly property color batteryFull: accent @@ -84,14 +115,14 @@ QtObject { readonly property color batteryLow: statusWarn readonly property color batteryIcon: clockIcon readonly property color batBg: bgPanel - readonly property color batBgHover: "#22ffffff" + 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: accent + readonly property color batPopupHeader: "#ff4a8c5c" readonly property color batPopupText: textMain readonly property color batPopupDim: textDim readonly property color batProgressTrack: separator @@ -99,19 +130,19 @@ QtObject { // ── Network Module ──────────────────────────────────────────────────────── readonly property color netBg: bgPanel - readonly property color netBgHover: "#22ffffff" + 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: accent + readonly property color netPopupHeader: "#ff4a8c5c" readonly property color netPopupText: textMain readonly property color netPopupDim: textDim readonly property color netFieldBg: "#22ffffff" readonly property color netCancelBgHover: "#22ffffff" - readonly property color netConnectText: "#ff0e1410" + readonly property color netConnectText: "#ff070e08" readonly property color netApActiveBg: Qt.alpha(accent, 0.15) readonly property color netApHoverBg: calArrowBgHover readonly property color netDisconnectBg: Qt.alpha(statusErr, 0.18) @@ -120,80 +151,97 @@ QtObject { 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: "#ffa7c080" // moss green, forest canopy - readonly property color netWifiIconErr: "#ffe67e80" // reddish pink, leaf fall - readonly property color netEthIconOk: "#ffa7c080" - readonly property color netEthIconErr: "#ffe67e80" + readonly property color netWifiIconOk: "#ff60a860" // healthy leaf green + readonly property color netWifiIconErr: "#ffcc5858" // warm red + readonly property color netEthIconOk: "#ff60a860" + readonly property color netEthIconErr: "#ffcc5858" // ── Calendar Popup ───────────────────────────────────────────────────────── readonly property color calCardBg: bgPopup readonly property color calCardBorder: borderPopup readonly property color calSeparator: separator - readonly property color clockPopupHeader: accent + readonly property color clockPopupHeader: "#ff4a8c5c" 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: "#ff4a8c5c" // Forest green on hover + readonly property color calArrowBg: "transparent" + readonly property color calArrowBgHover: "#224a8c5c" // Soft green tint + readonly property color calArrowBgPress: "#ff4a8c5c" // Full green on press + + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#ffcc6a40" // Warm amber-red + readonly property color weatherFeelsColor: "#ff78a870" // Mid sage + readonly property color weatherHumidColor: "#ff50a898" // Aqua (water droplets) + readonly property color weatherWindColor: "#ff90b8a8" // Cool pale aqua // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" readonly property color wsActiveBg: accent - readonly property color wsInactiveBg: "#22ffffff" - readonly property color wsHoverBg: borderPopup - readonly property color wsActiveText: "#ff0e1410" + readonly property color wsInactiveBg: "#15ffffff" + readonly property color wsHoverBg: "#33284038" + readonly property color wsActiveText: "#ff070e08" readonly property color wsInactiveText: textMain - readonly property color wsHoverText: wsActiveText + readonly property color wsHoverText: "#ffffffff" // ── Tray Module ──────────────────────────────────────────────────────────── - readonly property color trayBg: clockBg - readonly property color trayBgHover: clockBgHover - readonly property color trayBorder: clockBorder - readonly property color trayBorderHover: clockBorderHover - readonly property color trayIcon: clockIcon + 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: "#224a8c5c" + readonly property color trayMenuHover: "#224a8c5c" // soft green tint readonly property color trayMenuCheck: accent readonly property color trayMenuSeparator: separator - // ── Launcher ─────────────────────────────────────────────────────────────── + // ── Launcher (Variation: Undergrowth) ───────────────────────────────────── readonly property color launcherBg: bgPopup - readonly property color launcherBorder: "#22ffffff" - readonly property color launcherInput: "#330b1210" + readonly property color launcherBorder: borderPopup + readonly property color launcherInput: "#44050b06" readonly property color launcherInputBorderFocus: accent - readonly property color launcherPill: "#4d111a14" + readonly property color launcherPill: "#44284038" readonly property color launcherText: textMain readonly property color launcherDim: textDim readonly property color launcherAccent: accent - readonly property color launcherHover: "#4d2d4032" - readonly property color launcherSelected: launcherHover - readonly property color launcherModeActiveText: todayText + readonly property color launcherHover: "#224a8c5c" + readonly property color launcherSelected: "#444a8c5c" + readonly property color launcherModeActiveText: "#ffffffff" readonly property color launcherModeActiveBg: accent // ── Status Colors ────────────────────────────────────────────────────────── - readonly property color statusOk: "#ffa7c080" - readonly property color statusWarn: "#ffdbbc7f" - readonly property color statusErr: "#ffe67e80" - readonly property color statusInfo: "#ff7fbbb3" + readonly property color statusOk: "#ff60a860" // Healthy leaf green + readonly property color statusWarn: "#ffb88c48" // Amber + readonly property color statusErr: "#ffcc5858" // Warm red + readonly property color statusInfo: "#ff48a0b8" // Cool aqua // ── Notifications Module ─────────────────────────────────────────────────── readonly property color notifBg: bgPanel - readonly property color notifBgHover: "#22ffffff" + 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: "#ff0e1410" + readonly property color notifBadgeText: "#ffffffff" readonly property color notifSeparator: separator readonly property color notifDnd: separator - // ── Toast cards ──────────────────────────────────────────────────────────── + // ── Toast cards (Variation: Canopy Glow) ────────────────────────────────── readonly property color notifToastBg: bgPopup - readonly property color notifToastBgHover: borderPopup + readonly property color notifToastBgHover: "#22ffffff" readonly property color notifToastBorder: borderPopup readonly property color notifToastText: textMain readonly property color notifToastDim: textDim @@ -201,7 +249,7 @@ QtObject { // ── Urgency colours ──────────────────────────────────────────────────────── readonly property color notifUrgencyCritical: statusErr - readonly property color notifUrgencyNormal: statusInfo + readonly property color notifUrgencyNormal: accent readonly property color notifUrgencyLow: textDim // ── Progress bar ─────────────────────────────────────────────────────────── @@ -211,36 +259,35 @@ QtObject { // ── History popup ────────────────────────────────────────────────────────── readonly property color notifHistoryBg: bgPopup readonly property color notifHistoryBorder: borderPopup - readonly property color notifHistoryHover: "#22ffffff" + readonly property color notifHistoryHover: "#114a8c5c" readonly property color notifHistoryEmpty: textDim - // new variables adapted - readonly property color frameBorder: "transparent" - readonly property color clockPopupDate: textMain - readonly property color clockPopupUtc: textDim - readonly property color calArrowIcon: textDim - readonly property color calArrowIconHover: accent - readonly property color calArrowBg: "transparent" - readonly property color calArrowBgHover: "#224a8c5c" - readonly property color calArrowBgPress: accent + // ── BgDate Module ────────────────────────────────────────────────────────── + readonly property color bgDateText: "#ffffffff" + readonly property color bgDateShadow: "#88000000" + 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: statusOk - readonly property color cryptoDown: statusErr + + readonly property color cryptoUp: "#ff60a860" // leaf green + readonly property color cryptoDown: "#ffcc5858" // warm red + + // Popup card readonly property color cryptoPopupBg: bgPopup readonly property color cryptoPopupBorder: borderPopup - readonly property color cryptoPopupHeader: accent + readonly property color cryptoPopupHeader: "#ff4a8c5c" readonly property color cryptoPopupText: textMain readonly property color cryptoPopupDim: textDim - // Tinted surfaces (derived from main colours) + // 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) @@ -249,78 +296,72 @@ QtObject { readonly property color cryptoFieldBg: "#15ffffff" readonly property color cryptoFieldBgFocus: "#22ffffff" readonly property color cryptoRangeTrack: "#1affffff" - readonly property color cryptoTextOnAccent: "#ff0e1410" + readonly property color cryptoTextOnAccent: "#ff070e08" readonly property color cryptoPlaceholder: Qt.rgba(textDim.r, textDim.g, textDim.b, 0.33) - // ── BgDate Module ────────────────────────────────────────────────────────── - readonly property color bgDateText: textMain - readonly property color bgDateShadow: "#44000000" - readonly property color bgDateSecondsText: textMain - // ── Polkit Dialog ────────────────────────────────────────────────────────── // Overlay readonly property color polkitOverlayBg: "#bb000000" // Card chrome readonly property color polkitCardBg: bgPopup - readonly property color polkitCardBorder: Qt.rgba(accent.r, accent.g, accent.b, 0.16) + readonly property color polkitCardBorder: border // Lock icon - readonly property color polkitIconBg: Qt.rgba(accent.r, accent.g, accent.b, 0.12) - readonly property color polkitIconBorder: Qt.rgba(accent.r, accent.g, accent.b, 0.27) + readonly property color polkitIconBg: "#1e4a8c5c" // translucent green fill + readonly property color polkitIconBorder: "#444a8c5c" // stronger green ring readonly property color polkitIconColor: accent // Text hierarchy readonly property color polkitTitle: textMain - readonly property color polkitMessage: textMain + readonly property color polkitMessage: "#cce8f0ea" // Action-ID pill - readonly property color polkitPillBg: Qt.rgba(textDim.r, textDim.g, textDim.b, 0.10) - readonly property color polkitPillText: textDim + readonly property color polkitPillBg: "#1a284038" + readonly property color polkitPillText: "#667a9080" // Divider - readonly property color polkitDivider: separator + readonly property color polkitDivider: "#33284038" // Supplementary message — error state - readonly property color polkitSuppErrBg: Qt.rgba(statusErr.r, statusErr.g, statusErr.b, 0.10) - readonly property color polkitSuppErrBorder: Qt.rgba(statusErr.r, statusErr.g, statusErr.b, 0.27) + readonly property color polkitSuppErrBg: "#1acc6858" + readonly property color polkitSuppErrBorder: "#44cc6858" readonly property color polkitSuppErrText: statusErr // Supplementary message — info / ok state - readonly property color polkitSuppOkBg: Qt.rgba(statusOk.r, statusOk.g, statusOk.b, 0.10) - readonly property color polkitSuppOkBorder: Qt.rgba(statusOk.r, statusOk.g, statusOk.b, 0.27) + readonly property color polkitSuppOkBg: "#1a6ab85a" + readonly property color polkitSuppOkBorder: "#446ab85a" readonly property color polkitSuppOkText: statusOk - // Fields (password input & identity selector) - readonly property color polkitFieldBg: launcherInput + // Fields + readonly property color polkitFieldBg: "#44040a05" readonly property color polkitFieldBorder: "#22ffffff" readonly property color polkitFieldBorderFocus: accent // Identity selector text - readonly property color polkitUserLabel: textDim + readonly property color polkitUserLabel: "#997a9080" readonly property color polkitUserValue: accent - // Input prompt label above password field - readonly property color polkitInputPrompt: textDim + // Input prompt label + readonly property color polkitInputPrompt: "#887a9080" - // TextInput inside password field + // TextInput readonly property color polkitInputText: textMain - readonly property color polkitInputSelection: Qt.rgba(accent.r, accent.g, accent.b, 0.33) + readonly property color polkitInputSelection: "#554a8c5c" // green selection readonly property color polkitInputSelectedText: bg - // Eye / show-password toggle - readonly property color polkitEyeIcon: textDim + // Eye toggle + readonly property color polkitEyeIcon: "#667a9080" readonly property color polkitEyeIconHover: accent // Authenticate button - readonly property color polkitAuthBg: accent - readonly property color polkitAuthBgHover: Qt.lighter(accent, 1.15) + readonly property color polkitAuthBg: "#dd4a8c5c" // slightly-muted green fill + readonly property color polkitAuthBgHover: accent readonly property color polkitAuthText: bg // Cancel button - readonly property color polkitCancelBg: "transparent" + readonly property color polkitCancelBg: "#0dffffff" readonly property color polkitCancelBgHover: "#22ffffff" readonly property color polkitCancelBorder: "#22ffffff" - readonly property color polkitCancelText: textDim + readonly property color polkitCancelText: "#cce8f0ea" } - diff --git a/config/themes/goldencity.qml b/config/themes/goldencity.qml index b932f8d..9c8a4d1 100644 --- a/config/themes/goldencity.qml +++ b/config/themes/goldencity.qml @@ -37,6 +37,22 @@ QtObject { 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: Skyline Pulse) ─────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -44,7 +60,20 @@ QtObject { readonly property color statsMemColor: "#ff89b4fa" // Building window blue readonly property color statsDiskColor: "#ff94e2d5" // Teal office light readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ffcba6f7" // Soft lavender + + // ── 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: "#fff38ba8" + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Hazy Dusk) ────────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#224a5d6e" @@ -140,6 +169,15 @@ QtObject { readonly property color calArrowBgHover: "#22c19375" // Hovered button — soft gold tint readonly property color calArrowBgPress: "#ffc19375" // Pressed button — full horizon gold + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" @@ -204,11 +242,11 @@ QtObject { readonly property color notifToastBorder: borderPopup readonly property color notifToastText: textMain readonly property color notifToastDim: textDim - readonly property color notifToastAppName: "#ff89b4fa" + readonly property color notifToastAppName: accent // ── Urgency colours ──────────────────────────────────────────────────────── readonly property color notifUrgencyCritical: statusErr - readonly property color notifUrgencyNormal: statusInfo + readonly property color notifUrgencyNormal: accent readonly property color notifUrgencyLow: textDim // ── Progress bar ─────────────────────────────────────────────────────────── diff --git a/config/themes/hummingbird.qml b/config/themes/hummingbird.qml index bde3a11..c9392ac 100644 --- a/config/themes/hummingbird.qml +++ b/config/themes/hummingbird.qml @@ -37,6 +37,21 @@ QtObject { 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: Canopy Pulse) ─────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -44,7 +59,20 @@ QtObject { readonly property color statsMemColor: "#ff8bc34a" // Bright green readonly property color statsDiskColor: "#ff90caf9" // Bokeh sky blue readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ffff7043" // Deep orange + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Forest Echo) ────────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#222e7d32" @@ -141,6 +169,15 @@ QtObject { readonly property color calArrowBgHover: "#22ff5722" readonly property color calArrowBgPress: "#ffff5722" + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/lowlight.qml b/config/themes/lowlight.qml new file mode 100644 index 0000000..05bbdd3 --- /dev/null +++ b/config/themes/lowlight.qml @@ -0,0 +1,367 @@ +pragma Singleton +import QtQuick +import Quickshell + +QtObject { + id: theme + + // ── Wallpaper ────────────────────────────────────────────────────────────── + readonly property string wallpaper: Quickshell.env("HOME") + "/.config/quickshell/wallpapers/lowlight.jpg" + + // ── Base Backgrounds ─────────────────────────────────────────────────────── + readonly property color bg: "#cc07091c" // Near-black mountain silhouette + readonly property color bgPanel: "transparent" + readonly property color bgPopup: "#cc07091c" // Deep night shadow + readonly property color bgFrame: bg + + // ── Separators ──────────────────────────────────────────────────────────── + readonly property color separator: "#33203060" // Deep navy-blue + + // ── Text ────────────────────────────────────────────────────────────────── + readonly property color textMain: "#ffe8eef8" // Star-white + readonly property color textDim: "#996878a0" // Muted midnight blue-gray + readonly property color todayText: "#ffffffff" + + // ── Accent & Borders ────────────────────────────────────────────────────── + readonly property color accent: "#ffb068d8" // Mauve horizon glow + readonly property color border: "transparent" + readonly property color frameBorder: "transparent" + readonly property color borderPopup: "transparent" + readonly property color borderToday: accent + + // ── 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: Starfield) ─────────────────────────────────── + readonly property color statsBg: bgPanel + readonly property color statsBorder: border + readonly property color statsCpuColor: "#ffc870d0" // Soft violet-pink (horizon bloom) + readonly property color statsMemColor: "#ff5090e0" // Mid-sky cobalt blue + readonly property color statsDiskColor: "#ff4878c8" // Steel night blue + readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#ffcc60a8" // Deep rose-pink + readonly property color statsGpuColor: "#ffb898e8" // Pale lavender (star haze) + + + // ── 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: Dusk Signal) ──────────────────────────────── + readonly property color volBg: bgPanel + readonly property color volBgHover: "#22203060" + readonly property color volBorder: border + readonly property color volBorderHover: "#ff5090e0" + readonly property color volPopupBg: bgPopup + readonly property color volPopupBorder: borderPopup + readonly property color volIcon: "#ff5090e0" // Sky cobalt + readonly property color volIconMuted: "#ff304068" + readonly property color volTrack: "#22ffffff" + readonly property color volHandle: accent + readonly property color volHandleBorder: "#33ffffff" + readonly property color volMuteBg: "#33cc60a8" + readonly property color volPickerHover: "#15b068d8" + + // ── Volume Limit Buttons ──────────────────────────────────────────────── + readonly property color volLimitBtn: "transparent" + readonly property color volLimitBtnHover: "#22b068d8" + 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: "#ffb068d8" // Mauve horizon + 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: "#ffb068d8" + 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: "#ffb068d8" + readonly property color netPopupText: textMain + readonly property color netPopupDim: textDim + readonly property color netFieldBg: "#22ffffff" + readonly property color netCancelBgHover: "#22ffffff" + readonly property color netConnectText: "#ff07091c" + 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: "#ff60b8a0" // soft teal-green + readonly property color netWifiIconErr: "#ffcc6888" // muted rose + readonly property color netEthIconOk: "#ff60b8a0" + readonly property color netEthIconErr: "#ffcc6888" + + // ── Calendar Popup ───────────────────────────────────────────────────────── + readonly property color calCardBg: bgPopup + readonly property color calCardBorder: borderPopup + readonly property color calSeparator: separator + readonly property color clockPopupHeader: "#ffb068d8" + 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: "#ffb068d8" // Mauve on hover + readonly property color calArrowBg: "transparent" + readonly property color calArrowBgHover: "#22b068d8" // Soft mauve tint + readonly property color calArrowBgPress: "#ffb068d8" // Full mauve on press + + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#ffcc60a8" // Deep rose-pink + readonly property color weatherFeelsColor: "#ffb898e8" // Pale lavender + readonly property color weatherHumidColor: "#ff5090e0" // Cobalt sky + readonly property color weatherWindColor: "#ff90b8e8" // Pale sky blue + + // ── 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: "#33203060" + readonly property color wsActiveText: "#ff07091c" + readonly property color wsInactiveText: textMain + readonly property color wsHoverText: "#ffffffff" + + // ── 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: "#22b068d8" // soft mauve tint + readonly property color trayMenuCheck: accent + readonly property color trayMenuSeparator: separator + + // ── Launcher (Variation: Night Summit) ──────────────────────────────────── + readonly property color launcherBg: bgPopup + readonly property color launcherBorder: borderPopup + readonly property color launcherInput: "#44050718" + readonly property color launcherInputBorderFocus: accent + readonly property color launcherPill: "#44203060" + readonly property color launcherText: textMain + readonly property color launcherDim: textDim + readonly property color launcherAccent: accent + readonly property color launcherHover: "#22b068d8" + readonly property color launcherSelected: "#44b068d8" + readonly property color launcherModeActiveText: "#ffffffff" + readonly property color launcherModeActiveBg: accent + + // ── Status Colors ────────────────────────────────────────────────────────── + readonly property color statusOk: "#ff60b8a0" // Soft teal-green + readonly property color statusWarn: "#ffb89060" // Warm amber + readonly property color statusErr: "#ffcc6888" // Muted rose + readonly property color statusInfo: "#ff60a0e0" // 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: Horizon Bloom) ──────────────────────────────── + 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: "#11b068d8" + readonly property color notifHistoryEmpty: textDim + + // ── BgDate Module ────────────────────────────────────────────────────────── + readonly property color bgDateText: "#ffffffff" + readonly property color bgDateShadow: "#88000000" + 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: "#ff60b8a0" // teal-green + readonly property color cryptoDown: "#ffcc6888" // muted rose + + // Popup card + readonly property color cryptoPopupBg: bgPopup + readonly property color cryptoPopupBorder: borderPopup + readonly property color cryptoPopupHeader: "#ffb068d8" + 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: "#ff07091c" + readonly property color cryptoPlaceholder: Qt.rgba(textDim.r, textDim.g, textDim.b, 0.33) + + // ── Polkit Dialog ────────────────────────────────────────────────────────── + // Overlay + readonly property color polkitOverlayBg: "#bb000000" + + // Card chrome + readonly property color polkitCardBg: bgPopup + readonly property color polkitCardBorder: border + + // Lock icon + readonly property color polkitIconBg: "#1eb068d8" // translucent mauve fill + readonly property color polkitIconBorder: "#44b068d8" // stronger mauve ring + readonly property color polkitIconColor: accent + + // Text hierarchy + readonly property color polkitTitle: textMain + readonly property color polkitMessage: "#cce8eef8" + + // Action-ID pill + readonly property color polkitPillBg: "#1a203060" + readonly property color polkitPillText: "#666878a0" + + // Divider + readonly property color polkitDivider: "#33203060" + + // Supplementary message — error state + readonly property color polkitSuppErrBg: "#1acc6888" + readonly property color polkitSuppErrBorder: "#44cc6888" + readonly property color polkitSuppErrText: statusErr + + // Supplementary message — info / ok state + readonly property color polkitSuppOkBg: "#1a60b8a0" + readonly property color polkitSuppOkBorder: "#4460b8a0" + readonly property color polkitSuppOkText: statusOk + + // Fields + readonly property color polkitFieldBg: "#44040618" + readonly property color polkitFieldBorder: "#22ffffff" + readonly property color polkitFieldBorderFocus: accent + + // Identity selector text + readonly property color polkitUserLabel: "#996878a0" + readonly property color polkitUserValue: accent + + // Input prompt label + readonly property color polkitInputPrompt: "#886878a0" + + // TextInput + readonly property color polkitInputText: textMain + readonly property color polkitInputSelection: "#55b068d8" // mauve selection + readonly property color polkitInputSelectedText: bg + + // Eye toggle + readonly property color polkitEyeIcon: "#666878a0" + readonly property color polkitEyeIconHover: accent + + // Authenticate button + readonly property color polkitAuthBg: "#ddb068d8" // slightly-muted mauve fill + readonly property color polkitAuthBgHover: accent + 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: "#cce8eef8" +} diff --git a/config/themes/metropolitan.qml b/config/themes/metropolitan.qml index d837df4..2aec3c9 100644 --- a/config/themes/metropolitan.qml +++ b/config/themes/metropolitan.qml @@ -37,6 +37,21 @@ QtObject { 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: Night City Lights) ─────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -44,7 +59,20 @@ QtObject { readonly property color statsMemColor: "#ff9ece6a" // Train stripe green readonly property color statsDiskColor: "#ff7dcfff" // Cyan window light readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ffff9e64" // Warm amber + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Urban Sound) ──────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#22565f89" @@ -134,6 +162,15 @@ QtObject { readonly property color clockPopupText: textMain readonly property color clockPopupDim: textDim + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/neonica.qml b/config/themes/neonica.qml index 378ed54..2762d90 100644 --- a/config/themes/neonica.qml +++ b/config/themes/neonica.qml @@ -36,6 +36,21 @@ QtObject { 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: Cyan/Blue) ──────────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -43,7 +58,20 @@ QtObject { readonly property color statsMemColor: "#ffc4a7e7" // Soft Purple readonly property color statsDiskColor: "#ffebbcba" // Muted Rose readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#fff6c177" // Warm peach + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Variation: Violet) ────────────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#22443355" @@ -133,6 +161,15 @@ QtObject { readonly property color clockPopupText: textMain readonly property color clockPopupDim: "#ff6e6a86" + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/pinkie.qml b/config/themes/pinkie.qml new file mode 100644 index 0000000..a684013 --- /dev/null +++ b/config/themes/pinkie.qml @@ -0,0 +1,367 @@ +pragma Singleton +import QtQuick +import Quickshell + +QtObject { + id: theme + + // ── Wallpaper ────────────────────────────────────────────────────────────── + readonly property string wallpaper: Quickshell.env("HOME") + "/.config/quickshell/wallpapers/pinkie.jpg" + + // ── Base Backgrounds ─────────────────────────────────────────────────────── + readonly property color bg: "#cc0d0b1c" // Deep purple-navy (bow shadow) + readonly property color bgPanel: "transparent" + readonly property color bgPopup: "#cc0d0b1c" // Deep purple-navy + readonly property color bgFrame: bg + + // ── Separators ──────────────────────────────────────────────────────────── + readonly property color separator: "#334a4068" // Muted purple-gray + + // ── Text ────────────────────────────────────────────────────────────────── + readonly property color textMain: "#ffe8eef2" // Bright highlight white + readonly property color textDim: "#997e8098" // Muted lavender-gray + readonly property color todayText: "#ffffffff" + + // ── Accent & Borders ────────────────────────────────────────────────────── + readonly property color accent: "#ff4ec0b8" // Teal eye color + readonly property color border: "transparent" + readonly property color frameBorder: "transparent" + readonly property color borderPopup: "transparent" + readonly property color borderToday: accent + + // ── 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: Pastel Iris) ───────────────────────────────── + readonly property color statsBg: bgPanel + readonly property color statsBorder: border + readonly property color statsCpuColor: "#ffcfb4b4" // Soft peach-rose (skin tone) + readonly property color statsMemColor: "#ff86c8d4" // Soft teal-blue (eye) + readonly property color statsDiskColor: "#ffb8aae0" // Soft lavender (hair) + readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#ffea98b8" // Warm rose-pink + readonly property color statsGpuColor: "#ffaac8e8" // Soft sky blue + + + // ── 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: Silver Iris) ──────────────────────────────── + readonly property color volBg: bgPanel + readonly property color volBgHover: "#224a4068" + readonly property color volBorder: border + readonly property color volBorderHover: "#ff86c8d4" + readonly property color volPopupBg: bgPopup + readonly property color volPopupBorder: borderPopup + readonly property color volIcon: "#ff86c8d4" + readonly property color volIconMuted: "#ff565870" + readonly property color volTrack: "#22ffffff" + readonly property color volHandle: accent + readonly property color volHandleBorder: "#33ffffff" + readonly property color volMuteBg: "#33ea98b8" + readonly property color volPickerHover: "#154ec0b8" + + // ── Volume Limit Buttons ──────────────────────────────────────────────── + readonly property color volLimitBtn: "transparent" + readonly property color volLimitBtnHover: "#224ec0b8" + 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: "#ff4ec0b8" // Teal eye glow + 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: "#ff4ec0b8" + 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: "#ff4ec0b8" + readonly property color netPopupText: textMain + readonly property color netPopupDim: textDim + readonly property color netFieldBg: "#22ffffff" + readonly property color netCancelBgHover: "#22ffffff" + readonly property color netConnectText: "#ff0d0b1c" + 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: "#ffa0c8a8" // soft sage green + readonly property color netWifiIconErr: "#ffea98b8" // soft rose pink + readonly property color netEthIconOk: "#ffa0c8a8" + readonly property color netEthIconErr: "#ffea98b8" + + // ── Calendar Popup ───────────────────────────────────────────────────────── + readonly property color calCardBg: bgPopup + readonly property color calCardBorder: borderPopup + readonly property color calSeparator: separator + readonly property color clockPopupHeader: "#ff4ec0b8" + 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: "#ff4ec0b8" // Teal on hover + readonly property color calArrowBg: "transparent" + readonly property color calArrowBgHover: "#224ec0b8" // Soft teal tint + readonly property color calArrowBgPress: "#ff4ec0b8" // Full teal on press + + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#ffea98b8" // Warm rose-pink + readonly property color weatherFeelsColor: "#ffb8aae0" // Soft lavender + readonly property color weatherHumidColor: "#ff86c8d4" // Teal-blue + readonly property color weatherWindColor: "#ffaac8e8" // Sky blue + + // ── 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: "#334a4068" + readonly property color wsActiveText: "#ff0d0b1c" + readonly property color wsInactiveText: textMain + readonly property color wsHoverText: "#ffffffff" + + // ── 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: "#224ec0b8" // soft teal tint + readonly property color trayMenuCheck: accent + readonly property color trayMenuSeparator: separator + + // ── Launcher (Variation: Iris Mist) ─────────────────────────────────────── + readonly property color launcherBg: bgPopup + readonly property color launcherBorder: borderPopup + readonly property color launcherInput: "#440b0918" + readonly property color launcherInputBorderFocus: accent + readonly property color launcherPill: "#444a4068" + readonly property color launcherText: textMain + readonly property color launcherDim: textDim + readonly property color launcherAccent: accent + readonly property color launcherHover: "#224ec0b8" + readonly property color launcherSelected: "#444ec0b8" + readonly property color launcherModeActiveText: "#ffffffff" + readonly property color launcherModeActiveBg: accent + + // ── Status Colors ────────────────────────────────────────────────────────── + readonly property color statusOk: "#ffa0c8a8" // Soft sage green + readonly property color statusWarn: "#ffe8c0a0" // Soft peach + readonly property color statusErr: "#ffea98b8" // Soft rose + readonly property color statusInfo: "#ff86c8d4" // Teal-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: Iris Glow) ──────────────────────────────────── + 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: "#114ec0b8" + readonly property color notifHistoryEmpty: textDim + + // ── BgDate Module ────────────────────────────────────────────────────────── + readonly property color bgDateText: "#ffffffff" + readonly property color bgDateShadow: "#88000000" + 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: "#ffa0c8a8" // soft sage green + readonly property color cryptoDown: "#ffea98b8" // soft rose + + // Popup card + readonly property color cryptoPopupBg: bgPopup + readonly property color cryptoPopupBorder: borderPopup + readonly property color cryptoPopupHeader: "#ff4ec0b8" + 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: "#ff0d0b1c" + readonly property color cryptoPlaceholder: Qt.rgba(textDim.r, textDim.g, textDim.b, 0.33) + + // ── Polkit Dialog ────────────────────────────────────────────────────────── + // Overlay + readonly property color polkitOverlayBg: "#bb000000" + + // Card chrome + readonly property color polkitCardBg: bgPopup + readonly property color polkitCardBorder: border + + // Lock icon + readonly property color polkitIconBg: "#1e4ec0b8" // translucent teal fill + readonly property color polkitIconBorder: "#444ec0b8" // stronger teal ring + readonly property color polkitIconColor: accent + + // Text hierarchy + readonly property color polkitTitle: textMain + readonly property color polkitMessage: "#cce8eef2" + + // Action-ID pill + readonly property color polkitPillBg: "#1a4a4068" + readonly property color polkitPillText: "#667e8098" + + // Divider + readonly property color polkitDivider: "#334a4068" + + // Supplementary message — error state + readonly property color polkitSuppErrBg: "#1aea98b8" + readonly property color polkitSuppErrBorder: "#44ea98b8" + readonly property color polkitSuppErrText: statusErr + + // Supplementary message — info / ok state + readonly property color polkitSuppOkBg: "#1aa0c8a8" + readonly property color polkitSuppOkBorder: "#44a0c8a8" + readonly property color polkitSuppOkText: statusOk + + // Fields + readonly property color polkitFieldBg: "#440b0918" + readonly property color polkitFieldBorder: "#22ffffff" + readonly property color polkitFieldBorderFocus: accent + + // Identity selector text + readonly property color polkitUserLabel: "#997e8098" + readonly property color polkitUserValue: accent + + // Input prompt label + readonly property color polkitInputPrompt: "#887e8098" + + // TextInput + readonly property color polkitInputText: textMain + readonly property color polkitInputSelection: "#554ec0b8" // teal selection + readonly property color polkitInputSelectedText: bg + + // Eye toggle + readonly property color polkitEyeIcon: "#667e8098" + readonly property color polkitEyeIconHover: accent + + // Authenticate button + readonly property color polkitAuthBg: "#dd4ec0b8" // slightly-muted teal fill + readonly property color polkitAuthBgHover: accent + 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: "#cce8eef2" +} diff --git a/config/themes/qmldir b/config/themes/qmldir index 6de9969..e83f7d1 100644 --- a/config/themes/qmldir +++ b/config/themes/qmldir @@ -14,6 +14,6 @@ singleton Hummingbird 1.0 hummingbird.qml singleton Tropicalnight 1.0 tropicalnight.qml singleton Boat 1.0 boat.qml singleton Autumn 1.0 autumn.qml - - +singleton Pinkie 1.0 pinkie.qml +singleton Lowlight 1.0 lowlight.qml diff --git a/config/themes/supreme.qml b/config/themes/supreme.qml index b8f0618..66646b8 100644 --- a/config/themes/supreme.qml +++ b/config/themes/supreme.qml @@ -36,6 +36,21 @@ QtObject { 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 (Candy Tones) ───────────────────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -43,7 +58,20 @@ QtObject { readonly property color statsMemColor: "#ffee99ff" // Soft purple readonly property color statsDiskColor: "#ff70c5ce" // Cyan pop readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#ffbff7c2" // Mint green + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module (Berry Glass) ─────────────────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#22ffb7ce" @@ -133,6 +161,15 @@ QtObject { readonly property color clockPopupText: textMain readonly property color clockPopupDim: textDim + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/config/themes/tropicalnight.qml b/config/themes/tropicalnight.qml index 536d4e4..9ec44c5 100644 --- a/config/themes/tropicalnight.qml +++ b/config/themes/tropicalnight.qml @@ -38,6 +38,21 @@ QtObject { 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 ────────────────────────────────────────────────────────── readonly property color statsBg: bgPanel readonly property color statsBorder: border @@ -45,7 +60,20 @@ QtObject { readonly property color statsMemColor: "#ffb4c9a1" // Soft moonlit green readonly property color statsDiskColor: "#ff94e2d5" readonly property color statsTrackColor: "#15ffffff" + readonly property color statsCpuTempColor: "#fff38ba8" // Warm rose red + readonly property color statsGpuColor: "#fffab387" // Warm peach + + // ── 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: statsCpuColor + readonly property color sysInfoGpuColor: statsGpuColor + readonly property color sysInfoTrackColor: statsTrackColor // ── Volume Module ───────────────────────────────────────────────────────── readonly property color volBg: bgPanel readonly property color volBgHover: "#224a5d6e" @@ -142,6 +170,15 @@ QtObject { readonly property color calArrowBgHover: "#2289b4fa" readonly property color calArrowBgPress: accent + + // ── Weather Module ────────────────────────────────────────────────────── + readonly property color weatherAccent: accent + readonly property color weatherTextMain: textMain + readonly property color weatherTextDim: textDim + readonly property color weatherTempColor: "#fff38ba8" + readonly property color weatherFeelsColor: "#ffcba6f7" + readonly property color weatherHumidColor: "#ff89b4fa" + readonly property color weatherWindColor: "#ff94e2d5" // ── Workspace Module ─────────────────────────────────────────────────────── readonly property color wsPanelBg: bgPanel readonly property color wsPanelBorder: "transparent" diff --git a/shell.qml b/shell.qml index 4e2d26f..b4f324e 100644 --- a/shell.qml +++ b/shell.qml @@ -7,6 +7,7 @@ import Quickshell.Io import "bar" import "launcher" import "widgets/bgDate" +import "widgets/sidebar" import "polkit" import "config" as Cfg @@ -22,7 +23,14 @@ ShellRoot { property color frameBackground: Cfg.Config.theme.bgFrame property color frameBorderColor: Cfg.Config.theme.frameBorder - + // ── Sidebar (Widget Panel) ─────────────────────────────────────────── + Variants { + model: Quickshell.screens + Sidebar { + modelData: modelData + Component.onCompleted: modelData.sidebar = this + } + } // ── Polkit Agent ───────────────────────────────────────────────────────── Loader { active: Cfg.Config.enablePolkit diff --git a/wallpapers/lowlight.jpg b/wallpapers/lowlight.jpg new file mode 100644 index 0000000..088fa8c Binary files /dev/null and b/wallpapers/lowlight.jpg differ diff --git a/wallpapers/pinkie.jpg b/wallpapers/pinkie.jpg new file mode 100644 index 0000000..8c26d3e Binary files /dev/null and b/wallpapers/pinkie.jpg differ diff --git a/wallpapers/purpura.jpg b/wallpapers/purpura.jpg new file mode 100644 index 0000000..4c9e07e Binary files /dev/null and b/wallpapers/purpura.jpg differ diff --git a/widgets/sidebar/Sidebar.qml b/widgets/sidebar/Sidebar.qml new file mode 100644 index 0000000..ae42b2c --- /dev/null +++ b/widgets/sidebar/Sidebar.qml @@ -0,0 +1,208 @@ +import QtQuick +import QtQuick.Controls +import Quickshell +import Quickshell.Wayland +import Quickshell.Hyprland + +import "../../config" as Cfg +import "sysinfo" +import "mpris" +import "weather" + +PanelWindow { + id: root + + required property var modelData + screen: modelData + color: "transparent" + visible: false + + anchors { top: true; bottom: true; left: true; right: true } + + WlrLayershell.layer: WlrLayer.Top + WlrLayershell.namespace: "main-shell-sidebar" + WlrLayershell.exclusiveZone: -1 + WlrLayershell.keyboardFocus: _open ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None + + Region { id: noMask } + mask: _open ? null : noMask + + readonly property var t: Cfg.Config.theme + readonly property bool isTop: Cfg.Config.barPosition === "top" + readonly property int frameTop: isTop ? Cfg.Config.barHeight : Cfg.Config.margin + readonly property int frameBot: isTop ? Cfg.Config.margin : Cfg.Config.barHeight + readonly property int inset: Cfg.Config.margin + Cfg.Config.frameBorderWidth + 8 + readonly property int sbWidth: 260 + readonly property bool isLeft: Cfg.Config.sideBarPosition === "left" + readonly property int slideDist: root.sbWidth + 20 + readonly property int slideFrom: isLeft ? -slideDist : slideDist + readonly property int panelX: isLeft ? root.inset : (width - root.sbWidth - root.inset) + + property bool _open: false + readonly property bool isOpen: _open + + GlobalShortcut { + name: "sidebar" + onPressed: root.toggle() + } + + function open() { + visible = true + _open = true + enterAnim.stop() + exitAnim.stop() + hideTimer.stop() + enterAnim.start() + } + + function close() { + _open = false + enterAnim.stop() + exitAnim.start() + } + + function toggle() { _open ? close() : open() } + + Timer { + id: hideTimer + interval: 280 + onTriggered: visible = false + } + + Connections { + target: root + function onActiveChanged() { + if (!root.active && root._open) root.close() + } + } + + MouseArea { + anchors.fill: parent + onClicked: root.close() + } + + // ── Full right-side background panel ────────────────────────────────── + Rectangle { + id: sidebarPanel + transform: Translate { id: panelSlide; x: root.slideFrom } + + x: root.panelX + y: root.frameTop + Cfg.Config.frameBorderWidth + width: root.sbWidth + height: parent.height - root.frameTop - root.frameBot - Cfg.Config.frameBorderWidth * 2 + radius: Cfg.Config.popupRadius + color: "transparent" + opacity: 0 + + clip: true + + // ── Widget area ─────────────────────────────────────────────────── + Item { + id: widgetArea + anchors { + fill: parent + topMargin: 10 + bottomMargin: 10 + leftMargin: 10 + rightMargin: 10 + } + + Flickable { + id: flick + anchors.fill: parent + contentWidth: width + contentHeight: widgetCol.implicitHeight + boundsBehavior: Flickable.StopAtBounds + clip: true + flickDeceleration: 2000 + + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AsNeeded + width: 4 + contentItem: Rectangle { + radius: 2 + color: Qt.alpha(root.t.accent, 0.3) + } + } + + Column { + id: widgetCol + anchors { left: parent.left; right: parent.right } + spacing: 10 + + Loader { + active: Cfg.Config.sideBarSysInfo + sourceComponent: sysInfoComp + anchors { left: parent.left; right: parent.right } + } + + Loader { + active: Cfg.Config.sideBarMpris + sourceComponent: mprisComp + anchors { left: parent.left; right: parent.right } + } + + Loader { + active: Cfg.Config.sideBarWeather + sourceComponent: weatherComp + anchors { left: parent.left; right: parent.right } + } + } + } + } + } + + Component { + id: sysInfoComp + WidgetCard { + SysInfo { + anchors { left: parent.left; right: parent.right } + } + } + } + + Component { + id: mprisComp + WidgetCard { + MprisWidget { + anchors { left: parent.left; right: parent.right } + } + } + } + + Component { + id: weatherComp + WidgetCard { + WeatherWidget { + anchors { left: parent.left; right: parent.right } + } + } + } + + // ── Enter animation ─────────────────────────────────────────────────── + ParallelAnimation { + id: enterAnim + NumberAnimation { + target: panelSlide; property: "x" + to: 0; duration: 320; easing.type: Easing.OutCubic + } + NumberAnimation { + target: sidebarPanel; property: "opacity" + to: 1; duration: 280; easing.type: Easing.OutCubic + } + } + + // ── Exit animation ──────────────────────────────────────────────────── + ParallelAnimation { + id: exitAnim + onStopped: hideTimer.restart() + NumberAnimation { + target: panelSlide; property: "x" + to: root.slideFrom; duration: 250; easing.type: Easing.InCubic + } + NumberAnimation { + target: sidebarPanel; property: "opacity" + to: 0; duration: 200; easing.type: Easing.InBack + } + } +} diff --git a/widgets/sidebar/WidgetCard.qml b/widgets/sidebar/WidgetCard.qml new file mode 100644 index 0000000..cfbb3c3 --- /dev/null +++ b/widgets/sidebar/WidgetCard.qml @@ -0,0 +1,31 @@ +import QtQuick +import "../../config" as Cfg + +Rectangle { + id: card + + anchors { left: parent.left; right: parent.right } + + implicitHeight: contentArea.childrenRect.height + 28 + + radius: Cfg.Config.popupRadius + color: Cfg.Config.theme.bgPopup + border.color: Qt.alpha(Cfg.Config.theme.accent, 0.18) + border.width: 1 + clip: true + + default property alias content: contentArea.data + + Item { + id: contentArea + anchors { + top: parent.top + left: parent.left + right: parent.right + topMargin: 14 + leftMargin: 14 + rightMargin: 14 + } + height: childrenRect.height + } +} diff --git a/widgets/sidebar/mpris/MediaButton.qml b/widgets/sidebar/mpris/MediaButton.qml new file mode 100644 index 0000000..419e461 --- /dev/null +++ b/widgets/sidebar/mpris/MediaButton.qml @@ -0,0 +1,63 @@ +import QtQuick +import "../../../config" as Cfg + +Rectangle { + id: root + + property string icon: "" + property bool enabled: true + property bool primary: false + signal clicked() + + property bool _hovered: false + + readonly property var t: Cfg.Config.theme + + width: primary ? 44 : 36 + height: width + radius: width / 2 + + border.width: 1 + scale: _hovered && enabled ? 1.08 : 1 + + readonly property color _bgDefault: enabled + ? (primary ? t.accent : t.mprisBtnBg) + : "transparent" + readonly property color _bgHovered: primary + ? Qt.lighter(t.accent, 1.2) + : t.mprisBtnBgHover + + color: _hovered && enabled ? _bgHovered : _bgDefault + border.color: primary ? color : ( + enabled + ? (_hovered ? t.mprisBtnBorderHover : t.mprisBtnBorder) + : t.mprisBtnBorder + ) + + Behavior on color { ColorAnimation { duration: 150 } } + Behavior on border.color { ColorAnimation { duration: 150 } } + Behavior on scale { NumberAnimation { duration: 150; easing.type: Easing.OutBack } } + + Text { + anchors.centerIn: parent + text: root.icon + color: root.primary ? root.t.mprisButtonText : ( + root.enabled + ? (root._hovered ? root.t.mprisBtnIconHover : root.t.mprisBtnIcon) + : root.t.mprisTextDim + ) + font.pixelSize: primary ? 22 : 18 + Behavior on color { ColorAnimation { duration: 150 } } + } + + HoverHandler { + cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor + onHoveredChanged: root._hovered = hovered + } + + TapHandler { + onTapped: { + if (root.enabled) root.clicked() + } + } +} diff --git a/widgets/sidebar/mpris/MediaSlider.qml b/widgets/sidebar/mpris/MediaSlider.qml new file mode 100644 index 0000000..5d11212 --- /dev/null +++ b/widgets/sidebar/mpris/MediaSlider.qml @@ -0,0 +1,49 @@ +import QtQuick +import "../../../config" as Cfg + +Item { + id: root + + property real fraction: 0 + property bool interactive: true + signal seeked(real fraction) + + readonly property var t: Cfg.Config.theme + + implicitHeight: 14 + + function seek(posX) { + seeked(Math.max(0, Math.min(1, posX / width))) + } + + Rectangle { + anchors.verticalCenter: parent.verticalCenter + width: parent.width + height: 3 + radius: 2 + color: root.t.mprisTrackColor + + Rectangle { + width: parent.width * root.fraction + height: parent.height + radius: parent.radius + color: root.t.mprisAccent + } + } + + Rectangle { + anchors.verticalCenter: parent.verticalCenter + x: Math.max(0, Math.min(parent.width - width, (parent.width - width) * root.fraction)) + width: 10 + height: 10 + radius: 5 + color: root.t.mprisAccent + } + + MouseArea { + anchors.fill: parent + cursorShape: root.interactive ? Qt.PointingHandCursor : Qt.ArrowCursor + onPressed: pos => root.seek(pos.x) + onPositionChanged: pos => { if (pressed) root.seek(pos.x) } + } +} diff --git a/widgets/sidebar/mpris/MprisWidget.qml b/widgets/sidebar/mpris/MprisWidget.qml new file mode 100644 index 0000000..fc2596f --- /dev/null +++ b/widgets/sidebar/mpris/MprisWidget.qml @@ -0,0 +1,355 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell.Services.Mpris +import "../../../config" as Cfg + +Item { + id: root + + implicitHeight: contentCol.implicitHeight + + readonly property var t: Cfg.Config.theme + + property var activePlayer: null + + readonly property bool canChangeVolume: root.activePlayer && root.activePlayer.volumeSupported && root.activePlayer.canControl + + readonly property var _identityMap: ({ + "firefox": "Firefox", + "spotify": "Spotify", + "chromium": "Chromium", + "google-chrome": "Chrome", + "brave": "Brave", + "vlc": "VLC", + "mpv": "mpv" + }) + + function selectPlayer() { + var players = Mpris.players.values + var fallback = null + for (var i = 0; i < players.length; i++) { + var p = players[i] + if (!p || (p.trackTitle === "" && p.identity === "")) continue + if (p.playbackState === MprisPlaybackState.Playing) { activePlayer = p; return } + if (!fallback) fallback = p + } + if (activePlayer && activePlayer.playbackState !== MprisPlaybackState.Stopped) return + activePlayer = fallback + } + + Instantiator { + model: Mpris.players + Connections { + required property MprisPlayer modelData + target: modelData + + Component.onCompleted: { + if (root.activePlayer == null || modelData.playbackState === MprisPlaybackState.Playing) + root.selectPlayer() + } + + Component.onDestruction: { + if (root.activePlayer === modelData) { + root.activePlayer = null + root.selectPlayer() + } + } + + function onPlaybackStateChanged() { + root.selectPlayer() + } + } + } + + function formatDuration(s) { + if (isNaN(s) || s < 0) return "0:00" + var m = Math.floor(s / 60) + var sec = Math.floor(s % 60) + return m + ":" + (sec < 10 ? "0" : "") + sec + } + + function formatIdentity(name) { + if (!name) return "Media" + var lower = name.toLowerCase() + for (var key in root._identityMap) { + if (lower.indexOf(key) !== -1) return root._identityMap[key] + } + return name + } + + function playbackStatusText() { + if (!root.activePlayer) return "No players" + switch (root.activePlayer.playbackState) { + case MprisPlaybackState.Playing: return "Now playing" + case MprisPlaybackState.Paused: return "Paused" + default: return "Stopped" + } + } + + function volumeIcon() { + if (!root.activePlayer) return "󰕾" + var v = root.activePlayer.volume + if (v === 0) return "󰖁" + if (v < 0.33) return "󰕿" + if (v < 0.66) return "󰖀" + return "󰕾" + } + + Timer { + id: positionTimer + running: root.activePlayer && root.activePlayer.playbackState === MprisPlaybackState.Playing + interval: 1000 + repeat: true + onTriggered: { + if (root.activePlayer) root.activePlayer.positionChanged() + } + } + + ColumnLayout { + id: contentCol + anchors { left: parent.left; right: parent.right; top: parent.top } + spacing: 0 + + Rectangle { + Layout.fillWidth: true + height: 32 + color: "transparent" + + RowLayout { + anchors.fill: parent + spacing: 10 + + Rectangle { + width: 32; height: 32 + radius: 8 + color: Qt.alpha(root.t.mprisAccent, 0.12) + border.color: Qt.alpha(root.t.mprisAccent, 0.22) + border.width: 1 + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: "󰎆" + color: root.t.mprisAccent + font.pixelSize: 18 + } + } + + ColumnLayout { + spacing: 2 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + + Text { + text: root.activePlayer ? root.formatIdentity(root.activePlayer.identity) : "No media" + color: root.t.mprisTextMain + font.pixelSize: 13 + font.weight: Font.DemiBold + elide: Text.ElideRight + Layout.fillWidth: true + } + Text { + text: root.playbackStatusText() + color: root.t.mprisTextDim + font.pixelSize: 10 + opacity: 0.75 + } + } + } + } + + Item { Layout.preferredHeight: 12 } + + Rectangle { + Layout.fillWidth: true + height: 1 + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { position: 0.0; color: Qt.alpha(root.t.mprisAccent, 0.5) } + GradientStop { position: 1.0; color: "transparent" } + } + } + + Item { Layout.preferredHeight: root.activePlayer ? 10 : 0 } + + ColumnLayout { + id: trackArea + Layout.fillWidth: true + visible: root.activePlayer !== null + spacing: 0 + + RowLayout { + Layout.fillWidth: true + spacing: 12 + + Rectangle { + width: 64; height: 64 + radius: 8 + color: root.t.mprisAlbumBg + border.color: root.t.mprisAlbumBorder + border.width: 1 + Layout.alignment: Qt.AlignTop + + Image { + id: albumArt + anchors.fill: parent + anchors.margins: 2 + source: root.activePlayer ? root.activePlayer.trackArtUrl : "" + fillMode: Image.PreserveAspectCrop + visible: root.activePlayer && root.activePlayer.trackArtUrl !== "" && status === Image.Ready + } + + Text { + anchors.centerIn: parent + text: "󰝚" + color: root.t.mprisAccent + font.pixelSize: 28 + visible: root.activePlayer && (root.activePlayer.trackArtUrl === "" || !albumArt.visible) + } + } + + ColumnLayout { + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + spacing: 2 + + Text { + text: root.activePlayer ? (root.activePlayer.trackTitle || "Unknown Title") : "" + color: root.t.mprisTextMain + font.pixelSize: 13 + font.weight: Font.Medium + elide: Text.ElideRight + maximumLineCount: 2 + wrapMode: Text.WordWrap + Layout.fillWidth: true + } + + Text { + text: root.activePlayer ? (root.activePlayer.trackArtist || "Unknown Artist") : "" + color: root.t.mprisTextDim + font.pixelSize: 11 + elide: Text.ElideRight + Layout.fillWidth: true + } + + Text { + text: root.activePlayer ? (root.activePlayer.trackAlbum || "") : "" + color: root.t.mprisTextDim + font.pixelSize: 10 + opacity: 0.7 + elide: Text.ElideRight + visible: root.activePlayer && root.activePlayer.trackAlbum !== "" + Layout.fillWidth: true + } + } + } + + Item { Layout.preferredHeight: 12 } + + ColumnLayout { + Layout.fillWidth: true + spacing: 2 + visible: root.activePlayer && root.activePlayer.positionSupported + + MediaSlider { + Layout.fillWidth: true + interactive: root.activePlayer && root.activePlayer.canSeek + fraction: { + var p = root.activePlayer + if (!p) return 0 + var len = p.length + if (len > 0) return Math.max(0, Math.min(1, p.position / len)) + return 0 + } + onSeeked: frac => { + var p = root.activePlayer + if (p && p.canSeek && p.length > 0) { + p.position = frac * p.length + } + } + } + + RowLayout { + Layout.fillWidth: true + spacing: 0 + + Text { + text: root.activePlayer ? root.formatDuration(root.activePlayer.position) : "0:00" + color: root.t.mprisTextDim + font.pixelSize: 9 + Layout.alignment: Qt.AlignLeft + } + + Item { Layout.fillWidth: true } + + Text { + text: root.activePlayer ? root.formatDuration(root.activePlayer.length) : "0:00" + color: root.t.mprisTextDim + font.pixelSize: 9 + Layout.alignment: Qt.AlignRight + } + } + } + + Item { Layout.preferredHeight: 12 } + + RowLayout { + Layout.fillWidth: true + spacing: 8 + visible: root.canChangeVolume + + Text { + text: root.volumeIcon() + color: root.activePlayer && root.activePlayer.volume > 0 ? root.t.mprisAccent : root.t.mprisTextDim + font.pixelSize: 16 + Layout.alignment: Qt.AlignVCenter + } + + MediaSlider { + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + interactive: root.canChangeVolume + fraction: { + var p = root.activePlayer + if (!p) return 1 + return p.volume + } + onSeeked: frac => { + var p = root.activePlayer + if (p && root.canChangeVolume) { + p.volume = frac + } + } + } + } + + Item { Layout.preferredHeight: root.canChangeVolume ? 12 : 0 } + + RowLayout { + Layout.alignment: Qt.AlignHCenter + spacing: 16 + + MediaButton { + icon: "󰒮" + enabled: root.activePlayer && root.activePlayer.canGoPrevious + onClicked: root.activePlayer.previous() + } + + MediaButton { + primary: true + icon: root.activePlayer && root.activePlayer.playbackState === MprisPlaybackState.Playing ? "󰏤" : "󰐊" + enabled: root.activePlayer && root.activePlayer.canTogglePlaying + onClicked: root.activePlayer.togglePlaying() + } + + MediaButton { + icon: "󰒭" + enabled: root.activePlayer && root.activePlayer.canGoNext + onClicked: root.activePlayer.next() + } + } + } + + Item { Layout.preferredHeight: 6 } + } +} diff --git a/widgets/sidebar/sysinfo/SysInfo.qml b/widgets/sidebar/sysinfo/SysInfo.qml new file mode 100644 index 0000000..509d500 --- /dev/null +++ b/widgets/sidebar/sysinfo/SysInfo.qml @@ -0,0 +1,588 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import "../../../config" as Cfg + +ColumnLayout { + id: root + spacing: 0 + + readonly property var t: Cfg.Config.theme + + property string osName: "Linux" + property string kernelVer: "" + property real cpuPct: 0 + property real memPct: 0 + property real memUsedGb: 0 + property real swapPct: 0 + property real swapUsedGb: 0 + property bool hasSwap: false + property real diskPct: 0 + property real diskUsedGb: 0 + property string uptimeStr: "—" + property real battPct: -1 + property bool battCharging: false + property real cpuTemp: -1 + property real gpuTemp: -1 + property bool netOnline: false + property var _cpuPrev: ({ total: 0, idle: 0 }) + + Behavior on cpuPct { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on memPct { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on memUsedGb { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on swapPct { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on swapUsedGb { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on diskPct { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on diskUsedGb { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on battPct { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on cpuTemp { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on gpuTemp { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + + Process { + running: true + command: ["sh", "-c", + "grep '^PRETTY_NAME=' /etc/os-release 2>/dev/null | cut -d'\"' -f2 || echo Linux"] + stdout: SplitParser { onRead: d => { root.osName = d.trim() } } + } + Process { + running: true + command: ["uname", "-r"] + stdout: SplitParser { onRead: d => { root.kernelVer = d.trim() } } + } + + Process { + id: cpuTempProc + property string _buf: "" + command: ["sh", "-c", + "t=-1; for d in /sys/class/hwmon/hwmon*; do " + + "n=$(cat $d/name 2>/dev/null); " + + "if echo \"$n\" | grep -qiE 'coretemp|k10temp'; then " + + "t=$(( $(cat $d/temp1_input 2>/dev/null) / 1000 )); break; " + + "fi; done; echo $t"] + stdout: SplitParser { onRead: d => { cpuTempProc._buf = d } } + onRunningChanged: { + if (running || !_buf) return + root.cpuTemp = parseInt(_buf) + _buf = "" + } + } + + Process { + id: gpuTempProc + property string _buf: "" + command: ["sh", "-c", + "t=-1; for d in /sys/class/hwmon/hwmon*; do " + + "n=$(cat $d/name 2>/dev/null); " + + "if echo \"$n\" | grep -qiE 'amdgpu|radeon'; then " + + "t=$(( $(cat $d/temp1_input 2>/dev/null) / 1000 )); break; " + + "fi; done; echo $t"] + stdout: SplitParser { onRead: d => { gpuTempProc._buf = d } } + onRunningChanged: { + if (running || !_buf) return + root.gpuTemp = parseInt(_buf) + _buf = "" + } + } + + Process { + id: cpuProc + property string _buf: "" + command: ["sh", "-c", "grep '^cpu ' /proc/stat | head -1"] + stdout: SplitParser { onRead: d => { cpuProc._buf = d } } + onRunningChanged: { + if (running || !_buf) return + var p = _buf.trim().split(/\s+/) + var user = +p[1], nice = +p[2], sys = +p[3] + var idle = +p[4], iow = +p[5], irq = +p[6], sirq = +p[7] + var total = user + nice + sys + idle + iow + irq + sirq + var idleSum = idle + iow + if (root._cpuPrev.total > 0) { + var dt = total - root._cpuPrev.total + var di = idleSum - root._cpuPrev.idle + root.cpuPct = dt > 0 ? Math.round((dt - di) / dt * 100) : 0 + } + root._cpuPrev = { total: total, idle: idleSum } + _buf = "" + } + } + + Process { + id: memProc + property string _buf: "" + command: ["sh", "-c", "free -b | awk '/^Mem:/{print $2,$3,$7}'"] + stdout: SplitParser { onRead: d => { memProc._buf = d } } + onRunningChanged: { + if (running || !_buf) return + var p = _buf.trim().split(/\s+/) + var total = +p[0], avail = +p[2] + var used = total - avail + root.memUsedGb = used / 1073741824 + root.memPct = total > 0 ? (used / total * 100) : 0 + _buf = "" + } + } + + Process { + id: swapProc + property string _buf: "" + command: ["sh", "-c", "free -b | awk '/^Swap:/{print $2,$3}'"] + stdout: SplitParser { onRead: d => { swapProc._buf = d } } + onRunningChanged: { + if (running || !_buf) return + var p = _buf.trim().split(/\s+/) + var total = +p[0], used = +p[1] + root.hasSwap = total > 0 + root.swapUsedGb = total > 0 ? used / 1073741824 : 0 + root.swapPct = total > 0 ? (used / total * 100) : 0 + _buf = "" + } + } + + Process { + id: uptimeProc + property string _buf: "" + command: ["sh", "-c", + "u=$(awk '{print int($1)}' /proc/uptime); " + + "d=$((u/86400)); h=$(((u%86400)/3600)); m=$(((u%3600)/60)); " + + "[ $d -gt 0 ] && echo ${d}d${h}h || [ $h -gt 0 ] && echo ${h}h${m}m || echo ${m}m"] + stdout: SplitParser { onRead: d => { uptimeProc._buf = d } } + onRunningChanged: { + if (running || !_buf) return + root.uptimeStr = _buf.trim() + _buf = "" + } + } + + Process { + id: diskProc + property string _buf: "" + command: ["sh", "-c", "df -B1 / | awk 'NR==2{print $3,$2}'"] + stdout: SplitParser { onRead: d => { diskProc._buf = d } } + onRunningChanged: { + if (running || !_buf) return + var p = _buf.trim().split(/\s+/) + var used = +p[0], total = +p[1] + root.diskUsedGb = used / 1073741824 + root.diskPct = total > 0 ? (used / total * 100) : 0 + _buf = "" + } + } + + Process { + id: battProc + property string _buf: "" + command: ["sh", "-c", + "p=/sys/class/power_supply/BAT0; " + + "[ -f $p/capacity ] && echo $(cat $p/capacity) $(cat $p/status) || echo -1 Unknown"] + stdout: SplitParser { onRead: d => { battProc._buf = d } } + onRunningChanged: { + if (running || !_buf) return + var p = _buf.trim().split(/\s+/) + root.battPct = parseInt(p[0]) + root.battCharging = (p[1] === "Charging" || p[1] === "Full") + _buf = "" + } + } + + Process { + id: netProc + property string _buf: "" + command: ["sh", "-c", "ip route show default 2>/dev/null | grep -c default || echo 0"] + stdout: SplitParser { onRead: d => { netProc._buf = d } } + onRunningChanged: { + if (running) return + root.netOnline = parseInt(netProc._buf.trim()) > 0 + _buf = "" + } + } + + function refresh() { + if (!cpuProc.running) cpuProc.running = true + if (!memProc.running) memProc.running = true + if (!swapProc.running) swapProc.running = true + if (!diskProc.running) diskProc.running = true + if (!uptimeProc.running) uptimeProc.running = true + if (!battProc.running) battProc.running = true + if (!netProc.running) netProc.running = true + if (!cpuTempProc.running) cpuTempProc.running = true + if (!gpuTempProc.running) gpuTempProc.running = true + } + + Timer { + interval: 5000 + running: true + repeat: true + triggeredOnStart: true + onTriggered: root.refresh() + } + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + Rectangle { + width: 32; height: 32 + radius: 8 + color: Qt.alpha(root.t.sysInfoAccent, 0.12) + border.color: Qt.alpha(root.t.sysInfoAccent, 0.22) + border.width: 1 + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: "󰌽" + color: root.t.sysInfoAccent + font.pixelSize: 20 + } + } + + ColumnLayout { + spacing: 2 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + + Text { + text: root.osName + color: root.t.sysInfoTextMain + font.pixelSize: 13 + font.weight: Font.DemiBold + elide: Text.ElideRight + Layout.fillWidth: true + } + Text { + text: root.kernelVer + color: root.t.sysInfoTextDim + font.pixelSize: 10 + opacity: 0.75 + elide: Text.ElideRight + Layout.fillWidth: true + } + } + } + + Item { Layout.preferredHeight: 12 } + + Rectangle { + Layout.fillWidth: true + height: 1 + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { position: 0.0; color: Qt.alpha(root.t.sysInfoAccent, 0.5) } + GradientStop { position: 1.0; color: "transparent" } + } + } + + Item { Layout.preferredHeight: 10 } + + SysInfoRow { + Layout.fillWidth: true + icon: "󰻠" + label: "CPU" + value: Math.round(root.cpuPct) + "%" + iconColor: root.t.sysInfoCpuColor + dimColor: root.t.sysInfoTextDim + textColor: root.t.sysInfoTextMain + showBar: true + barPct: root.cpuPct + barColor: root.t.sysInfoCpuColor + trackColor: root.t.sysInfoTrackColor + } + + Item { Layout.preferredHeight: 9 } + + SysInfoRow { + Layout.fillWidth: true + visible: root.cpuTemp >= 0 + icon: "󰔄" + label: "CPU Temp" + value: root.cpuTemp >= 0 ? Math.round(root.cpuTemp) + "°C" : "—" + iconColor: root.cpuTemp > 80 ? root.t.statusErr + : root.cpuTemp > 60 ? root.t.statusWarn + : root.t.sysInfoCpuTempColor + dimColor: root.t.sysInfoTextDim + textColor: root.t.sysInfoTextMain + showBar: true + barPct: Math.min(100, Math.round(root.cpuTemp * 100 / 95)) + barColor: root.cpuTemp > 80 ? root.t.statusErr + : root.cpuTemp > 60 ? root.t.statusWarn + : root.t.sysInfoCpuTempColor + trackColor: root.t.sysInfoTrackColor + } + + Item { + Layout.fillWidth: true + implicitHeight: root.gpuTemp >= 0 ? 9 : 0 + visible: root.gpuTemp >= 0 + } + + SysInfoRow { + Layout.fillWidth: true + visible: root.gpuTemp >= 0 + icon: "󰾲" + label: "GPU Temp" + value: Math.round(root.gpuTemp) + "°C" + iconColor: root.gpuTemp > 80 ? root.t.statusErr + : root.gpuTemp > 65 ? root.t.statusWarn + : root.t.sysInfoGpuColor + dimColor: root.t.sysInfoTextDim + textColor: root.t.sysInfoTextMain + showBar: true + barPct: Math.min(100, Math.round(root.gpuTemp * 100 / 95)) + barColor: root.gpuTemp > 80 ? root.t.statusErr + : root.gpuTemp > 65 ? root.t.statusWarn + : root.t.sysInfoGpuColor + trackColor: root.t.sysInfoTrackColor + } + + Item { Layout.preferredHeight: 9 } + + SysInfoRow { + Layout.fillWidth: true + icon: "󰍛" + label: "Memory" + value: root.memUsedGb.toFixed(2) + " GB" + iconColor: root.t.sysInfoMemColor + dimColor: root.t.sysInfoTextDim + textColor: root.t.sysInfoTextMain + showBar: true + barPct: root.memPct + barColor: root.t.sysInfoMemColor + trackColor: root.t.sysInfoTrackColor + } + + Item { Layout.preferredHeight: 9 } + + SysInfoRow { + Layout.fillWidth: true + icon: "󰋊" + label: "Disk (/)" + value: root.diskUsedGb.toFixed(1) + " GB" + iconColor: root.t.sysInfoDiskColor + dimColor: root.t.sysInfoTextDim + textColor: root.t.sysInfoTextMain + showBar: true + barPct: root.diskPct + barColor: root.t.sysInfoDiskColor + trackColor: root.t.sysInfoTrackColor + } + + Item { + Layout.fillWidth: true + implicitHeight: root.hasSwap ? swapItem.implicitHeight + 9 : 0 + visible: root.hasSwap + clip: true + + ColumnLayout { + id: swapItem + anchors { top: parent.top; left: parent.left; right: parent.right } + anchors.topMargin: 9 + spacing: 5 + + SysInfoRow { + Layout.fillWidth: true + icon: "󰾫" + label: "Swap" + value: root.swapUsedGb.toFixed(1) + " GB" + iconColor: root.t.sysInfoMemColor + dimColor: root.t.sysInfoTextDim + textColor: root.t.sysInfoTextMain + showBar: true + barPct: root.swapPct + barColor: root.t.sysInfoMemColor + trackColor: root.t.sysInfoTrackColor + } + } + } + + Item { Layout.preferredHeight: 9 } + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + Rectangle { + width: 18; height: 18 + radius: 4 + color: Qt.alpha(root.t.sysInfoAccent, 0.15) + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: "󰅐" + color: root.t.sysInfoAccent + font.pixelSize: 12 + } + } + + Text { + text: "Uptime" + color: root.t.sysInfoTextDim + font.pixelSize: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + Text { + text: root.uptimeStr + color: root.t.sysInfoTextMain + font.pixelSize: 12 + font.weight: Font.Medium + Layout.alignment: Qt.AlignVCenter + } + } + + Item { Layout.preferredHeight: 9 } + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + Rectangle { + width: 18; height: 18 + radius: 4 + color: Qt.alpha(root.t.sysInfoAccent, 0.15) + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: "" + color: root.t.sysInfoAccent + font.pixelSize: 12 + } + } + + Text { + text: "Kernel" + color: root.t.sysInfoTextDim + font.pixelSize: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + Text { + text: root.kernelVer + color: root.t.sysInfoTextMain + font.pixelSize: 12 + font.weight: Font.Medium + Layout.alignment: Qt.AlignVCenter + } + } + + Item { + Layout.fillWidth: true + implicitHeight: root.battPct >= 0 ? battItem.implicitHeight + 9 : 0 + visible: root.battPct >= 0 + clip: true + + ColumnLayout { + id: battItem + anchors { top: parent.top; left: parent.left; right: parent.right } + anchors.topMargin: 9 + spacing: 5 + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + Rectangle { + width: 18; height: 18 + radius: 4 + color: Qt.alpha(battIconColor, 0.15) + Layout.alignment: Qt.AlignVCenter + readonly property color battIconColor: + root.battPct <= 20 ? root.t.statusErr + : root.battPct <= 40 ? root.t.statusWarn + : root.battCharging ? root.t.statusOk + : root.t.sysInfoAccent + + Text { + anchors.centerIn: parent + text: root.battCharging ? "󰂄" + : root.battPct > 80 ? "󰁹" + : root.battPct > 60 ? "󰂀" + : root.battPct > 40 ? "󰁿" + : root.battPct > 20 ? "󰁾" + : "󰂃" + color: parent.battIconColor + font.pixelSize: 12 + } + } + + Text { + text: "Battery" + color: root.t.sysInfoTextDim + font.pixelSize: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + Text { + text: Math.round(root.battPct) + "%" + color: root.t.sysInfoTextMain + font.pixelSize: 12 + Layout.alignment: Qt.AlignVCenter + } + } + + Rectangle { + Layout.fillWidth: true + height: 3 + radius: 2 + color: root.t.sysInfoTrackColor + + readonly property color fillColor: + root.battPct <= 20 ? root.t.statusErr + : root.battPct <= 40 ? root.t.statusWarn + : root.battCharging ? root.t.statusOk + : root.t.sysInfoAccent + + Rectangle { + width: parent.width * Math.max(0, Math.min(root.battPct, 100)) / 100 + height: parent.height + radius: parent.radius + color: parent.fillColor + Behavior on width { NumberAnimation { duration: 800; easing.type: Easing.OutCubic } } + Behavior on color { ColorAnimation { duration: 400 } } + } + } + } + } + + Item { Layout.preferredHeight: 9 } + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + Rectangle { + width: 18; height: 18 + radius: 4 + color: Qt.alpha(root.netOnline ? root.t.statusOk : root.t.sysInfoTextDim, 0.15) + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: root.netOnline ? "󰤨" : "󰤭" + color: root.netOnline ? root.t.statusOk : root.t.sysInfoTextDim + font.pixelSize: 12 + } + } + + Text { + text: "Network" + color: root.t.sysInfoTextDim + font.pixelSize: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + Text { + text: root.netOnline ? "Connected" : "Offline" + color: root.netOnline ? root.t.statusOk : root.t.statusErr + font.pixelSize: 12 + font.weight: Font.Medium + Layout.alignment: Qt.AlignVCenter + } + } +} diff --git a/widgets/sidebar/sysinfo/SysInfoRow.qml b/widgets/sidebar/sysinfo/SysInfoRow.qml new file mode 100644 index 0000000..fe390b5 --- /dev/null +++ b/widgets/sidebar/sysinfo/SysInfoRow.qml @@ -0,0 +1,90 @@ +import QtQuick +import QtQuick.Layouts + +// ── SysInfoRow ──────────────────────────────────────────────────────────────── +// Metric row with icon badge, label, right-aligned value, and an optional +// animated progress bar underneath. +Item { + id: root + + property string icon: "" + property string label: "" + property string value: "—" + property color iconColor: "#ffffffff" + property color dimColor: "#997a8996" + property color textColor: "#ffe8eef2" + property bool showBar: false + property int barPct: 0 // 0-100 + property color barColor: iconColor + property color trackColor: "#15ffffff" + + implicitHeight: col.implicitHeight + implicitWidth: col.implicitWidth + + ColumnLayout { + id: col + anchors { left: parent.left; right: parent.right } + spacing: 5 + + // ── Label row ───────────────────────────────────────────────────────── + RowLayout { + Layout.fillWidth: true + spacing: 10 + + // Icon in a tinted pill badge + Rectangle { + width: 18; height: 18 + radius: 4 + color: Qt.alpha(root.iconColor, 0.15) + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: root.icon + color: root.iconColor + font.pixelSize: 12 + } + } + + Text { + text: root.label + color: root.dimColor + font.pixelSize: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + Text { + text: root.value + color: root.textColor + font.pixelSize: 12 + font.weight: Font.Medium + Layout.alignment: Qt.AlignVCenter + } + } + + // ── Progress bar (optional) ─────────────────────────────────────────── + Rectangle { + visible: root.showBar + Layout.fillWidth: true + height: 3 + radius: 2 + color: root.trackColor + + Rectangle { + width: parent.width * Math.max(0, Math.min(root.barPct, 100)) / 100 + height: parent.height + radius: parent.radius + color: root.barColor + + // smooth fill transitions on data refresh + Behavior on width { + NumberAnimation { duration: 800; easing.type: Easing.OutCubic } + } + Behavior on color { + ColorAnimation { duration: 300 } + } + } + } + } +} diff --git a/widgets/sidebar/weather/WeatherWidget.qml b/widgets/sidebar/weather/WeatherWidget.qml new file mode 100644 index 0000000..3980524 --- /dev/null +++ b/widgets/sidebar/weather/WeatherWidget.qml @@ -0,0 +1,319 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell.Io +import "../../../config" as Cfg + +Item { + id: root + + implicitHeight: contentCol.implicitHeight + + readonly property var t: Cfg.Config.theme + + property string icon: "—" + property string condition: "—" + property string temp: "—" + property string feelsLike: "—" + property string humidity: "—" + property string wind: "—" + property string location: "—" + + readonly property string _url: { + var loc = Cfg.Config.weatherLocation.trim() + if (!loc) return "wttr.in?format=%t|%f|%c|%C|%h|%w|%l&m" + loc = loc.replace(/ /g, "+") + return "wttr.in/" + loc + "?format=%t|%f|%c|%C|%h|%w|%l&m" + } + + function fetchWeather() { + weatherProc.command = ["sh", "-c", "curl -s \"" + root._url + "\""] + weatherProc.running = true + } + + Timer { + interval: Cfg.Config.weatherRefreshMin * 60000 + running: true + repeat: true + triggeredOnStart: true + onTriggered: root.fetchWeather() + } + + Process { + id: weatherProc + property string _buf: "" + command: ["sh", "-c", ""] + stdout: SplitParser { + onRead: d => { weatherProc._buf = d } + } + onRunningChanged: { + if (running || !_buf) return + var parts = _buf.trim().split("|") + if (parts.length >= 7) { + root.temp = parts[0] || "—" + root.feelsLike = parts[1] || "—" + root.icon = parts[2] || "—" + root.condition = parts[3] || "—" + root.humidity = parts[4] || "—" + root.wind = parts[5] || "—" + root.location = parts[6] || "—" + } + _buf = "" + } + } + + ColumnLayout { + id: contentCol + anchors { left: parent.left; right: parent.right; top: parent.top } + spacing: 0 + + Rectangle { + Layout.fillWidth: true + height: 32 + color: "transparent" + + RowLayout { + anchors.fill: parent + spacing: 10 + + Rectangle { + width: 32; height: 32 + radius: 8 + color: Qt.alpha(root.t.weatherAccent, 0.12) + border.color: Qt.alpha(root.t.weatherAccent, 0.22) + border.width: 1 + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: root.icon + color: root.t.weatherAccent + font.pixelSize: 18 + } + } + + ColumnLayout { + spacing: 2 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + + Text { + text: root.condition + color: root.t.weatherTextMain + font.pixelSize: 13 + font.weight: Font.DemiBold + elide: Text.ElideRight + Layout.fillWidth: true + } + Text { + text: root.location + color: root.t.weatherTextDim + font.pixelSize: 10 + opacity: 0.75 + elide: Text.ElideRight + Layout.fillWidth: true + } + } + + Rectangle { + width: 24; height: 24 + radius: 6 + color: refreshMouse.containsMouse + ? (refreshMouse.pressed ? Qt.alpha(root.t.weatherAccent, 0.25) : Qt.alpha(root.t.weatherAccent, 0.12)) + : "transparent" + Layout.alignment: Qt.AlignVCenter + + Behavior on color { ColorAnimation { duration: 150 } } + + Text { + id: refreshIcon + anchors.centerIn: parent + text: "󰑐" + color: refreshMouse.containsMouse ? root.t.weatherAccent : root.t.weatherTextDim + font.pixelSize: 14 + Behavior on color { ColorAnimation { duration: 150 } } + + RotationAnimator { + id: spinAnim + target: refreshIcon + from: 0; to: 360 + duration: 600 + easing.type: Easing.OutCubic + running: false + } + } + + MouseArea { + id: refreshMouse + anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor + onClicked: { + spinAnim.restart() + root.fetchWeather() + } + } + } + } + } + + Item { Layout.preferredHeight: 12 } + + Rectangle { + Layout.fillWidth: true + height: 1 + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { position: 0.0; color: Qt.alpha(root.t.weatherAccent, 0.5) } + GradientStop { position: 1.0; color: "transparent" } + } + } + + Item { Layout.preferredHeight: 10 } + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + Rectangle { + width: 18; height: 18 + radius: 4 + color: Qt.alpha(root.t.weatherTempColor, 0.15) + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: "󰔄" + color: root.t.weatherTempColor + font.pixelSize: 12 + } + } + + Text { + text: "Temperature" + color: root.t.weatherTextDim + font.pixelSize: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + Text { + text: root.temp + color: root.t.weatherTextMain + font.pixelSize: 12 + font.weight: Font.Medium + Layout.alignment: Qt.AlignVCenter + } + } + + Item { Layout.preferredHeight: 9 } + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + Rectangle { + width: 18; height: 18 + radius: 4 + color: Qt.alpha(root.t.weatherFeelsColor, 0.15) + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: "󰔄" + color: root.t.weatherFeelsColor + font.pixelSize: 12 + } + } + + Text { + text: "Feels like" + color: root.t.weatherTextDim + font.pixelSize: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + Text { + text: root.feelsLike + color: root.t.weatherTextMain + font.pixelSize: 12 + font.weight: Font.Medium + Layout.alignment: Qt.AlignVCenter + } + } + + Item { Layout.preferredHeight: 9 } + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + Rectangle { + width: 18; height: 18 + radius: 4 + color: Qt.alpha(root.t.weatherHumidColor, 0.15) + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: "󰃚" + color: root.t.weatherHumidColor + font.pixelSize: 12 + } + } + + Text { + text: "Humidity" + color: root.t.weatherTextDim + font.pixelSize: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + Text { + text: root.humidity + color: root.t.weatherTextMain + font.pixelSize: 12 + font.weight: Font.Medium + Layout.alignment: Qt.AlignVCenter + } + } + + Item { Layout.preferredHeight: 9 } + + RowLayout { + Layout.fillWidth: true + spacing: 10 + + Rectangle { + width: 18; height: 18 + radius: 4 + color: Qt.alpha(root.t.weatherWindColor, 0.15) + Layout.alignment: Qt.AlignVCenter + + Text { + anchors.centerIn: parent + text: "󰖝" + color: root.t.weatherWindColor + font.pixelSize: 12 + } + } + + Text { + text: "Wind" + color: root.t.weatherTextDim + font.pixelSize: 12 + Layout.fillWidth: true + Layout.alignment: Qt.AlignVCenter + } + + Text { + text: root.wind + color: root.t.weatherTextMain + font.pixelSize: 12 + font.weight: Font.Medium + Layout.alignment: Qt.AlignVCenter + } + } + + Item { Layout.preferredHeight: 6 } + } +}