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::mergeBlockFormat() doesn't set format.
QtWS25 Last Chance

QTextCursor::mergeBlockFormat() doesn't set format.

Scheduled Pinned Locked Moved Solved General and Desktop
c++ qtwidgetqtexteditqwidget
4 Posts 2 Posters 337 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.
  • K Offline
    K Offline
    Khamza
    wrote on 20 Dec 2024, 11:39 last edited by
    #1

    I have this function for setting block format:

    void PasswordShowArea::updateBlockFormat()
    {
        insertPlainText("Some text");
        QTextBlockFormat fmt = textCursor().blockFormat();
    
        fmt.setTextIndent(g_lineNumberAreaWidth + g_lineNumberRightMargin);
    
        fmt.setLineHeight(fontMetrics().height() * 2, QTextBlockFormat::LineDistanceHeight);
    
        textCursor().mergeBlockFormat(fmt);
    }
    

    Idea was to se block format in constructor but it doesn't work as expected. The function itself is called but neither text is inserted nor block format changed:

    PasswordShowArea::PasswordShowArea(QWidget *parent)
        : QTextEdit(parent)
    {
        init();
    
        //doesn't work
    //  updateBlockFormat();
        // works - gpt4 suggest
        QTimer::singleShot(0, this, &PasswordShowArea::updateBlockFormat);
    }
    
    void PasswordShowArea::init()
    {
        QObject::connect(document()->documentLayout(), &QAbstractTextDocumentLayout::update,
                         this, &PasswordShowArea::updatePasswordShowArea);
    
        setTextColor(palette().color(QPalette::Text));
    
    }
    

    Any ideas why this happen?
    P.S. gpt suggested that the problem may be that the object at the time the updateBlockFormat() is called is not fully initialized

    J 1 Reply Last reply 20 Dec 2024, 13:24
    0
    • K Khamza
      20 Dec 2024, 11:39

      I have this function for setting block format:

      void PasswordShowArea::updateBlockFormat()
      {
          insertPlainText("Some text");
          QTextBlockFormat fmt = textCursor().blockFormat();
      
          fmt.setTextIndent(g_lineNumberAreaWidth + g_lineNumberRightMargin);
      
          fmt.setLineHeight(fontMetrics().height() * 2, QTextBlockFormat::LineDistanceHeight);
      
          textCursor().mergeBlockFormat(fmt);
      }
      

      Idea was to se block format in constructor but it doesn't work as expected. The function itself is called but neither text is inserted nor block format changed:

      PasswordShowArea::PasswordShowArea(QWidget *parent)
          : QTextEdit(parent)
      {
          init();
      
          //doesn't work
      //  updateBlockFormat();
          // works - gpt4 suggest
          QTimer::singleShot(0, this, &PasswordShowArea::updateBlockFormat);
      }
      
      void PasswordShowArea::init()
      {
          QObject::connect(document()->documentLayout(), &QAbstractTextDocumentLayout::update,
                           this, &PasswordShowArea::updatePasswordShowArea);
      
          setTextColor(palette().color(QPalette::Text));
      
      }
      

      Any ideas why this happen?
      P.S. gpt suggested that the problem may be that the object at the time the updateBlockFormat() is called is not fully initialized

      J Offline
      J Offline
      JonB
      wrote on 20 Dec 2024, 13:24 last edited by
      #2

      @Khamza
      Yes, if it does not work in constructor but does work on QTimer::singleShot(0) then you have you answer. There are other places in Qt where this trick is necessary.

      K 1 Reply Last reply 20 Dec 2024, 14:16
      1
      • J JonB
        20 Dec 2024, 13:24

        @Khamza
        Yes, if it does not work in constructor but does work on QTimer::singleShot(0) then you have you answer. There are other places in Qt where this trick is necessary.

        K Offline
        K Offline
        Khamza
        wrote on 20 Dec 2024, 14:16 last edited by Khamza
        #3

        @JonB Thanks for your answer
        I found another solution:

        void PasswordShowArea::showEvent(QShowEvent *event)
        {
            QTextEdit::showEvent(event);
            updateBlockFormat();
        }
        

        Could you please give a brief overview of why both of this approach works?

        J 1 Reply Last reply 21 Dec 2024, 09:38
        0
        • K Khamza
          20 Dec 2024, 14:16

          @JonB Thanks for your answer
          I found another solution:

          void PasswordShowArea::showEvent(QShowEvent *event)
          {
              QTextEdit::showEvent(event);
              updateBlockFormat();
          }
          

          Could you please give a brief overview of why both of this approach works?

          J Offline
          J Offline
          JonB
          wrote on 21 Dec 2024, 09:38 last edited by JonB
          #4

          @Khamza
          First to answer your question. Your new code delays the update till after the text edit has been shown. In that sense it is similar to the QTimer approach. For unknown reason you are claiming the code does not work correctly until after the text edit has been shown.

          There are cases in Qt which this is necessary. In particular sizes of widgets are not calculated till they are actually shown, so code which requires to know a size is often delayed in one of the above two fashions.

          HOWEVER I was never convinced by your assertion "The function itself is called but neither text is inserted nor block format changed:". While I could believe that possibly an operation on textCursor() might require the text edit to be shown I never thought that insertPlainText() for sure would depend on that. It should be callable any time, including e.g. during construction.

          I have now had time to create a minimal repro. Here are the 3 files:

          #include "passwordshowarea.h"
          
          #include <QApplication>
          
          int main(int argc, char *argv[])
          {
              QApplication a(argc, argv);
              PasswordShowArea w;
              w.show();
              return a.exec();
          }
          
          #ifndef PASSWORDSHOWAREA_H
          #define PASSWORDSHOWAREA_H
          
          #include <QTextEdit>
          
          class PasswordShowArea : public QTextEdit
          {
              Q_OBJECT
          
          public:
              PasswordShowArea(QWidget *parent = nullptr);
          private:
              void init();
              void updateBlockFormat();
          };
          #endif // PASSWORDSHOWAREA_H
          
          #include <QAbstractTextDocumentLayout>
          #include <QTimer>
          
          #include "passwordshowarea.h"
          
          PasswordShowArea::PasswordShowArea(QWidget *parent)
              : QTextEdit(parent)
          {
              init();
          
              //doesn't work
              updateBlockFormat();
              // works - gpt4 suggest
              // QTimer::singleShot(0, this, &PasswordShowArea::updateBlockFormat);
          }
          
          void PasswordShowArea::init()
          {
              // QObject::connect(document()->documentLayout(), &QAbstractTextDocumentLayout::update,
              //                  this, &PasswordShowArea::updatePasswordShowArea);
          
              setTextColor(palette().color(QPalette::Text));
          }
          
          void PasswordShowArea::updateBlockFormat()
          {
              insertPlainText("Some text");
              QTextBlockFormat fmt = textCursor().blockFormat();
          
              fmt.setTextIndent(20);
          
              fmt.setLineHeight(fontMetrics().height() * 2, QTextBlockFormat::LineDistanceHeight);
          
              fmt.setBackground(Qt::red);
          
              textCursor().mergeBlockFormat(fmt);
          }
          

          I have made couple of tiny tweaks where I did not have all of your code. I added fmt.setBackground(Qt::red); so that we had something to see. And here is what I get:

          Screenshot 2024-12-21 093554.png

          You can see that not only do I get the inserted text but I do also get the QTextBlockFormat changes. Identical if I change it to only call updateBlockFormat() on the delayed timer. Ubuntu 24.04, Qt 6.4.2.

          Sooo.... I suggest you try just this code.

          1 Reply Last reply
          1
          • K Khamza has marked this topic as solved on 23 Dec 2024, 15:39

          1/4

          20 Dec 2024, 11:39

          • Login

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