Grouping items in QTreeView using a separator
Solved
General and Desktop
-
I am loading a list of strings into QTreeView and I want to group them into virtual folders like so:
text |_ english |_ game |_ pro_scen.msg |_ pro_quests.msg |_ ...
However, the code below results in all of the nested items being placed into the "example" folder instead of "text". Can you spot what I am doing wrong?
QStandardItemModel *model = new QStandardItemModel(); QVector<QString> entries({ {"text/english/game/pro_scen.msg"}, {"text/english/game/pro_wall.msg"}, {"text/english/game/proto.msg"}, {"text/english/game/quests.msg"}, {"example/english/game/pro_scen.msg"}, {"script.int"} }); model->setColumnCount(1); for(auto &entry : entries) { QStringList fileParts = entry.split("/"); QStandardItem *root; QStandardItem *child; for(int i = 0; i < fileParts.size(); i++) { child = new QStandardItem(fileParts[i]); // FIXME: this will exclude items with the same name that are in different directories QList<QStandardItem*> exists = model->findItems(fileParts[i], Qt::MatchExactly | Qt::MatchRecursive); if(exists.empty()) { // item does not exist if(i == 0) { // root item root = child; model->appendRow(root); } else { // child of some other item root->appendRow(child); root = child; } } else { // item is already there root = exists[0]; } } } ui->treeView->setModel(model);
-
void appendPath(QAbstractItemModel* const model, QStringList& fileParts, const QModelIndex& parent = QModelIndex()){ Q_ASSERT(model); if(fileParts.isEmpty()) return; if(model->columnCount(parent)<=0) model->insertColumn(0,parent); QModelIndex currIdx; const QString currLevel = fileParts.takeFirst(); const int rowCount = model->rowCount(parent); for(int i=0;i<rowCount;++i){ if(model->index(i,0,parent).data().toString().compare(currLevel)==0){ currIdx = model->index(i,0,parent); break; } } if(!currIdx.isValid()){ model->insertRow(rowCount,parent); currIdx=model->index(rowCount,0,parent); model->setData(currIdx,currLevel); } appendPath(model,fileParts,currIdx); }
then you can use it:
QStandardItemModel *model = new QStandardItemModel(this); //give a parent or you'll leak QVector<QString> entries({ {"text/english/game/pro_scen.msg"}, {"text/english/game/pro_wall.msg"}, {"text/english/game/proto.msg"}, {"text/english/game/quests.msg"}, {"example/english/game/pro_scen.msg"}, {"script.int"} }); for(const QString& entry : entries) { QStringList fileParts = entry.split("/"); appendPath(model,fileParts); } ui->treeView->setModel(model);