Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How can I do something when the user clicks on a particular span/frame/block/fragment/whatever of text in a QTextEdit?

How can I do something when the user clicks on a particular span/frame/block/fragment/whatever of text in a QTextEdit?

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 3 Posters 666 Views
  • 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.
  • I Offline
    I Offline
    Inhahe
    wrote on 12 Apr 2021, 16:18 last edited by
    #1

    I'm writing an IRC client, and I have message/channel windows update with lines like

    <from_nick> message

    and I want to be able to bring up a context menu when the user right clicks on a nick (like the "from_nick" part above) and to know what the nick they clicked on is. I've tried numerous things, can't figure it out.

    Thanks.

    1 Reply Last reply
    0
    • K Offline
      K Offline
      Kent-Dorfman
      wrote on 13 Apr 2021, 03:20 last edited by Kent-Dorfman
      #2

      Well, since it is a text-edit field the widget sees what is in it is text, so if you are not satisifed with cut-n-paste text operations then you'd need to subclass the widget and get the mouse coordinates of the click in the widget, and then you would need to use the font metrics information to calculate the boundaries of each character and react accordingly. ps - this only seems possible if the font is monospaced.

      Or ditch text-edit and parse the incoming messages into separate widgets, the nickname containing one being a pushbutton.

      1 Reply Last reply
      1
      • J Offline
        J Offline
        jeremy_k
        wrote on 13 Apr 2021, 05:02 last edited by
        #3

        If using rich text is acceptable, there's QTextEdit::anchorAt(). Handle the context menu event, and use anchorAt to retrieve the anchor embedded in the nick text.

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

        1 Reply Last reply
        2
        • I Offline
          I Offline
          Inhahe
          wrote on 13 Apr 2021, 13:20 last edited by
          #4

          Thanks for the lead, @jeremy_k, though I'm having some trouble making it work...

          I tried two different ways of making an anchor, one with insertHtml, inserting something like '<a href="nick">nick</a>', and one with QTextFormat, setAnchorHref, and insertText... in both cases, the link extends to the end of the line, e.g. in my original example of

          <from_nick> message

          the whole 'from_nick> message' would be the link, instead of the link starting and ending with 'some_nick' like I want.

          I haven't posted my code because it's in PyQt and I don't know if that would annoy some people because this isn't the Qt for Python forum. I posted the question here, assuming that I'd be able to adapt any advice I get to PyQt, because I didn't get any response in the Qt for Python forum which I think is a less popular forum..

          1 Reply Last reply
          0
          • J Offline
            J Offline
            jeremy_k
            wrote on 13 Apr 2021, 16:55 last edited by
            #5
            import PyQt5.QtCore as QtCore
            import PyQt5.QtWidgets as QtWidgets
            
            class MyTextEdit(QtWidgets.QTextEdit):
                def contextMenuEvent(self, event):
                    anchor = self.anchorAt(event.pos())
                    if len(anchor) > 0:
                        QtWidgets.QMessageBox.information(self, "Anchor Found", "The anchor {} was found".format(anchor))
            
            app = QtWidgets.QApplication([])
            textEdit = MyTextEdit()
            textEdit.setHtml('<a href="first">&lt;user1&gt;</a> first user<br><a href="second">&lt;second&gt;</a> second user')
            textEdit.show()
            app.exec()
            

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

            1 Reply Last reply
            0
            • I Offline
              I Offline
              Inhahe
              wrote on 14 Apr 2021, 21:05 last edited by
              #6

              here's my code:

              def addmsg(textedit, nick, message):
                if config.show_timestamp:
                  obj_now = datetime.now()
                  textedit.insertPlainText(f"[{obj_now.hour: >2}:{obj_now.minute: >2}] ")
                textedit.insertPlainText("<")
                #textedit.insertHtml(f'<a href="{nick}">{nick}</a>') #doesn't work right, bug in qt
                charFormat = QTextCharFormat()
                charFormat.setAnchorHref(nick)
                textedit.textCursor().insertText(nick, charFormat)
                textedit.insertPlainText("> ")
                colorify(textedit, message)
                textedit.insertHtml("<br>")
              

              both the QTextCharFormat approach and the insertHtml approach (commented out in the above) result in the link extending all the way to the end of the line, which it seems it shouldn't. Just posting it in case you happen to have any insight; I expect I'll have to figure this out myself ;/

              J 1 Reply Last reply 16 Apr 2021, 21:51
              0
              • I Offline
                I Offline
                Inhahe
                wrote on 15 Apr 2021, 13:04 last edited by
                #7

                I verified that the problem isn't in my colorify function, I've temporarily replaced that with a simple insertPlainText:

                def addmsg(textedit, nick, message):
                  if config.show_timestamp:
                    obj_now = datetime.now()
                    textedit.insertPlainText(f"[{obj_now.hour: >2}:{obj_now.minute: >2}] ")
                  textedit.insertPlainText("<")
                  textedit.insertHtml(f'<a href="{nick}">{nick}</a>') #doesn't work right, bug in qt
                  textedit.insertPlainText("> ")
                  textedit.insertPlainText(message.decode('utf-8'))
                  textedit.insertHtml("<br>")
                
                1 Reply Last reply
                0
                • I Offline
                  I Offline
                  Inhahe
                  wrote on 15 Apr 2021, 18:15 last edited by
                  #8

                  @jeremy_k said in How can I do something when the user clicks on a particular span/frame/block/fragment/whatever of text in a QTextEdit?:

                  import PyQt5.QtCore as QtCore
                  import PyQt5.QtWidgets as QtWidgets

                  class MyTextEdit(QtWidgets.QTextEdit):
                  def contextMenuEvent(self, event):
                  anchor = self.anchorAt(event.pos())
                  if len(anchor) > 0:
                  QtWidgets.QMessageBox.information(self, "Anchor Found", "The anchor {} was found".format(anchor))

                  app = QtWidgets.QApplication([])
                  textEdit = MyTextEdit()
                  textEdit.setHtml('<a href="first"><user1></a> first user<br><a href="second"><second></a> second user')
                  textEdit.show()
                  app.exec()

                  Here's a minimal example that does the wrong thing:

                  import PyQt5.QtCore as QtCore
                  import PyQt5.QtWidgets as QtWidgets
                  
                  class MyTextEdit(QtWidgets.QTextEdit):
                      def contextMenuEvent(self, event):
                          anchor = self.anchorAt(event.pos())
                          if len(anchor) > 0:
                              QtWidgets.QMessageBox.information(self, "Anchor Found", "The anchor {} was found".format(anchor))
                  
                  app = QtWidgets.QApplication([])
                  textEdit = MyTextEdit()
                  textEdit.insertHtml('<a href="test1">test1</a>')
                  textEdit.insertPlainText("test2")
                  textEdit.show()
                  app.exec()
                  

                  both test1 and test2 in the textEdit window are underlined and in blue.

                  1 Reply Last reply
                  0
                  • I Offline
                    I Offline
                    Inhahe
                    wrote on 16 Apr 2021, 16:34 last edited by
                    #9

                    I figured it out. Thanks for your help.

                    def addmsg(textedit, nick, message):
                      if config.show_timestamp:
                        obj_now = datetime.now()
                        textedit.insertPlainText(f"[{obj_now.hour: >2}:{obj_now.minute: >2}] ")
                      textedit.insertHtml(f'&lt;<a style="text-decoration: none; color: inherit" href="{nick}">{nick}</a>&gt; ')
                      colorify(textedit, message)
                      textedit.insertHtml("<br>")
                    
                    1 Reply Last reply
                    0
                    • I Inhahe
                      14 Apr 2021, 21:05

                      here's my code:

                      def addmsg(textedit, nick, message):
                        if config.show_timestamp:
                          obj_now = datetime.now()
                          textedit.insertPlainText(f"[{obj_now.hour: >2}:{obj_now.minute: >2}] ")
                        textedit.insertPlainText("<")
                        #textedit.insertHtml(f'<a href="{nick}">{nick}</a>') #doesn't work right, bug in qt
                        charFormat = QTextCharFormat()
                        charFormat.setAnchorHref(nick)
                        textedit.textCursor().insertText(nick, charFormat)
                        textedit.insertPlainText("> ")
                        colorify(textedit, message)
                        textedit.insertHtml("<br>")
                      

                      both the QTextCharFormat approach and the insertHtml approach (commented out in the above) result in the link extending all the way to the end of the line, which it seems it shouldn't. Just posting it in case you happen to have any insight; I expect I'll have to figure this out myself ;/

                      J Offline
                      J Offline
                      jeremy_k
                      wrote on 16 Apr 2021, 21:51 last edited by
                      #10

                      @Inhahe said in How can I do something when the user clicks on a particular span/frame/block/fragment/whatever of text in a QTextEdit?:

                      here's my code:

                      def addmsg(textedit, nick, message):
                        if config.show_timestamp:
                          obj_now = datetime.now()
                          textedit.insertPlainText(f"[{obj_now.hour: >2}:{obj_now.minute: >2}] ")
                        textedit.insertPlainText("<")
                        #textedit.insertHtml(f'<a href="{nick}">{nick}</a>') #doesn't work right, bug in qt
                        charFormat = QTextCharFormat()
                        charFormat.setAnchorHref(nick)
                        textedit.textCursor().insertText(nick, charFormat)
                        textedit.insertPlainText("> ")
                        colorify(textedit, message)
                        textedit.insertHtml("<br>")
                      

                      both the QTextCharFormat approach and the insertHtml approach (commented out in the above) result in the link extending all the way to the end of the line, which it seems it shouldn't. Just posting it in case you happen to have any insight; I expect I'll have to figure this out myself ;/

                      Using textedit.insertHtml(f'<a href="{nick}">{nick}</a>&gt;') rather than adding > as plain text fixes the issue for me with Qt 5.15.2 and PyQt 5.15.3. I haven't tried using the QTextCharFormat method.

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

                      1 Reply Last reply
                      0

                      10/10

                      16 Apr 2021, 21:51

                      • Login

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