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 to count and measure the lines in a QTextDocument?
QtWS25 Last Chance

How to count and measure the lines in a QTextDocument?

Scheduled Pinned Locked Moved Solved General and Desktop
measurecountlineqtextdocument
5 Posts 3 Posters 2.8k 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.
  • J Offline
    J Offline
    jeanmilost
    wrote on 3 Apr 2020, 20:07 last edited by
    #1

    In one of my project, I created a QTextDocument which owns a text I need to draw. The text is a word wrapped HTML formatted text, and it should be drawn in a rectangle area, for which I know the width. Its content will also never exceed a paragraph.

    The text document is created as follow:

    // create and configure the text document to measure
    QTextDocument textDoc;
    textDoc.setHtml(text);
    textDoc.setDocumentMargin(m_TextMargin);
    textDoc.setDefaultFont(m_Font);
    textDoc.setDefaultTextOption(m_TextOption);
    textDoc.setTextWidth(m_Background.GetMessageWidth(size().width()));
    

    and here is a sample text I want to draw:

    Ceci est un texte <img src=\"Resources/1f601.svg\" width=\"24\" height=\"24\"> avec <img src=\"Resources/1f970.svg\" width=\"24\" height=\"24\"> une <img src=\"Resources/1f914.svg\" width=\"24\" height=\"24\"> dizaine <img src=\"Resources/1f469-1f3fe.svg\" width=\"24\" height=\"24\"> de <img src=\"Resources/1f3a8.svg\" width=\"24\" height=\"24\"> mots. Pour voir comment la vue réagit.
    

    The images are SVG images get from the qml resources.

    In order to perform several operations while the text is drawn, I need to know how many lines will be drawn, after the word wrapping is applied, and the height of any line in the word wrapped text.

    I tried to search in the functions provided by the text document, as well as those provided in QTextBLock, QTextFragment and QTextCursor. I tried several approaches like iterate through the chars with a cursor and count the lines, or count each fragments in a block. Unfortunately none of them worked: All the functions always count 1 line, or just fail.

    Here are some code sample I already tried, without success:

    // FAILS - always return 1
    int lineCount = textDoc.lineCount()
    
    ....
    
    // FAILS - always return 1
    int lineCount = textDoc.blockCount()
    
    ....
    
    // FAILS - return the whole text height, not a particular line height at index
    int lineHeight = int(textDoc.documentLayout()->blockBoundingRect(textDoc.findBlockByNumber(lineNb)).height());
    
    ....
    
    // get the paragraph (there is only 1 paragraph in the item text document
    QTextBlock textBlock = textDoc.findBlockByLineNumber(lineNb);
    
    int blockCount = 0;
    
    for (QTextBlock::iterator it = textBlock.begin(); it != textBlock.end(); ++it)
    {
        // FAILS - fragments aren't divided by line, e.g an image will generate a fragment
        QString blockText = it.fragment().text();
        ++blockCount;
    }
    
    return blockCount;
    
    ....
    
    QTextCursor cursor(&textDoc);
    
    int lineCount = 0;
    
    cursor.movePosition(QTextCursor::Start);
    
    // FAILS - movePosition() always return false
    while (cursor.movePosition(QTextCursor::Down))
        ++lineCount;
    

    I cannot figure out what I'm doing wrong, and why all my approaches fail.

    So my questions are:

    • How can I count the lines contained in my word wrapped document
    • How can I measure the height of a line in my word wrapped document
    • Are the text document function failing because of the html format? If yes, how should I do to reach my objectives in a such context?

    NOTE I know how to measure the whole text height. However, as each line height may be different, I cannot just divide the whole text height by the lines, so this is not an acceptable solution for me.

    J 1 Reply Last reply 3 Apr 2020, 20:39
    0
    • J jeanmilost
      3 Apr 2020, 21:19

      @JonB Thank you for the answer, however I get the exact same result as in all my other approaches. I explicitly tried the splitByLines() function provided in the accepted answer on Stack Overflow, and I get ... 0 lines a result. I debugged the function, all works fine until the line count is get from the text block layout. As for my previous tries the result is always 0, even if the text is clearly split in several lines.

      I seriously suspect a limitation of the QTextDocument class, which become completely broken when a html text is used. Am I the only one which is facing a such issue?

      C Offline
      C Offline
      Chris Kawa
      Lifetime Qt Champion
      wrote on 3 Apr 2020, 23:17 last edited by Chris Kawa 4 Mar 2020, 23:31
      #4

      @jeanmilost said:

      I seriously suspect a limitation of the QTextDocument class, which become completely broken when a html text is used

      There's nothing wrong with QTextDocument. Your example has only one line so naturally things like textDoc.lineCount() or textDoc.blockCount() will return 1.

      Text document is kinda virtual representation of the document. It doesn't do line breaking for example. This is done by the text layout. You can get currently used layout via QTextDocument::documentLayout(). QTextDocument has a private implementation of that layout interface.

      So, what you want is not the line count of the document but the line count the layout generates when a block is drawn. You can get that with textBlock.layout()->lineCount(). Before you do that call textDoc.documentlayout() to ensures layout is created.

      J 1 Reply Last reply 6 Apr 2020, 15:14
      6
      • J jeanmilost
        3 Apr 2020, 20:07

        In one of my project, I created a QTextDocument which owns a text I need to draw. The text is a word wrapped HTML formatted text, and it should be drawn in a rectangle area, for which I know the width. Its content will also never exceed a paragraph.

        The text document is created as follow:

        // create and configure the text document to measure
        QTextDocument textDoc;
        textDoc.setHtml(text);
        textDoc.setDocumentMargin(m_TextMargin);
        textDoc.setDefaultFont(m_Font);
        textDoc.setDefaultTextOption(m_TextOption);
        textDoc.setTextWidth(m_Background.GetMessageWidth(size().width()));
        

        and here is a sample text I want to draw:

        Ceci est un texte <img src=\"Resources/1f601.svg\" width=\"24\" height=\"24\"> avec <img src=\"Resources/1f970.svg\" width=\"24\" height=\"24\"> une <img src=\"Resources/1f914.svg\" width=\"24\" height=\"24\"> dizaine <img src=\"Resources/1f469-1f3fe.svg\" width=\"24\" height=\"24\"> de <img src=\"Resources/1f3a8.svg\" width=\"24\" height=\"24\"> mots. Pour voir comment la vue réagit.
        

        The images are SVG images get from the qml resources.

        In order to perform several operations while the text is drawn, I need to know how many lines will be drawn, after the word wrapping is applied, and the height of any line in the word wrapped text.

        I tried to search in the functions provided by the text document, as well as those provided in QTextBLock, QTextFragment and QTextCursor. I tried several approaches like iterate through the chars with a cursor and count the lines, or count each fragments in a block. Unfortunately none of them worked: All the functions always count 1 line, or just fail.

        Here are some code sample I already tried, without success:

        // FAILS - always return 1
        int lineCount = textDoc.lineCount()
        
        ....
        
        // FAILS - always return 1
        int lineCount = textDoc.blockCount()
        
        ....
        
        // FAILS - return the whole text height, not a particular line height at index
        int lineHeight = int(textDoc.documentLayout()->blockBoundingRect(textDoc.findBlockByNumber(lineNb)).height());
        
        ....
        
        // get the paragraph (there is only 1 paragraph in the item text document
        QTextBlock textBlock = textDoc.findBlockByLineNumber(lineNb);
        
        int blockCount = 0;
        
        for (QTextBlock::iterator it = textBlock.begin(); it != textBlock.end(); ++it)
        {
            // FAILS - fragments aren't divided by line, e.g an image will generate a fragment
            QString blockText = it.fragment().text();
            ++blockCount;
        }
        
        return blockCount;
        
        ....
        
        QTextCursor cursor(&textDoc);
        
        int lineCount = 0;
        
        cursor.movePosition(QTextCursor::Start);
        
        // FAILS - movePosition() always return false
        while (cursor.movePosition(QTextCursor::Down))
            ++lineCount;
        

        I cannot figure out what I'm doing wrong, and why all my approaches fail.

        So my questions are:

        • How can I count the lines contained in my word wrapped document
        • How can I measure the height of a line in my word wrapped document
        • Are the text document function failing because of the html format? If yes, how should I do to reach my objectives in a such context?

        NOTE I know how to measure the whole text height. However, as each line height may be different, I cannot just divide the whole text height by the lines, so this is not an acceptable solution for me.

        J Offline
        J Offline
        JonB
        wrote on 3 Apr 2020, 20:39 last edited by JonB 4 Mar 2020, 20:41
        #2

        @jeanmilost
        I believe you need to make use of QTextLine, https://doc.qt.io/qt-5/qtextline.html, for what you want. Does https://stackoverflow.com/questions/47038001/get-wrapped-lines-of-qtextedit point you to the approach? (I hope this is good for your HTML, not just plain text...)

        J 1 Reply Last reply 3 Apr 2020, 21:19
        0
        • J JonB
          3 Apr 2020, 20:39

          @jeanmilost
          I believe you need to make use of QTextLine, https://doc.qt.io/qt-5/qtextline.html, for what you want. Does https://stackoverflow.com/questions/47038001/get-wrapped-lines-of-qtextedit point you to the approach? (I hope this is good for your HTML, not just plain text...)

          J Offline
          J Offline
          jeanmilost
          wrote on 3 Apr 2020, 21:19 last edited by
          #3

          @JonB Thank you for the answer, however I get the exact same result as in all my other approaches. I explicitly tried the splitByLines() function provided in the accepted answer on Stack Overflow, and I get ... 0 lines a result. I debugged the function, all works fine until the line count is get from the text block layout. As for my previous tries the result is always 0, even if the text is clearly split in several lines.

          I seriously suspect a limitation of the QTextDocument class, which become completely broken when a html text is used. Am I the only one which is facing a such issue?

          C 1 Reply Last reply 3 Apr 2020, 23:17
          0
          • J jeanmilost
            3 Apr 2020, 21:19

            @JonB Thank you for the answer, however I get the exact same result as in all my other approaches. I explicitly tried the splitByLines() function provided in the accepted answer on Stack Overflow, and I get ... 0 lines a result. I debugged the function, all works fine until the line count is get from the text block layout. As for my previous tries the result is always 0, even if the text is clearly split in several lines.

            I seriously suspect a limitation of the QTextDocument class, which become completely broken when a html text is used. Am I the only one which is facing a such issue?

            C Offline
            C Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on 3 Apr 2020, 23:17 last edited by Chris Kawa 4 Mar 2020, 23:31
            #4

            @jeanmilost said:

            I seriously suspect a limitation of the QTextDocument class, which become completely broken when a html text is used

            There's nothing wrong with QTextDocument. Your example has only one line so naturally things like textDoc.lineCount() or textDoc.blockCount() will return 1.

            Text document is kinda virtual representation of the document. It doesn't do line breaking for example. This is done by the text layout. You can get currently used layout via QTextDocument::documentLayout(). QTextDocument has a private implementation of that layout interface.

            So, what you want is not the line count of the document but the line count the layout generates when a block is drawn. You can get that with textBlock.layout()->lineCount(). Before you do that call textDoc.documentlayout() to ensures layout is created.

            J 1 Reply Last reply 6 Apr 2020, 15:14
            6
            • C Chris Kawa
              3 Apr 2020, 23:17

              @jeanmilost said:

              I seriously suspect a limitation of the QTextDocument class, which become completely broken when a html text is used

              There's nothing wrong with QTextDocument. Your example has only one line so naturally things like textDoc.lineCount() or textDoc.blockCount() will return 1.

              Text document is kinda virtual representation of the document. It doesn't do line breaking for example. This is done by the text layout. You can get currently used layout via QTextDocument::documentLayout(). QTextDocument has a private implementation of that layout interface.

              So, what you want is not the line count of the document but the line count the layout generates when a block is drawn. You can get that with textBlock.layout()->lineCount(). Before you do that call textDoc.documentlayout() to ensures layout is created.

              J Offline
              J Offline
              jeanmilost
              wrote on 6 Apr 2020, 15:14 last edited by
              #5

              @Chris-Kawa Thank you very much, this worked and was exactly what I needed to resolve my issue. Thank you also for the explanations, clear and precise.

              1 Reply Last reply
              0

              1/5

              3 Apr 2020, 20:07

              • 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