summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/BarConfig.qml4
-rw-r--r--config/Config.qml54
-rw-r--r--config/ToastsConfig.qml14
-rw-r--r--config/UtilitiesConfig.qml65
-rw-r--r--config/WInfoConfig.qml10
-rw-r--r--modules/BatteryMonitor.qml4
-rw-r--r--modules/Shortcuts.qml28
-rw-r--r--modules/bar/Bar.qml4
-rw-r--r--modules/bar/components/Settings.qml41
-rw-r--r--modules/bar/components/SettingsIcon.qml41
-rw-r--r--modules/bar/components/workspaces/OccupiedBg.qml103
-rw-r--r--modules/bar/popouts/Audio.qml13
-rw-r--r--modules/bar/popouts/Background.qml2
-rw-r--r--modules/bar/popouts/Bluetooth.qml13
-rw-r--r--modules/bar/popouts/Content.qml5
-rw-r--r--modules/bar/popouts/LockStatus.qml16
-rw-r--r--modules/bar/popouts/Wrapper.qml56
-rw-r--r--modules/bar/popouts/kblayout/KbLayoutModel.qml2
-rw-r--r--modules/controlcenter/ControlCenter.qml100
-rw-r--r--modules/controlcenter/NavRail.qml231
-rw-r--r--modules/controlcenter/PaneRegistry.qml68
-rw-r--r--modules/controlcenter/Panes.qml171
-rw-r--r--modules/controlcenter/Session.qml21
-rw-r--r--modules/controlcenter/WindowFactory.qml62
-rw-r--r--modules/controlcenter/WindowTitle.qml51
-rw-r--r--modules/controlcenter/audio/AudioPane.qml621
-rw-r--r--modules/controlcenter/bluetooth/BtPane.qml73
-rw-r--r--modules/controlcenter/bluetooth/Details.qml671
-rw-r--r--modules/controlcenter/bluetooth/DeviceList.qml264
-rw-r--r--modules/controlcenter/bluetooth/Settings.qml532
-rw-r--r--modules/controlcenter/components/DeviceDetails.qml70
-rw-r--r--modules/controlcenter/components/DeviceList.qml84
-rw-r--r--modules/controlcenter/components/PaneTransition.qml71
-rw-r--r--modules/controlcenter/components/ReadonlySlider.qml67
-rw-r--r--modules/controlcenter/components/SettingsHeader.qml37
-rw-r--r--modules/controlcenter/components/SliderInput.qml180
-rw-r--r--modules/controlcenter/components/SplitPaneLayout.qml109
-rw-r--r--modules/controlcenter/components/SplitPaneWithDetails.qml93
-rw-r--r--modules/controlcenter/dashboard/DashboardPane.qml135
-rw-r--r--modules/controlcenter/dashboard/GeneralSection.qml128
-rw-r--r--modules/controlcenter/dashboard/PerformanceSection.qml106
-rw-r--r--modules/controlcenter/network/EthernetDetails.qml118
-rw-r--r--modules/controlcenter/network/EthernetList.qml177
-rw-r--r--modules/controlcenter/network/EthernetPane.qml50
-rw-r--r--modules/controlcenter/network/EthernetSettings.qml76
-rw-r--r--modules/controlcenter/network/NetworkSettings.qml99
-rw-r--r--modules/controlcenter/network/NetworkingPane.qml309
-rw-r--r--modules/controlcenter/network/WirelessDetails.qml211
-rw-r--r--modules/controlcenter/network/WirelessList.qml228
-rw-r--r--modules/controlcenter/network/WirelessPane.qml57
-rw-r--r--modules/controlcenter/network/WirelessPasswordDialog.qml511
-rw-r--r--modules/controlcenter/network/WirelessSettings.qml73
-rw-r--r--modules/controlcenter/state/BluetoothState.qml12
-rw-r--r--modules/controlcenter/state/EthernetState.qml7
-rw-r--r--modules/controlcenter/state/NetworkState.qml9
-rw-r--r--modules/drawers/Backgrounds.qml9
-rw-r--r--modules/drawers/Drawers.qml3
-rw-r--r--modules/drawers/Interactions.qml32
-rw-r--r--modules/drawers/Panels.qml27
-rw-r--r--modules/osd/Wrapper.qml2
-rw-r--r--modules/sidebar/Background.qml9
-rw-r--r--modules/toasts/ToastItem.qml (renamed from modules/utilities/toasts/ToastItem.qml)0
-rw-r--r--modules/toasts/Toasts.qml (renamed from modules/utilities/toasts/Toasts.qml)6
-rw-r--r--modules/utilities/Background.qml55
-rw-r--r--modules/utilities/Content.qml27
-rw-r--r--modules/utilities/Wrapper.qml92
-rw-r--r--modules/utilities/cards/Toggles.qml162
-rw-r--r--modules/windowinfo/Buttons.qml180
-rw-r--r--modules/windowinfo/Details.qml164
-rw-r--r--modules/windowinfo/Preview.qml96
-rw-r--r--modules/windowinfo/WindowInfo.qml64
-rw-r--r--services/Audio.qml4
-rw-r--r--services/Hypr.qml6
-rw-r--r--services/Notifs.qml2
-rw-r--r--services/Players.qml2
-rw-r--r--services/VPN.qml179
76 files changed, 56 insertions, 7422 deletions
diff --git a/config/BarConfig.qml b/config/BarConfig.qml
index 34d8436..6548e98 100644
--- a/config/BarConfig.qml
+++ b/config/BarConfig.qml
@@ -47,10 +47,6 @@ JsonObject {
id: "statusIcons",
enabled: true
},
- {
- id: "power",
- enabled: true
- }
]
component ScrollActions: JsonObject {
diff --git a/config/Config.qml b/config/Config.qml
index bf8f6f2..e5029b2 100644
--- a/config/Config.qml
+++ b/config/Config.qml
@@ -20,10 +20,9 @@ Singleton {
property alias notifs: adapter.notifs
property alias osd: adapter.osd
property alias session: adapter.session
- property alias winfo: adapter.winfo
- property alias utilities: adapter.utilities
property alias sidebar: adapter.sidebar
property alias services: adapter.services
+ property alias toasts: adapter.toasts
property alias paths: adapter.paths
// Helper function to serialize the config object
@@ -40,11 +39,10 @@ Singleton {
notifs: serializeNotifs(),
osd: serializeOsd(),
session: serializeSession(),
- winfo: serializeWinfo(),
- utilities: serializeUtilities(),
sidebar: serializeSidebar(),
services: serializeServices(),
- paths: serializePaths()
+ toasts: serializeToasts(),
+ paths: serializePaths(),
};
}
@@ -259,34 +257,6 @@ Singleton {
};
}
- function serializeWinfo(): var {
- return {};
- }
-
- function serializeUtilities(): var {
- return {
- enabled: utilities.enabled,
- maxToasts: utilities.maxToasts,
- toasts: {
- configLoaded: utilities.toasts.configLoaded,
- chargingChanged: utilities.toasts.chargingChanged,
- dndChanged: utilities.toasts.dndChanged,
- audioOutputChanged: utilities.toasts.audioOutputChanged,
- audioInputChanged: utilities.toasts.audioInputChanged,
- capsLockChanged: utilities.toasts.capsLockChanged,
- numLockChanged: utilities.toasts.numLockChanged,
- kbLayoutChanged: utilities.toasts.kbLayoutChanged,
- vpnChanged: utilities.toasts.vpnChanged,
- nowPlaying: utilities.toasts.nowPlaying
- },
- vpn: {
- enabled: utilities.vpn.enabled,
- provider: utilities.vpn.provider
- },
- quickToggles: utilities.quickToggles
- };
- }
-
function serializeSidebar(): var {
return {
enabled: sidebar.enabled,
@@ -310,6 +280,21 @@ Singleton {
};
}
+ function serializeToasts(): var {
+ return {
+ configLoaded: toats.configLoaded,
+ chargingChanged: toats.chargingChanged,
+ dndChanged: toats.dndChanged,
+ audioOutputChanged: toats.audioOutputChanged,
+ audioInputChanged: toats.audioInputChanged,
+ capsLockChanged: toats.capsLockChanged,
+ numLockChanged: toats.numLockChanged,
+ kbLayoutChanged: toats.kbLayoutChanged,
+ kbLimit: toats.kbLimit,
+ nowPlaying: toats.nowPlaying,
+ };
+ }
+
function serializePaths(): var {
return {
wallpaper: paths.wallpaper,
@@ -352,10 +337,9 @@ Singleton {
property NotifsConfig notifs: NotifsConfig {}
property OsdConfig osd: OsdConfig {}
property SessionConfig session: SessionConfig {}
- property WInfoConfig winfo: WInfoConfig {}
- property UtilitiesConfig utilities: UtilitiesConfig {}
property SidebarConfig sidebar: SidebarConfig {}
property ServiceConfig services: ServiceConfig {}
+ property ToastsConfig toasts: ToastsConfig {}
property UserPaths paths: UserPaths {}
}
}
diff --git a/config/ToastsConfig.qml b/config/ToastsConfig.qml
new file mode 100644
index 0000000..5fed72f
--- /dev/null
+++ b/config/ToastsConfig.qml
@@ -0,0 +1,14 @@
+import Quickshell.Io
+
+JsonObject {
+ property bool configLoaded: true
+ property bool chargingChanged: true
+ property bool dndChanged: true
+ property bool audioOutputChanged: true
+ property bool audioInputChanged: true
+ property bool capsLockChanged: true
+ property bool numLockChanged: true
+ property bool kbLayoutChanged: true
+ property bool kbLimit: true
+ property bool nowPlaying: false
+}
diff --git a/config/UtilitiesConfig.qml b/config/UtilitiesConfig.qml
deleted file mode 100644
index e102526..0000000
--- a/config/UtilitiesConfig.qml
+++ /dev/null
@@ -1,65 +0,0 @@
-import Quickshell.Io
-
-JsonObject {
- property bool enabled: true
- property int maxToasts: 4
-
- property Sizes sizes: Sizes {}
- property Toasts toasts: Toasts {}
- property Vpn vpn: Vpn {}
-
- component Sizes: JsonObject {
- property int width: 430
- property int toastWidth: 430
- }
-
- component Toasts: JsonObject {
- property bool configLoaded: true
- property bool chargingChanged: true
- property bool dndChanged: true
- property bool audioOutputChanged: true
- property bool audioInputChanged: true
- property bool capsLockChanged: true
- property bool numLockChanged: true
- property bool kbLayoutChanged: true
- property bool kbLimit: true
- property bool vpnChanged: true
- property bool nowPlaying: false
- }
-
- component Vpn: JsonObject {
- property bool enabled: false
- property list<var> provider: ["netbird"]
- }
-
- property list<var> quickToggles: [
- {
- id: "wifi",
- enabled: true
- },
- {
- id: "bluetooth",
- enabled: true
- },
- {
- id: "mic",
- enabled: true
- },
- {
- id: "settings",
- enabled: true
- },
- {
- id: "gameMode",
- enabled: true
- },
- {
- id: "dnd",
- enabled: true
- },
- {
- id: "vpn",
- enabled: false
- }
- ]
-}
diff --git a/config/WInfoConfig.qml b/config/WInfoConfig.qml
deleted file mode 100644
index 5025780..0000000
--- a/config/WInfoConfig.qml
+++ /dev/null
@@ -1,10 +0,0 @@
-import Quickshell.Io
-
-JsonObject {
- property Sizes sizes: Sizes {}
-
- component Sizes: JsonObject {
- property real heightMult: 0.7
- property real detailsWidth: 500
- }
-}
diff --git a/modules/BatteryMonitor.qml b/modules/BatteryMonitor.qml
index d24cff2..bd3d6f0 100644
--- a/modules/BatteryMonitor.qml
+++ b/modules/BatteryMonitor.qml
@@ -14,10 +14,10 @@ Scope {
function onOnBatteryChanged(): void {
if (UPower.onBattery) {
- if (Config.utilities.toasts.chargingChanged)
+ if (Config.toasts.chargingChanged)
Toaster.toast(qsTr("Charger unplugged"), qsTr("Battery is discharging"), "power_off");
} else {
- if (Config.utilities.toasts.chargingChanged)
+ if (Config.toasts.chargingChanged)
Toaster.toast(qsTr("Charger plugged in"), qsTr("Battery is charging"), "power");
for (const level of root.warnLevels)
level.warned = false;
diff --git a/modules/Shortcuts.qml b/modules/Shortcuts.qml
index 3bf20a4..348a119 100644
--- a/modules/Shortcuts.qml
+++ b/modules/Shortcuts.qml
@@ -1,5 +1,4 @@
import qs.components.misc
-import qs.modules.controlcenter
import qs.services
import Caelestia
import Quickshell
@@ -12,19 +11,13 @@ Scope {
readonly property bool hasFullscreen: Hypr.focusedWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen === 2) ?? false
CustomShortcut {
- name: "controlCenter"
- description: "Open control center"
- onPressed: WindowFactory.create()
- }
-
- CustomShortcut {
name: "showall"
description: "Toggle launcher, dashboard and osd"
onPressed: {
if (root.hasFullscreen)
return;
const v = Visibilities.getForActive();
- v.launcher = v.dashboard = v.osd = v.utilities = !(v.launcher || v.dashboard || v.osd || v.utilities);
+ v.launcher = v.dashboard = v.osd = !(v.launcher || v.dashboard || v.osd);
}
}
@@ -81,17 +74,6 @@ Scope {
}
}
- CustomShortcut {
- name: "utilities"
- description: "Toggle utilities"
- onPressed: {
- if (root.hasFullscreen)
- return;
- const visibilities = Visibilities.getForActive();
- visibilities.utilities = !visibilities.utilities;
- }
- }
-
IpcHandler {
target: "drawers"
@@ -113,14 +95,6 @@ Scope {
}
IpcHandler {
- target: "controlCenter"
-
- function open(): void {
- WindowFactory.create();
- }
- }
-
- IpcHandler {
target: "toaster"
function info(title: string, message: string, icon: string): void {
diff --git a/modules/bar/Bar.qml b/modules/bar/Bar.qml
index 95c166e..550fbeb 100644
--- a/modules/bar/Bar.qml
+++ b/modules/bar/Bar.qml
@@ -68,10 +68,6 @@ ColumnLayout {
popouts.hasCurrent = false;
item.expanded = true;
}
- } else if (id === "activeWindow" && Config.bar.popouts.activeWindow && Config.bar.activeWindow.showOnHover) {
- popouts.currentName = id.toLowerCase();
- popouts.currentCenter = item.mapToItem(root, 0, itemHeight / 2).y;
- popouts.hasCurrent = true;
}
}
diff --git a/modules/bar/components/Settings.qml b/modules/bar/components/Settings.qml
deleted file mode 100644
index 5d562ce..0000000
--- a/modules/bar/components/Settings.qml
+++ /dev/null
@@ -1,41 +0,0 @@
-import qs.components
-import qs.modules.controlcenter
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- implicitWidth: icon.implicitHeight + Appearance.padding.small * 2
- implicitHeight: icon.implicitHeight
-
- StateLayer {
- // Cursed workaround to make the height larger than the parent
- anchors.fill: undefined
- anchors.centerIn: parent
- implicitWidth: implicitHeight
- implicitHeight: icon.implicitHeight + Appearance.padding.small * 2
-
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- WindowFactory.create(null, {
- active: "network"
- });
- }
- }
-
- MaterialIcon {
- id: icon
-
- anchors.centerIn: parent
- anchors.horizontalCenterOffset: -1
-
- text: "settings"
- color: Colours.palette.m3onSurface
- font.bold: true
- font.pointSize: Appearance.font.size.normal
- }
-}
diff --git a/modules/bar/components/SettingsIcon.qml b/modules/bar/components/SettingsIcon.qml
deleted file mode 100644
index 5d562ce..0000000
--- a/modules/bar/components/SettingsIcon.qml
+++ /dev/null
@@ -1,41 +0,0 @@
-import qs.components
-import qs.modules.controlcenter
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- implicitWidth: icon.implicitHeight + Appearance.padding.small * 2
- implicitHeight: icon.implicitHeight
-
- StateLayer {
- // Cursed workaround to make the height larger than the parent
- anchors.fill: undefined
- anchors.centerIn: parent
- implicitWidth: implicitHeight
- implicitHeight: icon.implicitHeight + Appearance.padding.small * 2
-
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- WindowFactory.create(null, {
- active: "network"
- });
- }
- }
-
- MaterialIcon {
- id: icon
-
- anchors.centerIn: parent
- anchors.horizontalCenterOffset: -1
-
- text: "settings"
- color: Colours.palette.m3onSurface
- font.bold: true
- font.pointSize: Appearance.font.size.normal
- }
-}
diff --git a/modules/bar/components/workspaces/OccupiedBg.qml b/modules/bar/components/workspaces/OccupiedBg.qml
deleted file mode 100644
index 56b215e..0000000
--- a/modules/bar/components/workspaces/OccupiedBg.qml
+++ /dev/null
@@ -1,103 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property Repeater workspaces
- required property var occupied
- required property int groupOffset
-
- property list<var> pills: []
-
- onOccupiedChanged: {
- if (!occupied)
- return;
- let count = 0;
- const start = groupOffset;
- const end = start + Config.bar.workspaces.shown;
- for (const [ws, occ] of Object.entries(occupied)) {
- if (ws > start && ws <= end && occ) {
- const isFirstInGroup = Number(ws) === start + 1;
- const isLastInGroup = Number(ws) === end;
- if (isFirstInGroup || !occupied[ws - 1]) {
- if (pills[count])
- pills[count].start = ws;
- else
- pills.push(pillComp.createObject(root, {
- start: ws
- }));
- count++;
- }
- if ((isLastInGroup || !occupied[ws + 1]) && pills[count - 1])
- pills[count - 1].end = ws;
- }
- }
- if (pills.length > count)
- pills.splice(count, pills.length - count).forEach(p => p.destroy());
- }
-
- Repeater {
- model: ScriptModel {
- values: root.pills.filter(p => p)
- }
-
- StyledRect {
- id: rect
-
- required property var modelData
-
- readonly property Workspace start: root.workspaces.count > 0 ? root.workspaces.itemAt(getWsIdx(modelData.start)) ?? null : null
- readonly property Workspace end: root.workspaces.count > 0 ? root.workspaces.itemAt(getWsIdx(modelData.end)) ?? null : null
-
- function getWsIdx(ws: int): int {
- let i = ws - 1;
- while (i < 0)
- i += Config.bar.workspaces.shown;
- return i % Config.bar.workspaces.shown;
- }
-
- anchors.horizontalCenter: root.horizontalCenter
-
- y: (start?.y ?? 0) - 1
- implicitWidth: Config.bar.sizes.innerWidth - Appearance.padding.small * 2 + 2
- implicitHeight: start && end ? end.y + end.size - start.y + 2 : 0
-
- color: Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
- radius: Appearance.rounding.full
-
- scale: 0
- Component.onCompleted: scale = 1
-
- Behavior on scale {
- Anim {
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
-
- Behavior on y {
- Anim {}
- }
-
- Behavior on implicitHeight {
- Anim {}
- }
- }
- }
-
- component Pill: QtObject {
- property int start
- property int end
- }
-
- Component {
- id: pillComp
-
- Pill {}
- }
-}
diff --git a/modules/bar/popouts/Audio.qml b/modules/bar/popouts/Audio.qml
index 58b29ba..2bfb1c7 100644
--- a/modules/bar/popouts/Audio.qml
+++ b/modules/bar/popouts/Audio.qml
@@ -9,7 +9,6 @@ import Quickshell.Services.Pipewire
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
-import "../../controlcenter/network"
Item {
id: root
@@ -104,17 +103,5 @@ Item {
}
}
}
-
- IconTextButton {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- inactiveColour: Colours.palette.m3primaryContainer
- inactiveOnColour: Colours.palette.m3onPrimaryContainer
- verticalPadding: Appearance.padding.small
- text: qsTr("Open settings")
- icon: "settings"
-
- onClicked: root.wrapper.detach("audio")
- }
}
}
diff --git a/modules/bar/popouts/Background.qml b/modules/bar/popouts/Background.qml
index 075b698..983650c 100644
--- a/modules/bar/popouts/Background.qml
+++ b/modules/bar/popouts/Background.qml
@@ -9,7 +9,7 @@ ShapePath {
required property Wrapper wrapper
required property bool invertBottomRounding
- readonly property real rounding: wrapper.isDetached ? Appearance.rounding.normal : Config.border.rounding
+ readonly property real rounding: Config.border.rounding
readonly property bool flatten: wrapper.width < rounding * 2
readonly property real roundingX: flatten ? wrapper.width / 2 : rounding
property real ibr: invertBottomRounding ? -1 : 1
diff --git a/modules/bar/popouts/Bluetooth.qml b/modules/bar/popouts/Bluetooth.qml
index 676da82..151891f 100644
--- a/modules/bar/popouts/Bluetooth.qml
+++ b/modules/bar/popouts/Bluetooth.qml
@@ -9,7 +9,6 @@ import Quickshell
import Quickshell.Bluetooth
import QtQuick
import QtQuick.Layouts
-import "../../controlcenter/network"
ColumnLayout {
id: root
@@ -164,18 +163,6 @@ ColumnLayout {
}
}
- IconTextButton {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- inactiveColour: Colours.palette.m3primaryContainer
- inactiveOnColour: Colours.palette.m3onPrimaryContainer
- verticalPadding: Appearance.padding.small
- text: qsTr("Open settings")
- icon: "settings"
-
- onClicked: root.wrapper.detach("bluetooth")
- }
-
component Toggle: RowLayout {
required property string label
property alias checked: toggle.checked
diff --git a/modules/bar/popouts/Content.qml b/modules/bar/popouts/Content.qml
index 779cc5f..6bcc9f7 100644
--- a/modules/bar/popouts/Content.qml
+++ b/modules/bar/popouts/Content.qml
@@ -114,11 +114,6 @@ Item {
}
}
- Popout {
- name: "lockstatus"
- sourceComponent: LockStatus {}
- }
-
Repeater {
model: ScriptModel {
values: SystemTray.items.values.filter(i => !Config.bar.tray.hiddenIcons.includes(i.id))
diff --git a/modules/bar/popouts/LockStatus.qml b/modules/bar/popouts/LockStatus.qml
deleted file mode 100644
index 7d74530..0000000
--- a/modules/bar/popouts/LockStatus.qml
+++ /dev/null
@@ -1,16 +0,0 @@
-import qs.components
-import qs.services
-import qs.config
-import QtQuick.Layouts
-
-ColumnLayout {
- spacing: Appearance.spacing.small
-
- StyledText {
- text: qsTr("Capslock: %1").arg(Hypr.capsLock ? "Enabled" : "Disabled")
- }
-
- StyledText {
- text: qsTr("Numlock: %1").arg(Hypr.numLock ? "Enabled" : "Disabled")
- }
-}
diff --git a/modules/bar/popouts/Wrapper.qml b/modules/bar/popouts/Wrapper.qml
index 05a1d3c..73a7556 100644
--- a/modules/bar/popouts/Wrapper.qml
+++ b/modules/bar/popouts/Wrapper.qml
@@ -3,8 +3,6 @@ pragma ComponentBehavior: Bound
import qs.components
import qs.services
import qs.config
-import qs.modules.windowinfo
-import qs.modules.controlcenter
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
@@ -23,29 +21,15 @@ Item {
property real currentCenter
property bool hasCurrent
- property string detachedMode
property string queuedMode
- readonly property bool isDetached: detachedMode.length > 0
property int animLength: Appearance.anim.durations.normal
property list<real> animCurve: Appearance.anim.curves.emphasized
- function detach(mode: string): void {
- animLength = Appearance.anim.durations.large;
- if (mode === "winfo") {
- detachedMode = mode;
- } else {
- queuedMode = mode;
- detachedMode = "any";
- }
- focus = true;
- }
-
function close(): void {
hasCurrent = false;
animCurve = Appearance.anim.curves.emphasizedAccel;
animLength = Appearance.anim.durations.normal;
- detachedMode = "";
animCurve = Appearance.anim.curves.emphasized;
}
@@ -75,20 +59,6 @@ Item {
}
}
- HyprlandFocusGrab {
- active: root.isDetached
- windows: [QsWindow.window]
- onCleared: root.close()
- }
-
- Binding {
- when: root.isDetached
-
- target: QsWindow.window
- property: "WlrLayershell.keyboardFocus"
- value: WlrKeyboardFocus.OnDemand
- }
-
Binding {
when: root.hasCurrent && root.currentName === "wirelesspassword"
@@ -100,7 +70,7 @@ Item {
Comp {
id: content
- shouldBeActive: root.hasCurrent && !root.detachedMode
+ shouldBeActive: root.hasCurrent
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
@@ -109,30 +79,6 @@ Item {
}
}
- Comp {
- shouldBeActive: root.detachedMode === "winfo"
- anchors.centerIn: parent
-
- sourceComponent: WindowInfo {
- screen: root.screen
- client: Hypr.activeToplevel
- }
- }
-
- Comp {
- shouldBeActive: root.detachedMode === "any"
- anchors.centerIn: parent
-
- sourceComponent: ControlCenter {
- screen: root.screen
- active: root.queuedMode
-
- function close(): void {
- root.close();
- }
- }
- }
-
Behavior on x {
Anim {
duration: root.animLength
diff --git a/modules/bar/popouts/kblayout/KbLayoutModel.qml b/modules/bar/popouts/kblayout/KbLayoutModel.qml
index 4371095..d1845af 100644
--- a/modules/bar/popouts/kblayout/KbLayoutModel.qml
+++ b/modules/bar/popouts/kblayout/KbLayoutModel.qml
@@ -199,7 +199,7 @@ Item {
arr = arr.filter(i => i.layoutIndex !== activeIndex);
arr.forEach(i => _visibleModel.append(i));
- if (!Config.utilities.toasts.kbLimit)
+ if (!Config.toasts.kbLimit)
return;
if (_layoutsModel.count > 4) {
diff --git a/modules/controlcenter/ControlCenter.qml b/modules/controlcenter/ControlCenter.qml
deleted file mode 100644
index 4aacfad..0000000
--- a/modules/controlcenter/ControlCenter.qml
+++ /dev/null
@@ -1,100 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.controls
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property ShellScreen screen
- readonly property int rounding: floating ? 0 : Appearance.rounding.normal
-
- property alias floating: session.floating
- property alias active: session.active
- property alias navExpanded: session.navExpanded
-
- readonly property Session session: Session {
- id: session
-
- root: root
- }
-
- function close(): void {
- }
-
- implicitWidth: implicitHeight * Config.controlCenter.sizes.ratio
- implicitHeight: screen.height * Config.controlCenter.sizes.heightMult
-
- GridLayout {
- anchors.fill: parent
-
- rowSpacing: 0
- columnSpacing: 0
- rows: root.floating ? 2 : 1
- columns: 2
-
- Loader {
- Layout.fillWidth: true
- Layout.columnSpan: 2
-
- active: root.floating
- visible: active
-
- sourceComponent: WindowTitle {
- screen: root.screen
- session: root.session
- }
- }
-
- StyledRect {
- Layout.fillHeight: true
-
- topLeftRadius: root.rounding
- bottomLeftRadius: root.rounding
- implicitWidth: navRail.implicitWidth
- color: Colours.tPalette.m3surfaceContainer
-
- CustomMouseArea {
- anchors.fill: parent
-
- function onWheel(event: WheelEvent): void {
- // Prevent tab switching during initial opening animation to avoid blank pages
- if (!panes.initialOpeningComplete) {
- return;
- }
-
- if (event.angleDelta.y < 0)
- root.session.activeIndex = Math.min(root.session.activeIndex + 1, root.session.panes.length - 1);
- else if (event.angleDelta.y > 0)
- root.session.activeIndex = Math.max(root.session.activeIndex - 1, 0);
- }
- }
-
- NavRail {
- id: navRail
-
- screen: root.screen
- session: root.session
- initialOpeningComplete: root.initialOpeningComplete
- }
- }
-
- Panes {
- id: panes
-
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- topRightRadius: root.rounding
- bottomRightRadius: root.rounding
- session: root.session
- }
- }
-
- readonly property bool initialOpeningComplete: panes.initialOpeningComplete
-}
diff --git a/modules/controlcenter/NavRail.qml b/modules/controlcenter/NavRail.qml
deleted file mode 100644
index e61a741..0000000
--- a/modules/controlcenter/NavRail.qml
+++ /dev/null
@@ -1,231 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import qs.modules.controlcenter
-import Quickshell
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property ShellScreen screen
- required property Session session
- required property bool initialOpeningComplete
-
- implicitWidth: layout.implicitWidth + Appearance.padding.larger * 4
- implicitHeight: layout.implicitHeight + Appearance.padding.large * 2
-
- ColumnLayout {
- id: layout
-
- anchors.left: parent.left
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: Appearance.padding.larger * 2
- spacing: Appearance.spacing.normal
-
- states: State {
- name: "expanded"
- when: root.session.navExpanded
-
- PropertyChanges {
- layout.spacing: Appearance.spacing.small
- }
- }
-
- transitions: Transition {
- Anim {
- properties: "spacing"
- }
- }
-
- Loader {
- Layout.topMargin: Appearance.spacing.large
- active: !root.session.floating
- visible: active
-
- sourceComponent: StyledRect {
- readonly property int nonAnimWidth: normalWinIcon.implicitWidth + (root.session.navExpanded ? normalWinLabel.anchors.leftMargin + normalWinLabel.implicitWidth : 0) + normalWinIcon.anchors.leftMargin * 2
-
- implicitWidth: nonAnimWidth
- implicitHeight: root.session.navExpanded ? normalWinIcon.implicitHeight + Appearance.padding.normal * 2 : nonAnimWidth
-
- color: Colours.palette.m3primaryContainer
- radius: Appearance.rounding.small
-
- StateLayer {
- id: normalWinState
-
- color: Colours.palette.m3onPrimaryContainer
-
- function onClicked(): void {
- root.session.root.close();
- WindowFactory.create(null, {
- active: root.session.active,
- navExpanded: root.session.navExpanded
- });
- }
- }
-
- MaterialIcon {
- id: normalWinIcon
-
- anchors.left: parent.left
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: Appearance.padding.large
-
- text: "select_window"
- color: Colours.palette.m3onPrimaryContainer
- font.pointSize: Appearance.font.size.large
- fill: 1
- }
-
- StyledText {
- id: normalWinLabel
-
- anchors.left: normalWinIcon.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: Appearance.spacing.normal
-
- text: qsTr("Float window")
- color: Colours.palette.m3onPrimaryContainer
- opacity: root.session.navExpanded ? 1 : 0
-
- Behavior on opacity {
- Anim {
- duration: Appearance.anim.durations.small
- }
- }
- }
-
- Behavior on implicitWidth {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- Behavior on implicitHeight {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
- }
- }
-
- Repeater {
- model: PaneRegistry.count
-
- NavItem {
- required property int index
- Layout.topMargin: index === 0 ? Appearance.spacing.large * 2 : 0
- icon: PaneRegistry.getByIndex(index).icon
- label: PaneRegistry.getByIndex(index).label
- }
- }
- }
-
- component NavItem: Item {
- id: item
-
- required property string icon
- required property string label
- readonly property bool active: root.session.active === label
-
- implicitWidth: background.implicitWidth
- implicitHeight: background.implicitHeight + smallLabel.implicitHeight + smallLabel.anchors.topMargin
-
- states: State {
- name: "expanded"
- when: root.session.navExpanded
-
- PropertyChanges {
- expandedLabel.opacity: 1
- smallLabel.opacity: 0
- background.implicitWidth: icon.implicitWidth + icon.anchors.leftMargin * 2 + expandedLabel.anchors.leftMargin + expandedLabel.implicitWidth
- background.implicitHeight: icon.implicitHeight + Appearance.padding.normal * 2
- item.implicitHeight: background.implicitHeight
- }
- }
-
- transitions: Transition {
- Anim {
- property: "opacity"
- duration: Appearance.anim.durations.small
- }
-
- Anim {
- properties: "implicitWidth,implicitHeight"
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- StyledRect {
- id: background
-
- radius: Appearance.rounding.full
- color: Qt.alpha(Colours.palette.m3secondaryContainer, item.active ? 1 : 0)
-
- implicitWidth: icon.implicitWidth + icon.anchors.leftMargin * 2
- implicitHeight: icon.implicitHeight + Appearance.padding.small
-
- StateLayer {
- color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
-
- function onClicked(): void {
- // Prevent tab switching during initial opening animation to avoid blank pages
- if (!root.initialOpeningComplete) {
- return;
- }
- root.session.active = item.label;
- }
- }
-
- MaterialIcon {
- id: icon
-
- anchors.left: parent.left
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: Appearance.padding.large
-
- text: item.icon
- color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
- font.pointSize: Appearance.font.size.large
- fill: item.active ? 1 : 0
-
- Behavior on fill {
- Anim {}
- }
- }
-
- StyledText {
- id: expandedLabel
-
- anchors.left: icon.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: Appearance.spacing.normal
-
- opacity: 0
- text: item.label
- color: item.active ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
- font.capitalization: Font.Capitalize
- }
-
- StyledText {
- id: smallLabel
-
- anchors.horizontalCenter: icon.horizontalCenter
- anchors.top: icon.bottom
- anchors.topMargin: Appearance.spacing.small / 2
-
- text: item.label
- font.pointSize: Appearance.font.size.small
- font.capitalization: Font.Capitalize
- }
- }
- }
-}
diff --git a/modules/controlcenter/PaneRegistry.qml b/modules/controlcenter/PaneRegistry.qml
deleted file mode 100644
index 20719ca..0000000
--- a/modules/controlcenter/PaneRegistry.qml
+++ /dev/null
@@ -1,68 +0,0 @@
-pragma Singleton
-
-import QtQuick
-
-QtObject {
- id: root
-
- readonly property list<QtObject> panes: [
- QtObject {
- readonly property string id: "network"
- readonly property string label: "network"
- readonly property string icon: "router"
- readonly property string component: "network/NetworkingPane.qml"
- },
- QtObject {
- readonly property string id: "bluetooth"
- readonly property string label: "bluetooth"
- readonly property string icon: "settings_bluetooth"
- readonly property string component: "bluetooth/BtPane.qml"
- },
- QtObject {
- readonly property string id: "audio"
- readonly property string label: "audio"
- readonly property string icon: "volume_up"
- readonly property string component: "audio/AudioPane.qml"
- },
- ]
-
- readonly property int count: panes.length
-
- readonly property var labels: {
- const result = [];
- for (let i = 0; i < panes.length; i++) {
- result.push(panes[i].label);
- }
- return result;
- }
-
- function getByIndex(index: int): QtObject {
- if (index >= 0 && index < panes.length) {
- return panes[index];
- }
- return null;
- }
-
- function getIndexByLabel(label: string): int {
- for (let i = 0; i < panes.length; i++) {
- if (panes[i].label === label) {
- return i;
- }
- }
- return -1;
- }
-
- function getByLabel(label: string): QtObject {
- const index = getIndexByLabel(label);
- return getByIndex(index);
- }
-
- function getById(id: string): QtObject {
- for (let i = 0; i < panes.length; i++) {
- if (panes[i].id === id) {
- return panes[i];
- }
- }
- return null;
- }
-}
diff --git a/modules/controlcenter/Panes.qml b/modules/controlcenter/Panes.qml
deleted file mode 100644
index 4794c03..0000000
--- a/modules/controlcenter/Panes.qml
+++ /dev/null
@@ -1,171 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import "bluetooth"
-import "network"
-import "audio"
-import qs.components
-import qs.services
-import qs.config
-import qs.modules.controlcenter
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-ClippingRectangle {
- id: root
-
- required property Session session
-
- readonly property bool initialOpeningComplete: layout.initialOpeningComplete
-
- color: "transparent"
- clip: true
- focus: false
- activeFocusOnTab: false
-
- MouseArea {
- anchors.fill: parent
- z: -1
- onPressed: function (mouse) {
- root.focus = true;
- mouse.accepted = false;
- }
- }
-
- Connections {
- target: root.session
-
- function onActiveIndexChanged(): void {
- root.focus = true;
- }
- }
-
- ColumnLayout {
- id: layout
-
- spacing: 0
- y: -root.session.activeIndex * root.height
- clip: true
-
- property bool animationComplete: true
- property bool initialOpeningComplete: false
-
- Timer {
- id: animationDelayTimer
- interval: Appearance.anim.durations.normal
- onTriggered: {
- layout.animationComplete = true;
- }
- }
-
- Timer {
- id: initialOpeningTimer
- interval: Appearance.anim.durations.large
- running: true
- onTriggered: {
- layout.initialOpeningComplete = true;
- }
- }
-
- Repeater {
- model: PaneRegistry.count
-
- Pane {
- required property int index
- paneIndex: index
- componentPath: PaneRegistry.getByIndex(index).component
- }
- }
-
- Behavior on y {
- Anim {}
- }
-
- Connections {
- target: root.session
- function onActiveIndexChanged(): void {
- layout.animationComplete = false;
- animationDelayTimer.restart();
- }
- }
- }
-
- component Pane: Item {
- id: pane
-
- required property int paneIndex
- required property string componentPath
-
- implicitWidth: root.width
- implicitHeight: root.height
-
- property bool hasBeenLoaded: false
-
- function updateActive(): void {
- const diff = Math.abs(root.session.activeIndex - pane.paneIndex);
- const isActivePane = diff === 0;
- let shouldBeActive = false;
-
- if (!layout.initialOpeningComplete) {
- shouldBeActive = isActivePane;
- } else {
- if (diff <= 1) {
- shouldBeActive = true;
- } else if (pane.hasBeenLoaded) {
- shouldBeActive = true;
- } else {
- shouldBeActive = layout.animationComplete;
- }
- }
-
- loader.active = shouldBeActive;
- }
-
- Loader {
- id: loader
-
- anchors.fill: parent
- clip: false
- active: false
-
- Component.onCompleted: {
- Qt.callLater(pane.updateActive);
- }
-
- onActiveChanged: {
- if (active && !pane.hasBeenLoaded) {
- pane.hasBeenLoaded = true;
- }
-
- if (active && !item) {
- loader.setSource(pane.componentPath, {
- "session": root.session
- });
- }
- }
-
- onItemChanged: {
- if (item) {
- pane.hasBeenLoaded = true;
- }
- }
- }
-
- Connections {
- target: root.session
- function onActiveIndexChanged(): void {
- pane.updateActive();
- }
- }
-
- Connections {
- target: layout
- function onInitialOpeningCompleteChanged(): void {
- pane.updateActive();
- }
- function onAnimationCompleteChanged(): void {
- pane.updateActive();
- }
- }
- }
-}
diff --git a/modules/controlcenter/Session.qml b/modules/controlcenter/Session.qml
deleted file mode 100644
index b7dd888..0000000
--- a/modules/controlcenter/Session.qml
+++ /dev/null
@@ -1,21 +0,0 @@
-import QtQuick
-import "./state"
-import qs.modules.controlcenter
-
-QtObject {
- readonly property list<string> panes: PaneRegistry.labels
-
- required property var root
- property bool floating: false
- property string active: "network"
- property int activeIndex: 0
- property bool navExpanded: false
-
- readonly property BluetoothState bt: BluetoothState {}
- readonly property NetworkState network: NetworkState {}
- readonly property EthernetState ethernet: EthernetState {}
-
- onActiveChanged: activeIndex = Math.max(0, panes.indexOf(active))
- onActiveIndexChanged: if (panes[activeIndex])
- active = panes[activeIndex]
-}
diff --git a/modules/controlcenter/WindowFactory.qml b/modules/controlcenter/WindowFactory.qml
deleted file mode 100644
index abcf5df..0000000
--- a/modules/controlcenter/WindowFactory.qml
+++ /dev/null
@@ -1,62 +0,0 @@
-pragma Singleton
-
-import qs.components
-import qs.services
-import Quickshell
-import QtQuick
-
-Singleton {
- id: root
-
- function create(parent: Item, props: var): void {
- controlCenter.createObject(parent ?? dummy, props);
- }
-
- QtObject {
- id: dummy
- }
-
- Component {
- id: controlCenter
-
- FloatingWindow {
- id: win
-
- property alias active: cc.active
- property alias navExpanded: cc.navExpanded
-
- color: Colours.tPalette.m3surface
-
- onVisibleChanged: {
- if (!visible)
- destroy();
- }
-
- implicitWidth: cc.implicitWidth
- implicitHeight: cc.implicitHeight
-
- minimumSize.width: implicitWidth
- minimumSize.height: implicitHeight
- maximumSize.width: implicitWidth
- maximumSize.height: implicitHeight
-
- title: qsTr("Caelestia Settings - %1").arg(cc.active.slice(0, 1).toUpperCase() + cc.active.slice(1))
-
- ControlCenter {
- id: cc
-
- anchors.fill: parent
- screen: win.screen
- floating: true
-
- function close(): void {
- win.destroy();
- }
- }
-
- Behavior on color {
- CAnim {}
- }
- }
- }
-}
diff --git a/modules/controlcenter/WindowTitle.qml b/modules/controlcenter/WindowTitle.qml
deleted file mode 100644
index fb71608..0000000
--- a/modules/controlcenter/WindowTitle.qml
+++ /dev/null
@@ -1,51 +0,0 @@
-import qs.components
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-
-StyledRect {
- id: root
-
- required property ShellScreen screen
- required property Session session
-
- implicitHeight: text.implicitHeight + Appearance.padding.normal
- color: Colours.tPalette.m3surfaceContainer
-
- StyledText {
- id: text
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
-
- text: qsTr("Caelestia Settings - %1").arg(root.session.active)
- font.capitalization: Font.Capitalize
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- Item {
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.margins: Appearance.padding.normal
-
- implicitWidth: implicitHeight
- implicitHeight: closeIcon.implicitHeight + Appearance.padding.small
-
- StateLayer {
- radius: Appearance.rounding.full
-
- function onClicked(): void {
- QsWindow.window.destroy();
- }
- }
-
- MaterialIcon {
- id: closeIcon
-
- anchors.centerIn: parent
- text: "close"
- }
- }
-}
diff --git a/modules/controlcenter/audio/AudioPane.qml b/modules/controlcenter/audio/AudioPane.qml
deleted file mode 100644
index 01d90be..0000000
--- a/modules/controlcenter/audio/AudioPane.qml
+++ /dev/null
@@ -1,621 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property Session session
-
- anchors.fill: parent
-
- SplitPaneLayout {
- anchors.fill: parent
-
- leftContent: Component {
-
- StyledFlickable {
- id: leftAudioFlickable
- flickableDirection: Flickable.VerticalFlick
- contentHeight: leftContent.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: leftAudioFlickable
- }
-
- ColumnLayout {
- id: leftContent
-
- anchors.left: parent.left
- anchors.right: parent.right
- spacing: Appearance.spacing.normal
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Audio")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
- }
-
- CollapsibleSection {
- id: outputDevicesSection
-
- Layout.fillWidth: true
- title: qsTr("Output devices")
- expanded: true
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- StyledText {
- text: qsTr("Devices (%1)").arg(Audio.sinks.length)
- font.pointSize: Appearance.font.size.normal
- font.weight: 500
- }
- }
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("All available output devices")
- color: Colours.palette.m3outline
- }
-
- Repeater {
- Layout.fillWidth: true
- model: Audio.sinks
-
- delegate: StyledRect {
- required property var modelData
-
- Layout.fillWidth: true
-
- color: Audio.sink?.id === modelData.id ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent"
- radius: Appearance.rounding.normal
-
- StateLayer {
- function onClicked(): void {
- Audio.setAudioSink(modelData);
- }
- }
-
- RowLayout {
- id: outputRowLayout
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- MaterialIcon {
- text: Audio.sink?.id === modelData.id ? "speaker" : "speaker_group"
- font.pointSize: Appearance.font.size.large
- fill: Audio.sink?.id === modelData.id ? 1 : 0
- }
-
- StyledText {
- Layout.fillWidth: true
- elide: Text.ElideRight
- maximumLineCount: 1
-
- text: modelData.description || qsTr("Unknown")
- font.weight: Audio.sink?.id === modelData.id ? 500 : 400
- }
- }
-
- implicitHeight: outputRowLayout.implicitHeight + Appearance.padding.normal * 2
- }
- }
- }
- }
-
- CollapsibleSection {
- id: inputDevicesSection
-
- Layout.fillWidth: true
- title: qsTr("Input devices")
- expanded: true
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- StyledText {
- text: qsTr("Devices (%1)").arg(Audio.sources.length)
- font.pointSize: Appearance.font.size.normal
- font.weight: 500
- }
- }
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("All available input devices")
- color: Colours.palette.m3outline
- }
-
- Repeater {
- Layout.fillWidth: true
- model: Audio.sources
-
- delegate: StyledRect {
- required property var modelData
-
- Layout.fillWidth: true
-
- color: Audio.source?.id === modelData.id ? Colours.layer(Colours.palette.m3surfaceContainer, 2) : "transparent"
- radius: Appearance.rounding.normal
-
- StateLayer {
- function onClicked(): void {
- Audio.setAudioSource(modelData);
- }
- }
-
- RowLayout {
- id: inputRowLayout
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- MaterialIcon {
- text: "mic"
- font.pointSize: Appearance.font.size.large
- fill: Audio.source?.id === modelData.id ? 1 : 0
- }
-
- StyledText {
- Layout.fillWidth: true
- elide: Text.ElideRight
- maximumLineCount: 1
-
- text: modelData.description || qsTr("Unknown")
- font.weight: Audio.source?.id === modelData.id ? 500 : 400
- }
- }
-
- implicitHeight: inputRowLayout.implicitHeight + Appearance.padding.normal * 2
- }
- }
- }
- }
- }
- }
- }
-
- rightContent: Component {
- StyledFlickable {
- id: rightAudioFlickable
- flickableDirection: Flickable.VerticalFlick
- contentHeight: contentLayout.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: rightAudioFlickable
- }
-
- ColumnLayout {
- id: contentLayout
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- spacing: Appearance.spacing.normal
-
- SettingsHeader {
- icon: "volume_up"
- title: qsTr("Audio Settings")
- }
-
- SectionHeader {
- title: qsTr("Output volume")
- description: qsTr("Control the volume of your output device")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.normal
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: qsTr("Volume")
- font.pointSize: Appearance.font.size.normal
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- StyledInputField {
- id: outputVolumeInput
- Layout.preferredWidth: 70
- validator: IntValidator {
- bottom: 0
- top: 100
- }
- enabled: !Audio.muted
-
- Component.onCompleted: {
- text = Math.round(Audio.volume * 100).toString();
- }
-
- Connections {
- target: Audio
- function onVolumeChanged() {
- if (!outputVolumeInput.hasFocus) {
- outputVolumeInput.text = Math.round(Audio.volume * 100).toString();
- }
- }
- }
-
- onTextEdited: text => {
- if (hasFocus) {
- const val = parseInt(text);
- if (!isNaN(val) && val >= 0 && val <= 100) {
- Audio.setVolume(val / 100);
- }
- }
- }
-
- onEditingFinished: {
- const val = parseInt(text);
- if (isNaN(val) || val < 0 || val > 100) {
- text = Math.round(Audio.volume * 100).toString();
- }
- }
- }
-
- StyledText {
- text: "%"
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.normal
- opacity: Audio.muted ? 0.5 : 1
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: muteIcon.implicitHeight + Appearance.padding.normal * 2
-
- radius: Appearance.rounding.normal
- color: Audio.muted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
-
- StateLayer {
- function onClicked(): void {
- if (Audio.sink?.audio) {
- Audio.sink.audio.muted = !Audio.sink.audio.muted;
- }
- }
- }
-
- MaterialIcon {
- id: muteIcon
-
- anchors.centerIn: parent
- text: Audio.muted ? "volume_off" : "volume_up"
- color: Audio.muted ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
- }
- }
- }
-
- StyledSlider {
- id: outputVolumeSlider
- Layout.fillWidth: true
- implicitHeight: Appearance.padding.normal * 3
-
- value: Audio.volume
- enabled: !Audio.muted
- opacity: enabled ? 1 : 0.5
- onMoved: {
- Audio.setVolume(value);
- if (!outputVolumeInput.hasFocus) {
- outputVolumeInput.text = Math.round(value * 100).toString();
- }
- }
- }
- }
- }
-
- SectionHeader {
- title: qsTr("Input volume")
- description: qsTr("Control the volume of your input device")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.normal
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: qsTr("Volume")
- font.pointSize: Appearance.font.size.normal
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- StyledInputField {
- id: inputVolumeInput
- Layout.preferredWidth: 70
- validator: IntValidator {
- bottom: 0
- top: 100
- }
- enabled: !Audio.sourceMuted
-
- Component.onCompleted: {
- text = Math.round(Audio.sourceVolume * 100).toString();
- }
-
- Connections {
- target: Audio
- function onSourceVolumeChanged() {
- if (!inputVolumeInput.hasFocus) {
- inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString();
- }
- }
- }
-
- onTextEdited: text => {
- if (hasFocus) {
- const val = parseInt(text);
- if (!isNaN(val) && val >= 0 && val <= 100) {
- Audio.setSourceVolume(val / 100);
- }
- }
- }
-
- onEditingFinished: {
- const val = parseInt(text);
- if (isNaN(val) || val < 0 || val > 100) {
- text = Math.round(Audio.sourceVolume * 100).toString();
- }
- }
- }
-
- StyledText {
- text: "%"
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.normal
- opacity: Audio.sourceMuted ? 0.5 : 1
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: muteInputIcon.implicitHeight + Appearance.padding.normal * 2
-
- radius: Appearance.rounding.normal
- color: Audio.sourceMuted ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
-
- StateLayer {
- function onClicked(): void {
- if (Audio.source?.audio) {
- Audio.source.audio.muted = !Audio.source.audio.muted;
- }
- }
- }
-
- MaterialIcon {
- id: muteInputIcon
-
- anchors.centerIn: parent
- text: "mic_off"
- color: Audio.sourceMuted ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
- }
- }
- }
-
- StyledSlider {
- id: inputVolumeSlider
- Layout.fillWidth: true
- implicitHeight: Appearance.padding.normal * 3
-
- value: Audio.sourceVolume
- enabled: !Audio.sourceMuted
- opacity: enabled ? 1 : 0.5
- onMoved: {
- Audio.setSourceVolume(value);
- if (!inputVolumeInput.hasFocus) {
- inputVolumeInput.text = Math.round(value * 100).toString();
- }
- }
- }
- }
- }
-
- SectionHeader {
- title: qsTr("Applications")
- description: qsTr("Control volume for individual applications")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.normal
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- Repeater {
- model: Audio.streams
- Layout.fillWidth: true
-
- delegate: ColumnLayout {
- required property var modelData
- required property int index
-
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- MaterialIcon {
- text: "apps"
- font.pointSize: Appearance.font.size.normal
- fill: 0
- }
-
- StyledText {
- Layout.fillWidth: true
- elide: Text.ElideRight
- maximumLineCount: 1
- text: Audio.getStreamName(modelData)
- font.pointSize: Appearance.font.size.normal
- font.weight: 500
- }
-
- StyledInputField {
- id: streamVolumeInput
- Layout.preferredWidth: 70
- validator: IntValidator {
- bottom: 0
- top: 100
- }
- enabled: !Audio.getStreamMuted(modelData)
-
- Component.onCompleted: {
- text = Math.round(Audio.getStreamVolume(modelData) * 100).toString();
- }
-
- Connections {
- target: modelData
- function onAudioChanged() {
- if (!streamVolumeInput.hasFocus && modelData?.audio) {
- streamVolumeInput.text = Math.round(modelData.audio.volume * 100).toString();
- }
- }
- }
-
- onTextEdited: text => {
- if (hasFocus) {
- const val = parseInt(text);
- if (!isNaN(val) && val >= 0 && val <= 100) {
- Audio.setStreamVolume(modelData, val / 100);
- }
- }
- }
-
- onEditingFinished: {
- const val = parseInt(text);
- if (isNaN(val) || val < 0 || val > 100) {
- text = Math.round(Audio.getStreamVolume(modelData) * 100).toString();
- }
- }
- }
-
- StyledText {
- text: "%"
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.normal
- opacity: Audio.getStreamMuted(modelData) ? 0.5 : 1
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: streamMuteIcon.implicitHeight + Appearance.padding.normal * 2
-
- radius: Appearance.rounding.normal
- color: Audio.getStreamMuted(modelData) ? Colours.palette.m3secondary : Colours.palette.m3secondaryContainer
-
- StateLayer {
- function onClicked(): void {
- Audio.setStreamMuted(modelData, !Audio.getStreamMuted(modelData));
- }
- }
-
- MaterialIcon {
- id: streamMuteIcon
-
- anchors.centerIn: parent
- text: Audio.getStreamMuted(modelData) ? "volume_off" : "volume_up"
- color: Audio.getStreamMuted(modelData) ? Colours.palette.m3onSecondary : Colours.palette.m3onSecondaryContainer
- }
- }
- }
-
- StyledSlider {
- Layout.fillWidth: true
- implicitHeight: Appearance.padding.normal * 3
-
- value: Audio.getStreamVolume(modelData)
- enabled: !Audio.getStreamMuted(modelData)
- opacity: enabled ? 1 : 0.5
- onMoved: {
- Audio.setStreamVolume(modelData, value);
- if (!streamVolumeInput.hasFocus) {
- streamVolumeInput.text = Math.round(value * 100).toString();
- }
- }
-
- Connections {
- target: modelData
- function onAudioChanged() {
- if (modelData?.audio) {
- value = modelData.audio.volume;
- }
- }
- }
- }
- }
- }
-
- StyledText {
- Layout.fillWidth: true
- visible: Audio.streams.length === 0
- text: qsTr("No applications currently playing audio")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- horizontalAlignment: Text.AlignHCenter
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/modules/controlcenter/bluetooth/BtPane.qml b/modules/controlcenter/bluetooth/BtPane.qml
deleted file mode 100644
index 7d3b9ca..0000000
--- a/modules/controlcenter/bluetooth/BtPane.qml
+++ /dev/null
@@ -1,73 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import "."
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.config
-import Quickshell.Widgets
-import Quickshell.Bluetooth
-import QtQuick
-
-SplitPaneWithDetails {
- id: root
-
- required property Session session
-
- anchors.fill: parent
-
- activeItem: session.bt.active
- paneIdGenerator: function (item) {
- return item ? (item.address || "") : "";
- }
-
- leftContent: Component {
- StyledFlickable {
- id: leftFlickable
-
- flickableDirection: Flickable.VerticalFlick
- contentHeight: deviceList.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: leftFlickable
- }
-
- DeviceList {
- id: deviceList
-
- anchors.left: parent.left
- anchors.right: parent.right
- session: root.session
- }
- }
- }
-
- rightDetailsComponent: Component {
- Details {
- session: root.session
- }
- }
-
- rightSettingsComponent: Component {
- StyledFlickable {
- id: settingsFlickable
- flickableDirection: Flickable.VerticalFlick
- contentHeight: settingsInner.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: settingsFlickable
- }
-
- Settings {
- id: settingsInner
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- session: root.session
- }
- }
- }
-}
diff --git a/modules/controlcenter/bluetooth/Details.qml b/modules/controlcenter/bluetooth/Details.qml
deleted file mode 100644
index bc276e0..0000000
--- a/modules/controlcenter/bluetooth/Details.qml
+++ /dev/null
@@ -1,671 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell.Bluetooth
-import QtQuick
-import QtQuick.Layouts
-
-StyledFlickable {
- id: root
-
- required property Session session
- readonly property BluetoothDevice device: session.bt.active
-
- flickableDirection: Flickable.VerticalFlick
- contentHeight: detailsWrapper.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: root
- }
-
- Item {
- id: detailsWrapper
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- implicitHeight: details.implicitHeight
-
- DeviceDetails {
- id: details
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
-
- session: root.session
- device: root.device
-
- headerComponent: Component {
- SettingsHeader {
- icon: Icons.getBluetoothIcon(root.device?.icon ?? "")
- title: root.device?.name ?? ""
- }
- }
-
- sections: [
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.topMargin: Appearance.spacing.large
- text: qsTr("Connection status")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- StyledText {
- text: qsTr("Connection settings for this device")
- color: Colours.palette.m3outline
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: deviceStatus.implicitHeight + Appearance.padding.large * 2
-
- radius: Appearance.rounding.normal
- color: Colours.tPalette.m3surfaceContainer
-
- ColumnLayout {
- id: deviceStatus
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.larger
-
- Toggle {
- label: qsTr("Connected")
- checked: root.device?.connected ?? false
- toggle.onToggled: root.device.connected = checked
- }
-
- Toggle {
- label: qsTr("Paired")
- checked: root.device?.paired ?? false
- toggle.onToggled: {
- if (root.device.paired)
- root.device.forget();
- else
- root.device.pair();
- }
- }
-
- Toggle {
- label: qsTr("Blocked")
- checked: root.device?.blocked ?? false
- toggle.onToggled: root.device.blocked = checked
- }
- }
- }
- }
- },
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.topMargin: Appearance.spacing.large
- text: qsTr("Device properties")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- StyledText {
- text: qsTr("Additional settings")
- color: Colours.palette.m3outline
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: deviceProps.implicitHeight + Appearance.padding.large * 2
-
- radius: Appearance.rounding.normal
- color: Colours.tPalette.m3surfaceContainer
-
- ColumnLayout {
- id: deviceProps
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.larger
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- Item {
- id: renameDevice
-
- Layout.fillWidth: true
- Layout.rightMargin: Appearance.spacing.small
-
- implicitHeight: renameLabel.implicitHeight + deviceNameEdit.implicitHeight
-
- states: State {
- name: "editingDeviceName"
- when: root.session.bt.editingDeviceName
-
- AnchorChanges {
- target: deviceNameEdit
- anchors.top: renameDevice.top
- }
- PropertyChanges {
- renameDevice.implicitHeight: deviceNameEdit.implicitHeight
- renameLabel.opacity: 0
- deviceNameEdit.padding: Appearance.padding.normal
- }
- }
-
- transitions: Transition {
- AnchorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- Anim {
- properties: "implicitHeight,opacity,padding"
- }
- }
-
- StyledText {
- id: renameLabel
-
- anchors.left: parent.left
-
- text: qsTr("Device name")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledTextField {
- id: deviceNameEdit
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: renameLabel.bottom
- anchors.leftMargin: root.session.bt.editingDeviceName ? 0 : -Appearance.padding.normal
-
- text: root.device?.name ?? ""
- readOnly: !root.session.bt.editingDeviceName
- onAccepted: {
- root.session.bt.editingDeviceName = false;
- root.device.name = text;
- }
-
- leftPadding: Appearance.padding.normal
- rightPadding: Appearance.padding.normal
-
- background: StyledRect {
- radius: Appearance.rounding.small
- border.width: 2
- border.color: Colours.palette.m3primary
- opacity: root.session.bt.editingDeviceName ? 1 : 0
-
- Behavior on border.color {
- CAnim {}
- }
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- Behavior on anchors.leftMargin {
- Anim {}
- }
- }
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: cancelEditIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.small
- color: Colours.palette.m3secondaryContainer
- opacity: root.session.bt.editingDeviceName ? 1 : 0
- scale: root.session.bt.editingDeviceName ? 1 : 0.5
-
- StateLayer {
- color: Colours.palette.m3onSecondaryContainer
- disabled: !root.session.bt.editingDeviceName
-
- function onClicked(): void {
- root.session.bt.editingDeviceName = false;
- deviceNameEdit.text = Qt.binding(() => root.device?.name ?? "");
- }
- }
-
- MaterialIcon {
- id: cancelEditIcon
-
- anchors.centerIn: parent
- animate: true
- text: "cancel"
- color: Colours.palette.m3onSecondaryContainer
- }
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: editIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: root.session.bt.editingDeviceName ? Appearance.rounding.small : implicitHeight / 2 * Math.min(1, Appearance.rounding.scale)
- color: Qt.alpha(Colours.palette.m3primary, root.session.bt.editingDeviceName ? 1 : 0)
-
- StateLayer {
- color: root.session.bt.editingDeviceName ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
-
- function onClicked(): void {
- root.session.bt.editingDeviceName = !root.session.bt.editingDeviceName;
- if (root.session.bt.editingDeviceName)
- deviceNameEdit.forceActiveFocus();
- else
- deviceNameEdit.accepted();
- }
- }
-
- MaterialIcon {
- id: editIcon
-
- anchors.centerIn: parent
- animate: true
- text: root.session.bt.editingDeviceName ? "check_circle" : "edit"
- color: root.session.bt.editingDeviceName ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
- }
-
- Behavior on radius {
- Anim {}
- }
- }
- }
-
- Toggle {
- label: qsTr("Trusted")
- checked: root.device?.trusted ?? false
- toggle.onToggled: root.device.trusted = checked
- }
-
- Toggle {
- label: qsTr("Wake allowed")
- checked: root.device?.wakeAllowed ?? false
- toggle.onToggled: root.device.wakeAllowed = checked
- }
- }
- }
- }
- },
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.topMargin: Appearance.spacing.large
- text: qsTr("Device information")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- StyledText {
- text: qsTr("Information about this device")
- color: Colours.palette.m3outline
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: deviceInfo.implicitHeight + Appearance.padding.large * 2
-
- radius: Appearance.rounding.normal
- color: Colours.tPalette.m3surfaceContainer
-
- ColumnLayout {
- id: deviceInfo
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.small / 2
-
- StyledText {
- text: root.device?.batteryAvailable ? qsTr("Device battery (%1%)").arg(root.device.battery * 100) : qsTr("Battery unavailable")
- }
-
- RowLayout {
- id: batteryPercent
- Layout.topMargin: Appearance.spacing.small / 2
- Layout.fillWidth: true
- Layout.preferredHeight: Appearance.padding.smaller
- spacing: Appearance.spacing.small / 2
-
- StyledRect {
- Layout.fillWidth: true
- Layout.fillHeight: true
- radius: Appearance.rounding.full
- color: Colours.palette.m3secondaryContainer
-
- StyledRect {
- anchors.left: parent.left
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.margins: parent.height * 0.25
-
- implicitWidth: root.device?.batteryAvailable ? batteryPercent.width * root.device.battery : 0
- radius: Appearance.rounding.full
- color: Colours.palette.m3primary
- }
- }
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("Dbus path")
- }
-
- StyledText {
- text: root.device?.dbusPath ?? ""
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("MAC address")
- }
-
- StyledText {
- text: root.device?.address ?? ""
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("Bonded")
- }
-
- StyledText {
- text: root.device?.bonded ? qsTr("Yes") : qsTr("No")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("System name")
- }
-
- StyledText {
- text: root.device?.deviceName ?? ""
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
- }
- }
- }
- }
- ]
- }
- }
-
- ColumnLayout {
- anchors.right: fabRoot.right
- anchors.bottom: fabRoot.top
- anchors.bottomMargin: Appearance.padding.normal
-
- Repeater {
- id: fabMenu
-
- model: ListModel {
- ListElement {
- name: "trust"
- icon: "handshake"
- }
- ListElement {
- name: "block"
- icon: "block"
- }
- ListElement {
- name: "pair"
- icon: "missing_controller"
- }
- ListElement {
- name: "connect"
- icon: "bluetooth_connected"
- }
- }
-
- StyledClippingRect {
- id: fabMenuItem
-
- required property var modelData
- required property int index
-
- Layout.alignment: Qt.AlignRight
-
- implicitHeight: fabMenuItemInner.implicitHeight + Appearance.padding.larger * 2
-
- radius: Appearance.rounding.full
- color: Colours.palette.m3primaryContainer
-
- opacity: 0
-
- states: State {
- name: "visible"
- when: root.session.bt.fabMenuOpen
-
- PropertyChanges {
- fabMenuItem.implicitWidth: fabMenuItemInner.implicitWidth + Appearance.padding.large * 2
- fabMenuItem.opacity: 1
- fabMenuItemInner.opacity: 1
- }
- }
-
- transitions: [
- Transition {
- to: "visible"
-
- SequentialAnimation {
- PauseAnimation {
- duration: (fabMenu.count - 1 - fabMenuItem.index) * Appearance.anim.durations.small / 8
- }
- ParallelAnimation {
- Anim {
- property: "implicitWidth"
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- Anim {
- property: "opacity"
- duration: Appearance.anim.durations.small
- }
- }
- }
- },
- Transition {
- from: "visible"
-
- SequentialAnimation {
- PauseAnimation {
- duration: fabMenuItem.index * Appearance.anim.durations.small / 8
- }
- ParallelAnimation {
- Anim {
- property: "implicitWidth"
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- Anim {
- property: "opacity"
- duration: Appearance.anim.durations.small
- }
- }
- }
- }
- ]
-
- StateLayer {
- function onClicked(): void {
- root.session.bt.fabMenuOpen = false;
-
- const name = fabMenuItem.modelData.name;
- if (fabMenuItem.modelData.name !== "pair")
- root.device[`${name}ed`] = !root.device[`${name}ed`];
- else if (root.device.paired)
- root.device.forget();
- else
- root.device.pair();
- }
- }
-
- RowLayout {
- id: fabMenuItemInner
-
- anchors.centerIn: parent
- spacing: Appearance.spacing.normal
- opacity: 0
-
- MaterialIcon {
- text: fabMenuItem.modelData.icon
- color: Colours.palette.m3onPrimaryContainer
- fill: 1
- }
-
- StyledText {
- animate: true
- text: (root.device && root.device[`${fabMenuItem.modelData.name}ed`] ? fabMenuItem.modelData.name === "connect" ? "dis" : "un" : "") + fabMenuItem.modelData.name
- color: Colours.palette.m3onPrimaryContainer
- font.capitalization: Font.Capitalize
- Layout.preferredWidth: implicitWidth
-
- Behavior on Layout.preferredWidth {
- Anim {
- duration: Appearance.anim.durations.small
- }
- }
- }
- }
- }
- }
- }
-
- Item {
- id: fabRoot
-
- x: root.contentX + root.width - width
- y: root.contentY + root.height - height
- width: 64
- height: 64
- z: 10000
-
- StyledRect {
- id: fabBg
-
- anchors.right: parent.right
- anchors.top: parent.top
-
- implicitWidth: 64
- implicitHeight: 64
-
- radius: Appearance.rounding.normal
- color: root.session.bt.fabMenuOpen ? Colours.palette.m3primary : Colours.palette.m3primaryContainer
-
- states: State {
- name: "expanded"
- when: root.session.bt.fabMenuOpen
-
- PropertyChanges {
- fabBg.implicitWidth: 48
- fabBg.implicitHeight: 48
- fabBg.radius: 48 / 2
- fab.font.pointSize: Appearance.font.size.larger
- }
- }
-
- transitions: Transition {
- Anim {
- properties: "implicitWidth,implicitHeight"
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- Anim {
- properties: "radius,font.pointSize"
- }
- }
-
- Elevation {
- anchors.fill: parent
- radius: parent.radius
- z: -1
- level: fabState.containsMouse && !fabState.pressed ? 4 : 3
- }
-
- StateLayer {
- id: fabState
-
- color: root.session.bt.fabMenuOpen ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer
-
- function onClicked(): void {
- root.session.bt.fabMenuOpen = !root.session.bt.fabMenuOpen;
- }
- }
-
- MaterialIcon {
- id: fab
-
- anchors.centerIn: parent
- animate: true
- text: root.session.bt.fabMenuOpen ? "close" : "settings"
- color: root.session.bt.fabMenuOpen ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer
- font.pointSize: Appearance.font.size.large
- fill: 1
- }
- }
- }
-
- component Toggle: RowLayout {
- required property string label
- property alias checked: toggle.checked
- property alias toggle: toggle
-
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: parent.label
- }
-
- StyledSwitch {
- id: toggle
-
- cLayer: 2
- }
- }
-}
diff --git a/modules/controlcenter/bluetooth/DeviceList.qml b/modules/controlcenter/bluetooth/DeviceList.qml
deleted file mode 100644
index 2a2bde9..0000000
--- a/modules/controlcenter/bluetooth/DeviceList.qml
+++ /dev/null
@@ -1,264 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import Quickshell.Bluetooth
-import QtQuick
-import QtQuick.Layouts
-
-DeviceList {
- id: root
-
- required property Session session
- readonly property bool smallDiscoverable: width <= 540
- readonly property bool smallPairable: width <= 480
-
- title: qsTr("Devices (%1)").arg(Bluetooth.devices.values.length)
- description: qsTr("All available bluetooth devices")
- activeItem: session.bt.active
-
- model: ScriptModel {
- id: deviceModel
-
- values: [...Bluetooth.devices.values].sort((a, b) => (b.connected - a.connected) || (b.paired - a.paired) || a.name.localeCompare(b.name))
- }
-
- headerComponent: Component {
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Bluetooth")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- ToggleButton {
- toggled: Bluetooth.defaultAdapter?.enabled ?? false
- icon: "power"
- accent: "Tertiary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
- tooltip: qsTr("Toggle Bluetooth")
-
- onClicked: {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.enabled = !adapter.enabled;
- }
- }
-
- ToggleButton {
- toggled: Bluetooth.defaultAdapter?.discoverable ?? false
- icon: root.smallDiscoverable ? "group_search" : ""
- label: root.smallDiscoverable ? "" : qsTr("Discoverable")
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
- tooltip: qsTr("Make discoverable")
-
- onClicked: {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.discoverable = !adapter.discoverable;
- }
- }
-
- ToggleButton {
- toggled: Bluetooth.defaultAdapter?.pairable ?? false
- icon: "missing_controller"
- label: root.smallPairable ? "" : qsTr("Pairable")
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
- tooltip: qsTr("Make pairable")
-
- onClicked: {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.pairable = !adapter.pairable;
- }
- }
-
- ToggleButton {
- toggled: Bluetooth.defaultAdapter?.discovering ?? false
- icon: "bluetooth_searching"
- accent: "Secondary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
- tooltip: qsTr("Scan for devices")
-
- onClicked: {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.discovering = !adapter.discovering;
- }
- }
-
- ToggleButton {
- toggled: !root.session.bt.active
- icon: "settings"
- accent: "Primary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
- tooltip: qsTr("Bluetooth settings")
-
- onClicked: {
- if (root.session.bt.active)
- root.session.bt.active = null;
- else {
- root.session.bt.active = root.model.values[0] ?? null;
- }
- }
- }
- }
- }
-
- delegate: Component {
- StyledRect {
- id: device
-
- required property BluetoothDevice modelData
- readonly property bool loading: modelData && (modelData.state === BluetoothDeviceState.Connecting || modelData.state === BluetoothDeviceState.Disconnecting)
- readonly property bool connected: modelData && modelData.state === BluetoothDeviceState.Connected
-
- width: ListView.view ? ListView.view.width : undefined
- implicitHeight: deviceInner.implicitHeight + Appearance.padding.normal * 2
-
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.activeItem === modelData ? Colours.tPalette.m3surfaceContainer.a : 0)
- radius: Appearance.rounding.normal
-
- StateLayer {
- id: stateLayer
-
- function onClicked(): void {
- if (device.modelData)
- root.session.bt.active = device.modelData;
- }
- }
-
- RowLayout {
- id: deviceInner
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: icon.implicitHeight + Appearance.padding.normal * 2
-
- radius: Appearance.rounding.normal
- color: device.connected ? Colours.palette.m3primaryContainer : (device.modelData && device.modelData.bonded) ? Colours.palette.m3secondaryContainer : Colours.tPalette.m3surfaceContainerHigh
-
- StyledRect {
- anchors.fill: parent
- radius: parent.radius
- color: Qt.alpha(device.connected ? Colours.palette.m3onPrimaryContainer : (device.modelData && device.modelData.bonded) ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface, stateLayer.pressed ? 0.1 : stateLayer.containsMouse ? 0.08 : 0)
- }
-
- MaterialIcon {
- id: icon
-
- anchors.centerIn: parent
- text: Icons.getBluetoothIcon(device.modelData ? device.modelData.icon : "")
- color: device.connected ? Colours.palette.m3onPrimaryContainer : (device.modelData && device.modelData.bonded) ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
- font.pointSize: Appearance.font.size.large
- fill: device.connected ? 1 : 0
-
- Behavior on fill {
- Anim {}
- }
- }
- }
-
- ColumnLayout {
- Layout.fillWidth: true
-
- spacing: 0
-
- StyledText {
- Layout.fillWidth: true
- text: device.modelData ? device.modelData.name : qsTr("Unknown")
- elide: Text.ElideRight
- }
-
- StyledText {
- Layout.fillWidth: true
- text: (device.modelData ? device.modelData.address : "") + (device.connected ? qsTr(" (Connected)") : (device.modelData && device.modelData.bonded) ? qsTr(" (Paired)") : "")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- elide: Text.ElideRight
- }
- }
-
- StyledRect {
- id: connectBtn
-
- implicitWidth: implicitHeight
- implicitHeight: connectIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.full
- color: Qt.alpha(Colours.palette.m3primaryContainer, device.connected ? 1 : 0)
-
- CircularIndicator {
- anchors.fill: parent
- running: device.loading
- }
-
- StateLayer {
- color: device.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
- disabled: device.loading
-
- function onClicked(): void {
- if (device.loading)
- return;
-
- if (device.connected) {
- device.modelData.connected = false;
- } else {
- if (device.modelData.bonded) {
- device.modelData.connected = true;
- } else {
- device.modelData.pair();
- }
- }
- }
- }
-
- MaterialIcon {
- id: connectIcon
-
- anchors.centerIn: parent
- animate: true
- text: device.connected ? "link_off" : "link"
- color: device.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
-
- opacity: device.loading ? 0 : 1
-
- Behavior on opacity {
- Anim {}
- }
- }
- }
- }
- }
- }
-
- onItemSelected: item => session.bt.active = item
-}
diff --git a/modules/controlcenter/bluetooth/Settings.qml b/modules/controlcenter/bluetooth/Settings.qml
deleted file mode 100644
index c547240..0000000
--- a/modules/controlcenter/bluetooth/Settings.qml
+++ /dev/null
@@ -1,532 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.services
-import qs.config
-import Quickshell.Bluetooth
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property Session session
-
- spacing: Appearance.spacing.normal
-
- SettingsHeader {
- icon: "bluetooth"
- title: qsTr("Bluetooth Settings")
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.large
- text: qsTr("Adapter status")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- StyledText {
- text: qsTr("General adapter settings")
- color: Colours.palette.m3outline
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: adapterStatus.implicitHeight + Appearance.padding.large * 2
-
- radius: Appearance.rounding.normal
- color: Colours.tPalette.m3surfaceContainer
-
- ColumnLayout {
- id: adapterStatus
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.larger
-
- Toggle {
- label: qsTr("Powered")
- checked: Bluetooth.defaultAdapter?.enabled ?? false
- toggle.onToggled: {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.enabled = checked;
- }
- }
-
- Toggle {
- label: qsTr("Discoverable")
- checked: Bluetooth.defaultAdapter?.discoverable ?? false
- toggle.onToggled: {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.discoverable = checked;
- }
- }
-
- Toggle {
- label: qsTr("Pairable")
- checked: Bluetooth.defaultAdapter?.pairable ?? false
- toggle.onToggled: {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.pairable = checked;
- }
- }
- }
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.large
- text: qsTr("Adapter properties")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- StyledText {
- text: qsTr("Per-adapter settings")
- color: Colours.palette.m3outline
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: adapterSettings.implicitHeight + Appearance.padding.large * 2
-
- radius: Appearance.rounding.normal
- color: Colours.tPalette.m3surfaceContainer
-
- ColumnLayout {
- id: adapterSettings
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.larger
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Current adapter")
- }
-
- Item {
- id: adapterPickerButton
-
- property bool expanded
-
- implicitWidth: adapterPicker.implicitWidth + Appearance.padding.normal * 2
- implicitHeight: adapterPicker.implicitHeight + Appearance.padding.smaller * 2
-
- StateLayer {
- radius: Appearance.rounding.small
-
- function onClicked(): void {
- adapterPickerButton.expanded = !adapterPickerButton.expanded;
- }
- }
-
- RowLayout {
- id: adapterPicker
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.normal
- anchors.topMargin: Appearance.padding.smaller
- anchors.bottomMargin: Appearance.padding.smaller
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.leftMargin: Appearance.padding.small
- text: Bluetooth.defaultAdapter?.name ?? qsTr("None")
- }
-
- MaterialIcon {
- text: "expand_more"
- }
- }
-
- Elevation {
- anchors.fill: adapterListBg
- radius: adapterListBg.radius
- opacity: adapterPickerButton.expanded ? 1 : 0
- scale: adapterPickerButton.expanded ? 1 : 0.7
- level: 2
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
- }
-
- StyledClippingRect {
- id: adapterListBg
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- implicitHeight: adapterPickerButton.expanded ? adapterList.implicitHeight : adapterPickerButton.implicitHeight
-
- color: Colours.palette.m3secondaryContainer
- radius: Appearance.rounding.small
- opacity: adapterPickerButton.expanded ? 1 : 0
- scale: adapterPickerButton.expanded ? 1 : 0.7
-
- ColumnLayout {
- id: adapterList
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
-
- spacing: 0
-
- Repeater {
- model: Bluetooth.adapters
-
- Item {
- id: adapter
-
- required property BluetoothAdapter modelData
-
- Layout.fillWidth: true
- implicitHeight: adapterInner.implicitHeight + Appearance.padding.normal * 2
-
- StateLayer {
- disabled: !adapterPickerButton.expanded
-
- function onClicked(): void {
- adapterPickerButton.expanded = false;
- root.session.bt.currentAdapter = adapter.modelData;
- }
- }
-
- RowLayout {
- id: adapterInner
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- Layout.leftMargin: Appearance.padding.small
- text: adapter.modelData.name
- color: Colours.palette.m3onSecondaryContainer
- }
-
- MaterialIcon {
- text: "check"
- color: Colours.palette.m3onSecondaryContainer
- visible: adapter.modelData === root.session.bt.currentAdapter
- }
- }
- }
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
-
- Behavior on implicitHeight {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
- }
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Discoverable timeout")
- }
-
- CustomSpinBox {
- min: 0
- value: root.session.bt.currentAdapter?.discoverableTimeout ?? 0
- onValueModified: value => {
- if (root.session.bt.currentAdapter) {
- root.session.bt.currentAdapter.discoverableTimeout = value;
- }
- }
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- Item {
- id: renameAdapter
-
- Layout.fillWidth: true
- Layout.rightMargin: Appearance.spacing.small
-
- implicitHeight: renameLabel.implicitHeight + adapterNameEdit.implicitHeight
-
- states: State {
- name: "editingAdapterName"
- when: root.session.bt.editingAdapterName
-
- AnchorChanges {
- target: adapterNameEdit
- anchors.top: renameAdapter.top
- }
- PropertyChanges {
- renameAdapter.implicitHeight: adapterNameEdit.implicitHeight
- renameLabel.opacity: 0
- adapterNameEdit.padding: Appearance.padding.normal
- }
- }
-
- transitions: Transition {
- AnchorAnimation {
- duration: Appearance.anim.durations.normal
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standard
- }
- Anim {
- properties: "implicitHeight,opacity,padding"
- }
- }
-
- StyledText {
- id: renameLabel
-
- anchors.left: parent.left
-
- text: qsTr("Rename adapter (currently does not work)")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledTextField {
- id: adapterNameEdit
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: renameLabel.bottom
- anchors.leftMargin: root.session.bt.editingAdapterName ? 0 : -Appearance.padding.normal
-
- text: root.session.bt.currentAdapter?.name ?? ""
- readOnly: !root.session.bt.editingAdapterName
- onAccepted: {
- root.session.bt.editingAdapterName = false;
- }
-
- leftPadding: Appearance.padding.normal
- rightPadding: Appearance.padding.normal
-
- background: StyledRect {
- radius: Appearance.rounding.small
- border.width: 2
- border.color: Colours.palette.m3primary
- opacity: root.session.bt.editingAdapterName ? 1 : 0
-
- Behavior on border.color {
- CAnim {}
- }
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- Behavior on anchors.leftMargin {
- Anim {}
- }
- }
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: cancelEditIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.small
- color: Colours.palette.m3secondaryContainer
- opacity: root.session.bt.editingAdapterName ? 1 : 0
- scale: root.session.bt.editingAdapterName ? 1 : 0.5
-
- StateLayer {
- color: Colours.palette.m3onSecondaryContainer
- disabled: !root.session.bt.editingAdapterName
-
- function onClicked(): void {
- root.session.bt.editingAdapterName = false;
- adapterNameEdit.text = Qt.binding(() => root.session.bt.currentAdapter?.name ?? "");
- }
- }
-
- MaterialIcon {
- id: cancelEditIcon
-
- anchors.centerIn: parent
- animate: true
- text: "cancel"
- color: Colours.palette.m3onSecondaryContainer
- }
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: editIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: root.session.bt.editingAdapterName ? Appearance.rounding.small : implicitHeight / 2 * Math.min(1, Appearance.rounding.scale)
- color: Qt.alpha(Colours.palette.m3primary, root.session.bt.editingAdapterName ? 1 : 0)
-
- StateLayer {
- color: root.session.bt.editingAdapterName ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
-
- function onClicked(): void {
- root.session.bt.editingAdapterName = !root.session.bt.editingAdapterName;
- if (root.session.bt.editingAdapterName)
- adapterNameEdit.forceActiveFocus();
- else
- adapterNameEdit.accepted();
- }
- }
-
- MaterialIcon {
- id: editIcon
-
- anchors.centerIn: parent
- animate: true
- text: root.session.bt.editingAdapterName ? "check_circle" : "edit"
- color: root.session.bt.editingAdapterName ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
- }
-
- Behavior on radius {
- Anim {}
- }
- }
- }
- }
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.large
- text: qsTr("Adapter information")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- StyledText {
- text: qsTr("Information about the default adapter")
- color: Colours.palette.m3outline
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: adapterInfo.implicitHeight + Appearance.padding.large * 2
-
- radius: Appearance.rounding.normal
- color: Colours.tPalette.m3surfaceContainer
-
- ColumnLayout {
- id: adapterInfo
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.small / 2
-
- StyledText {
- text: qsTr("Adapter state")
- }
-
- StyledText {
- text: Bluetooth.defaultAdapter ? BluetoothAdapterState.toString(Bluetooth.defaultAdapter.state) : qsTr("Unknown")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("Dbus path")
- }
-
- StyledText {
- text: Bluetooth.defaultAdapter?.dbusPath ?? ""
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("Adapter id")
- }
-
- StyledText {
- text: Bluetooth.defaultAdapter?.adapterId ?? ""
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
- }
- }
-
- component Toggle: RowLayout {
- required property string label
- property alias checked: toggle.checked
- property alias toggle: toggle
-
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: parent.label
- }
-
- StyledSwitch {
- id: toggle
-
- cLayer: 2
- }
- }
-}
diff --git a/modules/controlcenter/components/DeviceDetails.qml b/modules/controlcenter/components/DeviceDetails.qml
deleted file mode 100644
index a5d0647..0000000
--- a/modules/controlcenter/components/DeviceDetails.qml
+++ /dev/null
@@ -1,70 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- property Session session
- property var device: null
-
- property Component headerComponent: null
- property list<Component> sections: []
-
- property Component topContent: null
- property Component bottomContent: null
-
- implicitWidth: layout.implicitWidth
- implicitHeight: layout.implicitHeight
-
- ColumnLayout {
- id: layout
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- spacing: Appearance.spacing.normal
-
- Loader {
- id: headerLoader
-
- Layout.fillWidth: true
- sourceComponent: root.headerComponent
- visible: root.headerComponent !== null
- }
-
- Loader {
- id: topContentLoader
-
- Layout.fillWidth: true
- sourceComponent: root.topContent
- visible: root.topContent !== null
- }
-
- Repeater {
- model: root.sections
-
- Loader {
- required property Component modelData
-
- Layout.fillWidth: true
- sourceComponent: modelData
- }
- }
-
- Loader {
- id: bottomContentLoader
-
- Layout.fillWidth: true
- sourceComponent: root.bottomContent
- visible: root.bottomContent !== null
- }
- }
-}
diff --git a/modules/controlcenter/components/DeviceList.qml b/modules/controlcenter/components/DeviceList.qml
deleted file mode 100644
index 722f9a1..0000000
--- a/modules/controlcenter/components/DeviceList.qml
+++ /dev/null
@@ -1,84 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- property Session session: null
- property var model: null
- property Component delegate: null
-
- property string title: ""
- property string description: ""
- property var activeItem: null
- property Component headerComponent: null
- property Component titleSuffix: null
- property bool showHeader: true
-
- signal itemSelected(var item)
-
- spacing: Appearance.spacing.small
-
- Loader {
- id: headerLoader
-
- Layout.fillWidth: true
- sourceComponent: root.headerComponent
- visible: root.headerComponent !== null && root.showHeader
- }
-
- RowLayout {
- Layout.fillWidth: true
- Layout.topMargin: root.headerComponent ? 0 : 0
- spacing: Appearance.spacing.small
- visible: root.title !== "" || root.description !== ""
-
- StyledText {
- visible: root.title !== ""
- text: root.title
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Loader {
- sourceComponent: root.titleSuffix
- visible: root.titleSuffix !== null
- }
-
- Item {
- Layout.fillWidth: true
- }
- }
-
- property alias view: view
-
- StyledText {
- visible: root.description !== ""
- Layout.fillWidth: true
- text: root.description
- color: Colours.palette.m3outline
- }
-
- StyledListView {
- id: view
-
- Layout.fillWidth: true
- implicitHeight: contentHeight
-
- model: root.model
- delegate: root.delegate
-
- spacing: Appearance.spacing.small / 2
- interactive: false
- clip: false
- }
-}
diff --git a/modules/controlcenter/components/PaneTransition.qml b/modules/controlcenter/components/PaneTransition.qml
deleted file mode 100644
index 5d80dbe..0000000
--- a/modules/controlcenter/components/PaneTransition.qml
+++ /dev/null
@@ -1,71 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.config
-import QtQuick
-
-SequentialAnimation {
- id: root
-
- required property Item target
- property list<PropertyAction> propertyActions
-
- property real scaleFrom: 1.0
- property real scaleTo: 0.8
- property real opacityFrom: 1.0
- property real opacityTo: 0.0
-
- ParallelAnimation {
- NumberAnimation {
- target: root.target
- property: "opacity"
- from: root.opacityFrom
- to: root.opacityTo
- duration: Appearance.anim.durations.normal / 2
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standardAccel
- }
-
- NumberAnimation {
- target: root.target
- property: "scale"
- from: root.scaleFrom
- to: root.scaleTo
- duration: Appearance.anim.durations.normal / 2
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standardAccel
- }
- }
-
- ScriptAction {
- script: {
- for (let i = 0; i < root.propertyActions.length; i++) {
- const action = root.propertyActions[i];
- if (action.target && action.property !== undefined) {
- action.target[action.property] = action.value;
- }
- }
- }
- }
-
- ParallelAnimation {
- NumberAnimation {
- target: root.target
- property: "opacity"
- from: root.opacityTo
- to: root.opacityFrom
- duration: Appearance.anim.durations.normal / 2
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
-
- NumberAnimation {
- target: root.target
- property: "scale"
- from: root.scaleTo
- to: root.scaleFrom
- duration: Appearance.anim.durations.normal / 2
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
-}
diff --git a/modules/controlcenter/components/ReadonlySlider.qml b/modules/controlcenter/components/ReadonlySlider.qml
deleted file mode 100644
index 169d636..0000000
--- a/modules/controlcenter/components/ReadonlySlider.qml
+++ /dev/null
@@ -1,67 +0,0 @@
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- property string label: ""
- property real value: 0
- property real from: 0
- property real to: 100
- property string suffix: ""
- property bool readonly: false
-
- spacing: Appearance.spacing.small
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- StyledText {
- visible: root.label !== ""
- text: root.label
- font.pointSize: Appearance.font.size.normal
- color: root.readonly ? Colours.palette.m3outline : Colours.palette.m3onSurface
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- MaterialIcon {
- visible: root.readonly
- text: "lock"
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledText {
- text: Math.round(root.value) + (root.suffix !== "" ? " " + root.suffix : "")
- font.pointSize: Appearance.font.size.normal
- color: root.readonly ? Colours.palette.m3outline : Colours.palette.m3onSurface
- }
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: Appearance.padding.normal
- radius: Appearance.rounding.full
- color: Colours.layer(Colours.palette.m3surfaceContainerHighest, 1)
- opacity: root.readonly ? 0.5 : 1.0
-
- StyledRect {
- anchors.left: parent.left
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- width: parent.width * ((root.value - root.from) / (root.to - root.from))
- radius: parent.radius
- color: root.readonly ? Colours.palette.m3outline : Colours.palette.m3primary
- }
- }
-}
diff --git a/modules/controlcenter/components/SettingsHeader.qml b/modules/controlcenter/components/SettingsHeader.qml
deleted file mode 100644
index 0dc190c..0000000
--- a/modules/controlcenter/components/SettingsHeader.qml
+++ /dev/null
@@ -1,37 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property string icon
- required property string title
-
- Layout.fillWidth: true
- implicitHeight: column.implicitHeight
-
- ColumnLayout {
- id: column
-
- anchors.centerIn: parent
- spacing: Appearance.spacing.normal
-
- MaterialIcon {
- Layout.alignment: Qt.AlignHCenter
- text: root.icon
- font.pointSize: Appearance.font.size.extraLarge * 3
- font.bold: true
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- text: root.title
- font.pointSize: Appearance.font.size.large
- font.bold: true
- }
- }
-}
diff --git a/modules/controlcenter/components/SliderInput.qml b/modules/controlcenter/components/SliderInput.qml
deleted file mode 100644
index 11b3f70..0000000
--- a/modules/controlcenter/components/SliderInput.qml
+++ /dev/null
@@ -1,180 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- property string label: ""
- property real value: 0
- property real from: 0
- property real to: 100
- property real stepSize: 0
- property var validator: null
- property string suffix: "" // Optional suffix text (e.g., "×", "px")
- property int decimals: 1 // Number of decimal places to show (default: 1)
- property var formatValueFunction: null // Optional custom format function
- property var parseValueFunction: null // Optional custom parse function
-
- function formatValue(val: real): string {
- if (formatValueFunction) {
- return formatValueFunction(val);
- }
- // Default format function
- // Check if it's an IntValidator (IntValidator doesn't have a 'decimals' property)
- if (validator && validator.bottom !== undefined && validator.decimals === undefined) {
- return Math.round(val).toString();
- }
- // For DoubleValidator or no validator, use the decimals property
- return val.toFixed(root.decimals);
- }
-
- function parseValue(text: string): real {
- if (parseValueFunction) {
- return parseValueFunction(text);
- }
- // Default parse function
- if (validator && validator.bottom !== undefined) {
- // Check if it's an integer validator
- if (validator.top !== undefined && validator.top === Math.floor(validator.top)) {
- return parseInt(text);
- }
- }
- return parseFloat(text);
- }
-
- signal valueModified(real newValue)
-
- property bool _initialized: false
-
- spacing: Appearance.spacing.small
-
- Component.onCompleted: {
- // Set initialized flag after a brief delay to allow component to fully load
- Qt.callLater(() => {
- _initialized = true;
- });
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- StyledText {
- visible: root.label !== ""
- text: root.label
- font.pointSize: Appearance.font.size.normal
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- StyledInputField {
- id: inputField
- Layout.preferredWidth: 70
- validator: root.validator
-
- Component.onCompleted: {
- // Initialize text without triggering valueModified signal
- text = root.formatValue(root.value);
- }
-
- onTextEdited: text => {
- if (hasFocus) {
- const val = root.parseValue(text);
- if (!isNaN(val)) {
- // Validate against validator bounds if available
- let isValid = true;
- if (root.validator) {
- if (root.validator.bottom !== undefined && val < root.validator.bottom) {
- isValid = false;
- }
- if (root.validator.top !== undefined && val > root.validator.top) {
- isValid = false;
- }
- }
-
- if (isValid) {
- root.valueModified(val);
- }
- }
- }
- }
-
- onEditingFinished: {
- const val = root.parseValue(text);
- let isValid = true;
- if (root.validator) {
- if (root.validator.bottom !== undefined && val < root.validator.bottom) {
- isValid = false;
- }
- if (root.validator.top !== undefined && val > root.validator.top) {
- isValid = false;
- }
- }
-
- if (isNaN(val) || !isValid) {
- text = root.formatValue(root.value);
- }
- }
- }
-
- StyledText {
- visible: root.suffix !== ""
- text: root.suffix
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.normal
- }
- }
-
- StyledSlider {
- id: slider
-
- Layout.fillWidth: true
- implicitHeight: Appearance.padding.normal * 3
-
- from: root.from
- to: root.to
- stepSize: root.stepSize
-
- // Use Binding to allow slider to move freely during dragging
- Binding {
- target: slider
- property: "value"
- value: root.value
- when: !slider.pressed
- }
-
- onValueChanged: {
- // Update input field text in real-time as slider moves during dragging
- // Always update when slider value changes (during dragging or external updates)
- if (!inputField.hasFocus) {
- const newValue = root.stepSize > 0 ? Math.round(value / root.stepSize) * root.stepSize : value;
- inputField.text = root.formatValue(newValue);
- }
- }
-
- onMoved: {
- const newValue = root.stepSize > 0 ? Math.round(value / root.stepSize) * root.stepSize : value;
- root.valueModified(newValue);
- if (!inputField.hasFocus) {
- inputField.text = root.formatValue(newValue);
- }
- }
- }
-
- // Update input field when value changes externally (slider is already bound)
- onValueChanged: {
- // Only update if component is initialized to avoid issues during creation
- if (root._initialized && !inputField.hasFocus) {
- inputField.text = root.formatValue(root.value);
- }
- }
-}
diff --git a/modules/controlcenter/components/SplitPaneLayout.qml b/modules/controlcenter/components/SplitPaneLayout.qml
deleted file mode 100644
index 89504a0..0000000
--- a/modules/controlcenter/components/SplitPaneLayout.qml
+++ /dev/null
@@ -1,109 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.effects
-import qs.config
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-RowLayout {
- id: root
-
- spacing: 0
-
- property Component leftContent: null
- property Component rightContent: null
-
- property real leftWidthRatio: 0.4
- property int leftMinimumWidth: 420
- property var leftLoaderProperties: ({})
- property var rightLoaderProperties: ({})
-
- property alias leftLoader: leftLoader
- property alias rightLoader: rightLoader
-
- Item {
- id: leftPane
-
- Layout.preferredWidth: Math.floor(parent.width * root.leftWidthRatio)
- Layout.minimumWidth: root.leftMinimumWidth
- Layout.fillHeight: true
-
- ClippingRectangle {
- id: leftClippingRect
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.normal
- anchors.leftMargin: 0
- anchors.rightMargin: Appearance.padding.normal / 2
-
- radius: leftBorder.innerRadius
- color: "transparent"
-
- Loader {
- id: leftLoader
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large + Appearance.padding.normal
- anchors.leftMargin: Appearance.padding.large
- anchors.rightMargin: Appearance.padding.large + Appearance.padding.normal / 2
-
- sourceComponent: root.leftContent
-
- Component.onCompleted: {
- for (const key in root.leftLoaderProperties) {
- leftLoader[key] = root.leftLoaderProperties[key];
- }
- }
- }
- }
-
- InnerBorder {
- id: leftBorder
-
- leftThickness: 0
- rightThickness: Appearance.padding.normal / 2
- }
- }
-
- Item {
- id: rightPane
-
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- ClippingRectangle {
- id: rightClippingRect
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.normal
- anchors.leftMargin: 0
- anchors.rightMargin: Appearance.padding.normal / 2
-
- radius: rightBorder.innerRadius
- color: "transparent"
-
- Loader {
- id: rightLoader
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large * 2
-
- sourceComponent: root.rightContent
-
- Component.onCompleted: {
- for (const key in root.rightLoaderProperties) {
- rightLoader[key] = root.rightLoaderProperties[key];
- }
- }
- }
- }
-
- InnerBorder {
- id: rightBorder
-
- leftThickness: Appearance.padding.normal / 2
- }
- }
-}
diff --git a/modules/controlcenter/components/SplitPaneWithDetails.qml b/modules/controlcenter/components/SplitPaneWithDetails.qml
deleted file mode 100644
index ce8c9d0..0000000
--- a/modules/controlcenter/components/SplitPaneWithDetails.qml
+++ /dev/null
@@ -1,93 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import qs.components
-import qs.components.effects
-import qs.components.containers
-import qs.config
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property Component leftContent
- required property Component rightDetailsComponent
- required property Component rightSettingsComponent
-
- property var activeItem: null
- property var paneIdGenerator: function (item) {
- return item ? String(item) : "";
- }
-
- property Component overlayComponent: null
-
- SplitPaneLayout {
- id: splitLayout
-
- anchors.fill: parent
-
- leftContent: root.leftContent
-
- rightContent: Component {
- Item {
- id: rightPaneItem
-
- property var pane: root.activeItem
- property string paneId: root.paneIdGenerator(pane)
- property Component targetComponent: root.rightSettingsComponent
- property Component nextComponent: root.rightSettingsComponent
-
- function getComponentForPane() {
- return pane ? root.rightDetailsComponent : root.rightSettingsComponent;
- }
-
- Component.onCompleted: {
- targetComponent = getComponentForPane();
- nextComponent = targetComponent;
- }
-
- Loader {
- id: rightLoader
-
- anchors.fill: parent
-
- opacity: 1
- scale: 1
- transformOrigin: Item.Center
-
- clip: false
- sourceComponent: rightPaneItem.targetComponent
- }
-
- Behavior on paneId {
- PaneTransition {
- target: rightLoader
- propertyActions: [
- PropertyAction {
- target: rightPaneItem
- property: "targetComponent"
- value: rightPaneItem.nextComponent
- }
- ]
- }
- }
-
- onPaneChanged: {
- nextComponent = getComponentForPane();
- paneId = root.paneIdGenerator(pane);
- }
- }
- }
- }
-
- Loader {
- id: overlayLoader
-
- anchors.fill: parent
- z: 1000
- sourceComponent: root.overlayComponent
- active: root.overlayComponent !== null
- }
-}
diff --git a/modules/controlcenter/dashboard/DashboardPane.qml b/modules/controlcenter/dashboard/DashboardPane.qml
deleted file mode 100644
index df29f09..0000000
--- a/modules/controlcenter/dashboard/DashboardPane.qml
+++ /dev/null
@@ -1,135 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property Session session
-
- // General Settings
- property bool enabled: Config.dashboard.enabled ?? true
- property bool showOnHover: Config.dashboard.showOnHover ?? true
- property int mediaUpdateInterval: Config.dashboard.mediaUpdateInterval ?? 1000
- property int resourceUpdateInterval: Config.dashboard.resourceUpdateInterval ?? 1000
- property int dragThreshold: Config.dashboard.dragThreshold ?? 50
-
- // Dashboard Tabs
- property bool showDashboard: Config.dashboard.showDashboard ?? true
- property bool showMedia: Config.dashboard.showMedia ?? true
- property bool showPerformance: Config.dashboard.showPerformance ?? true
- property bool showWeather: Config.dashboard.showWeather ?? true
-
- // Performance Resources
- property bool showBattery: Config.dashboard.performance.showBattery ?? false
- property bool showGpu: Config.dashboard.performance.showGpu ?? true
- property bool showCpu: Config.dashboard.performance.showCpu ?? true
- property bool showMemory: Config.dashboard.performance.showMemory ?? true
- property bool showStorage: Config.dashboard.performance.showStorage ?? true
- property bool showNetwork: Config.dashboard.performance.showNetwork ?? true
-
- anchors.fill: parent
-
- function saveConfig() {
- Config.dashboard.enabled = root.enabled;
- Config.dashboard.showOnHover = root.showOnHover;
- Config.dashboard.mediaUpdateInterval = root.mediaUpdateInterval;
- Config.dashboard.resourceUpdateInterval = root.resourceUpdateInterval;
- Config.dashboard.dragThreshold = root.dragThreshold;
- Config.dashboard.showDashboard = root.showDashboard;
- Config.dashboard.showMedia = root.showMedia;
- Config.dashboard.showPerformance = root.showPerformance;
- Config.dashboard.showWeather = root.showWeather;
- Config.dashboard.performance.showBattery = root.showBattery;
- Config.dashboard.performance.showGpu = root.showGpu;
- Config.dashboard.performance.showCpu = root.showCpu;
- Config.dashboard.performance.showMemory = root.showMemory;
- Config.dashboard.performance.showStorage = root.showStorage;
- Config.dashboard.performance.showNetwork = root.showNetwork;
- // Note: sizes properties are readonly and cannot be modified
- Config.save();
- }
-
- ClippingRectangle {
- id: dashboardClippingRect
- anchors.fill: parent
- anchors.margins: Appearance.padding.normal
- anchors.leftMargin: 0
- anchors.rightMargin: Appearance.padding.normal
-
- radius: dashboardBorder.innerRadius
- color: "transparent"
-
- Loader {
- id: dashboardLoader
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large + Appearance.padding.normal
- anchors.leftMargin: Appearance.padding.large
- anchors.rightMargin: Appearance.padding.large
-
- sourceComponent: dashboardContentComponent
- }
- }
-
- InnerBorder {
- id: dashboardBorder
- leftThickness: 0
- rightThickness: Appearance.padding.normal
- }
-
- Component {
- id: dashboardContentComponent
-
- StyledFlickable {
- id: dashboardFlickable
- flickableDirection: Flickable.VerticalFlick
- contentHeight: dashboardLayout.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: dashboardFlickable
- }
-
- ColumnLayout {
- id: dashboardLayout
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
-
- spacing: Appearance.spacing.normal
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Dashboard")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
- }
-
- // General Settings Section
- GeneralSection {
- rootItem: root
- }
-
- // Performance Resources Section
- PerformanceSection {
- rootItem: root
- }
- }
- }
- }
-}
diff --git a/modules/controlcenter/dashboard/GeneralSection.qml b/modules/controlcenter/dashboard/GeneralSection.qml
deleted file mode 100644
index 95e7531..0000000
--- a/modules/controlcenter/dashboard/GeneralSection.qml
+++ /dev/null
@@ -1,128 +0,0 @@
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-SectionContainer {
- id: root
-
- required property var rootItem
-
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("General Settings")
- font.pointSize: Appearance.font.size.normal
- }
-
- SwitchRow {
- label: qsTr("Enabled")
- checked: root.rootItem.enabled
- onToggled: checked => {
- root.rootItem.enabled = checked;
- root.rootItem.saveConfig();
- }
- }
-
- SwitchRow {
- label: qsTr("Show on hover")
- checked: root.rootItem.showOnHover
- onToggled: checked => {
- root.rootItem.showOnHover = checked;
- root.rootItem.saveConfig();
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- SwitchRow {
- Layout.fillWidth: true
- label: qsTr("Show Dashboard tab")
- checked: root.rootItem.showDashboard
- onToggled: checked => {
- root.rootItem.showDashboard = checked;
- root.rootItem.saveConfig();
- }
- }
-
- SwitchRow {
- Layout.fillWidth: true
- label: qsTr("Show Media tab")
- checked: root.rootItem.showMedia
- onToggled: checked => {
- root.rootItem.showMedia = checked;
- root.rootItem.saveConfig();
- }
- }
-
- SwitchRow {
- Layout.fillWidth: true
- label: qsTr("Show Performance tab")
- checked: root.rootItem.showPerformance
- onToggled: checked => {
- root.rootItem.showPerformance = checked;
- root.rootItem.saveConfig();
- }
- }
-
- SwitchRow {
- Layout.fillWidth: true
- label: qsTr("Show Weather tab")
- checked: root.rootItem.showWeather
- onToggled: checked => {
- root.rootItem.showWeather = checked;
- root.rootItem.saveConfig();
- }
- }
- }
-
- SliderInput {
- Layout.fillWidth: true
-
- label: qsTr("Media update interval")
- value: root.rootItem.mediaUpdateInterval
- from: 100
- to: 10000
- stepSize: 100
- suffix: "ms"
- validator: IntValidator {
- bottom: 100
- top: 10000
- }
- formatValueFunction: val => Math.round(val).toString()
- parseValueFunction: text => parseInt(text)
-
- onValueModified: newValue => {
- root.rootItem.mediaUpdateInterval = Math.round(newValue);
- root.rootItem.saveConfig();
- }
- }
-
- SliderInput {
- Layout.fillWidth: true
-
- label: qsTr("Drag threshold")
- value: root.rootItem.dragThreshold
- from: 0
- to: 100
- suffix: "px"
- validator: IntValidator {
- bottom: 0
- top: 100
- }
- formatValueFunction: val => Math.round(val).toString()
- parseValueFunction: text => parseInt(text)
-
- onValueModified: newValue => {
- root.rootItem.dragThreshold = Math.round(newValue);
- root.rootItem.saveConfig();
- }
- }
-}
diff --git a/modules/controlcenter/dashboard/PerformanceSection.qml b/modules/controlcenter/dashboard/PerformanceSection.qml
deleted file mode 100644
index ac84752..0000000
--- a/modules/controlcenter/dashboard/PerformanceSection.qml
+++ /dev/null
@@ -1,106 +0,0 @@
-import ".."
-import "../components"
-import QtQuick
-import QtQuick.Layouts
-import Quickshell.Services.UPower
-import qs.components
-import qs.components.controls
-import qs.config
-import qs.services
-
-SectionContainer {
- id: root
-
- required property var rootItem
- // GPU toggle is hidden when gpuType is "NONE" (no GPU data available)
- readonly property bool gpuAvailable: SystemUsage.gpuType !== "NONE"
- // Battery toggle is hidden when no laptop battery is present
- readonly property bool batteryAvailable: UPower.displayDevice.isLaptopBattery
-
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Performance Resources")
- font.pointSize: Appearance.font.size.normal
- }
-
- ConnectedButtonGroup {
- rootItem: root.rootItem
- options: {
- let opts = [];
- if (root.batteryAvailable)
- opts.push({
- "label": qsTr("Battery"),
- "propertyName": "showBattery",
- "onToggled": function (checked) {
- root.rootItem.showBattery = checked;
- root.rootItem.saveConfig();
- }
- });
-
- if (root.gpuAvailable)
- opts.push({
- "label": qsTr("GPU"),
- "propertyName": "showGpu",
- "onToggled": function (checked) {
- root.rootItem.showGpu = checked;
- root.rootItem.saveConfig();
- }
- });
-
- opts.push({
- "label": qsTr("CPU"),
- "propertyName": "showCpu",
- "onToggled": function (checked) {
- root.rootItem.showCpu = checked;
- root.rootItem.saveConfig();
- }
- }, {
- "label": qsTr("Memory"),
- "propertyName": "showMemory",
- "onToggled": function (checked) {
- root.rootItem.showMemory = checked;
- root.rootItem.saveConfig();
- }
- }, {
- "label": qsTr("Storage"),
- "propertyName": "showStorage",
- "onToggled": function (checked) {
- root.rootItem.showStorage = checked;
- root.rootItem.saveConfig();
- }
- }, {
- "label": qsTr("Network"),
- "propertyName": "showNetwork",
- "onToggled": function (checked) {
- root.rootItem.showNetwork = checked;
- root.rootItem.saveConfig();
- }
- });
- return opts;
- }
- }
-
- SliderInput {
- Layout.fillWidth: true
-
- label: qsTr("Resource update interval")
- value: root.rootItem.resourceUpdateInterval
- from: 100
- to: 10000
- stepSize: 100
- suffix: "ms"
- validator: IntValidator {
- bottom: 100
- top: 10000
- }
- formatValueFunction: val => Math.round(val).toString()
- parseValueFunction: text => parseInt(text)
-
- onValueModified: newValue => {
- root.rootItem.resourceUpdateInterval = Math.round(newValue);
- root.rootItem.saveConfig();
- }
- }
-}
diff --git a/modules/controlcenter/network/EthernetDetails.qml b/modules/controlcenter/network/EthernetDetails.qml
deleted file mode 100644
index 4e60b3d..0000000
--- a/modules/controlcenter/network/EthernetDetails.qml
+++ /dev/null
@@ -1,118 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-DeviceDetails {
- id: root
-
- required property Session session
- readonly property var ethernetDevice: root.session.ethernet.active
-
- device: ethernetDevice
-
- Component.onCompleted: {
- if (ethernetDevice && ethernetDevice.interface) {
- Nmcli.getEthernetDeviceDetails(ethernetDevice.interface, () => {});
- }
- }
-
- onEthernetDeviceChanged: {
- if (ethernetDevice && ethernetDevice.interface) {
- Nmcli.getEthernetDeviceDetails(ethernetDevice.interface, () => {});
- } else {
- Nmcli.ethernetDeviceDetails = null;
- }
- }
-
- headerComponent: Component {
- ConnectionHeader {
- icon: "cable"
- title: root.ethernetDevice?.interface ?? qsTr("Unknown")
- }
- }
-
- sections: [
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- SectionHeader {
- title: qsTr("Connection status")
- description: qsTr("Connection settings for this device")
- }
-
- SectionContainer {
- ToggleRow {
- label: qsTr("Connected")
- checked: root.ethernetDevice?.connected ?? false
- toggle.onToggled: {
- if (checked) {
- Nmcli.connectEthernet(root.ethernetDevice?.connection || "", root.ethernetDevice?.interface || "", () => {});
- } else {
- if (root.ethernetDevice?.connection) {
- Nmcli.disconnectEthernet(root.ethernetDevice.connection, () => {});
- }
- }
- }
- }
- }
- }
- },
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- SectionHeader {
- title: qsTr("Device properties")
- description: qsTr("Additional information")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.small / 2
-
- PropertyRow {
- label: qsTr("Interface")
- value: root.ethernetDevice?.interface ?? qsTr("Unknown")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Connection")
- value: root.ethernetDevice?.connection || qsTr("Not connected")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("State")
- value: root.ethernetDevice?.state ?? qsTr("Unknown")
- }
- }
- }
- },
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- SectionHeader {
- title: qsTr("Connection information")
- description: qsTr("Network connection details")
- }
-
- SectionContainer {
- ConnectionInfoSection {
- deviceDetails: Nmcli.ethernetDeviceDetails
- }
- }
- }
- }
- ]
-}
diff --git a/modules/controlcenter/network/EthernetList.qml b/modules/controlcenter/network/EthernetList.qml
deleted file mode 100644
index d1eb957..0000000
--- a/modules/controlcenter/network/EthernetList.qml
+++ /dev/null
@@ -1,177 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-DeviceList {
- id: root
-
- required property Session session
-
- title: qsTr("Devices (%1)").arg(Nmcli.ethernetDevices.length)
- description: qsTr("All available ethernet devices")
- activeItem: session.ethernet.active
-
- model: Nmcli.ethernetDevices
-
- headerComponent: Component {
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Settings")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- ToggleButton {
- toggled: !root.session.ethernet.active
- icon: "settings"
- accent: "Primary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
-
- onClicked: {
- if (root.session.ethernet.active)
- root.session.ethernet.active = null;
- else {
- root.session.ethernet.active = root.view.model.get(0)?.modelData ?? null;
- }
- }
- }
- }
- }
-
- delegate: Component {
- StyledRect {
- id: ethernetItem
-
- required property var modelData
- readonly property bool isActive: root.activeItem && modelData && root.activeItem.interface === modelData.interface
-
- width: ListView.view ? ListView.view.width : undefined
- implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2
-
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, ethernetItem.isActive ? Colours.tPalette.m3surfaceContainer.a : 0)
- radius: Appearance.rounding.normal
-
- StateLayer {
- id: stateLayer
-
- function onClicked(): void {
- root.session.ethernet.active = modelData;
- }
- }
-
- RowLayout {
- id: rowLayout
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: icon.implicitHeight + Appearance.padding.normal * 2
-
- radius: Appearance.rounding.normal
- color: modelData.connected ? Colours.palette.m3primaryContainer : Colours.tPalette.m3surfaceContainerHigh
-
- StyledRect {
- anchors.fill: parent
- radius: parent.radius
- color: Qt.alpha(modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface, stateLayer.pressed ? 0.1 : stateLayer.containsMouse ? 0.08 : 0)
- }
-
- MaterialIcon {
- id: icon
-
- anchors.centerIn: parent
- text: "cable"
- font.pointSize: Appearance.font.size.large
- fill: modelData.connected ? 1 : 0
- color: modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
-
- Behavior on fill {
- Anim {}
- }
- }
- }
-
- ColumnLayout {
- Layout.fillWidth: true
-
- spacing: 0
-
- StyledText {
- Layout.fillWidth: true
- text: modelData.interface || qsTr("Unknown")
- elide: Text.ElideRight
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller
-
- StyledText {
- Layout.fillWidth: true
- text: modelData.connected ? qsTr("Connected") : qsTr("Disconnected")
- color: modelData.connected ? Colours.palette.m3primary : Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- font.weight: modelData.connected ? 500 : 400
- elide: Text.ElideRight
- }
- }
- }
-
- StyledRect {
- id: connectBtn
-
- implicitWidth: implicitHeight
- implicitHeight: connectIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.full
- color: Qt.alpha(Colours.palette.m3primaryContainer, modelData.connected ? 1 : 0)
-
- StateLayer {
- color: modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
-
- function onClicked(): void {
- if (modelData.connected && modelData.connection) {
- Nmcli.disconnectEthernet(modelData.connection, () => {});
- } else {
- Nmcli.connectEthernet(modelData.connection || "", modelData.interface || "", () => {});
- }
- }
- }
-
- MaterialIcon {
- id: connectIcon
-
- anchors.centerIn: parent
- animate: true
- text: modelData.connected ? "link_off" : "link"
- color: modelData.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
- }
- }
- }
- }
- }
-
- onItemSelected: function (item) {
- session.ethernet.active = item;
- }
-}
diff --git a/modules/controlcenter/network/EthernetPane.qml b/modules/controlcenter/network/EthernetPane.qml
deleted file mode 100644
index 59d82bb..0000000
--- a/modules/controlcenter/network/EthernetPane.qml
+++ /dev/null
@@ -1,50 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.containers
-import qs.config
-import Quickshell.Widgets
-import QtQuick
-
-SplitPaneWithDetails {
- id: root
-
- required property Session session
-
- anchors.fill: parent
-
- activeItem: session.ethernet.active
- paneIdGenerator: function (item) {
- return item ? (item.interface || "") : "";
- }
-
- leftContent: Component {
- EthernetList {
- session: root.session
- }
- }
-
- rightDetailsComponent: Component {
- EthernetDetails {
- session: root.session
- }
- }
-
- rightSettingsComponent: Component {
- StyledFlickable {
- flickableDirection: Flickable.VerticalFlick
- contentHeight: settingsInner.height
- clip: true
-
- EthernetSettings {
- id: settingsInner
-
- anchors.left: parent.left
- anchors.right: parent.right
- session: root.session
- }
- }
- }
-}
diff --git a/modules/controlcenter/network/EthernetSettings.qml b/modules/controlcenter/network/EthernetSettings.qml
deleted file mode 100644
index 90bfcf4..0000000
--- a/modules/controlcenter/network/EthernetSettings.qml
+++ /dev/null
@@ -1,76 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property Session session
-
- spacing: Appearance.spacing.normal
-
- SettingsHeader {
- icon: "cable"
- title: qsTr("Ethernet settings")
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.large
- text: qsTr("Ethernet devices")
- font.pointSize: Appearance.font.size.larger
- font.weight: 500
- }
-
- StyledText {
- text: qsTr("Available ethernet devices")
- color: Colours.palette.m3outline
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: ethernetInfo.implicitHeight + Appearance.padding.large * 2
-
- radius: Appearance.rounding.normal
- color: Colours.tPalette.m3surfaceContainer
-
- ColumnLayout {
- id: ethernetInfo
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.small / 2
-
- StyledText {
- text: qsTr("Total devices")
- }
-
- StyledText {
- text: qsTr("%1").arg(Nmcli.ethernetDevices.length)
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledText {
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("Connected devices")
- }
-
- StyledText {
- text: qsTr("%1").arg(Nmcli.ethernetDevices.filter(d => d.connected).length)
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
- }
- }
-}
diff --git a/modules/controlcenter/network/NetworkSettings.qml b/modules/controlcenter/network/NetworkSettings.qml
deleted file mode 100644
index 69f4e63..0000000
--- a/modules/controlcenter/network/NetworkSettings.qml
+++ /dev/null
@@ -1,99 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.components.effects
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property Session session
-
- spacing: Appearance.spacing.normal
-
- SettingsHeader {
- icon: "router"
- title: qsTr("Network Settings")
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("Ethernet")
- description: qsTr("Ethernet device information")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.small / 2
-
- PropertyRow {
- label: qsTr("Total devices")
- value: qsTr("%1").arg(Nmcli.ethernetDevices.length)
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Connected devices")
- value: qsTr("%1").arg(Nmcli.ethernetDevices.filter(d => d.connected).length)
- }
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("Wireless")
- description: qsTr("WiFi network settings")
- }
-
- SectionContainer {
- ToggleRow {
- label: qsTr("WiFi enabled")
- checked: Nmcli.wifiEnabled
- toggle.onToggled: {
- Nmcli.enableWifi(checked);
- }
- }
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("Current connection")
- description: qsTr("Active network connection information")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.small / 2
-
- PropertyRow {
- label: qsTr("Network")
- value: Nmcli.active ? Nmcli.active.ssid : (Nmcli.activeEthernet ? Nmcli.activeEthernet.interface : qsTr("Not connected"))
- }
-
- PropertyRow {
- showTopMargin: true
- visible: Nmcli.active !== null
- label: qsTr("Signal strength")
- value: Nmcli.active ? qsTr("%1%").arg(Nmcli.active.strength) : qsTr("N/A")
- }
-
- PropertyRow {
- showTopMargin: true
- visible: Nmcli.active !== null
- label: qsTr("Security")
- value: Nmcli.active ? (Nmcli.active.isSecure ? qsTr("Secured") : qsTr("Open")) : qsTr("N/A")
- }
-
- PropertyRow {
- showTopMargin: true
- visible: Nmcli.active !== null
- label: qsTr("Frequency")
- value: Nmcli.active ? qsTr("%1 MHz").arg(Nmcli.active.frequency) : qsTr("N/A")
- }
- }
-}
diff --git a/modules/controlcenter/network/NetworkingPane.qml b/modules/controlcenter/network/NetworkingPane.qml
deleted file mode 100644
index c32fbb7..0000000
--- a/modules/controlcenter/network/NetworkingPane.qml
+++ /dev/null
@@ -1,309 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import "."
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property Session session
-
- anchors.fill: parent
-
- SplitPaneLayout {
- id: splitLayout
-
- anchors.fill: parent
-
- leftContent: Component {
- StyledFlickable {
- id: leftFlickable
-
- flickableDirection: Flickable.VerticalFlick
- contentHeight: leftContent.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: leftFlickable
- }
-
- ColumnLayout {
- id: leftContent
-
- anchors.left: parent.left
- anchors.right: parent.right
- spacing: Appearance.spacing.normal
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Network")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- ToggleButton {
- toggled: Nmcli.wifiEnabled
- icon: "wifi"
- accent: "Tertiary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
- tooltip: qsTr("Toggle WiFi")
-
- onClicked: {
- Nmcli.toggleWifi(null);
- }
- }
-
- ToggleButton {
- toggled: Nmcli.scanning
- icon: "wifi_find"
- accent: "Secondary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
- tooltip: qsTr("Scan for networks")
-
- onClicked: {
- Nmcli.rescanWifi();
- }
- }
-
- ToggleButton {
- toggled: !root.session.ethernet.active && !root.session.network.active
- icon: "settings"
- accent: "Primary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
- tooltip: qsTr("Network settings")
-
- onClicked: {
- if (root.session.ethernet.active || root.session.network.active) {
- root.session.ethernet.active = null;
- root.session.network.active = null;
- } else {
- if (Nmcli.ethernetDevices.length > 0) {
- root.session.ethernet.active = Nmcli.ethernetDevices[0];
- } else if (Nmcli.networks.length > 0) {
- root.session.network.active = Nmcli.networks[0];
- }
- }
- }
- }
- }
-
- CollapsibleSection {
- id: ethernetListSection
-
- Layout.fillWidth: true
- title: qsTr("Ethernet")
- expanded: true
-
- Loader {
- Layout.fillWidth: true
- sourceComponent: Component {
- EthernetList {
- session: root.session
- showHeader: false
- }
- }
- }
- }
-
- CollapsibleSection {
- id: wirelessListSection
-
- Layout.fillWidth: true
- title: qsTr("Wireless")
- expanded: true
-
- Loader {
- Layout.fillWidth: true
- sourceComponent: Component {
- WirelessList {
- session: root.session
- showHeader: false
- }
- }
- }
- }
- }
- }
- }
-
- rightContent: Component {
- Item {
- id: rightPaneItem
-
- property var ethernetPane: root.session && root.session.ethernet ? root.session.ethernet.active : null
- property var wirelessPane: root.session && root.session.network ? root.session.network.active : null
- property var pane: ethernetPane || wirelessPane
- property string paneId: ethernetPane ? ("eth:" + (ethernetPane.interface || "")) : (wirelessPane ? ("wifi:" + (wirelessPane.ssid || wirelessPane.bssid || "")) : "settings")
- property Component targetComponent: settingsComponent
- property Component nextComponent: settingsComponent
-
- function getComponentForPane() {
- if (ethernetPane)
- return ethernetDetailsComponent;
- if (wirelessPane)
- return wirelessDetailsComponent;
- return settingsComponent;
- }
-
- Component.onCompleted: {
- targetComponent = getComponentForPane();
- nextComponent = targetComponent;
- }
-
- Connections {
- target: root.session && root.session.ethernet ? root.session.ethernet : null
- enabled: target !== null
-
- function onActiveChanged() {
- // Clear others when ethernet is selected
- if (root.session && root.session.ethernet && root.session.ethernet.active) {
- if (root.session.network && root.session.network.active)
- root.session.network.active = null;
- }
- rightPaneItem.nextComponent = rightPaneItem.getComponentForPane();
- }
- }
-
- Connections {
- target: root.session && root.session.network ? root.session.network : null
- enabled: target !== null
-
- function onActiveChanged() {
- // Clear others when wireless is selected
- if (root.session && root.session.network && root.session.network.active) {
- if (root.session.ethernet && root.session.ethernet.active)
- root.session.ethernet.active = null;
- }
- rightPaneItem.nextComponent = rightPaneItem.getComponentForPane();
- }
- }
-
- Loader {
- id: rightLoader
-
- anchors.fill: parent
-
- opacity: 1
- scale: 1
- transformOrigin: Item.Center
- clip: false
-
- asynchronous: true
- sourceComponent: rightPaneItem.targetComponent
- }
-
- Behavior on paneId {
- PaneTransition {
- target: rightLoader
- propertyActions: [
- PropertyAction {
- target: rightPaneItem
- property: "targetComponent"
- value: rightPaneItem.nextComponent
- }
- ]
- }
- }
- }
- }
- }
-
- Component {
- id: settingsComponent
-
- StyledFlickable {
- id: settingsFlickable
- flickableDirection: Flickable.VerticalFlick
- contentHeight: settingsInner.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: settingsFlickable
- }
-
- NetworkSettings {
- id: settingsInner
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- session: root.session
- }
- }
- }
-
- Component {
- id: ethernetDetailsComponent
-
- StyledFlickable {
- id: ethernetFlickable
- flickableDirection: Flickable.VerticalFlick
- contentHeight: ethernetDetailsInner.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: ethernetFlickable
- }
-
- EthernetDetails {
- id: ethernetDetailsInner
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- session: root.session
- }
- }
- }
-
- Component {
- id: wirelessDetailsComponent
-
- StyledFlickable {
- id: wirelessFlickable
- flickableDirection: Flickable.VerticalFlick
- contentHeight: wirelessDetailsInner.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: wirelessFlickable
- }
-
- WirelessDetails {
- id: wirelessDetailsInner
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- session: root.session
- }
- }
- }
-
- WirelessPasswordDialog {
- anchors.fill: parent
- session: root.session
- z: 1000
- }
-}
diff --git a/modules/controlcenter/network/WirelessDetails.qml b/modules/controlcenter/network/WirelessDetails.qml
deleted file mode 100644
index e8777cd..0000000
--- a/modules/controlcenter/network/WirelessDetails.qml
+++ /dev/null
@@ -1,211 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import "."
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import QtQuick
-import QtQuick.Layouts
-
-DeviceDetails {
- id: root
-
- required property Session session
- readonly property var network: root.session.network.active
-
- device: network
-
- Component.onCompleted: {
- updateDeviceDetails();
- checkSavedProfile();
- }
-
- onNetworkChanged: {
- connectionUpdateTimer.stop();
- if (network && network.ssid) {
- connectionUpdateTimer.start();
- }
- updateDeviceDetails();
- checkSavedProfile();
- }
-
- function checkSavedProfile(): void {
- if (network && network.ssid) {
- Nmcli.loadSavedConnections(() => {});
- }
- }
-
- Connections {
- target: Nmcli
- function onActiveChanged() {
- updateDeviceDetails();
- }
- function onWirelessDeviceDetailsChanged() {
- if (network && network.ssid) {
- const isActive = network.active || (Nmcli.active && Nmcli.active.ssid === network.ssid);
- if (isActive && Nmcli.wirelessDeviceDetails && Nmcli.wirelessDeviceDetails !== null) {
- connectionUpdateTimer.stop();
- }
- }
- }
- }
-
- Timer {
- id: connectionUpdateTimer
- interval: 500
- repeat: true
- running: network && network.ssid
- onTriggered: {
- if (network) {
- const isActive = network.active || (Nmcli.active && Nmcli.active.ssid === network.ssid);
- if (isActive) {
- if (!Nmcli.wirelessDeviceDetails || Nmcli.wirelessDeviceDetails === null) {
- Nmcli.getWirelessDeviceDetails("", () => {});
- } else {
- connectionUpdateTimer.stop();
- }
- } else {
- if (Nmcli.wirelessDeviceDetails !== null) {
- Nmcli.wirelessDeviceDetails = null;
- }
- }
- }
- }
- }
-
- function updateDeviceDetails(): void {
- if (network && network.ssid) {
- const isActive = network.active || (Nmcli.active && Nmcli.active.ssid === network.ssid);
- if (isActive) {
- Nmcli.getWirelessDeviceDetails("");
- } else {
- Nmcli.wirelessDeviceDetails = null;
- }
- } else {
- Nmcli.wirelessDeviceDetails = null;
- }
- }
-
- headerComponent: Component {
- ConnectionHeader {
- icon: root.network?.isSecure ? "lock" : "wifi"
- title: root.network?.ssid ?? qsTr("Unknown")
- }
- }
-
- sections: [
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- SectionHeader {
- title: qsTr("Connection status")
- description: qsTr("Connection settings for this network")
- }
-
- SectionContainer {
- ToggleRow {
- label: qsTr("Connected")
- checked: root.network?.active ?? false
- toggle.onToggled: {
- if (checked) {
- NetworkConnection.handleConnect(root.network, root.session, null);
- } else {
- Nmcli.disconnectFromNetwork();
- }
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- Layout.minimumHeight: Appearance.font.size.normal + Appearance.padding.normal * 2
- visible: {
- if (!root.network || !root.network.ssid) {
- return false;
- }
- return Nmcli.hasSavedProfile(root.network.ssid);
- }
- inactiveColour: Colours.palette.m3secondaryContainer
- inactiveOnColour: Colours.palette.m3onSecondaryContainer
- text: qsTr("Forget Network")
-
- onClicked: {
- if (root.network && root.network.ssid) {
- if (root.network.active) {
- Nmcli.disconnectFromNetwork();
- }
- Nmcli.forgetNetwork(root.network.ssid);
- }
- }
- }
- }
- }
- },
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- SectionHeader {
- title: qsTr("Network properties")
- description: qsTr("Additional information")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.small / 2
-
- PropertyRow {
- label: qsTr("SSID")
- value: root.network?.ssid ?? qsTr("Unknown")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("BSSID")
- value: root.network?.bssid ?? qsTr("Unknown")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Signal strength")
- value: root.network ? qsTr("%1%").arg(root.network.strength) : qsTr("N/A")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Frequency")
- value: root.network ? qsTr("%1 MHz").arg(root.network.frequency) : qsTr("N/A")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Security")
- value: root.network ? (root.network.isSecure ? root.network.security : qsTr("Open")) : qsTr("N/A")
- }
- }
- }
- },
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- SectionHeader {
- title: qsTr("Connection information")
- description: qsTr("Network connection details")
- }
-
- SectionContainer {
- ConnectionInfoSection {
- deviceDetails: Nmcli.wirelessDeviceDetails
- }
- }
- }
- }
- ]
-}
diff --git a/modules/controlcenter/network/WirelessList.qml b/modules/controlcenter/network/WirelessList.qml
deleted file mode 100644
index 57a155f..0000000
--- a/modules/controlcenter/network/WirelessList.qml
+++ /dev/null
@@ -1,228 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import "."
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.components.effects
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import QtQuick
-import QtQuick.Layouts
-
-DeviceList {
- id: root
-
- required property Session session
-
- title: qsTr("Networks (%1)").arg(Nmcli.networks.length)
- description: qsTr("All available WiFi networks")
- activeItem: session.network.active
-
- titleSuffix: Component {
- StyledText {
- visible: Nmcli.scanning
- text: qsTr("Scanning...")
- color: Colours.palette.m3primary
- font.pointSize: Appearance.font.size.small
- }
- }
-
- model: ScriptModel {
- values: [...Nmcli.networks].sort((a, b) => {
- if (a.active !== b.active)
- return b.active - a.active;
- return b.strength - a.strength;
- })
- }
-
- headerComponent: Component {
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Settings")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Item {
- Layout.fillWidth: true
- }
-
- ToggleButton {
- toggled: Nmcli.wifiEnabled
- icon: "wifi"
- accent: "Tertiary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
-
- onClicked: {
- Nmcli.toggleWifi(null);
- }
- }
-
- ToggleButton {
- toggled: Nmcli.scanning
- icon: "wifi_find"
- accent: "Secondary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
-
- onClicked: {
- Nmcli.rescanWifi();
- }
- }
-
- ToggleButton {
- toggled: !root.session.network.active
- icon: "settings"
- accent: "Primary"
- iconSize: Appearance.font.size.normal
- horizontalPadding: Appearance.padding.normal
- verticalPadding: Appearance.padding.smaller
-
- onClicked: {
- if (root.session.network.active)
- root.session.network.active = null;
- else {
- root.session.network.active = root.view.model.get(0)?.modelData ?? null;
- }
- }
- }
- }
- }
-
- delegate: Component {
- StyledRect {
- required property var modelData
-
- width: ListView.view ? ListView.view.width : undefined
-
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, root.activeItem === modelData ? Colours.tPalette.m3surfaceContainer.a : 0)
- radius: Appearance.rounding.normal
-
- StateLayer {
- function onClicked(): void {
- root.session.network.active = modelData;
- if (modelData && modelData.ssid) {
- root.checkSavedProfileForNetwork(modelData.ssid);
- }
- }
- }
-
- RowLayout {
- id: rowLayout
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: icon.implicitHeight + Appearance.padding.normal * 2
-
- radius: Appearance.rounding.normal
- color: modelData.active ? Colours.palette.m3primaryContainer : Colours.tPalette.m3surfaceContainerHigh
-
- MaterialIcon {
- id: icon
-
- anchors.centerIn: parent
- text: Icons.getNetworkIcon(modelData.strength, modelData.isSecure)
- font.pointSize: Appearance.font.size.large
- fill: modelData.active ? 1 : 0
- color: modelData.active ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
- }
- }
-
- ColumnLayout {
- Layout.fillWidth: true
-
- spacing: 0
-
- StyledText {
- Layout.fillWidth: true
- elide: Text.ElideRight
- maximumLineCount: 1
-
- text: modelData.ssid || qsTr("Unknown")
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller
-
- StyledText {
- Layout.fillWidth: true
- text: {
- if (modelData.active)
- return qsTr("Connected");
- if (modelData.isSecure && modelData.security && modelData.security.length > 0) {
- return modelData.security;
- }
- if (modelData.isSecure)
- return qsTr("Secured");
- return qsTr("Open");
- }
- color: modelData.active ? Colours.palette.m3primary : Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- font.weight: modelData.active ? 500 : 400
- elide: Text.ElideRight
- }
- }
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: connectIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.full
- color: Qt.alpha(Colours.palette.m3primaryContainer, modelData.active ? 1 : 0)
-
- StateLayer {
- function onClicked(): void {
- if (modelData.active) {
- Nmcli.disconnectFromNetwork();
- } else {
- NetworkConnection.handleConnect(modelData, root.session, null);
- }
- }
- }
-
- MaterialIcon {
- id: connectIcon
-
- anchors.centerIn: parent
- text: modelData.active ? "link_off" : "link"
- color: modelData.active ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
- }
- }
- }
-
- implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2
- }
- }
-
- onItemSelected: function (item) {
- session.network.active = item;
- if (item && item.ssid) {
- checkSavedProfileForNetwork(item.ssid);
- }
- }
-
- function checkSavedProfileForNetwork(ssid: string): void {
- if (ssid && ssid.length > 0) {
- Nmcli.loadSavedConnections(() => {});
- }
- }
-}
diff --git a/modules/controlcenter/network/WirelessPane.qml b/modules/controlcenter/network/WirelessPane.qml
deleted file mode 100644
index 8150af9..0000000
--- a/modules/controlcenter/network/WirelessPane.qml
+++ /dev/null
@@ -1,57 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.containers
-import qs.config
-import Quickshell.Widgets
-import QtQuick
-
-SplitPaneWithDetails {
- id: root
-
- required property Session session
-
- anchors.fill: parent
-
- activeItem: session.network.active
- paneIdGenerator: function (item) {
- return item ? (item.ssid || item.bssid || "") : "";
- }
-
- leftContent: Component {
- WirelessList {
- session: root.session
- }
- }
-
- rightDetailsComponent: Component {
- WirelessDetails {
- session: root.session
- }
- }
-
- rightSettingsComponent: Component {
- StyledFlickable {
- flickableDirection: Flickable.VerticalFlick
- contentHeight: settingsInner.height
- clip: true
-
- WirelessSettings {
- id: settingsInner
-
- anchors.left: parent.left
- anchors.right: parent.right
- session: root.session
- }
- }
- }
-
- overlayComponent: Component {
- WirelessPasswordDialog {
- anchors.fill: parent
- session: root.session
- }
- }
-}
diff --git a/modules/controlcenter/network/WirelessPasswordDialog.qml b/modules/controlcenter/network/WirelessPasswordDialog.qml
deleted file mode 100644
index 7ad5204..0000000
--- a/modules/controlcenter/network/WirelessPasswordDialog.qml
+++ /dev/null
@@ -1,511 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "."
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property Session session
-
- readonly property var network: {
- if (session.network.pendingNetwork) {
- return session.network.pendingNetwork;
- }
- if (session.network.active) {
- return session.network.active;
- }
- return null;
- }
-
- property bool isClosing: false
- visible: session.network.showPasswordDialog || isClosing
- enabled: session.network.showPasswordDialog && !isClosing
- focus: enabled
-
- Keys.onEscapePressed: {
- closeDialog();
- }
-
- Rectangle {
- anchors.fill: parent
- color: Qt.rgba(0, 0, 0, 0.5)
- opacity: root.session.network.showPasswordDialog && !root.isClosing ? 1 : 0
-
- Behavior on opacity {
- Anim {}
- }
-
- MouseArea {
- anchors.fill: parent
- onClicked: closeDialog()
- }
- }
-
- StyledRect {
- id: dialog
-
- anchors.centerIn: parent
-
- implicitWidth: 400
- implicitHeight: content.implicitHeight + Appearance.padding.large * 2
-
- radius: Appearance.rounding.normal
- color: Colours.tPalette.m3surface
- opacity: root.session.network.showPasswordDialog && !root.isClosing ? 1 : 0
- scale: root.session.network.showPasswordDialog && !root.isClosing ? 1 : 0.7
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {}
- }
-
- ParallelAnimation {
- running: root.isClosing
- onFinished: {
- if (root.isClosing) {
- root.session.network.showPasswordDialog = false;
- root.isClosing = false;
- }
- }
-
- Anim {
- target: dialog
- property: "opacity"
- to: 0
- }
- Anim {
- target: dialog
- property: "scale"
- to: 0.7
- }
- }
-
- Keys.onEscapePressed: closeDialog()
-
- ColumnLayout {
- id: content
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.normal
-
- MaterialIcon {
- Layout.alignment: Qt.AlignHCenter
- text: "lock"
- font.pointSize: Appearance.font.size.extraLarge * 2
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- text: qsTr("Enter password")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- text: root.network ? qsTr("Network: %1").arg(root.network.ssid) : ""
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledText {
- id: statusText
-
- Layout.alignment: Qt.AlignHCenter
- Layout.topMargin: Appearance.spacing.small
- visible: connectButton.connecting || connectButton.hasError
- text: {
- if (connectButton.hasError) {
- return qsTr("Connection failed. Please check your password and try again.");
- }
- if (connectButton.connecting) {
- return qsTr("Connecting...");
- }
- return "";
- }
- color: connectButton.hasError ? Colours.palette.m3error : Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- font.weight: 400
- wrapMode: Text.WordWrap
- Layout.maximumWidth: parent.width - Appearance.padding.large * 2
- }
-
- Item {
- id: passwordContainer
- Layout.topMargin: Appearance.spacing.large
- Layout.fillWidth: true
- implicitHeight: Math.max(48, charList.implicitHeight + Appearance.padding.normal * 2)
-
- focus: true
- Keys.onPressed: event => {
- if (!activeFocus) {
- forceActiveFocus();
- }
-
- if (connectButton.hasError && event.text && event.text.length > 0) {
- connectButton.hasError = false;
- }
-
- if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
- if (connectButton.enabled) {
- connectButton.clicked();
- }
- event.accepted = true;
- } else if (event.key === Qt.Key_Backspace) {
- if (event.modifiers & Qt.ControlModifier) {
- passwordBuffer = "";
- } else {
- passwordBuffer = passwordBuffer.slice(0, -1);
- }
- event.accepted = true;
- } else if (event.text && event.text.length > 0) {
- passwordBuffer += event.text;
- event.accepted = true;
- }
- }
-
- property string passwordBuffer: ""
-
- Connections {
- target: root.session.network
- function onShowPasswordDialogChanged(): void {
- if (root.session.network.showPasswordDialog) {
- Qt.callLater(() => {
- passwordContainer.forceActiveFocus();
- passwordContainer.passwordBuffer = "";
- connectButton.hasError = false;
- });
- }
- }
- }
-
- Connections {
- target: root
- function onVisibleChanged(): void {
- if (root.visible) {
- Qt.callLater(() => {
- passwordContainer.forceActiveFocus();
- });
- }
- }
- }
-
- StyledRect {
- anchors.fill: parent
- radius: Appearance.rounding.normal
- color: passwordContainer.activeFocus ? Qt.lighter(Colours.tPalette.m3surfaceContainer, 1.05) : Colours.tPalette.m3surfaceContainer
- border.width: passwordContainer.activeFocus || connectButton.hasError ? 4 : (root.visible ? 1 : 0)
- border.color: {
- if (connectButton.hasError) {
- return Colours.palette.m3error;
- }
- if (passwordContainer.activeFocus) {
- return Colours.palette.m3primary;
- }
- return root.visible ? Colours.palette.m3outline : "transparent";
- }
-
- Behavior on border.color {
- CAnim {}
- }
-
- Behavior on border.width {
- CAnim {}
- }
-
- Behavior on color {
- CAnim {}
- }
- }
-
- StateLayer {
- hoverEnabled: false
- cursorShape: Qt.IBeamCursor
-
- function onClicked(): void {
- passwordContainer.forceActiveFocus();
- }
- }
-
- StyledText {
- id: placeholder
- anchors.centerIn: parent
- text: qsTr("Password")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.normal
- font.family: Appearance.font.family.mono
- opacity: passwordContainer.passwordBuffer ? 0 : 1
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- ListView {
- id: charList
-
- readonly property int fullWidth: count * (implicitHeight + spacing) - spacing
-
- anchors.centerIn: parent
- implicitWidth: fullWidth
- implicitHeight: Appearance.font.size.normal
-
- orientation: Qt.Horizontal
- spacing: Appearance.spacing.small / 2
- interactive: false
-
- model: ScriptModel {
- values: passwordContainer.passwordBuffer.split("")
- }
-
- delegate: StyledRect {
- id: ch
-
- implicitWidth: implicitHeight
- implicitHeight: charList.implicitHeight
-
- color: Colours.palette.m3onSurface
- radius: Appearance.rounding.small / 2
-
- opacity: 0
- scale: 0
- Component.onCompleted: {
- opacity = 1;
- scale = 1;
- }
- ListView.onRemove: removeAnim.start()
-
- SequentialAnimation {
- id: removeAnim
-
- PropertyAction {
- target: ch
- property: "ListView.delayRemove"
- value: true
- }
- ParallelAnimation {
- Anim {
- target: ch
- property: "opacity"
- to: 0
- }
- Anim {
- target: ch
- property: "scale"
- to: 0.5
- }
- }
- PropertyAction {
- target: ch
- property: "ListView.delayRemove"
- value: false
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
- }
-
- Behavior on implicitWidth {
- Anim {}
- }
- }
- }
-
- RowLayout {
- Layout.topMargin: Appearance.spacing.normal
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- TextButton {
- id: cancelButton
-
- Layout.fillWidth: true
- Layout.minimumHeight: Appearance.font.size.normal + Appearance.padding.normal * 2
- inactiveColour: Colours.palette.m3secondaryContainer
- inactiveOnColour: Colours.palette.m3onSecondaryContainer
- text: qsTr("Cancel")
-
- onClicked: root.closeDialog()
- }
-
- TextButton {
- id: connectButton
-
- property bool connecting: false
- property bool hasError: false
-
- Layout.fillWidth: true
- Layout.minimumHeight: Appearance.font.size.normal + Appearance.padding.normal * 2
- inactiveColour: Colours.palette.m3primary
- inactiveOnColour: Colours.palette.m3onPrimary
- text: qsTr("Connect")
- enabled: passwordContainer.passwordBuffer.length > 0 && !connecting
-
- onClicked: {
- if (!root.network || connecting) {
- return;
- }
-
- const password = passwordContainer.passwordBuffer;
- if (!password || password.length === 0) {
- return;
- }
-
- hasError = false;
- connecting = true;
- enabled = false;
- text = qsTr("Connecting...");
-
- NetworkConnection.connectWithPassword(root.network, password, result => {
- if (result && result.success) {} else if (result && result.needsPassword) {
- connectionMonitor.stop();
- connecting = false;
- hasError = true;
- enabled = true;
- text = qsTr("Connect");
- passwordContainer.passwordBuffer = "";
- if (root.network && root.network.ssid) {
- Nmcli.forgetNetwork(root.network.ssid);
- }
- } else {
- connectionMonitor.stop();
- connecting = false;
- hasError = true;
- enabled = true;
- text = qsTr("Connect");
- passwordContainer.passwordBuffer = "";
- if (root.network && root.network.ssid) {
- Nmcli.forgetNetwork(root.network.ssid);
- }
- }
- });
-
- connectionMonitor.start();
- }
- }
- }
- }
- }
-
- function checkConnectionStatus(): void {
- if (!root.visible || !connectButton.connecting) {
- return;
- }
-
- const isConnected = root.network && Nmcli.active && Nmcli.active.ssid && Nmcli.active.ssid.toLowerCase().trim() === root.network.ssid.toLowerCase().trim();
-
- if (isConnected) {
- connectionSuccessTimer.start();
- return;
- }
-
- if (Nmcli.pendingConnection === null && connectButton.connecting) {
- if (connectionMonitor.repeatCount > 10) {
- connectionMonitor.stop();
- connectButton.connecting = false;
- connectButton.hasError = true;
- connectButton.enabled = true;
- connectButton.text = qsTr("Connect");
- passwordContainer.passwordBuffer = "";
- if (root.network && root.network.ssid) {
- Nmcli.forgetNetwork(root.network.ssid);
- }
- }
- }
- }
-
- Timer {
- id: connectionMonitor
- interval: 1000
- repeat: true
- triggeredOnStart: false
- property int repeatCount: 0
-
- onTriggered: {
- repeatCount++;
- checkConnectionStatus();
- }
-
- onRunningChanged: {
- if (!running) {
- repeatCount = 0;
- }
- }
- }
-
- Timer {
- id: connectionSuccessTimer
- interval: 500
- onTriggered: {
- if (root.visible && Nmcli.active && Nmcli.active.ssid) {
- const stillConnected = Nmcli.active.ssid.toLowerCase().trim() === root.network.ssid.toLowerCase().trim();
- if (stillConnected) {
- connectionMonitor.stop();
- connectButton.connecting = false;
- connectButton.text = qsTr("Connect");
- closeDialog();
- }
- }
- }
- }
-
- Connections {
- target: Nmcli
- function onActiveChanged() {
- if (root.visible) {
- checkConnectionStatus();
- }
- }
- function onConnectionFailed(ssid: string) {
- if (root.visible && root.network && root.network.ssid === ssid && connectButton.connecting) {
- connectionMonitor.stop();
- connectButton.connecting = false;
- connectButton.hasError = true;
- connectButton.enabled = true;
- connectButton.text = qsTr("Connect");
- passwordContainer.passwordBuffer = "";
- Nmcli.forgetNetwork(ssid);
- }
- }
- }
-
- function closeDialog(): void {
- if (isClosing) {
- return;
- }
-
- isClosing = true;
- passwordContainer.passwordBuffer = "";
- connectButton.connecting = false;
- connectButton.hasError = false;
- connectButton.text = qsTr("Connect");
- connectionMonitor.stop();
- }
-}
diff --git a/modules/controlcenter/network/WirelessSettings.qml b/modules/controlcenter/network/WirelessSettings.qml
deleted file mode 100644
index b4eb391..0000000
--- a/modules/controlcenter/network/WirelessSettings.qml
+++ /dev/null
@@ -1,73 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property Session session
-
- spacing: Appearance.spacing.normal
-
- SettingsHeader {
- icon: "wifi"
- title: qsTr("Network settings")
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("WiFi status")
- description: qsTr("General WiFi settings")
- }
-
- SectionContainer {
- ToggleRow {
- label: qsTr("WiFi enabled")
- checked: Nmcli.wifiEnabled
- toggle.onToggled: {
- Nmcli.enableWifi(checked);
- }
- }
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("Network information")
- description: qsTr("Current network connection")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.small / 2
-
- PropertyRow {
- label: qsTr("Connected network")
- value: Nmcli.active ? Nmcli.active.ssid : qsTr("Not connected")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Signal strength")
- value: Nmcli.active ? qsTr("%1%").arg(Nmcli.active.strength) : qsTr("N/A")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Security")
- value: Nmcli.active ? (Nmcli.active.isSecure ? qsTr("Secured") : qsTr("Open")) : qsTr("N/A")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Frequency")
- value: Nmcli.active ? qsTr("%1 MHz").arg(Nmcli.active.frequency) : qsTr("N/A")
- }
- }
-}
diff --git a/modules/controlcenter/state/BluetoothState.qml b/modules/controlcenter/state/BluetoothState.qml
deleted file mode 100644
index 8678672..0000000
--- a/modules/controlcenter/state/BluetoothState.qml
+++ /dev/null
@@ -1,12 +0,0 @@
-import Quickshell.Bluetooth
-import QtQuick
-
-QtObject {
- id: root
-
- property BluetoothDevice active: null
- property BluetoothAdapter currentAdapter: Bluetooth.defaultAdapter
- property bool editingAdapterName: false
- property bool fabMenuOpen: false
- property bool editingDeviceName: false
-}
diff --git a/modules/controlcenter/state/EthernetState.qml b/modules/controlcenter/state/EthernetState.qml
deleted file mode 100644
index 58f5fc8..0000000
--- a/modules/controlcenter/state/EthernetState.qml
+++ /dev/null
@@ -1,7 +0,0 @@
-import QtQuick
-
-QtObject {
- id: root
-
- property var active: null
-}
diff --git a/modules/controlcenter/state/NetworkState.qml b/modules/controlcenter/state/NetworkState.qml
deleted file mode 100644
index f9324c8..0000000
--- a/modules/controlcenter/state/NetworkState.qml
+++ /dev/null
@@ -1,9 +0,0 @@
-import QtQuick
-
-QtObject {
- id: root
-
- property var active: null
- property bool showPasswordDialog: false
- property var pendingNetwork: null
-}
diff --git a/modules/drawers/Backgrounds.qml b/modules/drawers/Backgrounds.qml
index 7fa2ca1..1eed114 100644
--- a/modules/drawers/Backgrounds.qml
+++ b/modules/drawers/Backgrounds.qml
@@ -6,7 +6,6 @@ import qs.modules.session as Session
import qs.modules.launcher as Launcher
import qs.modules.dashboard as Dashboard
import qs.modules.bar.popouts as BarPopouts
-import qs.modules.utilities as Utilities
import qs.modules.sidebar as Sidebar
import QtQuick
import QtQuick.Shapes
@@ -66,14 +65,6 @@ Shape {
startY: wrapper.y - rounding * sideRounding
}
- Utilities.Background {
- wrapper: root.panels.utilities
- sidebar: sidebar
-
- startX: root.width
- startY: root.height
- }
-
Sidebar.Background {
id: sidebar
diff --git a/modules/drawers/Drawers.qml b/modules/drawers/Drawers.qml
index 86c9e99..4ae0b92 100644
--- a/modules/drawers/Drawers.qml
+++ b/modules/drawers/Drawers.qml
@@ -31,7 +31,7 @@ Variants {
readonly property bool hasFullscreen: Hypr.monitorFor(screen)?.activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen === 2) ?? false
readonly property int dragMaskPadding: {
- if (focusGrab.active || panels.popouts.isDetached)
+ if (focusGrab.active)
return 0;
const mon = Hypr.monitorFor(screen);
@@ -140,7 +140,6 @@ Variants {
property bool session
property bool launcher
property bool dashboard
- property bool utilities
property bool sidebar
Component.onCompleted: Visibilities.load(scope.modelData, this)
diff --git a/modules/drawers/Interactions.qml b/modules/drawers/Interactions.qml
index 9579b15..8c026ce 100644
--- a/modules/drawers/Interactions.qml
+++ b/modules/drawers/Interactions.qml
@@ -16,7 +16,6 @@ CustomMouseArea {
property point dragStart
property bool dashboardShortcutActive
property bool osdShortcutActive
- property bool utilitiesShortcutActive
function withinPanelHeight(panel: Item, x: real, y: real): bool {
const panelY = Config.border.thickness + panel.y;
@@ -65,9 +64,6 @@ CustomMouseArea {
if (!dashboardShortcutActive)
visibilities.dashboard = false;
- if (!utilitiesShortcutActive)
- visibilities.utilities = false;
-
if (!popouts.currentName.startsWith("traymenu") || (popouts.current?.depth ?? 0) <= 1) {
popouts.hasCurrent = false;
bar.closeTray();
@@ -79,9 +75,6 @@ CustomMouseArea {
}
onPositionChanged: event => {
- if (popouts.isDetached)
- return;
-
const x = event.x;
const y = event.y;
const dragX = x - dragStart.x;
@@ -187,17 +180,6 @@ CustomMouseArea {
visibilities.dashboard = false;
}
- // Show utilities on hover
- const showUtilities = inBottomPanel(panels.utilities, x, y);
-
- // Always update visibility based on hover if not in shortcut mode
- if (!utilitiesShortcutActive) {
- visibilities.utilities = showUtilities;
- } else if (showUtilities) {
- // If hovering over utilities area while in shortcut mode, transition to hover control
- utilitiesShortcutActive = false;
- }
-
// Show popouts on hover
if (x < bar.implicitWidth) {
bar.checkPopout(y);
@@ -216,7 +198,6 @@ CustomMouseArea {
if (!root.visibilities.launcher) {
root.dashboardShortcutActive = false;
root.osdShortcutActive = false;
- root.utilitiesShortcutActive = false;
// Also hide dashboard and OSD if they're not being hovered
const inDashboardArea = root.inTopPanel(root.panels.dashboard, root.mouseX, root.mouseY);
@@ -257,18 +238,5 @@ CustomMouseArea {
root.osdShortcutActive = false;
}
}
-
- function onUtilitiesChanged() {
- if (root.visibilities.utilities) {
- // Utilities became visible, immediately check if this should be shortcut mode
- const inUtilitiesArea = root.inBottomPanel(root.panels.utilities, root.mouseX, root.mouseY);
- if (!inUtilitiesArea) {
- root.utilitiesShortcutActive = true;
- }
- } else {
- // Utilities hidden, clear shortcut flag
- root.utilitiesShortcutActive = false;
- }
- }
}
}
diff --git a/modules/drawers/Panels.qml b/modules/drawers/Panels.qml
index 7705732..d459a04 100644
--- a/modules/drawers/Panels.qml
+++ b/modules/drawers/Panels.qml
@@ -5,8 +5,7 @@ import qs.modules.session as Session
import qs.modules.launcher as Launcher
import qs.modules.dashboard as Dashboard
import qs.modules.bar.popouts as BarPopouts
-import qs.modules.utilities as Utilities
-import qs.modules.utilities.toasts as Toasts
+import qs.modules.toasts as Toasts
import qs.modules.sidebar as Sidebar
import Quickshell
import QtQuick
@@ -24,7 +23,6 @@ Item {
readonly property alias launcher: launcher
readonly property alias dashboard: dashboard
readonly property alias popouts: popouts
- readonly property alias utilities: utilities
readonly property alias toasts: toasts
readonly property alias sidebar: sidebar
@@ -35,13 +33,13 @@ Item {
Osd.Wrapper {
id: osd
- clip: session.width > 0 || sidebar.width > 0
+ clip: sidebar.width > 0
screen: root.screen
visibilities: root.visibilities
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
- anchors.rightMargin: session.width + sidebar.width
+ anchors.rightMargin: sidebar.width
}
Notifications.Wrapper {
@@ -66,6 +64,7 @@ Item {
anchors.rightMargin: sidebar.width
}
+
Launcher.Wrapper {
id: launcher
@@ -91,11 +90,7 @@ Item {
screen: root.screen
- x: isDetached ? (root.width - nonAnimWidth) / 2 : 0
y: {
- if (isDetached)
- return (root.height - nonAnimHeight) / 2;
-
const off = currentCenter - Config.border.thickness - nonAnimHeight / 2;
const diff = root.height - Math.floor(off + nonAnimHeight);
if (diff < 0)
@@ -104,21 +99,10 @@ Item {
}
}
- Utilities.Wrapper {
- id: utilities
-
- visibilities: root.visibilities
- sidebar: sidebar
- popouts: popouts
-
- anchors.bottom: parent.bottom
- anchors.right: parent.right
- }
-
Toasts.Toasts {
id: toasts
- anchors.bottom: sidebar.visible ? parent.bottom : utilities.top
+ anchors.bottom: parent.bottom
anchors.right: sidebar.left
anchors.margins: Appearance.padding.normal
}
@@ -130,7 +114,6 @@ Item {
panels: root
anchors.top: notifications.bottom
- anchors.bottom: utilities.top
anchors.right: parent.right
}
}
diff --git a/modules/osd/Wrapper.qml b/modules/osd/Wrapper.qml
index 2519609..8cb5066 100644
--- a/modules/osd/Wrapper.qml
+++ b/modules/osd/Wrapper.qml
@@ -13,7 +13,7 @@ Item {
required property var visibilities
property bool hovered
readonly property Brightness.Monitor monitor: Brightness.getMonitorForScreen(root.screen)
- readonly property bool shouldBeActive: visibilities.osd && Config.osd.enabled && !(visibilities.utilities && Config.utilities.enabled)
+ readonly property bool shouldBeActive: visibilities.osd && Config.osd.enabled
property real volume
property bool muted
diff --git a/modules/sidebar/Background.qml b/modules/sidebar/Background.qml
index beefdf5..7300c57 100644
--- a/modules/sidebar/Background.qml
+++ b/modules/sidebar/Background.qml
@@ -15,9 +15,6 @@ ShapePath {
readonly property real notifsWidthDiff: panels.notifications.width - wrapper.width
readonly property real notifsRoundingX: panels.notifications.height > 0 && notifsWidthDiff < rounding * 2 ? notifsWidthDiff / 2 : rounding
- readonly property real utilsWidthDiff: panels.utilities.width - wrapper.width
- readonly property real utilsRoundingX: utilsWidthDiff < rounding * 2 ? utilsWidthDiff / 2 : rounding
-
strokeWidth: -1
fillColor: Colours.palette.m3surface
@@ -35,12 +32,6 @@ ShapePath {
relativeX: 0
relativeY: root.wrapper.height - root.rounding * 2
}
- PathArc {
- relativeX: -root.utilsRoundingX
- relativeY: root.rounding
- radiusX: root.utilsRoundingX
- radiusY: root.rounding
- }
PathLine {
relativeX: root.wrapper.width + root.utilsRoundingX
relativeY: 0
diff --git a/modules/utilities/toasts/ToastItem.qml b/modules/toasts/ToastItem.qml
index f475500..f475500 100644
--- a/modules/utilities/toasts/ToastItem.qml
+++ b/modules/toasts/ToastItem.qml
diff --git a/modules/utilities/toasts/Toasts.qml b/modules/toasts/Toasts.qml
index 2915404..28328f5 100644
--- a/modules/utilities/toasts/Toasts.qml
+++ b/modules/toasts/Toasts.qml
@@ -12,7 +12,7 @@ Item {
readonly property int spacing: Appearance.spacing.small
property bool flag
- implicitWidth: Config.utilities.sizes.toastWidth - Appearance.padding.normal * 2
+ implicitWidth: 430 - Appearance.padding.normal * 2
implicitHeight: {
let h = -spacing;
for (let i = 0; i < repeater.count; i++) {
@@ -34,7 +34,7 @@ Item {
toasts.push(toast);
if (!toast.closed) {
count++;
- if (count > Config.utilities.maxToasts)
+ if (count > 5)
break;
}
}
@@ -57,7 +57,7 @@ Item {
for (let i = 0; i < index; i++)
if (Toaster.toasts[i].closed)
extraHidden++;
- return index >= Config.utilities.maxToasts + extraHidden;
+ return index >= 5 + extraHidden;
}
onPreviewHiddenChanged: {
diff --git a/modules/utilities/Background.qml b/modules/utilities/Background.qml
deleted file mode 100644
index fbce896..0000000
--- a/modules/utilities/Background.qml
+++ /dev/null
@@ -1,55 +0,0 @@
-import qs.components
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Shapes
-
-ShapePath {
- id: root
-
- required property Wrapper wrapper
- required property var sidebar
- readonly property real rounding: Config.border.rounding
- readonly property bool flatten: wrapper.height < rounding * 2
- readonly property real roundingY: flatten ? wrapper.height / 2 : rounding
-
- strokeWidth: -1
- fillColor: Colours.palette.m3surface
-
- PathLine {
- relativeX: -(root.wrapper.width + root.rounding)
- relativeY: 0
- }
- PathArc {
- relativeX: root.rounding
- relativeY: -root.roundingY
- radiusX: root.rounding
- radiusY: Math.min(root.rounding, root.wrapper.height)
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: 0
- relativeY: -(root.wrapper.height - root.roundingY * 2)
- }
- PathArc {
- relativeX: root.sidebar.utilsRoundingX
- relativeY: -root.roundingY
- radiusX: root.sidebar.utilsRoundingX
- radiusY: Math.min(root.rounding, root.wrapper.height)
- }
- PathLine {
- relativeX: root.wrapper.height > 0 ? root.wrapper.width - root.rounding - root.sidebar.utilsRoundingX : root.wrapper.width
- relativeY: 0
- }
- PathArc {
- relativeX: root.rounding
- relativeY: -root.rounding
- radiusX: root.rounding
- radiusY: root.rounding
- direction: PathArc.Counterclockwise
- }
-
- Behavior on fillColor {
- CAnim {}
- }
-}
diff --git a/modules/utilities/Content.qml b/modules/utilities/Content.qml
deleted file mode 100644
index 770a774..0000000
--- a/modules/utilities/Content.qml
+++ /dev/null
@@ -1,27 +0,0 @@
-import "cards"
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property var props
- required property var visibilities
- required property Item popouts
-
- implicitWidth: layout.implicitWidth
- implicitHeight: layout.implicitHeight
-
- ColumnLayout {
- id: layout
-
- anchors.fill: parent
- spacing: Appearance.spacing.normal
-
- Toggles {
- visibilities: root.visibilities
- popouts: root.popouts
- }
- }
-}
diff --git a/modules/utilities/Wrapper.qml b/modules/utilities/Wrapper.qml
deleted file mode 100644
index 455b5fa..0000000
--- a/modules/utilities/Wrapper.qml
+++ /dev/null
@@ -1,92 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.config
-import Quickshell
-import QtQuick
-
-Item {
- id: root
-
- required property var visibilities
- required property Item sidebar
- required property Item popouts
-
- readonly property PersistentProperties props: PersistentProperties {
- reloadableId: "utilities"
- }
- readonly property bool shouldBeActive: visibilities.sidebar || (visibilities.utilities && Config.utilities.enabled && !(visibilities.session && Config.session.enabled))
-
- visible: height > 0
- implicitHeight: 0
- implicitWidth: sidebar.visible ? sidebar.width : Config.utilities.sizes.width
-
- onStateChanged: {
- if (state === "visible" && timer.running) {
- timer.triggered();
- timer.stop();
- }
- }
-
- states: State {
- name: "visible"
- when: root.shouldBeActive
-
- PropertyChanges {
- root.implicitHeight: content.implicitHeight + Appearance.padding.large * 2
- }
- }
-
- transitions: [
- Transition {
- from: ""
- to: "visible"
-
- Anim {
- target: root
- property: "implicitHeight"
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- },
- Transition {
- from: "visible"
- to: ""
-
- Anim {
- target: root
- property: "implicitHeight"
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- ]
-
- Timer {
- id: timer
-
- running: true
- interval: Appearance.anim.durations.extraLarge
- onTriggered: {
- content.active = Qt.binding(() => root.shouldBeActive || root.visible);
- content.visible = true;
- }
- }
-
- Loader {
- id: content
-
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.margins: Appearance.padding.large
-
- visible: false
- active: true
-
- sourceComponent: Content {
- implicitWidth: root.implicitWidth - Appearance.padding.large * 2
- props: root.props
- visibilities: root.visibilities
- popouts: root.popouts
- }
- }
-}
diff --git a/modules/utilities/cards/Toggles.qml b/modules/utilities/cards/Toggles.qml
deleted file mode 100644
index b8aea6a..0000000
--- a/modules/utilities/cards/Toggles.qml
+++ /dev/null
@@ -1,162 +0,0 @@
-import qs.components
-import qs.components.controls
-import qs.services
-import qs.config
-import qs.modules.controlcenter
-import Quickshell
-import Quickshell.Bluetooth
-import QtQuick
-import QtQuick.Layouts
-
-StyledRect {
- id: root
-
- required property var visibilities
- required property Item popouts
-
- readonly property var quickToggles: {
- const seenIds = new Set();
-
- return Config.utilities.quickToggles.filter(item => {
- if (!item.enabled)
- return false;
-
- if (seenIds.has(item.id)) {
- return false;
- }
-
- if (item.id === "vpn") {
- return Config.utilities.vpn.provider.some(p =>
- typeof p === "object" ? (p.enabled === true) : false
- );
- }
-
- seenIds.add(item.id);
- return true;
- });
- }
- readonly property int splitIndex: Math.ceil(quickToggles.length / 2)
- readonly property bool needExtraRow: quickToggles.length > 6
-
- Layout.fillWidth: true
- implicitHeight: layout.implicitHeight + Appearance.padding.large * 2
-
- radius: Appearance.rounding.normal
- color: Colours.tPalette.m3surfaceContainer
-
- ColumnLayout {
- id: layout
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: qsTr("Quick Toggles")
- font.pointSize: Appearance.font.size.normal
- }
-
- ToggleRow {
- rowModel: root.needExtraRow ? root.quickToggles.slice(0, root.splitIndex) : root.quickToggles
- }
-
- ToggleRow {
- visible: root.needExtraRow
- rowModel: root.needExtraRow ? root.quickToggles.slice(root.splitIndex) : []
- }
- }
-
- component ToggleRow: RowLayout {
- property var rowModel: []
-
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- Repeater {
- model: parent.rowModel
-
- delegate: DelegateChooser {
- role: "id"
-
- DelegateChoice {
- roleValue: "wifi"
- delegate: Toggle {
- icon: "wifi"
- checked: Nmcli.wifiEnabled
- onClicked: Nmcli.toggleWifi()
- }
- }
- DelegateChoice {
- roleValue: "bluetooth"
- delegate: Toggle {
- icon: "bluetooth"
- checked: Bluetooth.defaultAdapter?.enabled ?? false
- onClicked: {
- const adapter = Bluetooth.defaultAdapter;
- if (adapter)
- adapter.enabled = !adapter.enabled;
- }
- }
- }
- DelegateChoice {
- roleValue: "mic"
- delegate: Toggle {
- icon: "mic"
- checked: !Audio.sourceMuted
- onClicked: {
- const audio = Audio.source?.audio;
- if (audio)
- audio.muted = !audio.muted;
- }
- }
- }
- DelegateChoice {
- roleValue: "settings"
- delegate: Toggle {
- icon: "settings"
- inactiveOnColour: Colours.palette.m3onSurfaceVariant
- toggle: false
- onClicked: {
- root.visibilities.utilities = false;
- root.popouts.detach("network");
- }
- }
- }
- DelegateChoice {
- roleValue: "dnd"
- delegate: Toggle {
- icon: "notifications_off"
- checked: Notifs.dnd
- onClicked: Notifs.dnd = !Notifs.dnd
- }
- }
- DelegateChoice {
- roleValue: "vpn"
- delegate: Toggle {
- icon: "vpn_key"
- checked: VPN.connected
- enabled: !VPN.connecting
- onClicked: VPN.toggle()
- }
- }
- }
- }
- }
-
- component Toggle: IconButton {
- Layout.fillWidth: true
- Layout.preferredWidth: implicitWidth + (stateLayer.pressed ? Appearance.padding.large : internalChecked ? Appearance.padding.smaller : 0)
- radius: stateLayer.pressed ? Appearance.rounding.small / 2 : internalChecked ? Appearance.rounding.small : Appearance.rounding.normal
- inactiveColour: Colours.layer(Colours.palette.m3surfaceContainerHighest, 2)
- toggle: true
- radiusAnim.duration: Appearance.anim.durations.expressiveFastSpatial
- radiusAnim.easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
-
- Behavior on Layout.preferredWidth {
- Anim {
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
- }
-}
diff --git a/modules/windowinfo/Buttons.qml b/modules/windowinfo/Buttons.qml
deleted file mode 100644
index 89acfe6..0000000
--- a/modules/windowinfo/Buttons.qml
+++ /dev/null
@@ -1,180 +0,0 @@
-import qs.components
-import qs.services
-import qs.config
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property var client
- property bool moveToWsExpanded
-
- anchors.fill: parent
- spacing: Appearance.spacing.small
-
- RowLayout {
- Layout.topMargin: Appearance.padding.large
- Layout.leftMargin: Appearance.padding.large
- Layout.rightMargin: Appearance.padding.large
-
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Move to workspace")
- elide: Text.ElideRight
- }
-
- StyledRect {
- color: Colours.palette.m3primary
- radius: Appearance.rounding.small
-
- implicitWidth: moveToWsIcon.implicitWidth + Appearance.padding.small * 2
- implicitHeight: moveToWsIcon.implicitHeight + Appearance.padding.small
-
- StateLayer {
- color: Colours.palette.m3onPrimary
-
- function onClicked(): void {
- root.moveToWsExpanded = !root.moveToWsExpanded;
- }
- }
-
- MaterialIcon {
- id: moveToWsIcon
-
- anchors.centerIn: parent
-
- animate: true
- text: root.moveToWsExpanded ? "expand_more" : "keyboard_arrow_right"
- color: Colours.palette.m3onPrimary
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-
- WrapperItem {
- Layout.fillWidth: true
- Layout.leftMargin: Appearance.padding.large * 2
- Layout.rightMargin: Appearance.padding.large * 2
-
- Layout.preferredHeight: root.moveToWsExpanded ? implicitHeight : 0
- clip: true
-
- topMargin: Appearance.spacing.normal
- bottomMargin: Appearance.spacing.normal
-
- GridLayout {
- id: wsGrid
-
- rowSpacing: Appearance.spacing.smaller
- columnSpacing: Appearance.spacing.normal
- columns: 5
-
- Repeater {
- model: 10
-
- Button {
- required property int index
- readonly property int wsId: Math.floor((Hypr.activeWsId - 1) / 10) * 10 + index + 1
- readonly property bool isCurrent: root.client?.workspace.id === wsId
-
- color: isCurrent ? Colours.tPalette.m3surfaceContainerHighest : Colours.palette.m3tertiaryContainer
- onColor: isCurrent ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer
- text: wsId
- disabled: isCurrent
-
- function onClicked(): void {
- Hypr.dispatch(`movetoworkspace ${wsId},address:0x${root.client?.address}`);
- }
- }
- }
- }
-
- Behavior on Layout.preferredHeight {
- Anim {}
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- Layout.leftMargin: Appearance.padding.large
- Layout.rightMargin: Appearance.padding.large
- Layout.bottomMargin: Appearance.padding.large
-
- spacing: root.client?.lastIpcObject.floating ? Appearance.spacing.normal : Appearance.spacing.small
-
- Button {
- color: Colours.palette.m3secondaryContainer
- onColor: Colours.palette.m3onSecondaryContainer
- text: root.client?.lastIpcObject.floating ? qsTr("Tile") : qsTr("Float")
-
- function onClicked(): void {
- Hypr.dispatch(`togglefloating address:0x${root.client?.address}`);
- }
- }
-
- Loader {
- active: root.client?.lastIpcObject.floating
- Layout.fillWidth: active
- Layout.leftMargin: active ? 0 : -parent.spacing
- Layout.rightMargin: active ? 0 : -parent.spacing
-
- sourceComponent: Button {
- color: Colours.palette.m3secondaryContainer
- onColor: Colours.palette.m3onSecondaryContainer
- text: root.client?.lastIpcObject.pinned ? qsTr("Unpin") : qsTr("Pin")
-
- function onClicked(): void {
- Hypr.dispatch(`pin address:0x${root.client?.address}`);
- }
- }
- }
-
- Button {
- color: Colours.palette.m3errorContainer
- onColor: Colours.palette.m3onErrorContainer
- text: qsTr("Kill")
-
- function onClicked(): void {
- Hypr.dispatch(`killwindow address:0x${root.client?.address}`);
- }
- }
- }
-
- component Button: StyledRect {
- property color onColor: Colours.palette.m3onSurface
- property alias disabled: stateLayer.disabled
- property alias text: label.text
-
- function onClicked(): void {
- }
-
- radius: Appearance.rounding.small
-
- Layout.fillWidth: true
- implicitHeight: label.implicitHeight + Appearance.padding.small * 2
-
- StateLayer {
- id: stateLayer
-
- color: parent.onColor
-
- function onClicked(): void {
- parent.onClicked();
- }
- }
-
- StyledText {
- id: label
-
- anchors.centerIn: parent
-
- animate: true
- color: parent.onColor
- font.pointSize: Appearance.font.size.normal
- }
- }
-}
diff --git a/modules/windowinfo/Details.qml b/modules/windowinfo/Details.qml
deleted file mode 100644
index f9ee66a..0000000
--- a/modules/windowinfo/Details.qml
+++ /dev/null
@@ -1,164 +0,0 @@
-import qs.components
-import qs.services
-import qs.config
-import Quickshell.Hyprland
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property HyprlandToplevel client
-
- anchors.fill: parent
- spacing: Appearance.spacing.small
-
- Label {
- Layout.topMargin: Appearance.padding.large * 2
-
- text: root.client?.title ?? qsTr("No active client")
- wrapMode: Text.WrapAtWordBoundaryOrAnywhere
-
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- Label {
- text: root.client?.lastIpcObject.class ?? qsTr("No active client")
- color: Colours.palette.m3tertiary
-
- font.pointSize: Appearance.font.size.larger
- }
-
- StyledRect {
- Layout.fillWidth: true
- Layout.preferredHeight: 1
- Layout.leftMargin: Appearance.padding.large * 2
- Layout.rightMargin: Appearance.padding.large * 2
- Layout.topMargin: Appearance.spacing.normal
- Layout.bottomMargin: Appearance.spacing.large
-
- color: Colours.palette.m3secondary
- }
-
- Detail {
- icon: "location_on"
- text: qsTr("Address: %1").arg(`0x${root.client?.address}` ?? "unknown")
- color: Colours.palette.m3primary
- }
-
- Detail {
- icon: "location_searching"
- text: qsTr("Position: %1, %2").arg(root.client?.lastIpcObject.at[0] ?? -1).arg(root.client?.lastIpcObject.at[1] ?? -1)
- }
-
- Detail {
- icon: "resize"
- text: qsTr("Size: %1 x %2").arg(root.client?.lastIpcObject.size[0] ?? -1).arg(root.client?.lastIpcObject.size[1] ?? -1)
- color: Colours.palette.m3tertiary
- }
-
- Detail {
- icon: "workspaces"
- text: qsTr("Workspace: %1 (%2)").arg(root.client?.workspace.name ?? -1).arg(root.client?.workspace.id ?? -1)
- color: Colours.palette.m3secondary
- }
-
- Detail {
- icon: "desktop_windows"
- text: {
- const mon = root.client?.monitor;
- if (mon)
- return qsTr("Monitor: %1 (%2) at %3, %4").arg(mon.name).arg(mon.id).arg(mon.x).arg(mon.y);
- return qsTr("Monitor: unknown");
- }
- }
-
- Detail {
- icon: "page_header"
- text: qsTr("Initial title: %1").arg(root.client?.lastIpcObject.initialTitle ?? "unknown")
- color: Colours.palette.m3tertiary
- }
-
- Detail {
- icon: "category"
- text: qsTr("Initial class: %1").arg(root.client?.lastIpcObject.initialClass ?? "unknown")
- }
-
- Detail {
- icon: "account_tree"
- text: qsTr("Process id: %1").arg(root.client?.lastIpcObject.pid ?? -1)
- color: Colours.palette.m3primary
- }
-
- Detail {
- icon: "picture_in_picture_center"
- text: qsTr("Floating: %1").arg(root.client?.lastIpcObject.floating ? "yes" : "no")
- color: Colours.palette.m3secondary
- }
-
- Detail {
- icon: "gradient"
- text: qsTr("Xwayland: %1").arg(root.client?.lastIpcObject.xwayland ? "yes" : "no")
- }
-
- Detail {
- icon: "keep"
- text: qsTr("Pinned: %1").arg(root.client?.lastIpcObject.pinned ? "yes" : "no")
- color: Colours.palette.m3secondary
- }
-
- Detail {
- icon: "fullscreen"
- text: {
- const fs = root.client?.lastIpcObject.fullscreen;
- if (fs)
- return qsTr("Fullscreen state: %1").arg(fs == 0 ? "off" : fs == 1 ? "maximised" : "on");
- return qsTr("Fullscreen state: unknown");
- }
- color: Colours.palette.m3tertiary
- }
-
- Item {
- Layout.fillHeight: true
- }
-
- component Detail: RowLayout {
- id: detail
-
- required property string icon
- required property string text
- property alias color: icon.color
-
- Layout.leftMargin: Appearance.padding.large
- Layout.rightMargin: Appearance.padding.large
- Layout.fillWidth: true
-
- spacing: Appearance.spacing.smaller
-
- MaterialIcon {
- id: icon
-
- Layout.alignment: Qt.AlignVCenter
- text: detail.icon
- }
-
- StyledText {
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignVCenter
-
- text: detail.text
- elide: Text.ElideRight
- font.pointSize: Appearance.font.size.normal
- }
- }
-
- component Label: StyledText {
- Layout.leftMargin: Appearance.padding.large
- Layout.rightMargin: Appearance.padding.large
- Layout.fillWidth: true
- elide: Text.ElideRight
- horizontalAlignment: Text.AlignHCenter
- animate: true
- }
-}
diff --git a/modules/windowinfo/Preview.qml b/modules/windowinfo/Preview.qml
deleted file mode 100644
index 4cc0aab..0000000
--- a/modules/windowinfo/Preview.qml
+++ /dev/null
@@ -1,96 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import Quickshell
-import Quickshell.Wayland
-import Quickshell.Hyprland
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property ShellScreen screen
- required property HyprlandToplevel client
-
- Layout.preferredWidth: preview.implicitWidth + Appearance.padding.large * 2
- Layout.fillHeight: true
-
- StyledClippingRect {
- id: preview
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.top: parent.top
- anchors.bottom: label.top
- anchors.topMargin: Appearance.padding.large
- anchors.bottomMargin: Appearance.spacing.normal
-
- implicitWidth: view.implicitWidth
-
- color: Colours.tPalette.m3surfaceContainer
- radius: Appearance.rounding.small
-
- Loader {
- anchors.centerIn: parent
- active: !root.client
-
- sourceComponent: ColumnLayout {
- spacing: 0
-
- MaterialIcon {
- Layout.alignment: Qt.AlignHCenter
- text: "web_asset_off"
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.extraLarge * 3
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- text: qsTr("No active client")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- text: qsTr("Try switching to a window")
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-
- ScreencopyView {
- id: view
-
- anchors.centerIn: parent
-
- captureSource: root.client?.wayland ?? null
- live: true
-
- constraintSize.width: root.client ? parent.height * Math.min(root.screen.width / root.screen.height, root.client?.lastIpcObject.size[0] / root.client?.lastIpcObject.size[1]) : parent.height
- constraintSize.height: parent.height
- }
- }
-
- StyledText {
- id: label
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
- anchors.bottomMargin: Appearance.padding.large
-
- animate: true
- text: {
- const client = root.client;
- if (!client)
- return qsTr("No active client");
-
- const mon = client.monitor;
- return qsTr("%1 on monitor %2 at %3, %4").arg(client.title).arg(mon.name).arg(client.lastIpcObject.at[0]).arg(client.lastIpcObject.at[1]);
- }
- }
-}
diff --git a/modules/windowinfo/WindowInfo.qml b/modules/windowinfo/WindowInfo.qml
deleted file mode 100644
index 919b3fb..0000000
--- a/modules/windowinfo/WindowInfo.qml
+++ /dev/null
@@ -1,64 +0,0 @@
-import qs.components
-import qs.services
-import qs.config
-import Quickshell
-import Quickshell.Hyprland
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property ShellScreen screen
- required property HyprlandToplevel client
-
- implicitWidth: child.implicitWidth
- implicitHeight: screen.height * Config.winfo.sizes.heightMult
-
- RowLayout {
- id: child
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.normal
-
- Preview {
- screen: root.screen
- client: root.client
- }
-
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- Layout.preferredWidth: Config.winfo.sizes.detailsWidth
- Layout.fillHeight: true
-
- StyledRect {
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- color: Colours.tPalette.m3surfaceContainer
- radius: Appearance.rounding.normal
-
- Details {
- client: root.client
- }
- }
-
- StyledRect {
- Layout.fillWidth: true
- Layout.preferredHeight: buttons.implicitHeight
-
- color: Colours.tPalette.m3surfaceContainer
- radius: Appearance.rounding.normal
-
- Buttons {
- id: buttons
-
- client: root.client
- }
- }
- }
- }
-}
diff --git a/services/Audio.qml b/services/Audio.qml
index 14d0a4e..3bbd9c6 100644
--- a/services/Audio.qml
+++ b/services/Audio.qml
@@ -101,7 +101,7 @@ Singleton {
const newSinkName = sink.description || sink.name || qsTr("Unknown Device");
- if (previousSinkName && previousSinkName !== newSinkName && Config.utilities.toasts.audioOutputChanged)
+ if (previousSinkName && previousSinkName !== newSinkName && Config.toasts.audioOutputChanged)
Toaster.toast(qsTr("Audio output changed"), qsTr("Now using: %1").arg(newSinkName), "volume_up");
previousSinkName = newSinkName;
@@ -113,7 +113,7 @@ Singleton {
const newSourceName = source.description || source.name || qsTr("Unknown Device");
- if (previousSourceName && previousSourceName !== newSourceName && Config.utilities.toasts.audioInputChanged)
+ if (previousSourceName && previousSourceName !== newSourceName && Config.toasts.audioInputChanged)
Toaster.toast(qsTr("Audio input changed"), qsTr("Now using: %1").arg(newSourceName), "mic");
previousSourceName = newSourceName;
diff --git a/services/Hypr.qml b/services/Hypr.qml
index 77ba264..138b9f2 100644
--- a/services/Hypr.qml
+++ b/services/Hypr.qml
@@ -59,7 +59,7 @@ Singleton {
Component.onCompleted: reloadDynamicConfs()
onCapsLockChanged: {
- if (!Config.utilities.toasts.capsLockChanged)
+ if (!Config.toasts.capsLockChanged)
return;
if (capsLock)
@@ -69,7 +69,7 @@ Singleton {
}
onNumLockChanged: {
- if (!Config.utilities.toasts.numLockChanged)
+ if (!Config.toasts.numLockChanged)
return;
if (numLock)
@@ -79,7 +79,7 @@ Singleton {
}
onKbLayoutFullChanged: {
- if (hadKeyboard && Config.utilities.toasts.kbLayoutChanged)
+ if (hadKeyboard && Config.toasts.kbLayoutChanged)
Toaster.toast(qsTr("Keyboard layout changed"), qsTr("Layout changed to: %1").arg(kbLayoutFull), "keyboard");
hadKeyboard = !!keyboard;
diff --git a/services/Notifs.qml b/services/Notifs.qml
index aff2dfc..a702968 100644
--- a/services/Notifs.qml
+++ b/services/Notifs.qml
@@ -21,7 +21,7 @@ Singleton {
property bool loaded
onDndChanged: {
- if (!Config.utilities.toasts.dndChanged)
+ if (!Config.toasts.dndChanged)
return;
if (dnd)
diff --git a/services/Players.qml b/services/Players.qml
index 1191696..742b4d0 100644
--- a/services/Players.qml
+++ b/services/Players.qml
@@ -24,7 +24,7 @@ Singleton {
target: active
function onPostTrackChanged() {
- if (!Config.utilities.toasts.nowPlaying) {
+ if (!Config.toasts.nowPlaying) {
return;
}
if (active.trackArtist != "" && active.trackTitle != "") {
diff --git a/services/VPN.qml b/services/VPN.qml
deleted file mode 100644
index 2d08631..0000000
--- a/services/VPN.qml
+++ /dev/null
@@ -1,179 +0,0 @@
-pragma Singleton
-
-import Quickshell
-import Quickshell.Io
-import QtQuick
-import qs.config
-import Caelestia
-
-Singleton {
- id: root
-
- property bool connected: false
-
- readonly property bool connecting: connectProc.running || disconnectProc.running
- readonly property bool enabled: Config.utilities.vpn.provider.some(p => typeof p === "object" ? (p.enabled === true) : false)
- readonly property var providerInput: {
- const enabledProvider = Config.utilities.vpn.provider.find(p => typeof p === "object" ? (p.enabled === true) : false);
- return enabledProvider || "wireguard";
- }
- readonly property bool isCustomProvider: typeof providerInput === "object"
- readonly property string providerName: isCustomProvider ? (providerInput.name || "custom") : String(providerInput)
- readonly property string interfaceName: isCustomProvider ? (providerInput.interface || "") : ""
- readonly property var currentConfig: {
- const name = providerName;
- const iface = interfaceName;
- const defaults = getBuiltinDefaults(name, iface);
-
- if (isCustomProvider) {
- const custom = providerInput;
- return {
- connectCmd: custom.connectCmd || defaults.connectCmd,
- disconnectCmd: custom.disconnectCmd || defaults.disconnectCmd,
- interface: custom.interface || defaults.interface,
- displayName: custom.displayName || defaults.displayName
- };
- }
-
- return defaults;
- }
-
- function getBuiltinDefaults(name, iface) {
- const builtins = {
- "wireguard": {
- connectCmd: ["pkexec", "wg-quick", "up", iface],
- disconnectCmd: ["pkexec", "wg-quick", "down", iface],
- interface: iface,
- displayName: iface
- },
- "warp": {
- connectCmd: ["warp-cli", "connect"],
- disconnectCmd: ["warp-cli", "disconnect"],
- interface: "CloudflareWARP",
- displayName: "Warp"
- },
- "netbird": {
- connectCmd: ["netbird", "up"],
- disconnectCmd: ["netbird", "down"],
- interface: "wt0",
- displayName: "NetBird"
- },
- "tailscale": {
- connectCmd: ["tailscale", "up"],
- disconnectCmd: ["tailscale", "down"],
- interface: "tailscale0",
- displayName: "Tailscale"
- }
- };
-
- return builtins[name] || {
- connectCmd: [name, "up"],
- disconnectCmd: [name, "down"],
- interface: iface || name,
- displayName: name
- };
- }
-
- function connect(): void {
- if (!connected && !connecting && root.currentConfig && root.currentConfig.connectCmd) {
- connectProc.exec(root.currentConfig.connectCmd);
- }
- }
-
- function disconnect(): void {
- if (connected && !connecting && root.currentConfig && root.currentConfig.disconnectCmd) {
- disconnectProc.exec(root.currentConfig.disconnectCmd);
- }
- }
-
- function toggle(): void {
- if (connected) {
- disconnect();
- } else {
- connect();
- }
- }
-
- function checkStatus(): void {
- if (root.enabled) {
- statusProc.running = true;
- }
- }
-
- onConnectedChanged: {
- if (!Config.utilities.toasts.vpnChanged)
- return;
-
- const displayName = root.currentConfig ? (root.currentConfig.displayName || "VPN") : "VPN";
- if (connected) {
- Toaster.toast(qsTr("VPN connected"), qsTr("Connected to %1").arg(displayName), "vpn_key");
- } else {
- Toaster.toast(qsTr("VPN disconnected"), qsTr("Disconnected from %1").arg(displayName), "vpn_key_off");
- }
- }
-
- Component.onCompleted: root.enabled && statusCheckTimer.start()
-
- Process {
- id: nmMonitor
-
- running: root.enabled
- command: ["nmcli", "monitor"]
- stdout: SplitParser {
- onRead: statusCheckTimer.restart()
- }
- }
-
- Process {
- id: statusProc
-
- command: ["ip", "link", "show"]
- environment: ({
- LANG: "C.UTF-8",
- LC_ALL: "C.UTF-8"
- })
- stdout: StdioCollector {
- onStreamFinished: {
- const iface = root.currentConfig ? root.currentConfig.interface : "";
- root.connected = iface && text.includes(iface + ":");
- }
- }
- }
-
- Process {
- id: connectProc
-
- onExited: statusCheckTimer.start()
- stderr: StdioCollector {
- onStreamFinished: {
- const error = text.trim();
- if (error && !error.includes("[#]") && !error.includes("already exists")) {
- console.warn("VPN connection error:", error);
- } else if (error.includes("already exists")) {
- root.connected = true;
- }
- }
- }
- }
-
- Process {
- id: disconnectProc
-
- onExited: statusCheckTimer.start()
- stderr: StdioCollector {
- onStreamFinished: {
- const error = text.trim();
- if (error && !error.includes("[#]")) {
- console.warn("VPN disconnection error:", error);
- }
- }
- }
- }
-
- Timer {
- id: statusCheckTimer
-
- interval: 500
- onTriggered: root.checkStatus()
- }
-}