chore: fix prop order

This commit is contained in:
2 * r + 2 * t 2026-03-20 16:03:18 +11:00
parent 72e534bad8
commit 796c2e4e76
73 changed files with 609 additions and 584 deletions

View file

@ -53,6 +53,7 @@ ColumnLayout {
rotation: root.expanded ? 180 : 0 rotation: root.expanded ? 180 : 0
color: Colours.palette.m3onSurfaceVariant color: Colours.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.normal font.pointSize: Appearance.font.size.normal
Behavior on rotation { Behavior on rotation {
Anim { Anim {
duration: Appearance.anim.durations.small duration: Appearance.anim.durations.small

View file

@ -36,24 +36,6 @@ ScrollBar {
} }
} }
// Sync nonAnimPosition with flickable when not animating
Connections {
target: flickable
function onContentYChanged() {
if (!animating && !fullMouse.pressed) {
_updatingFromFlickable = true;
const contentHeight = flickable.contentHeight;
const height = flickable.height;
if (contentHeight > height) {
nonAnimPosition = Math.max(0, Math.min(1, flickable.contentY / (contentHeight - height)));
} else {
nonAnimPosition = 0;
}
_updatingFromFlickable = false;
}
}
}
Component.onCompleted: { Component.onCompleted: {
if (flickable) { if (flickable) {
const contentHeight = flickable.contentHeight; const contentHeight = flickable.contentHeight;
@ -96,15 +78,34 @@ ScrollBar {
} }
} }
// Sync nonAnimPosition with flickable when not animating
Connections { Connections {
target: root.flickable function onContentYChanged() {
if (!animating && !fullMouse.pressed) {
_updatingFromFlickable = true;
const contentHeight = flickable.contentHeight;
const height = flickable.height;
if (contentHeight > height) {
nonAnimPosition = Math.max(0, Math.min(1, flickable.contentY / (contentHeight - height)));
} else {
nonAnimPosition = 0;
}
_updatingFromFlickable = false;
}
}
target: flickable
}
Connections {
function onMovingChanged(): void { function onMovingChanged(): void {
if (root.flickable.moving) if (root.flickable.moving)
root.shouldBeActive = true; root.shouldBeActive = true;
else else
hideDelay.restart(); hideDelay.restart();
} }
target: root.flickable
} }
Timer { Timer {

View file

@ -28,8 +28,6 @@ TextField {
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
Connections { Connections {
target: root
function onCursorPositionChanged(): void { function onCursorPositionChanged(): void {
if (root.activeFocus && root.cursorVisible) { if (root.activeFocus && root.cursorVisible) {
cursor.opacity = 1; cursor.opacity = 1;
@ -37,6 +35,8 @@ TextField {
enableBlink.restart(); enableBlink.restart();
} }
} }
target: root
} }
Timer { Timer {

View file

@ -18,31 +18,30 @@ StyledRect {
property real horizontalPadding: Appearance.padding.large property real horizontalPadding: Appearance.padding.large
property real verticalPadding: Appearance.padding.normal property real verticalPadding: Appearance.padding.normal
property string tooltip: "" property string tooltip: ""
property bool hovered: false property bool hovered: false
signal clicked signal clicked
Component.onCompleted: { Component.onCompleted: {
hovered = toggleStateLayer.containsMouse; hovered = toggleStateLayer.containsMouse;
} }
Layout.preferredWidth: implicitWidth + (toggleStateLayer.pressed ? Appearance.padding.normal * 2 : toggled ? Appearance.padding.small * 2 : 0)
implicitWidth: toggleBtnInner.implicitWidth + horizontalPadding * 2
implicitHeight: toggleBtnIcon.implicitHeight + verticalPadding * 2
radius: toggled || toggleStateLayer.pressed ? Appearance.rounding.small : Math.min(width, height) / 2 * Math.min(1, Appearance.rounding.scale)
color: toggled ? Colours.palette[`m3${accent.toLowerCase()}`] : Colours.palette[`m3${accent.toLowerCase()}Container`]
Connections { Connections {
target: toggleStateLayer
function onContainsMouseChanged() { function onContainsMouseChanged() {
const newHovered = toggleStateLayer.containsMouse; const newHovered = toggleStateLayer.containsMouse;
if (hovered !== newHovered) { if (hovered !== newHovered) {
hovered = newHovered; hovered = newHovered;
} }
} }
target: toggleStateLayer
} }
Layout.preferredWidth: implicitWidth + (toggleStateLayer.pressed ? Appearance.padding.normal * 2 : toggled ? Appearance.padding.small * 2 : 0)
implicitWidth: toggleBtnInner.implicitWidth + horizontalPadding * 2
implicitHeight: toggleBtnIcon.implicitHeight + verticalPadding * 2
radius: toggled || toggleStateLayer.pressed ? Appearance.rounding.small : Math.min(width, height) / 2 * Math.min(1, Appearance.rounding.scale)
color: toggled ? Colours.palette[`m3${accent.toLowerCase()}`] : Colours.palette[`m3${accent.toLowerCase()}Container`]
StateLayer { StateLayer {
id: toggleStateLayer id: toggleStateLayer

View file

@ -90,23 +90,9 @@ Popup {
Qt.callLater(updatePosition); Qt.callLater(updatePosition);
} }
} }
Connections { Component.onCompleted: {
target: root.target if (tooltipVisible) {
function onXChanged() { updatePosition();
if (root.tooltipVisible)
root.updatePosition();
}
function onYChanged() {
if (root.tooltipVisible)
root.updatePosition();
}
function onWidthChanged() {
if (root.tooltipVisible)
root.updatePosition();
}
function onHeightChanged() {
if (root.tooltipVisible)
root.updatePosition();
} }
} }
@ -130,24 +116,6 @@ Popup {
} }
} }
// Monitor hover state
Connections {
target: root.target
function onHoveredChanged() {
if (target.hovered) {
showTimer.start();
if (timeout > 0) {
hideTimer.stop();
hideTimer.start();
}
} else {
showTimer.stop();
hideTimer.stop();
tooltipVisible = false;
}
}
}
contentItem: StyledRect { contentItem: StyledRect {
id: tooltipRect id: tooltipRect
@ -177,9 +145,43 @@ Popup {
} }
} }
Component.onCompleted: { Connections {
if (tooltipVisible) { function onXChanged() {
updatePosition(); if (root.tooltipVisible)
root.updatePosition();
} }
function onYChanged() {
if (root.tooltipVisible)
root.updatePosition();
}
function onWidthChanged() {
if (root.tooltipVisible)
root.updatePosition();
}
function onHeightChanged() {
if (root.tooltipVisible)
root.updatePosition();
}
target: root.target
}
// Monitor hover state
Connections {
function onHoveredChanged() {
if (target.hovered) {
showTimer.start();
if (timeout > 0) {
hideTimer.stop();
hideTimer.start();
}
} else {
showTimer.stop();
hideTimer.stop();
tooltipVisible = false;
}
}
target: root.target
} }
} }

View file

@ -80,12 +80,12 @@ Item {
anchors.bottomMargin: Appearance.padding.normal - Appearance.padding.small anchors.bottomMargin: Appearance.padding.normal - Appearance.padding.small
Connections { Connections {
target: root
function onCurrentItemChanged(): void { function onCurrentItemChanged(): void {
if (root.currentItem) if (root.currentItem)
content.text = qsTr(`"%1" selected`).arg(root.currentItem.modelData.name); content.text = qsTr(`"%1" selected`).arg(root.currentItem.modelData.name);
} }
target: root
} }
} }
} }

View file

@ -129,16 +129,16 @@ Item {
clip: true clip: true
StateLayer { StateLayer {
function onClicked(): void {
view.currentIndex = item.index;
}
onDoubleClicked: { onDoubleClicked: {
if (item.modelData.isDir) if (item.modelData.isDir)
root.dialog.cwd.push(item.modelData.name); root.dialog.cwd.push(item.modelData.name);
else if (root.dialog.selectionValid) else if (root.dialog.selectionValid)
root.dialog.accepted(item.modelData.path); root.dialog.accepted(item.modelData.path);
} }
function onClicked(): void {
view.currentIndex = item.index;
}
} }
CachingIconImage { CachingIconImage {

View file

@ -12,11 +12,11 @@ Image {
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
Connections { Connections {
target: QsWindow.window
function onDevicePixelRatioChanged(): void { function onDevicePixelRatioChanged(): void {
manager.updateSource(); manager.updateSource();
} }
target: QsWindow.window
} }
CachingImageManager { CachingImageManager {

View file

@ -10,8 +10,6 @@ Scope {
readonly property list<var> warnLevels: [...Config.general.battery.warnLevels].sort((a, b) => b.level - a.level) readonly property list<var> warnLevels: [...Config.general.battery.warnLevels].sort((a, b) => b.level - a.level)
Connections { Connections {
target: UPower
function onOnBatteryChanged(): void { function onOnBatteryChanged(): void {
if (UPower.onBattery) { if (UPower.onBattery) {
if (Config.utilities.toasts.chargingChanged) if (Config.utilities.toasts.chargingChanged)
@ -23,11 +21,11 @@ Scope {
level.warned = false; level.warned = false;
} }
} }
target: UPower
} }
Connections { Connections {
target: UPower.displayDevice
function onPercentageChanged(): void { function onPercentageChanged(): void {
if (!UPower.onBattery) if (!UPower.onBattery)
return; return;
@ -45,6 +43,8 @@ Scope {
hibernateTimer.start(); hibernateTimer.start();
} }
} }
target: UPower.displayDevice
} }
Timer { Timer {

View file

@ -93,8 +93,6 @@ Scope {
} }
IpcHandler { IpcHandler {
target: "drawers"
function toggle(drawer: string): void { function toggle(drawer: string): void {
if (list().split("\n").includes(drawer)) { if (list().split("\n").includes(drawer)) {
if (root.hasFullscreen && ["launcher", "session", "dashboard"].includes(drawer)) if (root.hasFullscreen && ["launcher", "session", "dashboard"].includes(drawer))
@ -110,19 +108,19 @@ Scope {
const visibilities = Visibilities.getForActive(); const visibilities = Visibilities.getForActive();
return Object.keys(visibilities).filter(k => typeof visibilities[k] === "boolean").join("\n"); return Object.keys(visibilities).filter(k => typeof visibilities[k] === "boolean").join("\n");
} }
target: "drawers"
} }
IpcHandler { IpcHandler {
target: "controlCenter"
function open(): void { function open(): void {
WindowFactory.create(); WindowFactory.create();
} }
target: "controlCenter"
} }
IpcHandler { IpcHandler {
target: "toaster"
function info(title: string, message: string, icon: string): void { function info(title: string, message: string, icon: string): void {
Toaster.toast(title, message, icon, Toast.Info); Toaster.toast(title, message, icon, Toast.Info);
} }
@ -138,5 +136,7 @@ Scope {
function error(title: string, message: string, icon: string): void { function error(title: string, message: string, icon: string): void {
Toaster.toast(title, message, icon, Toast.Error); Toaster.toast(title, message, icon, Toast.Error);
} }
target: "toaster"
} }
} }

View file

@ -48,8 +48,6 @@ Scope {
} }
IpcHandler { IpcHandler {
target: "picker"
function open(): void { function open(): void {
root.freeze = false; root.freeze = false;
root.closing = false; root.closing = false;
@ -77,6 +75,8 @@ Scope {
root.clipboardOnly = true; root.clipboardOnly = true;
root.activeAsync = true; root.activeAsync = true;
} }
target: "picker"
} }
CustomShortcut { CustomShortcut {

View file

@ -68,6 +68,7 @@ Loader {
states: [ states: [
State { State {
name: "top-left" name: "top-left"
AnchorChanges { AnchorChanges {
target: clockLoader target: clockLoader
anchors.top: parent.top anchors.top: parent.top
@ -76,6 +77,7 @@ Loader {
}, },
State { State {
name: "top-center" name: "top-center"
AnchorChanges { AnchorChanges {
target: clockLoader target: clockLoader
anchors.top: parent.top anchors.top: parent.top
@ -84,6 +86,7 @@ Loader {
}, },
State { State {
name: "top-right" name: "top-right"
AnchorChanges { AnchorChanges {
target: clockLoader target: clockLoader
anchors.top: parent.top anchors.top: parent.top
@ -92,6 +95,7 @@ Loader {
}, },
State { State {
name: "middle-left" name: "middle-left"
AnchorChanges { AnchorChanges {
target: clockLoader target: clockLoader
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -100,6 +104,7 @@ Loader {
}, },
State { State {
name: "middle-center" name: "middle-center"
AnchorChanges { AnchorChanges {
target: clockLoader target: clockLoader
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -108,6 +113,7 @@ Loader {
}, },
State { State {
name: "middle-right" name: "middle-right"
AnchorChanges { AnchorChanges {
target: clockLoader target: clockLoader
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
@ -116,6 +122,7 @@ Loader {
}, },
State { State {
name: "bottom-left" name: "bottom-left"
AnchorChanges { AnchorChanges {
target: clockLoader target: clockLoader
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -124,6 +131,7 @@ Loader {
}, },
State { State {
name: "bottom-center" name: "bottom-center"
AnchorChanges { AnchorChanges {
target: clockLoader target: clockLoader
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -132,6 +140,7 @@ Loader {
}, },
State { State {
name: "bottom-right" name: "bottom-right"
AnchorChanges { AnchorChanges {
target: clockLoader target: clockLoader
anchors.bottom: parent.bottom anchors.bottom: parent.bottom

View file

@ -14,16 +14,15 @@ Item {
StateLayer { StateLayer {
// Cursed workaround to make the height larger than the parent // Cursed workaround to make the height larger than the parent
function onClicked(): void {
root.visibilities.session = !root.visibilities.session;
}
anchors.fill: undefined anchors.fill: undefined
anchors.centerIn: parent anchors.centerIn: parent
implicitWidth: implicitHeight implicitWidth: implicitHeight
implicitHeight: icon.implicitHeight + Appearance.padding.small * 2 implicitHeight: icon.implicitHeight + Appearance.padding.small * 2
radius: Appearance.rounding.full radius: Appearance.rounding.full
function onClicked(): void {
root.visibilities.session = !root.visibilities.session;
}
} }
MaterialIcon { MaterialIcon {

View file

@ -13,18 +13,17 @@ Item {
StateLayer { StateLayer {
// Cursed workaround to make the height larger than the parent // 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 { function onClicked(): void {
WindowFactory.create(null, { WindowFactory.create(null, {
active: "network" active: "network"
}); });
} }
anchors.fill: undefined
anchors.centerIn: parent
implicitWidth: implicitHeight
implicitHeight: icon.implicitHeight + Appearance.padding.small * 2
radius: Appearance.rounding.full
} }
MaterialIcon { MaterialIcon {

View file

@ -13,18 +13,17 @@ Item {
StateLayer { StateLayer {
// Cursed workaround to make the height larger than the parent // 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 { function onClicked(): void {
WindowFactory.create(null, { WindowFactory.create(null, {
active: "network" active: "network"
}); });
} }
anchors.fill: undefined
anchors.centerIn: parent
implicitWidth: implicitHeight
implicitHeight: icon.implicitHeight + Appearance.padding.small * 2
radius: Appearance.rounding.full
} }
MaterialIcon { MaterialIcon {

View file

@ -134,8 +134,6 @@ Item {
// Hacky thing cause modelData gets destroyed before the remove anim finishes // Hacky thing cause modelData gets destroyed before the remove anim finishes
Connections { Connections {
target: ws.modelData
function onIdChanged(): void { function onIdChanged(): void {
if (ws.modelData) if (ws.modelData)
ws.wsId = ws.modelData.id; ws.wsId = ws.modelData.id;
@ -150,15 +148,17 @@ Item {
if (ws.modelData) if (ws.modelData)
ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0; ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0;
} }
target: ws.modelData
} }
Connections { Connections {
target: Config.bar.workspaces
function onShowWindowsOnSpecialWorkspacesChanged(): void { function onShowWindowsOnSpecialWorkspacesChanged(): void {
if (ws.modelData) if (ws.modelData)
ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0; ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0;
} }
target: Config.bar.workspaces
} }
Loader { Loader {

View file

@ -63,7 +63,6 @@ Item {
} }
Connections { Connections {
target: root.wrapper
function onCurrentNameChanged() { function onCurrentNameChanged() {
// Update network immediately when password popout becomes active // Update network immediately when password popout becomes active
if (root.wrapper.currentName === "wirelesspassword") { if (root.wrapper.currentName === "wirelesspassword") {
@ -81,10 +80,11 @@ Item {
}, 100); }, 100);
} }
} }
target: root.wrapper
} }
Connections { Connections {
target: networkPopout
function onItemChanged() { function onItemChanged() {
// When network popout loads, update password popout if it's active // When network popout loads, update password popout if it's active
if (root.wrapper.currentName === "wirelesspassword" && passwordPopout.item) { if (root.wrapper.currentName === "wirelesspassword" && passwordPopout.item) {
@ -95,6 +95,8 @@ Item {
}); });
} }
} }
target: networkPopout
} }
} }
@ -144,14 +146,14 @@ Item {
sourceComponent: trayMenuComp sourceComponent: trayMenuComp
Connections { Connections {
target: root.wrapper
function onHasCurrentChanged(): void { function onHasCurrentChanged(): void {
if (root.wrapper.hasCurrent && trayMenu.shouldBeActive) { if (root.wrapper.hasCurrent && trayMenu.shouldBeActive) {
trayMenu.sourceComponent = null; trayMenu.sourceComponent = null;
trayMenu.sourceComponent = trayMenuComp; trayMenu.sourceComponent = trayMenuComp;
} }
} }
target: root.wrapper
} }
Component { Component {

View file

@ -334,8 +334,6 @@ ColumnLayout {
} }
Connections { Connections {
target: Nmcli
function onActiveChanged(): void { function onActiveChanged(): void {
if (Nmcli.active && root.connectingToSsid === Nmcli.active.ssid) { if (Nmcli.active && root.connectingToSsid === Nmcli.active.ssid) {
root.connectingToSsid = ""; root.connectingToSsid = "";
@ -354,10 +352,11 @@ ColumnLayout {
if (!Nmcli.scanning) if (!Nmcli.scanning)
scanIcon.rotation = 0; scanIcon.rotation = 0;
} }
target: Nmcli
} }
Connections { Connections {
target: root.wrapper
function onCurrentNameChanged(): void { function onCurrentNameChanged(): void {
// Clear password network when leaving password dialog // Clear password network when leaving password dialog
if (root.wrapper.currentName !== "wirelesspassword" && root.showPasswordDialog) { if (root.wrapper.currentName !== "wirelesspassword" && root.showPasswordDialog) {
@ -365,6 +364,8 @@ ColumnLayout {
root.passwordNetwork = null; root.passwordNetwork = null;
} }
} }
target: root.wrapper
} }
component Toggle: RowLayout { component Toggle: RowLayout {

View file

@ -69,43 +69,9 @@ ColumnLayout {
} }
} }
Connections {
target: root.wrapper
function onCurrentNameChanged() {
if (root.wrapper.currentName === "wirelesspassword") {
// Update network when popout becomes active
Qt.callLater(() => {
// Try to get network from parent Content's networkPopout
const content = root.parent?.parent?.parent;
if (content) {
const networkPopout = content.children.find(c => c.name === "network");
if (networkPopout && networkPopout.item) {
root.network = networkPopout.item.passwordNetwork;
}
}
// Force focus to password container when popout becomes active
// Use Timer for actual delay to ensure dialog is fully rendered
focusTimer.start();
});
}
}
}
Timer {
id: focusTimer
interval: 150
onTriggered: {
root.forceActiveFocus();
passwordContainer.forceActiveFocus();
}
}
spacing: Appearance.spacing.normal spacing: Appearance.spacing.normal
implicitWidth: 400 implicitWidth: 400
implicitHeight: content.implicitHeight + Appearance.padding.large * 2 implicitHeight: content.implicitHeight + Appearance.padding.large * 2
visible: shouldBeVisible || isClosing visible: shouldBeVisible || isClosing
enabled: shouldBeVisible && !isClosing enabled: shouldBeVisible && !isClosing
focus: enabled focus: enabled
@ -126,16 +92,49 @@ ColumnLayout {
Keys.onEscapePressed: closeDialog() Keys.onEscapePressed: closeDialog()
Connections {
function onCurrentNameChanged() {
if (root.wrapper.currentName === "wirelesspassword") {
// Update network when popout becomes active
Qt.callLater(() => {
// Try to get network from parent Content's networkPopout
const content = root.parent?.parent?.parent;
if (content) {
const networkPopout = content.children.find(c => c.name === "network");
if (networkPopout && networkPopout.item) {
root.network = networkPopout.item.passwordNetwork;
}
}
// Force focus to password container when popout becomes active
// Use Timer for actual delay to ensure dialog is fully rendered
focusTimer.start();
});
}
}
target: root.wrapper
}
Timer {
id: focusTimer
interval: 150
onTriggered: {
root.forceActiveFocus();
passwordContainer.forceActiveFocus();
}
}
StyledRect { StyledRect {
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredWidth: 400 Layout.preferredWidth: 400
implicitHeight: content.implicitHeight + Appearance.padding.large * 2 implicitHeight: content.implicitHeight + Appearance.padding.large * 2
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
color: Colours.tPalette.m3surfaceContainer color: Colours.tPalette.m3surfaceContainer
visible: root.shouldBeVisible || root.isClosing visible: root.shouldBeVisible || root.isClosing
opacity: root.shouldBeVisible && !root.isClosing ? 1 : 0 opacity: root.shouldBeVisible && !root.isClosing ? 1 : 0
scale: root.shouldBeVisible && !root.isClosing ? 1 : 0.7 scale: root.shouldBeVisible && !root.isClosing ? 1 : 0.7
Keys.onEscapePressed: root.closeDialog()
Behavior on opacity { Behavior on opacity {
Anim {} Anim {}
@ -165,8 +164,6 @@ ColumnLayout {
} }
} }
Keys.onEscapePressed: root.closeDialog()
ColumnLayout { ColumnLayout {
id: content id: content
@ -208,10 +205,11 @@ ColumnLayout {
} }
Timer { Timer {
property int attempts: 0
interval: 50 interval: 50
running: root.shouldBeVisible && (!root.network || !root.network.ssid) running: root.shouldBeVisible && (!root.network || !root.network.ssid)
repeat: true repeat: true
property int attempts: 0
onTriggered: { onTriggered: {
attempts++; attempts++;
// Keep trying to get network from Network component // Keep trying to get network from Network component
@ -260,16 +258,15 @@ ColumnLayout {
FocusScope { FocusScope {
id: passwordContainer id: passwordContainer
property string passwordBuffer: ""
objectName: "passwordContainer" objectName: "passwordContainer"
Layout.topMargin: Appearance.spacing.large Layout.topMargin: Appearance.spacing.large
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: Math.max(48, charList.implicitHeight + Appearance.padding.normal * 2) implicitHeight: Math.max(48, charList.implicitHeight + Appearance.padding.normal * 2)
focus: true focus: true
activeFocusOnTab: true activeFocusOnTab: true
property string passwordBuffer: ""
Keys.onPressed: event => { Keys.onPressed: event => {
// Ensure we have focus when receiving keyboard input // Ensure we have focus when receiving keyboard input
if (!activeFocus) { if (!activeFocus) {
@ -300,7 +297,6 @@ ColumnLayout {
} }
Connections { Connections {
target: root
function onShouldBeVisibleChanged(): void { function onShouldBeVisibleChanged(): void {
if (root.shouldBeVisible) { if (root.shouldBeVisible) {
// Use Timer for actual delay to ensure focus works correctly // Use Timer for actual delay to ensure focus works correctly
@ -309,6 +305,8 @@ ColumnLayout {
connectButton.hasError = false; connectButton.hasError = false;
} }
} }
target: root
} }
Timer { Timer {
@ -549,10 +547,11 @@ ColumnLayout {
Timer { Timer {
id: connectionMonitor id: connectionMonitor
property int repeatCount: 0
interval: 1000 interval: 1000
repeat: true repeat: true
triggeredOnStart: false triggeredOnStart: false
property int repeatCount: 0
onTriggered: { onTriggered: {
repeatCount++; repeatCount++;
@ -589,12 +588,12 @@ ColumnLayout {
} }
Connections { Connections {
target: Nmcli
function onActiveChanged() { function onActiveChanged() {
if (root.shouldBeVisible) { if (root.shouldBeVisible) {
root.checkConnectionStatus(); root.checkConnectionStatus();
} }
} }
function onConnectionFailed(ssid: string) { function onConnectionFailed(ssid: string) {
if (root.shouldBeVisible && root.network && root.network.ssid === ssid && connectButton.connecting) { if (root.shouldBeVisible && root.network && root.network.ssid === ssid && connectButton.connecting) {
connectionMonitor.stop(); connectionMonitor.stop();
@ -607,5 +606,7 @@ ColumnLayout {
Nmcli.forgetNetwork(ssid); Nmcli.forgetNetwork(ssid);
} }
} }
target: Nmcli
} }
} }

View file

@ -124,12 +124,12 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
sourceComponent: ControlCenter { sourceComponent: ControlCenter {
screen: root.screen
active: root.queuedMode
function close(): void { function close(): void {
root.close(); root.close();
} }
screen: root.screen
active: root.queuedMode
} }
} }

View file

@ -89,11 +89,12 @@ ColumnLayout {
delegate: Item { delegate: Item {
required property int layoutIndex required property int layoutIndex
required property string label required property string label
readonly property bool isDisabled: layoutIndex > 3
width: list.width width: list.width
height: Math.max(36, rowText.implicitHeight + Appearance.padding.small * 2) height: Math.max(36, rowText.implicitHeight + Appearance.padding.small * 2)
ToolTip.visible: isDisabled && layer.containsMouse
readonly property bool isDisabled: layoutIndex > 3 ToolTip.text: "XKB limitation: maximum 4 layouts allowed"
StateLayer { StateLayer {
id: layer id: layer
@ -107,7 +108,6 @@ ColumnLayout {
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitHeight: parent.height - 4 implicitHeight: parent.height - 4
radius: Appearance.rounding.full radius: Appearance.rounding.full
enabled: !isDisabled enabled: !isDisabled
} }
@ -124,9 +124,6 @@ ColumnLayout {
elide: Text.ElideRight elide: Text.ElideRight
opacity: isDisabled ? 0.4 : 1.0 opacity: isDisabled ? 0.4 : 1.0
} }
ToolTip.visible: isDisabled && layer.containsMouse
ToolTip.text: "XKB limitation: maximum 4 layouts allowed"
} }
} }
@ -167,12 +164,13 @@ ColumnLayout {
} }
Connections { Connections {
target: kb
function onActiveLabelChanged() { function onActiveLabelChanged() {
if (!activeRow.visible) if (!activeRow.visible)
return; return;
popIn.restart(); popIn.restart();
} }
target: kb
} }
SequentialAnimation { SequentialAnimation {

View file

@ -18,6 +18,7 @@ Item {
property alias active: session.active property alias active: session.active
property alias navExpanded: session.navExpanded property alias navExpanded: session.navExpanded
readonly property bool initialOpeningComplete: panes.initialOpeningComplete
readonly property Session session: Session { readonly property Session session: Session {
id: session id: session
@ -61,8 +62,6 @@ Item {
color: Colours.tPalette.m3surfaceContainer color: Colours.tPalette.m3surfaceContainer
CustomMouseArea { CustomMouseArea {
anchors.fill: parent
function onWheel(event: WheelEvent): void { function onWheel(event: WheelEvent): void {
// Prevent tab switching during initial opening animation to avoid blank pages // Prevent tab switching during initial opening animation to avoid blank pages
if (!panes.initialOpeningComplete) { if (!panes.initialOpeningComplete) {
@ -74,6 +73,8 @@ Item {
else if (event.angleDelta.y > 0) else if (event.angleDelta.y > 0)
root.session.activeIndex = Math.max(root.session.activeIndex - 1, 0); root.session.activeIndex = Math.max(root.session.activeIndex - 1, 0);
} }
anchors.fill: parent
} }
NavRail { NavRail {
@ -96,6 +97,4 @@ Item {
session: root.session session: root.session
} }
} }
readonly property bool initialOpeningComplete: panes.initialOpeningComplete
} }

View file

@ -122,6 +122,7 @@ Item {
NavItem { NavItem {
required property int index required property int index
Layout.topMargin: index === 0 ? Appearance.spacing.large * 2 : 0 Layout.topMargin: index === 0 ? Appearance.spacing.large * 2 : 0
icon: PaneRegistry.getByIndex(index).icon icon: PaneRegistry.getByIndex(index).icon
label: PaneRegistry.getByIndex(index).label label: PaneRegistry.getByIndex(index).label

View file

@ -37,23 +37,23 @@ ClippingRectangle {
} }
Connections { Connections {
target: root.session
function onActiveIndexChanged(): void { function onActiveIndexChanged(): void {
root.focus = true; root.focus = true;
} }
target: root.session
} }
ColumnLayout { ColumnLayout {
id: layout id: layout
property bool animationComplete: true
property bool initialOpeningComplete: false
spacing: 0 spacing: 0
y: -root.session.activeIndex * root.height y: -root.session.activeIndex * root.height
clip: true clip: true
property bool animationComplete: true
property bool initialOpeningComplete: false
Timer { Timer {
id: animationDelayTimer id: animationDelayTimer
@ -78,6 +78,7 @@ ClippingRectangle {
Pane { Pane {
required property int index required property int index
paneIndex: index paneIndex: index
componentPath: PaneRegistry.getByIndex(index).component componentPath: PaneRegistry.getByIndex(index).component
} }
@ -88,11 +89,12 @@ ClippingRectangle {
} }
Connections { Connections {
target: root.session
function onActiveIndexChanged(): void { function onActiveIndexChanged(): void {
layout.animationComplete = false; layout.animationComplete = false;
animationDelayTimer.restart(); animationDelayTimer.restart();
} }
target: root.session
} }
} }
@ -158,20 +160,22 @@ ClippingRectangle {
} }
Connections { Connections {
target: root.session
function onActiveIndexChanged(): void { function onActiveIndexChanged(): void {
pane.updateActive(); pane.updateActive();
} }
target: root.session
} }
Connections { Connections {
target: layout
function onInitialOpeningCompleteChanged(): void { function onInitialOpeningCompleteChanged(): void {
pane.updateActive(); pane.updateActive();
} }
function onAnimationCompleteChanged(): void { function onAnimationCompleteChanged(): void {
pane.updateActive(); pane.updateActive();
} }
target: layout
} }
} }
} }

View file

@ -45,13 +45,13 @@ Singleton {
ControlCenter { ControlCenter {
id: cc id: cc
anchors.fill: parent
screen: win.screen
floating: true
function close(): void { function close(): void {
win.destroy(); win.destroy();
} }
anchors.fill: parent
screen: win.screen
floating: true
} }
Behavior on color { Behavior on color {

View file

@ -152,11 +152,11 @@ Item {
anchors.fill: parent anchors.fill: parent
leftContent: Component { leftContent: Component {
StyledFlickable { StyledFlickable {
id: sidebarFlickable id: sidebarFlickable
readonly property var rootPane: root readonly property var rootPane: root
flickableDirection: Flickable.VerticalFlick flickableDirection: Flickable.VerticalFlick
contentHeight: sidebarLayout.height contentHeight: sidebarLayout.height

View file

@ -79,19 +79,22 @@ CollapsibleSection {
menuItems: [ menuItems: [
MenuItem { MenuItem {
property string val: "top"
text: qsTr("Top") text: qsTr("Top")
icon: "vertical_align_top" icon: "vertical_align_top"
property string val: "top"
}, },
MenuItem { MenuItem {
property string val: "middle"
text: qsTr("Middle") text: qsTr("Middle")
icon: "vertical_align_center" icon: "vertical_align_center"
property string val: "middle"
}, },
MenuItem { MenuItem {
property string val: "bottom"
text: qsTr("Bottom") text: qsTr("Bottom")
icon: "vertical_align_bottom" icon: "vertical_align_bottom"
property string val: "bottom"
} }
] ]
@ -113,19 +116,22 @@ CollapsibleSection {
menuItems: [ menuItems: [
MenuItem { MenuItem {
property string val: "left"
text: qsTr("Left") text: qsTr("Left")
icon: "align_horizontal_left" icon: "align_horizontal_left"
property string val: "left"
}, },
MenuItem { MenuItem {
property string val: "center"
text: qsTr("Center") text: qsTr("Center")
icon: "align_horizontal_center" icon: "align_horizontal_center"
property string val: "center"
}, },
MenuItem { MenuItem {
property string val: "right"
text: qsTr("Right") text: qsTr("Right")
icon: "align_horizontal_right" icon: "align_horizontal_right"
property string val: "right"
} }
] ]

View file

@ -48,10 +48,9 @@ CollapsibleSection {
delegate: StyledRect { delegate: StyledRect {
required property string modelData required property string modelData
required property int index required property int index
readonly property bool isCurrent: modelData === rootPane.fontFamilySans
width: ListView.view.width width: ListView.view.width
readonly property bool isCurrent: modelData === rootPane.fontFamilySans
color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0) color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
border.width: isCurrent ? 1 : 0 border.width: isCurrent ? 1 : 0
@ -131,10 +130,9 @@ CollapsibleSection {
delegate: StyledRect { delegate: StyledRect {
required property string modelData required property string modelData
required property int index required property int index
readonly property bool isCurrent: modelData === rootPane.fontFamilyMono
width: ListView.view.width width: ListView.view.width
readonly property bool isCurrent: modelData === rootPane.fontFamilyMono
color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0) color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
border.width: isCurrent ? 1 : 0 border.width: isCurrent ? 1 : 0
@ -216,10 +214,9 @@ CollapsibleSection {
delegate: StyledRect { delegate: StyledRect {
required property string modelData required property string modelData
required property int index required property int index
readonly property bool isCurrent: modelData === rootPane.fontFamilyMaterial
width: ListView.view.width width: ListView.view.width
readonly property bool isCurrent: modelData === rootPane.fontFamilyMaterial
color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0) color: Qt.alpha(Colours.tPalette.m3surfaceContainer, isCurrent ? Colours.tPalette.m3surfaceContainer.a : 0)
radius: Appearance.rounding.normal radius: Appearance.rounding.normal
border.width: isCurrent ? 1 : 0 border.width: isCurrent ? 1 : 0

View file

@ -23,7 +23,6 @@ Item {
anchors.fill: parent anchors.fill: parent
leftContent: Component { leftContent: Component {
StyledFlickable { StyledFlickable {
id: leftAudioFlickable id: leftAudioFlickable
@ -280,12 +279,13 @@ Item {
} }
Connections { Connections {
target: Audio
function onVolumeChanged() { function onVolumeChanged() {
if (!outputVolumeInput.hasFocus) { if (!outputVolumeInput.hasFocus) {
outputVolumeInput.text = Math.round(Audio.volume * 100).toString(); outputVolumeInput.text = Math.round(Audio.volume * 100).toString();
} }
} }
target: Audio
} }
onTextEdited: text => { onTextEdited: text => {
@ -397,12 +397,13 @@ Item {
} }
Connections { Connections {
target: Audio
function onSourceVolumeChanged() { function onSourceVolumeChanged() {
if (!inputVolumeInput.hasFocus) { if (!inputVolumeInput.hasFocus) {
inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString(); inputVolumeInput.text = Math.round(Audio.sourceVolume * 100).toString();
} }
} }
target: Audio
} }
onTextEdited: text => { onTextEdited: text => {
@ -530,12 +531,13 @@ Item {
} }
Connections { Connections {
target: modelData
function onAudioChanged() { function onAudioChanged() {
if (!streamVolumeInput.hasFocus && modelData?.audio) { if (!streamVolumeInput.hasFocus && modelData?.audio) {
streamVolumeInput.text = Math.round(modelData.audio.volume * 100).toString(); streamVolumeInput.text = Math.round(modelData.audio.volume * 100).toString();
} }
} }
target: modelData
} }
onTextEdited: text => { onTextEdited: text => {
@ -600,12 +602,13 @@ Item {
} }
Connections { Connections {
target: modelData
function onAudioChanged() { function onAudioChanged() {
if (modelData?.audio) { if (modelData?.audio) {
value = modelData.audio.volume; value = modelData.audio.volume;
} }
} }
target: modelData
} }
} }
} }

View file

@ -58,11 +58,10 @@ StyledRect {
required property int index required property int index
required property var modelData required property var modelData
Layout.fillWidth: true
text: modelData.label
property bool _checked: false property bool _checked: false
Layout.fillWidth: true
text: modelData.label
checked: _checked checked: _checked
toggle: false toggle: false
type: TextButton.Tonal type: TextButton.Tonal

View file

@ -21,6 +21,9 @@ ColumnLayout {
property int decimals: 1 // Number of decimal places to show (default: 1) property int decimals: 1 // Number of decimal places to show (default: 1)
property var formatValueFunction: null // Optional custom format function property var formatValueFunction: null // Optional custom format function
property var parseValueFunction: null // Optional custom parse function property var parseValueFunction: null // Optional custom parse function
property bool _initialized: false
signal valueModified(real newValue)
function formatValue(val: real): string { function formatValue(val: real): string {
if (formatValueFunction) { if (formatValueFunction) {
@ -49,10 +52,6 @@ ColumnLayout {
return parseFloat(text); return parseFloat(text);
} }
signal valueModified(real newValue)
property bool _initialized: false
spacing: Appearance.spacing.small spacing: Appearance.spacing.small
Component.onCompleted: { Component.onCompleted: {
@ -62,6 +61,14 @@ ColumnLayout {
}); });
} }
// 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);
}
}
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Appearance.spacing.normal spacing: Appearance.spacing.normal
@ -170,12 +177,4 @@ ColumnLayout {
} }
} }
} }
// 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);
}
}
} }

View file

@ -10,19 +10,17 @@ import QtQuick.Layouts
RowLayout { RowLayout {
id: root id: root
spacing: 0
property Component leftContent: null property Component leftContent: null
property Component rightContent: null property Component rightContent: null
property real leftWidthRatio: 0.4 property real leftWidthRatio: 0.4
property int leftMinimumWidth: 420 property int leftMinimumWidth: 420
property var leftLoaderProperties: ({}) property var leftLoaderProperties: ({})
property var rightLoaderProperties: ({}) property var rightLoaderProperties: ({})
property alias leftLoader: leftLoader property alias leftLoader: leftLoader
property alias rightLoader: rightLoader property alias rightLoader: rightLoader
spacing: 0
Item { Item {
id: leftPane id: leftPane

View file

@ -32,14 +32,13 @@ GridView {
delegate: Item { delegate: Item {
required property var modelData required property var modelData
required property int index required property int index
width: root.cellWidth
height: root.cellHeight
readonly property bool isCurrent: modelData && modelData.path === Wallpapers.actualCurrent readonly property bool isCurrent: modelData && modelData.path === Wallpapers.actualCurrent
readonly property real itemMargin: Appearance.spacing.normal / 2 readonly property real itemMargin: Appearance.spacing.normal / 2
readonly property real itemRadius: Appearance.rounding.normal readonly property real itemRadius: Appearance.rounding.normal
width: root.cellWidth
height: root.cellHeight
StateLayer { StateLayer {
function onClicked(): void { function onClicked(): void {
Wallpapers.setWallpaper(modelData.path); Wallpapers.setWallpaper(modelData.path);
@ -117,6 +116,7 @@ GridView {
id: fallbackTimer id: fallbackTimer
property bool triggered: false property bool triggered: false
interval: 800 interval: 800
running: cachingImage.status === Image.Loading || cachingImage.status === Image.Null running: cachingImage.status === Image.Loading || cachingImage.status === Image.Null
onTriggered: triggered = true onTriggered: triggered = true

View file

@ -108,12 +108,21 @@ Item {
updateToggleState(); updateToggleState();
} }
onSearchTextChanged: {
updateFilteredApps();
}
Component.onCompleted: {
updateFilteredApps();
}
Connections { Connections {
target: root.session.launcher
function onActiveChanged() { function onActiveChanged() {
root.selectedApp = root.session.launcher.active; root.selectedApp = root.session.launcher.active;
updateToggleState(); updateToggleState();
} }
target: root.session.launcher
} }
AppDb { AppDb {
@ -124,26 +133,18 @@ Item {
entries: DesktopEntries.applications.values entries: DesktopEntries.applications.values
} }
onSearchTextChanged: {
updateFilteredApps();
}
Component.onCompleted: {
updateFilteredApps();
}
Connections { Connections {
target: allAppsDb
function onAppsChanged() { function onAppsChanged() {
updateFilteredApps(); updateFilteredApps();
} }
target: allAppsDb
} }
SplitPaneLayout { SplitPaneLayout {
anchors.fill: parent anchors.fill: parent
leftContent: Component { leftContent: Component {
ColumnLayout { ColumnLayout {
id: leftLauncherLayout id: leftLauncherLayout
@ -358,9 +359,10 @@ Item {
} }
Loader { Loader {
Layout.alignment: Qt.AlignVCenter
readonly property bool isHidden: modelData ? Strings.testRegexList(Config.launcher.hiddenApps, modelData.id) : false readonly property bool isHidden: modelData ? Strings.testRegexList(Config.launcher.hiddenApps, modelData.id) : false
readonly property bool isFav: modelData ? Strings.testRegexList(Config.launcher.favouriteApps, modelData.id) : false readonly property bool isFav: modelData ? Strings.testRegexList(Config.launcher.favouriteApps, modelData.id) : false
Layout.alignment: Qt.AlignVCenter
asynchronous: true asynchronous: true
active: isHidden || isFav active: isHidden || isFav
@ -413,6 +415,22 @@ Item {
nextComponent = targetComponent; nextComponent = targetComponent;
} }
onPaneChanged: {
nextComponent = getComponentForPane();
paneId = pane ? (pane.id || pane.entry?.id || "") : "";
}
onDisplayedAppChanged: {
if (displayedApp) {
const appId = displayedApp.id || displayedApp.entry?.id;
root.hideFromLauncherChecked = Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0 && Strings.testRegexList(Config.launcher.hiddenApps, appId);
root.favouriteChecked = Config.launcher.favouriteApps && Config.launcher.favouriteApps.length > 0 && Strings.testRegexList(Config.launcher.favouriteApps, appId);
} else {
root.hideFromLauncherChecked = false;
root.favouriteChecked = false;
}
}
Loader { Loader {
id: rightLauncherLoader id: rightLauncherLoader
@ -463,22 +481,6 @@ Item {
] ]
} }
} }
onPaneChanged: {
nextComponent = getComponentForPane();
paneId = pane ? (pane.id || pane.entry?.id || "") : "";
}
onDisplayedAppChanged: {
if (displayedApp) {
const appId = displayedApp.id || displayedApp.entry?.id;
root.hideFromLauncherChecked = Config.launcher.hiddenApps && Config.launcher.hiddenApps.length > 0 && Strings.testRegexList(Config.launcher.hiddenApps, appId);
root.favouriteChecked = Config.launcher.favouriteApps && Config.launcher.favouriteApps.length > 0 && Strings.testRegexList(Config.launcher.favouriteApps, appId);
} else {
root.hideFromLauncherChecked = false;
root.favouriteChecked = false;
}
}
} }
} }
} }

View file

@ -199,9 +199,6 @@ Item {
} }
Connections { Connections {
target: root.session && root.session.vpn ? root.session.vpn : null
enabled: target !== null
function onActiveChanged() { function onActiveChanged() {
// Clear others when VPN is selected // Clear others when VPN is selected
if (root.session && root.session.vpn && root.session.vpn.active) { if (root.session && root.session.vpn && root.session.vpn.active) {
@ -212,12 +209,12 @@ Item {
} }
rightPaneItem.nextComponent = rightPaneItem.getComponentForPane(); rightPaneItem.nextComponent = rightPaneItem.getComponentForPane();
} }
target: root.session && root.session.vpn ? root.session.vpn : null
enabled: target !== null
} }
Connections { Connections {
target: root.session && root.session.ethernet ? root.session.ethernet : null
enabled: target !== null
function onActiveChanged() { function onActiveChanged() {
// Clear others when ethernet is selected // Clear others when ethernet is selected
if (root.session && root.session.ethernet && root.session.ethernet.active) { if (root.session && root.session.ethernet && root.session.ethernet.active) {
@ -228,12 +225,12 @@ Item {
} }
rightPaneItem.nextComponent = rightPaneItem.getComponentForPane(); rightPaneItem.nextComponent = rightPaneItem.getComponentForPane();
} }
target: root.session && root.session.ethernet ? root.session.ethernet : null
enabled: target !== null
} }
Connections { Connections {
target: root.session && root.session.network ? root.session.network : null
enabled: target !== null
function onActiveChanged() { function onActiveChanged() {
// Clear others when wireless is selected // Clear others when wireless is selected
if (root.session && root.session.network && root.session.network.active) { if (root.session && root.session.network && root.session.network.active) {
@ -244,6 +241,9 @@ Item {
} }
rightPaneItem.nextComponent = rightPaneItem.getComponentForPane(); rightPaneItem.nextComponent = rightPaneItem.getComponentForPane();
} }
target: root.session && root.session.network ? root.session.network : null
enabled: target !== null
} }
Loader { Loader {

View file

@ -21,7 +21,6 @@ ColumnLayout {
spacing: Appearance.spacing.normal spacing: Appearance.spacing.normal
Connections { Connections {
target: VPN
function onConnectedChanged() { function onConnectedChanged() {
if (!VPN.connected && root.pendingSwitchIndex >= 0) { if (!VPN.connected && root.pendingSwitchIndex >= 0) {
const targetIndex = root.pendingSwitchIndex; const targetIndex = root.pendingSwitchIndex;
@ -50,6 +49,8 @@ ColumnLayout {
}); });
} }
} }
target: VPN
} }
TextButton { TextButton {
@ -367,36 +368,6 @@ ColumnLayout {
currentState = "selection"; currentState = "selection";
} }
SequentialAnimation {
id: transitionToForm
ParallelAnimation {
Anim {
target: selectionContent
property: "opacity"
to: 0
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
ScriptAction {
script: {
vpnDialog.currentState = "form";
}
}
ParallelAnimation {
Anim {
target: formContent
property: "opacity"
to: 1
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
}
background: StyledRect { background: StyledRect {
color: Colours.palette.m3surfaceContainerHigh color: Colours.palette.m3surfaceContainerHigh
radius: Appearance.rounding.large radius: Appearance.rounding.large
@ -685,5 +656,35 @@ ColumnLayout {
} }
} }
} }
SequentialAnimation {
id: transitionToForm
ParallelAnimation {
Anim {
target: selectionContent
property: "opacity"
to: 0
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
ScriptAction {
script: {
vpnDialog.currentState = "form";
}
}
ParallelAnimation {
Anim {
target: formContent
property: "opacity"
to: 1
duration: Appearance.anim.durations.small
easing.bezierCurve: Appearance.anim.curves.emphasized
}
}
}
} }
} }

View file

@ -19,67 +19,12 @@ DeviceDetails {
required property Session session required property Session session
readonly property var network: root.session.network.active 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 { function checkSavedProfile(): void {
if (network && network.ssid) { if (network && network.ssid) {
Nmcli.loadSavedConnections(() => {}); 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 { function updateDeviceDetails(): void {
if (network && network.ssid) { if (network && network.ssid) {
const isActive = network.active || (Nmcli.active && Nmcli.active.ssid === network.ssid); const isActive = network.active || (Nmcli.active && Nmcli.active.ssid === network.ssid);
@ -93,6 +38,22 @@ DeviceDetails {
} }
} }
device: network
Component.onCompleted: {
updateDeviceDetails();
checkSavedProfile();
}
onNetworkChanged: {
connectionUpdateTimer.stop();
if (network && network.ssid) {
connectionUpdateTimer.start();
}
updateDeviceDetails();
checkSavedProfile();
}
headerComponent: Component { headerComponent: Component {
ConnectionHeader { ConnectionHeader {
icon: root.network?.isSecure ? "lock" : "wifi" icon: root.network?.isSecure ? "lock" : "wifi"
@ -209,4 +170,44 @@ DeviceDetails {
} }
} }
] ]
Connections {
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();
}
}
}
target: Nmcli
}
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;
}
}
}
}
}
} }

View file

@ -19,6 +19,12 @@ DeviceList {
required property Session session required property Session session
function checkSavedProfileForNetwork(ssid: string): void {
if (ssid && ssid.length > 0) {
Nmcli.loadSavedConnections(() => {});
}
}
title: qsTr("Networks (%1)").arg(Nmcli.networks.length) title: qsTr("Networks (%1)").arg(Nmcli.networks.length)
description: qsTr("All available WiFi networks") description: qsTr("All available WiFi networks")
activeItem: session.network.active activeItem: session.network.active
@ -219,10 +225,4 @@ DeviceList {
checkSavedProfileForNetwork(item.ssid); checkSavedProfileForNetwork(item.ssid);
} }
} }
function checkSavedProfileForNetwork(ssid: string): void {
if (ssid && ssid.length > 0) {
Nmcli.loadSavedConnections(() => {});
}
}
} }

View file

@ -192,10 +192,11 @@ Item {
Item { Item {
id: passwordContainer id: passwordContainer
property string passwordBuffer: ""
Layout.topMargin: Appearance.spacing.large Layout.topMargin: Appearance.spacing.large
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: Math.max(48, charList.implicitHeight + Appearance.padding.normal * 2) implicitHeight: Math.max(48, charList.implicitHeight + Appearance.padding.normal * 2)
focus: true focus: true
Keys.onPressed: event => { Keys.onPressed: event => {
if (!activeFocus) { if (!activeFocus) {
@ -224,10 +225,7 @@ Item {
} }
} }
property string passwordBuffer: ""
Connections { Connections {
target: root.session.network
function onShowPasswordDialogChanged(): void { function onShowPasswordDialogChanged(): void {
if (root.session.network.showPasswordDialog) { if (root.session.network.showPasswordDialog) {
Qt.callLater(() => { Qt.callLater(() => {
@ -237,10 +235,11 @@ Item {
}); });
} }
} }
target: root.session.network
} }
Connections { Connections {
target: root
function onVisibleChanged(): void { function onVisibleChanged(): void {
if (root.visible) { if (root.visible) {
Qt.callLater(() => { Qt.callLater(() => {
@ -248,6 +247,8 @@ Item {
}); });
} }
} }
target: root
} }
StyledRect { StyledRect {
@ -460,11 +461,11 @@ Item {
Timer { Timer {
id: connectionMonitor id: connectionMonitor
property int repeatCount: 0
interval: 1000 interval: 1000
repeat: true repeat: true
triggeredOnStart: false triggeredOnStart: false
property int repeatCount: 0
onTriggered: { onTriggered: {
repeatCount++; repeatCount++;
checkConnectionStatus(); checkConnectionStatus();
@ -495,7 +496,6 @@ Item {
} }
Connections { Connections {
target: Nmcli
function onActiveChanged() { function onActiveChanged() {
if (root.visible) { if (root.visible) {
checkConnectionStatus(); checkConnectionStatus();
@ -512,5 +512,7 @@ Item {
Nmcli.forgetNetwork(ssid); Nmcli.forgetNetwork(ssid);
} }
} }
target: Nmcli
} }
} }

View file

@ -92,18 +92,17 @@ StyledRect {
delegate: Item { delegate: Item {
id: delegateRoot id: delegateRoot
width: ListView.view.width * 0.98
height: 70
anchors.horizontalCenter: parent?.horizontalCenter
required property real id required property real id
required property string title required property string title
required property string artist required property string artist
property bool hovered: false property bool hovered: false
property bool pressed: false property bool pressed: false
width: ListView.view.width * 0.98
height: 70
anchors.horizontalCenter: parent?.horizontalCenter
scale: hovered ? 1.02 : 1.0 scale: hovered ? 1.02 : 1.0
Behavior on scale { Behavior on scale {
NumberAnimation { NumberAnimation {
duration: Appearance.anim.durations.small duration: Appearance.anim.durations.small
@ -158,6 +157,7 @@ StyledRect {
radius: 2 radius: 2
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: LyricsService.currentSongId === delegateRoot.id ? Colours.palette.m3primary : "transparent" color: LyricsService.currentSongId === delegateRoot.id ? Colours.palette.m3primary : "transparent"
Behavior on color { Behavior on color {
ColorAnimation { ColorAnimation {
duration: Appearance.anim.durations.small duration: Appearance.anim.durations.small
@ -177,6 +177,7 @@ StyledRect {
color: delegateRoot.hovered ? Colours.palette.m3primary : Colours.palette.m3onSurface color: delegateRoot.hovered ? Colours.palette.m3primary : Colours.palette.m3onSurface
width: parent.width width: parent.width
elide: Text.ElideRight elide: Text.ElideRight
Behavior on color { Behavior on color {
ColorAnimation { ColorAnimation {
duration: Appearance.anim.durations.small duration: Appearance.anim.durations.small
@ -288,21 +289,6 @@ StyledRect {
font.pointSize: Appearance.font.size.normal font.pointSize: Appearance.font.size.normal
selectByMouse: true selectByMouse: true
text: (LyricsService.offset >= 0 ? "+" : "") + LyricsService.offset.toFixed(1) + "s" text: (LyricsService.offset >= 0 ? "+" : "") + LyricsService.offset.toFixed(1) + "s"
Binding {
target: offsetInput
property: "text"
value: (LyricsService.offset >= 0 ? "+" : "") + LyricsService.offset.toFixed(1) + "s"
when: !offsetInput.activeFocus
}
Connections {
target: LyricsService
function onCurrentRequestIdChanged() {
offsetInput.focus = false;
}
}
onEditingFinished: { onEditingFinished: {
let cleaned = offsetInput.text.replace(/[+s]/g, "").trim(); let cleaned = offsetInput.text.replace(/[+s]/g, "").trim();
let val = parseFloat(cleaned); let val = parseFloat(cleaned);
@ -313,6 +299,21 @@ StyledRect {
offsetInput.text = (LyricsService.offset >= 0 ? "+" : "") + LyricsService.offset.toFixed(1) + "s"; offsetInput.text = (LyricsService.offset >= 0 ? "+" : "") + LyricsService.offset.toFixed(1) + "s";
} }
} }
Binding {
target: offsetInput
property: "text"
value: (LyricsService.offset >= 0 ? "+" : "") + LyricsService.offset.toFixed(1) + "s"
when: !offsetInput.activeFocus
}
Connections {
function onCurrentRequestIdChanged() {
offsetInput.focus = false;
}
target: LyricsService
}
} }
IconButton { IconButton {

View file

@ -14,55 +14,40 @@ StyledListView {
clip: true clip: true
model: LyricsService.model model: LyricsService.model
currentIndex: LyricsService.currentIndex currentIndex: LyricsService.currentIndex
visible: lyricsActuallyVisible || hideTimer.running visible: lyricsActuallyVisible || hideTimer.running
onLyricsActuallyVisibleChanged: {
if (!lyricsActuallyVisible)
hideTimer.restart();
}
Timer {
id: hideTimer
interval: 300 // long enough to bridge the track switch gap
running: false
repeat: false
}
preferredHighlightBegin: height / 2 - 30 preferredHighlightBegin: height / 2 - 30
preferredHighlightEnd: height / 2 + 30 preferredHighlightEnd: height / 2 + 30
highlightRangeMode: ListView.ApplyRange highlightRangeMode: ListView.ApplyRange
highlightFollowsCurrentItem: true highlightFollowsCurrentItem: true
highlightMoveDuration: LyricsService.isManualSeeking ? 0 : Appearance.anim.durations.normal highlightMoveDuration: LyricsService.isManualSeeking ? 0 : Appearance.anim.durations.normal
layer.enabled: true layer.enabled: true
layer.effect: ShaderEffect { layer.effect: ShaderEffect {
required property Item source required property Item source
property real fadeMargin: 0.5 property real fadeMargin: 0.5
fragmentShader: Quickshell.shellPath("assets/shaders/fade.frag.qsb") fragmentShader: Quickshell.shellPath("assets/shaders/fade.frag.qsb")
} }
onLyricsActuallyVisibleChanged: {
if (!lyricsActuallyVisible)
hideTimer.restart();
}
onModelChanged: { onModelChanged: {
if (model && model.count > 0) { if (model && model.count > 0) {
Qt.callLater(() => positionViewAtIndex(currentIndex, ListView.Center)); Qt.callLater(() => positionViewAtIndex(currentIndex, ListView.Center));
} }
} }
delegate: Item { delegate: Item {
id: delegateRoot id: delegateRoot
width: ListView.view.width
required property string lyricLine required property string lyricLine
required property real time required property real time
required property int index required property int index
readonly property bool hasContent: lyricLine && lyricLine.trim().length > 0 readonly property bool hasContent: lyricLine && lyricLine.trim().length > 0
height: hasContent ? (lyricText.contentHeight + Appearance.spacing.large) : 0
property bool isCurrent: ListView.isCurrentItem property bool isCurrent: ListView.isCurrentItem
width: ListView.view.width
height: hasContent ? (lyricText.contentHeight + Appearance.spacing.large) : 0
MultiEffect { MultiEffect {
id: effect id: effect
@ -103,6 +88,7 @@ StyledListView {
color: delegateRoot.isCurrent ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant color: delegateRoot.isCurrent ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant
font.bold: delegateRoot.isCurrent font.bold: delegateRoot.isCurrent
scale: delegateRoot.isCurrent ? 1.15 : 1.0 scale: delegateRoot.isCurrent ? 1.15 : 1.0
Behavior on color { Behavior on color {
CAnim { CAnim {
duration: Appearance.anim.durations.small duration: Appearance.anim.durations.small
@ -115,4 +101,12 @@ StyledListView {
} }
} }
} }
Timer {
id: hideTimer
interval: 300 // long enough to bridge the track switch gap
running: false
repeat: false
}
} }

View file

@ -86,10 +86,11 @@ Item {
} }
Connections { Connections {
target: lyricsHideDelay
function onTriggered() { function onTriggered() {
root.lyricsShowingDebounced = false; root.lyricsShowingDebounced = false;
} }
target: lyricsHideDelay
} }
ServiceRef { ServiceRef {
@ -327,9 +328,6 @@ Item {
} }
CustomMouseArea { CustomMouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
function onWheel(event: WheelEvent) { function onWheel(event: WheelEvent) {
const active = Players.active; const active = Players.active;
if (!active?.canSeek || !active?.positionSupported) if (!active?.canSeek || !active?.positionSupported)
@ -341,6 +339,9 @@ Item {
active.position = Math.max(0, Math.min(active.length, active.position + delta)); active.position = Math.max(0, Math.min(active.length, active.position + delta));
}); });
} }
anchors.fill: parent
acceptedButtons: Qt.NoButton
} }
} }
@ -380,6 +381,7 @@ Item {
visible: lyricMenu.height === 0 || opacity > 0 visible: lyricMenu.height === 0 || opacity > 0
opacity: lyricMenu.height === 0 ? 1 : 0 opacity: lyricMenu.height === 0 ? 1 : 0
Behavior on opacity { Behavior on opacity {
NumberAnimation { NumberAnimation {
duration: Appearance.anim.durations.normal duration: Appearance.anim.durations.normal
@ -421,6 +423,7 @@ Item {
visible: root.lyricMenuOpen || height > 0 visible: root.lyricMenuOpen || height > 0
height: root.lyricMenuOpen ? implicitHeight : 0 height: root.lyricMenuOpen ? implicitHeight : 0
clip: true clip: true
Behavior on height { Behavior on height {
NumberAnimation { NumberAnimation {
duration: Appearance.anim.durations.normal duration: Appearance.anim.durations.normal

View file

@ -695,12 +695,12 @@ Item {
historyLength: NetworkUsage.historyLength historyLength: NetworkUsage.historyLength
Connections { Connections {
target: NetworkUsage.downloadBuffer
function onValuesChanged(): void { function onValuesChanged(): void {
sparkline.targetMax = Math.max(NetworkUsage.downloadBuffer.maximum, NetworkUsage.uploadBuffer.maximum, 1024); sparkline.targetMax = Math.max(NetworkUsage.downloadBuffer.maximum, NetworkUsage.uploadBuffer.maximum, 1024);
slideAnim.restart(); slideAnim.restart();
} }
target: NetworkUsage.downloadBuffer
} }
NumberAnimation { NumberAnimation {

View file

@ -7,11 +7,10 @@ import QtQuick.Layouts
Item { Item {
id: root id: root
implicitWidth: layout.implicitWidth > 800 ? layout.implicitWidth : 840
implicitHeight: layout.implicitHeight
readonly property var today: Weather.forecast && Weather.forecast.length > 0 ? Weather.forecast[0] : null readonly property var today: Weather.forecast && Weather.forecast.length > 0 ? Weather.forecast[0] : null
implicitWidth: layout.implicitWidth > 800 ? layout.implicitWidth : 840
implicitHeight: layout.implicitHeight
Component.onCompleted: Weather.reload() Component.onCompleted: Weather.reload()
ColumnLayout { ColumnLayout {

View file

@ -174,30 +174,30 @@ Item {
spacing: Appearance.spacing.small spacing: Appearance.spacing.small
Control { Control {
icon: "skip_previous"
canUse: Players.active?.canGoPrevious ?? false
function onClicked(): void { function onClicked(): void {
Players.active?.previous(); Players.active?.previous();
} }
icon: "skip_previous"
canUse: Players.active?.canGoPrevious ?? false
} }
Control { Control {
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
canUse: Players.active?.canTogglePlaying ?? false
function onClicked(): void { function onClicked(): void {
Players.active?.togglePlaying(); Players.active?.togglePlaying();
} }
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
canUse: Players.active?.canTogglePlaying ?? false
} }
Control { Control {
icon: "skip_next"
canUse: Players.active?.canGoNext ?? false
function onClicked(): void { function onClicked(): void {
Players.active?.next(); Players.active?.next();
} }
icon: "skip_next"
canUse: Players.active?.canGoNext ?? false
} }
} }
@ -224,6 +224,7 @@ Item {
required property string icon required property string icon
required property bool canUse required property bool canUse
function onClicked(): void { function onClicked(): void {
} }

View file

@ -209,8 +209,6 @@ CustomMouseArea {
// Monitor individual visibility changes // Monitor individual visibility changes
Connections { Connections {
target: root.visibilities
function onLauncherChanged() { function onLauncherChanged() {
// If launcher is hidden, clear shortcut flags for dashboard and OSD // If launcher is hidden, clear shortcut flags for dashboard and OSD
if (!root.visibilities.launcher) { if (!root.visibilities.launcher) {
@ -270,5 +268,7 @@ CustomMouseArea {
root.utilitiesShortcutActive = false; root.utilitiesShortcutActive = false;
} }
} }
target: root.visibilities
} }
} }

View file

@ -130,8 +130,6 @@ Item {
Component.onCompleted: forceActiveFocus() Component.onCompleted: forceActiveFocus()
Connections { Connections {
target: root.visibilities
function onLauncherChanged(): void { function onLauncherChanged(): void {
if (!root.visibilities.launcher) if (!root.visibilities.launcher)
search.text = ""; search.text = "";
@ -141,6 +139,8 @@ Item {
if (!root.visibilities.session) if (!root.visibilities.session)
search.forceActiveFocus(); search.forceActiveFocus();
} }
target: root.visibilities
} }
} }

View file

@ -69,8 +69,6 @@ Item {
} }
Connections { Connections {
target: Config.launcher
function onEnabledChanged(): void { function onEnabledChanged(): void {
timer.start(); timer.start();
} }
@ -78,15 +76,17 @@ Item {
function onMaxShownChanged(): void { function onMaxShownChanged(): void {
timer.start(); timer.start();
} }
target: Config.launcher
} }
Connections { Connections {
target: DesktopEntries.applications
function onValuesChanged(): void { function onValuesChanged(): void {
if (DesktopEntries.applications.values.length < Config.launcher.maxShown) if (DesktopEntries.applications.values.length < Config.launcher.maxShown)
timer.start(); timer.start();
} }
target: DesktopEntries.applications
} }
Timer { Timer {

View file

@ -357,8 +357,6 @@ ColumnLayout {
} }
Connections { Connections {
target: root.lock.pam
function onFlashMsg(): void { function onFlashMsg(): void {
exitAnim.stop(); exitAnim.stop();
if (message.scale < 1) if (message.scale < 1)
@ -366,6 +364,8 @@ ColumnLayout {
else else
flashAnim.restart(); flashAnim.restart();
} }
target: root.lock.pam
} }
Anim { Anim {

View file

@ -20,8 +20,6 @@ Item {
clip: true clip: true
Connections { Connections {
target: root.pam
function onBufferChanged(): void { function onBufferChanged(): void {
if (root.pam.buffer.length > root.buffer.length) { if (root.pam.buffer.length > root.buffer.length) {
charList.bindImWidth(); charList.bindImWidth();
@ -32,6 +30,8 @@ Item {
root.buffer = root.pam.buffer; root.buffer = root.pam.buffer;
} }
target: root.pam
} }
StyledText { StyledText {

View file

@ -38,8 +38,6 @@ Scope {
} }
IpcHandler { IpcHandler {
target: "lock"
function lock(): void { function lock(): void {
lock.locked = true; lock.locked = true;
} }
@ -51,5 +49,7 @@ Scope {
function isLocked(): bool { function isLocked(): bool {
return lock.locked; return lock.locked;
} }
target: "lock"
} }
} }

View file

@ -18,11 +18,11 @@ WlSessionLockSurface {
color: "transparent" color: "transparent"
Connections { Connections {
target: root.lock
function onUnlock(): void { function onUnlock(): void {
unlockAnim.start(); unlockAnim.start();
} }
target: root.lock
} }
SequentialAnimation { SequentialAnimation {

View file

@ -110,34 +110,34 @@ Item {
spacing: Appearance.spacing.large spacing: Appearance.spacing.large
PlayerControl { PlayerControl {
icon: "skip_previous"
function onClicked(): void { function onClicked(): void {
if (Players.active?.canGoPrevious) if (Players.active?.canGoPrevious)
Players.active.previous(); Players.active.previous();
} }
icon: "skip_previous"
} }
PlayerControl { PlayerControl {
function onClicked(): void {
if (Players.active?.canTogglePlaying)
Players.active.togglePlaying();
}
animate: true animate: true
icon: active ? "pause" : "play_arrow" icon: active ? "pause" : "play_arrow"
colour: "Primary" colour: "Primary"
level: active ? 2 : 1 level: active ? 2 : 1
active: Players.active?.isPlaying ?? false active: Players.active?.isPlaying ?? false
function onClicked(): void {
if (Players.active?.canTogglePlaying)
Players.active.togglePlaying();
}
} }
PlayerControl { PlayerControl {
icon: "skip_next"
function onClicked(): void { function onClicked(): void {
if (Players.active?.canGoNext) if (Players.active?.canGoNext)
Players.active.next(); Players.active.next();
} }
icon: "skip_next"
} }
} }
} }

View file

@ -166,8 +166,6 @@ Scope {
} }
Connections { Connections {
target: root.lock
function onSecureChanged(): void { function onSecureChanged(): void {
if (root.lock.secure) { if (root.lock.secure) {
availProc.running = true; availProc.running = true;
@ -181,13 +179,15 @@ Scope {
function onUnlock(): void { function onUnlock(): void {
fprint.abort(); fprint.abort();
} }
target: root.lock
} }
Connections { Connections {
target: Config.lock
function onEnableFprintChanged(): void { function onEnableFprintChanged(): void {
fprint.checkAvail(); fprint.checkAvail();
} }
target: Config.lock
} }
} }

View file

@ -460,6 +460,7 @@ StyledRect {
Action { Action {
modelData: QtObject { modelData: QtObject {
readonly property string text: qsTr("Close") readonly property string text: qsTr("Close")
function invoke(): void { function invoke(): void {
root.modelData.close(); root.modelData.close();
} }

View file

@ -31,9 +31,6 @@ Item {
// Speaker volume // Speaker volume
CustomMouseArea { CustomMouseArea {
implicitWidth: Config.osd.sizes.sliderWidth
implicitHeight: Config.osd.sizes.sliderHeight
function onWheel(event: WheelEvent) { function onWheel(event: WheelEvent) {
if (event.angleDelta.y > 0) if (event.angleDelta.y > 0)
Audio.incrementVolume(); Audio.incrementVolume();
@ -41,6 +38,9 @@ Item {
Audio.decrementVolume(); Audio.decrementVolume();
} }
implicitWidth: Config.osd.sizes.sliderWidth
implicitHeight: Config.osd.sizes.sliderHeight
FilledSlider { FilledSlider {
anchors.fill: parent anchors.fill: parent
@ -56,9 +56,6 @@ Item {
shouldBeActive: Config.osd.enableMicrophone && (!Config.osd.enableBrightness || !root.visibilities.session) shouldBeActive: Config.osd.enableMicrophone && (!Config.osd.enableBrightness || !root.visibilities.session)
sourceComponent: CustomMouseArea { sourceComponent: CustomMouseArea {
implicitWidth: Config.osd.sizes.sliderWidth
implicitHeight: Config.osd.sizes.sliderHeight
function onWheel(event: WheelEvent) { function onWheel(event: WheelEvent) {
if (event.angleDelta.y > 0) if (event.angleDelta.y > 0)
Audio.incrementSourceVolume(); Audio.incrementSourceVolume();
@ -66,6 +63,9 @@ Item {
Audio.decrementSourceVolume(); Audio.decrementSourceVolume();
} }
implicitWidth: Config.osd.sizes.sliderWidth
implicitHeight: Config.osd.sizes.sliderHeight
FilledSlider { FilledSlider {
anchors.fill: parent anchors.fill: parent
@ -82,9 +82,6 @@ Item {
shouldBeActive: Config.osd.enableBrightness shouldBeActive: Config.osd.enableBrightness
sourceComponent: CustomMouseArea { sourceComponent: CustomMouseArea {
implicitWidth: Config.osd.sizes.sliderWidth
implicitHeight: Config.osd.sizes.sliderHeight
function onWheel(event: WheelEvent) { function onWheel(event: WheelEvent) {
const monitor = root.monitor; const monitor = root.monitor;
if (!monitor) if (!monitor)
@ -95,6 +92,9 @@ Item {
monitor.setBrightness(monitor.brightness - Config.services.brightnessIncrement); monitor.setBrightness(monitor.brightness - Config.services.brightnessIncrement);
} }
implicitWidth: Config.osd.sizes.sliderWidth
implicitHeight: Config.osd.sizes.sliderHeight
FilledSlider { FilledSlider {
anchors.fill: parent anchors.fill: parent

View file

@ -71,8 +71,6 @@ Item {
] ]
Connections { Connections {
target: Audio
function onMutedChanged(): void { function onMutedChanged(): void {
root.show(); root.show();
root.muted = Audio.muted; root.muted = Audio.muted;
@ -92,15 +90,17 @@ Item {
root.show(); root.show();
root.sourceVolume = Audio.sourceVolume; root.sourceVolume = Audio.sourceVolume;
} }
target: Audio
} }
Connections { Connections {
target: root.monitor
function onBrightnessChanged(): void { function onBrightnessChanged(): void {
root.show(); root.show();
root.brightness = root.monitor?.brightness ?? 0; root.brightness = root.monitor?.brightness ?? 0;
} }
target: root.monitor
} }
Timer { Timer {

View file

@ -26,12 +26,12 @@ Column {
Component.onCompleted: forceActiveFocus() Component.onCompleted: forceActiveFocus()
Connections { Connections {
target: root.visibilities
function onLauncherChanged(): void { function onLauncherChanged(): void {
if (!root.visibilities.launcher) if (!root.visibilities.launcher)
logout.forceActiveFocus(); logout.forceActiveFocus();
} }
target: root.visibilities
} }
} }

View file

@ -81,14 +81,14 @@ ColumnLayout {
readonly property int wsId: Math.floor((Hypr.activeWsId - 1) / 10) * 10 + index + 1 readonly property int wsId: Math.floor((Hypr.activeWsId - 1) / 10) * 10 + index + 1
readonly property bool isCurrent: root.client?.workspace.id === wsId readonly property bool isCurrent: root.client?.workspace.id === wsId
function onClicked(): void {
Hypr.dispatch(`movetoworkspace ${wsId},address:0x${root.client?.address}`);
}
color: isCurrent ? Colours.tPalette.m3surfaceContainerHighest : Colours.palette.m3tertiaryContainer color: isCurrent ? Colours.tPalette.m3surfaceContainerHighest : Colours.palette.m3tertiaryContainer
onColor: isCurrent ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer onColor: isCurrent ? Colours.palette.m3onSurface : Colours.palette.m3onTertiaryContainer
text: wsId text: wsId
disabled: isCurrent disabled: isCurrent
function onClicked(): void {
Hypr.dispatch(`movetoworkspace ${wsId},address:0x${root.client?.address}`);
}
} }
} }
} }
@ -107,13 +107,13 @@ ColumnLayout {
spacing: root.client?.lastIpcObject.floating ? Appearance.spacing.normal : Appearance.spacing.small spacing: root.client?.lastIpcObject.floating ? Appearance.spacing.normal : Appearance.spacing.small
Button { Button {
color: Colours.palette.m3secondaryContainer
onColor: Colours.palette.m3onSecondaryContainer
text: root.client?.lastIpcObject.floating ? qsTr("Tile") : qsTr("Float")
function onClicked(): void { function onClicked(): void {
Hypr.dispatch(`togglefloating address:0x${root.client?.address}`); Hypr.dispatch(`togglefloating address:0x${root.client?.address}`);
} }
color: Colours.palette.m3secondaryContainer
onColor: Colours.palette.m3onSecondaryContainer
text: root.client?.lastIpcObject.floating ? qsTr("Tile") : qsTr("Float")
} }
Loader { Loader {
@ -124,24 +124,24 @@ ColumnLayout {
Layout.rightMargin: active ? 0 : -parent.spacing Layout.rightMargin: active ? 0 : -parent.spacing
sourceComponent: Button { sourceComponent: Button {
color: Colours.palette.m3secondaryContainer
onColor: Colours.palette.m3onSecondaryContainer
text: root.client?.lastIpcObject.pinned ? qsTr("Unpin") : qsTr("Pin")
function onClicked(): void { function onClicked(): void {
Hypr.dispatch(`pin address:0x${root.client?.address}`); Hypr.dispatch(`pin address:0x${root.client?.address}`);
} }
color: Colours.palette.m3secondaryContainer
onColor: Colours.palette.m3onSecondaryContainer
text: root.client?.lastIpcObject.pinned ? qsTr("Unpin") : qsTr("Pin")
} }
} }
Button { Button {
color: Colours.palette.m3errorContainer
onColor: Colours.palette.m3onErrorContainer
text: qsTr("Kill")
function onClicked(): void { function onClicked(): void {
Hypr.dispatch(`killwindow address:0x${root.client?.address}`); Hypr.dispatch(`killwindow address:0x${root.client?.address}`);
} }
color: Colours.palette.m3errorContainer
onColor: Colours.palette.m3onErrorContainer
text: qsTr("Kill")
} }
} }

View file

@ -125,8 +125,6 @@ Singleton {
} }
Connections { Connections {
target: Pipewire.nodes
function onValuesChanged(): void { function onValuesChanged(): void {
const newSinks = []; const newSinks = [];
const newSources = []; const newSources = [];
@ -147,6 +145,8 @@ Singleton {
root.sources = newSources; root.sources = newSources;
root.streams = newStreams; root.streams = newStreams;
} }
target: Pipewire.nodes
} }
PwObjectTracker { PwObjectTracker {

View file

@ -105,8 +105,6 @@ Singleton {
} }
IpcHandler { IpcHandler {
target: "brightness"
function get(): real { function get(): real {
return getFor("active"); return getFor("active");
} }
@ -155,6 +153,8 @@ Singleton {
return `Set monitor ${monitor.modelData.name} brightness to ${+monitor.brightness.toFixed(2)}`; return `Set monitor ${monitor.modelData.name} brightness to ${+monitor.brightness.toFixed(2)}`;
} }
target: "brightness"
} }
component Monitor: QtObject { component Monitor: QtObject {

View file

@ -46,17 +46,15 @@ Singleton {
} }
Connections { Connections {
target: Hypr
function onConfigReloaded(): void { function onConfigReloaded(): void {
if (props.enabled) if (props.enabled)
root.setDynamicConfs(); root.setDynamicConfs();
} }
target: Hypr
} }
IpcHandler { IpcHandler {
target: "gameMode"
function isEnabled(): bool { function isEnabled(): bool {
return props.enabled; return props.enabled;
} }
@ -72,5 +70,7 @@ Singleton {
function disable(): void { function disable(): void {
props.enabled = false; props.enabled = false;
} }
target: "gameMode"
} }
} }

View file

@ -120,8 +120,6 @@ Singleton {
} }
Connections { Connections {
target: Hyprland
function onRawEvent(event: HyprlandEvent): void { function onRawEvent(event: HyprlandEvent): void {
const n = event.name; const n = event.name;
if (n.endsWith("v2")) if (n.endsWith("v2"))
@ -144,11 +142,11 @@ Singleton {
Hyprland.refreshToplevels(); Hyprland.refreshToplevels();
} }
} }
target: Hyprland
} }
Connections { Connections {
target: root.focusedMonitor
function onLastIpcObjectChanged(): void { function onLastIpcObjectChanged(): void {
const specialName = root.focusedMonitor.lastIpcObject.specialWorkspace.name; const specialName = root.focusedMonitor.lastIpcObject.specialWorkspace.name;
@ -156,6 +154,8 @@ Singleton {
root.lastSpecialWorkspace = specialName; root.lastSpecialWorkspace = specialName;
} }
} }
target: root.focusedMonitor
} }
FileView { FileView {
@ -192,8 +192,6 @@ Singleton {
} }
IpcHandler { IpcHandler {
target: "hypr"
function refreshDevices(): void { function refreshDevices(): void {
extras.refreshDevices(); extras.refreshDevices();
} }
@ -205,6 +203,8 @@ Singleton {
function listSpecialWorkspaces(): string { function listSpecialWorkspaces(): string {
return root.workspaces.values.filter(w => w.name.startsWith("special:") && w.lastIpcObject.windows > 0).map(w => w.name).join("\n"); return root.workspaces.values.filter(w => w.name.startsWith("special:") && w.lastIpcObject.windows > 0).map(w => w.name).join("\n");
} }
target: "hypr"
} }
CustomShortcut { CustomShortcut {

View file

@ -35,8 +35,6 @@ Singleton {
} }
IpcHandler { IpcHandler {
target: "idleInhibitor"
function isEnabled(): bool { function isEnabled(): bool {
return props.enabled; return props.enabled;
} }
@ -52,5 +50,7 @@ Singleton {
function disable(): void { function disable(): void {
props.enabled = false; props.enabled = false;
} }
target: "idleInhibitor"
} }
} }

View file

@ -32,6 +32,12 @@ Singleton {
property var lyricsMap: ({}) property var lyricsMap: ({})
// shared headers for all NetEase requests
readonly property var _netEaseHeaders: ({
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0",
"Referer": "https://music.163.com/"
})
ListModel { ListModel {
id: lyricsModel id: lyricsModel
} }
@ -99,19 +105,21 @@ Singleton {
} }
Connections { Connections {
target: Players
function onActiveChanged() { function onActiveChanged() {
root.player = Players.active; root.player = Players.active;
loadLyrics(); loadLyrics();
} }
target: Players
} }
Connections { Connections {
target: root.player
ignoreUnknownSignals: true
function onMetadataChanged() { function onMetadataChanged() {
loadLyrics(); loadLyrics();
} }
target: root.player
ignoreUnknownSignals: true
} }
Process { Process {
@ -226,12 +234,6 @@ Singleton {
// NetEase // NetEase
// shared headers for all NetEase requests
readonly property var _netEaseHeaders: ({
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:120.0) Gecko/20100101 Firefox/120.0",
"Referer": "https://music.163.com/"
})
// searches NetEase and populates the candidates model. returns the result array via the onResults callback // searches NetEase and populates the candidates model. returns the result array via the onResults callback
function _searchNetEase(title, artist, reqId, onResults) { function _searchNetEase(title, artist, reqId, onResults) {
Requests.resetCookies(); Requests.resetCookies();

View file

@ -8,37 +8,21 @@ import qs.services
Singleton { Singleton {
id: root id: root
Component.onCompleted: {
// Trigger ethernet device detection after initialization
Qt.callLater(() => {
getEthernetDevices();
});
// Load saved connections on startup
Nmcli.loadSavedConnections(() => {
root.savedConnections = Nmcli.savedConnections;
root.savedConnectionSsids = Nmcli.savedConnectionSsids;
});
// Get initial WiFi status
Nmcli.getWifiStatus(enabled => {
root.wifiEnabled = enabled;
});
// Sync networks from Nmcli on startup
Qt.callLater(() => {
syncNetworksFromNmcli();
}, 100);
}
readonly property list<AccessPoint> networks: [] readonly property list<AccessPoint> networks: []
readonly property AccessPoint active: networks.find(n => n.active) ?? null readonly property AccessPoint active: networks.find(n => n.active) ?? null
property bool wifiEnabled: true property bool wifiEnabled: true
readonly property bool scanning: Nmcli.scanning readonly property bool scanning: Nmcli.scanning
property list<var> ethernetDevices: [] property list<var> ethernetDevices: []
readonly property var activeEthernet: ethernetDevices.find(d => d.connected) ?? null readonly property var activeEthernet: ethernetDevices.find(d => d.connected) ?? null
property int ethernetDeviceCount: 0 property int ethernetDeviceCount: 0
property bool ethernetProcessRunning: false property bool ethernetProcessRunning: false
property var ethernetDeviceDetails: null property var ethernetDeviceDetails: null
property var wirelessDeviceDetails: null property var wirelessDeviceDetails: null
property var pendingConnection: null
property list<string> savedConnections: []
property list<string> savedConnectionSsids: []
signal connectionFailed(string ssid)
function enableWifi(enabled: bool): void { function enableWifi(enabled: bool): void {
Nmcli.enableWifi(enabled, result => { Nmcli.enableWifi(enabled, result => {
@ -66,9 +50,6 @@ Singleton {
Nmcli.rescanWifi(); Nmcli.rescanWifi();
} }
property var pendingConnection: null
signal connectionFailed(string ssid)
function connectToNetwork(ssid: string, password: string, bssid: string, callback: var): void { function connectToNetwork(ssid: string, password: string, bssid: string, callback: var): void {
// Set up pending connection tracking if callback provided // Set up pending connection tracking if callback provided
if (callback) { if (callback) {
@ -159,20 +140,6 @@ Singleton {
}); });
} }
property list<string> savedConnections: []
property list<string> savedConnectionSsids: []
// Sync saved connections from Nmcli when they're updated
Connections {
target: Nmcli
function onSavedConnectionsChanged() {
root.savedConnections = Nmcli.savedConnections;
}
function onSavedConnectionSsidsChanged() {
root.savedConnectionSsids = Nmcli.savedConnectionSsids;
}
}
function syncNetworksFromNmcli(): void { function syncNetworksFromNmcli(): void {
const rNetworks = root.networks; const rNetworks = root.networks;
const nNetworks = Nmcli.networks; const nNetworks = Nmcli.networks;
@ -217,23 +184,6 @@ Singleton {
} }
} }
component AccessPoint: QtObject {
required property var lastIpcObject
readonly property string ssid: lastIpcObject.ssid
readonly property string bssid: lastIpcObject.bssid
readonly property int strength: lastIpcObject.strength
readonly property int frequency: lastIpcObject.frequency
readonly property bool active: lastIpcObject.active
readonly property string security: lastIpcObject.security
readonly property bool isSecure: security.length > 0
}
Component {
id: apComp
AccessPoint {}
}
function hasSavedProfile(ssid: string): bool { function hasSavedProfile(ssid: string): bool {
// Use Nmcli's hasSavedProfile which has the same logic // Use Nmcli's hasSavedProfile which has the same logic
return Nmcli.hasSavedProfile(ssid); return Nmcli.hasSavedProfile(ssid);
@ -310,6 +260,39 @@ Singleton {
return octets.join("."); return octets.join(".");
} }
Component.onCompleted: {
// Trigger ethernet device detection after initialization
Qt.callLater(() => {
getEthernetDevices();
});
// Load saved connections on startup
Nmcli.loadSavedConnections(() => {
root.savedConnections = Nmcli.savedConnections;
root.savedConnectionSsids = Nmcli.savedConnectionSsids;
});
// Get initial WiFi status
Nmcli.getWifiStatus(enabled => {
root.wifiEnabled = enabled;
});
// Sync networks from Nmcli on startup
Qt.callLater(() => {
syncNetworksFromNmcli();
}, 100);
}
// Sync saved connections from Nmcli when they're updated
Connections {
function onSavedConnectionsChanged() {
root.savedConnections = Nmcli.savedConnections;
}
function onSavedConnectionSsidsChanged() {
root.savedConnectionSsids = Nmcli.savedConnectionSsids;
}
target: Nmcli
}
Timer { Timer {
id: monitorDebounce id: monitorDebounce
@ -329,4 +312,21 @@ Singleton {
onRead: monitorDebounce.start() onRead: monitorDebounce.start()
} }
} }
component AccessPoint: QtObject {
required property var lastIpcObject
readonly property string ssid: lastIpcObject.ssid
readonly property string bssid: lastIpcObject.bssid
readonly property int strength: lastIpcObject.strength
readonly property int frequency: lastIpcObject.frequency
readonly property bool active: lastIpcObject.active
readonly property string security: lastIpcObject.security
readonly property bool isSecure: security.length > 0
}
Component {
id: apComp
AccessPoint {}
}
} }

View file

@ -24,12 +24,10 @@ Singleton {
property var wifiConnectionQueue: [] property var wifiConnectionQueue: []
property int currentSsidQueryIndex: 0 property int currentSsidQueryIndex: 0
property var pendingConnection: null property var pendingConnection: null
signal connectionFailed(string ssid)
property var wirelessDeviceDetails: null property var wirelessDeviceDetails: null
property var ethernetDeviceDetails: null property var ethernetDeviceDetails: null
property list<var> ethernetDevices: [] property list<var> ethernetDevices: []
readonly property var activeEthernet: ethernetDevices.find(d => d.connected) ?? null readonly property var activeEthernet: ethernetDevices.find(d => d.connected) ?? null
property list<var> activeProcesses: [] property list<var> activeProcesses: []
// Constants // Constants
@ -55,6 +53,8 @@ Singleton {
readonly property string connectionParamPassword: "password" readonly property string connectionParamPassword: "password"
readonly property string connectionParamBssid: "802-11-wireless.bssid" readonly property string connectionParamBssid: "802-11-wireless.bssid"
signal connectionFailed(string ssid)
function detectPasswordRequired(error: string): bool { function detectPasswordRequired(error: string): bool {
if (!error || error.length === 0) { if (!error || error.length === 0) {
return false; return false;

View file

@ -114,8 +114,6 @@ Singleton {
} }
IpcHandler { IpcHandler {
target: "notifs"
function clear(): void { function clear(): void {
for (const notif of root.list.slice()) for (const notif of root.list.slice())
notif.close(); notif.close();
@ -136,6 +134,8 @@ Singleton {
function disableDnd(): void { function disableDnd(): void {
props.dnd = false; props.dnd = false;
} }
target: "notifs"
} }
component Notif: QtObject { component Notif: QtObject {
@ -227,8 +227,6 @@ Singleton {
} }
readonly property Connections conn: Connections { readonly property Connections conn: Connections {
target: notif.notification
function onClosed(): void { function onClosed(): void {
notif.close(); notif.close();
} }
@ -282,6 +280,8 @@ Singleton {
function onHintsChanged(): void { function onHintsChanged(): void {
notif.hints = notif.notification.hints; notif.hints = notif.notification.hints;
} }
target: notif.notification
} }
function updateTimeStr(): void { function updateTimeStr(): void {

View file

@ -21,8 +21,6 @@ Singleton {
} }
Connections { Connections {
target: active
function onPostTrackChanged() { function onPostTrackChanged() {
if (!Config.utilities.toasts.nowPlaying) { if (!Config.utilities.toasts.nowPlaying) {
return; return;
@ -31,6 +29,8 @@ Singleton {
Toaster.toast(qsTr("Now Playing"), qsTr("%1 - %2").arg(active.trackArtist).arg(active.trackTitle), "music_note"); Toaster.toast(qsTr("Now Playing"), qsTr("%1 - %2").arg(active.trackArtist).arg(active.trackTitle), "music_note");
} }
} }
target: active
} }
PersistentProperties { PersistentProperties {
@ -78,8 +78,6 @@ Singleton {
} }
IpcHandler { IpcHandler {
target: "mpris"
function getActive(prop: string): string { function getActive(prop: string): string {
const active = root.active; const active = root.active;
return active ? active[prop] ?? "Invalid property" : "No active player"; return active ? active[prop] ?? "Invalid property" : "No active player";
@ -122,5 +120,7 @@ Singleton {
function stop(): void { function stop(): void {
root.active?.stop(); root.active?.stop();
} }
target: "mpris"
} }
} }

View file

@ -72,11 +72,11 @@ Singleton {
} }
Connections { Connections {
target: Time
// enabled: props.running && !props.paused // enabled: props.running && !props.paused
function onSecondsChanged(): void { function onSecondsChanged(): void {
props.elapsed++; props.elapsed++;
} }
target: Time
} }
} }

View file

@ -46,8 +46,6 @@ Searcher {
}) })
IpcHandler { IpcHandler {
target: "wallpaper"
function get(): string { function get(): string {
return root.actualCurrent; return root.actualCurrent;
} }
@ -59,6 +57,8 @@ Searcher {
function list(): string { function list(): string {
return root.list.map(w => w.path).join("\n"); return root.list.map(w => w.path).join("\n");
} }
target: "wallpaper"
} }
FileView { FileView {

View file

@ -210,10 +210,11 @@ Singleton {
onLocChanged: fetchWeatherData() onLocChanged: fetchWeatherData()
Connections { Connections {
target: Config.services
function onWeatherLocationChanged(): void { function onWeatherLocationChanged(): void {
root.reload(); root.reload();
} }
target: Config.services
} }
// Refresh current location hourly // Refresh current location hourly

View file

@ -50,11 +50,11 @@ Singleton {
} }
Connections { Connections {
target: Config.general
function onLogoChanged(): void { function onLogoChanged(): void {
osRelease.reload(); osRelease.reload();
} }
target: Config.general
} }
Timer { Timer {