2

そのため、この問題について以前の質問を閲覧していましたが、コードの解決策が見つかりませんでした。

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);
}

コードの一部はここにあります。残りは正常に動作するため、ここのどこかにあるはずです。

この問題は、ダイアログを使用してユーザーがリストから int を選択できるようにした後に現れました。

以下は、このために作成したダイアログを呼び出す関数です。コード形式については申し訳ありませんが、動作後にクリーンアップします

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();
}
4

1 に答える 1

2

先に進む前に、一部のコードでSQL インジェクションが許可されています。セキュリティ ホールではない場合でも、バグが発生する可能性があります。SQL クエリで文字列置換を使用する代わりに、バインディングを使用する必要があります。

あなたの問題はここにあります:

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

これexec()はブロック機能です。ダイアログが閉じられるまでメイン イベント ループをブロックします。したがって、スレッド化されたネットワーク アクセス マネージャーからのシグナルがオブジェクトに配信されることはありません。

次のように、ダイアログ ボックスを非同期で表示する必要があります。

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

型名が小文字で始まり、変数名が大文字で始まると誤解を招くことに注意してください。Qt の規約は逆であり、特に理由がない限り、そのままにしておくと便利です。

SQL クエリでの DO パラメータのバインド

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

してはいけないこと SQL クエリでの文字列置換

setQuery(QString("SELECT ... WHERE tm.TypeID=%1 ").arg(typeId));
于 2013-09-05T19:34:43.740 に答える