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. QTextDocument in thread issue
Forum Updated to NodeBB v4.3 + New Features

QTextDocument in thread issue

Scheduled Pinned Locked Moved Solved General and Desktop
22 Posts 5 Posters 2.7k 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.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #7

    If by passing you mean updating a pointer value, then you are not moving things around.

    Since QTextDocument is a QObject, hence the suggestion of using moveToThread.

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    Cobra91151C 1 Reply Last reply
    0
    • SGaistS SGaist

      If by passing you mean updating a pointer value, then you are not moving things around.

      Since QTextDocument is a QObject, hence the suggestion of using moveToThread.

      Cobra91151C Offline
      Cobra91151C Offline
      Cobra91151
      wrote on last edited by
      #8

      @SGaist

      So, I should call moveToThread on QTextDocument object in a worker or in main GUI? Thanks.

      eyllanescE 1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #9

        Since you create it in your secondary thread, you need to push it to your main thread.

        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
        0
        • Cobra91151C Cobra91151

          @SGaist

          So, I should call moveToThread on QTextDocument object in a worker or in main GUI? Thanks.

          eyllanescE Offline
          eyllanescE Offline
          eyllanesc
          wrote on last edited by
          #10

          @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

          If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

          Cobra91151C 2 Replies Last reply
          0
          • eyllanescE eyllanesc

            @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

            Cobra91151C Offline
            Cobra91151C Offline
            Cobra91151
            wrote on last edited by
            #11

            @SGaist @eyllanesc

            From this old post, I can use QTextDocument object in worker class (second thread) and pass it between the threads: https://www.qt.io/blog/2007/09/27/multi-threaded-text-layout-and-printing

            It contains the old thread design but I want to check out the full source code. Where I can find this snapshot example? Thank you.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #12

              Based on the name, I would go with the Qt 4 sources of Assistant.

              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
              0
              • eyllanescE eyllanesc

                @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

                Cobra91151C Offline
                Cobra91151C Offline
                Cobra91151
                wrote on last edited by
                #13

                @eyllanesc said in QTextDocument in thread issue:

                @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

                @eyllanesc

                I had QTextDocument in my main thread but setPlainText method freezes the GUI for a couple of seconds. So, I need to fix it. That is why I put it to the worker (second thread). Thanks.

                jsulmJ 1 Reply Last reply
                0
                • Cobra91151C Cobra91151

                  @eyllanesc said in QTextDocument in thread issue:

                  @Cobra91151 QTextDocument should not live in a second thread so you get that error. QTextDocument will interact with QObjects that live in the main thread (for example QTextEdit, QPrinter, etc).

                  @eyllanesc

                  I had QTextDocument in my main thread but setPlainText method freezes the GUI for a couple of seconds. So, I need to fix it. That is why I put it to the worker (second thread). Thanks.

                  jsulmJ Offline
                  jsulmJ Offline
                  jsulm
                  Lifetime Qt Champion
                  wrote on last edited by
                  #14

                  @Cobra91151 Qt UI classes should not be used in other threads than main (UI) thread!
                  How big is the text you're trying to load?

                  https://forum.qt.io/topic/113070/qt-code-of-conduct

                  Cobra91151C 1 Reply Last reply
                  1
                  • jsulmJ jsulm

                    @Cobra91151 Qt UI classes should not be used in other threads than main (UI) thread!
                    How big is the text you're trying to load?

                    Cobra91151C Offline
                    Cobra91151C Offline
                    Cobra91151
                    wrote on last edited by
                    #15

                    @jsulm

                    It is 280 pages for printing. I run some debugging and found out that setPlainText does not lead to such issue. The actual problem is with print method. It takes too much time to paint all these pages to the QPrintPreviewDialog.

                    Code:

                    connect(printPreviewDlg, &QPrintPreviewDialog::paintRequested, this, [txtDoc](QPrinter *printer) {
                            txtDoc->print(printer);
                    });
                    

                    I will subclass the QTextDocument and reimplement the print method to display some progress dialog. Thanks.

                    1 Reply Last reply
                    0
                    • Cobra91151C Offline
                      Cobra91151C Offline
                      Cobra91151
                      wrote on last edited by
                      #16

                      Nope, it does not work. The progress dialog still freezing.

                      jsulmJ 1 Reply Last reply
                      0
                      • Cobra91151C Cobra91151

                        Nope, it does not work. The progress dialog still freezing.

                        jsulmJ Offline
                        jsulmJ Offline
                        jsulm
                        Lifetime Qt Champion
                        wrote on last edited by
                        #17

                        @Cobra91151 Can you show ther code?

                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                        Cobra91151C 1 Reply Last reply
                        0
                        • jsulmJ jsulm

                          @Cobra91151 Can you show ther code?

                          Cobra91151C Offline
                          Cobra91151C Offline
                          Cobra91151
                          wrote on last edited by
                          #18

                          @jsulm

                          Yes, I will create the test example and post it soon. Thank you.

                          JonBJ 1 Reply Last reply
                          0
                          • Cobra91151C Cobra91151

                            @jsulm

                            Yes, I will create the test example and post it soon. Thank you.

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by JonB
                            #19

                            @Cobra91151
                            Also for 280 pages just how long does it take/freeze? Oh you said "a couple of seconds". Does your end-user not have the patience to wait 2 seconds for 280 pages? :) If the user prints to printer how long does it take? Users are over-pampered these days....

                            Cobra91151C 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @Cobra91151
                              Also for 280 pages just how long does it take/freeze? Oh you said "a couple of seconds". Does your end-user not have the patience to wait 2 seconds for 280 pages? :) If the user prints to printer how long does it take? Users are over-pampered these days....

                              Cobra91151C Offline
                              Cobra91151C Offline
                              Cobra91151
                              wrote on last edited by
                              #20

                              @jsulm @JonB

                              Here is my test example:

                              printexample.h

                              #ifndef PRINTEXAMPLE_H
                              #define PRINTEXAMPLE_H
                              
                              #include <QWidget>
                              #include <QPushButton>
                              #include <QHBoxLayout>
                              #include <QThread>
                              #include <QPrinter>
                              #include <QPrintPreviewDialog>
                              #include <QToolBar>
                              #include <QTextDocument>
                              #include <QDebug>
                              #include "printworker.h"
                              
                              class PrintExample : public QWidget
                              {
                                  Q_OBJECT
                              
                              public:
                                  PrintExample(QWidget *parent = nullptr);
                                  ~PrintExample();
                              
                              private slots:
                                  void printData();
                                  void setPrintPreviewData(QString printData);
                                  void setPreviewDataGenerationFailed();
                              
                              private:
                                  QLayout *printLayout(QPushButton *btn);
                              };
                              #endif // PRINTEXAMPLE_H
                              

                              printexample.cpp

                              #include "printexample.h"
                              
                              PrintExample::PrintExample(QWidget *parent)
                                  : QWidget(parent)
                              {
                                  setWindowTitle("Print example");
                                  setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
                                  setFixedSize(500, 400);
                                  QPushButton *printBtn = new QPushButton("Print", this);
                                  printBtn->setFixedSize(120, 50);
                                  connect(printBtn, &QPushButton::clicked, this, &PrintExample::printData);
                                  setLayout(printLayout(printBtn));
                              }
                              
                              QLayout *PrintExample::printLayout(QPushButton *btn)
                              {
                                  QHBoxLayout *btnLayout = new QHBoxLayout();
                                  btnLayout->setAlignment(Qt::AlignHCenter);
                                  btnLayout->addWidget(btn);
                                  return btnLayout;
                              }
                              
                              void PrintExample::printData()
                              {
                                  //This is just test example data
                                  QString testBigData = "QTextDocument is a container for structured rich text documents, providing support for styled text and various types of document elements, such as lists, tables, "
                                                        "frames, and images. They can be created for use in a QTextEdit, or used independently. Each document element is described by an associated format object. "
                                                        "Each format object is treated as a unique object by QTextDocuments, and can be passed to objectForFormat() to obtain the document element that it is applied to. "
                                                        "A QTextDocument can be edited programmatically using a QTextCursor, and its contents can be examined by traversing the document structure. "
                                                        "The entire document structure is stored as a hierarchy of document elements beneath the root frame, found with the rootFrame() function. "
                                                        "Alternatively, if you just want to iterate over the textual contents of the document you can use begin(), end(), and findBlock() to retrieve text blocks that you can "
                                                        "examine and iterate over. The layout of a document is determined by the documentLayout(); you can create your own QAbstractTextDocumentLayout subclass and set it using "
                                                        "setDocumentLayout() if you want to use your own layout logic. The document's title and other meta-information can be obtained by calling the metaInformation() "
                                                        "function. For documents that are exposed to users through the QTextEdit class, the document title is also available via the QTextEdit::documentTitle() "
                                                        "function. The toPlainText() and toHtml() convenience functions allow you to retrieve the contents of the document as plain text and HTML. "
                                                        "The document's text can be searched using the find() functions. Undo/redo of operations performed on the document can be controlled using the setUndoRedoEnabled() "
                                                        "function. The undo/redo system can be controlled by an editor widget through the undo() and redo() slots; the document also provides contentsChanged(), "
                                                        "undoAvailable(), and redoAvailable() signals that inform connected editor widgets about the state of the undo/redo system. "
                                                        "The following are the undo/redo operations of a QTextDocument.";
                                  QThread *printDataThread = new QThread();
                                  PrintWorker *printWorker = new PrintWorker();
                                  printWorker->moveToThread(printDataThread);
                                  connect(printWorker, &PrintWorker::generatedPreviewData, this, &PrintExample::setPrintPreviewData);
                                  connect(printWorker, &PrintWorker::previewDataGenerationFailed, this, &PrintExample::setPreviewDataGenerationFailed);
                                  connect(printWorker, &PrintWorker::finished, printDataThread, &QThread::quit);
                                  connect(printWorker, &PrintWorker::finished, printWorker, &PrintWorker::deleteLater);
                                  connect(printDataThread, &QThread::finished, printDataThread, &QThread::deleteLater);
                                  QMetaObject::invokeMethod(printWorker, "generatePrintPreview", Q_ARG(QString, testBigData));
                                  printDataThread->start();
                              }
                              
                              void PrintExample::setPrintPreviewData(QString printData)
                              {
                                  QPrinter *previewPrinter = new QPrinter(QPrinter::HighResolution);
                                  previewPrinter->setOutputFormat(QPrinter::NativeFormat);
                                  previewPrinter->setPaperSize(QPrinter::A4);
                                  previewPrinter->setPageMargins(QMarginsF(15, 15, 15, 15));
                                  QPrintPreviewDialog *printPreviewDlg = new QPrintPreviewDialog(previewPrinter, this);
                                  printPreviewDlg->setGeometry(100, 100, 700, 500);
                                  printPreviewDlg->setMinimumSize(700, 500);
                                  printPreviewDlg->setWindowModality(Qt::ApplicationModal);
                                  printPreviewDlg->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
                                  printPreviewDlg->installEventFilter(this);
                                  QFont docFont;
                                  docFont.setPointSize(14);
                                  QTextDocument *textDoc = new QTextDocument(this);
                                  textDoc->setDefaultFont(docFont);
                                  textDoc->setPlainText(printData);
                                  connect(printPreviewDlg, &QPrintPreviewDialog::paintRequested, this, [this, textDoc](QPrinter *printer) {
                                      textDoc->print(printer);
                                  });
                                  connect(printPreviewDlg, &QPrintPreviewDialog::finished, this, [textDoc, previewPrinter, printPreviewDlg]() {
                                      textDoc->deleteLater();
                                      delete previewPrinter;
                                      printPreviewDlg->deleteLater();
                                  });
                                  printPreviewDlg->show();
                              }
                              
                              void PrintExample::setPreviewDataGenerationFailed()
                              {
                                  //Failed to generate preview
                              }
                              
                              PrintExample::~PrintExample()
                              {
                              
                              }
                              

                              printworker.h:

                              #ifndef PRINTWORKER_H
                              #define PRINTWORKER_H
                              
                              #include <QObject>
                              
                              class PrintWorker : public QObject
                              {
                                  Q_OBJECT
                              public:
                                  explicit PrintWorker(QObject *parent = nullptr);
                              
                              public slots:
                                  void generatePrintPreview(QString previewData);
                              
                              signals:
                                  void generatedPreviewData(QString data);
                                  void previewDataGenerationFailed();
                                  void finished();
                              };
                              
                              #endif // PRINTWORKER_H
                              

                              printworker.cpp:

                              #include "printworker.h"
                              
                              PrintWorker::PrintWorker(QObject *parent) : QObject(parent)
                              {
                              
                              }
                              
                              void PrintWorker::generatePrintPreview(QString previewData)
                              {
                                  if (!previewData.isEmpty()) {
                                      emit generatedPreviewData(previewData);
                                  } else {
                                      emit previewDataGenerationFailed();
                                  }
                              
                                  emit finished();
                              }
                              

                              Screenshot:
                              alt text

                              So, it does not freeze much for 1 page. Anyway, I want to display some progress dialog before the preview dialog. Any ideas? Thanks.

                              jsulmJ 1 Reply Last reply
                              0
                              • Cobra91151C Cobra91151

                                @jsulm @JonB

                                Here is my test example:

                                printexample.h

                                #ifndef PRINTEXAMPLE_H
                                #define PRINTEXAMPLE_H
                                
                                #include <QWidget>
                                #include <QPushButton>
                                #include <QHBoxLayout>
                                #include <QThread>
                                #include <QPrinter>
                                #include <QPrintPreviewDialog>
                                #include <QToolBar>
                                #include <QTextDocument>
                                #include <QDebug>
                                #include "printworker.h"
                                
                                class PrintExample : public QWidget
                                {
                                    Q_OBJECT
                                
                                public:
                                    PrintExample(QWidget *parent = nullptr);
                                    ~PrintExample();
                                
                                private slots:
                                    void printData();
                                    void setPrintPreviewData(QString printData);
                                    void setPreviewDataGenerationFailed();
                                
                                private:
                                    QLayout *printLayout(QPushButton *btn);
                                };
                                #endif // PRINTEXAMPLE_H
                                

                                printexample.cpp

                                #include "printexample.h"
                                
                                PrintExample::PrintExample(QWidget *parent)
                                    : QWidget(parent)
                                {
                                    setWindowTitle("Print example");
                                    setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
                                    setFixedSize(500, 400);
                                    QPushButton *printBtn = new QPushButton("Print", this);
                                    printBtn->setFixedSize(120, 50);
                                    connect(printBtn, &QPushButton::clicked, this, &PrintExample::printData);
                                    setLayout(printLayout(printBtn));
                                }
                                
                                QLayout *PrintExample::printLayout(QPushButton *btn)
                                {
                                    QHBoxLayout *btnLayout = new QHBoxLayout();
                                    btnLayout->setAlignment(Qt::AlignHCenter);
                                    btnLayout->addWidget(btn);
                                    return btnLayout;
                                }
                                
                                void PrintExample::printData()
                                {
                                    //This is just test example data
                                    QString testBigData = "QTextDocument is a container for structured rich text documents, providing support for styled text and various types of document elements, such as lists, tables, "
                                                          "frames, and images. They can be created for use in a QTextEdit, or used independently. Each document element is described by an associated format object. "
                                                          "Each format object is treated as a unique object by QTextDocuments, and can be passed to objectForFormat() to obtain the document element that it is applied to. "
                                                          "A QTextDocument can be edited programmatically using a QTextCursor, and its contents can be examined by traversing the document structure. "
                                                          "The entire document structure is stored as a hierarchy of document elements beneath the root frame, found with the rootFrame() function. "
                                                          "Alternatively, if you just want to iterate over the textual contents of the document you can use begin(), end(), and findBlock() to retrieve text blocks that you can "
                                                          "examine and iterate over. The layout of a document is determined by the documentLayout(); you can create your own QAbstractTextDocumentLayout subclass and set it using "
                                                          "setDocumentLayout() if you want to use your own layout logic. The document's title and other meta-information can be obtained by calling the metaInformation() "
                                                          "function. For documents that are exposed to users through the QTextEdit class, the document title is also available via the QTextEdit::documentTitle() "
                                                          "function. The toPlainText() and toHtml() convenience functions allow you to retrieve the contents of the document as plain text and HTML. "
                                                          "The document's text can be searched using the find() functions. Undo/redo of operations performed on the document can be controlled using the setUndoRedoEnabled() "
                                                          "function. The undo/redo system can be controlled by an editor widget through the undo() and redo() slots; the document also provides contentsChanged(), "
                                                          "undoAvailable(), and redoAvailable() signals that inform connected editor widgets about the state of the undo/redo system. "
                                                          "The following are the undo/redo operations of a QTextDocument.";
                                    QThread *printDataThread = new QThread();
                                    PrintWorker *printWorker = new PrintWorker();
                                    printWorker->moveToThread(printDataThread);
                                    connect(printWorker, &PrintWorker::generatedPreviewData, this, &PrintExample::setPrintPreviewData);
                                    connect(printWorker, &PrintWorker::previewDataGenerationFailed, this, &PrintExample::setPreviewDataGenerationFailed);
                                    connect(printWorker, &PrintWorker::finished, printDataThread, &QThread::quit);
                                    connect(printWorker, &PrintWorker::finished, printWorker, &PrintWorker::deleteLater);
                                    connect(printDataThread, &QThread::finished, printDataThread, &QThread::deleteLater);
                                    QMetaObject::invokeMethod(printWorker, "generatePrintPreview", Q_ARG(QString, testBigData));
                                    printDataThread->start();
                                }
                                
                                void PrintExample::setPrintPreviewData(QString printData)
                                {
                                    QPrinter *previewPrinter = new QPrinter(QPrinter::HighResolution);
                                    previewPrinter->setOutputFormat(QPrinter::NativeFormat);
                                    previewPrinter->setPaperSize(QPrinter::A4);
                                    previewPrinter->setPageMargins(QMarginsF(15, 15, 15, 15));
                                    QPrintPreviewDialog *printPreviewDlg = new QPrintPreviewDialog(previewPrinter, this);
                                    printPreviewDlg->setGeometry(100, 100, 700, 500);
                                    printPreviewDlg->setMinimumSize(700, 500);
                                    printPreviewDlg->setWindowModality(Qt::ApplicationModal);
                                    printPreviewDlg->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);
                                    printPreviewDlg->installEventFilter(this);
                                    QFont docFont;
                                    docFont.setPointSize(14);
                                    QTextDocument *textDoc = new QTextDocument(this);
                                    textDoc->setDefaultFont(docFont);
                                    textDoc->setPlainText(printData);
                                    connect(printPreviewDlg, &QPrintPreviewDialog::paintRequested, this, [this, textDoc](QPrinter *printer) {
                                        textDoc->print(printer);
                                    });
                                    connect(printPreviewDlg, &QPrintPreviewDialog::finished, this, [textDoc, previewPrinter, printPreviewDlg]() {
                                        textDoc->deleteLater();
                                        delete previewPrinter;
                                        printPreviewDlg->deleteLater();
                                    });
                                    printPreviewDlg->show();
                                }
                                
                                void PrintExample::setPreviewDataGenerationFailed()
                                {
                                    //Failed to generate preview
                                }
                                
                                PrintExample::~PrintExample()
                                {
                                
                                }
                                

                                printworker.h:

                                #ifndef PRINTWORKER_H
                                #define PRINTWORKER_H
                                
                                #include <QObject>
                                
                                class PrintWorker : public QObject
                                {
                                    Q_OBJECT
                                public:
                                    explicit PrintWorker(QObject *parent = nullptr);
                                
                                public slots:
                                    void generatePrintPreview(QString previewData);
                                
                                signals:
                                    void generatedPreviewData(QString data);
                                    void previewDataGenerationFailed();
                                    void finished();
                                };
                                
                                #endif // PRINTWORKER_H
                                

                                printworker.cpp:

                                #include "printworker.h"
                                
                                PrintWorker::PrintWorker(QObject *parent) : QObject(parent)
                                {
                                
                                }
                                
                                void PrintWorker::generatePrintPreview(QString previewData)
                                {
                                    if (!previewData.isEmpty()) {
                                        emit generatedPreviewData(previewData);
                                    } else {
                                        emit previewDataGenerationFailed();
                                    }
                                
                                    emit finished();
                                }
                                

                                Screenshot:
                                alt text

                                So, it does not freeze much for 1 page. Anyway, I want to display some progress dialog before the preview dialog. Any ideas? Thanks.

                                jsulmJ Offline
                                jsulmJ Offline
                                jsulm
                                Lifetime Qt Champion
                                wrote on last edited by
                                #21

                                @Cobra91151 I'm not sure there is an easy way to add a progress dialog here as printing does not emit any signals reporting progress as far as I know. But you could have a busy indicator to let the user know that the app is busy. Would that be enough?

                                https://forum.qt.io/topic/113070/qt-code-of-conduct

                                Cobra91151C 1 Reply Last reply
                                2
                                • jsulmJ jsulm

                                  @Cobra91151 I'm not sure there is an easy way to add a progress dialog here as printing does not emit any signals reporting progress as far as I know. But you could have a busy indicator to let the user know that the app is busy. Would that be enough?

                                  Cobra91151C Offline
                                  Cobra91151C Offline
                                  Cobra91151
                                  wrote on last edited by
                                  #22

                                  @jsulm

                                  Yes, it should work well too. Thanks.

                                  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