diff --git a/Bar/Bar.qml b/Bar/Bar.qml index 037d76c..67c20bf 100644 --- a/Bar/Bar.qml +++ b/Bar/Bar.qml @@ -163,6 +163,7 @@ Scope { offsetX: -39 offsetY: 0 anchors.top: parent.top + visible: Settings.settings.showCorners } } @@ -189,6 +190,7 @@ Scope { offsetX: 39 offsetY: 0 anchors.top: parent.top + visible: Settings.settings.showCorners } } @@ -214,6 +216,7 @@ Scope { offsetX: -39 offsetY: 0 anchors.top: parent.top + visible: Settings.settings.showCorners } } @@ -239,6 +242,7 @@ Scope { offsetX: 39 offsetY: 0 anchors.top: parent.top + visible: Settings.settings.showCorners } } } diff --git a/Bar/Modules/ActiveWindow.qml b/Bar/Modules/ActiveWindow.qml index 2e0aa2d..c01d58d 100644 --- a/Bar/Modules/ActiveWindow.qml +++ b/Bar/Modules/ActiveWindow.qml @@ -128,7 +128,6 @@ PanelWindow { text: ToplevelManager?.activeToplevel?.title && ToplevelManager?.activeToplevel?.title.length > 60 ? ToplevelManager?.activeToplevel?.title.substring(0, 60) + "..." : ToplevelManager?.activeToplevel?.title || "" font.pixelSize: 12 color: Theme.textSecondary - elide: Text.ElideRight anchors.left: icon.right anchors.leftMargin: Settings.settings.showActiveWindowIcon ? 4 : 6 anchors.right: parent.right diff --git a/Bar/Modules/Applauncher.qml b/Bar/Modules/Applauncher.qml index f45269d..4536c15 100644 --- a/Bar/Modules/Applauncher.qml +++ b/Bar/Modules/Applauncher.qml @@ -11,6 +11,23 @@ import "../../Helpers/Fuzzysort.js" as Fuzzysort PanelWithOverlay { id: appLauncherPanel WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand + + function isPinned(app) { + return app && app.execString && Settings.settings.pinnedExecs.indexOf(app.execString) !== -1; + } + function togglePin(app) { + if (!app || !app.execString) return; + var arr = Settings.settings.pinnedExecs ? Settings.settings.pinnedExecs.slice() : []; + var idx = arr.indexOf(app.execString); + if (idx === -1) { + arr.push(app.execString); + } else { + arr.splice(idx, 1); + } + Settings.settings.pinnedExecs = arr; + root.updateFilter(); + } + function showAt() { appLauncherPanelRect.showAt(); } @@ -126,7 +143,22 @@ PanelWithOverlay { return r.obj; })); } - root.filteredApps = results; + // Pinning logic: split into pinned and unpinned + var pinned = []; + var unpinned = []; + for (var i = 0; i < results.length; ++i) { + var app = results[i]; + if (app.execString && Settings.settings.pinnedExecs.indexOf(app.execString) !== -1) { + pinned.push(app); + } else { + unpinned.push(app); + } + } + // Sort pinned alphabetically + pinned.sort(function(a, b) { + return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); + }); + root.filteredApps = pinned.concat(unpinned); root.selectedIndex = 0; } function selectNext() { @@ -143,12 +175,15 @@ PanelWithOverlay { return; var modelData = filteredApps[selectedIndex]; + const termEmu = Quickshell.env("TERMINAL") || Quickshell.env("TERM_PROGRAM") || ""; if (modelData.isCalculator) { Qt.callLater(function () { Quickshell.clipboardText = String(modelData.result); Quickshell.execDetached(["notify-send", "Calculator Result", `${modelData.expr} = ${modelData.result} (copied to clipboard)`]); }); + } else if (modelData.runInTerminal && termEmu){ + Quickshell.execDetached([termEmu, "-e", modelData.execString.trim()]); } else if (modelData.execute) { modelData.execute(); } else { @@ -273,10 +308,14 @@ PanelWithOverlay { Rectangle { anchors.fill: parent - color: hovered || isSelected ? Theme.accentPrimary : "transparent" + color: (hovered || isSelected) + ? Theme.accentPrimary + : (appLauncherPanel.isPinned(modelData) ? Theme.surfaceVariant : "transparent") radius: 12 - border.color: hovered || isSelected ? Theme.accentPrimary : "transparent" - border.width: hovered || isSelected ? 2 : 0 + border.color: appLauncherPanel.isPinned(modelData) + ? "transparent" + : (hovered || isSelected ? Theme.accentPrimary : "transparent") + border.width: appLauncherPanel.isPinned(modelData) ? 0 : (hovered || isSelected ? 2 : 0) Behavior on color { ColorAnimation { duration: 120 @@ -328,7 +367,7 @@ PanelWithOverlay { spacing: 1 Text { text: modelData.name - color: hovered || isSelected ? Theme.onAccent : Theme.textPrimary + color: (hovered || isSelected) ? Theme.onAccent : (appLauncherPanel.isPinned(modelData) ? Theme.textPrimary : Theme.textPrimary) font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall font.bold: hovered || isSelected @@ -338,7 +377,7 @@ PanelWithOverlay { } Text { text: modelData.isCalculator ? (modelData.expr + " = " + modelData.result) : (modelData.comment || modelData.genericName || "No description available") - color: hovered || isSelected ? Theme.onAccent : Theme.textSecondary + color: (hovered || isSelected) ? Theme.onAccent : (appLauncherPanel.isPinned(modelData) ? Theme.textSecondary : Theme.textSecondary) font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeCaption font.italic: !(modelData.comment || modelData.genericName) @@ -355,9 +394,14 @@ PanelWithOverlay { text: modelData.isCalculator ? "content_copy" : "chevron_right" font.family: "Material Symbols Outlined" font.pixelSize: Theme.fontSizeBody - color: hovered || isSelected ? Theme.onAccent : Theme.textSecondary + color: (hovered || isSelected) + ? Theme.onAccent + : (appLauncherPanel.isPinned(modelData) ? Theme.textPrimary : Theme.textSecondary) verticalAlignment: Text.AlignVCenter + Layout.rightMargin: 8 // Add margin to separate from star } + // Add a spacing item between chevron and star + Item { width: 8; height: 1 } } Rectangle { @@ -371,7 +415,14 @@ PanelWithOverlay { id: mouseArea anchors.fill: parent hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: { + // Prevent app launch if click is inside pinArea + if (pinArea.containsMouse) return; + if (mouse.button === Qt.RightButton) { + appLauncherPanel.togglePin(modelData); + return; + } ripple.opacity = 0.18; rippleNumberAnimation.start(); root.selectedIndex = index; @@ -398,6 +449,37 @@ PanelWithOverlay { color: Theme.outline opacity: index === appList.count - 1 ? 0 : 0.10 } + // Pin/Unpin button (move to last child for stacking) + Item { + id: pinArea + width: 28; height: 28 + z: 100 // Ensure above everything else + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + MouseArea { + anchors.fill: parent + preventStealing: true + z: 100 + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + acceptedButtons: Qt.LeftButton | Qt.RightButton + propagateComposedEvents: false + onClicked: { + appLauncherPanel.togglePin(modelData); + event.accepted = true; + } + } + Text { + anchors.centerIn: parent + text: "star" + font.family: "Material Symbols Outlined" + font.pixelSize: Theme.fontSizeSmall + color: (parent.MouseArea.containsMouse || hovered || isSelected) + ? Theme.onAccent + : (appLauncherPanel.isPinned(modelData) ? Theme.textPrimary : Theme.textDisabled) + verticalAlignment: Text.AlignVCenter + } + } } } } diff --git a/Bar/Modules/CustomTrayMenu.qml b/Bar/Modules/CustomTrayMenu.qml index ae60890..5366d7f 100644 --- a/Bar/Modules/CustomTrayMenu.qml +++ b/Bar/Modules/CustomTrayMenu.qml @@ -51,8 +51,8 @@ PopupWindow { Rectangle { id: bg anchors.fill: parent - color: Theme.backgroundElevated || "#222" - border.color: Theme.border || "#444" + color: Theme.surfaceVariant || "#222" + border.color: Theme.outline || "#444" border.width: 1 radius: 12 z: 0 @@ -84,7 +84,7 @@ PopupWindow { anchors.centerIn: parent width: parent.width - 20 height: 1 - color: Qt.darker(Theme.backgroundElevated || "#222", 1.4) + color: Qt.darker(Theme.surfaceVariant || "#222", 1.4) visible: modelData?.isSeparator ?? false } diff --git a/Bar/Modules/Workspace.qml b/Bar/Modules/Workspace.qml index e537118..7d2f788 100644 --- a/Bar/Modules/Workspace.qml +++ b/Bar/Modules/Workspace.qml @@ -168,11 +168,17 @@ Item { color: { if (model.isFocused) return Theme.accentPrimary; - if (model.isActive) - return Theme.accentPrimary.lighter(130); if (model.isUrgent) return Theme.error; - return Qt.lighter(Theme.surfaceVariant, 1.6); + if (model.isActive) + return Theme.accentSecondary; + if (model.isOccupied) + return Qt.darker(Theme.accentSecondary, 1.5); + + if (model.isUrgent) + return Theme.error; + + return Theme.surfaceVariant.lighter(1.5); } scale: model.isFocused ? 1.0 : 0.9 z: 0 @@ -182,7 +188,7 @@ Item { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: { - WorkspaceManager.switchToWorkspace(model.idx); + WorkspaceManager.switchToWorkspace(model.id); } z: 20 hoverEnabled: true diff --git a/Components/Cava.qml b/Components/Cava.qml index f04c132..1581810 100644 --- a/Components/Cava.qml +++ b/Components/Cava.qml @@ -67,9 +67,9 @@ Scope { process.index = 0; } for (let i = 0; i < data.length; i += 1) { - newValues[i + process.index] = Math.min(data.charCodeAt(i), 128) / 128; + newValues[process.index] = Math.min(data.charCodeAt(i), 128) / 128; + process.index = (process.index+1) % count; } - process.index += data.length; values = newValues; } } diff --git a/Components/StyledTooltip.qml b/Components/StyledTooltip.qml index 6fe0f12..49e6694 100644 --- a/Components/StyledTooltip.qml +++ b/Components/StyledTooltip.qml @@ -1,4 +1,4 @@ -import QtQuick +import QtQuick import QtQuick.Window 2.15 import qs.Settings @@ -57,8 +57,8 @@ Window { Rectangle { anchors.fill: parent radius: 6 - color: "#222" - border.color: Theme.backgroundTertiary || "#444" + color: Theme.backgroundTertiary || "#222" + border.color: Theme.outline || "#444" border.width: 1 opacity: 0.97 z: 1 diff --git a/Helpers/Weather.js b/Helpers/Weather.js index 538ade2..52b83eb 100644 --- a/Helpers/Weather.js +++ b/Helpers/Weather.js @@ -1,5 +1,5 @@ function fetchCoordinates(city, callback, errorCallback) { - var geoUrl = "https://geocoding-api.open-meteo.com/v1/search?name=" + encodeURIComponent(city) + "&count=1&language=en&format=json"; + var geoUrl = "https://geocoding-api.open-meteo.com/v1/search?name=" + encodeURIComponent(city) + "&language=en&format=json"; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE) { diff --git a/README.md b/README.md index 1c2aed4..6dc3b90 100644 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ You will need to install a few things to get everything working: - `swww` to add fancy wallpaper animations (optional) - `wallust` to theme the setup based on wallpaper (optional) -## zigstat and zigbrightnesss is bundled - source can be found [here](https://git.pika-os.com/wm-packages/pikabar/src/t). +## zigstat and zigbrightnesss is bundled - source can be found [here](https://git.pika-os.com/wm-packages/pikabar/src/branch/main/src) ## Known issues diff --git a/Services/Niri.qml b/Services/Niri.qml index a8f551a..fd003cb 100644 --- a/Services/Niri.qml +++ b/Services/Niri.qml @@ -49,10 +49,10 @@ Singleton { isFocused: ws.is_focused === true, isActive: ws.is_active === true, isUrgent: ws.is_urgent === true, - activeWindowId: ws.active_window_id + isOccupied: ws.active_window_id ? true : false }); } - + workspacesList.sort((a, b) => { if (a.output !== b.output) { return a.output.localeCompare(b.output); diff --git a/Services/WorkspaceManager.qml b/Services/WorkspaceManager.qml index f2f7bcb..b5dc29c 100644 --- a/Services/WorkspaceManager.qml +++ b/Services/WorkspaceManager.qml @@ -124,7 +124,8 @@ Singleton { output: ws.output || "", isFocused: ws.isFocused === true, isActive: ws.isActive === true, - isUrgent: ws.isUrgent === true + isUrgent: ws.isUrgent === true, + isOccupied: ws.isOccupied === true, }); } diff --git a/Settings/Settings.qml b/Settings/Settings.qml index 17941bc..b5bddb4 100644 --- a/Settings/Settings.qml +++ b/Settings/Settings.qml @@ -45,6 +45,7 @@ Singleton { property string videoPath: "~/Videos/" property bool showActiveWindowIcon: false property bool showSystemInfoInBar: false + property bool showCorners: true property bool showMediaInBar: false property bool useSWWW: false property bool randomWallpaper: false diff --git a/Settings/Theme.qml b/Settings/Theme.qml index ab61f04..74f3afc 100644 --- a/Settings/Theme.qml +++ b/Settings/Theme.qml @@ -112,4 +112,3 @@ Singleton { property int fontSizeSmall: Math.round(14 * fontSizeMultiplier) // Small text like clock, labels property int fontSizeCaption: Math.round(12 * fontSizeMultiplier) // Captions and fine print } - diff --git a/Widgets/Notification/NotificationPopup.qml b/Widgets/Notification/NotificationPopup.qml index 10324c0..42ad0ba 100644 --- a/Widgets/Notification/NotificationPopup.qml +++ b/Widgets/Notification/NotificationPopup.qml @@ -39,6 +39,7 @@ PanelWindow { appName: notification.appName || "Notification", summary: notification.summary || "", body: notification.body || "", + urgency: notification.urgency || 0, rawNotification: notification, appeared: false, dismissed: false @@ -91,6 +92,8 @@ PanelWindow { width: parent.width color: Theme.backgroundPrimary radius: 20 + border.color: model.urgency == 2 ? Theme.warning : Theme.outline + border.width: 1 property bool appeared: model.appeared property bool dismissed: model.dismissed diff --git a/Widgets/Sidebar/Config/ProfileSettings.qml b/Widgets/Sidebar/Config/ProfileSettings.qml index b1b800f..9f5fdb9 100644 --- a/Widgets/Sidebar/Config/ProfileSettings.qml +++ b/Widgets/Sidebar/Config/ProfileSettings.qml @@ -7,7 +7,7 @@ import qs.Settings Rectangle { id: profileSettingsCard Layout.fillWidth: true - Layout.preferredHeight: 540 + Layout.preferredHeight: 580 color: Theme.surface radius: 18 border.color: "transparent" @@ -252,6 +252,61 @@ Rectangle { } } + // Show Corners In Bar Setting + RowLayout { + spacing: 8 + Layout.fillWidth: true + Layout.topMargin: 8 + + Text { + text: "Show Corners" + font.family: Theme.fontFamily + font.pixelSize: 13 + font.bold: true + color: Theme.textPrimary + Layout.alignment: Qt.AlignVCenter + } + + Item { + Layout.fillWidth: true + } + + // Custom Material 3 Switch + Rectangle { + id: customSwitch4 + width: 52 + height: 32 + radius: 16 + color: Settings.settings.showCorners ? Theme.accentPrimary : Theme.surfaceVariant + border.color: Settings.settings.showCorners ? Theme.accentPrimary : Theme.outline + border.width: 2 + + Rectangle { + id: thumb4 + width: 28 + height: 28 + radius: 14 + color: Theme.surface + border.color: Theme.outline + border.width: 1 + y: 2 + x: Settings.settings.showCorners ? customSwitch4.width - width - 2 : 2 + + Behavior on x { + NumberAnimation { duration: 200; easing.type: Easing.OutCubic } + } + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + Settings.settings.showCorners = !Settings.settings.showCorners + } + } + } + } + // Show Media In Bar Setting RowLayout { spacing: 8 diff --git a/shell.qml b/shell.qml index 6be575b..8cb676c 100644 --- a/shell.qml +++ b/shell.qml @@ -71,6 +71,7 @@ Scope { appName: notification.appName || "Notification", summary: notification.summary || "", body: notification.body || "", + urgency: notification.urgency, timestamp: Date.now() }); }