import QtQuick import QtQuick.Window Item { id: root property string text: "" property bool active: false property int delay: 550 property int timeout: 4000 width: 0 height: 0 enabled: false Accessible.ignored: true Timer { id: showTimer interval: root.delay repeat: false onTriggered: root.open() } Timer { id: hideTimer interval: root.timeout repeat: false onTriggered: tip.visible = false } Window { id: tip flags: Qt.Popup | Qt.ToolTip | Qt.FramelessWindowHint | Qt.WindowDoesNotAcceptFocus color: "transparent" visible: false width: Math.ceil(tipText.implicitWidth) + 16 height: Math.ceil(tipText.implicitHeight) + 10 Rectangle { anchors.fill: parent radius: Theme.radiusSmall color: Theme.surfaceRaised border.color: Theme.borderStrong border.width: 1 Text { id: tipText anchors.centerIn: parent text: root.text color: Theme.textPrimary font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall } } } onActiveChanged: root.sync() onTextChanged: { if (tip.visible) root.place() else root.sync() } function sync() { if (root.active && root.text.length > 0) { showTimer.restart() return } showTimer.stop() hideTimer.stop() tip.visible = false } function open() { if (!root.active || root.text.length === 0) return const host = root.parent if (!host) return const win = host.Window.window if (win) tip.transientParent = win root.place() tip.visible = true hideTimer.restart() } function place() { const host = root.parent if (!host) return const pos = host.mapToGlobal(host.width / 2, host.height + 6) const screenWidth = Screen.width tip.x = Math.round(Math.max(8, Math.min(pos.x - tip.width / 2, screenWidth - tip.width - 8))) tip.y = Math.round(pos.y) } }