为什么不同的树项链接到相同的数据

why are different treeItems linked to the same data

我一直在尝试将树项及其子树复制到树视图中的另一个位置。

我终于能够成功地移动它们了。

treeItem 的头文件

class TreeItem
{
public:
    explicit TreeItem( Container *data , TreeItem *parent = 0 );
    ~TreeItem();
    TreeItem *parent();
    void appendChild(TreeItem *child);
    TreeItem& operator = (const TreeItem &item);
    TreeItem *child(int iNumber);
    int childCount() const;
    int childNumber() const;
    Container data() const ;
    Container* GetContainer();
    bool setData(Container* data , QVariant value);
    void setContainer( Container* data);
    bool insertChildren(int position, int count );
    bool removeChildren( int position  , int count );
    void removeChild(int row);
    void removeChild(TreeItem* itm);
    QList<TreeItem*> children();
    std::string getChildName(int row);
    std::string getName();
    int row() const;
    void insertChild(int pos, TreeItem *child);

private:
    QList<TreeItem*> childItems;
    Container* itemData;
    TreeItem* parentItem;
};

treeItem 的 Cpp 文件

TreeItem::TreeItem( Container *data, TreeItem *parent )
{
    parentItem = parent;
    itemData = new Container;
    *itemData = *data;  
}
TreeItem::~TreeItem()
{   
    if (itemData != nullptr)
    {
        delete itemData;
    }   
    qDeleteAll(childItems);
}
TreeItem& TreeItem::operator = (const TreeItem &item)
{
    qDebug() << "TreeItem operator called";
//  if( this->itemData == nullptr)
//      this->itemData = new Container;

    *this->itemData = *item.itemData;
    this->childItems = item.childItems;
    this->parentItem = item.parentItem;
    return *this;
}
TreeItem *TreeItem::parent()
{
    return parentItem;
}
TreeItem *TreeItem::child(int iNumber)
{
    return childItems.value(iNumber);
}
int TreeItem::childCount() const 
{
    return childItems.count();
}
int TreeItem::childNumber() const
{
    if (parentItem)
        return parentItem->childItems.indexOf(const_cast<TreeItem*> (this));

    return 0;
}
Container TreeItem::data() const
{
    return *itemData;
}
bool TreeItem::setData( Container* data , QVariant value )
{
    //*itemData = *data;  // Do Not !!!! uncomment this ///////////////////////////as it will set the value of default container constructor.
    itemData->SetName(value.toString().toStdString() );
    return true;
}
bool TreeItem::insertChildren(int position, int count)
{
    if (position < 0 || position > childItems.count())
        return false;

    Container cont;
    TreeItem *item = new TreeItem(&cont, this);
    childItems.insert(position, item);

    return true;
}
bool TreeItem::removeChildren(int position, int count)
{
    if (position < 0 || position > childItems.count())
        return false;

    for (int row = 0; row < count; ++row)
    {
        delete childItems.takeAt(position);
    }

    return true;
}
void TreeItem::setContainer( Container* cont)
{
    *itemData = *cont;  
}
void TreeItem::appendChild(TreeItem *node)
{
    childItems.append( node );
}
int TreeItem::row() const
{
//  qDebug() << "The child count = " << parentItem->childItems.indexOf(const_cast<TreeItem*>(this));

    if (parentItem)
    return parentItem->childItems.indexOf( const_cast<TreeItem*>(this) );

    return 0;
}
void TreeItem::removeChild(int row)
{   
    //   qDebug() << "The Row Number" << row;
     //  childItems.removeAt(row);
       delete childItems.takeAt(row);     
}
void TreeItem::insertChild(int pos, TreeItem *child)
{
    childItems.insert(pos, child);
    child->parentItem = this;
}
void TreeItem::removeChild(TreeItem* itm)
{
    childItems.removeOne(itm);
}
std::string TreeItem::getChildName(int row)
{
    return childItems.value(row)->getName();
}
std::string TreeItem::getName()
{
    return itemData->GetName();
}
Container* TreeItem::GetContainer()
{
    return itemData;
}
QList<TreeItem*> TreeItem::children()
{
    return  childItems;
}

这是我为树结构中树项的子容器构建树的函数。

void TreeModel::buildTree(TreeItem * pItem, QDataStream & ds) const
{
    if (pItem == NULL)
        return;

     ds << reinterpret_cast<qlonglong>(pItem);
     ds << pItem->childCount();
     foreach(TreeItem* childItem, pItem->children())
     {
         buildTree(childItem, ds);
     }
}

这是在我还原容器子树的 Drop mime 数据函数中。

// count is the number of child containers of the tree item
TreeItem *node;
    //qDebug() << "The row" << row << parentNode->data().GetName().c_str() ;
    for (int i = 0; i < count; ++i) {
        // Decode data from the QMimeData
        qlonglong nodePtr;
        int childCount;
        stream >> nodePtr;
        stream >> childCount;
        node = reinterpret_cast<TreeItem *>(nodePtr);
        // Adjust destination row for the case of moving an item
        // within the same parent, to a position further down.
        // Its own removal will reduce the final row number by one.
        if (node->row() < row  && parentNode == node->parent())
            --row;

        TreeItem *nodeNew = new TreeItem(node->GetContainer(), node->parent());
        nodeNew->setContainer(node->GetContainer());        
        // Insert at new position
        //qDebug() << "Inserting into" << parent << row;
        beginInsertRows(parent, row, row);
        parentNode->insertChild(row, nodeNew);          
        endInsertRows();
        for (int k = 0; k < childCount; k++)
        {
            restoreTree(stream, nodeNew);
        }

        ++row;      
    }

这是恢复子树的函数

TreeItem * TreeModel::restoreTree(QDataStream & ds , TreeItem* parent) const
{
    Container cont;

    // Restore the info from the stream
    int childCount;     
    qlonglong nodePtr;          
    ds >> nodePtr;
    ds >> childCount;       
    TreeItem *currentItem = reinterpret_cast<TreeItem *>(nodePtr);
    if (currentItem == nullptr)
        return nullptr;

    TreeItem *thisItem = new TreeItem(currentItem->GetContainer(), currentItem->parent() );
    thisItem->setContainer(currentItem->GetContainer());
    //*thisItem = *currentItem;
    parent->appendChild(thisItem);
    for (auto nChild = 0; nChild < childCount; ++nChild)
    {
       TreeItem* oldChild = restoreTree(ds, thisItem);          
        if (oldChild != nullptr)
        {
            TreeItem *pChild = new TreeItem( oldChild->GetContainer() , oldChild->parent() );
            pChild->setContainer(oldChild->GetContainer());
            thisItem->appendChild(pChild);
            qDebug() << "Appending child";
        }
    }
    return thisItem;
}

树以正确的方式恢复。

但现在我有一个问题,旧位置的树项和新位置的树项链接在一起,如果我对旧位置的树项进行任何更改,它也会影响新位置的树项。

更改父项->appendChild(thisItem);到父->insertChild(row, thisItem);现在解决了这个问题,BuildTree 函数起作用了。

TreeItem * TreeModel::restoreTree(QDataStream & ds , TreeItem* parent , int row) const
{
    Container cont; 
    // Restore the info from the stream
    int childCount;     
    qlonglong nodePtr;
    QModelIndex parentIndex;
    ds >> nodePtr;
    ds >> childCount;

    TreeItem *currentItem = reinterpret_cast<TreeItem *>(nodePtr);
    if (currentItem == nullptr)
        return nullptr;

    TreeItem *thisItem = new TreeItem(currentItem->GetContainer(), currentItem->parent() );
    thisItem->setContainer(currentItem->GetContainer());
    //*thisItem = *currentItem;
//  parent->appendChild(thisItem);
    parent->insertChild(row, thisItem);
    for (auto nChild = 0; nChild < childCount; ++nChild)
    {   
       restoreTree(ds, thisItem , nChild);
    }
    return thisItem;
}

如果有人可以解释 parent->appendChild(thisItem) 之间的区别,那就更重要了,并尝试找到有效的解决方案;到 parent->insertChild(row, thisItem) 那会很棒。

或任何替代解决方案。