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. QPlainTextEdit left margin for text
Forum Updated to NodeBB v4.3 + New Features

QPlainTextEdit left margin for text

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 3 Posters 1.3k 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.
  • M Offline
    M Offline
    mpergand
    wrote on last edited by
    #2

    Hi,
    Have look at setViewportMargins

    What you want to do resemble very much like in this example:
    Code Editor

    1 Reply Last reply
    1
    • L Offline
      L Offline
      Lasse
      wrote on last edited by
      #3

      In that example they are using a separate widget with a custom paint event for the margin area. I guess I'm not completely comfortable with sub-widgets that aren't part of any layout, but copying what they did there seems to work, at least to a degree.

      If this is the best solution available then I would like to make sure the paint event of the master widget (QPlainTextEdit) always happens first. (This is because I then can cache the results of the potentially expensive document iterating and use the same data for painting the sub-widget.) I'm not sure if there is a good way to guarantee this, other than calling repaint() on the sub-widget from the master paint event and keeping updates disabled for it at all other times.

      I didn't implement everything yet but it seems this could potentially work adequately, so thanks for the suggestion.

      1 Reply Last reply
      0
      • JoeCFDJ Offline
        JoeCFDJ Offline
        JoeCFD
        wrote on last edited by
        #4

        Can you please show your drawing code in paintEvent()?
        you can move the start position to the right to add margin which has to be scaled according to your design.

        1 Reply Last reply
        0
        • L Offline
          L Offline
          Lasse
          wrote on last edited by
          #5

          Here's the code. "TextBuffer" derives from QPlainTextEdit. The last 3 lines are today's experiment with the margin sub-widget. I don't know what "start position" means, but if you could e.g. transpose the coordinates that QPlainTextEdit::paintEvent() uses when drawing the content, that would probably accomplish the goal

          void TextBuffer::paintEvent(QPaintEvent* e) {
          	QPainter painter(viewport());
          	QBrush brush0(theme.shadow);
          	QBrush brush1(theme.ether);
          	int w=painter.viewport().width();
          	QTextBlock block=firstVisibleBlock();
          	QRectF p=blockBoundingGeometry(block).translated(contentOffset());
          	int y1=(int)p.top();
          	int y0=y1-rowHgt;
          	int bottom=y1+painter.viewport().height();
          	int d=rowHgt>>2;
          	while(y1<bottom) {
          		bool full=true;
          		if(!block.isValid() || !block.isVisible()) {
          			y1=bottom;
          		} else if(block.userState()!=0x10000) {
          			full=block.length()>1;
          		}
          		if(full && y1>y0) {
          			y0+=d;
          			painter.fillRect(0  ,y0,1,1,brush0);
          			painter.fillRect(w-1,y0,1,1,brush0);
          			++y0;
          			painter.fillRect(0,  y0,1,1,brush1);
          			painter.fillRect(w-1,y0,1,1,brush1);
          			painter.fillRect(1,y0,w-2,1,brush0);
          			++y0;
          			int y2=y1-1-d;
          			painter.fillRect(0  ,y2,1,1,brush1);
          			painter.fillRect(w-1,y2,1,1,brush1);
          			//
          			painter.fillRect(0,y0,w,y2-y0,brush1);
          		}
          		y1+=rowHgt;
          		if(full) {
          			y0=y1;
          		} else if(y1>=bottom) {
          			y0+=d;
          			painter.fillRect(0  ,y0,1,1,brush0);
          			painter.fillRect(w-1,y0,1,1,brush0);
          			++y0;
          			painter.fillRect(0,  y0,1,1,brush1);
          			painter.fillRect(w-1,y0,1,1,brush1);
          			painter.fillRect(1,y0,w-2,1,brush0);
          			++y0;
          			painter.fillRect(0,y0,w,bottom-y0,brush1);
          		}
          		block=block.next();
          	}
          	QPlainTextEdit::paintEvent(e);
          	margin->setUpdatesEnabled(true);
          	margin->repaint();
          	margin->setUpdatesEnabled(false);
          }
          
          
          1 Reply Last reply
          0
          • JoeCFDJ Offline
            JoeCFDJ Offline
            JoeCFD
            wrote on last edited by JoeCFD
            #6
            QPoint p; /* p is the point of text rect left bottom corner. */
            painter.setPen(color);
            painter.drawText(p.x() + off, p.y() + off, text);
            

            you paint text by yourself without calling QPlainTextEdit::paintEvent(e);
            p has to be calculated properly and p.x() can be set with the margin.

            1 Reply Last reply
            0
            • L Offline
              L Offline
              Lasse
              wrote on last edited by
              #7

              The text display is using QSyntaxHighlighter, so it feels quite non-trivial to implement the text rendering without calling paintEvent in the parent class.

              JoeCFDJ 1 Reply Last reply
              0
              • L Lasse

                The text display is using QSyntaxHighlighter, so it feels quite non-trivial to implement the text rendering without calling paintEvent in the parent class.

                JoeCFDJ Offline
                JoeCFDJ Offline
                JoeCFD
                wrote on last edited by JoeCFD
                #8

                @Lasse Try it out to see if there is any side effect. Simple text draw(one func call) and it is not a big deal. If the text is drawn in your class, it is not needed to do it again in parent class.

                1 Reply Last reply
                0
                • L Offline
                  L Offline
                  Lasse
                  wrote on last edited by
                  #9

                  painter.drawText() draws the text using the selected pen color, doesn't it? I vaguely remember trying to figure out how to invoke QSyntaxHighlighter manually (i.e. outside of QPlainTextEdit::paintEvent()) but I was unable to. So I'm not sure how to break each line into substrings that can have different colors according to the attached highlighter.

                  JoeCFDJ 1 Reply Last reply
                  0
                  • L Lasse

                    painter.drawText() draws the text using the selected pen color, doesn't it? I vaguely remember trying to figure out how to invoke QSyntaxHighlighter manually (i.e. outside of QPlainTextEdit::paintEvent()) but I was unable to. So I'm not sure how to break each line into substrings that can have different colors according to the attached highlighter.

                    JoeCFDJ Offline
                    JoeCFDJ Offline
                    JoeCFD
                    wrote on last edited by JoeCFD
                    #10

                    @Lasse It is the color you choose. Try it out and you learn something new. Use the font size to find the bounding box of your text
                    QRect text_rect = this->fontMetrics().tightBoundingRect( text );
                    and then set proper x0 and y0 for the upper corner point of text_rect.

                    1 Reply Last reply
                    0
                    • L Offline
                      L Offline
                      Lasse
                      wrote on last edited by Lasse
                      #11

                      Drawing the QPlainTextEdit by hand seems very hard without calling the parent class' paintEvent.

                      For example, if I move the text to the right in the paint method, the system generating the paint events doesn't know it and the update regions are off. I now have to draw the text cursor manually. QPlainTextEdit::cursorRect() returns the wrong position for the cursor because that also doesn't know where anything is anymore. Obviously I can translate the cursor rectangle before drawing it, but if I do that the cursor will leave visible trails on the screen, again, because the update regions are off. I do not even know if the text cursor should be drawn or not, since sometimes its blinking and therefore should not be drawn. At a glance the blink status information doesn't seem to be available through the QPlainTextEdit API.

                      These are just some of the problems with this approach. Other problems include refactoring and detaching the mentioned QHighlighter functionality from QPlainTextEdit, which is responsible for the colors of the visible glyphs on the screen. Caching glyphs in QPixmaps instead of drawing directly on the surface using drawText() showed some promise in terms of performance, but I'm not convinced of this either. I didn't even start figuring out how to determine if a glyph is selected and thus should be drawn with the different, highlighted background.

                      Seems a bit overkill don't you think. All I wanted to do was move the text to the right a few pixels.

                      1 Reply Last reply
                      0
                      • L Offline
                        L Offline
                        Lasse
                        wrote on last edited by
                        #12

                        I now implemented it using the sub-widget method suggested by @mpergand

                        I'm not completely happy with the result for reasons that are a bit difficult to explain, but its better than nothing so thanks for both of you who replied

                        1 Reply Last reply
                        0

                        • Login

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