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. QObject::connect: Cannot queue arguments of type 'QTextCursor'
QtWS25 Last Chance

QObject::connect: Cannot queue arguments of type 'QTextCursor'

Scheduled Pinned Locked Moved Unsolved General and Desktop
qtextcursorconnectprocessqtexteditmultithreading
16 Posts 5 Posters 17.3k 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.
  • B Offline
    B Offline
    bachir
    wrote on 10 Aug 2018, 09:25 last edited by
    #1

    Hi everyone,

    I have a issue that I was not able to solve. Can anyone help me please?

    QObject::connect: Cannot queue arguments of type 'QTextCursor'
    (Make sure 'QTextCursor' is registered using qRegisterMetaType().)

    The weird part is that I am not declaring at all an object of type 'QTextCursor'.

    I have a controller class, implemented as a singleton that instantiate processes :

    • taskprocessor.cpp
    #include "taskprocessor.h"
    
    TaskProcessor *TaskProcessor::instance = new TaskProcessor();
    
    TaskProcessor *TaskProcessor::getInstance() {
        return instance;
    }
    
    TaskProcessor::TaskProcessor() : QObject() {
    }
    
    QProcess *TaskProcessor::proc(const QString &program, const QStringList &arguments, const QStringList &dispargs,  const QMap<int, QString> &display) {
        // instantiate a new process
        QProcess *process = new QProcess();
        // set the program to process
        process->setProgram(program);
        // set the program arguments
        process->setArguments(arguments);
        // display the command on started
        QString commandName = display.value(DISPLAY_COMMAND);
        QString commandLine = program+" "+dispargs.join(" ");
        connect(process,&QProcess::started, [this, commandName, commandLine]{print(commandName,commandLine);});
        // return the process instance
        return process;
    }
    
    void TaskProcessor::print(const QString &commandName, const QString &commandLine) {
        // display the command name
        if (!commandName.isEmpty())
            emit printInfo(commandName);
        // display the command line
        emit printLog(commandLine);
    }
    
    • taskprocessor.h
    #ifndef TASKPROCESSOR_H
    #define TASKPROCESSOR_H
    
    #include <QProcess>
    #include <QObject>
    #include <QMap>
    
    // the display string
    #define DISPLAY_COMMAND 0
    #define DISPLAY_SUCCESS 1
    #define DISPLAY_ERROR -1
    
    /**
     * @class TaskProcessor
     * @brief The task processor class
     * Generate the tasks process
     */
    class TaskProcessor : public QObject
    {
        Q_OBJECT
    
        public:
            /**
             * @brief Get the class instance
             * @return The class instance
             */
            static TaskProcessor *getInstance();
            /**
             * @brief Process a new program with its arguments
             * @param program The program
             * @param arguments The arguments
             * @param dispargs The arguments to display
             * @param display The strings to display
             * @return The process
             */
            QProcess *proc(const QString &program, const QStringList &arguments, const QStringList &dispargs, const QMap<int,QString> &display);
    
        private:
            /**
             * @brief The class instance
             */
            static TaskProcessor *instance;
            /**
             * @brief The default constructor
             */
            TaskProcessor();
            /**
             * @brief Display the command
             * @param commandName The command name
             * @param commandLine The command line
             */
            void print(const QString &commandName, const QString &commandLine);
    
        signals:
            /**
             * \brief Print a error message in the console
             * \param message The message
             */
            void printError(QString message);
            /**
             * \brief Print a log message in the console
             * \param message The message
             */
            void printLog(QString message);
            /**
             * \brief Print an info message in the console
             * \param message The message
             */
            void printInfo(QString message);
            /**
             * \brief Print an success message in the console
             * \param message The message
             */
            void printSuccess(QString message);
    };
    
    #endif // TASKPROCESSOR_H
    
    

    And I have of course a main window class

    • mainwindow.cpp
    #include "mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent)
    {
        /* The task processor */
        TaskProcessor *taskProcessor = TaskProcessor::getInstance();
        connect(taskProcessor, &TaskProcessor::printError, [this](QString message){consolePrint(message, ConsoleMsgType::error);});
        connect(taskProcessor, &TaskProcessor::printLog, [this](QString message){consolePrint(message);});
        connect(taskProcessor, &TaskProcessor::printInfo, [this](QString message){consolePrint(message,ConsoleMsgType::info);});
        connect(taskProcessor, &TaskProcessor::printSuccess, [this](QString message){consolePrint(message,ConsoleMsgType::success);});
    
        /* The console */
        consoleDock = new QDockWidget(this);
        console = new QTextEdit(consoleDock);
        console->setTextColor(Qt::white);
        QPalette p = console->palette();
        p.setColor(QPalette::Base, QColor(20,0,20));
        console->setPalette(p);
        console->setReadOnly(true);
        consoleDock->setWidget(console);
        consoleDock->setAllowedAreas(Qt::BottomDockWidgetArea);
        consoleDock->setFeatures(QDockWidget::NoDockWidgetFeatures);
        addDockWidget(Qt::BottomDockWidgetArea, consoleDock);
        setCorner(Qt::BottomLeftCorner, Qt::BottomDockWidgetArea);
        setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
    }
    
    void MainWindow::consolePrint(QString msg, ConsoleMsgType mtype){
        QString endMsg;
        switch(mtype){
            case log:
                endMsg = "<span style='color:white'>";
                break;
            case error:
                endMsg = "<span style='color:red'>";
                break;
            case info:
                endMsg = "<span style='color:cyan'>";
                break;
            case warning:
                endMsg = "<span style='color:orange'>";
                break;
            case success:
                endMsg = "<span style='color:lime'>";
                break;
        }
    
        endMsg += msg + "</span>";
    
        console->append(endMsg);
    }
    

    My code is clearly more complex but I am just giving the relevant part.

    • When the process generated by the class TaskProcessor is executed on the same thread, everything is fine : the command is printed in the console and no error message appears.
      BUT
    • When the same process is executed on another thread, I have the error message (see below) and the command is still printed in the console. Yet, the first line is invisible and this line becomes visible only if we click on it! Very weird!

    QObject::connect: Cannot queue arguments of type 'QTextCursor'
    (Make sure 'QTextCursor' is registered using qRegisterMetaType().)

    So it seems to be a multi-threading issue caused by this instruction connect(process,&QProcess::started, [this, commandName, commandLine]{print(commandName,commandLine);});. However:

    • If I connect directly the process started signal to the main window, and even if the process is started from another thread, it is all right. No message error;
    • The class instance of TaskProcessor is on the same thread that the class instance of MainWindow;
    • If the last line console->append(endMsg); is commented, I have no more error message (and there is no more print on the console...).

    I have tried registering QTextCursor with qRegisterMetaType, but it doesn't help;

    Anyone can tell what I am doing wrong, and how to fix that? Many thanks.

    Bachir.

    1 Reply Last reply
    0
    • hskoglundH Offline
      hskoglundH Offline
      hskoglund
      wrote on 10 Aug 2018, 10:02 last edited by
      #2

      Hi, you can try using a more robust flavor of connect() by adding an argument after the lambda, like this:

      connect(process,&QProcess::started, [this, commandName, commandLine]{print(commandName,commandLine);},Qt::BlockingQueuedConnection);
      1 Reply Last reply
      1
      • B Offline
        B Offline
        bachir
        wrote on 10 Aug 2018, 10:47 last edited by
        #3

        Hi,

        thanks for your answer.

        I tried but it doesn't compile.

        no matching function for call to ‘TaskProcessor::connect(QProcess*&, void (QProcess::*)(QProcess::QPrivateSignal), TaskProcessor::proc(const QString&, const QStringList&, const QStringList&, const QMap<int, QString>&)::<lambda()>, Qt::ConnectionType)’

        1 Reply Last reply
        0
        • B Offline
          B Offline
          bachir
          wrote on 10 Aug 2018, 12:52 last edited by
          #4

          Finally, that works!
          I have been able to compile and test.
          But I don't understand, why it was not working with default Qt::AutoConnection?
          The doc says : The connection type is determined when the signal is emitted.
          So that means that Qt was not able to connect correctly the signal?
          And why when I connect to the main window, it works without any problem??

          It will be helpful if you can help me understand this weird behaviour as I am not at ease with Qt signal and slots.
          Many thanks,
          Bachir.

          B 1 Reply Last reply 10 Jun 2019, 09:17
          0
          • hskoglundH Offline
            hskoglundH Offline
            hskoglund
            wrote on 10 Aug 2018, 14:29 last edited by hskoglund 8 Oct 2018, 14:47
            #5

            Hi, a good read about Qt's signal/slot is here

            Re. why Qt::BlockingQueuedConnection works, just guessing, but when the connection is to a lambda, then when QProcess::started emits the signal, perhaps it cannot properly detect that the lambda's from another thread, so the connection defaults to Qt::DirectConnection (not good).

            Edit: googled a bit about connect() to lambdas across threads and it looks that when the signal is emitted to a lambda the detection if it's across threads or not indeed is shaky. To avoid that, you could try a connect() to a member function of TaskProcessor instead of a lambda.

            kshegunovK 1 Reply Last reply 10 Aug 2018, 16:25
            5
            • B Offline
              B Offline
              bachir
              wrote on 10 Aug 2018, 15:25 last edited by
              #6

              Thanks a lot for your answer, complete and clear.
              Thanks again!

              Bachir.

              1 Reply Last reply
              0
              • hskoglundH hskoglund
                10 Aug 2018, 14:29

                Hi, a good read about Qt's signal/slot is here

                Re. why Qt::BlockingQueuedConnection works, just guessing, but when the connection is to a lambda, then when QProcess::started emits the signal, perhaps it cannot properly detect that the lambda's from another thread, so the connection defaults to Qt::DirectConnection (not good).

                Edit: googled a bit about connect() to lambdas across threads and it looks that when the signal is emitted to a lambda the detection if it's across threads or not indeed is shaky. To avoid that, you could try a connect() to a member function of TaskProcessor instead of a lambda.

                kshegunovK Offline
                kshegunovK Offline
                kshegunov
                Moderators
                wrote on 10 Aug 2018, 16:25 last edited by
                #7

                @hskoglund said in QObject::connect: Cannot queue arguments of type 'QTextCursor':

                googled a bit about connect() to lambdas across threads and it looks that when the signal is emitted to a lambda the detection if it's across threads or not indeed is shaky.

                This makes no sense Henry, a lambda is at best just a regular object it has no notion of threads to begin with. That's why you can specify context QObject (and you should) when connecting signals to lambdas.

                Read and abide by the Qt Code of Conduct

                hskoglundH 1 Reply Last reply 10 Aug 2018, 17:11
                0
                • kshegunovK kshegunov
                  10 Aug 2018, 16:25

                  @hskoglund said in QObject::connect: Cannot queue arguments of type 'QTextCursor':

                  googled a bit about connect() to lambdas across threads and it looks that when the signal is emitted to a lambda the detection if it's across threads or not indeed is shaky.

                  This makes no sense Henry, a lambda is at best just a regular object it has no notion of threads to begin with. That's why you can specify context QObject (and you should) when connecting signals to lambdas.

                  hskoglundH Offline
                  hskoglundH Offline
                  hskoglund
                  wrote on 10 Aug 2018, 17:11 last edited by
                  #8

                  @kshegunov Thanks for the clarification, it makes sense., i.e. the detection is not "shaky" it's impossible to do!

                  I should have a coffee and study the source code for how that detection is done when signals are emitted across threads.

                  And, this "problem" with connecting to lambdas across threads should be documented better I think.

                  kshegunovK 1 Reply Last reply 10 Aug 2018, 17:18
                  0
                  • hskoglundH hskoglund
                    10 Aug 2018, 17:11

                    @kshegunov Thanks for the clarification, it makes sense., i.e. the detection is not "shaky" it's impossible to do!

                    I should have a coffee and study the source code for how that detection is done when signals are emitted across threads.

                    And, this "problem" with connecting to lambdas across threads should be documented better I think.

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on 10 Aug 2018, 17:18 last edited by
                    #9

                    @hskoglund said in QObject::connect: Cannot queue arguments of type 'QTextCursor':

                    Thanks for the clarification, it makes sense., i.e. the detection is not "shaky" it's impossible to do!

                    Exactly!

                    I should have a coffee and study the source code for how that detection is done when signals are emitted across threads.

                    Coffee sounds nice, I'm now envious ... ;)
                    You can look here about the second part:
                    https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qobject.cpp.html#_ZN11QMetaObject8activateEP7QObjectiiPPv

                    And, this "problem" with connecting to lambdas across threads should be documented better I think.

                    Perhaps you're right, but I'm too lazy to check what it really says in the docs ... :p
                    However I think it's documented, probably more emphasis can be put though.

                    Read and abide by the Qt Code of Conduct

                    1 Reply Last reply
                    2
                    • B bachir
                      10 Aug 2018, 12:52

                      Finally, that works!
                      I have been able to compile and test.
                      But I don't understand, why it was not working with default Qt::AutoConnection?
                      The doc says : The connection type is determined when the signal is emitted.
                      So that means that Qt was not able to connect correctly the signal?
                      And why when I connect to the main window, it works without any problem??

                      It will be helpful if you can help me understand this weird behaviour as I am not at ease with Qt signal and slots.
                      Many thanks,
                      Bachir.

                      B Offline
                      B Offline
                      Bremenpl
                      wrote on 10 Jun 2019, 09:17 last edited by
                      #10

                      @bachir Hi there,
                      sorry for digging this up. How did you get to compile this lambda connection with the additional argument? I still cannot do that.

                      This works:

                      		connect(uap, &CUaProxy::uaItemChanged,
                      				[this, i](
                      				const CUaProxy::MsgType msgt,
                      				const int riskIndex,
                      				const QVariant& value)
                      		{
                      			this->onUaMsgReceived(msgt, i, riskIndex, value);
                      		});
                      

                      This doesnt compile:

                      		connect(uap, &CUaProxy::uaItemChanged,
                      				[this, i](
                      				const CUaProxy::MsgType msgt,
                      				const int riskIndex,
                      				const QVariant& value)
                      		{
                      			this->onUaMsgReceived(msgt, i, riskIndex, value);
                      		}, Qt::BlockingQueuedConnection);
                      

                      Would appreciate your feedback.

                      lprzenioslo.zut.edu.pl

                      1 Reply Last reply
                      0
                      • Christian EhrlicherC Offline
                        Christian EhrlicherC Offline
                        Christian Ehrlicher
                        Lifetime Qt Champion
                        wrote on 10 Jun 2019, 09:33 last edited by
                        #11

                        @Bremenpl said in QObject::connect: Cannot queue arguments of type 'QTextCursor':

                        This doesnt compile:

                        And what compiler error do you get?

                        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                        Visit the Qt Academy at https://academy.qt.io/catalog

                        B 1 Reply Last reply 10 Jun 2019, 09:38
                        1
                        • Christian EhrlicherC Christian Ehrlicher
                          10 Jun 2019, 09:33

                          @Bremenpl said in QObject::connect: Cannot queue arguments of type 'QTextCursor':

                          This doesnt compile:

                          And what compiler error do you get?

                          B Offline
                          B Offline
                          Bremenpl
                          wrote on 10 Jun 2019, 09:38 last edited by
                          #12

                          @Christian-Ehrlicher Sorry I didnt add it, here it is:

                          cintegrator.cpp:63: error: no matching member function for call to 'connect'
                          
                          cintegrator.cpp:70: error: no matching function for call to 'CIntegrator::connect(CUaProxy*&, void (CUaProxy::*)(CUaProxy::MsgType, int, const QVariant&), CIntegrator::uaInit()::<lambda(CUaProxy::MsgType, int, const QVariant&)>, Qt::ConnectionType)'
                             }, Qt::DirectConnection);
                                                    ^
                          
                          qobject.h:228: error: no type named 'Object' in 'struct QtPrivate::FunctionPointer<Qt::ConnectionType>'
                          

                          lprzenioslo.zut.edu.pl

                          kshegunovK 1 Reply Last reply 10 Jun 2019, 09:43
                          0
                          • B Bremenpl
                            10 Jun 2019, 09:38

                            @Christian-Ehrlicher Sorry I didnt add it, here it is:

                            cintegrator.cpp:63: error: no matching member function for call to 'connect'
                            
                            cintegrator.cpp:70: error: no matching function for call to 'CIntegrator::connect(CUaProxy*&, void (CUaProxy::*)(CUaProxy::MsgType, int, const QVariant&), CIntegrator::uaInit()::<lambda(CUaProxy::MsgType, int, const QVariant&)>, Qt::ConnectionType)'
                               }, Qt::DirectConnection);
                                                      ^
                            
                            qobject.h:228: error: no type named 'Object' in 'struct QtPrivate::FunctionPointer<Qt::ConnectionType>'
                            
                            kshegunovK Offline
                            kshegunovK Offline
                            kshegunov
                            Moderators
                            wrote on 10 Jun 2019, 09:43 last edited by kshegunov 6 Oct 2019, 09:44
                            #13

                            @Bremenpl said in QObject::connect: Cannot queue arguments of type 'QTextCursor':

                            Sorry I didnt add it, here it is

                            You can't have blocking queued connection (or explicitly specify the connection type for that matter) without specifying a context object. Qt can't know what's the receiving thread this is supposed to block.

                            Read and abide by the Qt Code of Conduct

                            B 1 Reply Last reply 10 Jun 2019, 09:45
                            0
                            • kshegunovK kshegunov
                              10 Jun 2019, 09:43

                              @Bremenpl said in QObject::connect: Cannot queue arguments of type 'QTextCursor':

                              Sorry I didnt add it, here it is

                              You can't have blocking queued connection (or explicitly specify the connection type for that matter) without specifying a context object. Qt can't know what's the receiving thread this is supposed to block.

                              B Offline
                              B Offline
                              Bremenpl
                              wrote on 10 Jun 2019, 09:45 last edited by Bremenpl 6 Oct 2019, 09:46
                              #14

                              @kshegunov To be honest this was just an example. Originally I was aiming for Qt::DirectConnection which doesnt compile as well (same errors). How to point the context object?

                              lprzenioslo.zut.edu.pl

                              kshegunovK 1 Reply Last reply 10 Jun 2019, 09:47
                              0
                              • B Bremenpl
                                10 Jun 2019, 09:45

                                @kshegunov To be honest this was just an example. Originally I was aiming for Qt::DirectConnection which doesnt compile as well (same errors). How to point the context object?

                                kshegunovK Offline
                                kshegunovK Offline
                                kshegunov
                                Moderators
                                wrote on 10 Jun 2019, 09:47 last edited by kshegunov 6 Oct 2019, 09:48
                                #15

                                @Bremenpl said in QObject::connect: Cannot queue arguments of type 'QTextCursor':

                                To be honest this was just an example. Originally I was aiming for Qt::DirectConnection which doesnt compile as well (same errors).

                                Give context object. Otherwise specifying a connection type makes no sense whatsoever. If the slot's to be called in the emitting thread then you can omit the connection type, and then it implies "direct". In all other cases you must know what's the receiving thread, which you can specify only through a QObject you pass as context.

                                How to point the context object?

                                https://doc.qt.io/qt-5/qobject.html#connect-5

                                Read and abide by the Qt Code of Conduct

                                B 1 Reply Last reply 10 Jun 2019, 09:53
                                2
                                • kshegunovK kshegunov
                                  10 Jun 2019, 09:47

                                  @Bremenpl said in QObject::connect: Cannot queue arguments of type 'QTextCursor':

                                  To be honest this was just an example. Originally I was aiming for Qt::DirectConnection which doesnt compile as well (same errors).

                                  Give context object. Otherwise specifying a connection type makes no sense whatsoever. If the slot's to be called in the emitting thread then you can omit the connection type, and then it implies "direct". In all other cases you must know what's the receiving thread, which you can specify only through a QObject you pass as context.

                                  How to point the context object?

                                  https://doc.qt.io/qt-5/qobject.html#connect-5

                                  B Offline
                                  B Offline
                                  Bremenpl
                                  wrote on 10 Jun 2019, 09:53 last edited by
                                  #16

                                  @kshegunov Right... Thanks, something didnt trigger in the brain. Now its fine:

                                  connect(uap, &CUaProxy::uaItemChanged, this,
                                  		[this, i](
                                  		const CUaProxy::MsgType msgt,
                                  		const int riskIndex,
                                  		const QVariant& value)
                                  {
                                  	this->onUaMsgReceived(msgt, i, riskIndex, value);
                                  }, Qt::QueuedConnection);
                                  

                                  Also needed Qt::QueuedConnection eventually.

                                  lprzenioslo.zut.edu.pl

                                  1 Reply Last reply
                                  3

                                  • Login

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