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