PDA

View Full Version : Why object on the heap for QStandardItemModel?



arcull
19th August 2015, 08:14
Hi all.
I'm trying to populate a QTableView with some data. Here is a working snippet:


void MainWindow::FillData() {
qDebug() << "will try to fill some data now";
stdModel = new QStandardItemModel();
stdModel->setHorizontalHeaderItem(0,new QStandardItem(QString("Col1")));
stdModel->setHorizontalHeaderItem(1,new QStandardItem(QString("Col2")));
stdModel->setHorizontalHeaderItem(2,new QStandardItem(QString("Col3")));

for (int i=0;i<5;i++) {

QList<QStandardItem*>newRow;

QStandardItem *stItem1 = new QStandardItem("A" + QString::number(i));
newRow.append(stItem1);

QStandardItem *stItem2 = new QStandardItem("B" + QString::number(i));
newRow.append(stItem2);

QStandardItem *stItem3 = new QStandardItem("C" + QString::number(i));
newRow.append(stItem3);

stdModel->appendRow(newRow);
}

ui->tableView->setModel(stdModel);
}


and here is a non working one (result is empty QTableView, but it has 5 rows and 3 columns):


void MainWindow::FillData() {
qDebug() << "will try to fill some data now";
stdModel = new QStandardItemModel();
stdModel->setHorizontalHeaderItem(0,new QStandardItem(QString("Col1")));
stdModel->setHorizontalHeaderItem(1,new QStandardItem(QString("Col2")));
stdModel->setHorizontalHeaderItem(2,new QStandardItem(QString("Col3")));

for (int i=0;i<5;i++) {

QList<QStandardItem*>newRow;

QStandardItem stItem1("A" + QString::number(i));
newRow.append(&stItem1);

QStandardItem stItem2("B" + QString::number(i));
newRow.append(&stItem2);

QStandardItem stItem3("C" + QString::number(i));
newRow.append(&stItem3);

stdModel->appendRow(newRow);
}

ui->tableView->setModel(stdModel);
}

So as title goes, why do I need to create QStandardItem on the heap. Why do I need this object after it was appended to QStandardModel? I just want to make clear this. Much thanks.

prasad_N
19th August 2015, 08:59
As simple as All the stack items will get deleted when you come out of for loop & model is trying ti get data from items but there is no items.

arcull
19th August 2015, 09:57
As simple as All the stack items will get deleted when you come out of for loop & model is trying ti get data from items but there is no items. I know, but why do I need them ( I mean QStandardItems), I've added what I want to QStandardItemModel, which is still in scope and on the heap.

prasad_N
19th August 2015, 10:04
but model do not hold a data, model will take data (while displaying) from items which are invalid.

arcull
19th August 2015, 10:14
but model do not hold a data, model will take data (while displaying) from items which are invalid.
Yes you're right. But how do I make sure I don't cause a memory leak in this case. How would you do it, or better what is good practice in general in this case?

prasad_N
19th August 2015, 11:12
You no need to take care of items, model will delete all its items when model gets deleted. all we need to do is just delete model.

something like this: observe destructor will be called for all the heap items

you can remove sItem class, I just put it to show you there is no memory leak.


#include "mainwindow.h"
#include <QApplication>
#include <QStandardItemModel>
#include <QTableView>

#include <QDebug>

class sItem : public QStandardItem
{
public:
sItem ( const QString & text = QString() ) : QStandardItem(text)
{
qDebug() << "Const";
}
~sItem()
{
qDebug() << "Dest";
}
};

QStandardItem *root;

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTableView* view = new QTableView();


QStandardItemModel* stdModel = new QStandardItemModel(view);
stdModel->setHorizontalHeaderItem(0,new sItem(QString("Col1")));

root = stdModel->invisibleRootItem();;

for (int i=0;i<5;i++) {
sItem *stItem1 = new sItem("A" + QString::number(i));
root->appendRow(stItem1);
}

view->setModel(stdModel);
//view->show();

delete view;

return a.exec();
}

ChrisW67
19th August 2015, 11:14
The QStandardItems added to the QStandardItemModel are owned by the model and deleted when it is destroyed. See QStandardItemModel::setItem(). You can reclaim ownership of the items with the QStandardItemModel::take* methods;

arcull
19th August 2015, 11:27
all we need to do is just delete model does deleting QTableView delete the QStandardModel it was assinged?

anda_skoa
19th August 2015, 12:04
No, because a model can be used by more than one view.

Cheers,
_

arcull
19th August 2015, 12:32
No, because a model can be used by more than one view.

Cheers,
_
Hmmm. I create QStandardItem and append it to QStandardModel. By the same analogy I create QTableView and append QStandardModel to it. But deleting QStandardModel deletes his QStandardItems, while deleting QTableView doesn't delete QStandardModel. Please explaing logic behind this, or how can I know in which cases deleting "parent" object will delete "child" object, much thanks.

prasad_N
19th August 2015, 12:59
QTableView* view = new QTableView();
QStandardItemModel* stdModel = new QStandardItemModel(view);


I set view as parent to the model that is why model also getting deleted when i delete view.
(when you delete an object in qt, all it's child also will get deleted automatically, for more info check qt memory management in google).

if you create model with out parent,(like this: QStandardItemModel* stdModel = new QStandardItemModel(view);) you need to delete the model explicitly (delete stdModel) so that it will delete all its items.

anda_skoa
19th August 2015, 13:06
Hmmm. I create QStandardItem and append it to QStandardModel.

Yes



By the same analogy I create QTableView and append QStandardModel to it.

You tell the view which model to ask for data.



QStandardModel deletes his QStandardItems

Yes, it owns the items.



while deleting QTableView doesn't delete QStandardModel

Yes, it doesn't own it.



Please explaing logic behind this, or how can I know in which cases deleting "parent" object will delete "child" object, much thanks.

In the case of QStandardItemModel you could indeed consider the model to be parent of the items.
You know that it deletes its items because its documentation says so.

A view does not own a model, it also does not have any parent/child relationship with the model.
Since a model can be used by multiple views, none of these views can assume it is the only one and delete the model on its own destruction.
If you, as the application developer, know that a certain model/view pair is stand-alone, you can just pass the view as the model's parent and let the QObject parent/child handling delete the model upon view deletion.

Cheers,
_

arcull
19th August 2015, 13:12
A view does not own a model, it also does not have any parent/child relationship with the model.
No but a model can "get" a parent, when creating it, that's why the deltion of table deletes the model as well. I guess prasad_N is right on this one. Thanks both. I think I got the point.

anda_skoa
19th August 2015, 13:24
No but a model can "get" a parent, when creating it, that's why the deltion of table deletes the model as well.

QAbstractItemModel is a QObject derived class, so yes, it can have a parent that deletes it as its child.
That parent can be a view.

Also wrote that already in my previous comment, last sentence.

Cheers,
_

arcull
19th August 2015, 13:29
Also wrote that already in my previous comment, last sentence.
I've overlooked that, sorry.