Add tooltips, fix tray menu

This commit is contained in:
ly-sec 2025-07-16 13:56:09 +02:00
parent a7fbccaf8b
commit 32e1160f8f
13 changed files with 319 additions and 69 deletions

View file

@ -176,7 +176,7 @@ Scope {
id: bottomLeftCorner id: bottomLeftCorner
position: "topleft" position: "topleft"
size: 1.3 size: 1.3
fillColor: (Theme.backgroundPrimary !== undefined && Theme.backgroundPrimary !== null) ? Theme.backgroundPrimary : "#222" fillColor: "#00FFFF"
offsetX: -39 offsetX: -39
offsetY: 0 offsetY: 0
anchors.top: parent.top anchors.top: parent.top
@ -198,7 +198,7 @@ Scope {
id: bottomRightCorner id: bottomRightCorner
position: "topright" position: "topright"
size: 1.3 size: 1.3
fillColor: (Theme.backgroundPrimary !== undefined && Theme.backgroundPrimary !== null) ? Theme.backgroundPrimary : "#222" fillColor: "#00FFFF"//(Theme.backgroundPrimary !== undefined && Theme.backgroundPrimary !== null) ? Theme.backgroundPrimary : "#222"
offsetX: 39 offsetX: 39
offsetY: 0 offsetY: 0
anchors.top: parent.top anchors.top: parent.top

View file

@ -15,6 +15,7 @@ PanelWindow {
margins.top: barHeight margins.top: barHeight
visible: activeWindowWrapper.shouldShow visible: activeWindowWrapper.shouldShow
implicitHeight: activeWindowTitleContainer.height implicitHeight: activeWindowTitleContainer.height
implicitWidth: activeWindowTitleContainer.x
property int barHeight: 36 property int barHeight: 36
color: "transparent" color: "transparent"

View file

@ -40,6 +40,19 @@ Item {
iconCircleColor: Theme.accentPrimary iconCircleColor: Theme.accentPrimary
iconTextColor: Theme.backgroundPrimary iconTextColor: Theme.backgroundPrimary
textColor: Theme.textPrimary textColor: Theme.textPrimary
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: brightnessTooltip.tooltipVisible = true
onExited: brightnessTooltip.tooltipVisible = false
}
StyledTooltip {
id: brightnessTooltip
text: "Brightness: " + brightness + "%"
tooltipVisible: false
targetItem: pill
delay: 200
}
} }
Component.onCompleted: { Component.onCompleted: {

View file

@ -18,7 +18,7 @@ PopupWindow {
property real anchorY property real anchorY
anchor.item: anchorItem ? anchorItem : null anchor.item: anchorItem ? anchorItem : null
anchor.rect.x: anchorX anchor.rect.x: anchorX + 10
anchor.rect.y: anchorY anchor.rect.y: anchorY
function showAt(item, x, y) { function showAt(item, x, y) {
@ -51,10 +51,10 @@ PopupWindow {
Rectangle { Rectangle {
id: bg id: bg
anchors.fill: parent anchors.fill: parent
color: Theme.backgroundPrimary color: Theme.backgroundElevated || "#222"
border.color: Theme.accentPrimary border.color: Theme.border || "#444"
border.width: 2 border.width: 1
radius: 20 radius: 12
z: 0 z: 0
} }
@ -76,15 +76,15 @@ PopupWindow {
required property var modelData required property var modelData
width: listView.width width: listView.width
height: (modelData?.isSeparator) ? 8 : 28 height: (modelData?.isSeparator) ? 8 : 32
color: "transparent" color: "transparent"
radius: 6 radius: 12
Rectangle { Rectangle {
anchors.centerIn: parent anchors.centerIn: parent
width: parent.width - 20 width: parent.width - 20
height: 1 height: 1
color: Qt.darker(Theme.backgroundPrimary, 1.4) color: Qt.darker(Theme.backgroundElevated || "#222", 1.4)
visible: modelData?.isSeparator ?? false visible: modelData?.isSeparator ?? false
} }
@ -92,14 +92,14 @@ PopupWindow {
id: bg id: bg
anchors.fill: parent anchors.fill: parent
color: mouseArea.containsMouse ? Theme.highlight : "transparent" color: mouseArea.containsMouse ? Theme.highlight : "transparent"
radius: 6 radius: 12
visible: !(modelData?.isSeparator ?? false) visible: !(modelData?.isSeparator ?? false)
property color hoverTextColor: mouseArea.containsMouse ? Theme.onAccent : Theme.textPrimary property color hoverTextColor: mouseArea.containsMouse ? Theme.onAccent : Theme.textPrimary
RowLayout { RowLayout {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: 10 anchors.leftMargin: 12
anchors.rightMargin: 10 anchors.rightMargin: 12
spacing: 8 spacing: 8
Text { Text {

View file

@ -6,6 +6,7 @@ import Qt5Compat.GraphicalEffects
import Quickshell.Services.SystemTray import Quickshell.Services.SystemTray
import Quickshell.Widgets import Quickshell.Widgets
import qs.Settings import qs.Settings
import qs.Components
Row { Row {
property var bar property var bar
@ -110,8 +111,8 @@ Row {
modelData.secondaryActivate && modelData.secondaryActivate() modelData.secondaryActivate && modelData.secondaryActivate()
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
trayTooltip.tooltipVisible = false
console.log("Right click on", modelData.id, "hasMenu:", modelData.hasMenu, "menu:", modelData.menu) console.log("Right click on", modelData.id, "hasMenu:", modelData.hasMenu, "menu:", modelData.menu)
// If menu is already visible, close it // If menu is already visible, close it
if (trayMenu && trayMenu.visible) { if (trayMenu && trayMenu.visible) {
trayMenu.hideMenu() trayMenu.hideMenu()
@ -129,6 +130,16 @@ Row {
} }
} }
} }
onEntered: trayTooltip.tooltipVisible = true
onExited: trayTooltip.tooltipVisible = false
}
StyledTooltip {
id: trayTooltip
text: modelData.name || modelData.id || "Tray Item"
tooltipVisible: false
targetItem: trayIcon
delay: 200
} }
Component.onDestruction: { Component.onDestruction: {

View file

@ -21,6 +21,13 @@ Item {
iconCircleColor: Theme.accentPrimary iconCircleColor: Theme.accentPrimary
iconTextColor: Theme.backgroundPrimary iconTextColor: Theme.backgroundPrimary
textColor: Theme.textPrimary textColor: Theme.textPrimary
StyledTooltip {
id: volumeTooltip
text: "Volume: " + volume + "%\nScroll up/down to change volume"
tooltipVisible: false
targetItem: pillIndicator
delay: 200
}
} }
Connections { Connections {
@ -47,6 +54,8 @@ Item {
hoverEnabled: true hoverEnabled: true
acceptedButtons: Qt.NoButton // Accept wheel events only acceptedButtons: Qt.NoButton // Accept wheel events only
propagateComposedEvents: true propagateComposedEvents: true
onEntered: volumeTooltip.tooltipVisible = true
onExited: volumeTooltip.tooltipVisible = false
onWheel:(wheel) => { onWheel:(wheel) => {
if (!shell) return; if (!shell) return;
let step = 5; let step = 5;

View file

@ -0,0 +1,84 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Window 2.15
import qs.Settings
Window {
id: tooltipWindow
property string text: ""
property bool tooltipVisible: false
property Item targetItem: null
property int delay: 300
flags: Qt.ToolTip | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint
color: "transparent"
visible: false
minimumWidth: Math.max(minimumWidth, tooltipText.implicitWidth + 24)
minimumHeight: Math.max(minimumHeight, tooltipText.implicitHeight + 16)
property var _timerObj: null
onTooltipVisibleChanged: {
if (tooltipVisible) {
if (delay > 0) {
if (_timerObj) { _timerObj.destroy(); _timerObj = null; }
_timerObj = Qt.createQmlObject('import QtQuick 2.0; Timer { interval: ' + delay + '; running: true; repeat: false; onTriggered: tooltipWindow._showNow() }', tooltipWindow);
} else {
_showNow();
}
} else {
_hideNow();
}
}
function _showNow() {
if (!targetItem) return;
var pos = targetItem.mapToGlobal(0, targetItem.height);
x = pos.x - width / 2 + targetItem.width / 2;
y = pos.y + 8;
visible = true;
console.log("StyledTooltip _showNow called");
console.log("StyledTooltip Theme.textPrimary:", Theme.textPrimary);
}
function _hideNow() {
visible = false;
if (_timerObj) { _timerObj.destroy(); _timerObj = null; }
}
Connections {
target: targetItem
onXChanged: if (tooltipWindow.visible) tooltipWindow._showNow()
onYChanged: if (tooltipWindow.visible) tooltipWindow._showNow()
onWidthChanged: if (tooltipWindow.visible) tooltipWindow._showNow()
onHeightChanged: if (tooltipWindow.visible) tooltipWindow._showNow()
}
Component.onCompleted: console.log("Tooltip window loaded")
Rectangle {
anchors.fill: parent
radius: 6
color: "#222"
border.color: Theme.border || "#444"
border.width: 1
opacity: 0.97
z: 1
}
Text {
id: tooltipText
text: tooltipWindow.text
color: Theme.textPrimary
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.Wrap
padding: 8
z: 2
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onExited: tooltipWindow.tooltipVisible = false
cursorShape: Qt.ArrowCursor
}
onTextChanged: {
width = Math.max(minimumWidth, tooltipText.implicitWidth + 24);
height = Math.max(minimumHeight, tooltipText.implicitHeight + 16);
}
}

View file

@ -1,28 +1,28 @@
{ {
"backgroundPrimary": "#0F1012", "backgroundPrimary": "#0E0F10",
"backgroundSecondary": "#1B1C1E", "backgroundSecondary": "#1A1B1C",
"backgroundTertiary": "#27282A", "backgroundTertiary": "#262728",
"surface": "#222325", "surface": "#212223",
"surfaceVariant": "#333436", "surfaceVariant": "#323334",
"textPrimary": "#DBF7F5", "textPrimary": "#F0F1E0",
"textSecondary": "#C5DEDD", "textSecondary": "#D8D9CA",
"textDisabled": "#839493", "textDisabled": "#909186",
"accentPrimary": "#5D9BEC", "accentPrimary": "#A3A485",
"accentSecondary": "#7DAFF0", "accentSecondary": "#B5B69D",
"accentTertiary": "#4A7CBD", "accentTertiary": "#82836A",
"error": "#D687D8", "error": "#A5A9ED",
"warning": "#DFA2E1", "warning": "#B9BCF1",
"highlight": "#9EC3F4", "highlight": "#C8C8B6",
"rippleEffect": "#6DA5EE", "rippleEffect": "#ACAD91",
"onAccent": "#0F1012", "onAccent": "#0E0F10",
"outline": "#575859", "outline": "#565758",
"shadow": "#0F1012", "shadow": "#0E0F10",
"overlay": "#0F1012" "overlay": "#0E0F10"
} }

View file

@ -0,0 +1,29 @@
# Ghostty theme template for wallust
# Add to wallust config: ghostty = { src = "ghostty.conf", dst = "~/.config/ghostty/theme.conf" }
# And add to ghostty config: theme = "theme.conf"
palette = 0={{ color0 }}
palette = 1={{ color1 }}
palette = 2={{ color2 }}
palette = 3={{ color3 }}
palette = 4={{ color4 }}
palette = 5={{ color5 }}
palette = 6={{ color6 }}
palette = 7={{ color7 }}
palette = 8={{ color8 }}
palette = 9={{ color9 }}
palette = 10={{ color10 }}
palette = 11={{ color11 }}
palette = 12={{ color12 }}
palette = 13={{ color13 }}
palette = 14={{ color14 }}
palette = 15={{ color15 }}
background = {{ background }}
foreground = {{ foreground }}
cursor-color = {{ cursor }}
cursor-text = {{ foreground }}
selection-background = {{ color8 }}
selection-foreground = {{ foreground }}

View file

@ -6,7 +6,7 @@ import qs.Settings
PanelWindow { PanelWindow {
id: window id: window
implicitWidth: 350 implicitWidth: 350
implicitHeight: notificationColumn.implicitHeight + 60 implicitHeight: notificationColumn.implicitHeight
color: "transparent" color: "transparent"
visible: notificationModel.count > 0 visible: notificationModel.count > 0
screen: Quickshell.primaryScreen !== undefined ? Quickshell.primaryScreen : null screen: Quickshell.primaryScreen !== undefined ? Quickshell.primaryScreen : null
@ -16,7 +16,7 @@ PanelWindow {
anchors.top: true anchors.top: true
anchors.right: true anchors.right: true
margins.top: barVisible ? -20 : 10 margins.top: 6
margins.right: 6 margins.right: 6
ListModel { ListModel {

View file

@ -16,7 +16,7 @@ PanelWindow {
screen: modelData screen: modelData
anchors.top: true anchors.top: true
anchors.right: true anchors.right: true
margins.top: -24 margins.top: 0
WlrLayershell.keyboardFocus: (settingsModal.visible && mouseArea.containsMouse) ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None WlrLayershell.keyboardFocus: (settingsModal.visible && mouseArea.containsMouse) ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
// Animation properties // Animation properties

View file

@ -3,6 +3,7 @@ import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import Quickshell.Services.UPower import Quickshell.Services.UPower
import qs.Settings import qs.Settings
import qs.Components
Rectangle { Rectangle {
id: card id: card
@ -28,6 +29,7 @@ Rectangle {
opacity: (typeof PowerProfiles !== 'undefined' && !PowerProfiles.hasPerformanceProfile) ? 0.4 : 1 opacity: (typeof PowerProfiles !== 'undefined' && !PowerProfiles.hasPerformanceProfile) ? 0.4 : 1
Text { Text {
id: perfIcon
anchors.centerIn: parent anchors.centerIn: parent
text: "speed" text: "speed"
font.family: "Material Symbols Outlined" font.family: "Material Symbols Outlined"
@ -49,6 +51,15 @@ Rectangle {
if (typeof PowerProfiles !== 'undefined') if (typeof PowerProfiles !== 'undefined')
PowerProfiles.profile = PowerProfile.Performance; PowerProfiles.profile = PowerProfile.Performance;
} }
onEntered: perfTooltip.tooltipVisible = true
onExited: perfTooltip.tooltipVisible = false
}
StyledTooltip {
id: perfTooltip
text: "Performance Profile"
tooltipVisible: false
targetItem: perfIcon
delay: 200
} }
} }
@ -64,6 +75,7 @@ Rectangle {
opacity: 1 opacity: 1
Text { Text {
id: balIcon
anchors.centerIn: parent anchors.centerIn: parent
text: "balance" text: "balance"
font.family: "Material Symbols Outlined" font.family: "Material Symbols Outlined"
@ -85,6 +97,15 @@ Rectangle {
if (typeof PowerProfiles !== 'undefined') if (typeof PowerProfiles !== 'undefined')
PowerProfiles.profile = PowerProfile.Balanced; PowerProfiles.profile = PowerProfile.Balanced;
} }
onEntered: balTooltip.tooltipVisible = true
onExited: balTooltip.tooltipVisible = false
}
StyledTooltip {
id: balTooltip
text: "Balanced Profile"
tooltipVisible: false
targetItem: balIcon
delay: 200
} }
} }
@ -100,6 +121,7 @@ Rectangle {
opacity: 1 opacity: 1
Text { Text {
id: saveIcon
anchors.centerIn: parent anchors.centerIn: parent
text: "eco" text: "eco"
font.family: "Material Symbols Outlined" font.family: "Material Symbols Outlined"
@ -121,6 +143,15 @@ Rectangle {
if (typeof PowerProfiles !== 'undefined') if (typeof PowerProfiles !== 'undefined')
PowerProfiles.profile = PowerProfile.PowerSaver; PowerProfiles.profile = PowerProfile.PowerSaver;
} }
onEntered: saveTooltip.tooltipVisible = true
onExited: saveTooltip.tooltipVisible = false
}
StyledTooltip {
id: saveTooltip
text: "Power Saver Profile"
tooltipVisible: false
targetItem: saveIcon
delay: 200
} }
} }
} }

View file

@ -27,48 +27,120 @@ Rectangle {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
// CPU Usage // CPU Usage
CircularProgressBar { Item {
progress: Sysinfo.cpuUsage / 100 width: 50; height: 50
size: 50 CircularProgressBar {
strokeWidth: 4 id: cpuBar
hasNotch: true progress: Sysinfo.cpuUsage / 100
notchIcon: "speed" size: 50
notchIconSize: 14 strokeWidth: 4
Layout.alignment: Qt.AlignHCenter hasNotch: true
notchIcon: "speed"
notchIconSize: 14
Layout.alignment: Qt.AlignHCenter
}
MouseArea {
id: cpuBarMouse
anchors.fill: parent
hoverEnabled: true
onEntered: cpuTooltip.tooltipVisible = true
onExited: cpuTooltip.tooltipVisible = false
}
StyledTooltip {
id: cpuTooltip
text: 'CPU Usage: ' + Sysinfo.cpuUsage + '%'
tooltipVisible: false
targetItem: cpuBar
delay: 200
}
} }
// Cpu Temp // Cpu Temp
CircularProgressBar { Item {
progress: Sysinfo.cpuTemp / 100 width: 50; height: 50
size: 50 CircularProgressBar {
strokeWidth: 4 id: tempBar
hasNotch: true progress: Sysinfo.cpuTemp / 100
units: "°C" size: 50
notchIcon: "thermometer" strokeWidth: 4
notchIconSize: 14 hasNotch: true
Layout.alignment: Qt.AlignHCenter units: "°C"
notchIcon: "thermometer"
notchIconSize: 14
Layout.alignment: Qt.AlignHCenter
}
MouseArea {
id: tempBarMouse
anchors.fill: parent
hoverEnabled: true
onEntered: tempTooltip.tooltipVisible = true
onExited: tempTooltip.tooltipVisible = false
}
StyledTooltip {
id: tempTooltip
text: 'CPU Temp: ' + Sysinfo.cpuTemp + '°C'
tooltipVisible: false
targetItem: tempBar
delay: 200
}
} }
// Memory Usage // Memory Usage
CircularProgressBar { Item {
progress: Sysinfo.memoryUsagePer / 100 width: 50; height: 50
size: 50 CircularProgressBar {
strokeWidth: 4 id: memBar
hasNotch: true progress: Sysinfo.memoryUsagePer / 100
notchIcon: "memory" size: 50
notchIconSize: 14 strokeWidth: 4
Layout.alignment: Qt.AlignHCenter hasNotch: true
notchIcon: "memory"
notchIconSize: 14
Layout.alignment: Qt.AlignHCenter
}
MouseArea {
id: memBarMouse
anchors.fill: parent
hoverEnabled: true
onEntered: memTooltip.tooltipVisible = true
onExited: memTooltip.tooltipVisible = false
}
StyledTooltip {
id: memTooltip
text: 'Memory Usage: ' + Sysinfo.memoryUsagePer + '% (' + Sysinfo.memoryUsageStr + ' used)'
tooltipVisible: false
targetItem: memBar
delay: 200
}
} }
// Disk Usage // Disk Usage
CircularProgressBar { Item {
progress: Sysinfo.diskUsage / 100 width: 50; height: 50
size: 50 CircularProgressBar {
strokeWidth: 4 id: diskBar
hasNotch: true progress: Sysinfo.diskUsage / 100
notchIcon: "storage" size: 50
notchIconSize: 14 strokeWidth: 4
Layout.alignment: Qt.AlignHCenter hasNotch: true
notchIcon: "storage"
notchIconSize: 14
Layout.alignment: Qt.AlignHCenter
}
MouseArea {
id: diskBarMouse
anchors.fill: parent
hoverEnabled: true
onEntered: diskTooltip.tooltipVisible = true
onExited: diskTooltip.tooltipVisible = false
}
StyledTooltip {
id: diskTooltip
text: 'Disk Usage: ' + Sysinfo.diskUsage + '%'
tooltipVisible: false
targetItem: diskBar
delay: 200
}
} }
} }
} }