quickshell: modularize QML into separate files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
252d88c758
commit
3a4d8db003
1 changed files with 1444 additions and 1393 deletions
|
|
@ -441,21 +441,72 @@ in
|
|||
Install.WantedBy = [ "hyprland-session.target" ];
|
||||
};
|
||||
|
||||
xdg.configFile."quickshell/shell.qml" = {
|
||||
onChange = ''
|
||||
xdg.configFile = let
|
||||
qsRestart = ''
|
||||
${pkgs.systemd}/bin/systemctl --user restart quickshell.service 2>/dev/null || true
|
||||
'';
|
||||
wifiConnectScript = pkgs.writeShellScript "wifi-connect" ''
|
||||
ssid="$1"
|
||||
${pkgs.networkmanager}/bin/nmcli device wifi connect "$ssid" 2>/dev/null && exit 0
|
||||
pw=$(${pkgs.zenity}/bin/zenity --password --title="WiFi Password" 2>/dev/null)
|
||||
[ -n "$pw" ] && ${pkgs.networkmanager}/bin/nmcli device wifi connect "$ssid" password "$pw"
|
||||
'';
|
||||
nmcli = "${pkgs.networkmanager}/bin/nmcli";
|
||||
powerprofilesctl = "${pkgs.power-profiles-daemon}/bin/powerprofilesctl";
|
||||
in {
|
||||
"quickshell/qmldir" = {
|
||||
onChange = qsRestart;
|
||||
text = ''
|
||||
singleton Theme 1.0 Theme.qml
|
||||
singleton Commands 1.0 Commands.qml
|
||||
'';
|
||||
};
|
||||
|
||||
"quickshell/Theme.qml" = {
|
||||
onChange = qsRestart;
|
||||
text = ''
|
||||
pragma Singleton
|
||||
import QtQuick
|
||||
|
||||
QtObject {
|
||||
readonly property color base00: "#${c.base00}"
|
||||
readonly property color base01: "#${c.base01}"
|
||||
readonly property color base02: "#${c.base02}"
|
||||
readonly property color base03: "#${c.base03}"
|
||||
readonly property color base04: "#${c.base04}"
|
||||
readonly property color base05: "#${c.base05}"
|
||||
readonly property color base08: "#${c.base08}"
|
||||
readonly property color base0A: "#${c.base0A}"
|
||||
readonly property color base0B: "#${c.base0B}"
|
||||
readonly property color base0C: "#${c.base0C}"
|
||||
readonly property color base0D: "#${c.base0D}"
|
||||
readonly property color barBg: "#D1${c.base00}"
|
||||
readonly property color toastBg: "#E6${c.base00}"
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
"quickshell/Commands.qml" = {
|
||||
onChange = qsRestart;
|
||||
text = ''
|
||||
pragma Singleton
|
||||
import QtQuick
|
||||
|
||||
QtObject {
|
||||
readonly property string nmcli: "${nmcli}"
|
||||
readonly property string wifiConnect: "${wifiConnectScript}"
|
||||
readonly property string powerprofilesctl: "${powerprofilesctl}"
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
"quickshell/shell.qml" = {
|
||||
onChange = qsRestart;
|
||||
text = ''
|
||||
//@ pragma UseQApplication
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Services.SystemTray
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Io
|
||||
import Quickshell.Services.Notifications
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
ShellRoot {
|
||||
id: root
|
||||
|
|
@ -479,9 +530,39 @@ in
|
|||
Variants {
|
||||
model: Quickshell.screens
|
||||
|
||||
Bar {
|
||||
notifServer: notifServer
|
||||
}
|
||||
}
|
||||
|
||||
Variants {
|
||||
model: Quickshell.screens
|
||||
|
||||
NotificationToast {
|
||||
shellRoot: root
|
||||
}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
"quickshell/Bar.qml" = {
|
||||
onChange = qsRestart;
|
||||
text = ''
|
||||
import Quickshell
|
||||
import Quickshell.Hyprland
|
||||
import Quickshell.Services.SystemTray
|
||||
import Quickshell.Services.Notifications
|
||||
import Quickshell.Widgets
|
||||
import Quickshell.Io
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
PanelWindow {
|
||||
id: bar
|
||||
required property var modelData
|
||||
required property NotificationServer notifServer
|
||||
screen: modelData
|
||||
|
||||
anchors {
|
||||
|
|
@ -491,7 +572,7 @@ in
|
|||
}
|
||||
|
||||
implicitHeight: 30
|
||||
color: "#D1${c.base00}"
|
||||
color: Theme.barBg
|
||||
|
||||
property var activeDropdown: null
|
||||
function closeAllDropdowns() {
|
||||
|
|
@ -510,7 +591,6 @@ in
|
|||
}
|
||||
if (setupFn) setupFn();
|
||||
if (dd.closing) {
|
||||
// Cancel close animation, reopen
|
||||
dd.closing = false;
|
||||
dd.open = true;
|
||||
} else {
|
||||
|
|
@ -538,7 +618,7 @@ in
|
|||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: modelData.name
|
||||
color: modelData.focused ? "#${c.base05}" : "#${c.base03}"
|
||||
color: modelData.focused ? Theme.base05 : Theme.base03
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 13
|
||||
}
|
||||
|
|
@ -548,7 +628,7 @@ in
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width - 8
|
||||
height: 2
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
visible: modelData.focused
|
||||
}
|
||||
|
||||
|
|
@ -566,7 +646,7 @@ in
|
|||
anchors.centerIn: parent
|
||||
property date now: new Date()
|
||||
text: now.toLocaleTimeString(Qt.locale(), "HH:mm")
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
|
|
@ -603,6 +683,14 @@ in
|
|||
property string netConn: ""
|
||||
property string netType: ""
|
||||
property string netIcon: "\u{f0b0}"
|
||||
property var wifiNetworks: []
|
||||
property string netDevice: ""
|
||||
|
||||
property string _pendingState: "disconnected"
|
||||
property string _pendingConn: ""
|
||||
property string _pendingType: ""
|
||||
property string _pendingDevice: ""
|
||||
property var _pendingNets: []
|
||||
|
||||
Timer {
|
||||
interval: 5000
|
||||
|
|
@ -612,11 +700,6 @@ in
|
|||
onTriggered: netWidget.refreshNet()
|
||||
}
|
||||
|
||||
property string _pendingState: "disconnected"
|
||||
property string _pendingConn: ""
|
||||
property string _pendingType: ""
|
||||
property string _pendingDevice: ""
|
||||
|
||||
function refreshNet() {
|
||||
netWidget._pendingState = "disconnected";
|
||||
netWidget._pendingConn = "";
|
||||
|
|
@ -626,7 +709,7 @@ in
|
|||
|
||||
Process {
|
||||
id: netProc
|
||||
command: ["${pkgs.networkmanager}/bin/nmcli", "-t", "-f", "DEVICE,TYPE,STATE,CONNECTION", "device"]
|
||||
command: [Commands.nmcli, "-t", "-f", "DEVICE,TYPE,STATE,CONNECTION", "device"]
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
let fields = data.split(":");
|
||||
|
|
@ -663,25 +746,20 @@ in
|
|||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: netWidget.netIcon
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 14
|
||||
}
|
||||
|
||||
property var wifiNetworks: []
|
||||
property string netDevice: ""
|
||||
|
||||
Timer {
|
||||
id: netRefreshDelay
|
||||
interval: 2000
|
||||
onTriggered: netWidget.refreshNet()
|
||||
}
|
||||
|
||||
property var _pendingNets: []
|
||||
|
||||
Process {
|
||||
id: wifiScanProc
|
||||
command: ["${pkgs.networkmanager}/bin/nmcli", "-t", "-f", "SSID,SIGNAL,SECURITY,IN-USE", "device", "wifi", "list", "--rescan", "auto"]
|
||||
command: [Commands.nmcli, "-t", "-f", "SSID,SIGNAL,SECURITY,IN-USE", "device", "wifi", "list", "--rescan", "auto"]
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
let fields = data.split(":");
|
||||
|
|
@ -708,21 +786,15 @@ in
|
|||
Process {
|
||||
id: wifiConnectProc
|
||||
property string targetSsid: ""
|
||||
command: ["${pkgs.writeShellScript "wifi-connect" ''
|
||||
ssid="$1"
|
||||
${pkgs.networkmanager}/bin/nmcli device wifi connect "$ssid" 2>/dev/null && exit 0
|
||||
pw=$(${pkgs.zenity}/bin/zenity --password --title="WiFi Password" 2>/dev/null)
|
||||
[ -n "$pw" ] && ${pkgs.networkmanager}/bin/nmcli device wifi connect "$ssid" password "$pw"
|
||||
''}", targetSsid]
|
||||
command: [Commands.wifiConnect, targetSsid]
|
||||
}
|
||||
|
||||
Process {
|
||||
id: netDisconnectProc
|
||||
property string targetDevice: ""
|
||||
command: ["${pkgs.networkmanager}/bin/nmcli", "device", "disconnect", targetDevice]
|
||||
command: [Commands.nmcli, "device", "disconnect", targetDevice]
|
||||
}
|
||||
|
||||
|
||||
function openNetDropdown() {
|
||||
bar.toggleDropdown(netDropdown, function() {
|
||||
wifiScanProc.running = true;
|
||||
|
|
@ -793,7 +865,6 @@ in
|
|||
} else if (lineNum === 5) {
|
||||
if (!isNaN(num)) batteryWidget.energyFull = num / 1000000.0;
|
||||
lineNum = 0;
|
||||
// Calculate time remaining
|
||||
if (batteryWidget.powerDraw > 0.5) {
|
||||
let hours;
|
||||
if (batteryWidget.charging) {
|
||||
|
|
@ -815,7 +886,7 @@ in
|
|||
|
||||
Process {
|
||||
id: profileProc
|
||||
command: ["${pkgs.power-profiles-daemon}/bin/powerprofilesctl", "get"]
|
||||
command: [Commands.powerprofilesctl, "get"]
|
||||
stdout: SplitParser {
|
||||
onRead: data => {
|
||||
batteryWidget.powerProfile = data.trim();
|
||||
|
|
@ -826,7 +897,7 @@ in
|
|||
Process {
|
||||
id: setProfileProc
|
||||
property string target: "balanced"
|
||||
command: ["${pkgs.power-profiles-daemon}/bin/powerprofilesctl", "set", target]
|
||||
command: [Commands.powerprofilesctl, "set", target]
|
||||
}
|
||||
|
||||
Row {
|
||||
|
|
@ -836,9 +907,9 @@ in
|
|||
Text {
|
||||
id: batteryText
|
||||
text: batteryWidget.batteryLevel + "%"
|
||||
color: batteryWidget.batteryLevel <= 15 ? "#${c.base08}"
|
||||
: batteryWidget.batteryLevel <= 30 ? "#${c.base0A}"
|
||||
: "#${c.base05}"
|
||||
color: batteryWidget.batteryLevel <= 15 ? Theme.base08
|
||||
: batteryWidget.batteryLevel <= 30 ? Theme.base0A
|
||||
: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 13
|
||||
}
|
||||
|
|
@ -846,9 +917,9 @@ in
|
|||
Text {
|
||||
id: batteryIconText
|
||||
text: batteryWidget.batteryIcon
|
||||
color: batteryWidget.batteryLevel <= 15 ? "#${c.base08}"
|
||||
: batteryWidget.batteryLevel <= 30 ? "#${c.base0A}"
|
||||
: "#${c.base05}"
|
||||
color: batteryWidget.batteryLevel <= 15 ? Theme.base08
|
||||
: batteryWidget.batteryLevel <= 30 ? Theme.base0A
|
||||
: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 14
|
||||
}
|
||||
|
|
@ -900,7 +971,7 @@ in
|
|||
ColorOverlay {
|
||||
anchors.fill: trayIcon
|
||||
source: trayIcon
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
|
|
@ -1013,7 +1084,7 @@ in
|
|||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
ctx.clearRect(0, 0, 8, 8);
|
||||
ctx.fillStyle = "#D1${c.base00}";
|
||||
ctx.fillStyle = Theme.barBg;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 0); ctx.lineTo(8, 0); ctx.lineTo(8, 8);
|
||||
ctx.arc(0, 8, 8, 0, -Math.PI / 2, true);
|
||||
|
|
@ -1035,7 +1106,7 @@ in
|
|||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
ctx.clearRect(0, 0, 8, 8);
|
||||
ctx.fillStyle = "#D1${c.base00}";
|
||||
ctx.fillStyle = Theme.barBg;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 0); ctx.lineTo(8, 0);
|
||||
ctx.arc(8, 8, 8, -Math.PI / 2, Math.PI, true);
|
||||
|
|
@ -1050,7 +1121,7 @@ in
|
|||
anchors.top: parent.top
|
||||
width: dropdown.fullWidth
|
||||
height: dropdown.open ? dropdown.fullHeight : 0
|
||||
color: "#D1${c.base00}"
|
||||
color: Theme.barBg
|
||||
radius: 8
|
||||
topLeftRadius: 0
|
||||
topRightRadius: 0
|
||||
|
|
@ -1097,7 +1168,7 @@ in
|
|||
width: 200
|
||||
height: modelData.isSeparator ? 9 : 28
|
||||
color: !modelData.isSeparator && itemMouse.containsMouse && modelData.enabled
|
||||
? "#${c.base02}" : "transparent"
|
||||
? Theme.base02 : "transparent"
|
||||
radius: modelData.isSeparator ? 0 : 4
|
||||
|
||||
Rectangle {
|
||||
|
|
@ -1105,7 +1176,7 @@ in
|
|||
anchors.centerIn: parent
|
||||
width: parent.width - 20
|
||||
height: 1
|
||||
color: "#${c.base03}"
|
||||
color: Theme.base03
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
|
@ -1118,7 +1189,7 @@ in
|
|||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: modelData.text ?? ""
|
||||
color: modelData.enabled ? "#${c.base05}" : "#${c.base03}"
|
||||
color: modelData.enabled ? Theme.base05 : Theme.base03
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 12
|
||||
elide: Text.ElideRight
|
||||
|
|
@ -1127,7 +1198,7 @@ in
|
|||
Text {
|
||||
visible: modelData.buttonType !== QsMenuButtonType.None
|
||||
text: modelData.checkState === Qt.Checked ? "\u2713" : ""
|
||||
color: "#${c.base0D}"
|
||||
color: Theme.base0D
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
|
@ -1162,31 +1233,29 @@ in
|
|||
width: 220
|
||||
spacing: 4
|
||||
|
||||
// Current connection header
|
||||
Text {
|
||||
width: parent.width
|
||||
text: netWidget.netState === "connected"
|
||||
? "\u{f05a9} " + netWidget.netConn
|
||||
: "\u{f05aa} Not connected"
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
// Disconnect button (when connected)
|
||||
Rectangle {
|
||||
visible: netWidget.netState === "connected"
|
||||
width: parent.width
|
||||
height: 28
|
||||
color: disconnectMouse.containsMouse ? "#${c.base02}" : "transparent"
|
||||
color: disconnectMouse.containsMouse ? Theme.base02 : "transparent"
|
||||
radius: 4
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Disconnect"
|
||||
color: "#${c.base08}"
|
||||
color: Theme.base08
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 12
|
||||
}
|
||||
|
|
@ -1207,24 +1276,21 @@ in
|
|||
}
|
||||
}
|
||||
|
||||
// Separator
|
||||
Rectangle {
|
||||
width: parent.width - 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 1
|
||||
color: "#${c.base03}"
|
||||
color: Theme.base03
|
||||
}
|
||||
|
||||
// Available networks header
|
||||
Text {
|
||||
text: "Available networks"
|
||||
color: "#${c.base03}"
|
||||
color: Theme.base03
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 11
|
||||
topPadding: 2
|
||||
}
|
||||
|
||||
// Network list
|
||||
Repeater {
|
||||
model: netWidget.wifiNetworks
|
||||
|
||||
|
|
@ -1232,7 +1298,7 @@ in
|
|||
required property var modelData
|
||||
width: 220
|
||||
height: 32
|
||||
color: netItemMouse.containsMouse ? "#${c.base02}" : "transparent"
|
||||
color: netItemMouse.containsMouse ? Theme.base02 : "transparent"
|
||||
radius: 4
|
||||
|
||||
Row {
|
||||
|
|
@ -1243,7 +1309,6 @@ in
|
|||
anchors.rightMargin: 8
|
||||
spacing: 8
|
||||
|
||||
// Signal icon
|
||||
Text {
|
||||
text: {
|
||||
let s = modelData.signal;
|
||||
|
|
@ -1252,16 +1317,15 @@ in
|
|||
if (s >= 25) return "\u{f05a9}";
|
||||
return "\u{f05aa}";
|
||||
}
|
||||
color: modelData.active ? "#${c.base0B}" : "#${c.base04}"
|
||||
color: modelData.active ? Theme.base0B : Theme.base04
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 13
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
// SSID
|
||||
Text {
|
||||
text: modelData.ssid
|
||||
color: modelData.active ? "#${c.base0B}" : "#${c.base05}"
|
||||
color: modelData.active ? Theme.base0B : Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 12
|
||||
elide: Text.ElideRight
|
||||
|
|
@ -1269,11 +1333,10 @@ in
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
// Lock icon for secured networks
|
||||
Text {
|
||||
visible: modelData.security !== "" && modelData.security !== "--"
|
||||
text: "\u{f0341}"
|
||||
color: "#${c.base03}"
|
||||
color: Theme.base03
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
|
@ -1313,14 +1376,13 @@ in
|
|||
width: 200
|
||||
spacing: 8
|
||||
|
||||
// Battery status
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: 8
|
||||
|
||||
Text {
|
||||
text: batteryWidget.batteryIcon
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 18
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
|
@ -1330,7 +1392,7 @@ in
|
|||
anchors.verticalCenter: parent.verticalCenter
|
||||
Text {
|
||||
text: batteryWidget.batteryLevel + "%" + (batteryWidget.charging ? " — Charging" : "")
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
|
|
@ -1338,30 +1400,27 @@ in
|
|||
Text {
|
||||
text: batteryWidget.powerDraw.toFixed(1) + " W"
|
||||
+ (batteryWidget.timeRemaining !== "" ? " \u2022 " + batteryWidget.timeRemaining + (batteryWidget.charging ? " to full" : " left") : "")
|
||||
color: "#${c.base04}"
|
||||
color: Theme.base04
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 11
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Separator
|
||||
Rectangle {
|
||||
width: parent.width - 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 1
|
||||
color: "#${c.base03}"
|
||||
color: Theme.base03
|
||||
}
|
||||
|
||||
// Power profile label
|
||||
Text {
|
||||
text: "Power Profile"
|
||||
color: "#${c.base03}"
|
||||
color: Theme.base03
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 11
|
||||
}
|
||||
|
||||
// Profile buttons
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: 4
|
||||
|
|
@ -1379,10 +1438,10 @@ in
|
|||
height: 36
|
||||
radius: 6
|
||||
color: batteryWidget.powerProfile === modelData.name
|
||||
? "#${c.base02}" : profMouse.containsMouse
|
||||
? "#${c.base01}" : "transparent"
|
||||
? Theme.base02 : profMouse.containsMouse
|
||||
? Theme.base01 : "transparent"
|
||||
border.width: batteryWidget.powerProfile === modelData.name ? 1 : 0
|
||||
border.color: "#${c.base03}"
|
||||
border.color: Theme.base03
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
|
|
@ -1391,14 +1450,14 @@ in
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: modelData.label
|
||||
color: batteryWidget.powerProfile === modelData.name
|
||||
? "#${c.base0D}" : "#${c.base05}"
|
||||
? Theme.base0D : Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 14
|
||||
}
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: modelData.tip
|
||||
color: "#${c.base04}"
|
||||
color: Theme.base04
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 9
|
||||
}
|
||||
|
|
@ -1440,17 +1499,15 @@ in
|
|||
NumberAnimation { duration: 150; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
// Date header
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: clockText.now.toLocaleDateString(Qt.locale(), "dddd, d MMMM yyyy")
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 14
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
// Day headers
|
||||
Row {
|
||||
spacing: 0
|
||||
Repeater {
|
||||
|
|
@ -1460,14 +1517,13 @@ in
|
|||
width: 28
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: modelData
|
||||
color: "#${c.base03}"
|
||||
color: Theme.base03
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 11
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calendar grid
|
||||
Grid {
|
||||
columns: 7
|
||||
spacing: 0
|
||||
|
|
@ -1488,7 +1544,7 @@ in
|
|||
let dayNum = index - startDay + 1;
|
||||
let daysInMonth = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
|
||||
return (dayNum === d.getDate() && dayNum >= 1 && dayNum <= daysInMonth)
|
||||
? "#${c.base02}" : "transparent";
|
||||
? Theme.base02 : "transparent";
|
||||
}
|
||||
|
||||
Text {
|
||||
|
|
@ -1506,7 +1562,7 @@ in
|
|||
let first = new Date(d.getFullYear(), d.getMonth(), 1);
|
||||
let startDay = (first.getDay() + 6) % 7;
|
||||
let dayNum = parent.index - startDay + 1;
|
||||
return (dayNum === d.getDate()) ? "#${c.base05}" : "#${c.base04}";
|
||||
return (dayNum === d.getDate()) ? Theme.base05 : Theme.base04;
|
||||
}
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 11
|
||||
|
|
@ -1515,19 +1571,17 @@ in
|
|||
}
|
||||
}
|
||||
|
||||
// Separator
|
||||
Rectangle {
|
||||
width: 7 * 28
|
||||
height: 1
|
||||
color: "#${c.base02}"
|
||||
color: Theme.base02
|
||||
}
|
||||
|
||||
// Notifications header
|
||||
Row {
|
||||
width: 7 * 28
|
||||
Text {
|
||||
text: "Notifications"
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
|
|
@ -1535,15 +1589,15 @@ in
|
|||
Item { Layout.fillWidth: true; width: 10 }
|
||||
Text {
|
||||
anchors.right: parent.right
|
||||
text: notifServer.trackedNotifications.values.length > 0 ? "Clear all" : ""
|
||||
color: "#${c.base04}"
|
||||
text: bar.notifServer.trackedNotifications.values.length > 0 ? "Clear all" : ""
|
||||
color: Theme.base04
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 11
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
let notifs = notifServer.trackedNotifications.values;
|
||||
let notifs = bar.notifServer.trackedNotifications.values;
|
||||
for (let i = notifs.length - 1; i >= 0; i--) {
|
||||
notifs[i].dismiss();
|
||||
}
|
||||
|
|
@ -1552,22 +1606,21 @@ in
|
|||
}
|
||||
}
|
||||
|
||||
// Notification list
|
||||
Column {
|
||||
spacing: 4
|
||||
width: 7 * 28
|
||||
|
||||
Text {
|
||||
visible: notifServer.trackedNotifications.values.length === 0
|
||||
visible: bar.notifServer.trackedNotifications.values.length === 0
|
||||
text: "No notifications"
|
||||
color: "#${c.base03}"
|
||||
color: Theme.base03
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 11
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: notifServer.trackedNotifications
|
||||
model: bar.notifServer.trackedNotifications
|
||||
|
||||
Rectangle {
|
||||
id: notifItem
|
||||
|
|
@ -1575,7 +1628,7 @@ in
|
|||
width: 7 * 28
|
||||
height: notifCol.height + 12
|
||||
radius: 6
|
||||
color: "#${c.base01}"
|
||||
color: Theme.base01
|
||||
|
||||
Column {
|
||||
id: notifCol
|
||||
|
|
@ -1588,7 +1641,7 @@ in
|
|||
Text {
|
||||
width: parent.width
|
||||
text: notifItem.modelData.summary || notifItem.modelData.appName
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 11
|
||||
font.weight: Font.Medium
|
||||
|
|
@ -1598,7 +1651,7 @@ in
|
|||
Text {
|
||||
width: parent.width
|
||||
text: notifItem.modelData.body || ""
|
||||
color: "#${c.base04}"
|
||||
color: Theme.base04
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 10
|
||||
elide: Text.ElideRight
|
||||
|
|
@ -1607,7 +1660,6 @@ in
|
|||
visible: text !== ""
|
||||
}
|
||||
|
||||
// Action buttons
|
||||
Row {
|
||||
spacing: 4
|
||||
visible: notifItem.modelData.actions.length > 0
|
||||
|
|
@ -1618,14 +1670,14 @@ in
|
|||
width: actionText.width + 12
|
||||
height: actionText.height + 4
|
||||
radius: 4
|
||||
color: actionMa.containsMouse ? "#${c.base02}" : "#${c.base01}"
|
||||
color: actionMa.containsMouse ? Theme.base02 : Theme.base01
|
||||
border.width: 1
|
||||
border.color: "#${c.base02}"
|
||||
border.color: Theme.base02
|
||||
Text {
|
||||
id: actionText
|
||||
anchors.centerIn: parent
|
||||
text: modelData.text
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 10
|
||||
}
|
||||
|
|
@ -1641,14 +1693,13 @@ in
|
|||
}
|
||||
}
|
||||
|
||||
// Dismiss button
|
||||
Text {
|
||||
id: dismissBtn
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 6
|
||||
text: "\u{f0156}"
|
||||
color: dismissMa.containsMouse ? "#${c.base05}" : "#${c.base03}"
|
||||
color: dismissMa.containsMouse ? Theme.base05 : Theme.base03
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 12
|
||||
MouseArea {
|
||||
|
|
@ -1665,25 +1716,28 @@ in
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
// Notification toast
|
||||
Variants {
|
||||
model: Quickshell.screens
|
||||
"quickshell/NotificationToast.qml" = {
|
||||
onChange = qsRestart;
|
||||
text = ''
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
|
||||
PopupWindow {
|
||||
id: notifToast
|
||||
required property var modelData
|
||||
required property var shellRoot
|
||||
screen: modelData
|
||||
property var currentNotif: null
|
||||
property bool open: false
|
||||
|
||||
Connections {
|
||||
target: root
|
||||
target: shellRoot
|
||||
function onNotificationReceived() {
|
||||
if (notifToast.modelData === Quickshell.screens[0]) {
|
||||
notifToast.show(root.latestNotification);
|
||||
notifToast.show(shellRoot.latestNotification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1735,7 +1789,7 @@ in
|
|||
width: 316
|
||||
height: toastCol.height + 16
|
||||
radius: 8
|
||||
color: "#E6${c.base00}"
|
||||
color: Theme.toastBg
|
||||
clip: true
|
||||
|
||||
transform: Translate {
|
||||
|
|
@ -1761,7 +1815,7 @@ in
|
|||
Text {
|
||||
width: parent.width
|
||||
text: notifToast.currentNotif ? (notifToast.currentNotif.summary || notifToast.currentNotif.appName) : ""
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 12
|
||||
font.weight: Font.Medium
|
||||
|
|
@ -1771,7 +1825,7 @@ in
|
|||
Text {
|
||||
width: parent.width
|
||||
text: notifToast.currentNotif ? (notifToast.currentNotif.body || "") : ""
|
||||
color: "#${c.base04}"
|
||||
color: Theme.base04
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 11
|
||||
elide: Text.ElideRight
|
||||
|
|
@ -1780,7 +1834,6 @@ in
|
|||
visible: text !== ""
|
||||
}
|
||||
|
||||
// Action buttons
|
||||
Row {
|
||||
spacing: 4
|
||||
visible: notifToast.currentNotif && notifToast.currentNotif.actions.length > 0
|
||||
|
|
@ -1791,14 +1844,14 @@ in
|
|||
width: toastActionText.width + 12
|
||||
height: toastActionText.height + 6
|
||||
radius: 4
|
||||
color: toastActionMa.containsMouse ? "#${c.base02}" : "#${c.base01}"
|
||||
color: toastActionMa.containsMouse ? Theme.base02 : Theme.base01
|
||||
border.width: 1
|
||||
border.color: "#${c.base02}"
|
||||
border.color: Theme.base02
|
||||
Text {
|
||||
id: toastActionText
|
||||
anchors.centerIn: parent
|
||||
text: modelData.text
|
||||
color: "#${c.base05}"
|
||||
color: Theme.base05
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 10
|
||||
}
|
||||
|
|
@ -1814,14 +1867,13 @@ in
|
|||
}
|
||||
}
|
||||
|
||||
// Dismiss X
|
||||
Text {
|
||||
id: toastDismiss
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 8
|
||||
text: "\u{f0156}"
|
||||
color: toastDismissMa.containsMouse ? "#${c.base05}" : "#${c.base03}"
|
||||
color: toastDismissMa.containsMouse ? Theme.base05 : Theme.base03
|
||||
font.family: "FiraMono Nerd Font"
|
||||
font.pixelSize: 13
|
||||
MouseArea {
|
||||
|
|
@ -1834,10 +1886,9 @@ in
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue