-// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019 CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
#include <Model_Data.h>
#include <Model_AttributeTables.h>
#include <Model_Events.h>
#include <Model_Expression.h>
+#include <Model_Tools.h>
+#include <Model_Validator.h>
+
#include <ModelAPI_Feature.h>
#include <ModelAPI_Result.h>
#include <ModelAPI_ResultParameter.h>
+#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_ResultPart.h>
-#include <ModelAPI_ResultCompSolid.h>
#include <ModelAPI_Tools.h>
-#include <Model_Validator.h>
#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
#include <TDataStd_Name.hxx>
#include <TDataStd_AsciiString.hxx>
-#include <TDataStd_IntegerArray.hxx>
-#include <TDF_AttributeIterator.hxx>
-#include <TDF_ChildIterator.hxx>
-#include <TDF_RelocationTable.hxx>
-#include <TColStd_HArray1OfByte.hxx>
+#include <TDataStd_UAttribute.hxx>
+#include <TDF_ChildIDIterator.hxx>
#include <string>
static const int kFlagDisplayed = 1;
// 2 - is deleted (for results) or not
static const int kFlagDeleted = 2;
+// TDataStd_Integer - 0 if the name of the object is generated automatically,
+// otherwise the name is defined by user
+Standard_GUID kUSER_DEFINED_NAME("9c694d18-a83c-4a56-bc9b-8020628a8244");
// invalid data
const static std::shared_ptr<ModelAPI_Data> kInvalid(new Model_Data());
+static const Standard_GUID kGroupAttributeGroupID("df64ea4c-fc42-4bf8-ad7e-08f7a54bf1b8");
+static const Standard_GUID kGroupAttributeID("ebdcb22a-e045-455b-9a7f-cfd38d68e185");
+
+
Model_Data::Model_Data() : mySendAttributeUpdated(true), myWasChangedButBlocked(false)
{
}
myFlags->SetValue(kFlagInHistory, Standard_True); // is in history by default is true
myFlags->SetValue(kFlagDisplayed, Standard_True); // is displayed by default is true
myFlags->SetValue(kFlagDeleted, Standard_False); // is deleted by default is false
- } else if (myFlags->Length() != 3) { // for old formats support
- Standard_Boolean aFlag0 = myFlags->Upper() >= 0 ? myFlags->Value(0) : Standard_True;
- Standard_Boolean aFlag1 = myFlags->Upper() >= 1 ? myFlags->Value(1) : Standard_True;
- Standard_Boolean aFlag2 = myFlags->Upper() >= 2 ? myFlags->Value(2) : Standard_True;
- Handle(TColStd_HArray1OfByte) aNewArray = new TColStd_HArray1OfByte(0, 2);
- myFlags->SetInternalArray(aNewArray);
- myFlags->SetValue(0, aFlag0);
- myFlags->SetValue(1, aFlag1);
- myFlags->SetValue(2, aFlag2);
}
}
std::string Model_Data::name()
{
Handle(TDataStd_Name) aName;
- if (myLab.FindAttribute(TDataStd_Name::GetID(), aName)) {
+ if (shapeLab().FindAttribute(TDataStd_Name::GetID(), aName)) {
#ifdef DEBUG_NAMES
myObject->myName = TCollection_AsciiString(aName->Get()).ToCString();
#endif
bool isModified = false;
std::string anOldName = name();
Handle(TDataStd_Name) aName;
- if (!myLab.FindAttribute(TDataStd_Name::GetID(), aName)) {
- TDataStd_Name::Set(myLab, theName.c_str());
+ if (!shapeLab().FindAttribute(TDataStd_Name::GetID(), aName)) {
+ TDataStd_Name::Set(shapeLab(), theName.c_str());
isModified = true;
} else {
isModified = !aName->Get().IsEqual(theName.c_str());
- if (isModified)
+ if (isModified) {
aName->Set(theName.c_str());
+
+ // check the name of result is defined by user
+ // (name of result does not composed of the name of feature and the result index)
+ bool isUserDefined = true;
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
+ if (aResult) {
+ std::string aDefaultName = ModelAPI_Tools::getDefaultName(aResult, false).first;
+ isUserDefined = aDefaultName != theName;
+ }
+ if (isUserDefined) {
+ // name is user-defined, thus special attribute is set
+ TDataStd_UAttribute::Set(shapeLab(), kUSER_DEFINED_NAME);
+ }
+ }
}
if (mySendAttributeUpdated && isModified)
ModelAPI_ObjectRenamedMessage::send(myObject, anOldName, theName, this);
if (isModified && myObject && myObject->document()) {
std::dynamic_pointer_cast<Model_Document>(myObject->document())->
- changeNamingName(anOldName, theName, myLab);
+ changeNamingName(anOldName, theName, shapeLab());
}
#ifdef DEBUG_NAMES
myObject->myName = theName;
#endif
}
-AttributePtr Model_Data::addAttribute(const std::string& theID, const std::string theAttrType)
+bool Model_Data::hasUserDefinedName() const
+{
+ return shapeLab().IsAttribute(kUSER_DEFINED_NAME);
+}
+
+AttributePtr Model_Data::addAttribute(
+ const std::string& theID, const std::string theAttrType, const int theIndex)
{
AttributePtr aResult;
- int anAttrIndex = int(myAttrs.size()) + 1;
+ int anAttrIndex = theIndex == -1 ? int(myAttrs.size()) + 1 : theIndex;
TDF_Label anAttrLab = myLab.FindChild(anAttrIndex);
ModelAPI_Attribute* anAttr = 0;
if (theAttrType == ModelAPI_AttributeDocRef::typeId()) {
return aResult;
}
+AttributePtr Model_Data::addFloatingAttribute(
+ const std::string& theID, const std::string theAttrType, const std::string& theGroup)
+{
+ // compute the index of the attribute placement
+ int anIndex;
+ TDF_Label aLab;
+ if (myLab.IsAttribute(TDF_TagSource::GetID())) {
+ // check this is re-init of attributes, so, check attribute with this name already there
+ TDF_ChildIDIterator anIter(myLab, kGroupAttributeID, false);
+ for(; anIter.More(); anIter.Next()) {
+ TCollection_AsciiString aThisName(Handle(TDataStd_Name)::DownCast(anIter.Value())->Get());
+ if (theID == aThisName.ToCString()) {
+ TDF_Label aLab = anIter.Value()->Label();
+ Handle(TDataStd_Name) aGName;
+ if (aLab.FindAttribute(kGroupAttributeGroupID, aGName)) {
+ TCollection_AsciiString aGroupName(aGName->Get());
+ if (theGroup == aGroupName.ToCString()) {
+ return addAttribute(theGroup + "__" + theID, theAttrType, aLab.Tag());
+ }
+ }
+ }
+ }
+ aLab = myLab.NewChild(); // already exists a floating attribute, create the next
+ anIndex = aLab.Tag();
+ } else { // put the first floating attribute, quite far from other standard attributes
+ anIndex = int(myAttrs.size()) + 1000;
+ TDF_TagSource::Set(myLab)->Set(anIndex);
+ aLab = myLab.FindChild(anIndex, true);
+ }
+ // store the group ID and the attribute ID (to restore correctly)
+ TDataStd_Name::Set(aLab, kGroupAttributeGroupID, theGroup.c_str());
+ TDataStd_Name::Set(aLab, kGroupAttributeID, theID.c_str());
+
+ return addAttribute(theGroup + "__" + theID, theAttrType, anIndex);
+}
+
+void Model_Data::allGroups(std::list<std::string>& theGroups)
+{
+ std::set<std::string> alreadyThere;
+ for(TDF_ChildIDIterator aGroup(myLab, kGroupAttributeGroupID); aGroup.More(); aGroup.Next()) {
+ Handle(TDataStd_Name) aGroupAttr = Handle(TDataStd_Name)::DownCast(aGroup.Value());
+ std::string aGroupID = TCollection_AsciiString(aGroupAttr->Get()).ToCString();
+ if (alreadyThere.find(aGroupID) == alreadyThere.end()) {
+ theGroups.push_back(aGroupID);
+ alreadyThere.insert(aGroupID);
+ }
+ }
+}
+
+void Model_Data::attributesOfGroup(const std::string& theGroup,
+ std::list<std::shared_ptr<ModelAPI_Attribute> >& theAttrs)
+{
+ for(TDF_ChildIDIterator aGroup(myLab, kGroupAttributeGroupID); aGroup.More(); aGroup.Next()) {
+ Handle(TDataStd_Name) aGroupID = Handle(TDataStd_Name)::DownCast(aGroup.Value());
+ if (aGroupID->Get().IsEqual(theGroup.c_str())) {
+ Handle(TDataStd_Name) anID;
+ if (aGroup.Value()->Label().FindAttribute(kGroupAttributeID, anID)) {
+ TCollection_AsciiString anAsciiID(aGroupID->Get() + "__" + anID->Get());
+ theAttrs.push_back(attribute(anAsciiID.ToCString()));
+ }
+ }
+ }
+}
+
+void Model_Data::removeAttributes(const std::string& theGroup)
+{
+ TDF_LabelList aLabsToRemove; // collect labels that must be erased after the cycle
+ for(TDF_ChildIDIterator aGroup(myLab, kGroupAttributeGroupID); aGroup.More(); aGroup.Next()) {
+ Handle(TDataStd_Name) aGroupID = Handle(TDataStd_Name)::DownCast(aGroup.Value());
+ if (aGroupID->Get().IsEqual(theGroup.c_str())) {
+ Handle(TDataStd_Name) anID;
+ if (!aGroup.Value()->Label().IsNull() &&
+ aGroup.Value()->Label().FindAttribute(kGroupAttributeID, anID)) {
+ aLabsToRemove.Append(aGroup.Value()->Label());
+ }
+ TCollection_AsciiString anAsciiID(aGroupID->Get() + "__" + anID->Get());
+ myAttrs.erase(anAsciiID.ToCString());
+ }
+ }
+ for(TDF_LabelList::Iterator aLab(aLabsToRemove); aLab.More(); aLab.Next()) {
+ aLab.ChangeValue().ForgetAllAttributes(true);
+ }
+}
+
+void Model_Data::clearAttributes()
+{
+ myAttrs.clear();
+}
+
+
+
// macro for the generic returning of the attribute by the ID
#define GET_ATTRIBUTE_BY_ID(ATTR_TYPE, METHOD_NAME) \
std::shared_ptr<ATTR_TYPE> Model_Data::METHOD_NAME(const std::string& theID) { \
myWasChangedButBlocked.push_back(theAttr);
}
} else {
- // trim: need to redisplay
- if (myObject) {
+ // trim: need to redisplay or set color in the python script
+ if (myObject && (theAttr->attributeType() == "Point2D" || theAttr->id() == "Color")) {
static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent);
}
STATE_INDEX_TRANSACTION = 2, // transaction ID
};
-/// Returns the label array, initialises it by default values if not exists
+/// Returns the label array, initializes it by default values if not exists
static Handle(TDataStd_IntegerArray) stateArray(TDF_Label& theLab)
{
Handle(TDataStd_IntegerArray) aStateArray;
return myLab.Father().Tag(); // tag of the feature label
}
-void Model_Data::eraseBackReferences()
+void Model_Data::removeBackReference(ObjectPtr theObject, std::string theAttrID)
{
- myRefsToMe.clear();
- std::shared_ptr<ModelAPI_Result> aRes =
- std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
- if (aRes)
- aRes->setIsConcealed(false);
-}
-
-void Model_Data::removeBackReference(FeaturePtr theFeature, std::string theAttrID)
-{
- AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
+ AttributePtr anAttribute = theObject->data()->attribute(theAttrID);
removeBackReference(anAttribute);
}
myRefsToMe.erase(theAttr);
- // remove concealment immideately: on deselection it must be posible to reselect in GUI the same
+ // remove concealment immediately: on deselection it must be possible to reselect in GUI the same
FeaturePtr aFeatureOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttr->owner());
if (aFeatureOwner.get() &&
ModelAPI_Session::get()->validators()->isConcealed(aFeatureOwner->getKind(), theAttr->id())) {
void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID,
const bool theApplyConcealment)
{
- // it is possible to add the same attribute twice: may be last time the owner was not Stable...
- AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
- if (myRefsToMe.find(anAttribute) == myRefsToMe.end())
- myRefsToMe.insert(theFeature->data()->attribute(theAttrID));
+ addBackReference(ObjectPtr(theFeature), theAttrID);
if (theApplyConcealment && theFeature->isStable() &&
ModelAPI_Session::get()->validators()->isConcealed(theFeature->getKind(), theAttrID)) {
- std::shared_ptr<ModelAPI_Result> aRes =
- std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
+ std::shared_ptr<ModelAPI_Result> aRes = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
// the second condition is for history upper than concealment causer, so the feature result may
// be displayed and previewed; also for avoiding of quick show/hide on history
// moving deep down
if (aRes && !theFeature->isDisabled()) {
- aRes->setIsConcealed(true);
+ aRes->setIsConcealed(true, theFeature->getKind() == "RemoveResults");
}
}
}
+void Model_Data::addBackReference(ObjectPtr theObject, std::string theAttrID)
+{
+ // it is possible to add the same attribute twice: may be last time the owner was not Stable...
+ AttributePtr anAttribute = theObject->data()->attribute(theAttrID);
+ if (myRefsToMe.find(anAttribute) == myRefsToMe.end())
+ myRefsToMe.insert(anAttribute);
+}
+
void Model_Data::updateConcealmentFlag()
{
std::set<AttributePtr>::iterator aRefsIter = myRefsToMe.begin();
std::shared_ptr<ModelAPI_Result> aRes =
std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
if (aRes.get()) {
- aRes->setIsConcealed(true); // set concealed
- return;
+ if (aRes->groupName() != ModelAPI_ResultConstruction::group()) {
+ aRes->setIsConcealed(true); // set concealed
+ return;
+ } else if (aFeature->getKind() == "RemoveResults") {
+ aRes->setIsConcealed(true, true);
+ return;
+ }
}
}
}
return anUsedParameters;
}
-std::list<ResultParameterPtr> findVariables(const std::set<std::string>& theParameters)
+std::list<ResultParameterPtr> findVariables(const std::set<std::string>& theParameters,
+ const DocumentPtr& theDocument)
{
std::list<ResultParameterPtr> aResult;
std::set<std::string>::const_iterator aParamIt = theParameters.cbegin();
ResultParameterPtr aParam;
// theSearcher is not needed here: in expressions
// of features the parameters history is not needed
- if (ModelAPI_Tools::findVariable(FeaturePtr(), aName, aValue, aParam))
+ if (ModelAPI_Tools::findVariable(FeaturePtr(), aName, aValue, aParam, theDocument))
aResult.push_back(aParam);
}
return aResult;
}
} else if (aType == ModelAPI_AttributeRefList::typeId()) { // list of references
aReferenced = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(anAttr)->list();
- } else if (aType == ModelAPI_AttributeSelection::typeId()) { // selection attribute
+ }
+ else if (aType == ModelAPI_AttributeSelection::typeId()) { // selection attribute
std::shared_ptr<ModelAPI_AttributeSelection> aRef = std::dynamic_pointer_cast<
- ModelAPI_AttributeSelection>(anAttr);
- aReferenced.push_back(aRef->context());
+ ModelAPI_AttributeSelection>(anAttr);
+ FeaturePtr aRefFeat = aRef->contextFeature();
+ if (aRefFeat.get()) { // reference to all results of the referenced feature
+ const std::list<ResultPtr>& allRes = aRefFeat->results();
+ std::list<ResultPtr>::const_iterator aRefRes = allRes.cbegin();
+ for(; aRefRes != allRes.cend(); aRefRes++) {
+ aReferenced.push_back(*aRefRes);
+ }
+ } else {
+ aReferenced.push_back(aRef->context());
+ }
} else if (aType == ModelAPI_AttributeSelectionList::typeId()) { // list of selection attributes
std::shared_ptr<ModelAPI_AttributeSelectionList> aRef = std::dynamic_pointer_cast<
ModelAPI_AttributeSelectionList>(anAttr);
for(int a = 0, aSize = aRef->size(); a < aSize; ++a) {
- aReferenced.push_back(aRef->value(a)->context());
+ FeaturePtr aRefFeat = aRef->value(a)->contextFeature();
+ if (aRefFeat.get()) { // reference to all results of the referenced feature
+ const std::list<ResultPtr>& allRes = aRefFeat->results();
+ std::list<ResultPtr>::const_iterator aRefRes = allRes.cbegin();
+ for (; aRefRes != allRes.cend(); aRefRes++) {
+ aReferenced.push_back(*aRefRes);
+ }
+ } else {
+ aReferenced.push_back(aRef->value(a)->context());
+ }
}
} else if (aType == ModelAPI_AttributeRefAttrList::typeId()) {
std::shared_ptr<ModelAPI_AttributeRefAttrList> aRefAttr = std::dynamic_pointer_cast<
AttributeIntegerPtr anAttribute =
std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(anAttr);
std::set<std::string> anUsedParameters = anAttribute->usedParameters();
- std::list<ResultParameterPtr> aParameters = findVariables(anUsedParameters);
+ std::list<ResultParameterPtr> aParameters =
+ findVariables(anUsedParameters, owner()->document());
aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end());
} else if (aType == ModelAPI_AttributeDouble::typeId()) { // double attribute
AttributeDoublePtr anAttribute =
std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr);
std::set<std::string> anUsedParameters = anAttribute->usedParameters();
- std::list<ResultParameterPtr> aParameters = findVariables(anUsedParameters);
+ std::list<ResultParameterPtr> aParameters =
+ findVariables(anUsedParameters, owner()->document());
aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end());
} else if (aType == GeomDataAPI_Point::typeId()) { // point attribute
AttributePointPtr anAttribute =
std::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr);
std::set<std::string> anUsedParameters = usedParameters(anAttribute);
- std::list<ResultParameterPtr> aParameters = findVariables(anUsedParameters);
+ std::list<ResultParameterPtr> aParameters =
+ findVariables(anUsedParameters, owner()->document());
aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end());
} else if (aType == GeomDataAPI_Point2D::typeId()) { // point attribute
AttributePoint2DPtr anAttribute =
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
std::set<std::string> anUsedParameters = usedParameters(anAttribute);
- std::list<ResultParameterPtr> aParameters = findVariables(anUsedParameters);
+ std::list<ResultParameterPtr> aParameters =
+ findVariables(anUsedParameters, owner()->document());
aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end());
} else
continue; // nothing to do, not reference
}
}
-/// makes copy of all attributes on the given label and all sub-labels
-static void copyAttrs(TDF_Label theSource, TDF_Label theDestination) {
- TDF_AttributeIterator anAttrIter(theSource);
- for(; anAttrIter.More(); anAttrIter.Next()) {
- Handle(TDF_Attribute) aTargetAttr;
- if (!theDestination.FindAttribute(anAttrIter.Value()->ID(), aTargetAttr)) {
- // create a new attribute if not yet exists in the destination
- aTargetAttr = anAttrIter.Value()->NewEmpty();
- theDestination.AddAttribute(aTargetAttr);
- }
- // no special relocation, empty map, but self-relocation is on: copy references w/o changes
- Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable(Standard_True);
- anAttrIter.Value()->Paste(aTargetAttr, aRelocTable);
- }
- // copy the sub-labels content
- TDF_ChildIterator aSubLabsIter(theSource);
- for(; aSubLabsIter.More(); aSubLabsIter.Next()) {
- copyAttrs(aSubLabsIter.Value(), theDestination.FindChild(aSubLabsIter.Value().Tag()));
- }
-}
-
void Model_Data::copyTo(std::shared_ptr<ModelAPI_Data> theTarget)
{
TDF_Label aTargetRoot = std::dynamic_pointer_cast<Model_Data>(theTarget)->label();
- copyAttrs(myLab, aTargetRoot);
+ Model_Tools::copyAttrs(myLab, aTargetRoot);
// reinitialize Model_Attributes by TDF_Attributes set
std::shared_ptr<Model_Data> aTData = std::dynamic_pointer_cast<Model_Data>(theTarget);
aTData->myAttrs.clear();
- theTarget->owner()->initAttributes(); // reinit feature attributes
+ theTarget->owner()->initAttributes(); // reinitialize feature attributes
}
bool Model_Data::isInHistory()
return myObject;
}
-bool Model_Data::isEarlierAttribute(const std::string& theAttribute1,
- const std::string& theAttribute2) const
+bool Model_Data::isPrecedingAttribute(const std::string& theAttribute1,
+ const std::string& theAttribute2) const
{
AttributeMap::const_iterator aFound1 = myAttrs.find(theAttribute1);
AttributeMap::const_iterator aFound2 = myAttrs.find(theAttribute2);