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. QTextCursor and html tables
QtWS25 Last Chance

QTextCursor and html tables

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 2 Posters 283 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.
  • M Offline
    M Offline
    Mise
    wrote on last edited by Mise
    #1

    I have a very strange problem with an existing Qt5.10 Applciation and QTextCursor.

    In the application, we have a text input area where the user can paste text from antwhere (word doc, web pages .. etc).

    We also need to sanatize this pasted text before the appliction can accept it.

    Part of this sanatization requires us to use a cursor to go through the document - this is required. But certain users of the application have reported hangs in the app when certain rich text gets pasted. We have narrowed the text that causes the to an odd sequence - and empty table followed by text.

    Let me give an example

    #include "qtguiapplication1.h"
    
    #include <QTextEdit>
    #include <QTextDocument>
    #include <QTextDocumentFragment>
    #include <QTextCursor>
    
    
    QtGuiApplication1::QtGuiApplication1(QWidget *parent)
        : QMainWindow(parent)
    {
        ui.setupUi(this);
    
        QTextEdit textEdit{};
    
        const std::string sourceMimeDataInHtmlFormat = R"(
                    <html>
                       <body>
                          <table>
                                <tr>
                                   <td>
                                   </td>
                                </tr>
                          </table>
                          foo
                       </body>
                    </html>
                )";
    
    
        QString testHtml = QString::fromStdString(sourceMimeDataInHtmlFormat);
        textEdit.insertHtml(testHtml);
    
        QTextCursor cursor{};
        while ((cursor = textEdit.document()->find("foo")) != QTextCursor{})
        {
            cursor.select(QTextCursor::BlockUnderCursor);
            cursor.removeSelectedText();
        }
    }
    

    So as you can see, sourceMimeDataInHtmlFormat is a simple table with an empty cell followed by the word "foo"
    The simple while loop gets stuck in an infinite loop with the above code.

    If the table cell contains text .... any text, the problem doesn't happen! While loop behaves as expected.

    Any idea what could be the problem here?

    1 Reply Last reply
    1
    • M Offline
      M Offline
      Mise
      wrote on last edited by
      #2

      Also tried it on Qt5.15 and the problem is there as well!

      1 Reply Last reply
      0
      • mrjjM Offline
        mrjjM Offline
        mrjj
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi
        It seems it's not able to select as its not a block for it.
        So BlockUnderCursor fails to select the text and it can find it over and over.
        (checked with qDebug() << "sel:" << cursor.selectedText(); )

        so if you do LineUnderCursor instead.

        QTextCursor cursor{};
        while ((cursor = ui->textEdit->document()->find("foo")) != QTextCursor{})
        {
        cursor.select(QTextCursor::LineUnderCursor);
        cursor.removeSelectedText();
        qDebug() << "this" << cursor.selectedText();
        }

        it works.

        So it seems the empty table somehow makes BlockUnderCursor fail
        but im not sure why exactly.

        M 1 Reply Last reply
        1
        • mrjjM mrjj

          Hi
          It seems it's not able to select as its not a block for it.
          So BlockUnderCursor fails to select the text and it can find it over and over.
          (checked with qDebug() << "sel:" << cursor.selectedText(); )

          so if you do LineUnderCursor instead.

          QTextCursor cursor{};
          while ((cursor = ui->textEdit->document()->find("foo")) != QTextCursor{})
          {
          cursor.select(QTextCursor::LineUnderCursor);
          cursor.removeSelectedText();
          qDebug() << "this" << cursor.selectedText();
          }

          it works.

          So it seems the empty table somehow makes BlockUnderCursor fail
          but im not sure why exactly.

          M Offline
          M Offline
          Mise
          wrote on last edited by
          #4

          Thanks @mrjj - that has somewhat solved it.

          It seems that cursor.select(QTextCursor::LineUnderCursor) behaves slightly different to cursor.select(QTextCursor::BlockUnderCursor) for certain input types.
          But it certainly helps me. So thanks again.

          This is what I have now:

              QTextEdit textEdit{};
          
              const std::string sourceMimeDataInHtmlFormat = R"(
                          <html>
                             <body>
                                <table>
                                      <tr>
                                         <td>
                                         </td>
                                      </tr>
                                </table>
                                <p>foo</p>
                                <p>bar</p>
                                <p>foo</p>
                                <p>bar</p>
                             </body>
                          </html>
                      )";
          
          
              QString testHtml = QString::fromStdString(sourceMimeDataInHtmlFormat);
              textEdit.insertHtml(testHtml);
          
              QTextCursor cursor{};
          
              QTextCursor::SelectionType selectionType = QTextCursor::BlockUnderCursor;
              while ((cursor = textEdit.document()->find("foo")) != QTextCursor{})
              {
                  cursor.select(selectionType);
                  if (cursor.selectedText().isEmpty())
                  {
                      // We can get stuck in this while loop forever for certain types of HTML.
                      // Change the selection type for the next time through the loop so we are sure to select the text
                      selectionType = QTextCursor::LineUnderCursor;
                  }
                  else
                  {
                      selectionType = QTextCursor::BlockUnderCursor;
                  }
                  cursor.removeSelectedText();
              }
          
          ```
          mrjjM 1 Reply Last reply
          1
          • M Mise

            Thanks @mrjj - that has somewhat solved it.

            It seems that cursor.select(QTextCursor::LineUnderCursor) behaves slightly different to cursor.select(QTextCursor::BlockUnderCursor) for certain input types.
            But it certainly helps me. So thanks again.

            This is what I have now:

                QTextEdit textEdit{};
            
                const std::string sourceMimeDataInHtmlFormat = R"(
                            <html>
                               <body>
                                  <table>
                                        <tr>
                                           <td>
                                           </td>
                                        </tr>
                                  </table>
                                  <p>foo</p>
                                  <p>bar</p>
                                  <p>foo</p>
                                  <p>bar</p>
                               </body>
                            </html>
                        )";
            
            
                QString testHtml = QString::fromStdString(sourceMimeDataInHtmlFormat);
                textEdit.insertHtml(testHtml);
            
                QTextCursor cursor{};
            
                QTextCursor::SelectionType selectionType = QTextCursor::BlockUnderCursor;
                while ((cursor = textEdit.document()->find("foo")) != QTextCursor{})
                {
                    cursor.select(selectionType);
                    if (cursor.selectedText().isEmpty())
                    {
                        // We can get stuck in this while loop forever for certain types of HTML.
                        // Change the selection type for the next time through the loop so we are sure to select the text
                        selectionType = QTextCursor::LineUnderCursor;
                    }
                    else
                    {
                        selectionType = QTextCursor::BlockUnderCursor;
                    }
                    cursor.removeSelectedText();
                }
            
            ```
            mrjjM Offline
            mrjjM Offline
            mrjj
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @Mise
            Hi
            hopefully there wont be inputs where LineUnderCursor will eat too much :)

            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