chilly83
chilly83

Reputation: 25

QNetworkAccessManager not emitting finished signal with this code

so i have been browsing the previous questions before about this issue, but i could not find a solution for my code.

cpp file of dialog
------------------------------------------------
#include "everesult.h"
#include "ui_everesult.h"

everesult::everesult(QWidget *parent) :
    QDialog(parent),
    ui1(new Ui::everesult)
{
    ui1->setupUi(this);
}

everesult::~everesult()
{
    delete ui1;
}

void everesult::setmodel(QStandardItemModel *model)
{
    ui1->listView->setModel(model);
}

void everesult::on_buttonBox_clicked(QAbstractButton *button)
{
    EveReprocess M_;
    QModelIndex Selectedindex = ui1->listView->currentIndex();
    QModelIndex StationIdsindex = ui1->listView->model()->index(0, 1);

    int typeID = 0;
    int stationID = 0;
    stationID = ui1->listView->model()->data(StationIdsindex, Qt::DisplayRole).toInt();
    typeID = ui1->listView->model()->data(Selectedindex, Qt::DisplayRole).toInt();
    M_.GetMaterials(typeID, stationID);
}
--------------------------------------------------
Getmaterial and replyFinished from main window.
--------------------------------------------------

void EveReprocess::GetMaterials(int typeId, int stationid)
{
    //get typeid from material list
    this->modelMaterial = new QSqlQueryModel();
    modelMaterial->setQuery(QString("SELECT tm.quantity, tm.materialTypeID, t.typeName FROM invTypeMaterials tm INNER JOIN invTypes t ON t.TypeID = tm.materialTypeId WHERE tm.TypeID=%1 ").arg(typeId));
    if (!modelMaterial->query().exec())
        qDebug() << modelMaterial->query().lastError();

    //Set eve Central Url with typeids
    QUrl url = QUrl("http://api.eve-central.com/api/marketstat?");
    QUrlQuery q;
    int numRows = modelMaterial->rowCount();
    for (int row = 0; row < numRows; ++row)
    {
        QModelIndex index = modelMaterial->index(row, 1);
        q.addQueryItem( QString("typeid"), QString::number(modelMaterial->data(index, Qt::DisplayRole).toInt()));
    }
    q.addQueryItem( QString("usesystem"), QString::number(stationid));

    //set created url and connect
    url.setQuery(q);
    qDebug() << url;    
    manager = new QNetworkAccessManager(this);
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply *)));
    manager->get(QNetworkRequest(url) );
}

void EveReprocess::replyFinished(QNetworkReply *reply)
{
    qDebug() << "replyFinished called";
    if ( reply->error() != QNetworkReply::NoError ) {
        qDebug() << "Request failed, " << reply->errorString();
        emit replyFinished(false);
        return;
    }
    qDebug() << "Request succeeded";
    //process with xmlreader and get values
    processSearchResult( reply);
}

some of the code is here, i think it should be somewhere here, as the rest works fine.

this issue showed up after i use a dialog to let user pick a int from a list.

below is the function that calls the dialog that i have made for this. sorry about code format wil clean it up after it is working

void EveReprocess::Search_TypeId(QString ItemName, QString SystemName)
{    
    QList<int> TypeIdList;
    QList<int> StationIdList;
    modelIds = new QStandardItemModel(10,2,this);
    if !(db.isOpen()) return;

    this->queryItem = new QSqlQuery;
    queryItem->prepare("SELECT typeID FROM invTypes WHERE invTypes.typeName LIKE ? AND invTypes.groupID NOT IN (268,269,270)AND published= 1");
    ItemName.prepend("%");
    ItemName.append("%");
    queryItem->bindValue(0, ItemName);

    this->queryStation = new QSqlQuery;
    queryStation->prepare("SELECT solarSystemID FROM mapSolarSystems WHERE mapSolarSystems.solarSystemName LIKE ?");
    SystemName.prepend("%");
    SystemName.append("%");
    queryStation->bindValue(0, SystemName);

    if(!queryStation->exec() || !queryItem->exec() )
    {
        qDebug() << queryItem->lastError().text();
        qDebug() << queryItem->lastQuery();
        qDebug() << queryStation->lastError().text();
        qDebug() << queryStation->lastQuery();
    }

    while( queryStation->next())
    {
        StationIdList.append(queryStation->value(0).toInt());
    }

    while(queryItem->next())
    {
        TypeIdList.append(queryItem->value(0).toInt());
    }


    for (int i = 0; i < StationIdList.count(); ++i)
    {
        modelIds->setItem(i,1,new QStandardItem(QString::number(StationIdList.at(i))));
    }

    for (int i = 0; i < TypeIdList.count(); ++i)
    {
        modelIds->setItem(i,0,new QStandardItem(QString::number(TypeIdList.at(i))));
    }


    //
    everesult Dialog;
    Dialog.setmodel(modelIds);
    Dialog.exec();
}

Upvotes: 2

Views: 1018

Answers (1)

Before you proceed any further, some of your code is allows SQL injections. Even when it's not a security hole, it'll still lead to bugs. Instead of using string substitution in SQL queries, you should be using bindings.

Your problem is here:

everesult Dialog;
Dialog.setmodel(modelIds);
Dialog.exec();

The exec() is a blocking function - it blocks the main event loop until the dialog is dismissed. Thus the signals from the threaded network access manager never get delivered to your objects.

You should display the dialog box asynchronously, like so:

everesult * dialog = new everesult;
dialog->setModel(modelIds);
dialog->show();
connect(dialog, SIGNAL(accepted()), dialog, SLOT(deleteLater());
connect(dialog, SIGNAL(rejected()), dialog, SLOT(deleteLater());

Note that it's misleading to have type names starting with lower case and variable names starting with upper case. Qt's convention is the opposite, and it's useful to retain it unless you have a good reason to do otherwise.

DO Parameter Binding in SQL Queries

QSqlQuery query("SELECT .. WHERE tm.TypeID=:typeid");
query.bindValue(":typeid", typeId);
QSqlQueryModel model;
model.setQuery(query);

DON'T DO String Substitution in SQL Queries

setQuery(QString("SELECT ... WHERE tm.TypeID=%1 ").arg(typeId));

Upvotes: 2

Related Questions