void GraphComponent::removeChildInternal( GraphComponentPtr child, bool emitParentChanged ) { if( emitParentChanged ) { child->parentChanging( 0 ); } ChildContainer::iterator it = std::find( m_children.begin(), m_children.end(), child ); if( it == m_children.end() || child->m_parent != this ) { // the public removeChild() method protects against this case, but it's still possible to // arrive here if an Action (which has a direct binding to removeChildInternal) is being replayed // from the undo queue, and just prior to that something called the public removeChild() method. // this can occur if a slot calls removeChild() from a signal triggered during the replay of the // undo queue. the onus is on such slots to not reperform their work when ScriptNode::currentActionStage() // is Action::Redo - instead they should rely on the fact that their actions will have been // recorded and replayed automatically. throw Exception( boost::str( boost::format( "GraphComponent::removeChildInternal : \"%s\" is not a child of \"%s\"." ) % child->fullName() % fullName() ) ); } m_children.erase( it ); child->m_parent = 0; childRemovedSignal()( this, child.get() ); if( emitParentChanged ) { child->parentChangedSignal()( child.get(), this ); } }
void GraphComponent::addChildInternal( GraphComponentPtr child ) { child->parentChanging( this ); GraphComponent *previousParent = child->m_parent; if( previousParent ) { // remove the child from the previous parent, but don't emit parentChangedSignal. // this prevents a parent changed signal with new parent 0 followed by a parent // changed signal with the new parent. previousParent->removeChildInternal( child, false ); } m_children.push_back( child ); child->m_parent = this; child->setName( child->m_name.value() ); // to force uniqueness childAddedSignal()( this, child.get() ); child->parentChangedSignal()( child.get(), previousParent ); }