PDA

View Full Version : Updating QTreeView with custom model



supergillis
17th September 2008, 11:43
I really need some help updating my QTreeView. I have been looking all over the forum for solutions but I couldn't find any that worked...

This is the code I got:

PlaylistModel* plm = NULL;

MainWindow::MainWindow()
{
setupUi(this);
plm = new PlaylistModel(this);
treeView->setModel(plm);
}

extern Playlist* currentPlaylist;

QVariant PlaylistModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
return QVariant();
if(index.row() >= currentPlaylist->size())
return QVariant();
if(role == Qt::DisplayRole)
{
Song* song = currentPlaylist->at(index.row());
if(song)
{
std::cout << "Song found!" << std::endl;
if(song->info)
{
std::cout << "Info found!" << std::endl;
if(index.column() == 0)
return "Title";
else if(index.column() == 1)
return "Artist";
}
}
return "N/A";
}
else
return QVariant();
}

QVariant PlaylistModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if(role != Qt::DisplayRole)
return QVariant();
if(orientation == Qt::Horizontal)
return QString("Column %1").arg(section);
else
return QString("Row %1").arg(section);
}

int PlaylistModel::rowCount(const QModelIndex &parent) const
{
return currentPlaylist->size();
}

int PlaylistModel::columnCount(const QModelIndex &parent) const
{
return 2;
}

void PlaylistModel::update()
{
QModelIndex topLeft = createIndex(0, 0);
QModelIndex bottomRight = createIndex(currentPlaylist->size()-1, 1);
dataChanged(topLeft, bottomRight);
}

As you can see, the data is stored in currentPlaylist (the Playlist class is just a QList). But when I add data to the currentPlaylist, it doesn't show it on the treeView... But when I add data to the currentPlaylist before I construct the tableView and model, it does show the data!

So I have tried to make an update function. But that doesn't work either...

Thanks in advance,
Gillis

caduel
17th September 2008, 11:50
You are aware that you have to wrap adding rows in calls to
QAbstractItemModel::beginInsertRows(),
QAbstractItemModel::endInsertRows()?

otherwise, your model('s base class) does not know its underlying data got added to and it can not tell the view about it.

supergillis
17th September 2008, 12:45
What must I do then when importing files?
I got this now:

void GMainWindow::addFiles()
{
QFileDialog dialog(this, "Import Music File", "", "MP3 Files (*.mp3)");
dialog.setFileMode(QFileDialog::ExistingFiles);
if(dialog.exec())
{
QStringList fileNames = dialog.selectedFiles();
for(int i = 0; i < fileNames.size(); ++i)
{
GFileInfo* fileInfo = new GFileInfo(fileNames.at(i));
Song* song = new Song();
song->info = fileInfo;
currentPlaylist->append(song);
}
/*PlaylistModel* model = (PlaylistModel*)treeView->model();
model->update();*/
}
}
Should I add model->beginInsertRows(); at the beginning of the function and model->endInsertRows(); at the end?

caduel
17th September 2008, 13:02
Add a method append to your model, and call the model's append method!
(Never modify the underlying data except through the model, otherwise the model won't know about it and views can't get updated.)


PlayListModel::append(Song *song)
{
beginInsertRows(QModeIndex(), rowCount(), rowCount());
currentPlaylist->append(song);
endInsertRows();
}

call this method in your addFiles()

HTH

supergillis
17th September 2008, 13:11
That works! But I still find it a bit weird... There should be a function or something to notify the model, that would be alot easier :)

Thanks!

caduel
17th September 2008, 13:26
Well, if class X has all the possibilities to inform a model M about the relevant changes, then that class X already is (has to be) a model and M is a mere proxy (model).

(I have a list class I wrote before Qt introduced the model/view concept that I used as my own model before. I have written an adapter to plug that into a Qt-model. No need to do so when you start from scratch, though.)

supergillis
18th September 2008, 00:21
And if I want to sort the tree on 'Artist' for example, and I want to do it by sorting the currentPlaylist and then updating the view instead of sorting the model?

aamer4yu
18th September 2008, 06:42
You dont have to sort the actual model. You can use a proxy model.
Have a look at QSortFilterProxyModel . And also the examples in Qt Demo

caduel
18th September 2008, 08:01
I second that you should use QSortFilterProxyModel here. It's easier (otherwhise you have to connect the QHeaderView with some custom slot etc...), with QSortFilterProxyModel all you need is there.

If you should, however, really sort your model's underlying data, you have to tell the model about it: subclass it, make reset() public and call it.