diff --git a/tests/ui/test_jira_knowledge_help_ux.py b/tests/ui/test_jira_knowledge_help_ux.py
index 6e1bc51..4ed56db 100644
--- a/tests/ui/test_jira_knowledge_help_ux.py
+++ b/tests/ui/test_jira_knowledge_help_ux.py
@@ -51,15 +51,16 @@ def test_help_icon_exists(dialog):
def test_help_icon_has_tooltip(dialog):
- """Help icon must have a non-empty tooltip with both Project ID and Jira Key explanations."""
+ """Help icon must store help text with both Project ID and Jira Key explanations."""
from PySide6.QtWidgets import QToolButton
dlg = dialog
help_icons = dlg.findChildren(QToolButton)
assert help_icons, "No help button found"
- tooltip = help_icons[0].toolTip()
- assert tooltip, "Help button has no tooltip"
- assert "Project ID" in tooltip, "Tooltip missing Project ID explanation"
- assert "Jira Key" in tooltip, "Tooltip missing Jira Key explanation"
+ # Help text is stored in _help_text for click-based popup
+ help_text = getattr(dlg, '_help_text', '') or help_icons[0].toolTip()
+ assert help_text, "Help button has no help content"
+ assert "Project ID" in help_text, "Help content missing Project ID explanation"
+ assert "Jira Key" in help_text, "Help content missing Jira Key explanation"
# ---- Help text content ----------------------------------------------------
diff --git a/ui/connectors_panel.py b/ui/connectors_panel.py
index 009f10c..5350e98 100644
--- a/ui/connectors_panel.py
+++ b/ui/connectors_panel.py
@@ -11,12 +11,12 @@ setup dialog; OneDrive/SharePoint: neither, they only toggle).
"""
from __future__ import annotations
-from PySide6.QtCore import Qt
+from PySide6.QtCore import Qt, QPoint
from PySide6.QtGui import QFont
from PySide6.QtWidgets import (
QCheckBox, QDialog, QFormLayout, QFrame, QGroupBox, QHBoxLayout, QLabel,
- QLineEdit, QMessageBox, QPushButton, QScrollArea, QToolButton, QToolTip,
- QVBoxLayout, QWidget,
+ QLineEdit, QMessageBox, QPushButton, QScrollArea, QToolButton,
+ QVBoxLayout, QWidget, QApplication,
)
from ..core.ext_connectors import CATEGORIES as EXT_CATEGORIES
@@ -109,12 +109,6 @@ class JiraConnectDialog(QDialog):
mapping_label = QLabel(tr("connectors.jira_kb_mapping_label"))
self.help_icon = QToolButton()
self.help_icon.setText("?")
- self.help_icon.setToolTip(
- "" + tr("connectors.jira_kb_project_id_title") + "
"
- + tr("connectors.jira_kb_project_id_help")
- + "
" + tr("connectors.jira_kb_jira_key_title") + "
"
- + tr("connectors.jira_kb_jira_key_help")
- )
self.help_icon.setStyleSheet("""
QToolButton {
border: 1px solid #5B9BD5;
@@ -135,9 +129,15 @@ class JiraConnectDialog(QDialog):
color: white;
}
""")
- # Native Qt tooltip: hover to show, no click handler needed.
- # AutoRaise=False keeps the button always visible (not faded out).
- self.help_icon.setAutoRaise(False)
+ # Click-based popover: build help content once, show on click
+ self._help_text = (
+ "" + tr("connectors.jira_kb_project_id_title") + "
"
+ + tr("connectors.jira_kb_project_id_help")
+ + "
" + tr("connectors.jira_kb_jira_key_title") + "
"
+ + tr("connectors.jira_kb_jira_key_help")
+ )
+ self._help_popup = None
+ self.help_icon.clicked.connect(self._toggle_help_popup)
label_row = QHBoxLayout()
label_row.setSpacing(4)
label_row.addWidget(mapping_label)
@@ -188,6 +188,43 @@ class JiraConnectDialog(QDialog):
self.kb_enabled.toggled.connect(self._update_sync_state)
self._update_sync_state(self.kb_enabled.isChecked())
+ def _toggle_help_popup(self) -> None:
+ """Show/hide a floating help popup when the ? button is clicked."""
+ if self._help_popup is not None and self._help_popup.isVisible():
+ self._help_popup.hide()
+ self._help_popup.deleteLater()
+ self._help_popup = None
+ return
+
+ popup = QFrame(self)
+ popup.setWindowFlags(Qt.Popup | Qt.FramelessWindowHint)
+ popup.setAttribute(Qt.WA_DeleteOnClose, False)
+ popup.setStyleSheet("""
+ QFrame {
+ background: #2D2D2D;
+ border: 1px solid #5B9BD5;
+ border-radius: 8px;
+ padding: 12px;
+ }
+ """)
+ popup_layout = QVBoxLayout(popup)
+ popup_layout.setContentsMargins(12, 10, 12, 10)
+
+ content = QLabel(self._help_text)
+ content.setWordWrap(True)
+ content.setMaximumWidth(380)
+ content.setStyleSheet("color: #E0E0E0; font-size: 12px; background: transparent; border: none;")
+ content.setTextFormat(Qt.RichText)
+ content.setOpenExternalLinks(True)
+ popup_layout.addWidget(content)
+
+ # Position below the help button
+ btn_global = self.help_icon.mapToGlobal(QPoint(0, self.help_icon.height()))
+ popup.move(btn_global)
+ popup.show()
+ popup.raise_()
+ self._help_popup = popup
+
def _on_paste(self, text: str) -> None:
"""Auto-fill Base URL from a pasted Jira link."""
import re