diff options
| author | Freya Murphy <freya@freyacat.org> | 2026-03-16 17:07:54 -0400 |
|---|---|---|
| committer | Freya Murphy <freya@freyacat.org> | 2026-03-16 17:07:54 -0400 |
| commit | bb6717666a669aa81cda28896ed292ca5af55ece (patch) | |
| tree | 5f3c5fed20fd3bf8fe38e10d7e09b81558c64a79 | |
| parent | add date to clock (diff) | |
| download | caelestia-shell-bb6717666a669aa81cda28896ed292ca5af55ece.tar.gz caelestia-shell-bb6717666a669aa81cda28896ed292ca5af55ece.tar.bz2 caelestia-shell-bb6717666a669aa81cda28896ed292ca5af55ece.zip | |
change things
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() - } -} |