fixed notifications font rendering
This commit is contained in:
@@ -5,24 +5,15 @@ import Quickshell.Wayland
|
|||||||
import Quickshell.Services.UPower
|
import Quickshell.Services.UPower
|
||||||
|
|
||||||
import "../../config" as Cfg
|
import "../../config" as Cfg
|
||||||
|
import "../../components"
|
||||||
|
|
||||||
Rectangle {
|
ModuleChip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real panelRadius: Cfg.Config.radius / 2
|
|
||||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
|
||||||
|
|
||||||
property bool isTop: true
|
|
||||||
property var targetScreen: null
|
|
||||||
property int barHeight: Cfg.Config.barHeight
|
|
||||||
property int barMargin: Cfg.Config.margin
|
|
||||||
|
|
||||||
readonly property var t: Cfg.Config.theme
|
|
||||||
|
|
||||||
readonly property var bat: UPower.displayDevice
|
readonly property var bat: UPower.displayDevice
|
||||||
readonly property bool batReady: bat && bat.ready && bat.isLaptopBattery
|
readonly property bool batReady: bat && bat.ready && bat.isLaptopBattery
|
||||||
|
|
||||||
readonly property bool moduleEnabled: batReady
|
readonly property bool moduleEnabled: false
|
||||||
|
|
||||||
readonly property real pct: batReady ? bat.percentage * 100 : 72
|
readonly property real pct: batReady ? bat.percentage * 100 : 72
|
||||||
readonly property int state: batReady ? bat.state : UPowerDeviceState.Unknown
|
readonly property int state: batReady ? bat.state : UPowerDeviceState.Unknown
|
||||||
@@ -163,53 +154,11 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PopupPanel {
|
||||||
id: batteryPopup
|
id: batteryPopup
|
||||||
screen: root.targetScreen
|
ns: "battery"
|
||||||
visible: false
|
chipRoot: root
|
||||||
color: "transparent"
|
cardWidth: 260
|
||||||
|
|
||||||
property bool popupOpen: false
|
|
||||||
|
|
||||||
function open() { hideTimer.stop(); visible = true; popupOpen = true }
|
|
||||||
function close() { popupOpen = false; hideTimer.restart() }
|
|
||||||
function toggle() { popupOpen ? close() : open() }
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: hideTimer
|
|
||||||
interval: Cfg.Config.popupAnimDuration + 70
|
|
||||||
onTriggered: batteryPopup.visible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors { top: true; bottom: true; left: true; right: true }
|
|
||||||
WlrLayershell.layer: WlrLayer.Top
|
|
||||||
WlrLayershell.namespace: "main-shell-battery"
|
|
||||||
WlrLayershell.exclusiveZone: -1
|
|
||||||
mask: popupOpen ? null : _noInput
|
|
||||||
Region { id: _noInput }
|
|
||||||
|
|
||||||
TapHandler { onTapped: batteryPopup.close() }
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: popupClipContainer
|
|
||||||
readonly property int cardW: 260
|
|
||||||
readonly property int screenPad: root.barMargin + 10
|
|
||||||
|
|
||||||
x: {
|
|
||||||
let centerX = root.mapToItem(null, 0, 0).x + root.width / 2
|
|
||||||
let desiredX = centerX - cardW / 2
|
|
||||||
return Math.max(screenPad,
|
|
||||||
Math.min(desiredX, parent.width - cardW - screenPad))
|
|
||||||
}
|
|
||||||
width: cardW
|
|
||||||
|
|
||||||
anchors.top: root.isTop ? parent.top : undefined
|
|
||||||
anchors.bottom: root.isTop ? undefined : parent.bottom
|
|
||||||
anchors.topMargin: root.isTop ? (root.barHeight + 10) : 0
|
|
||||||
anchors.bottomMargin: root.isTop ? 0 : (root.barHeight + 10)
|
|
||||||
height: parent.height - root.barHeight - 10
|
|
||||||
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: cardShadow
|
id: cardShadow
|
||||||
@@ -586,4 +535,3 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,19 +6,9 @@ import Quickshell.Wayland
|
|||||||
import "../../config" as Cfg
|
import "../../config" as Cfg
|
||||||
import "../../components"
|
import "../../components"
|
||||||
|
|
||||||
Rectangle {
|
ModuleChip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real panelRadius: Cfg.Config.radius / 2
|
|
||||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
|
||||||
|
|
||||||
property bool isTop: true
|
|
||||||
property var targetScreen: null
|
|
||||||
property int barHeight: Cfg.Config.barHeight
|
|
||||||
property int barMargin: Cfg.Config.margin
|
|
||||||
|
|
||||||
readonly property var t: Cfg.Config.theme
|
|
||||||
|
|
||||||
TimezoneProvider { id: timezone }
|
TimezoneProvider { id: timezone }
|
||||||
|
|
||||||
width: clockLayout.implicitWidth + 24
|
width: clockLayout.implicitWidth + 24
|
||||||
@@ -92,52 +82,11 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PopupPanel {
|
||||||
id: calendarPopup
|
id: calendarPopup
|
||||||
screen: root.targetScreen
|
ns: "calendar"
|
||||||
visible: false
|
chipRoot: root
|
||||||
color: "transparent"
|
cardWidth: 284
|
||||||
|
|
||||||
property bool popupOpen: false
|
|
||||||
|
|
||||||
function open() { hideTimer.stop(); visible = true; popupOpen = true }
|
|
||||||
function close() { popupOpen = false; hideTimer.restart() }
|
|
||||||
function toggle() { popupOpen ? close() : open() }
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: hideTimer
|
|
||||||
interval: Cfg.Config.popupAnimDuration + 70
|
|
||||||
onTriggered: calendarPopup.visible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors { top: true; bottom: true; left: true; right: true }
|
|
||||||
WlrLayershell.layer: WlrLayer.Top
|
|
||||||
WlrLayershell.namespace: "main-shell-calendar"
|
|
||||||
WlrLayershell.exclusiveZone: -1
|
|
||||||
mask: popupOpen ? null : _noInput
|
|
||||||
Region { id: _noInput }
|
|
||||||
|
|
||||||
TapHandler { onTapped: calendarPopup.close() }
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: calClipContainer
|
|
||||||
readonly property int cardW: 284
|
|
||||||
readonly property int screenPad: root.barMargin + 10
|
|
||||||
|
|
||||||
x: {
|
|
||||||
let centerX = root.mapToItem(null, 0, 0).x + root.width / 2
|
|
||||||
let desiredX = centerX - cardW / 2
|
|
||||||
return Math.max(screenPad, Math.min(desiredX, parent.width - cardW - screenPad))
|
|
||||||
}
|
|
||||||
width: cardW
|
|
||||||
|
|
||||||
anchors.top: root.isTop ? parent.top : undefined
|
|
||||||
anchors.bottom: root.isTop ? undefined : parent.bottom
|
|
||||||
anchors.topMargin: root.isTop ? (root.barHeight + 10) : 0
|
|
||||||
anchors.bottomMargin: root.isTop ? 0 : (root.barHeight + 10)
|
|
||||||
height: parent.height - root.barHeight - 10
|
|
||||||
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: card
|
id: card
|
||||||
@@ -409,4 +358,3 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,18 +5,11 @@ import Quickshell.Wayland
|
|||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
|
||||||
import "../../config" as Cfg
|
import "../../config" as Cfg
|
||||||
|
import "../../components"
|
||||||
|
|
||||||
Rectangle {
|
ModuleChip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real panelRadius: Cfg.Config.radius / 2
|
|
||||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
|
||||||
property bool isTop: true
|
|
||||||
property var targetScreen: null
|
|
||||||
property int barHeight: Cfg.Config.barHeight
|
|
||||||
property int barMargin: Cfg.Config.margin
|
|
||||||
|
|
||||||
readonly property var t: Cfg.Config.theme
|
|
||||||
readonly property var cfg: Cfg.Config
|
readonly property var cfg: Cfg.Config
|
||||||
|
|
||||||
readonly property string configPath:
|
readonly property string configPath:
|
||||||
@@ -43,36 +36,24 @@ Rectangle {
|
|||||||
Behavior on color { ColorAnimation { duration: 150 } }
|
Behavior on color { ColorAnimation { duration: 150 } }
|
||||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||||
|
|
||||||
property var localPairs: [{ coin: cfg.cryptoCoinId ?? "bitcoin", currency: cfg.cryptoVsCurrency ?? "usd" }]
|
property var localPairs: [{ coin: "bitcoin", currency: "usd" }]
|
||||||
property int activeCoinIndex: 0
|
property int activeCoinIndex: 0
|
||||||
readonly property string localCoinId: localPairs.length > 0
|
readonly property string localCoinId: localPairs.length > 0
|
||||||
? localPairs[activeCoinIndex % localPairs.length].coin
|
? localPairs[activeCoinIndex % localPairs.length].coin
|
||||||
: (cfg.cryptoCoinId ?? "bitcoin")
|
: "bitcoin"
|
||||||
readonly property string localActiveCurrency: localPairs.length > 0
|
readonly property string localActiveCurrency: localPairs.length > 0
|
||||||
? localPairs[activeCoinIndex % localPairs.length].currency
|
? localPairs[activeCoinIndex % localPairs.length].currency
|
||||||
: (cfg.cryptoVsCurrency ?? "usd")
|
: "usd"
|
||||||
|
|
||||||
property string localVsCur: cfg.cryptoVsCurrency ?? "usd"
|
property string localVsCur: "usd"
|
||||||
property int localDecimals: cfg.cryptoDecimals ?? 1
|
property int localDecimals: cfg.cryptoDecimals ?? 1
|
||||||
property int localRefreshSec: cfg.cryptoRefreshSec ?? 60
|
property int localRefreshSec: cfg.cryptoRefreshSec ?? 60
|
||||||
property bool localShowIcon: cfg.cryptoShowIcon ?? true
|
property bool localShowIcon: cfg.cryptoShowIcon ?? true
|
||||||
|
|
||||||
function resolveWithPersistence() {
|
function resolveWithPersistence() {
|
||||||
const cfgCoin = cfg.cryptoCoinId ?? "bitcoin"
|
root.localPairs = Array.isArray(cfg.cryptoPairs) && cfg.cryptoPairs.length > 0 ? cfg.cryptoPairs : [{ coin: "bitcoin", currency: "usd" }]
|
||||||
const cfgCur = cfg.cryptoVsCurrency ?? "usd"
|
root.localVsCur = root.localPairs[0].currency
|
||||||
|
root.displayCurrency = root.localPairs[0].currency
|
||||||
let cfgPairs
|
|
||||||
if (typeof cfg.cryptoPairs !== "undefined" && Array.isArray(cfg.cryptoPairs) && cfg.cryptoPairs.length > 0) {
|
|
||||||
cfgPairs = cfg.cryptoPairs
|
|
||||||
} else if (typeof cfg.cryptoCoinIds !== "undefined" && Array.isArray(cfg.cryptoCoinIds) && cfg.cryptoCoinIds.length > 0) {
|
|
||||||
cfgPairs = cfg.cryptoCoinIds.map(c => ({ coin: c, currency: cfgCur }))
|
|
||||||
} else {
|
|
||||||
cfgPairs = [{ coin: cfgCoin, currency: cfgCur }]
|
|
||||||
}
|
|
||||||
|
|
||||||
root.localPairs = cfgPairs
|
|
||||||
root.localVsCur = cfgPairs.length > 0 ? cfgPairs[0].currency : cfgCur
|
|
||||||
root.displayCurrency = cfgPairs.length > 0 ? cfgPairs[0].currency : cfgCur
|
|
||||||
root.activeCoinIndex = 0
|
root.activeCoinIndex = 0
|
||||||
root.localDecimals = cfg.cryptoDecimals ?? 1
|
root.localDecimals = cfg.cryptoDecimals ?? 1
|
||||||
root.localRefreshSec = cfg.cryptoRefreshSec ?? 60
|
root.localRefreshSec = cfg.cryptoRefreshSec ?? 60
|
||||||
@@ -123,7 +104,7 @@ Rectangle {
|
|||||||
property string coinSymbol: localCoinId.toUpperCase().slice(0, 4)
|
property string coinSymbol: localCoinId.toUpperCase().slice(0, 4)
|
||||||
property string coinName: ""
|
property string coinName: ""
|
||||||
property string lastUpdated: ""
|
property string lastUpdated: ""
|
||||||
property string displayCurrency: cfg.cryptoVsCurrency ?? "usd"
|
property string displayCurrency: "usd"
|
||||||
property bool loading: false
|
property bool loading: false
|
||||||
property bool loadingVisible: false
|
property bool loadingVisible: false
|
||||||
property bool hasError: false
|
property bool hasError: false
|
||||||
@@ -289,54 +270,18 @@ Rectangle {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PopupPanel {
|
||||||
id: cryptoPopup
|
id: cryptoPopup
|
||||||
screen: root.targetScreen
|
ns: "crypto"
|
||||||
visible: false
|
chipRoot: root
|
||||||
color: "transparent"
|
cardWidth: 300
|
||||||
|
hasKeyboardFocus: true
|
||||||
|
|
||||||
property bool popupOpen: false
|
function open() {
|
||||||
property real popupCenterX: 0
|
popupCenterX = root.mapToItem(null, 0, 0).x + root.width / 2
|
||||||
|
_doOpen()
|
||||||
function open() { popupCenterX = root.mapToItem(null, 0, 0).x + root.width / 2; hideTimer.stop(); visible = true; popupOpen = true }
|
|
||||||
function close() { popupOpen = false; hideTimer.restart() }
|
|
||||||
function toggle() { popupOpen ? close() : open() }
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: hideTimer
|
|
||||||
interval: Cfg.Config.popupAnimDuration + 70
|
|
||||||
onTriggered: cryptoPopup.visible = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors { top: true; bottom: true; left: true; right: true }
|
|
||||||
WlrLayershell.layer: WlrLayer.Top
|
|
||||||
WlrLayershell.namespace: "main-shell-crypto"
|
|
||||||
WlrLayershell.exclusiveZone: -1
|
|
||||||
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
|
|
||||||
mask: popupOpen ? null : _noInput
|
|
||||||
Region { id: _noInput }
|
|
||||||
|
|
||||||
TapHandler { onTapped: cryptoPopup.close() }
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: popClip
|
|
||||||
readonly property int cardW: 300
|
|
||||||
readonly property int screenPad: root.barMargin + 10
|
|
||||||
|
|
||||||
x: {
|
|
||||||
let cx = cryptoPopup.popupCenterX
|
|
||||||
return Math.max(screenPad,
|
|
||||||
Math.min(cx - cardW / 2, parent.width - cardW - screenPad))
|
|
||||||
}
|
|
||||||
width: cardW
|
|
||||||
|
|
||||||
anchors.top: root.isTop ? parent.top : undefined
|
|
||||||
anchors.bottom: root.isTop ? undefined : parent.bottom
|
|
||||||
anchors.topMargin: root.isTop ? (root.barHeight + 10) : 0
|
|
||||||
anchors.bottomMargin: root.isTop ? 0 : (root.barHeight + 10)
|
|
||||||
height: parent.height - root.barHeight - 10
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: card
|
id: card
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -1166,19 +1111,9 @@ Rectangle {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent; cursorShape: Qt.PointingHandCursor
|
anchors.fill: parent; cursorShape: Qt.PointingHandCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
const cfgCoin = cfg.cryptoCoinId ?? "bitcoin"
|
root.localPairs = Array.isArray(cfg.cryptoPairs) && cfg.cryptoPairs.length > 0 ? cfg.cryptoPairs : [{ coin: "bitcoin", currency: "usd" }]
|
||||||
const cfgCur = cfg.cryptoVsCurrency ?? "usd"
|
root.localVsCur = "usd"
|
||||||
let cfgPairs
|
root.displayCurrency = root.localPairs.length > 0 ? root.localPairs[0].currency : "usd"
|
||||||
if (typeof cfg.cryptoPairs !== "undefined" && Array.isArray(cfg.cryptoPairs) && cfg.cryptoPairs.length > 0) {
|
|
||||||
cfgPairs = cfg.cryptoPairs
|
|
||||||
} else if (typeof cfg.cryptoCoinIds !== "undefined" && Array.isArray(cfg.cryptoCoinIds) && cfg.cryptoCoinIds.length > 0) {
|
|
||||||
cfgPairs = cfg.cryptoCoinIds.map(c => ({ coin: c, currency: cfgCur }))
|
|
||||||
} else {
|
|
||||||
cfgPairs = [{ coin: cfgCoin, currency: cfgCur }]
|
|
||||||
}
|
|
||||||
root.localPairs = cfgPairs
|
|
||||||
root.localVsCur = cfgCur
|
|
||||||
root.displayCurrency = cfgPairs.length > 0 ? cfgPairs[0].currency : cfgCur
|
|
||||||
root.activeCoinIndex = 0
|
root.activeCoinIndex = 0
|
||||||
root.localDecimals = cfg.cryptoDecimals ?? 1
|
root.localDecimals = cfg.cryptoDecimals ?? 1
|
||||||
root.localRefreshSec = cfg.cryptoRefreshSec ?? 60
|
root.localRefreshSec = cfg.cryptoRefreshSec ?? 60
|
||||||
@@ -1197,4 +1132,3 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,20 +1,11 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
|
|
||||||
import "../../config" as Cfg
|
import "../../config" as Cfg
|
||||||
|
import "../../components"
|
||||||
|
|
||||||
Rectangle {
|
ModuleChip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real panelRadius: Cfg.Config.radius / 2
|
|
||||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
|
||||||
|
|
||||||
property bool isTop: true
|
|
||||||
property var targetScreen: null
|
|
||||||
property int barHeight: Cfg.Config.barHeight
|
|
||||||
property int barMargin: Cfg.Config.margin
|
|
||||||
|
|
||||||
readonly property var t: Cfg.Config.theme
|
|
||||||
|
|
||||||
property var launcher: null
|
property var launcher: null
|
||||||
|
|
||||||
readonly property bool launcherActive: !!launcher && launcher.isOpen
|
readonly property bool launcherActive: !!launcher && launcher.isOpen
|
||||||
|
|||||||
@@ -3,22 +3,13 @@ import QtQuick.Layouts
|
|||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Networking
|
import Quickshell.Networking
|
||||||
import Quickshell.Services.Polkit
|
|
||||||
|
|
||||||
import "../../config" as Cfg
|
import "../../config" as Cfg
|
||||||
|
import "../../components"
|
||||||
|
|
||||||
Rectangle {
|
ModuleChip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real panelRadius: Cfg.Config.radius / 2
|
|
||||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
|
||||||
property bool isTop: true
|
|
||||||
property var targetScreen: null
|
|
||||||
property int barHeight: Cfg.Config.barHeight
|
|
||||||
property int barMargin: Cfg.Config.margin
|
|
||||||
|
|
||||||
readonly property var t: Cfg.Config.theme
|
|
||||||
|
|
||||||
readonly property var wifiDevice: {
|
readonly property var wifiDevice: {
|
||||||
for (const dev of (Networking.devices?.values ?? []))
|
for (const dev of (Networking.devices?.values ?? []))
|
||||||
if (dev.type === DeviceType.Wifi) return dev
|
if (dev.type === DeviceType.Wifi) return dev
|
||||||
@@ -159,58 +150,18 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PopupPanel {
|
||||||
id: netPopup
|
id: netPopup
|
||||||
screen: root.targetScreen
|
ns: "network"
|
||||||
visible: false
|
chipRoot: root
|
||||||
color: "transparent"
|
cardWidth: 310
|
||||||
|
|
||||||
property bool popupOpen: false
|
|
||||||
|
|
||||||
function open() {
|
function open() {
|
||||||
root.cancelConnect()
|
root.cancelConnect()
|
||||||
hideTimer.stop()
|
_doOpen()
|
||||||
visible = true
|
|
||||||
popupOpen = true
|
|
||||||
if (root.hasWifi && root.wifiDevice)
|
if (root.hasWifi && root.wifiDevice)
|
||||||
root.wifiDevice.scannerEnabled = true
|
root.wifiDevice.scannerEnabled = true
|
||||||
}
|
}
|
||||||
function close() { popupOpen = false; hideTimer.restart() }
|
|
||||||
function toggle() { popupOpen ? close() : open() }
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: hideTimer
|
|
||||||
interval: Cfg.Config.popupAnimDuration + 70
|
|
||||||
onTriggered: netPopup.visible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors { top: true; bottom: true; left: true; right: true }
|
|
||||||
WlrLayershell.layer: WlrLayer.Top
|
|
||||||
WlrLayershell.namespace: "main-shell-network"
|
|
||||||
WlrLayershell.exclusiveZone: -1
|
|
||||||
mask: netPopup.popupOpen ? null : _noInput
|
|
||||||
Region { id: _noInput }
|
|
||||||
|
|
||||||
TapHandler { onTapped: netPopup.close() }
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: popupClip
|
|
||||||
readonly property int cardW: 310
|
|
||||||
readonly property int screenPad: root.barMargin + 10
|
|
||||||
|
|
||||||
x: {
|
|
||||||
var cx = root.mapToItem(null, 0, 0).x + root.width / 2
|
|
||||||
var dx = cx - cardW / 2
|
|
||||||
return Math.max(screenPad, Math.min(dx, parent.width - cardW - screenPad))
|
|
||||||
}
|
|
||||||
width: cardW
|
|
||||||
|
|
||||||
anchors.top: root.isTop ? parent.top : undefined
|
|
||||||
anchors.bottom: root.isTop ? undefined : parent.bottom
|
|
||||||
anchors.topMargin: root.isTop ? (root.barHeight + 10) : 0
|
|
||||||
anchors.bottomMargin: root.isTop ? 0 : (root.barHeight + 10)
|
|
||||||
height: parent.height - root.barHeight - 10
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: card
|
id: card
|
||||||
@@ -725,4 +676,3 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,18 +6,11 @@ import Quickshell.Wayland
|
|||||||
import Quickshell.Services.Notifications
|
import Quickshell.Services.Notifications
|
||||||
|
|
||||||
import "../../config" as Cfg
|
import "../../config" as Cfg
|
||||||
|
import "../../components"
|
||||||
|
|
||||||
Rectangle {
|
ModuleChip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real panelRadius: Cfg.Config.radius / 2
|
|
||||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
|
||||||
property bool isTop: true
|
|
||||||
property var targetScreen: null
|
|
||||||
property int barHeight: Cfg.Config.barHeight
|
|
||||||
property int barMargin: Cfg.Config.margin
|
|
||||||
readonly property var t: Cfg.Config.theme
|
|
||||||
|
|
||||||
property int unreadCount: 0
|
property int unreadCount: 0
|
||||||
property bool doNotDisturb: false
|
property bool doNotDisturb: false
|
||||||
property bool historyOpen: historyPopup.popupOpen
|
property bool historyOpen: historyPopup.popupOpen
|
||||||
@@ -111,7 +104,6 @@ Rectangle {
|
|||||||
? toastRoot.t.notifUrgencyCritical
|
? toastRoot.t.notifUrgencyCritical
|
||||||
: (cardHover.hovered ? toastRoot.t.notifBorderActive : toastRoot.t.notifToastBorder)
|
: (cardHover.hovered ? toastRoot.t.notifBorderActive : toastRoot.t.notifToastBorder)
|
||||||
border.width: Cfg.Config.popupBorderWidth
|
border.width: Cfg.Config.popupBorderWidth
|
||||||
layer.enabled: true
|
|
||||||
|
|
||||||
Behavior on color { ColorAnimation { duration: 150; easing.type: Easing.OutCubic } }
|
Behavior on color { ColorAnimation { duration: 150; easing.type: Easing.OutCubic } }
|
||||||
Behavior on border.color { ColorAnimation { duration: 150 } }
|
Behavior on border.color { ColorAnimation { duration: 150 } }
|
||||||
@@ -152,22 +144,26 @@ Rectangle {
|
|||||||
color: toastRoot.urgencyColor(toastRoot.urgency)
|
color: toastRoot.urgencyColor(toastRoot.urgency)
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: toastRoot.appName
|
text: toastRoot.appName
|
||||||
color: toastRoot.t.notifToastAppName
|
color: toastRoot.t.notifToastAppName
|
||||||
font.pixelSize: 11
|
font.pixelSize: 12
|
||||||
font.bold: true
|
font.bold: true
|
||||||
font.capitalization: Font.AllUppercase
|
font.capitalization: Font.AllUppercase
|
||||||
|
font.letterSpacing: 0.4
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: toastRoot.timeStr
|
text: toastRoot.timeStr
|
||||||
color: toastRoot.t.notifToastDim
|
color: toastRoot.t.notifToastDim
|
||||||
font.pixelSize: 10
|
font.pixelSize: 11
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -181,6 +177,7 @@ Rectangle {
|
|||||||
text: "✕"
|
text: "✕"
|
||||||
color: closeHover.hovered ? toastRoot.t.notifToastText : toastRoot.t.notifToastDim
|
color: closeHover.hovered ? toastRoot.t.notifToastText : toastRoot.t.notifToastDim
|
||||||
font.pixelSize: 10
|
font.pixelSize: 10
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
HoverHandler { id: closeHover; cursorShape: Qt.PointingHandCursor }
|
HoverHandler { id: closeHover; cursorShape: Qt.PointingHandCursor }
|
||||||
TapHandler { onTapped: toastRoot.triggerDismiss() }
|
TapHandler { onTapped: toastRoot.triggerDismiss() }
|
||||||
@@ -196,6 +193,7 @@ Rectangle {
|
|||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
textFormat: Text.PlainText
|
textFormat: Text.PlainText
|
||||||
visible: toastRoot.summary !== ""
|
visible: toastRoot.summary !== ""
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
@@ -209,7 +207,8 @@ Rectangle {
|
|||||||
textFormat: Text.PlainText
|
textFormat: Text.PlainText
|
||||||
visible: toastRoot.body !== ""
|
visible: toastRoot.body !== ""
|
||||||
Layout.bottomMargin: toastRoot.urgency === NotificationUrgency.Low ? 6 : 0
|
Layout.bottomMargin: toastRoot.urgency === NotificationUrgency.Low ? 6 : 0
|
||||||
lineHeight: 1.15
|
lineHeight: 1.2
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +285,7 @@ Rectangle {
|
|||||||
Behavior on opacity { NumberAnimation { duration: 150 } }
|
Behavior on opacity { NumberAnimation { duration: 150 } }
|
||||||
Behavior on color { ColorAnimation { duration: 150 } }
|
Behavior on color { ColorAnimation { duration: 150 } }
|
||||||
|
|
||||||
Text { anchors.centerIn: parent; text: "✕"; color: histRoot.t.notifToastText; font.pixelSize: 10 }
|
Text { anchors.centerIn: parent; text: "✕"; color: histRoot.t.notifToastText; font.pixelSize: 10; renderType: Text.NativeRendering }
|
||||||
HoverHandler { id: histCloseHover; cursorShape: Qt.PointingHandCursor }
|
HoverHandler { id: histCloseHover; cursorShape: Qt.PointingHandCursor }
|
||||||
TapHandler { onTapped: dismissAnim.start() }
|
TapHandler { onTapped: dismissAnim.start() }
|
||||||
}
|
}
|
||||||
@@ -298,21 +297,24 @@ Rectangle {
|
|||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.fillWidth: true; spacing: 5
|
Layout.fillWidth: true; spacing: 5
|
||||||
Text { text: histRoot.urgencyIcon(histRoot.urgency); color: histRoot.urgencyColor(histRoot.urgency); font.pixelSize: 11; Layout.alignment: Qt.AlignVCenter }
|
Text { text: histRoot.urgencyIcon(histRoot.urgency); color: histRoot.urgencyColor(histRoot.urgency); font.pixelSize: 11; Layout.alignment: Qt.AlignVCenter; renderType: Text.NativeRendering }
|
||||||
Text {
|
Text {
|
||||||
text: histRoot.appName; color: histRoot.t.notifToastAppName; font.pixelSize: 11; font.bold: true
|
text: histRoot.appName; color: histRoot.t.notifToastAppName; font.pixelSize: 12; font.bold: true
|
||||||
font.capitalization: Font.AllUppercase; Layout.fillWidth: true; elide: Text.ElideRight; verticalAlignment: Text.AlignVCenter
|
font.capitalization: Font.AllUppercase; font.letterSpacing: 0.4; Layout.fillWidth: true; elide: Text.ElideRight; verticalAlignment: Text.AlignVCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Text { text: histRoot.timeStr; color: histRoot.t.notifToastDim; font.pixelSize: 11; verticalAlignment: Text.AlignVCenter }
|
Text { text: histRoot.timeStr; color: histRoot.t.notifToastDim; font.pixelSize: 11; verticalAlignment: Text.AlignVCenter; renderType: Text.NativeRendering }
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
text: histRoot.summary; color: histRoot.t.notifToastText; font.pixelSize: 13; font.bold: true
|
text: histRoot.summary; color: histRoot.t.notifToastText; font.pixelSize: 13; font.bold: true
|
||||||
Layout.fillWidth: true; elide: Text.ElideRight; textFormat: Text.PlainText; visible: histRoot.summary !== ""
|
Layout.fillWidth: true; elide: Text.ElideRight; textFormat: Text.PlainText; visible: histRoot.summary !== ""
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: histRoot.body; color: histRoot.t.notifToastDim; font.pixelSize: 12; Layout.fillWidth: true
|
text: histRoot.body; color: histRoot.t.notifToastDim; font.pixelSize: 12; Layout.fillWidth: true
|
||||||
wrapMode: Text.WordWrap; maximumLineCount: 2; elide: Text.ElideRight; textFormat: Text.PlainText; visible: histRoot.body !== ""; lineHeight: 1.15
|
wrapMode: Text.WordWrap; maximumLineCount: 2; elide: Text.ElideRight; textFormat: Text.PlainText; visible: histRoot.body !== ""; lineHeight: 1.2
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -375,6 +377,7 @@ Rectangle {
|
|||||||
color: t.notifBadgeText
|
color: t.notifBadgeText
|
||||||
font.pixelSize: 8
|
font.pixelSize: 8
|
||||||
font.bold: true
|
font.bold: true
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -574,7 +577,6 @@ Rectangle {
|
|||||||
radius: Cfg.Config.popupRadius
|
radius: Cfg.Config.popupRadius
|
||||||
border.color: t.notifHistoryBorder
|
border.color: t.notifHistoryBorder
|
||||||
border.width: Cfg.Config.popupBorderWidth
|
border.width: Cfg.Config.popupBorderWidth
|
||||||
layer.enabled: true
|
|
||||||
|
|
||||||
MouseArea { anchors.fill: parent; propagateComposedEvents: false }
|
MouseArea { anchors.fill: parent; propagateComposedEvents: false }
|
||||||
|
|
||||||
@@ -584,10 +586,10 @@ Rectangle {
|
|||||||
anchors.topMargin: 20; anchors.leftMargin: 20; anchors.rightMargin: 20
|
anchors.topMargin: 20; anchors.leftMargin: 20; anchors.rightMargin: 20
|
||||||
spacing: 10
|
spacing: 10
|
||||||
|
|
||||||
Text { text: ""; color: t.notifToastAppName; font.pixelSize: 18; Layout.alignment: Qt.AlignVCenter }
|
Text { text: ""; color: t.notifToastAppName; font.pixelSize: 18; Layout.alignment: Qt.AlignVCenter; renderType: Text.NativeRendering }
|
||||||
Text {
|
Text {
|
||||||
text: "Notifications"; color: t.notifToastAppName; font.pixelSize: 15; font.bold: true
|
text: "Notifications"; color: t.notifToastAppName; font.pixelSize: 15; font.bold: true
|
||||||
Layout.fillWidth: true; Layout.alignment: Qt.AlignVCenter
|
Layout.fillWidth: true; Layout.alignment: Qt.AlignVCenter; renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -613,6 +615,7 @@ Rectangle {
|
|||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
Behavior on color { ColorAnimation { duration: 150 } }
|
Behavior on color { ColorAnimation { duration: 150 } }
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: root.doNotDisturb ? "On" : "Off"
|
text: root.doNotDisturb ? "On" : "Off"
|
||||||
@@ -621,6 +624,7 @@ Rectangle {
|
|||||||
font.bold: root.doNotDisturb
|
font.bold: root.doNotDisturb
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
Behavior on color { ColorAnimation { duration: 150 } }
|
Behavior on color { ColorAnimation { duration: 150 } }
|
||||||
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,7 +641,7 @@ Rectangle {
|
|||||||
color: clearHover.hovered ? t.notifHistoryHover : "transparent"
|
color: clearHover.hovered ? t.notifHistoryHover : "transparent"
|
||||||
Behavior on color { ColorAnimation { duration: 150 } }
|
Behavior on color { ColorAnimation { duration: 150 } }
|
||||||
|
|
||||||
Text { id: clearText; anchors.centerIn: parent; text: "Clear all"; color: t.notifToastDim; font.pixelSize: 11 }
|
Text { id: clearText; anchors.centerIn: parent; text: "Clear all"; color: t.notifToastDim; font.pixelSize: 11; renderType: Text.NativeRendering }
|
||||||
HoverHandler { id: clearHover; cursorShape: Qt.PointingHandCursor }
|
HoverHandler { id: clearHover; cursorShape: Qt.PointingHandCursor }
|
||||||
TapHandler { onTapped: clearAllAnim.start() }
|
TapHandler { onTapped: clearAllAnim.start() }
|
||||||
}
|
}
|
||||||
@@ -689,8 +693,8 @@ Rectangle {
|
|||||||
width: histCol.width - 16; height: 90; visible: notifHistory.count === 0
|
width: histCol.width - 16; height: 90; visible: notifHistory.count === 0
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.centerIn: parent; spacing: 8
|
anchors.centerIn: parent; spacing: 8
|
||||||
Text { text: ""; color: t.notifHistoryEmpty; font.pixelSize: 30; Layout.alignment: Qt.AlignHCenter }
|
Text { text: ""; color: t.notifHistoryEmpty; font.pixelSize: 30; Layout.alignment: Qt.AlignHCenter; renderType: Text.NativeRendering }
|
||||||
Text { text: "No notifications"; color: t.notifHistoryEmpty; font.pixelSize: 12; Layout.alignment: Qt.AlignHCenter }
|
Text { text: "No notifications"; color: t.notifHistoryEmpty; font.pixelSize: 12; Layout.alignment: Qt.AlignHCenter; renderType: Text.NativeRendering }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,11 @@ import QtQuick.Layouts
|
|||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
|
||||||
import "../../config" as Cfg
|
import "../../config" as Cfg
|
||||||
|
import "../../components"
|
||||||
|
|
||||||
Rectangle {
|
ModuleChip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real panelRadius: Cfg.Config.radius / 2
|
|
||||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
|
||||||
property int barHeight: Cfg.Config.barHeight
|
|
||||||
property int barMargin: Cfg.Config.margin
|
|
||||||
readonly property var t: Cfg.Config.theme
|
|
||||||
|
|
||||||
width: statsLayout.implicitWidth + 20
|
width: statsLayout.implicitWidth + 20
|
||||||
height: Cfg.Config.moduleHeight
|
height: Cfg.Config.moduleHeight
|
||||||
color: t.statsBg
|
color: t.statsBg
|
||||||
|
|||||||
@@ -239,6 +239,130 @@ Item {
|
|||||||
|
|
||||||
QsMenuOpener { id: rootMenuOpener }
|
QsMenuOpener { id: rootMenuOpener }
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: trayMenuItemComponent
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: menuItem
|
||||||
|
required property var modelData
|
||||||
|
readonly property bool isSep: modelData.isSeparator
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
height: isSep ? 5 : 32
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: isSep
|
||||||
|
anchors {
|
||||||
|
left: parent.left; right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
anchors.leftMargin: 8; anchors.rightMargin: 8
|
||||||
|
height: 1
|
||||||
|
color: root.tmSeparator
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: !isSep
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 2
|
||||||
|
radius: 10
|
||||||
|
readonly property bool active: menuMouse.containsMouse
|
||||||
|
|| (submenuCard.visible
|
||||||
|
&& trayMenuPopup._submenuParentRef === menuItem)
|
||||||
|
color: active ? root.tmHover : "transparent"
|
||||||
|
Behavior on color { ColorAnimation { duration: 120 } }
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: 8; anchors.rightMargin: 8
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.preferredWidth: 16
|
||||||
|
Layout.preferredHeight: 16
|
||||||
|
visible: !isSep
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: modelData.buttonType === QsMenuButtonType.CheckBox
|
||||||
|
&& modelData.checkState === Qt.Checked
|
||||||
|
text: "✓"; color: root.tmCheck
|
||||||
|
font.pixelSize: 14
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: modelData.buttonType === QsMenuButtonType.RadioButton
|
||||||
|
&& modelData.checkState === Qt.Checked
|
||||||
|
text: "●"; color: root.tmCheck
|
||||||
|
font.pixelSize: 9
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
visible: modelData.buttonType === QsMenuButtonType.RadioButton
|
||||||
|
&& modelData.checkState !== Qt.Checked
|
||||||
|
text: "○"; color: root.tmDim
|
||||||
|
font.pixelSize: 11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
visible: !isSep && modelData.icon !== ""
|
||||||
|
source: modelData.icon
|
||||||
|
width: 16; height: 16
|
||||||
|
sourceSize: Qt.size(16, 16)
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: modelData.text
|
||||||
|
color: modelData.enabled ? root.tmText : root.tmDim
|
||||||
|
font.pixelSize: 13
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
visible: !isSep && modelData.hasChildren
|
||||||
|
text: "▶"
|
||||||
|
color: root.tmDim
|
||||||
|
font.pixelSize: 9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: menuMouse
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
enabled: !isSep && modelData.enabled
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (modelData.hasChildren) {
|
||||||
|
closeSubmenuTimer.stop()
|
||||||
|
submenuDelayTimer.itemRef = menuItem
|
||||||
|
submenuDelayTimer.restart()
|
||||||
|
} else {
|
||||||
|
modelData.triggered()
|
||||||
|
trayMenuPopup.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onEntered: {
|
||||||
|
if (modelData.hasChildren) {
|
||||||
|
closeSubmenuTimer.stop()
|
||||||
|
submenuDelayTimer.itemRef = menuItem
|
||||||
|
submenuDelayTimer.restart()
|
||||||
|
} else {
|
||||||
|
closeSubmenuTimer.stop()
|
||||||
|
submenuCard.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
if (modelData.hasChildren)
|
||||||
|
closeSubmenuTimer.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: menuCardWrapper
|
id: menuCardWrapper
|
||||||
@@ -301,133 +425,7 @@ Item {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: rootMenuOpener.children
|
model: rootMenuOpener.children
|
||||||
|
delegate: trayMenuItemComponent
|
||||||
delegate: Item {
|
|
||||||
id: menuDelegate
|
|
||||||
required property var modelData
|
|
||||||
property bool isSep: modelData.isSeparator
|
|
||||||
|
|
||||||
width: menuCol.width
|
|
||||||
height: isSep ? 5 : 32
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
visible: isSep
|
|
||||||
anchors {
|
|
||||||
left: parent.left; right: parent.right
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
anchors.leftMargin: 8
|
|
||||||
anchors.rightMargin: 8
|
|
||||||
height: 1
|
|
||||||
color: root.tmSeparator
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: itemBg
|
|
||||||
visible: !isSep
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 2
|
|
||||||
radius: 10
|
|
||||||
property bool active: itemMouse.containsMouse
|
|
||||||
|| (submenuCard.visible
|
|
||||||
&& trayMenuPopup._submenuParentRef === menuDelegate)
|
|
||||||
color: active ? root.tmHover : "transparent"
|
|
||||||
Behavior on color { ColorAnimation { duration: 120 } }
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: 8
|
|
||||||
anchors.rightMargin: 8
|
|
||||||
spacing: 8
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.preferredWidth: 16
|
|
||||||
Layout.preferredHeight: 16
|
|
||||||
visible: !isSep
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: modelData.buttonType === QsMenuButtonType.CheckBox
|
|
||||||
&& modelData.checkState === Qt.Checked
|
|
||||||
text: "✓"
|
|
||||||
color: root.tmCheck
|
|
||||||
font.pixelSize: 14
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: modelData.buttonType === QsMenuButtonType.RadioButton
|
|
||||||
&& modelData.checkState === Qt.Checked
|
|
||||||
text: "●"
|
|
||||||
color: root.tmCheck
|
|
||||||
font.pixelSize: 9
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: modelData.buttonType === QsMenuButtonType.RadioButton
|
|
||||||
&& modelData.checkState !== Qt.Checked
|
|
||||||
text: "○"
|
|
||||||
color: root.tmDim
|
|
||||||
font.pixelSize: 11
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
visible: !isSep && modelData.icon !== ""
|
|
||||||
source: modelData.icon
|
|
||||||
width: 16; height: 16
|
|
||||||
sourceSize: Qt.size(16, 16)
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: modelData.text
|
|
||||||
color: modelData.enabled ? root.tmText : root.tmDim
|
|
||||||
font.pixelSize: 13
|
|
||||||
Layout.fillWidth: true
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
visible: !isSep && modelData.hasChildren
|
|
||||||
text: "▶"
|
|
||||||
color: root.tmDim
|
|
||||||
font.pixelSize: 9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: itemMouse
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
enabled: !isSep && modelData.enabled
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (modelData.hasChildren) {
|
|
||||||
closeSubmenuTimer.stop()
|
|
||||||
submenuDelayTimer.itemRef = menuDelegate
|
|
||||||
submenuDelayTimer.restart()
|
|
||||||
} else {
|
|
||||||
modelData.triggered()
|
|
||||||
trayMenuPopup.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onEntered: {
|
|
||||||
if (modelData.hasChildren) {
|
|
||||||
closeSubmenuTimer.stop()
|
|
||||||
submenuDelayTimer.itemRef = menuDelegate
|
|
||||||
submenuDelayTimer.restart()
|
|
||||||
} else {
|
|
||||||
closeSubmenuTimer.stop()
|
|
||||||
submenuCard.visible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
if (modelData.hasChildren)
|
|
||||||
closeSubmenuTimer.restart()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,96 +513,7 @@ Item {
|
|||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: subMenuOpener.children
|
model: subMenuOpener.children
|
||||||
|
delegate: trayMenuItemComponent
|
||||||
delegate: Item {
|
|
||||||
required property var modelData
|
|
||||||
property bool isSep: modelData.isSeparator
|
|
||||||
|
|
||||||
width: submenuCol.width
|
|
||||||
height: isSep ? 5 : 32
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
visible: isSep
|
|
||||||
anchors {
|
|
||||||
left: parent.left; right: parent.right
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
anchors.leftMargin: 8; anchors.rightMargin: 8
|
|
||||||
height: 1
|
|
||||||
color: root.tmSeparator
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: subBg
|
|
||||||
visible: !isSep
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 2
|
|
||||||
radius: 10
|
|
||||||
color: subMouse.containsMouse ? root.tmHover : "transparent"
|
|
||||||
Behavior on color { ColorAnimation { duration: 120 } }
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: 8; anchors.rightMargin: 8
|
|
||||||
spacing: 8
|
|
||||||
|
|
||||||
Item {
|
|
||||||
Layout.preferredWidth: 16
|
|
||||||
Layout.preferredHeight: 16
|
|
||||||
visible: !isSep
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: modelData.buttonType === QsMenuButtonType.CheckBox
|
|
||||||
&& modelData.checkState === Qt.Checked
|
|
||||||
text: "✓"; color: root.tmCheck
|
|
||||||
font.pixelSize: 14
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: modelData.buttonType === QsMenuButtonType.RadioButton
|
|
||||||
&& modelData.checkState === Qt.Checked
|
|
||||||
text: "●"; color: root.tmCheck
|
|
||||||
font.pixelSize: 9
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
visible: modelData.buttonType === QsMenuButtonType.RadioButton
|
|
||||||
&& modelData.checkState !== Qt.Checked
|
|
||||||
text: "○"; color: root.tmDim
|
|
||||||
font.pixelSize: 11
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
visible: !isSep && modelData.icon !== ""
|
|
||||||
source: modelData.icon
|
|
||||||
width: 16; height: 16
|
|
||||||
sourceSize: Qt.size(16, 16)
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
text: modelData.text
|
|
||||||
color: modelData.enabled ? root.tmText : root.tmDim
|
|
||||||
font.pixelSize: 13
|
|
||||||
Layout.fillWidth: true
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: subMouse
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
enabled: !isSep && modelData.enabled
|
|
||||||
onClicked: {
|
|
||||||
modelData.triggered()
|
|
||||||
trayMenuPopup.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,19 +6,11 @@ import Quickshell.Wayland
|
|||||||
import Quickshell.Services.Pipewire
|
import Quickshell.Services.Pipewire
|
||||||
|
|
||||||
import "../../config" as Cfg
|
import "../../config" as Cfg
|
||||||
|
import "../../components"
|
||||||
|
|
||||||
Rectangle {
|
ModuleChip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real panelRadius: Cfg.Config.radius / 2
|
|
||||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
|
||||||
property bool isTop: true
|
|
||||||
property var targetScreen: null
|
|
||||||
property int barHeight: Cfg.Config.barHeight
|
|
||||||
property int barMargin: Cfg.Config.margin
|
|
||||||
|
|
||||||
readonly property var t: Cfg.Config.theme
|
|
||||||
|
|
||||||
property int outputMaxVolume: Cfg.Config.volumeOutputMax
|
property int outputMaxVolume: Cfg.Config.volumeOutputMax
|
||||||
property int inputMaxVolume: Cfg.Config.volumeInputMax
|
property int inputMaxVolume: Cfg.Config.volumeInputMax
|
||||||
|
|
||||||
@@ -165,54 +157,11 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PanelWindow {
|
PopupPanel {
|
||||||
id: volumePopup
|
id: volumePopup
|
||||||
screen: root.targetScreen
|
ns: "volume"
|
||||||
visible: false
|
chipRoot: root
|
||||||
color: "transparent"
|
cardWidth: Cfg.Config.volumePopupWidth
|
||||||
|
|
||||||
property bool popupOpen: false
|
|
||||||
|
|
||||||
function open() { hideTimer.stop(); visible = true; popupOpen = true }
|
|
||||||
function close() { popupOpen = false; hideTimer.restart() }
|
|
||||||
function toggle() { popupOpen ? close() : open() }
|
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: hideTimer
|
|
||||||
interval: Cfg.Config.popupAnimDuration + 70
|
|
||||||
onTriggered: volumePopup.visible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors { top: true; bottom: true; left: true; right: true }
|
|
||||||
WlrLayershell.layer: WlrLayer.Top
|
|
||||||
WlrLayershell.namespace: "main-shell-volume"
|
|
||||||
WlrLayershell.exclusiveZone: -1
|
|
||||||
mask: popupOpen ? null : _noInput
|
|
||||||
Region { id: _noInput }
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: volumePopup.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: volClipContainer
|
|
||||||
readonly property int cardW: Cfg.Config.volumePopupWidth
|
|
||||||
readonly property int screenPad: root.barMargin + 10
|
|
||||||
|
|
||||||
x: {
|
|
||||||
let cx = root.mapToItem(null, 0, 0).x + root.width / 2
|
|
||||||
return Math.max(screenPad, Math.min(cx - cardW / 2, parent.width - cardW - screenPad))
|
|
||||||
}
|
|
||||||
width: cardW
|
|
||||||
|
|
||||||
anchors.top: root.isTop ? parent.top : undefined
|
|
||||||
anchors.bottom: root.isTop ? undefined : parent.bottom
|
|
||||||
anchors.topMargin: root.isTop ? (root.barHeight + 10) : 0
|
|
||||||
anchors.bottomMargin: root.isTop ? 0 : (root.barHeight + 10)
|
|
||||||
height: parent.height - root.barHeight - 10
|
|
||||||
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: volCard
|
id: volCard
|
||||||
@@ -341,7 +290,6 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
component VolumeSection: ColumnLayout {
|
component VolumeSection: ColumnLayout {
|
||||||
id: vs
|
id: vs
|
||||||
|
|||||||
@@ -3,15 +3,11 @@ import QtQuick.Layouts
|
|||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
import "../../config" as Cfg
|
import "../../config" as Cfg
|
||||||
|
import "../../components"
|
||||||
|
|
||||||
Rectangle {
|
ModuleChip {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property real panelRadius: Cfg.Config.radius / 2
|
|
||||||
property int borderWidth: Cfg.Config.panelBorderWidth
|
|
||||||
|
|
||||||
readonly property var t: Cfg.Config.theme
|
|
||||||
|
|
||||||
width: workspaceLayout.implicitWidth + 24
|
width: workspaceLayout.implicitWidth + 24
|
||||||
height: Cfg.Config.moduleHeight
|
height: Cfg.Config.moduleHeight
|
||||||
color: t.wsPanelBg
|
color: t.wsPanelBg
|
||||||
|
|||||||
16
components/ModuleChip.qml
Normal file
16
components/ModuleChip.qml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import QtQuick
|
||||||
|
import "../config" as Cfg
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: chip
|
||||||
|
|
||||||
|
property real panelRadius: Cfg.Config.radius / 2
|
||||||
|
property int borderWidth: Cfg.Config.panelBorderWidth
|
||||||
|
property bool isTop: true
|
||||||
|
property var targetScreen: null
|
||||||
|
property int barHeight: Cfg.Config.barHeight
|
||||||
|
property int barMargin: Cfg.Config.margin
|
||||||
|
readonly property var t: Cfg.Config.theme
|
||||||
|
|
||||||
|
property bool moduleEnabled: true
|
||||||
|
}
|
||||||
68
components/PopupPanel.qml
Normal file
68
components/PopupPanel.qml
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import "../config" as Cfg
|
||||||
|
|
||||||
|
PanelWindow {
|
||||||
|
id: popup
|
||||||
|
|
||||||
|
property string ns: ""
|
||||||
|
property var chipRoot: null
|
||||||
|
property int cardWidth: 260
|
||||||
|
property bool hasKeyboardFocus: false
|
||||||
|
|
||||||
|
property alias clipItem: popupClip
|
||||||
|
default property alias content: popupClip.data
|
||||||
|
|
||||||
|
screen: chipRoot ? chipRoot.targetScreen : null
|
||||||
|
visible: false
|
||||||
|
color: "transparent"
|
||||||
|
|
||||||
|
property bool popupOpen: false
|
||||||
|
property real popupCenterX: -1
|
||||||
|
|
||||||
|
function _doOpen() { hideTimer.stop(); visible = true; popupOpen = true }
|
||||||
|
function open() {
|
||||||
|
if (popupCenterX < 0 && chipRoot)
|
||||||
|
popupCenterX = chipRoot.mapToItem(null, 0, 0).x + chipRoot.width / 2
|
||||||
|
_doOpen()
|
||||||
|
}
|
||||||
|
function close() { popupOpen = false; hideTimer.restart() }
|
||||||
|
function toggle() { popupOpen ? close() : open() }
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: hideTimer
|
||||||
|
interval: Cfg.Config.popupAnimDuration + 70
|
||||||
|
onTriggered: popup.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors { top: true; bottom: true; left: true; right: true }
|
||||||
|
WlrLayershell.layer: WlrLayer.Top
|
||||||
|
WlrLayershell.namespace: "main-shell-" + ns
|
||||||
|
WlrLayershell.exclusiveZone: -1
|
||||||
|
WlrLayershell.keyboardFocus: hasKeyboardFocus ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
|
||||||
|
mask: popupOpen ? null : _noInput
|
||||||
|
Region { id: _noInput }
|
||||||
|
|
||||||
|
TapHandler { onTapped: popup.close() }
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: popupClip
|
||||||
|
property int screenPad: chipRoot ? chipRoot.barMargin + 10 : 30
|
||||||
|
|
||||||
|
x: {
|
||||||
|
if (!chipRoot && popupCenterX < 0) return 0
|
||||||
|
let cx = popupCenterX >= 0 ? popupCenterX : chipRoot.mapToItem(null, 0, 0).x + chipRoot.width / 2
|
||||||
|
return Math.max(screenPad, Math.min(cx - cardWidth / 2, parent.width - cardWidth - screenPad))
|
||||||
|
}
|
||||||
|
width: cardWidth
|
||||||
|
|
||||||
|
anchors.top: chipRoot && chipRoot.isTop ? parent.top : undefined
|
||||||
|
anchors.bottom: chipRoot && chipRoot.isTop ? undefined : parent.bottom
|
||||||
|
anchors.topMargin: chipRoot && chipRoot.isTop ? (chipRoot.barHeight + 10) : 0
|
||||||
|
anchors.bottomMargin: chipRoot && chipRoot.isTop ? 0 : (chipRoot.barHeight + 10)
|
||||||
|
height: chipRoot ? parent.height - chipRoot.barHeight - 10 : parent.height
|
||||||
|
|
||||||
|
clip: true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -129,11 +129,6 @@ QtObject {
|
|||||||
// Settings popup and those changes are persisted across restarts.
|
// Settings popup and those changes are persisted across restarts.
|
||||||
property var cryptoPairs: [{ coin: "bitcoin", currency: "usd" }, { coin: "ethereum", currency: "eur" }, { coin: "monero", currency: "usd" }, { coin: "solana", currency: "brl" }]
|
property var cryptoPairs: [{ coin: "bitcoin", currency: "usd" }, { coin: "ethereum", currency: "eur" }, { coin: "monero", currency: "usd" }, { coin: "solana", currency: "brl" }]
|
||||||
|
|
||||||
// Legacy fallbacks – used by Crypto.qml when cryptoPairs is absent.
|
|
||||||
// You can leave these as-is; they are derived from the first pair above.
|
|
||||||
property string cryptoCoinId: cryptoPairs[0].coin ?? "bitcoin"
|
|
||||||
property string cryptoVsCurrency: cryptoPairs[0].currency ?? "usd"
|
|
||||||
|
|
||||||
// ── Compact label decimals ────────────────────────────────────────────────
|
// ── Compact label decimals ────────────────────────────────────────────────
|
||||||
// 0 → "80k"
|
// 0 → "80k"
|
||||||
// 1 → "80.0k" (default)
|
// 1 → "80.0k" (default)
|
||||||
|
|||||||
@@ -430,3 +430,4 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Wayland
|
import Quickshell.Wayland
|
||||||
import Quickshell.Services.Polkit
|
import Quickshell.Services.Polkit
|
||||||
|
|||||||
Reference in New Issue
Block a user