PDA

View Full Version : QFileSystemModel and custom column / data



ArnSpin
18th February 2015, 17:20
Hi everybody

I am trying to create a little treeview based on a QFileSystem. The folders will be selected to perform several analysis with the files inside.
I would like to provide more information in the treeview columns such as the number of files in the subfolder, some values extracted from path name etc.

I spent several hours on google, this forum and others Qt resources and I still have difficulties to understand how it works.
I found different solutions. The one I investigated is to create a subclass of the QFileSystemModel class and overwriting flags, data, setdata methods.
I succeed to did it with this very basic code:



TreeModel::TreeModel(const QString &path, const QStringList &headers, const MainAnalysis &data, QObject *parent)
: QFileSystemModel(parent)
{
this->setReadOnly(true);
this->setFilter(QDir::Dirs| QDir::NoDotAndDotDot);
this->setRootPath(path);
headerList = headers;

}



int TreeModel::columnCount(const QModelIndex& parent = QModelIndex()) const
{
int sup;
sup = headerList.size()-QFileSystemModel::columnCount();

return QFileSystemModel::columnCount();//+sup;
}



QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
for(uint i = 0; i<headerList.size(); i++){
if (section == i && orientation == Qt::Horizontal && role == Qt::DisplayRole)
return headerList.at(i);
}
return QFileSystemModel::headerData(section, orientation, role);
}


QVariant TreeModel::data(const QModelIndex& index,int role) const
{

QString test;
qDebug() << "index: " << index << "role: " << role;
if(!index.isValid()){
return QFileSystemModel::data(index,role);}
if(index.column()==0){
if (role == Qt::CheckStateRole) return checklist.contains(index) ? Qt::Checked : Qt::Unchecked;
}
if(index.column()== 2)
{
switch(role)
{
case(Qt::DisplayRole):
{return QString("Your text");}
case(Qt::TextAlignmentRole):
{return Qt::AlignHCenter;}
default:{}
}
}


return QFileSystemModel::data(index,role);
}


Qt::ItemFlags TreeModel::flags(const QModelIndex& index) const {
return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable;

}


bool TreeModel::setData(const QModelIndex& index, const QVariant& value, int role) {
if (role == Qt::CheckStateRole) {
if (value == Qt::Checked) checklist.insert(index);
else checklist.remove(index);
emit dataChanged(index, index);
return true;
}
return QFileSystemModel::setData(index, value, role);
}

Parts of these codes are extracted from different wokrs found on forums... may be here.
I understood how to create a column (done in headerData and columnCount...
I understood -- partially-- how to add a checkbox (done in data) and handle if it is checked or not in setData

But I don't understand how to modify item and index values... Is there a clever person to explain how to do that with in a newbie language ?

With these functions, How I can add in the column 2 (for example) the number of subdirectories of the item ?
How I can add the results of the operation on the item path name (a double) ?

Thanks a lot ;)

d_stranz
18th February 2015, 18:37
But I don't understand how to modify item and index values.

I don't know what you mean by this. Explain what you are trying to accomplish where you think you must "modify item and index values".

There are two ways to do what you want. First is to derive from your base model (as you have done). The second is to create a proxy model that adds to what the source model provides. I personally prefer to use a proxy rather than derive from the source model. In either case though, you have to pay careful attention to parent-child relationships with model indexes. For selection to work properly, you also have to make sure that mapToSource() and mapFromSource() are correct.

anda_skoa
19th February 2015, 09:59
The easiest way is most likely to have your columns after the ones from the file system model.
So you can always delegate all requests for column < baseColumnCount to the base class and only handle those above yourself.

Cheers,
_

ArnSpin
19th February 2015, 11:29
I don't know what you mean by this. Explain what you are trying to accomplish where you think you must "modify item and index values".

There are two ways to do what you want. First is to derive from your base model (as you have done). The second is to create a proxy model that adds to what the source model provides. I personally prefer to use a proxy rather than derive from the source model. In either case though, you have to pay careful attention to parent-child relationships with model indexes. For selection to work properly, you also have to make sure that mapToSource() and mapFromSource() are correct.



My apologies, I probably use wrong terms.

I understood that a Treeview is composed by item, each items is characterized by a row, column.
When I use the word index, I just want to say a folder or a file in the QFileSystemModel. It could be an "item" in any other environment but it is not the case in Qt so I used "index" to explain my problem. I will do some research on proxy model.


The easiest way is most likely to have your columns after the ones from the file system model.
So you can always delegate all requests for column < baseColumnCount to the base class and only handle those above yourself.

Would you have a short example. I am not sure to understand clearly how to use delegate here.


Thanks for your helps guys :)

anda_skoa
2nd March 2015, 13:07
Would you have a short example. I am not sure to understand clearly how to use delegate here.

Not a delegate in the model/view concept's sense, but delegating the call.

Something like:


int MyModel::columnCount(const QModelIndex &index) const
{
return QFileSystemModel::columnCount(index) + 2; // two additional columns.
}

QVariant data(const QModelIndex &index, int role) const
{
if (index.column() >= QFileSystemModel::columnCount(index)) {
// handle custom columns
} else {
return QFileSystemModel::data(index, role);
}
}


Cheers,
_