Created new hover window, theming changes

This commit is contained in:
Amaro Lopes
2025-09-24 01:04:31 -03:00
parent 01afd5718c
commit 161988cbb6
7 changed files with 205 additions and 92 deletions

View File

@@ -2,6 +2,7 @@ import QtQuick
import Quickshell.Io import Quickshell.Io
import Quickshell.Services.Pipewire import Quickshell.Services.Pipewire
import qs.Common import qs.Common
import qs.Services
Rectangle { Rectangle {
id: audioWidget id: audioWidget
@@ -10,6 +11,7 @@ Rectangle {
property string icon: " " property string icon: " "
property bool audioPipewireActive: Pipewire.defaultAudioSink? true:false property bool audioPipewireActive: Pipewire.defaultAudioSink? true:false
property int volume: audioPipewireActive? Math.round(Pipewire.defaultAudioSink.audio.volume * 100): 30 property int volume: audioPipewireActive? Math.round(Pipewire.defaultAudioSink.audio.volume * 100): 30
property var sink: audioPipewireActive? Pipewire.defaultAudioSink : null
implicitWidth: audioText.implicitWidth * 1.6 implicitWidth: audioText.implicitWidth * 1.6
implicitHeight: Theme.heightGaps implicitHeight: Theme.heightGaps
@@ -79,6 +81,14 @@ Rectangle {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true
onEntered: {
PopUpHover.start(audioWidget,"audio")
}
onExited: {
// PopUpHover.exit()
PopUpHover.exit()
}
onClicked: { onClicked: {
audioWidgetProcess.startDetached(); audioWidgetProcess.startDetached();
} }
@@ -96,5 +106,4 @@ Rectangle {
} }
} }
} }
} }

View File

@@ -4,17 +4,16 @@ import qs.Common
PanelWindow { PanelWindow {
id: root id: root
property var panelMonitor: "DP-1" property var modelData: null
property var panelMonitor: modelData? modelData.name:"DP-1"
property var barComponentsLeft: [] property var barComponentsLeft: []
property var barComponentsCenter: [] property var barComponentsCenter: []
property var barComponentsRight: [] property var barComponentsRight: []
screen:modelData
implicitHeight: Theme.barSize implicitHeight: Theme.barSize
color: Qt.rgba(0.68, 0.75, 0.88,0) color: Qt.rgba(0.68, 0.75, 0.88,0)
screen: Quickshell.screens.filter((screen) => {
return screen.name == panelMonitor;
})[0]
anchors { anchors {
top: true top: true

18
Common/HoverMediator.qml Normal file
View File

@@ -0,0 +1,18 @@
pragma Singleton
import Quickshell
import qs.Common
Singleton {
id: mediatorRoot
property var component: null
property string type: ""
property int width: 100
property int height: 100
property int x: component? component.implicitWidth : 0
property int y: component? (component.implicitHeight + Theme.gaps) : 100
property bool visible: false
}

View File

@@ -11,7 +11,8 @@ Singleton {
readonly property double heightGaps: barSize * 0.8 readonly property double heightGaps: barSize * 0.8
readonly property string fontFamily: "Source Code Pro" readonly property string fontFamily: "Source Code Pro"
readonly property int gaps: 5 readonly property int gaps: 5
readonly property int animationDuration: 200
// Colors // Colors
FileView { FileView {
id: walColors id: walColors

115
Services/PopUpHover.qml Normal file
View File

@@ -0,0 +1,115 @@
pragma Singleton
import QtQuick
import QtQuick.Layouts
// Workspaces.qml
import Quickshell
import Quickshell.Widgets
import qs.Common
import qs.Services
Singleton {
function start(component, type) {
HoverMediator.component = component
HoverMediator.type = type
hoverTimer.start()
}
function exit() {
hoverTimer.stop()
wsPopUp.opacity=0
}
PopupWindow {
id: hoverPopUp
anchor.item: HoverMediator.component
property bool initialized: false
anchor.rect.y: HoverMediator.y
anchor.rect.x: (HoverMediator.x - this.implicitWidth)/2
implicitHeight: wsPopUp.implicitHeight
implicitWidth: wsPopUp.implicitWidth
// implicitHeight: HoverMediator.height
// implicitWidth: HoverMediator.width
color:"transparent"
visible:true
Component {
id: stub
Text {
text: "stub"
}
}
Component {
id: audio
Text {
property string sinkDescription:(HoverMediator.component && HoverMediator.component.sink)? HoverMediator.component.sink.description : ""
text: sinkDescription
color:"white"
}
}
Component {
id: workspaceComponent
RowLayout {
id: wsPopUpRow
property int workspaceIndexAlign: HoverMediator.component.workspaceIndexAlign || 0
Repeater {
property var modelo: HyprlandService.sortedDesktopApplications.get(parent.workspaceIndexAlign)
model: modelo
delegate: IconImage {
required property var modelData
width:30; height:30
source: (modelData && modelData.icon) ? Quickshell.iconPath(modelData.icon, 1) : ""
}
}
}
}
WrapperRectangle {
id: wsPopUp
leftMargin: (Theme.gaps * 2)
rightMargin: (Theme.gaps * 2)
topMargin: Theme.gaps
bottomMargin: Theme.gaps
color: Theme.backgroudColor
radius: 25
opacity: 0
Behavior on opacity {
NumberAnimation { property: "opacity"; duration: Theme.animationDuration}
}
Loader {
id: hoverLoader
sourceComponent: {
if(!HoverMediator.type) return stub
if(HoverMediator.type === "workspace") return workspaceComponent
if(HoverMediator.type === "audio") return audio
}
}
}
}
Timer {
id: hoverTimer
interval: 300
onTriggered: {
wsPopUp.opacity = 1
// hoverPopUp.visible = true
}
}
}

View File

@@ -1,3 +1,5 @@
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
// Workspaces.qml // Workspaces.qml
@@ -33,6 +35,7 @@ WrapperMouseArea {
Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
Repeater { Repeater {
id:workspacesRepeater
property var monitor: parent.monitor property var monitor: parent.monitor
@@ -41,84 +44,49 @@ WrapperMouseArea {
delegate: Rectangle { delegate: Rectangle {
id: workspacesRectangle id: workspacesRectangle
property string type: "workspace"
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 int workspaceIndex: parent.monitor === "DP-2" ? modelData + 5 : modelData property int workspaceIndex: parent.monitor === "DP-2" ? modelData + 5 : modelData
property int workspaceIndexAlign: workspaceIndex+1 property int workspaceIndexAlign: workspaceIndex+1
property var workspace: Hyprland.workspaces.values.length > workspaceIndex ? Hyprland.workspaces.values[workspaceIndex] : null 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 bool workspaceActive: workspace === Hyprland.focusedWorkspace? true:false
property var topLevels: HyprlandService.topLevelWorkspaces
property var hasTopLevel: topLevels.filter(topLevelworkspace => topLevelworkspace.id === workspaceIndexAlign).length ? 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: workspaceActive? Theme.barSize* 1.5 : Theme.barSize
radius: 25 radius: 25
color: {
if (workspaceActive) { states: [
return Theme.color6 State {
} name: "Active"
if (hasTopLevel) { when: workspacesRectangle.workspaceActive
PropertyChanges { workspacesRectangle{ color: Theme.color6; implicitWidth: Theme.barSize*1.5}}
return Theme.backgroudColorBright },
State {
name: "Filled"
when: !workspacesRectangle.workspaceActive && workspacesRectangle.hasTopLevel
PropertyChanges { workspacesRectangle{ color: Theme.backgroudColorBright; implicitWidth: Theme.barSize}}
},
State {
name: "Empty"
when: !workspacesRectangle.workspaceActive && !workspacesRectangle.hasTopLevel
PropertyChanges { workspacesRectangle{ color: Theme.backgroudColor;implicitWidth: Theme.barSize}}
} }
return Theme.backgroudColor ]
Behavior on color {
ColorAnimation {duration: Theme.animationDuration}
} }
PopupWindow { Behavior on implicitWidth {
id: workspacesPopUp NumberAnimation {
duration: Theme.animationDuration
property int workspaceIndexAlign: workspacesRectangle.workspaceIndexAlign
anchor.item: workspacesRectangle
anchor.rect.y: workspacesRectangle.implicitHeight+5
anchor.rect.x: -implicitWidth/2 + workspacesRectangle.implicitWidth/2
implicitWidth: wsPopUp.implicitWidth
implicitHeight: wsPopUp.implicitHeight
color:"transparent"
WrapperRectangle {
id: wsPopUp
property int workspaceIndexAlign: workspacesPopUp.workspaceIndexAlign
leftMargin: Theme.gaps*2
rightMargin: Theme.gaps*2
topMargin: Theme.gaps
bottomMargin: Theme.gaps
color: Theme.backgroudColor
radius: 25
RowLayout {
id: wsPopUpRow
property int workspaceIndexAlign: parent.workspaceIndexAlign
anchors{
horizontalCenter:parent.horizontalCenter
verticalCenter:parent.verticalCenter
}
Repeater {
property var modelo: HyprlandService.sortedDesktopApplications.get(parent.workspaceIndexAlign)
model: modelo
delegate: IconImage {
required property var modelData
width:30; height:30
source: (modelData && modelData.icon) ? Quickshell.iconPath(modelData.icon, 1) : ""
}
}
}
} }
} }
Timer {
id: workspacesTimer
interval: 300
onTriggered: { workspacesPopUp.visible = true }
}
Text { Text {
property int workspaceName: workspacesRectangle.workspaceIndexAlign > 5? workspacesRectangle.workspaceIndexAlign -5: workspacesRectangle.workspaceIndexAlign property int workspaceName: workspacesRectangle.workspaceIndexAlign > 5? workspacesRectangle.workspaceIndexAlign -5: workspacesRectangle.workspaceIndexAlign
@@ -132,31 +100,25 @@ WrapperMouseArea {
} }
MouseArea { MouseArea {
anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onEntered: { onEntered: {
if (parent.hasTopLevel) { if (parent.hasTopLevel) {
workspacesTimer.start() // PopUpHover.show(workspacesRectangle)
PopUpHover.start(workspacesRectangle, "workspace")
} }
} }
onExited: { onExited: {
workspacesTimer.stop() // PopUpHover.exit()
workspacesPopUp.visible = false PopUpHover.exit()
} }
anchors.fill: parent
onClicked: { onClicked: {
if(workspacesRectangle.workspace.id === Hyprland.focusedWorkspace.id) {return} ; if(workspacesRectangle.workspace.id === Hyprland.focusedWorkspace.id) {return} ;
Hyprland.dispatch("workspace " + workspacesRectangle.workspace.id); Hyprland.dispatch("workspace " + workspacesRectangle.workspace.id);
} }
} }
Behavior on implicitWidth {
NumberAnimation {
duration: 100
}
}
} }
} }

View File

@@ -2,18 +2,27 @@
import Quickshell import Quickshell
ShellRoot { ShellRoot {
Bar { // Bar {
panelMonitor: "DP-1" // modelData: Quickshell.screens.values[0]
barComponentsLeft: ["NotificationsWidget.qml"] // barComponentsLeft: ["NotificationsWidget.qml"]
barComponentsCenter: ["Workspaces.qml"] // barComponentsCenter: ["Workspaces.qml"]
barComponentsRight: ["AudioWidget.qml", "SysTrayWidget.qml", "ClockWidget.qml"] // barComponentsRight: ["AudioWidget.qml", "SysTrayWidget.qml", "ClockWidget.qml"]
} // }
Bar { // Bar {
panelMonitor: "DP-2" // panelMonitor: "DP-2"
barComponentsLeft: [] // barComponentsLeft: []
barComponentsCenter: ["Workspaces.qml"] // barComponentsCenter: ["Workspaces.qml"]
barComponentsRight: ["AudioWidget.qml", "ClockWidget.qml"] // barComponentsRight: ["AudioWidget.qml", "ClockWidget.qml"]
} // }
} Variants {
model: Quickshell.screens
delegate: Bar{
modelData: item
barComponentsLeft: ["NotificationsWidget.qml"]
barComponentsCenter: ["Workspaces.qml"]
barComponentsRight: ["AudioWidget.qml", "SysTrayWidget.qml", "ClockWidget.qml"]
}
}
}