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; }
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); }
QVariant BtTreeModel::data(const QModelIndex &index, int role) const { int maxColumns; switch(treeMask) { case RECIPEMASK: maxColumns = BtTreeItem::RECIPENUMCOLS; break; case EQUIPMASK: maxColumns = BtTreeItem::EQUIPMENTNUMCOLS; break; case FERMENTMASK: maxColumns = BtTreeItem::FERMENTABLENUMCOLS; break; case HOPMASK: maxColumns = BtTreeItem::HOPNUMCOLS; break; case MISCMASK: maxColumns = BtTreeItem::MISCNUMCOLS; break; case YEASTMASK: maxColumns = BtTreeItem::YEASTNUMCOLS; break; case STYLEMASK: maxColumns = BtTreeItem::STYLENUMCOLS; break; case FOLDERMASK: maxColumns = BtTreeItem::FOLDERNUMCOLS; break; default: // Backwards compatibility. This MUST be fixed prior to releasing the code maxColumns = BtTreeItem::RECIPENUMCOLS; } if ( !rootItem || !index.isValid() || index.column() < 0 || index.column() >= maxColumns) return QVariant(); if ( role == Qt::ToolTipRole ) return toolTipData(index); if ( role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::DecorationRole) return QVariant(); BtTreeItem* itm = item(index); if ( role == Qt::DecorationRole && index.column() == 0) { if ( itm->type() == BtTreeItem::FOLDER ) return QIcon(":images/folder.png"); else return QVariant(); } return itm->data(index.column()); }
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); }
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::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; }