Qt connect - объект излучает сигнал до того, как будет выдано соединение

У меня есть следующие main.cpp:

#include <QtQml>
#include <QApplication>
#include <QQmlApplicationEngine>

#include "database/uepeoplemodel.h"
#include "core/uestatus.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    UeStatus* ueApplicationStatus=new UeStatus(qApp);
    UePeopleModel* uePeopleModel=new UePeopleModel(qApp);

    QObject::connect(uePeopleModel,
                     SIGNAL(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)),
                     ueApplicationStatus,
                     SLOT(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)));

    engine.rootContext()->setContextProperty("uePeopleModel",
                                             uePeopleModel);
    engine.rootContext()->setContextProperty("ueApplicationStatus",
                                             ueApplicationStatus);
    engine.addImageProvider(QLatin1String("uePeopleModel"),
                            uePeopleModel);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

Теперь внутри main.cpp я создаю два объекта из классов:

UeStatus* ueApplicationStatus=new UeStatus(qApp);
UePeopleModel* uePeopleModel=new UePeopleModel(qApp);

и я подключаю сигнал от UePeopleModel к слоту в ueApplicationStatus:

QObject::connect(uePeopleModel,
    SIGNAL(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)), 
    ueApplicationStatus,
    SLOT(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)));

Проблема в том, что при создании uePeopleModel сигнал передается внутри конструктора:

UePeopleModel::UePeopleModel(QObject* parent)
    : QSqlQueryModel(parent),
      QQuickImageProvider(QQmlImageProviderBase::Image,
                          QQmlImageProviderBase::ForceAsynchronousImageLoading)
{
    if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
                                                 Qt::CaseInsensitive))
    {
        this->ueSetDatabase(QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
                                                      UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE));
    }   // if

    this->ueDatabase().setHostName(/*this->uePosSettings()->ueDbHostname()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
    this->ueDatabase().setDatabaseName(/*this->uePosSettings()->ueDbName()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
    this->ueDatabase().setUserName(/*this->uePosSettings()->ueDbUser()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
    this->ueDatabase().setPassword(/*this->uePosSettings()->ueDbPassword()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);

    if(this->ueDatabase().open())
    {
        emit this->ueSignalDatabaseConnectionChanged(CONNECTED);
        this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
                       this->ueDatabase());
/*
        if(this->lastError().isValid())
            qDebug() << this->lastError();
*/
    }
    else
    {
        emit this->ueSignalDatabaseConnectionChanged(NOT_CONNECTED);
//        qDebug() << this->ueDatabase().lastError();
    }

//    qDebug() << this->ueDatabase().connectionNames();
}   // default constructor

до того, как выдается connect, и поэтому ueApplicationStatus объект не улавливается со слотом. Кто-нибудь знает, как избавиться от этой ситуации?


person KernelPanic    schedule 14.09.2015    source источник
comment
Проблема в том, что когда создается uePeopleModel, внутри конструктора выдается сигнал: Ну, не делайте этого! Серьезно, что за вопрос?   -  person Kuba hasn't forgotten Monica    schedule 14.09.2015


Ответы (2)


Вы не должны использовать конструктор для открытия соединения с базой данных.

Используйте конструктор только для создания экземпляров других классов, инициализации переменных, выделения памяти и так далее.

В вашем случае ваш конструктор должен использоваться для инициализации базы данных, но вы можете создать другой метод с помощью:

if(this->ueDatabase().open())
    {
        emit this->ueSignalDatabaseConnectionChanged(CONNECTED);
        this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
                       this->ueDatabase());
    }
    else
    {
        emit this->ueSignalDatabaseConnectionChanged(NOT_CONNECTED);
}

Этот метод будет вызываться после connect в вашем main.cpp.

person Tarod    schedule 14.09.2015

Я решил проблему, добавив метод void ueConnectToDatabase() и переместив в него содержимое конструктора и переопределив main.cpp как:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    UeStatus* ueApplicationStatus=new UeStatus(qApp);
    UePeopleModel* uePeopleModel=new UePeopleModel(qApp);

    QObject::connect(uePeopleModel,
                     SIGNAL(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)),
                     ueApplicationStatus,
                     SLOT(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)));

    uePeopleModel->ueConnectToDatabase();

    engine.rootContext()->setContextProperty("uePeopleModel",
                                             uePeopleModel);
    engine.rootContext()->setContextProperty("ueApplicationStatus",
                                             ueApplicationStatus);
    engine.addImageProvider(QLatin1String("uePeopleModel"),
                            uePeopleModel);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

Теперь объект создан, сигнал и слот подключены и ПОСЛЕ этого происходит подключение к базе данных.

person KernelPanic    schedule 14.09.2015
comment
Хе-хе-хе, то же самое решение, которое я предложил :) Удивительно;) - person Tarod; 14.09.2015
comment
@Tarod все равно спасибо! Сегодня я не думаю на 100% возможностей. Я должен был запомнить решение, не задавая вопрос :). - person KernelPanic; 14.09.2015