Search code examples
c++qtsignals-slots

QObject::connect: No such signal runtime warning - cannot find the reasion for


I am working on async multithreaded server, based on this example. Now, I the following method:

void UeClient::ueSlotReadyRead()
{
    QList<QVariant> incomingData=QList<QVariant>();
    QByteArray incomingMessage=this->ueSocket()->readAll();

    UePosCommProtocolArch::UeCommand incomingCommand=UePOSCommProtocol::ueDecodeCommand(incomingMessage,
                                                                                        incomingData);

    UeTask* ueTask=new UeTask("testDb",
                              "testUsername",
                              "testPassword",
                              "localhost",
                              "3306",
                              incomingCommand);

    connect(ueTask,
            SIGNAL(ueSignalTaskFinished(UePosCommProtocolArch::UeCommand,
                                        QByteArray)),
            this,
            SLOT(ueSlotFetchData(UePosCommProtocolArch::UeCommand,
                                 QByteArray)),
            Qt::QueuedConnection);

    QThreadPool::globalInstance()->start(ueTask);
}   // ueSlotReadyRead

I get following runtime warning/error in QtCreator:

QObject::connect: No such signal UeTask::ueSignalTaskFinished(UePosCommProtocolArch::UeCommand, QByteArray) in ../../../net/ueclient.cpp:55

Here is UeTask class header file, from which we can see ueSignalTaskFinished(UePosCommProtocolArch::UeCommand& executedCommand, QByteArray& fetchedData); IS declared:

#ifndef UETASK_H
#define UETASK_H

#include <QObject>
#include <QRunnable>
#include <QSqlDatabase>
#include <QSqlError>
#include <QUuid>
#include <QString>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QVariant>
#include <QJsonDocument>
#include <QJsonValue>
#include <QJsonObject>
#include <QJsonArray>
#include <QByteArray>

#include "../../uePOSCommProtocol/uecommands.h"
#include "database/models/uefieldindexes.h"
#include "database/models/uequeries.h"

/*!
 * \brief The UeTask class
 */
class UeTask : public QObject,
               public QRunnable
{
    Q_OBJECT

private:
    /*!
     * \brief m_ueDatabaseName
     */
    QString m_ueDatabaseName;

    /*!
     * \brief m_ueUserName
     */
    QString m_ueUserName;

    /*!
     * \brief m_uePassword
     */
    QString m_uePassword;

    /*!
     * \brief m_ueHostName
     */
    QString m_ueHostName;

    /*!
     * \brief m_uePort
     */
    QString m_uePort;

    /*!
     * \brief m_ueCommand
     */
    UePosCommProtocolArch::UeCommand m_ueCommand;

    /*!
     * @brief ueDatabaseName
     * @return database name
     */
    inline const QString& ueDatabaseName() const
        { return this->m_ueDatabaseName; }

    /*!
     * @brief ueDatabaseUserName
     * @return database user name
     */
    inline const QString& ueDatabaseUserName() const
        { return this->m_ueUserName; }

    /*!
     * @brief ueDatabasePassword
     * @return database password
     */
    inline const QString& ueDatabasePassword() const
        { return this->m_uePassword; }

    /*!
     * @brief ueDatabasHost
     * @return database host name
     */
    inline const QString& ueDatabasHost() const
        { return this->m_ueHostName; }

    /*!
     * @brief uePort
     * @return database host port
     */
    inline const QString& ueDatabaseHostPort() const
        { return this->m_uePort; }

    /*!
     * \brief ueCommand
     * \return task command
     */
    inline UePosCommProtocolArch::UeCommand& ueCommand()
        { return this->m_ueCommand; }

    /*!
     * @brief ueSetDatbaseName
     * @param name
     */
    inline void ueSetDatbaseName(const QString& name)
        { this->m_ueDatabaseName=name; }

    /*!
     * @brief ueSetDatabaseUserName
     * @param userName
     */
    inline void ueSetDatabaseUserName(const QString& userName)
        { this->m_ueUserName=userName; }

    /*!
     * @brief ueSetDatabasePassword
     * @param password
     */
    inline void ueSetDatabasePassword(const QString& password)
        { this->m_uePassword=password; }

    /*!
     * @brief ueSetDatabaseHostName
     * @param hostName
     */
    inline void ueSetDatabaseHostName(const QString& hostName)
        { this->m_ueHostName=hostName; }

    /*!
     * @brief ueSetDatabaseHostPort
     * @param port
     */
    inline void ueSetDatabaseHostPort(const QString& port)
        { this->m_uePort=port; }

    /*!
     * \brief ueSetCommand
     * \param command
     */
    inline void ueSetCommand(const UePosCommProtocolArch::UeCommand& command)
        { this->m_ueCommand=command; }

public:
    /*!
     * @brief UeTask
     */
    explicit UeTask(const QString& databaseName,
                    const QString& userName,
                    const QString& password,
                    const QString& hostName,
                    const QString& port,
                    const UePosCommProtocolArch::UeCommand& command);

protected:
    /*!
     * @brief run
     */
    void run();

signals:
    /*!
     * \brief ueSignalTaskFinished
     * \param executedCommand
     * \param fetchedData
     */
    void ueSignalTaskFinished(UePosCommProtocolArch::UeCommand& executedCommand,
                              QByteArray& fetchedData);

    /*!
     * @brief ueSignalDatabaseConnectionOk
     */
    void ueSignalDatabaseConnectionOk();

    /*!
     * @brief ueSignalDatabaseConnectionError
     * @param error
     */
    void ueSignalDatabaseConnectionError(const QSqlError& error);
};

#endif // UETASK_H

Why the hell am I a getting this runtime warning/error and signal is NOT connected to slot? This might be some dumb mistake made, but I have been struggling with this bug for several hours ...


Solution

  • I've managed to solve the problem via @peppe's answer and I've added const to SIGNAL's declaration:

    #ifndef UETASK_H
    #define UETASK_H
    
    #include <QObject>
    #include <QRunnable>
    #include <QSqlDatabase>
    #include <QSqlError>
    #include <QUuid>
    #include <QString>
    #include <QSqlQuery>
    #include <QSqlRecord>
    #include <QVariant>
    #include <QJsonDocument>
    #include <QJsonValue>
    #include <QJsonObject>
    #include <QJsonArray>
    #include <QByteArray>
    
    #include "../../uePOSCommProtocol/uecommands.h"
    #include "database/models/uefieldindexes.h"
    #include "database/models/uequeries.h"
    
    /*!
     * \brief The UeTask class
     */
    class UeTask : public QObject,
                   public QRunnable
    {
        Q_OBJECT
    
    private:
        /*!
         * \brief m_ueDatabaseName
         */
        QString m_ueDatabaseName;
    
        /*!
         * \brief m_ueUserName
         */
        QString m_ueUserName;
    
        /*!
         * \brief m_uePassword
         */
        QString m_uePassword;
    
        /*!
         * \brief m_ueHostName
         */
        QString m_ueHostName;
    
        /*!
         * \brief m_uePort
         */
        QString m_uePort;
    
        /*!
         * \brief m_ueCommand
         */
        UePosCommProtocolArch::UeCommand m_ueCommand;
    
        /*!
         * @brief ueDatabaseName
         * @return database name
         */
        inline const QString& ueDatabaseName() const
            { return this->m_ueDatabaseName; }
    
        /*!
         * @brief ueDatabaseUserName
         * @return database user name
         */
        inline const QString& ueDatabaseUserName() const
            { return this->m_ueUserName; }
    
        /*!
         * @brief ueDatabasePassword
         * @return database password
         */
        inline const QString& ueDatabasePassword() const
            { return this->m_uePassword; }
    
        /*!
         * @brief ueDatabasHost
         * @return database host name
         */
        inline const QString& ueDatabasHost() const
            { return this->m_ueHostName; }
    
        /*!
         * @brief uePort
         * @return database host port
         */
        inline const QString& ueDatabaseHostPort() const
            { return this->m_uePort; }
    
        /*!
         * \brief ueCommand
         * \return task command
         */
        inline UePosCommProtocolArch::UeCommand& ueCommand()
            { return this->m_ueCommand; }
    
        /*!
         * @brief ueSetDatbaseName
         * @param name
         */
        inline void ueSetDatbaseName(const QString& name)
            { this->m_ueDatabaseName=name; }
    
        /*!
         * @brief ueSetDatabaseUserName
         * @param userName
         */
        inline void ueSetDatabaseUserName(const QString& userName)
            { this->m_ueUserName=userName; }
    
        /*!
         * @brief ueSetDatabasePassword
         * @param password
         */
        inline void ueSetDatabasePassword(const QString& password)
            { this->m_uePassword=password; }
    
        /*!
         * @brief ueSetDatabaseHostName
         * @param hostName
         */
        inline void ueSetDatabaseHostName(const QString& hostName)
            { this->m_ueHostName=hostName; }
    
        /*!
         * @brief ueSetDatabaseHostPort
         * @param port
         */
        inline void ueSetDatabaseHostPort(const QString& port)
            { this->m_uePort=port; }
    
        /*!
         * \brief ueSetCommand
         * \param command
         */
        inline void ueSetCommand(const UePosCommProtocolArch::UeCommand& command)
            { this->m_ueCommand=command; }
    
    public:
        /*!
         * @brief UeTask
         */
        explicit UeTask(const QString& databaseName,
                        const QString& userName,
                        const QString& password,
                        const QString& hostName,
                        const QString& port,
                        const UePosCommProtocolArch::UeCommand& command);
    
    protected:
        /*!
         * @brief run
         */
        void run();
    
    signals:
        /*!
         * \brief ueSignalTaskFinished
         * \param executedCommand
         * \param fetchedData
         */
        void ueSignalTaskFinished(const UePosCommProtocolArch::UeCommand& executedCommand,
                                  const QByteArray& fetchedData);
    
        /*!
         * @brief ueSignalDatabaseConnectionOk
         */
        void ueSignalDatabaseConnectionOk();
    
        /*!
         * @brief ueSignalDatabaseConnectionError
         * @param error
         */
        void ueSignalDatabaseConnectionError(const QSqlError& error);
    };
    
    #endif // UETASK_H
    

    Then I had to register meta type with:

    qRegisterMetaType<UePosCommProtocolArch::UeCommand>("UePosCommProtocolArch::UeCommand");
    

    in constructor of upper class:

    UeClient::UeClient(QObject *parent,
                       UeSettings* const settings)
        : QObject(parent)
    {
        qRegisterMetaType<UePosCommProtocolArch::UeCommand>("UePosCommProtocolArch::UeCommand");
    
        QThreadPool::globalInstance()->setMaxThreadCount(10);
    
        this->ueSetSettings(settings);
    }   // constructor
    

    and now it works!