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. Adding clickable widgets into a qplaintextedit
Servers for Qt installer are currently down

Adding clickable widgets into a qplaintextedit

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 796 Views 1 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.
  • F Offline
    F Offline
    Fuchsiaff
    wrote on 20 Aug 2019, 11:58 last edited by Fuchsiaff
    #1

    So basically let's say you have followed this guide: https://doc.qt.io/qt-5/qtwidgets-widgets-codeeditor-example.html

    And you modify the width to be a bit bigger: 0_1566302222616_12afce80-1ace-4e6e-b0e3-6325682fadef-Screenshot 2019-08-20 at 14.56.46.png Screenshot 2019-08-20 at 14.56.46

    I want to add a little arrow next to line number 1, like QtCreator has, to be clickable so I could fold the text that is on line 2
    But I have no idea where to start, how can I add a little widget next to the line number

    1 Reply Last reply
    0
    • F Offline
      F Offline
      Fuchsiaff
      wrote on 20 Aug 2019, 12:53 last edited by
      #2

      I'm currently trying to find out how QtCreator does it, if anyone knows, please let me know!

      1 Reply Last reply
      0
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 20 Aug 2019, 13:59 last edited by
        #3

        Hi,

        I would start by looking at the TextEditor plugin and the CppEditor plugin.

        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
        1
        • F Offline
          F Offline
          Fuchsiaff
          wrote on 20 Aug 2019, 15:52 last edited by
          #4

          Alright so I think the best way to proceed is to have each of the numbers on the number bar clickable
          so instead of painting them, they should be widgets

          Here's a little Number class:

          class Number(QFrame):
              def __init__(self, number):
                  super().__init__()
                  self.num = QLabel(str(number), self)
                  self.layout = QVBoxLayout()
                  self.layout.addWidget(self.num)
                  self.layout.addStretch()
                  self.setLayout(self.layout)
                  self.setStyleSheet("background-color: red; color: black")
                  self.setContentsMargins(0,0,0,0)
          

          But there is still some annoying spacing around the widget:0_1566316340588_26f80f26-ce8c-4994-a4e1-05c0b3eca274-Screenshot 2019-08-20 at 18.52.05.png
          How do I remove that?

          1 Reply Last reply
          0
          • F Offline
            F Offline
            Fuchsiaff
            wrote on 20 Aug 2019, 20:19 last edited by Fuchsiaff
            #5

            Well after digging, and I mean A LOT of digging I found I could use QStyle to draw those little arrows
            and since QStyleOptionViewItem has states, I can choose how the arrow is pointing.

            This is a little example of code:

                def paintEvent(self, event: QPaintEvent):
            
                    if self.isVisible():
                        block: QTextBlock = self.editor.firstVisibleBlock()
                        height: int = self.fontMetrics().height()
                        number: int = block.blockNumber()
            
                        painter = QPainter(self)
                        painter.fillRect(event.rect(), QColor(53, 53, 53))
                        # painter.drawRect(0, 0, event.rect().width() - 1, event.rect().height() - 1)
                        font = painter.font()
                        font.setPointSize(15)
                        currentBlockNumber: int = self.editor.textCursor().block().blockNumber() + 1
            
                        while block.isValid():
                            blockGeometry: QRectF = self.editor.blockBoundingGeometry(block)
                            offset: QPointF = self.editor.contentOffset()
                            blockTop: int = int(blockGeometry.translated(offset).top() + 1)
                            number += 1
            
                            if number == currentBlockNumber:
                                font.setBold(True)
                            else:
                                font.setBold(False)
                            painter.setFont(font)
                            rect: QRect = QRect(0, blockTop, self.width() - 5, height)
                            painter.drawText(rect, Qt.AlignCenter, str(number))
                            if number in self.lines:
                                options = QStyleOptionViewItem()
                                options.rect = QRect(0, blockTop, self.width() + 45, height)
                                options.state = (QStyle.State_Active |
                                             QStyle.State_Item |
                                             QStyle.State_Children |
                                             QStyle.State_Open)
                                self.style().drawPrimitive(QStyle.PE_IndicatorBranch, options,
                                                           painter, self)
                                print("drawn")
                            if blockTop > event.rect().bottom():
                                break
            
                            block = block.next()
            
                        painter.end()
            

            That is the whole paintEvent function and the magic happens here:

                            if number in self.lines:
                                options = QStyleOptionViewItem()
                                options.rect = QRect(0, blockTop, self.width() + 45, height)
                                options.state = (QStyle.State_Active |
                                             QStyle.State_Item |
                                             QStyle.State_Children |
                                             QStyle.State_Open)
                                self.style().drawPrimitive(QStyle.PE_IndicatorBranch, options,
                                                           painter, self)
                                print("drawn")
            

            when painting numbers I will check that if the current number is in a list of numbers where the user can fold at (this is done parsing a syntax tree, if anyone is interested in that please let me know!) and if it is in there then it will create a rect and draw a little arrow that points down (this is because QStyle.State_Open) is in the options.state variable
            if you remove that, the arrow points right. That will be useful when after folding

            Here's a little preview:
            0_1566332422283_ee3f8570-58e3-45a6-97df-4084ce47bc8e-Screenshot 2019-08-20 at 23.19.53.png

            1 Reply Last reply
            0

            1/5

            20 Aug 2019, 11:58

            • Login

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