void NodeGraph::decloneSelectedNodes() { if ( _imp->_selection.empty() ) { Dialogs::warningDialog( tr("Declone").toStdString(), tr("You must select at least a node to declone first.").toStdString() ); return; } std::map<NodeGuiPtr, NodePtr> nodesToDeclone; for (NodesGuiList::iterator it = _imp->_selection.begin(); it != _imp->_selection.end(); ++it) { BackdropGuiPtr isBd = toBackdropGui(*it); if (isBd) { // Also clone all nodes within the backdrop NodesGuiList nodesWithinBD = getNodesWithinBackdrop(*it); for (NodesGuiList::iterator it2 = nodesWithinBD.begin(); it2 != nodesWithinBD.end(); ++it2) { std::map<NodeGuiPtr, NodePtr>::iterator found = nodesToDeclone.find(*it2); if ( found == nodesToDeclone.end() ) { std::list<NodePtr> linkedNodes; (*it2)->getNode()->getCloneLinkedNodes(&linkedNodes); if (!linkedNodes.empty()) { nodesToDeclone[*it2] = linkedNodes.front(); } } } } std::list<NodePtr> linkedNodes; (*it)->getNode()->getCloneLinkedNodes(&linkedNodes); if (!linkedNodes.empty()) { nodesToDeclone[*it] = linkedNodes.front(); } } pushUndoCommand( new DecloneMultipleNodesCommand(this, nodesToDeclone) ); }
void NodeGraph::deleteSelection() { if ( !_imp->_selection.empty()) { NodesGuiList nodesToRemove = _imp->_selection; ///For all backdrops also move all the nodes contained within it for (NodesGuiList::iterator it = nodesToRemove.begin(); it != nodesToRemove.end(); ++it) { NodesGuiList nodesWithinBD = getNodesWithinBackdrop(*it); for (NodesGuiList::iterator it2 = nodesWithinBD.begin(); it2 != nodesWithinBD.end(); ++it2) { NodesGuiList::iterator found = std::find(nodesToRemove.begin(),nodesToRemove.end(),*it2); if ( found == nodesToRemove.end()) { nodesToRemove.push_back(*it2); } } } for (NodesGuiList::iterator it = nodesToRemove.begin(); it != nodesToRemove.end(); ++it) { const KnobsVec & knobs = (*it)->getNode()->getKnobs(); bool mustBreak = false; NodeGroup* isGrp = (*it)->getNode()->isEffectGroup(); for (U32 i = 0; i < knobs.size(); ++i) { KnobI::ListenerDimsMap listeners; knobs[i]->getListeners(listeners); ///For all listeners make sure they belong to a node bool foundEffect = false; for (KnobI::ListenerDimsMap::iterator it2 = listeners.begin(); it2 != listeners.end(); ++it2) { KnobPtr listener = it2->first.lock(); if (!listener) { continue; } EffectInstance* isEffect = dynamic_cast<EffectInstance*>(listener->getHolder() ); if (!isEffect) { continue; } if (isGrp && isEffect->getNode()->getGroup().get() == isGrp) { continue; } if (!isEffect->getNode()->getGroup()) { continue; } if ( isEffect && ( isEffect != (*it)->getNode()->getEffectInstance().get() ) ) { foundEffect = true; break; } } if (foundEffect) { StandardButtonEnum reply = Dialogs::questionDialog( tr("Delete").toStdString(), tr("This node has one or several " "parameters from which other parameters " "of the project rely on through expressions " "or links. Deleting this node will " "may break these expressions." "\nContinue anyway ?") .toStdString(), false ); if (reply == eStandardButtonNo) { return; } mustBreak = true; break; } } if (mustBreak) { break; } } for (NodesGuiList::iterator it = nodesToRemove.begin(); it != nodesToRemove.end(); ++it) { (*it)->setUserSelected(false); } pushUndoCommand( new RemoveMultipleNodesCommand(this,nodesToRemove) ); _imp->_selection.clear(); } } // deleteSelection