Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Grouping items in QTreeView using a separator

Grouping items in QTreeView using a separator

Scheduled Pinned Locked Moved Solved General and Desktop
3 Posts 2 Posters 1.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • JansiJ Offline
    JansiJ Offline
    Jansi
    wrote on last edited by
    #1

    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);
    
    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #2
      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);
      

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      3
      • JansiJ Offline
        JansiJ Offline
        Jansi
        wrote on last edited by
        #3

        Perfect. Thank you.

        1 Reply Last reply
        0

        • Login

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved