quickshell: material symbols icons, network cards, session menu morphs from right edge
- Material Symbols Rounded (ligature names) replaces nerd-font glyphs for all shell icons; text stays on the stylix mono font - network dropdown gets the card treatment like the others - power menu is now an icon-only session panel melting out of the right frame column at screen centre (still Super+L); launcher is apps-only Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
4540e38321
commit
a14ccd8c09
1 changed files with 415 additions and 232 deletions
|
|
@ -12,6 +12,10 @@ in
|
|||
qt6.qt5compat # Qt5Compat.GraphicalEffects in Bar.qml
|
||||
];
|
||||
|
||||
# Icon font for the shell (ligature-based: text "volume_up" renders the
|
||||
# icon) — same font caelestia uses; nerd-font glyphs stay for terminals.
|
||||
fonts.packages = [ pkgs.material-symbols ];
|
||||
|
||||
home-manager.users.fred = { config, lib, pkgs, osConfig, ... }:
|
||||
let
|
||||
c = config.lib.stylix.colors;
|
||||
|
|
@ -64,6 +68,7 @@ in
|
|||
vec4 cutout; // cx, cy, hw, hh — rounded inner screen cutout
|
||||
vec4 panel; // cx, cy, hw, hh — dropdown panel (hw <= 0: none)
|
||||
vec4 toast; // cx, cy, hw, hh — toast (hw <= 0: none)
|
||||
vec4 session; // cx, cy, hw, hh — session menu (hw <= 0: none)
|
||||
vec4 fillColor; // straight (non-premultiplied) rgba
|
||||
vec4 borderColor;
|
||||
vec2 res;
|
||||
|
|
@ -94,6 +99,8 @@ in
|
|||
d = smin(d, sdRoundedBox(p, panel.xy, panel.zw, panelR), meltK);
|
||||
if (toast.z > 0.5)
|
||||
d = smin(d, sdRoundedBox(p, toast.xy, toast.zw, panelR), meltK);
|
||||
if (session.z > 0.5)
|
||||
d = smin(d, sdRoundedBox(p, session.xy, session.zw, panelR), meltK);
|
||||
|
||||
float fw = fwidth(d);
|
||||
// 1 inside the union, 0 outside (antialiased)
|
||||
|
|
@ -152,6 +159,8 @@ in
|
|||
readonly property color barBg: "#B3${c.base00}"
|
||||
readonly property color toastBg: "#E6${c.base00}"
|
||||
readonly property string fontFamily: "${monoFont}"
|
||||
// Ligature-based icon font: text "volume_up" renders the icon
|
||||
readonly property string iconFont: "Material Symbols Rounded"
|
||||
// Matches hyprland general.border_size (col.inactive_border = base03)
|
||||
readonly property int borderWidth: 2
|
||||
// Screen frame band; sits inside hyprland's gaps_out (12)
|
||||
|
|
@ -189,17 +198,19 @@ in
|
|||
ShellRoot {
|
||||
id: root
|
||||
property var latestNotification: null
|
||||
property var mainBar: null
|
||||
signal notificationReceived()
|
||||
|
||||
Launcher {
|
||||
id: launcher
|
||||
}
|
||||
|
||||
// Bound in hyprland.nix: Super+R → toggle, Super+L → powermenu
|
||||
// Bound in hyprland.nix: Super+R → app launcher,
|
||||
// Super+L → session menu (in the bar window).
|
||||
IpcHandler {
|
||||
target: "launcher"
|
||||
function toggle(): void { launcher.toggleMode("apps"); }
|
||||
function powermenu(): void { launcher.toggleMode("power"); }
|
||||
function toggle(): void { launcher.toggle(); }
|
||||
function powermenu(): void { if (root.mainBar) root.mainBar.toggleSession(); }
|
||||
}
|
||||
|
||||
// Soft reload, used by the nix onChange hook — keeps the
|
||||
|
|
@ -249,9 +260,6 @@ in
|
|||
PanelWindow {
|
||||
id: root
|
||||
|
||||
// "apps" (Super+R) or "power" (Super+L)
|
||||
property string mode: "apps"
|
||||
|
||||
visible: false
|
||||
screen: Quickshell.screens[0]
|
||||
WlrLayershell.namespace: "quickshell-launcher"
|
||||
|
|
@ -267,9 +275,8 @@ in
|
|||
right: true
|
||||
}
|
||||
|
||||
function toggleMode(m) {
|
||||
if (visible && mode === m) { close(); return; }
|
||||
mode = m;
|
||||
function toggle() {
|
||||
if (visible) { close(); return; }
|
||||
search.text = "";
|
||||
list.currentIndex = 0;
|
||||
visible = true;
|
||||
|
|
@ -279,18 +286,6 @@ in
|
|||
visible = false;
|
||||
}
|
||||
|
||||
// Lock/reboot/shutdown spawn via Quickshell.execDetached — fully
|
||||
// detached, so a quickshell restart can never kill a running
|
||||
// hyprlock. Logout (empty cmd) goes through Hyprland IPC; with a
|
||||
// Lua config the dispatch body is evaluated as a Lua dispatcher
|
||||
// expression, so it must use hl.dsp.* syntax, not hyprlang's.
|
||||
readonly property var powerActions: [
|
||||
{ name: "Lock", glyph: "", cmd: [Commands.hyprlock] },
|
||||
{ name: "Logout", glyph: "", cmd: [] },
|
||||
{ name: "Reboot", glyph: "", cmd: [Commands.systemctl, "reboot"] },
|
||||
{ name: "Shutdown", glyph: "", cmd: [Commands.systemctl, "poweroff"] }
|
||||
]
|
||||
|
||||
function score(name, extra, q) {
|
||||
let n = name.toLowerCase();
|
||||
if (n.startsWith(q)) return 5;
|
||||
|
|
@ -313,9 +308,6 @@ in
|
|||
|
||||
property var entries: {
|
||||
let q = search.text.toLowerCase().trim();
|
||||
if (mode === "power") {
|
||||
return powerActions.filter(a => q === "" || score(a.name, "", q) > 0);
|
||||
}
|
||||
let apps = DesktopEntries.applications.values.filter(a => !a.noDisplay);
|
||||
if (q === "") {
|
||||
apps.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
|
@ -332,12 +324,7 @@ in
|
|||
|
||||
function activate(item) {
|
||||
if (!item) return;
|
||||
if (mode === "power") {
|
||||
if (item.cmd.length === 0) Hyprland.dispatch("hl.dsp.exit()");
|
||||
else Quickshell.execDetached(item.cmd);
|
||||
} else {
|
||||
item.execute();
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
|
|
@ -399,7 +386,7 @@ in
|
|||
anchors.fill: search
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
visible: search.text === ""
|
||||
text: root.mode === "power" ? "Power" : "Search"
|
||||
text: "Search"
|
||||
color: Theme.base03
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 13
|
||||
|
|
@ -429,22 +416,13 @@ in
|
|||
spacing: 10
|
||||
|
||||
Image {
|
||||
visible: root.mode === "apps" && source != ""
|
||||
visible: source != ""
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 18
|
||||
height: 18
|
||||
sourceSize.width: 18
|
||||
sourceSize.height: 18
|
||||
source: root.mode === "apps" ? Quickshell.iconPath(modelData.icon, true) : ""
|
||||
}
|
||||
|
||||
Text {
|
||||
visible: root.mode === "power"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.mode === "power" ? modelData.glyph : ""
|
||||
color: Theme.base0D
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 14
|
||||
source: Quickshell.iconPath(modelData.icon, true)
|
||||
}
|
||||
|
||||
Text {
|
||||
|
|
@ -522,6 +500,12 @@ in
|
|||
width: toastItem.visible ? toastItem.width : 0
|
||||
height: toastItem.visible ? toastItem.height : 0
|
||||
}
|
||||
Region {
|
||||
x: sessionMenu.visible ? sessionMenu.x : 0
|
||||
y: sessionMenu.visible ? sessionMenu.y : 0
|
||||
width: sessionMenu.visible ? sessionMenu.width : 0
|
||||
height: sessionMenu.visible ? sessionMenu.height : 0
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
@ -532,6 +516,113 @@ in
|
|||
height: 30
|
||||
}
|
||||
|
||||
// Register the primary bar so shell.qml's IPC handler can
|
||||
// reach the session menu.
|
||||
Component.onCompleted: {
|
||||
if (bar.screen === Quickshell.screens[0])
|
||||
bar.shellRoot.mainBar = bar;
|
||||
}
|
||||
|
||||
function toggleSession() {
|
||||
sessionMenu.toggle();
|
||||
}
|
||||
|
||||
// ── Session menu: icon-only power controls morphing out of
|
||||
// the right frame column at screen centre (Super+L).
|
||||
Item {
|
||||
id: sessionMenu
|
||||
property bool open: false
|
||||
property real openW: open ? 56 : 0
|
||||
Behavior on openW {
|
||||
NumberAnimation { duration: 280; easing.type: Easing.OutExpo }
|
||||
}
|
||||
|
||||
x: bar.width - Theme.frameWidth - openW
|
||||
y: Math.round((bar.height - height) / 2)
|
||||
width: openW
|
||||
height: sessionCol.height + 24
|
||||
visible: openW > 0.5
|
||||
|
||||
function toggle() {
|
||||
open = !open;
|
||||
if (open) _sessionAutoClose.restart();
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: _sessionAutoClose
|
||||
interval: 2500
|
||||
onTriggered: sessionMenu.open = false
|
||||
}
|
||||
|
||||
HoverHandler {
|
||||
onHoveredChanged: {
|
||||
if (hovered) _sessionAutoClose.stop();
|
||||
else if (sessionMenu.open) _sessionAutoClose.restart();
|
||||
}
|
||||
}
|
||||
|
||||
// Content pinned to the column edge, revealed by the grow
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
opacity: sessionMenu.open ? 1 : 0
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 200; easing.type: Easing.OutCubic }
|
||||
}
|
||||
|
||||
Column {
|
||||
id: sessionCol
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
spacing: 4
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
{ icon: "lock", danger: false, act: "lock" },
|
||||
{ icon: "logout", danger: false, act: "logout" },
|
||||
{ icon: "restart_alt", danger: true, act: "reboot" },
|
||||
{ icon: "power_settings_new", danger: true, act: "poweroff" }
|
||||
]
|
||||
|
||||
Rectangle {
|
||||
id: sessBtn
|
||||
required property var modelData
|
||||
width: 40
|
||||
height: 40
|
||||
radius: 8
|
||||
color: sessBtnMa.containsMouse ? Theme.base02 : "transparent"
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: sessBtn.modelData.icon
|
||||
color: sessBtn.modelData.danger && sessBtnMa.containsMouse
|
||||
? Theme.base08 : Theme.base05
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 20
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: sessBtnMa
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
sessionMenu.open = false;
|
||||
if (sessBtn.modelData.act === "lock") Quickshell.execDetached([Commands.hyprlock]);
|
||||
else if (sessBtn.modelData.act === "logout") Hyprland.dispatch("hl.dsp.exit()");
|
||||
else if (sessBtn.modelData.act === "reboot") Quickshell.execDetached([Commands.systemctl, "reboot"]);
|
||||
else Quickshell.execDetached([Commands.systemctl, "poweroff"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Shell chrome: bar, frame, panel and toast rendered as
|
||||
// ONE signed-distance field (caelestia-style). Surfaces merge
|
||||
// via circular smooth-min, and the 2px border is the distance
|
||||
|
|
@ -555,6 +646,11 @@ in
|
|||
? Qt.vector4d(toastItem.x + 8 + _toastRect.width / 2, 26 + _toastRect.height / 2,
|
||||
_toastRect.width / 2, 4 + _toastRect.height / 2)
|
||||
: Qt.vector4d(0, 0, 0, 0)
|
||||
readonly property real sessRight: bar.width - Theme.frameWidth + 4
|
||||
property vector4d session: sessionMenu.visible
|
||||
? Qt.vector4d((sessionMenu.x + sessRight) / 2, sessionMenu.y + sessionMenu.height / 2,
|
||||
(sessRight - sessionMenu.x) / 2, sessionMenu.height / 2)
|
||||
: Qt.vector4d(0, 0, 0, 0)
|
||||
property vector4d fillColor: Qt.vector4d(Theme.barBg.r, Theme.barBg.g, Theme.barBg.b, Theme.barBg.a)
|
||||
property vector4d borderColor: Qt.vector4d(Theme.base03.r, Theme.base03.g, Theme.base03.b, 1)
|
||||
property vector2d res: Qt.vector2d(width, height)
|
||||
|
|
@ -691,7 +787,7 @@ in
|
|||
// Volume
|
||||
Item {
|
||||
id: volWidget
|
||||
width: volText.width
|
||||
width: volRow.width
|
||||
height: 30
|
||||
|
||||
property PwNode sink: Pipewire.defaultAudioSink
|
||||
|
|
@ -702,11 +798,11 @@ in
|
|||
|
||||
property int vol: sink && sink.audio ? Math.round(sink.audio.volume * 100) : 0
|
||||
property bool muted: sink && sink.audio ? sink.audio.muted : false
|
||||
property string volIcon: muted ? "\u{f0581}"
|
||||
: vol > 66 ? "\u{f057e}"
|
||||
: vol > 33 ? "\u{f0580}"
|
||||
: vol > 0 ? "\u{f057f}"
|
||||
: "\u{f0581}"
|
||||
property string volIcon: muted ? "volume_off"
|
||||
: vol > 66 ? "volume_up"
|
||||
: vol > 33 ? "volume_down"
|
||||
: vol > 0 ? "volume_mute"
|
||||
: "volume_off"
|
||||
|
||||
function openVolDropdown() {
|
||||
bar.toggleDropdown(volDropdown, function() {
|
||||
|
|
@ -715,14 +811,27 @@ in
|
|||
});
|
||||
}
|
||||
|
||||
Text {
|
||||
id: volText
|
||||
Row {
|
||||
id: volRow
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: volWidget.volIcon + " " + volWidget.vol + "%"
|
||||
spacing: 3
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: volWidget.volIcon
|
||||
color: volWidget.muted ? Theme.base03 : Theme.base05
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 16
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: volWidget.vol + "%"
|
||||
color: volWidget.muted ? Theme.base03 : Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 13
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
|
@ -754,7 +863,7 @@ in
|
|||
property string netState: "disconnected"
|
||||
property string netConn: ""
|
||||
property string netType: ""
|
||||
property string netIcon: "\u{f0b0}"
|
||||
property string netIcon: "wifi_off"
|
||||
property var wifiNetworks: []
|
||||
property string netDevice: ""
|
||||
|
||||
|
|
@ -832,9 +941,9 @@ in
|
|||
netWidget.netType = netWidget._pendingType.length > 0 ? netWidget._pendingType : netWidget.netType;
|
||||
netWidget.netDevice = netWidget._pendingDevice.length > 0 ? netWidget._pendingDevice : netWidget.netDevice;
|
||||
if (netWidget.netState === "connected") {
|
||||
netWidget.netIcon = netWidget.netType === "wifi" ? "\u{f05a9}" : "\u{f0200}";
|
||||
netWidget.netIcon = netWidget.netType === "wifi" ? "wifi" : "lan";
|
||||
} else {
|
||||
netWidget.netIcon = netWidget.netType === "wifi" ? "\u{f05aa}" : "\u{f0201}";
|
||||
netWidget.netIcon = netWidget.netType === "wifi" ? "wifi_off" : "settings_ethernet";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -844,8 +953,8 @@ in
|
|||
anchors.centerIn: parent
|
||||
text: netWidget.netIcon
|
||||
color: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 14
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 16
|
||||
}
|
||||
|
||||
Timer {
|
||||
|
|
@ -938,13 +1047,13 @@ in
|
|||
PowerProfiles.profile === PowerProfile.PowerSaver ? "power-saver"
|
||||
: PowerProfiles.profile === PowerProfile.Performance ? "performance"
|
||||
: "balanced"
|
||||
property string batteryIcon: charging ? "\u{f0084}"
|
||||
: batteryLevel >= 90 ? "\u{f0079}"
|
||||
: batteryLevel >= 70 ? "\u{f0082}"
|
||||
: batteryLevel >= 50 ? "\u{f007f}"
|
||||
: batteryLevel >= 30 ? "\u{f007c}"
|
||||
: batteryLevel >= 15 ? "\u{f007a}"
|
||||
: "\u{f008e}"
|
||||
property string batteryIcon: charging ? "battery_charging_full"
|
||||
: batteryLevel >= 90 ? "battery_full"
|
||||
: batteryLevel >= 70 ? "battery_6_bar"
|
||||
: batteryLevel >= 50 ? "battery_5_bar"
|
||||
: batteryLevel >= 30 ? "battery_3_bar"
|
||||
: batteryLevel >= 15 ? "battery_2_bar"
|
||||
: "battery_alert"
|
||||
|
||||
Row {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
|
@ -966,8 +1075,8 @@ in
|
|||
color: batteryWidget.batteryLevel <= 15 ? Theme.base08
|
||||
: batteryWidget.batteryLevel <= 30 ? Theme.base0A
|
||||
: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 14
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 16
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1383,13 +1492,24 @@ in
|
|||
width: parent.width - 16
|
||||
spacing: 8
|
||||
|
||||
Row {
|
||||
spacing: 6
|
||||
Text {
|
||||
text: "\u{f057e} Master"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "volume_up"
|
||||
color: Theme.base05
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 16
|
||||
}
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Master"
|
||||
color: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width
|
||||
|
|
@ -1456,13 +1576,24 @@ in
|
|||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
radius: 4
|
||||
|
||||
Text {
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
text: volWidget.muted ? "\u{f0581} Unmute" : "\u{f057e} Mute"
|
||||
spacing: 6
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: volWidget.muted ? "volume_off" : "volume_up"
|
||||
color: Theme.base05
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 15
|
||||
}
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: volWidget.muted ? "Unmute" : "Mute"
|
||||
color: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
id: masterMuteMa
|
||||
anchors.fill: parent
|
||||
|
|
@ -1493,13 +1624,24 @@ in
|
|||
width: parent.width - 16
|
||||
spacing: 8
|
||||
|
||||
Row {
|
||||
spacing: 6
|
||||
Text {
|
||||
text: "\u{f0641} Applications"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "graphic_eq"
|
||||
color: Theme.base05
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 16
|
||||
}
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Applications"
|
||||
color: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
}
|
||||
|
||||
// Per-app streams
|
||||
Column {
|
||||
|
|
@ -1602,20 +1744,48 @@ in
|
|||
Column {
|
||||
id: netDropdownCol
|
||||
anchors.centerIn: parent
|
||||
width: 220
|
||||
width: 228
|
||||
spacing: 8
|
||||
|
||||
// Connection card
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: connCardCol.height + 16
|
||||
radius: 8
|
||||
color: Theme.base01
|
||||
|
||||
Column {
|
||||
id: connCardCol
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width - 16
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
Row {
|
||||
width: parent.width
|
||||
spacing: 6
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: netWidget.netState === "connected" ? "wifi" : "wifi_off"
|
||||
color: Theme.base05
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 16
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width - 22
|
||||
text: netWidget.netState === "connected"
|
||||
? "\u{f05a9} " + netWidget.netConn
|
||||
: "\u{f05aa} Not connected"
|
||||
? netWidget.netConn : "Not connected"
|
||||
color: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: netWidget.netState === "connected"
|
||||
|
|
@ -1637,31 +1807,41 @@ in
|
|||
id: disconnectMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
netDisconnectProc.targetDevice = netWidget.netDevice;
|
||||
netDisconnectProc.running = true;
|
||||
netWidget.netState = "disconnected";
|
||||
netWidget.netConn = "";
|
||||
netWidget.netIcon = "\u{f05aa}";
|
||||
netWidget.netIcon = "wifi_off";
|
||||
bar.closeAllDropdowns();
|
||||
netRefreshDelay.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width - 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 1
|
||||
color: Theme.base03
|
||||
}
|
||||
}
|
||||
|
||||
// Available networks card
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: netsCardCol.height + 16
|
||||
radius: 8
|
||||
color: Theme.base01
|
||||
|
||||
Column {
|
||||
id: netsCardCol
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: parent.width - 16
|
||||
spacing: 4
|
||||
|
||||
Text {
|
||||
text: "Available networks"
|
||||
color: Theme.base03
|
||||
color: Theme.base04
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 11
|
||||
topPadding: 2
|
||||
}
|
||||
|
||||
Repeater {
|
||||
|
|
@ -1669,7 +1849,7 @@ in
|
|||
|
||||
Rectangle {
|
||||
required property var modelData
|
||||
width: 220
|
||||
width: netsCardCol.width
|
||||
height: 32
|
||||
color: netItemMouse.containsMouse ? Theme.base02 : "transparent"
|
||||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
|
|
@ -1686,14 +1866,14 @@ in
|
|||
Text {
|
||||
text: {
|
||||
let s = modelData.signal;
|
||||
if (s >= 75) return "\u{f0928}"; // strength 4
|
||||
if (s >= 50) return "\u{f0925}"; // strength 3
|
||||
if (s >= 25) return "\u{f0922}"; // strength 2
|
||||
return "\u{f091f}"; // strength 1
|
||||
if (s >= 75) return "signal_wifi_4_bar";
|
||||
if (s >= 50) return "network_wifi_3_bar";
|
||||
if (s >= 25) return "network_wifi_2_bar";
|
||||
return "network_wifi_1_bar";
|
||||
}
|
||||
color: modelData.active ? Theme.base0B : Theme.base04
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 13
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
|
@ -1709,10 +1889,10 @@ in
|
|||
|
||||
Text {
|
||||
visible: modelData.security !== "" && modelData.security !== "--"
|
||||
text: "\u{f0341}"
|
||||
text: "lock"
|
||||
color: Theme.base03
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 10
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 13
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
|
@ -1721,6 +1901,7 @@ in
|
|||
id: netItemMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
if (!modelData.active) {
|
||||
wifiConnectProc.targetSsid = modelData.ssid;
|
||||
|
|
@ -1734,6 +1915,8 @@ in
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${lib.optionalString isMacbook ''
|
||||
// Battery dropdown
|
||||
|
|
@ -1770,8 +1953,8 @@ in
|
|||
Text {
|
||||
text: batteryWidget.batteryIcon
|
||||
color: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 18
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 22
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
|
|
@ -1848,9 +2031,9 @@ in
|
|||
|
||||
Repeater {
|
||||
model: [
|
||||
{ name: "power-saver", profile: PowerProfile.PowerSaver, label: "\u{f0425}", tip: "Saver" },
|
||||
{ name: "balanced", profile: PowerProfile.Balanced, label: "\u{f0376}", tip: "Balanced" },
|
||||
{ name: "performance", profile: PowerProfile.Performance, label: "\u{f0e0e}", tip: "Performance" }
|
||||
{ name: "power-saver", profile: PowerProfile.PowerSaver, label: "energy_savings_leaf", tip: "Saver" },
|
||||
{ name: "balanced", profile: PowerProfile.Balanced, label: "balance", tip: "Balanced" },
|
||||
{ name: "performance", profile: PowerProfile.Performance, label: "speed", tip: "Performance" }
|
||||
]
|
||||
|
||||
Rectangle {
|
||||
|
|
@ -1871,8 +2054,8 @@ in
|
|||
color: batteryWidget.powerProfile === modelData.name
|
||||
? Theme.base0D : Theme.base05
|
||||
Behavior on color { ColorAnimation { duration: 200 } }
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 14
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 17
|
||||
}
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
|
@ -1963,16 +2146,16 @@ in
|
|||
onTriggered: weatherProc.running = true
|
||||
}
|
||||
function weatherGlyph(code) {
|
||||
if (code === 0) return "\u{f0599}"; // sunny
|
||||
if (code <= 2) return "\u{f0595}"; // partly cloudy
|
||||
if (code === 3) return "\u{f0590}"; // overcast
|
||||
if (code <= 48) return "\u{f0591}"; // fog
|
||||
if (code <= 57) return "\u{f0597}"; // drizzle
|
||||
if (code <= 67) return "\u{f0596}"; // rain
|
||||
if (code <= 77) return "\u{f0598}"; // snow
|
||||
if (code <= 82) return "\u{f0597}"; // showers
|
||||
if (code <= 86) return "\u{f0598}"; // snow showers
|
||||
return "\u{f0593}"; // thunder
|
||||
if (code === 0) return "clear_day";
|
||||
if (code <= 2) return "partly_cloudy_day";
|
||||
if (code === 3) return "cloud";
|
||||
if (code <= 48) return "foggy";
|
||||
if (code <= 57) return "rainy";
|
||||
if (code <= 67) return "rainy";
|
||||
if (code <= 77) return "cloudy_snowing";
|
||||
if (code <= 82) return "rainy";
|
||||
if (code <= 86) return "cloudy_snowing";
|
||||
return "thunderstorm";
|
||||
}
|
||||
|
||||
// --- Media: prefer the actively playing MPRIS player ---
|
||||
|
|
@ -2029,10 +2212,10 @@ in
|
|||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "\u{f0141}"
|
||||
text: "chevron_left"
|
||||
color: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 16
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 18
|
||||
}
|
||||
MouseArea {
|
||||
id: calPrevMa
|
||||
|
|
@ -2064,10 +2247,10 @@ in
|
|||
Behavior on color { ColorAnimation { duration: 120 } }
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "\u{f0142}"
|
||||
text: "chevron_right"
|
||||
color: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 16
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 18
|
||||
}
|
||||
MouseArea {
|
||||
id: calNextMa
|
||||
|
|
@ -2159,8 +2342,8 @@ in
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: calPopup.weatherGlyph(modelData.code)
|
||||
color: Theme.base0C
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 14
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 16
|
||||
}
|
||||
Text {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
|
@ -2210,10 +2393,10 @@ in
|
|||
Text {
|
||||
anchors.centerIn: parent
|
||||
visible: albumArt.status !== Image.Ready
|
||||
text: "\u{f0387}"
|
||||
text: "music_note"
|
||||
color: Theme.base04
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 20
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 22
|
||||
}
|
||||
Image {
|
||||
id: albumArt
|
||||
|
|
@ -2251,9 +2434,9 @@ in
|
|||
spacing: 2
|
||||
Repeater {
|
||||
model: [
|
||||
{ glyph: "\u{f04ae}", act: "prev" },
|
||||
{ glyph: calPopup.player && calPopup.player.playbackState === MprisPlaybackState.Playing ? "\u{f03e4}" : "\u{f040a}", act: "toggle" },
|
||||
{ glyph: "\u{f04ad}", act: "next" }
|
||||
{ glyph: "skip_previous", act: "prev" },
|
||||
{ glyph: calPopup.player && calPopup.player.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow", act: "toggle" },
|
||||
{ glyph: "skip_next", act: "next" }
|
||||
]
|
||||
Rectangle {
|
||||
id: mediaBtn
|
||||
|
|
@ -2265,8 +2448,8 @@ in
|
|||
anchors.centerIn: parent
|
||||
text: mediaBtn.modelData.glyph
|
||||
color: Theme.base05
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 16
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 18
|
||||
}
|
||||
MouseArea {
|
||||
id: mediaBtnMa
|
||||
|
|
@ -2425,10 +2608,10 @@ in
|
|||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 6
|
||||
text: "\u{f0156}"
|
||||
text: "close"
|
||||
color: dismissMa.containsMouse ? Theme.base05 : Theme.base03
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 12
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 14
|
||||
MouseArea {
|
||||
id: dismissMa
|
||||
anchors.fill: parent
|
||||
|
|
@ -2604,10 +2787,10 @@ in
|
|||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 8
|
||||
text: "\u{f0156}"
|
||||
text: "close"
|
||||
color: toastDismissMa.containsMouse ? Theme.base05 : Theme.base03
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 13
|
||||
font.family: Theme.iconFont
|
||||
font.pixelSize: 15
|
||||
MouseArea {
|
||||
id: toastDismissMa
|
||||
anchors.fill: parent
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue