Fix Warnings and implements Systray
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import Quickshell.Services.Pipewire
|
import Quickshell.Services.Pipewire
|
||||||
import Quickshell.Widgets
|
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -10,7 +8,8 @@ Rectangle {
|
|||||||
|
|
||||||
property string monitor: ""
|
property string monitor: ""
|
||||||
property string icon: " "
|
property string icon: " "
|
||||||
property int volume: Math.round(Pipewire.defaultAudioSink.audio.volume * 100)
|
property bool audioPipewireActive: Pipewire.defaultAudioSink? true:false
|
||||||
|
property int volume: audioPipewireActive? Math.round(Pipewire.defaultAudioSink.audio.volume * 100): 30
|
||||||
|
|
||||||
implicitWidth: audioText.implicitWidth * 1.6
|
implicitWidth: audioText.implicitWidth * 1.6
|
||||||
implicitHeight: Theme.heightGaps
|
implicitHeight: Theme.heightGaps
|
||||||
@@ -55,17 +54,19 @@ Rectangle {
|
|||||||
audioWidget.volume = Math.round(Pipewire.defaultAudioSink.audio.volume * 100);
|
audioWidget.volume = Math.round(Pipewire.defaultAudioSink.audio.volume * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
target: Pipewire.defaultAudioSink.audio
|
target: audioWidget.audioPipewireActive? Pipewire.defaultAudioSink.audio: null
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: audioText
|
id: audioText
|
||||||
|
|
||||||
|
property string audioTextText: audioWidget.audioPipewireActive? audioWidget.icon + " " + Math.round(Pipewire.defaultAudioSink.audio.volume * 100).toString() + "%" : ""
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: audioWidget.icon + " " + Math.round(Pipewire.defaultAudioSink.audio.volume * 100).toString() + "%"
|
text: audioTextText
|
||||||
font.bold: true
|
font.bold: true
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
font.family: root.fontFamily
|
font.family: Theme.fontFamily
|
||||||
color: Theme.textColor
|
color: Theme.textColor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,61 +77,8 @@ Rectangle {
|
|||||||
command: ["pavucontrol"]
|
command: ["pavucontrol"]
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
|
||||||
id: audioTimer
|
|
||||||
|
|
||||||
interval: 1000
|
|
||||||
onTriggered: {
|
|
||||||
audioPopUp.visible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PopupWindow {
|
|
||||||
id: audioPopUp
|
|
||||||
|
|
||||||
anchor.window: root
|
|
||||||
anchor.rect.x: barArea.x
|
|
||||||
anchor.rect.y: root.implicitHeight
|
|
||||||
implicitWidth: 500
|
|
||||||
implicitHeight: 500
|
|
||||||
color: "transparent"
|
|
||||||
|
|
||||||
Item {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
color: "teal"
|
|
||||||
radius: 25
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "opa"
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
hoverEnabled: true
|
|
||||||
onExited: {
|
|
||||||
audioPopUp.visible = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on visible {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: 1000 // Matches your original duration
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
audioWidgetProcess.startDetached();
|
audioWidgetProcess.startDetached();
|
||||||
}
|
}
|
||||||
@@ -147,13 +95,6 @@ Rectangle {
|
|||||||
Pipewire.defaultAudioSink.audio.volume = (audioWidget.volume - 5) / 100;
|
Pipewire.defaultAudioSink.audio.volume = (audioWidget.volume - 5) / 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onEntered: {
|
|
||||||
audioTimer.start();
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
audioPopUp.visible = false;
|
|
||||||
audioTimer.stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import Quickshell.Widgets
|
import Quickshell.Widgets
|
||||||
|
import qs.Common
|
||||||
|
|
||||||
WrapperRectangle {
|
WrapperRectangle {
|
||||||
id: barArea
|
id: barArea
|
||||||
@@ -10,7 +11,8 @@ WrapperRectangle {
|
|||||||
property var components: [] // Add this new property
|
property var components: [] // Add this new property
|
||||||
|
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
margin: 0
|
rightMargin: Theme.gaps
|
||||||
|
leftMargin: Theme.gaps
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Repeater {
|
Repeater {
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ Item {
|
|||||||
property var monitor: ""
|
property var monitor: ""
|
||||||
|
|
||||||
MarginWrapperManager {
|
MarginWrapperManager {
|
||||||
rightMargin: 10
|
rightMargin: Theme.gaps
|
||||||
|
leftMargin: Theme.gaps
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ Singleton {
|
|||||||
|
|
||||||
readonly property int barSize: 35
|
readonly property int barSize: 35
|
||||||
readonly property double heightGaps: barSize * 0.8
|
readonly property double heightGaps: barSize * 0.8
|
||||||
|
readonly property string fontFamily: "Source Code Pro"
|
||||||
|
readonly property int gaps: 5
|
||||||
|
|
||||||
// Colors
|
// Colors
|
||||||
FileView {
|
FileView {
|
||||||
@@ -38,7 +40,7 @@ Singleton {
|
|||||||
property color color7Bright: walColorsText[14]
|
property color color7Bright: walColorsText[14]
|
||||||
property color foregroundColorBright: walColorsText[15]
|
property color foregroundColorBright: walColorsText[15]
|
||||||
|
|
||||||
readonly property string textColor: foregroundColor
|
readonly property color textColor: foregroundColor
|
||||||
// background "#0e1721"
|
// background "#0e1721"
|
||||||
// color2 "#463e44"
|
// color2 "#463e44"
|
||||||
// color3 "#7b4834"
|
// color3 "#7b4834"
|
||||||
|
|||||||
@@ -2,12 +2,17 @@ pragma Singleton
|
|||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
|
import Quickshell.Wayland
|
||||||
|
|
||||||
Singleton {
|
Singleton {
|
||||||
|
|
||||||
readonly property string hyprlandSignature: Quickshell.env("HYPRLAND_INSTANCE_SIGNATURE")
|
readonly property string hyprlandSignature: Quickshell.env("HYPRLAND_INSTANCE_SIGNATURE")
|
||||||
|
|
||||||
property var sortedTopLevels: {
|
property var sortedTopLevels: {
|
||||||
|
if (!ToplevelManager.toplevels || !ToplevelManager.toplevels.values) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
const topLevels = Array.from(Hyprland.toplevels.values)
|
const topLevels = Array.from(Hyprland.toplevels.values)
|
||||||
const sortedHyprland = topLevels.sort((a, b) => {
|
const sortedHyprland = topLevels.sort((a, b) => {
|
||||||
if (a.monitor && b.monitor) {
|
if (a.monitor && b.monitor) {
|
||||||
@@ -50,7 +55,7 @@ Singleton {
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
})
|
})
|
||||||
return sortedHyprland
|
return sortedHyprland.filter(tl => tl.wayland !== null)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +64,10 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
property var sortedDesktopApplications: {
|
property var sortedDesktopApplications: {
|
||||||
const desktopEntries = sortedTopLevels.map( topLevel => {
|
const sortedWayland = sortedTopLevels.map(topLevel => topLevel.wayland).filter(wayland=> wayland !== null)
|
||||||
return DesktopEntries.heuristicLookup(topLevel.wayland.appId)
|
|
||||||
|
const desktopEntries = sortedWayland.map( topLevel => {
|
||||||
|
return DesktopEntries.heuristicLookup(topLevel.appId)
|
||||||
})
|
})
|
||||||
const workspace = sortedTopLevels.map( topLevel => {
|
const workspace = sortedTopLevels.map( topLevel => {
|
||||||
return topLevel.workspace.id
|
return topLevel.workspace.id
|
||||||
|
|||||||
@@ -6,38 +6,92 @@ import Quickshell.Widgets
|
|||||||
import Quickshell.Services.SystemTray
|
import Quickshell.Services.SystemTray
|
||||||
import qs.Common
|
import qs.Common
|
||||||
|
|
||||||
Item {
|
WrapperRectangle {
|
||||||
|
id: systrayRoot
|
||||||
property var monitor: ""
|
property var monitor: ""
|
||||||
|
rightMargin: Theme.gaps
|
||||||
|
leftMargin: Theme.gaps
|
||||||
|
radius: 25
|
||||||
|
|
||||||
MarginWrapperManager {
|
color: Theme.backgroudColor
|
||||||
leftMargin: 5
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
// color: Theme.backgroudColor
|
||||||
color:"blue"
|
RowLayout {
|
||||||
implicitHeight: 50
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||||
implicitWidth: 50
|
Repeater {
|
||||||
// color: Theme.backgroudColor
|
model: SystemTray.items.values
|
||||||
radius: 25
|
delegate: Rectangle {
|
||||||
RowLayout {
|
id: systrayItem
|
||||||
anchors{
|
|
||||||
horizontalCenter:parent.horizontalCenter
|
required property var modelData
|
||||||
verticalCenter:parent.verticalCenter
|
property var model: modelData
|
||||||
}
|
property string iconSource: {
|
||||||
Repeater {
|
let icon = systrayItem.model && systrayItem.model.icon;
|
||||||
model: SystemTray.items.values
|
if (typeof icon === 'string' || icon instanceof String) {
|
||||||
delegate: IconImage {
|
if (icon.includes("?path=")) {
|
||||||
required property var modelData
|
const split = icon.split("?path=");
|
||||||
width:30; height:30
|
if (split.length !== 2) {
|
||||||
source: modelData.icon
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = split[0];
|
||||||
|
const path = split[1];
|
||||||
|
const fileName = name.substring(name.lastIndexOf("/") + 1);
|
||||||
|
return `file://${path}/${fileName}`;
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
implicitHeight: 30
|
||||||
|
implicitWidth: 30
|
||||||
|
color:"transparent"
|
||||||
|
|
||||||
|
IconImage {
|
||||||
|
anchors.verticalCenter:parent.verticalCenter
|
||||||
|
anchors.horizontalCenter:parent.horizontalCenter
|
||||||
|
width:25; height:25
|
||||||
|
source: iconSource
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||||
|
onClicked: (mouse) => {
|
||||||
|
if (mouse.button === Qt.RightButton) {
|
||||||
|
|
||||||
|
const globalPos = mapToGlobal(0, 0);
|
||||||
|
|
||||||
|
const currentScreen = systrayRoot.monitor
|
||||||
|
const screenX = currentScreen.x || 0;
|
||||||
|
console.log(screenX)
|
||||||
|
const relativeX = globalPos.x - screenX;
|
||||||
|
menuAnchor.menu = systrayItem.model.menu;
|
||||||
|
menuAnchor.anchor.window = root;
|
||||||
|
menuAnchor.anchor.rect = Qt.rect(
|
||||||
|
globalPos.x,
|
||||||
|
globalPos.y+10,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
menuAnchor.open();
|
||||||
|
|
||||||
|
} else if (mouse.button === Qt.LeftButton) {
|
||||||
|
// systrayItem.model.activate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onDoubleClicked: {
|
||||||
|
systrayItem.model.activate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseArea {
|
}
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
QsMenuAnchor {
|
||||||
console.log(SystemTray.items.values[0].icon)
|
id: menuAnchor
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,8 @@ import qs.Common
|
|||||||
import qs.Services
|
import qs.Services
|
||||||
|
|
||||||
WrapperMouseArea {
|
WrapperMouseArea {
|
||||||
id: workspacesRoot
|
id: workspacesWidget
|
||||||
|
|
||||||
property var monitor: "black"
|
property var monitor: "black"
|
||||||
|
|
||||||
onWheel: (wheel) => {
|
onWheel: (wheel) => {
|
||||||
@@ -26,28 +27,39 @@ WrapperMouseArea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
|
||||||
|
property var monitor: workspacesWidget.monitor
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
|
|
||||||
|
property var monitor: parent.monitor
|
||||||
|
|
||||||
model: 5
|
model: 5
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
id: workspacesRectangle
|
id: workspacesRectangle
|
||||||
|
|
||||||
required property var modelData
|
required property var modelData
|
||||||
property var index: modelData // Get the workspace data from the model
|
property var index: modelData // Get the workspace data from the model
|
||||||
property var workspace: {
|
property int workspaceIndex: parent.monitor === "DP-2" ? modelData + 5 : modelData
|
||||||
workspacesRoot.monitor === "DP-2" ? Hyprland.workspaces.values[index + 5] : Hyprland.workspaces.values[index];
|
property int workspaceIndexAlign: workspaceIndex+1
|
||||||
}
|
property var workspace: Hyprland.workspaces.values.length > workspaceIndex ? Hyprland.workspaces.values[workspaceIndex] : null
|
||||||
|
property var topLevels: HyprlandService.topLevelWorkspaces
|
||||||
|
property bool workspaceActive: workspace === Hyprland.focusedWorkspace? true:false
|
||||||
|
property var hasTopLevel: topLevels.filter(topLevelworkspace => topLevelworkspace.id === workspaceIndexAlign).length ? true:false
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
|
||||||
implicitHeight: Theme.heightGaps
|
implicitHeight: Theme.heightGaps
|
||||||
implicitWidth: workspace.id === Hyprland.focusedWorkspace.id ? Theme.barSize* 1.5 : Theme.barSize
|
implicitWidth: workspaceActive? Theme.barSize* 1.5 : Theme.barSize
|
||||||
radius: 25
|
radius: 25
|
||||||
color: {
|
color: {
|
||||||
if (workspace.id === Hyprland.focusedWorkspace.id) {
|
if (workspaceActive) {
|
||||||
return Theme.color6
|
return Theme.color6
|
||||||
}
|
}
|
||||||
if (HyprlandService.topLevelWorkspaces.filter(topLevelworkspace => topLevelworkspace.id === workspace.id).length) {
|
if (hasTopLevel) {
|
||||||
|
|
||||||
return Theme.backgroudColorBright
|
return Theme.backgroudColorBright
|
||||||
}
|
}
|
||||||
return Theme.backgroudColor
|
return Theme.backgroudColor
|
||||||
@@ -55,27 +67,45 @@ WrapperMouseArea {
|
|||||||
|
|
||||||
PopupWindow {
|
PopupWindow {
|
||||||
id: workspacesPopUp
|
id: workspacesPopUp
|
||||||
|
|
||||||
|
property int workspaceIndexAlign: workspacesRectangle.workspaceIndexAlign
|
||||||
|
|
||||||
anchor.item: workspacesRectangle
|
anchor.item: workspacesRectangle
|
||||||
anchor.rect.y: workspacesRectangle.implicitHeight+5
|
anchor.rect.y: workspacesRectangle.implicitHeight+5
|
||||||
anchor.rect.x: -implicitWidth/2 + workspacesRectangle.implicitWidth/2
|
anchor.rect.x: -implicitWidth/2 + workspacesRectangle.implicitWidth/2
|
||||||
implicitWidth: wsPopUpRow.implicitWidth*1.6
|
implicitWidth: wsPopUp.implicitWidth
|
||||||
implicitHeight: 35
|
implicitHeight: wsPopUp.implicitHeight
|
||||||
color:"transparent"
|
color:"transparent"
|
||||||
|
WrapperRectangle {
|
||||||
|
id: wsPopUp
|
||||||
|
|
||||||
Rectangle {
|
property int workspaceIndexAlign: workspacesPopUp.workspaceIndexAlign
|
||||||
anchors.fill: parent
|
|
||||||
|
leftMargin: Theme.gaps*2
|
||||||
|
rightMargin: Theme.gaps*2
|
||||||
|
topMargin: Theme.gaps
|
||||||
|
bottomMargin: Theme.gaps
|
||||||
color: Theme.backgroudColor
|
color: Theme.backgroudColor
|
||||||
radius: 25
|
radius: 25
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
id: wsPopUpRow
|
||||||
|
|
||||||
|
property int workspaceIndexAlign: parent.workspaceIndexAlign
|
||||||
|
|
||||||
anchors{
|
anchors{
|
||||||
horizontalCenter:parent.horizontalCenter
|
horizontalCenter:parent.horizontalCenter
|
||||||
verticalCenter:parent.verticalCenter
|
verticalCenter:parent.verticalCenter
|
||||||
}
|
}
|
||||||
id: wsPopUpRow
|
|
||||||
Repeater {
|
Repeater {
|
||||||
model: HyprlandService.sortedDesktopApplications.get(workspacesRectangle.workspace.id)
|
|
||||||
|
property var modelo: HyprlandService.sortedDesktopApplications.get(parent.workspaceIndexAlign)
|
||||||
|
|
||||||
|
model: modelo
|
||||||
delegate: IconImage {
|
delegate: IconImage {
|
||||||
|
|
||||||
required property var modelData
|
required property var modelData
|
||||||
|
|
||||||
width:30; height:30
|
width:30; height:30
|
||||||
source: (modelData && modelData.icon) ? Quickshell.iconPath(modelData.icon, 1) : ""
|
source: (modelData && modelData.icon) ? Quickshell.iconPath(modelData.icon, 1) : ""
|
||||||
}
|
}
|
||||||
@@ -85,12 +115,16 @@ WrapperMouseArea {
|
|||||||
}
|
}
|
||||||
Timer {
|
Timer {
|
||||||
id: workspacesTimer
|
id: workspacesTimer
|
||||||
|
|
||||||
interval: 300
|
interval: 300
|
||||||
onTriggered: { workspacesPopUp.visible = true }
|
onTriggered: { workspacesPopUp.visible = true }
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
|
|
||||||
|
property int workspaceName: workspacesRectangle.workspaceIndexAlign > 5? workspacesRectangle.workspaceIndexAlign -5: workspacesRectangle.workspaceIndexAlign
|
||||||
|
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
text: workspacesRoot.monitor === "DP-2" ? workspacesRectangle.workspace.id - 5 : workspacesRectangle.workspace.id
|
text: workspaceName
|
||||||
font.bold: true
|
font.bold: true
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
font.family: Theme.fontFamily
|
font.family: Theme.fontFamily
|
||||||
@@ -100,7 +134,7 @@ WrapperMouseArea {
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if (HyprlandService.sortedDesktopApplications.get(workspacesRectangle.workspace.id)){
|
if (parent.hasTopLevel) {
|
||||||
workspacesTimer.start()
|
workspacesTimer.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user