如何合并两个QStandardItemModel以构建TreeView的新数据模型
Got it, let's tackle this problem step by step. Merging two QStandardItemModel instances into a new one for a TreeView is totally doable—here's how you can achieve the combined structure shown in your Figure C.
Key Concepts
The core idea is to either clone (deep copy) or move the top-level nodes from your source models (fileTree and zipTree) into the new model (fullTree). Cloning keeps your source models intact, while moving is more efficient but removes nodes from the source models.
Step 1: Helper Function for Deep Cloning (Optional but Recommended)
If you need to keep your original models (fileTree and zipTree) intact, use this helper function to clone each item and its child hierarchy:
QStandardItem* cloneItem(const QStandardItem* sourceItem) { if (!sourceItem) return nullptr; // Clone core properties of the item (icon, text, data, flags) QStandardItem* clonedItem = new QStandardItem(sourceItem->icon(), sourceItem->text()); clonedItem->setData(sourceItem->data(), sourceItem->role()); clonedItem->setFlags(sourceItem->flags()); // Recursively clone all child items for (int row = 0; row < sourceItem->rowCount(); ++row) { QStandardItem* clonedChild = cloneItem(sourceItem->child(row)); if (clonedChild) { clonedItem->appendRow(clonedChild); } } return clonedItem; }
Step 2: Merge the Models
Option 1: Clone Nodes (Preserve Source Models)
Use this if you still need to use fileTree and zipTree after merging:
// Initialize your new model QStandardItemModel* fullTree = new QStandardItemModel(); // Get the invisible root items from both source models QStandardItem* fileRoot = fileTree->invisibleRootItem(); QStandardItem* zipRoot = zipTree->invisibleRootItem(); // Clone and add all top-level items from fileTree to fullTree for (int row = 0; row < fileRoot->rowCount(); ++row) { QStandardItem* clonedItem = cloneItem(fileRoot->child(row)); if (clonedItem) { fullTree->invisibleRootItem()->appendRow(clonedItem); } } // Clone and add all top-level items from zipTree to fullTree for (int row = 0; row < zipRoot->rowCount(); ++row) { QStandardItem* clonedItem = cloneItem(zipRoot->child(row)); if (clonedItem) { fullTree->invisibleRootItem()->appendRow(clonedItem); } } // Assign the merged model to your TreeView ui->treeView->setModel(fullTree);
Option 2: Move Nodes (Efficient, Source Models Lose Nodes)
If you don't need fileTree and zipTree anymore, use takeRow() to move nodes directly (no cloning needed):
QStandardItemModel* fullTree = new QStandardItemModel(); QStandardItem* fileRoot = fileTree->invisibleRootItem(); QStandardItem* zipRoot = zipTree->invisibleRootItem(); // Move top-level items from fileTree to fullTree for (int row = 0; row < fileRoot->rowCount();) { // Don't increment row—takeRow() shifts remaining rows QList<QStandardItem*> rowItems = fileRoot->takeRow(row); fullTree->invisibleRootItem()->appendRow(rowItems); } // Move top-level items from zipTree to fullTree for (int row = 0; row < zipRoot->rowCount();) { QList<QStandardItem*> rowItems = zipRoot->takeRow(row); fullTree->invisibleRootItem()->appendRow(rowItems); } ui->treeView->setModel(fullTree);
How It Works
- If your source models have a single top-level root (e.g., Figure A's "Local Files" and Figure B's "Archive.zip"), this code will add both roots as top-level items in
fullTree—exactly matching Figure C's structure. - The cloning function ensures all item data (icons, custom roles, flags, child nodes) are preserved in the new model.
内容的提问来源于stack exchange,提问作者kien bui

