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. QModelIndex is invalid in QTreeView based on Qt SimpleTreeModel example (source code pasted)

QModelIndex is invalid in QTreeView based on Qt SimpleTreeModel example (source code pasted)

Scheduled Pinned Locked Moved Solved General and Desktop
qmodeindex qtreqmodelindexqtreeviewinternalpointersimpletreemodel
3 Posts 1 Posters 2.1k 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.
  • Q Offline
    Q Offline
    qt_fan_4k
    wrote on 10 Jan 2016, 07:09 last edited by qt_fan_4k 1 Oct 2016, 08:08
    #1

    I'm creating a file browser based on the Qt4.8 example SimpleTree
    And I rewrote my own setUpModelData as shown in the function FileTreeModel::setupModelData below (totally less than 60 lines)

    Basically, the argument root contains the user-specified root path, like "D:\qt_project\prj1", and setUpModelData will create a tree model from the real root directory D:\ to this user-specified path, with all sibling items added.

    The problem is, whenever I expanded any directory under D:, I got a segment fault.
    With all the addresses dumped, I could see that the childItem in the function TreeModel::parent is none of the dumped address, i.e., such childItem retrieved from index.internalPointer is invalid.

    How come internalPointer returns an invalid TreeItem pointer ?

    QModelIndex TreeModel::parent(const QModelIndex &index) const
    {
        if (!index.isValid())
            return QModelIndex();
    
        TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
        TreeItem *parentItem = childItem->parent();
    
        if (parentItem == rootItem)
            return QModelIndex();
    
        return createIndex(parentItem->row(), 0, parentItem);
    }
    
    QModelIndex FileTreeModel::setupModelData(TreeItem *root) {
        QFileInfo fi_root = QFileInfo(root->data().toString());
        TreeItem *activeItem = root;    // always points to the current child
        QDir it_dir = fi_root.dir();    // check with the locating dir
        QList<TreeItem *> lstParents;     // to calculate the model index
        bool rootDirNotMet = true;
        do {
            TreeItem *startItem = new TreeItem(it_dir.dirName());      // create the father node
            startItem->setData(QVariant(it_dir.path()));
            startItem->setIcon(QIcon(":/images/parent"));
            lstParents.append(activeItem);
            QString addr; addr.setNum((long)(void *)activeItem, 16);
            qDebug() << (activeItem->data().toString() + " @@ " + addr);    // dump all address for each path
            this->listSubDir(it_dir, startItem, activeItem);
            activeItem = startItem;
            if (!rootDirNotMet) break;   // ensure the root dir is also processed when cdUp failed
            rootDirNotMet = it_dir.cdUp();
        }  while(1);
        qDebug() << it_dir.absolutePath();
        activeItem->setParent(rootItem);             // setParent sets parentItem in the TreeItem
        activeItem->setText(it_dir.absolutePath());
        rootItem->appendChild(activeItem);
        QModelIndex itemIndex = QModelIndex(); // index(0, 0, QModelIndex());        // calculate from root index
        do {
            itemIndex = this->index(lstParents.takeLast()->row(), 0, itemIndex);
        } while (!lstParents.isEmpty());
        return itemIndex;   // return the index of the user-specified root
    }   // setupModelData
    
    void FileTreeModel::listSubDir(QDir &dir, TreeItem *parent, TreeItem *registered_child = 0) {
        if (parent->childCount() > 1) return;       // this dir has already been listed
        if (parent->hasChildren() && parent->child(0)->text().compare("")) return;  // the only child is not dummy
        QDirIterator it(dir.path(), QDirIterator::NoIteratorFlags);      // check this parent node
        while (it.hasNext()) {      // check each child
            QString full_path;
            QFileInfo fi = QFileInfo(full_path = it.next());
            if (!fi.fileName().compare(".") || !fi.fileName().compare("..")) continue;        // ignore "." and ".."
            TreeItem *siblingItem;
            if (registered_child && registered_child->data().toString() == full_path) {     // this is registered child
                siblingItem = registered_child;
                parent->appendChild(siblingItem);
            } else if (parent->childCount() == 1 && parent->child(0)->text().compare("") == 0) { // can reuse the dummy item
                siblingItem = parent->child(0);
                siblingItem->setText(fi.fileName());
            } else {    // need a new node for the item
                siblingItem = new TreeItem(fi.fileName());
                parent->appendChild(siblingItem);
            }   // else for a new node
            if (fi.isDir()) {  // is directory
                siblingItem->setIcon(QIcon(":/images/parent"));
                TreeItem *dummyItem = new TreeItem("");     // dummy child to mark the folder to expand
                siblingItem->appendChild(dummyItem);
            } else {    // a file
                siblingItem->setIcon(QIcon(":/images/child"));
            } // else of if dir
            siblingItem->setData(full_path);
            siblingItem->setParent(parent);
            QString addr; addr.setNum((long)(void *)siblingItem, 16);
            qDebug() << (siblingItem->data().toString() + " ## " + addr);    // dump all address for each found child
        }   // while it.hasNext
    }   // listSubDir
    
    Q 1 Reply Last reply 10 Jan 2016, 08:10
    0
    • Q qt_fan_4k
      10 Jan 2016, 07:09

      I'm creating a file browser based on the Qt4.8 example SimpleTree
      And I rewrote my own setUpModelData as shown in the function FileTreeModel::setupModelData below (totally less than 60 lines)

      Basically, the argument root contains the user-specified root path, like "D:\qt_project\prj1", and setUpModelData will create a tree model from the real root directory D:\ to this user-specified path, with all sibling items added.

      The problem is, whenever I expanded any directory under D:, I got a segment fault.
      With all the addresses dumped, I could see that the childItem in the function TreeModel::parent is none of the dumped address, i.e., such childItem retrieved from index.internalPointer is invalid.

      How come internalPointer returns an invalid TreeItem pointer ?

      QModelIndex TreeModel::parent(const QModelIndex &index) const
      {
          if (!index.isValid())
              return QModelIndex();
      
          TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
          TreeItem *parentItem = childItem->parent();
      
          if (parentItem == rootItem)
              return QModelIndex();
      
          return createIndex(parentItem->row(), 0, parentItem);
      }
      
      QModelIndex FileTreeModel::setupModelData(TreeItem *root) {
          QFileInfo fi_root = QFileInfo(root->data().toString());
          TreeItem *activeItem = root;    // always points to the current child
          QDir it_dir = fi_root.dir();    // check with the locating dir
          QList<TreeItem *> lstParents;     // to calculate the model index
          bool rootDirNotMet = true;
          do {
              TreeItem *startItem = new TreeItem(it_dir.dirName());      // create the father node
              startItem->setData(QVariant(it_dir.path()));
              startItem->setIcon(QIcon(":/images/parent"));
              lstParents.append(activeItem);
              QString addr; addr.setNum((long)(void *)activeItem, 16);
              qDebug() << (activeItem->data().toString() + " @@ " + addr);    // dump all address for each path
              this->listSubDir(it_dir, startItem, activeItem);
              activeItem = startItem;
              if (!rootDirNotMet) break;   // ensure the root dir is also processed when cdUp failed
              rootDirNotMet = it_dir.cdUp();
          }  while(1);
          qDebug() << it_dir.absolutePath();
          activeItem->setParent(rootItem);             // setParent sets parentItem in the TreeItem
          activeItem->setText(it_dir.absolutePath());
          rootItem->appendChild(activeItem);
          QModelIndex itemIndex = QModelIndex(); // index(0, 0, QModelIndex());        // calculate from root index
          do {
              itemIndex = this->index(lstParents.takeLast()->row(), 0, itemIndex);
          } while (!lstParents.isEmpty());
          return itemIndex;   // return the index of the user-specified root
      }   // setupModelData
      
      void FileTreeModel::listSubDir(QDir &dir, TreeItem *parent, TreeItem *registered_child = 0) {
          if (parent->childCount() > 1) return;       // this dir has already been listed
          if (parent->hasChildren() && parent->child(0)->text().compare("")) return;  // the only child is not dummy
          QDirIterator it(dir.path(), QDirIterator::NoIteratorFlags);      // check this parent node
          while (it.hasNext()) {      // check each child
              QString full_path;
              QFileInfo fi = QFileInfo(full_path = it.next());
              if (!fi.fileName().compare(".") || !fi.fileName().compare("..")) continue;        // ignore "." and ".."
              TreeItem *siblingItem;
              if (registered_child && registered_child->data().toString() == full_path) {     // this is registered child
                  siblingItem = registered_child;
                  parent->appendChild(siblingItem);
              } else if (parent->childCount() == 1 && parent->child(0)->text().compare("") == 0) { // can reuse the dummy item
                  siblingItem = parent->child(0);
                  siblingItem->setText(fi.fileName());
              } else {    // need a new node for the item
                  siblingItem = new TreeItem(fi.fileName());
                  parent->appendChild(siblingItem);
              }   // else for a new node
              if (fi.isDir()) {  // is directory
                  siblingItem->setIcon(QIcon(":/images/parent"));
                  TreeItem *dummyItem = new TreeItem("");     // dummy child to mark the folder to expand
                  siblingItem->appendChild(dummyItem);
              } else {    // a file
                  siblingItem->setIcon(QIcon(":/images/child"));
              } // else of if dir
              siblingItem->setData(full_path);
              siblingItem->setParent(parent);
              QString addr; addr.setNum((long)(void *)siblingItem, 16);
              qDebug() << (siblingItem->data().toString() + " ## " + addr);    // dump all address for each found child
          }   // while it.hasNext
      }   // listSubDir
      
      Q Offline
      Q Offline
      qt_fan_4k
      wrote on 10 Jan 2016, 08:10 last edited by
      #2

      The reason that I added dummy child is to make all directories expandable, a lazy expansion.

      1 Reply Last reply
      0
      • Q Offline
        Q Offline
        qt_fan_4k
        wrote on 10 Jan 2016, 09:30 last edited by
        #3

        The dummy child is the culprit. It did not set the parent so the parent is invalid.

        1 Reply Last reply
        0

        1/3

        10 Jan 2016, 07:09

        • Login

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