QModelIndexList BtTreeModel::allChildren(QModelIndex ndx) { QModelIndexList leafNodes; QList<BtTreeItem*> folders; int i; // Don't send an invalid index or something that isn't a folder if ( ! ndx.isValid() || type(ndx) != BtTreeItem::FOLDER ) return leafNodes; BtTreeItem* start = item(ndx); folders.append(start); while ( ! folders.isEmpty() ) { BtTreeItem* target = folders.takeFirst(); for (i=0; i < target->childCount(); ++i) { BtTreeItem* next = target->child(i); // If a folder, push it onto the folders stack for later processing if ( next->type() == BtTreeItem::FOLDER ) folders.append(next); else // Leafnode leafNodes.append(createIndex(i,0,next)); } } return leafNodes; }
QModelIndex BtTreeModel::createFolderTree( QStringList dirs, BtTreeItem* parent, QString pPath) { BtTreeItem* pItem = parent; // Start the loop. We are going to return ndx at the end, // so we need to declare and initialize outside of the loop QModelIndex ndx = createIndex(pItem->childCount(),0,pItem); // Need to call this because we are adding different things with different // column counts. Just using the rowsAboutToBeAdded throws ugly errors and // then a sigsegv emit layoutAboutToBeChanged(); foreach ( QString cur, dirs ) { QString fPath; BtFolder* temp = new BtFolder(); int i; // If the parent item is a folder, use its full path if ( pItem->type() == BtTreeItem::FOLDER ) fPath = pItem->folder()->fullPath() % "/" % cur; else fPath = pPath % "/" % cur; // If it isn't we need the parent path fPath.replace(QRegExp("//"), "/"); // Set the full path, which will set the name and the path temp->setfullPath(fPath); i = pItem->childCount(); pItem->insertChildren(i, 1, BtTreeItem::FOLDER); pItem->child(i)->setData(BtTreeItem::FOLDER, temp); // Insert the item into the tree. If it fails, bug out //if ( ! insertRow(i, ndx, temp, BtTreeItem::FOLDER) ) //{ // emit layoutChanged(); // return QModelIndex(); //} // Set the parent item to point to the newly created tree pItem = pItem->child(i); // And this for the return ndx = createIndex(pItem->childCount(), 0, pItem); }
bool BtTreeModel::renameFolder(BtFolder* victim, QString newName) { QModelIndex ndx = findFolder(victim->fullPath(), 0, false); QModelIndex pInd; QString targetPath = newName % "/" % victim->name(); QPair<QString,BtTreeItem*> f; QList<QPair<QString, BtTreeItem*> > folders; // This space is important ^ int i, kids,src; if ( ! ndx.isValid() ) return false; pInd = parent(ndx); if ( ! pInd.isValid() ) return false; BtTreeItem* start = item(ndx); f.first = targetPath; f.second = start; folders.append(f); while ( ! folders.isEmpty() ) { // This looks weird, but it is needed for later f = folders.takeFirst(); targetPath = f.first; BtTreeItem* target = f.second; // As we move things, childCount changes. This makes sure we loop // through all of the kids kids = target->childCount(); src = 0; // Ok. We have a start and an index. for (i=0; i < kids; ++i) { // This looks weird and it is. As we move children out, the 0 items // changes to the next child. In the case of a folder, though, we // don't move it, so we need to get the item beyond that. BtTreeItem* next = target->child(src); // If a folder, push it onto the folders stack for latter processing if ( next->type() == BtTreeItem::FOLDER ) { QPair<QString,BtTreeItem*> newTarget; newTarget.first = targetPath % "/" % next->name(); newTarget.second = next; folders.append(newTarget); src++; } else // Leafnode next->thing()->setFolder(targetPath); } } // Last thing is to remove the victim. i = start->childNumber(); return removeRows(i, 1, pInd); }
QModelIndex BtTreeModel::first() { QModelIndex parent; BtTreeItem* pItem; // get the first item in the list, which is the place holder pItem = rootItem->child(0); if ( pItem->childCount() > 0 ) return createIndex(0,0,pItem->child(0)); return QModelIndex(); }
bool BtTreeModel::renameFolder(BtFolder* victim, QString newName) { QModelIndex ndx = findFolder(victim->fullPath(), 0, false); QModelIndex pInd; QString targetPath = newName % "/" % victim->name(); QPair<QString,BtTreeItem*> f; QList<QPair<QString, BtTreeItem*> > folders; // This space is important ^ int i; if ( ! ndx.isValid() ) return false; pInd = parent(ndx); if ( ! pInd.isValid() ) return false; BtTreeItem* start = item(ndx); f.first = targetPath; f.second = start; folders.append(f); while ( ! folders.isEmpty() ) { // This looks weird, but it is needed for later f = folders.takeFirst(); targetPath = f.first; BtTreeItem* target = f.second; // Ok. We have a start and an index. for (i=0; i < target->childCount(); ++i) { BtTreeItem* next = target->child(i); // If a folder, push it onto the folders stack for latter processing if ( next->type() == BtTreeItem::FOLDER ) { QPair<QString,BtTreeItem*> newTarget; newTarget.first = targetPath % "/" % next->name(); newTarget.second = next; folders.append(newTarget); } else // Leafnode next->thing()->setFolder(targetPath); } } // Last thing is to remove the victim. i = start->childNumber(); return removeRows(i, 1, pInd); }
// One find method for all things. This .. is nice QModelIndex BtTreeModel::findElement(BeerXMLElement* thing, BtTreeItem* parent) { BtTreeItem* pItem; QModelIndex pIndex; QList<BtTreeItem*> folders; int i; if ( parent == NULL ) pItem = rootItem->child(0); else pItem = parent; if (! thing ) return createIndex(0,0,pItem); folders.append(pItem); // Recursion. Wonderful. while ( ! folders.isEmpty() ) { BtTreeItem* target = folders.takeFirst(); for(i=0; i < target->childCount(); ++i) { // If we've found what we are looking for, return if ( target->child(i)->thing() == thing ) return createIndex(i,0,target->child(i)); // If we have a folder, or we are looking for a brewnote and have a // recipe in hand, push the child onto the stack if ( target->child(i)->type() == BtTreeItem::FOLDER || (qobject_cast<BrewNote*>(thing) && target->child(i)->type() == BtTreeItem::RECIPE ) ) folders.append(target->child(i)); } } return QModelIndex(); }
bool BtTreeModel::insertRow(int row, const QModelIndex &parent, QObject* victim, int victimType ) { if ( ! parent.isValid() ) return false; BtTreeItem *pItem = item(parent); int type = pItem->type(); bool success = true; beginInsertRows(parent,row,row); success = pItem->insertChildren(row,1,type); if ( victim && success ) { type = victimType == -1 ? type : victimType; BtTreeItem* added = pItem->child(row); added->setData(type, victim); } endInsertRows(); return success; }