0

I'm a beginner at Qt and I'm struggling to populate a QStandardItemModel from an XML file.

I've tried the following and the entire project runs successfully but the QtableView does not display the data.

Here is my main.cpp:

void readXml(const QString& fileName) {
    QFile file(fileName);
    if(!file.open(QFile::ReadOnly | QFile::Text)) {
        qDebug() << "Cannot read file" << file.errorString();
        return;
    }

    StockItems* stockitems = new StockItems;
    XmlStockItemsReader xmlReader(stockitems);

    if(!xmlReader.read(&file))
        qDebug() << "Parse error in file " << xmlReader.errorString();
    else {
        stockitems->print();
        stockitems->populateStockModel();
    }
}

int main(int argc, char* argv[]) {
    QApplication app(argc, argv);
    StockItems si;

    //! Change this to match the path of your project
    QString path = "C:\\unisa\\cos3711\\FIConcession";
    readXml(path + "\\stockitems.xml");

    si.show();

    return app.exec();
}

In stockitems.cpp I have the following function:

void StockItems::populateStockModel() {
    foreach(Item* item, m_items) {
        QList<QStandardItem*> newRow;

        QStandardItem *stockID = new QStandardItem(QString("%1").arg(item->stockID()));
        QStandardItem *desc = new QStandardItem(QString("%2").arg(item->desc()));
        QStandardItem *price = new QStandardItem(QString("%3").arg(item->price()));

        newRow.append(stockID);
        newRow.append(desc);
        newRow.append(price);

        stockModel->appendRow(newRow);
    }
}

If I do some debugging I can see that the stockID, desc and prices are correctly read, so the problem must lie somewhere with updating the stockModel.

My main StockItems Constructor is as follows:

StockItems::StockItems(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::StockItems)
{
    ui->setupUi(this);
    stockModel = new QStandardItemModel(0, 3);

    // Set Model Headers
    stockModel->setHeaderData(0, Qt::Horizontal, "Stock ID", Qt::DisplayRole);
    stockModel->setHeaderData(1, Qt::Horizontal, "Description", Qt::DisplayRole);
    stockModel->setHeaderData(2, Qt::Horizontal, "Price", Qt::DisplayRole);

    // Link Model to Table View
    ui->tvStock->setModel(stockModel);
}

I have an add button which contains the following onclick code which works as expected so I'm just not sure if I'm referencing the stockModel correctly.

QList<QStandardItem*> newRow;

QStandardItem* stockID = new QStandardItem(QString("%1").arg(ui->tbStockId->text()));
QStandardItem* desc = new QStandardItem(QString("%2").arg(ui->tbDesc->text()));
QStandardItem* price = new QStandardItem(QString("%3").arg(ui->sbPrice->text()));

newRow.append(stockID);
newRow.append(desc);
newRow.append(price);

stockModel->appendRow(newRow);

Finally I think this might help, my stockitems.h file:

class StockItems : public QDialog
{
    Q_OBJECT

public:
    explicit StockItems(QWidget *parent = 0);
    ~StockItems();
    void populateStockModel();
    void addItem(Item* item);
    void print() const;

private slots:
    void on_btnAdd_clicked();
    void on_btnDelete_clicked();

private:
    Ui::StockItems *ui;
    QStandardItemModel *stockModel;
    QList<Item*> m_items;
};

This is a lot and please let me know if I should provide anything else but I'm really lost as to how to populate this model correctly.

Thanks for any guidance!

Barry Michael Doyle
  • 9,333
  • 30
  • 83
  • 143
  • As far as I see, this looks correct. I'd suggest writing a debug function to dump the contents of the model after you've populated it. Make sure the column and row counts are as expected and the text of each item. The problem might be in your table view setup, although that also looks OK. – goug Feb 13 '17 at 19:51
  • I think the problem may be in the StockItems constructor where I say `stockModel = new QStandardItemModel(0, 3);` but whenever I change this it breaks... Not sure what to do :/ – Barry Michael Doyle Feb 13 '17 at 20:05
  • I see the answer has been added. That answer is correct, and I missed that when I was reading the code. – goug Feb 13 '17 at 23:38

1 Answers1

1

Your readXml function does not populate the StockItems instance that you create in your main function, but a completely new StockItems instance that isn't used anywhere.

For example, instead of

StockItems* stockitems = new StockItems;

in your readXml function, let readXml take another StockItems argument, and use that:

void readXml(const QString& fileName, StockItems *stockItems) {
    // do everything here as before, except for the
    // StockItems* stockitems = new StockItems;
    ...
}

int main(int argc, char* argv[]) {
    ...
    readXml(path + "\\stockitems.xml", &si);
    si.show();
    ...
}
E4z9
  • 1,713
  • 9
  • 11