Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Issues with link switching via keyboard in QPlainTextEdit
Forum Updated to NodeBB v4.3 + New Features

Issues with link switching via keyboard in QPlainTextEdit

Scheduled Pinned Locked Moved Solved Qt for Python
7 Posts 3 Posters 456 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    wayfarer
    wrote on last edited by wayfarer
    #1

    I'm using a QPlainTextEdit widget to display read-only text to the user, programatically inserted into the widget via .appendHtml(). Included in the HTML are links enclosed in standard <a></a> tags. Clicking them with the mouse works fine.

    I intend to provide full keyboard navigation capability to the user by allowing them to cycle through links with Tab and click them with Enter. After some digging, I discovered the LinksAccessibleByKeyboard text interaction flag, which - according to the documentation - can do exactly that.

    However, even after implementing textWidget.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByKeyboard), Tab still only changes focus between a dropdown on my QMainWindow's toolbar and the QPlainTextEdit rather than focusing on the links inside the widget. I tried changing/removing the other text interaction flags I used and hiding the toolbar using toolBar.hide() but nothing's worked yet, so I'm not sure what the problem is.

    jeremy_kJ 1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      Which version of PySide/PyQt are you using ?
      On which OS ?
      Can you provide a minimal runnable script that shows this behavior ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • W Offline
        W Offline
        wayfarer
        wrote on last edited by wayfarer
        #3

        I'm on Arch Linux, using PyQt version 6.9.1-2 from the Extra repository. Here's a minimum working example:

        import sys
        from PyQt6.QtCore import Qt
        from PyQt6.QtWidgets import QApplication, QMainWindow, QToolBar, QToolButton, QMenu, QPlainTextEdit
        from PyQt6.QtGui import QIcon, QAction
        
        class AppWindow(QMainWindow):
        	def __init__(self):
        		super().__init__()
        		self.buffer = QPlainTextEdit()
        		self.setCentralWidget(self.buffer)
        		toggleIcon = QIcon.fromTheme('preferences-other')
        		toggleSomething = QAction(QIcon(toggleIcon), 'Toggle Something', self)
        		aboutIcon = QIcon.fromTheme('help-about')
        		aboutPage = QAction(QIcon(aboutIcon), 'About the App', self)
        		settingsButton = QToolButton()
        		settingsButton.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
        		settingsMenu = QMenu()
        		settingsButton.setMenu(settingsMenu)
        		settingsAction = QAction(QIcon(QIcon.fromTheme('preferences-other')), 'Settings', self)
        		settingsButton.setDefaultAction(settingsAction)
        		settingsMenu.addAction(toggleSomething)
        		settingsMenu.addAction(aboutPage)
        		self.toolBar = QToolBar()
        		self.addToolBar(self.toolBar)
        		self.toolBar.setMovable(False)
        		self.toolBar.addWidget(settingsButton)
        		self.addAction(toggleSomething)
        		self.addAction(aboutPage)
        		self.setContextMenuPolicy(Qt.ContextMenuPolicy.PreventContextMenu)
        		self.buffer.setContextMenuPolicy(Qt.ContextMenuPolicy.PreventContextMenu)
        		self.buffer.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByKeyboard) # This should make the links clickable via keyboard, but it's not doing that
        
        class QPlainTextEdit(QPlainTextEdit):
        	def mousePressEvent(self, e):
        		self.link = self.anchorAt(e.pos())
        		if self.link:
        			print('Link clicked! In my app, this is a function call instead of a print statement.')
        
        def addLines():
        	lines = ['<a href="https://example.com">Example</a>', 'Another line', '<a href="https://example.com">Example</a>']
        	for line in lines:
        		window.buffer.appendHtml(line)
        
        app = QApplication(sys.argv)
        window = AppWindow()
        addLines()
        window.show()
        app.exec()
        
        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          From a quick look at Qt sources, it seems this flag requires keypad navigation so I currently don't know how exactly it is supposed to work in this case.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • W wayfarer

            I'm using a QPlainTextEdit widget to display read-only text to the user, programatically inserted into the widget via .appendHtml(). Included in the HTML are links enclosed in standard <a></a> tags. Clicking them with the mouse works fine.

            I intend to provide full keyboard navigation capability to the user by allowing them to cycle through links with Tab and click them with Enter. After some digging, I discovered the LinksAccessibleByKeyboard text interaction flag, which - according to the documentation - can do exactly that.

            However, even after implementing textWidget.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByKeyboard), Tab still only changes focus between a dropdown on my QMainWindow's toolbar and the QPlainTextEdit rather than focusing on the links inside the widget. I tried changing/removing the other text interaction flags I used and hiding the toolbar using toolBar.hide() but nothing's worked yet, so I'm not sure what the problem is.

            jeremy_kJ Offline
            jeremy_kJ Offline
            jeremy_k
            wrote on last edited by
            #5

            @wayfarer said in Issues with link switching via keyboard in QPlainTextEdit:

            I'm using a QPlainTextEdit widget to display read-only text to the user, programatically inserted into the widget via .appendHtml(). Included in the HTML are links enclosed in standard <a></a> tags. Clicking them with the mouse works fine.

            Have you considered QTextBrowser? It has link handling APIs, and tab navigation between links works.

            from PyQt6.QtWidgets import QApplication, QTextBrowser
            from PyQt6.QtCore import Qt
            
            app = QApplication([])
            
            browser = QTextBrowser()
            browser.setOpenLinks(False)
            browser.anchorClicked.connect(lambda url: print(f"Anchor clicked: {url}"))
            browser.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByKeyboard | Qt.TextInteractionFlag.LinksAccessibleByMouse)
            
            for i in range(3):
                browser.append(f"<a href='link_{i}'>link {i}</a>")
            browser.show()
            app.exec()
            

            Asking a question about code? http://eel.is/iso-c++/testcase/

            W 1 Reply Last reply
            0
            • jeremy_kJ jeremy_k

              @wayfarer said in Issues with link switching via keyboard in QPlainTextEdit:

              I'm using a QPlainTextEdit widget to display read-only text to the user, programatically inserted into the widget via .appendHtml(). Included in the HTML are links enclosed in standard <a></a> tags. Clicking them with the mouse works fine.

              Have you considered QTextBrowser? It has link handling APIs, and tab navigation between links works.

              from PyQt6.QtWidgets import QApplication, QTextBrowser
              from PyQt6.QtCore import Qt
              
              app = QApplication([])
              
              browser = QTextBrowser()
              browser.setOpenLinks(False)
              browser.anchorClicked.connect(lambda url: print(f"Anchor clicked: {url}"))
              browser.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByKeyboard | Qt.TextInteractionFlag.LinksAccessibleByMouse)
              
              for i in range(3):
                  browser.append(f"<a href='link_{i}'>link {i}</a>")
              browser.show()
              app.exec()
              
              W Offline
              W Offline
              wayfarer
              wrote on last edited by
              #6

              @jeremy_k said in Issues with link switching via keyboard in QPlainTextEdit:

              Have you considered QTextBrowser? It has link handling APIs, and tab navigation between links works.

              I was hoping to avoid having to use a different widget since I've already built most of my app around the QPlainTextEdit.

              Besides, I vastly prefer its scrolling behavior. QTextEdit and QTextBrowser both cut off the text when the user scrolls past it, leaving it partially visible at the top of the window. QPlainTextEdit doesn't. It's a nice visual feature that makes the app feel much smoother.

              Switching to QTextBrowser seems like a viable solution, though I'll have to modify my existing code to work with it. I would prefer to keep the QPlainTextEdit scrolling behavior somehow if possible.

              Is there any particular reason why that flag doesn't work with QPlainTextEdit?

              jeremy_kJ 1 Reply Last reply
              0
              • W wayfarer

                @jeremy_k said in Issues with link switching via keyboard in QPlainTextEdit:

                Have you considered QTextBrowser? It has link handling APIs, and tab navigation between links works.

                I was hoping to avoid having to use a different widget since I've already built most of my app around the QPlainTextEdit.

                Besides, I vastly prefer its scrolling behavior. QTextEdit and QTextBrowser both cut off the text when the user scrolls past it, leaving it partially visible at the top of the window. QPlainTextEdit doesn't. It's a nice visual feature that makes the app feel much smoother.

                Switching to QTextBrowser seems like a viable solution, though I'll have to modify my existing code to work with it. I would prefer to keep the QPlainTextEdit scrolling behavior somehow if possible.

                Is there any particular reason why that flag doesn't work with QPlainTextEdit?

                jeremy_kJ Offline
                jeremy_kJ Offline
                jeremy_k
                wrote on last edited by jeremy_k
                #7

                @wayfarer said in Issues with link switching via keyboard in QPlainTextEdit:

                @jeremy_k said in Issues with link switching via keyboard in QPlainTextEdit:

                Have you considered QTextBrowser? It has link handling APIs, and tab navigation between links works.

                I was hoping to avoid having to use a different widget since I've already built most of my app around the QPlainTextEdit.

                Besides, I vastly prefer its scrolling behavior. QTextEdit and QTextBrowser both cut off the text when the user scrolls past it, leaving it partially visible at the top of the window. QPlainTextEdit doesn't. It's a nice visual feature that makes the app feel much smoother.

                Switching to QTextBrowser seems like a viable solution, though I'll have to modify my existing code to work with it. I would prefer to keep the QPlainTextEdit scrolling behavior somehow if possible.

                Is there any particular reason why that flag doesn't work with QPlainTextEdit?

                The scrolling difference is due to QPlainTextEdit's override definition of QAbstractScrollArea::scrollContentsBy. The implementation is here.

                My guess is that handling of links, including navigation between them, isn't seen as part of the functionality of the widget. QTextEdit also lacks navigation between links. The QPlainTextEdit::textInteractionFlags contains what may be a revealing error:

                Specifies how the label should interact with user input if it displays text.

                Asking a question about code? http://eel.is/iso-c++/testcase/

                1 Reply Last reply
                0
                • W wayfarer has marked this topic as solved

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved