mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2026-06-07 04:15:26 +00:00
Tooltips: proper tooltip service
This commit is contained in:
+3
-3
@@ -171,14 +171,14 @@ Singleton {
|
|||||||
// Detect user's favorite locale - languages
|
// Detect user's favorite locale - languages
|
||||||
for (var i = 0; i < Qt.locale().uiLanguages.length; i++) {
|
for (var i = 0; i < Qt.locale().uiLanguages.length; i++) {
|
||||||
const fullUserLang = Qt.locale().uiLanguages[i]
|
const fullUserLang = Qt.locale().uiLanguages[i]
|
||||||
|
|
||||||
// Try full code match (such as zh CN, en US)
|
// Try full code match (such as zh CN, en US)
|
||||||
if (availableLanguages.includes(fullUserLang)) {
|
if (availableLanguages.includes(fullUserLang)) {
|
||||||
Logger.log("I18n", `Exact match found: "${fullUserLang}"`)
|
Logger.log("I18n", `Exact match found: "${fullUserLang}"`)
|
||||||
setLanguage(fullUserLang)
|
setLanguage(fullUserLang)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If full code match fails, try short code matching (such as zh, en)
|
// If full code match fails, try short code matching (such as zh, en)
|
||||||
const shortUserLang = fullUserLang.substring(0, 2)
|
const shortUserLang = fullUserLang.substring(0, 2)
|
||||||
if (availableLanguages.includes(shortUserLang)) {
|
if (availableLanguages.includes(shortUserLang)) {
|
||||||
@@ -186,7 +186,7 @@ Singleton {
|
|||||||
setLanguage(shortUserLang)
|
setLanguage(shortUserLang)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.log("I18n", `No match for system language: "${fullUserLang}"`)
|
Logger.log("I18n", `No match for system language: "${fullUserLang}"`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,9 +49,7 @@ Item {
|
|||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
function onTooltipTextChanged() {
|
function onTooltipTextChanged() {
|
||||||
if (PanelService.tooltip.visible) {
|
TooltipService.updateText(root.tooltipText)
|
||||||
PanelService.tooltip.updateText(root.tooltipText)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +219,7 @@ Item {
|
|||||||
onEntered: {
|
onEntered: {
|
||||||
hovered = true
|
hovered = true
|
||||||
root.entered()
|
root.entered()
|
||||||
PanelService.tooltip.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
TooltipService.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
||||||
if (disableOpen || forceClose) {
|
if (disableOpen || forceClose) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -235,7 +233,7 @@ Item {
|
|||||||
if (!forceOpen && !forceClose) {
|
if (!forceOpen && !forceClose) {
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
onClicked: function (mouse) {
|
onClicked: function (mouse) {
|
||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
|
|||||||
@@ -61,9 +61,7 @@ Item {
|
|||||||
Connections {
|
Connections {
|
||||||
target: root
|
target: root
|
||||||
function onTooltipTextChanged() {
|
function onTooltipTextChanged() {
|
||||||
if (PanelService.tooltip.visible) {
|
TooltipService.updateText(root.tooltipText)
|
||||||
PanelService.tooltip.updateText(root.tooltipText)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +260,7 @@ Item {
|
|||||||
onEntered: {
|
onEntered: {
|
||||||
hovered = true
|
hovered = true
|
||||||
root.entered()
|
root.entered()
|
||||||
PanelService.tooltip.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
TooltipService.show(pill, root.tooltipText, BarService.getTooltipDirection(), Style.tooltipDelayLong)
|
||||||
if (disableOpen || forceClose) {
|
if (disableOpen || forceClose) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -276,7 +274,7 @@ Item {
|
|||||||
if (!forceOpen && !forceClose) {
|
if (!forceOpen && !forceClose) {
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
onClicked: function (mouse) {
|
onClicked: function (mouse) {
|
||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
|
|||||||
@@ -329,11 +329,11 @@ Item {
|
|||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if ((windowTitle !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) {
|
if ((windowTitle !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) {
|
||||||
PanelService.tooltip.show(root, windowTitle, BarService.getTooltipDirection())
|
TooltipService.show(root, windowTitle, BarService.getTooltipDirection())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,14 +114,14 @@ Rectangle {
|
|||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if (!PanelService.getPanel("calendarPanel")?.active) {
|
if (!PanelService.getPanel("calendarPanel")?.active) {
|
||||||
PanelService.tooltip.show(root, I18n.tr("clock.tooltip"), BarService.getTooltipDirection())
|
TooltipService.show(root, I18n.tr("clock.tooltip"), BarService.getTooltipDirection())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
onClicked: {
|
onClicked: {
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
PanelService.getPanel("calendarPanel")?.toggle(this)
|
PanelService.getPanel("calendarPanel")?.toggle(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -376,11 +376,11 @@ Item {
|
|||||||
|
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if ((tooltipText !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) {
|
if ((tooltipText !== "") && (barPosition === "left" || barPosition === "right") || (scrollingMode === "never")) {
|
||||||
PanelService.tooltip.show(root, tooltipText, BarService.getTooltipDirection())
|
TooltipService.show(root, tooltipText, BarService.getTooltipDirection())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onEntered: PanelService.tooltip.show(taskbarItem, taskbarItem.modelData.title || taskbarItem.modelData.appId || "Unknown app.", BarService.getTooltipDirection())
|
onEntered: TooltipService.show(taskbarItem, taskbarItem.modelData.title || taskbarItem.modelData.appId || "Unknown app.", BarService.getTooltipDirection())
|
||||||
onExited: PanelService.tooltip.hide()
|
onExited: TooltipService.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,8 +135,8 @@ Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onEntered: PanelService.tooltip.show(trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection())
|
onEntered: TooltipService.show(trayIcon, modelData.tooltipTitle || modelData.name || modelData.id || "Tray Item", BarService.getTooltipDirection())
|
||||||
onExited: PanelService.tooltip.hide()
|
onExited: TooltipService.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ Variants {
|
|||||||
anyAppHovered = true
|
anyAppHovered = true
|
||||||
const appName = appButton.appTitle || appButton.appId || "Unknown"
|
const appName = appButton.appTitle || appButton.appId || "Unknown"
|
||||||
const tooltipText = appName.length > 40 ? appName.substring(0, 37) + "..." : appName
|
const tooltipText = appName.length > 40 ? appName.substring(0, 37) + "..." : appName
|
||||||
PanelService.tooltip.show(appButton, tooltipText, "top")
|
TooltipService.show(appButton, tooltipText, "top")
|
||||||
if (autoHide) {
|
if (autoHide) {
|
||||||
showTimer.stop()
|
showTimer.stop()
|
||||||
hideTimer.stop()
|
hideTimer.stop()
|
||||||
@@ -484,7 +484,7 @@ Variants {
|
|||||||
|
|
||||||
onExited: {
|
onExited: {
|
||||||
anyAppHovered = false
|
anyAppHovered = false
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
if (autoHide && !dockHovered && !peekHovered && !menuHovered) {
|
if (autoHide && !dockHovered && !peekHovered && !menuHovered) {
|
||||||
hideTimer.restart()
|
hideTimer.restart()
|
||||||
}
|
}
|
||||||
@@ -500,7 +500,7 @@ Variants {
|
|||||||
// Close any other existing context menu first
|
// Close any other existing context menu first
|
||||||
root.closeAllContextMenus()
|
root.closeAllContextMenus()
|
||||||
// Hide tooltip when showing context menu
|
// Hide tooltip when showing context menu
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
contextMenu.show(appButton, modelData.toplevel || modelData)
|
contextMenu.show(appButton, modelData.toplevel || modelData)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ PopupWindow {
|
|||||||
property int padding: Style.marginM
|
property int padding: Style.marginM
|
||||||
property int delay: 0
|
property int delay: 0
|
||||||
property int hideDelay: 0
|
property int hideDelay: 0
|
||||||
property int maxWidth: 340
|
property int maxWidth: 320
|
||||||
property real scaling: 1.0
|
property real scaling: 1.0
|
||||||
property int animationDuration: Style.animationFast
|
property int animationDuration: Style.animationFast
|
||||||
property real animationScale: 0.85
|
property real animationScale: 0.85
|
||||||
@@ -25,7 +25,7 @@ PopupWindow {
|
|||||||
property real anchorY: 0
|
property real anchorY: 0
|
||||||
property bool isPositioned: false
|
property bool isPositioned: false
|
||||||
property bool pendingShow: false
|
property bool pendingShow: false
|
||||||
property bool animatingOut: false
|
property bool animatingOut: true
|
||||||
|
|
||||||
visible: false
|
visible: false
|
||||||
color: Color.transparent
|
color: Color.transparent
|
||||||
@@ -110,11 +110,7 @@ PopupWindow {
|
|||||||
if (!target || !tipText || tipText === "")
|
if (!target || !tipText || tipText === "")
|
||||||
return
|
return
|
||||||
|
|
||||||
if (showDelay !== undefined) {
|
delay = showDelay
|
||||||
delay = showDelay
|
|
||||||
} else {
|
|
||||||
delay = Style.tooltipDelay
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop any running timers and animations
|
// Stop any running timers and animations
|
||||||
hideTimer.stop()
|
hideTimer.stop()
|
||||||
@@ -144,8 +140,9 @@ PopupWindow {
|
|||||||
|
|
||||||
// Function to position and display the tooltip
|
// Function to position and display the tooltip
|
||||||
function positionAndShow() {
|
function positionAndShow() {
|
||||||
if (!targetItem || !pendingShow)
|
if (!targetItem || !targetItem.parent || !pendingShow) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get screen dimensions - try multiple methods
|
// Get screen dimensions - try multiple methods
|
||||||
var screenWidth = Screen.width
|
var screenWidth = Screen.width
|
||||||
@@ -393,6 +390,8 @@ PopupWindow {
|
|||||||
color: Color.mOnSurfaceVariant
|
color: Color.mOnSurfaceVariant
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
width: root.maxWidth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,6 @@ Singleton {
|
|||||||
// This is not a panel...
|
// This is not a panel...
|
||||||
property var lockScreen: null
|
property var lockScreen: null
|
||||||
|
|
||||||
// A ref. to our global tooltip
|
|
||||||
property var tooltip: null
|
|
||||||
|
|
||||||
// Panels
|
// Panels
|
||||||
property var registeredPanels: ({})
|
property var registeredPanels: ({})
|
||||||
property var openedPanel: null
|
property var openedPanel: null
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import qs.Commons
|
||||||
|
import qs.Modules.Tooltip
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property var activeTooltip: null
|
||||||
|
property var pendingTooltip: null // Track tooltip being created
|
||||||
|
|
||||||
|
property Component tooltipComponent: Component {
|
||||||
|
Tooltip {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show(target, text, direction, delay) {
|
||||||
|
// Don't create if no text
|
||||||
|
if (!target || !text) {
|
||||||
|
Logger.log("Tooltip", "No target or text")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a pending tooltip for a different target, cancel it
|
||||||
|
if (pendingTooltip && pendingTooltip.targetItem !== target) {
|
||||||
|
pendingTooltip.hideImmediately()
|
||||||
|
pendingTooltip.destroy()
|
||||||
|
pendingTooltip = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have an active tooltip for a different target, hide it
|
||||||
|
if (activeTooltip && activeTooltip.targetItem !== target) {
|
||||||
|
activeTooltip.hideImmediately()
|
||||||
|
// Don't destroy immediately - let it clean itself up
|
||||||
|
activeTooltip = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we already have a tooltip for this target, just update it
|
||||||
|
if (activeTooltip && activeTooltip.targetItem === target) {
|
||||||
|
activeTooltip.updateText(text)
|
||||||
|
return activeTooltip
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new tooltip instance
|
||||||
|
const newTooltip = tooltipComponent.createObject(null)
|
||||||
|
|
||||||
|
if (newTooltip) {
|
||||||
|
// Track as pending until it's visible
|
||||||
|
pendingTooltip = newTooltip
|
||||||
|
|
||||||
|
// Connect cleanup when tooltip hides
|
||||||
|
newTooltip.visibleChanged.connect(() => {
|
||||||
|
if (!newTooltip.visible) {
|
||||||
|
// Clean up after a delay to avoid interfering with new tooltips
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (newTooltip && !newTooltip.visible) {
|
||||||
|
if (activeTooltip === newTooltip) {
|
||||||
|
activeTooltip = null
|
||||||
|
}
|
||||||
|
if (pendingTooltip === newTooltip) {
|
||||||
|
pendingTooltip = null
|
||||||
|
}
|
||||||
|
newTooltip.destroy()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// Tooltip is now visible, move from pending to active
|
||||||
|
if (pendingTooltip === newTooltip) {
|
||||||
|
activeTooltip = newTooltip
|
||||||
|
pendingTooltip = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Show the tooltip
|
||||||
|
newTooltip.show(target, text, direction || "auto", delay || Style.tooltipDelay)
|
||||||
|
|
||||||
|
return newTooltip
|
||||||
|
} else {
|
||||||
|
Logger.error("Tooltip", "Failed to create tooltip instance")
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide() {
|
||||||
|
if (pendingTooltip) {
|
||||||
|
pendingTooltip.hide()
|
||||||
|
}
|
||||||
|
if (activeTooltip) {
|
||||||
|
activeTooltip.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideImmediately() {
|
||||||
|
if (pendingTooltip) {
|
||||||
|
pendingTooltip.hideImmediately()
|
||||||
|
pendingTooltip.destroy()
|
||||||
|
pendingTooltip = null
|
||||||
|
}
|
||||||
|
if (activeTooltip) {
|
||||||
|
activeTooltip.hideImmediately()
|
||||||
|
activeTooltip.destroy()
|
||||||
|
activeTooltip = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateText(newText) {
|
||||||
|
if (activeTooltip) {
|
||||||
|
activeTooltip.updateText(newText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-4
@@ -139,18 +139,18 @@ Rectangle {
|
|||||||
onEntered: {
|
onEntered: {
|
||||||
root.hovered = true
|
root.hovered = true
|
||||||
if (tooltipText) {
|
if (tooltipText) {
|
||||||
PanelService.tooltip.show(root, root.tooltipText)
|
TooltipService.show(root, root.tooltipText)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
root.hovered = false
|
root.hovered = false
|
||||||
if (tooltipText) {
|
if (tooltipText) {
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onPressed: mouse => {
|
onPressed: mouse => {
|
||||||
if (tooltipText) {
|
if (tooltipText) {
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
if (mouse.button === Qt.LeftButton) {
|
if (mouse.button === Qt.LeftButton) {
|
||||||
root.clicked()
|
root.clicked()
|
||||||
@@ -164,7 +164,7 @@ Rectangle {
|
|||||||
onCanceled: {
|
onCanceled: {
|
||||||
root.hovered = false
|
root.hovered = false
|
||||||
if (tooltipText) {
|
if (tooltipText) {
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,20 +73,20 @@ Rectangle {
|
|||||||
onEntered: {
|
onEntered: {
|
||||||
hovering = root.enabled ? true : false
|
hovering = root.enabled ? true : false
|
||||||
if (tooltipText) {
|
if (tooltipText) {
|
||||||
PanelService.tooltip.show(parent, tooltipText, tooltipDirection)
|
TooltipService.show(parent, tooltipText, tooltipDirection)
|
||||||
}
|
}
|
||||||
root.entered()
|
root.entered()
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
hovering = false
|
hovering = false
|
||||||
if (tooltipText) {
|
if (tooltipText) {
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
root.exited()
|
root.exited()
|
||||||
}
|
}
|
||||||
onClicked: function (mouse) {
|
onClicked: function (mouse) {
|
||||||
if (tooltipText) {
|
if (tooltipText) {
|
||||||
PanelService.tooltip.hide()
|
TooltipService.hide()
|
||||||
}
|
}
|
||||||
if (!root.enabled && !allowClickWhenDisabled) {
|
if (!root.enabled && !allowClickWhenDisabled) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -51,10 +51,6 @@ ShellRoot {
|
|||||||
Bar {}
|
Bar {}
|
||||||
Dock {}
|
Dock {}
|
||||||
|
|
||||||
Tooltip {
|
|
||||||
id: globalTooltip
|
|
||||||
}
|
|
||||||
|
|
||||||
Notification {
|
Notification {
|
||||||
id: notification
|
id: notification
|
||||||
}
|
}
|
||||||
@@ -120,7 +116,6 @@ ShellRoot {
|
|||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
// Save a ref. to our lockScreen so we can access it easily
|
// Save a ref. to our lockScreen so we can access it easily
|
||||||
PanelService.lockScreen = lockScreen
|
PanelService.lockScreen = lockScreen
|
||||||
PanelService.tooltip = globalTooltip
|
|
||||||
|
|
||||||
BarWidgetRegistry.init()
|
BarWidgetRegistry.init()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user