X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH_I%2FSMESH_2smeshpy.cxx;h=929da0dcf43bc2518b5e946ff3dd1d90e88374f8;hb=2ec7f35acedb4734ca755bd095a5504440e875f8;hp=7cfe7dd47165df303d8514221db441971316265b;hpb=85aae58eadeb3276be732dbb81ec9fc7a7cec147;p=modules%2Fsmesh.git diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 7cfe7dd47..929da0dcf 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -44,7 +44,7 @@ #include -#ifdef WNT +#ifdef WIN32 #include #else #include @@ -183,7 +183,8 @@ namespace { if ( cmd->GetString().Location( TPythonDump::NotPublishedObjectName(), 1, cmd->Length() )) { bool isResultPublished = false; - for ( int i = 0; i < cmd->GetNbResultValues(); i++ ) + const int nbRes = cmd->GetNbResultValues(); + for ( int i = 0; i < nbRes; i++ ) { _pyID objID = cmd->GetResultValue( i+1 ); if ( cmd->IsStudyEntry( objID )) @@ -198,8 +199,17 @@ namespace { } // check if an Object was created in the script _AString comment; - const _pyID& obj = cmd->GetObject(); - if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj )) + + _pyID obj = cmd->GetObject(); + if ( obj.Search( "print " ) == 1 ) + return; // print statement + + if ( !obj.IsEmpty() && obj.Value( obj.Length() ) == ')' ) + // remove an accessor method + obj = _pyCommand( obj ).GetObject(); + + const bool isMethodCall = cmd->IsMethodCall(); + if ( !obj.IsEmpty() && isMethodCall && !presentObjects.count( obj ) ) { comment = "not created Object"; theGen->ObjectCreationRemoved( obj ); @@ -218,6 +228,8 @@ namespace { comment += *id + " has not been yet created"; break; } + // if ( idList.empty() && cmd->IsID( arg ) && !presentObjects.count( arg )) + // comment += arg + " has not been yet created"; } // treat result objects const _pyID& result = cmd->GetResultValue(); @@ -226,10 +238,14 @@ namespace { list< _pyID > idList = cmd->GetStudyEntries( result ); list< _pyID >::iterator id = idList.begin(); for ( ; id != idList.end(); ++id ) + { if ( comment.IsEmpty() ) presentObjects.insert( *id ); else theGen->ObjectCreationRemoved( *id ); // objID.SetName( name ) is not needed + } + if ( idList.empty() && cmd->IsID( result )) + presentObjects.insert( result ); } // comment the command if ( !comment.IsEmpty() ) @@ -437,7 +453,7 @@ namespace { //================================================================================ /*! * \brief Convert a python script using commands of smeshBuilder.py - * \param theScript - Input script + * \param theScriptLines - Lines of the input script * \param theEntry2AccessorMethod - returns method names to access to * objects wrapped with python class * \param theObjectNames - names of objects @@ -448,48 +464,41 @@ namespace { */ //================================================================================ -TCollection_AsciiString -SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, +void +SMESH_2smeshpy::ConvertScript(std::list< TCollection_AsciiString >& theScriptLines, Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod, Resource_DataMapOfAsciiStringAsciiString& theObjectNames, std::set< TCollection_AsciiString >& theRemovedObjIDs, SALOMEDS::Study_ptr& theStudy, const bool theToKeepAllCommands) { - theGen = new _pyGen( theEntry2AccessorMethod, - theObjectNames, - theRemovedObjIDs, - theStudy, - theToKeepAllCommands ); + std::list< TCollection_AsciiString >::iterator lineIt; + // process notebook variables + { + SMESH_NoteBook aNoteBook; - // split theScript into separate commands + for ( lineIt = theScriptLines.begin(); lineIt != theScriptLines.end(); ++lineIt ) + aNoteBook.AddCommand( *lineIt ); - SMESH_NoteBook * aNoteBook = new SMESH_NoteBook(); + theScriptLines.clear(); - int from = 1, end = theScript.Length(), to; - while ( from < end && ( to = theScript.Location( "\n", from, end ))) - { - if ( to != from ) - // cut out and store a command - aNoteBook->AddCommand( theScript.SubString( from, to - 1 )); - from = to + 1; + aNoteBook.ReplaceVariables(); + + aNoteBook.GetResultLines( theScriptLines ); } - aNoteBook->ReplaceVariables(); + // convert to smeshBuilder.py API + + theGen = new _pyGen( theEntry2AccessorMethod, + theObjectNames, + theRemovedObjIDs, + theStudy, + theToKeepAllCommands ); - TCollection_AsciiString aNoteScript = aNoteBook->GetResultScript(); - delete aNoteBook; - aNoteBook = 0; + for ( lineIt = theScriptLines.begin(); lineIt != theScriptLines.end(); ++lineIt ) + theGen->AddCommand( *lineIt ); - // split theScript into separate commands - from = 1, end = aNoteScript.Length(); - while ( from < end && ( to = aNoteScript.Location( "\n", from, end ))) - { - if ( to != from ) - // cut out and store a command - theGen->AddCommand( aNoteScript.SubString( from, to - 1 )); - from = to + 1; - } + theScriptLines.clear(); // finish conversion theGen->Flush(); @@ -511,8 +520,11 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScrip } while ( orderChanges ); // concat commands back into a script - TCollection_AsciiString aScript, aPrevCmd; + TCollection_AsciiString aPrevCmd; set<_pyID> createdObjects; + createdObjects.insert( "smeshBuilder" ); + createdObjects.insert( "smesh" ); + createdObjects.insert( "theStudy" ); for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd ) { #ifdef DUMP_CONVERSION @@ -520,17 +532,15 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScrip #endif if ( !(*cmd)->IsEmpty() && aPrevCmd != (*cmd)->GetString()) { CheckObjectPresence( *cmd, createdObjects ); - aPrevCmd = (*cmd)->GetString(); - aScript += "\n"; - aScript += aPrevCmd; + if ( !(*cmd)->IsEmpty() ) { + aPrevCmd = (*cmd)->GetString(); + theScriptLines.push_back( aPrevCmd ); + } } } - aScript += "\n"; theGen->Free(); theGen.Nullify(); - - return aScript; } //================================================================================ @@ -630,15 +640,36 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand // Method( SMESH.PointStruct(x,y,z)... -> Method( [x,y,z]... StructToList( aCommand ); + const TCollection_AsciiString& method = aCommand->GetMethod(); + // not to erase _pySelfEraser's etc. used as args in some commands - std::list< _pyID >::const_iterator id = myKeepAgrCmdsIDs.begin(); - for ( ; id != myKeepAgrCmdsIDs.end(); ++id ) - if ( *id != objID && theCommand.Search( *id ) > id->Length() ) + { +#ifdef USE_STRING_FAMILY + std::list<_pyID> objIDs; + if ( myKeepAgrCmdsIDs.IsInArgs( aCommand, objIDs )) { - Handle(_pyObject) obj = FindObject( *id ); - if ( !obj.IsNull() ) - obj->AddArgCmd( aCommand ); + std::list<_pyID>::iterator objID = objIDs.begin(); + for ( ; objID != objIDs.end(); ++objID ) + { + Handle(_pyObject) obj = FindObject( *objID ); + if ( !obj.IsNull() ) + { + obj->AddArgCmd( aCommand ); + //cout << objID << " found in " << theCommand << endl; + } + } } +#else + std::list< _pyID >::const_iterator id = myKeepAgrCmdsIDs.begin(); + for ( ; id != myKeepAgrCmdsIDs.end(); ++id ) + if ( *id != objID && theCommand.Search( *id ) > id->Length() ) + { + Handle(_pyObject) obj = FindObject( *id ); + if ( !obj.IsNull() ) + obj->AddArgCmd( aCommand ); + } +#endif + } // Find an object to process theCommand @@ -667,8 +698,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand else if ( aCommand->GetMethod() == "GetSubMesh" ) { // SubMesh creation _pyID subMeshID = aCommand->GetResultValue(); Handle(_pySubMesh) subMesh = new _pySubMesh( aCommand ); - CheckObjectIsReCreated( subMesh ); - myObjects.insert( make_pair( subMeshID, subMesh )); + AddObject( subMesh ); } // Method( mesh.GetIDSource([id1,id2]) -> Method( [id1,id2] @@ -690,8 +720,6 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand //addFilterUser( aCommand, theGen ); // protect filters from clearing - const TCollection_AsciiString& method = aCommand->GetMethod(); - // some commands of SMESH_MeshEditor create meshes and groups _pyID meshID, groups; if ( method.Search("MakeMesh") != -1 ) @@ -860,17 +888,19 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand if ( Type == "SMESH.FT_ElemGeomType" ) { // set SMESH.GeometryType instead of a numerical Threshold - const char* types[SMESH::Geom_BALL+1] = { + const int nbTypes = SMESH::Geom_BALL+1; + const char* types[nbTypes] = { "Geom_POINT", "Geom_EDGE", "Geom_TRIANGLE", "Geom_QUADRANGLE", "Geom_POLYGON", "Geom_TETRA", "Geom_PYRAMID", "Geom_HEXA", "Geom_PENTA", "Geom_HEXAGONAL_PRISM", "Geom_POLYHEDRA", "Geom_BALL" }; - if ( -1 < iGeom && iGeom < SMESH::Geom_POLYHEDRA+1 ) + if ( -1 < iGeom && iGeom < nbTypes ) Threshold = SMESH + types[ iGeom ]; } if (Type == "SMESH.FT_EntityType") { // set SMESH.EntityType instead of a numerical Threshold - const char* types[SMESH::Entity_Ball+1] = { + const int nbTypes = SMESH::Entity_Ball+1; + const char* types[nbTypes] = { "Entity_Node", "Entity_0D", "Entity_Edge", "Entity_Quad_Edge", "Entity_Triangle", "Entity_Quad_Triangle", "Entity_BiQuad_Triangle", "Entity_Quadrangle", "Entity_Quad_Quadrangle", "Entity_BiQuad_Quadrangle", @@ -879,7 +909,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand "Entity_Hexa", "Entity_Quad_Hexa", "Entity_TriQuad_Hexa", "Entity_Penta", "Entity_Quad_Penta", "Entity_Hexagonal_Prism", "Entity_Polyhedra", "Entity_Quad_Polyhedra", "Entity_Ball" }; - if ( -1 < iGeom && iGeom < SMESH::Entity_Quad_Polyhedra+1 ) + if ( -1 < iGeom && iGeom < nbTypes ) Threshold = SMESH + types[ iGeom ]; } } @@ -951,11 +981,11 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) method == "CreateMeshesFromCGNS" || method == "CreateMeshesFromGMF" ) // command result is ( [mesh1,mesh2], status ) { - for ( int ind = 0; ind < theCommand->GetNbResultValues(); ind++ ) + std::list< _pyID > meshIDs = theCommand->GetStudyEntries( theCommand->GetResultValue() ); + std::list< _pyID >::iterator meshID = meshIDs.begin(); + for ( ; meshID != meshIDs.end(); ++meshID ) { - _pyID meshID = theCommand->GetResultValue(ind+1); - if ( !theCommand->IsStudyEntry( meshID ) ) continue; - Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue(ind+1)); + Handle(_pyMesh) mesh = new _pyMesh( theCommand, *meshID ); AddObject( mesh ); } if ( method == "CreateMeshesFromGMF" ) @@ -1023,7 +1053,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) method == "CreateMeasurements" ) { Handle(_pyObject) obj = new _pySelfEraser( theCommand ); - if ( !myObjects.insert( make_pair( obj->GetID(), obj )).second ) + if ( !AddObject( obj ) ) theCommand->Clear(); // already created } // Concatenate( [mesh1, ...], ... ) @@ -1119,10 +1149,15 @@ void _pyGen::Flush() id_hyp->second->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() ); } - // Flush other objects - for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj ) - if ( ! id_obj->second.IsNull() ) - id_obj->second->Flush(); + // Flush other objects. 2 times, for objects depending on Flush() of later created objects + std::list< Handle(_pyObject) >::reverse_iterator robj = myOrderedObjects.rbegin(); + for ( ; robj != myOrderedObjects.rend(); ++robj ) + if ( ! robj->IsNull() ) + (*robj)->Flush(); + std::list< Handle(_pyObject) >::iterator obj = myOrderedObjects.begin(); + for ( ; obj != myOrderedObjects.end(); ++obj ) + if ( ! obj->IsNull() ) + (*obj)->Flush(); myLastCommand->SetOrderNb( ++myNbCommands ); myCommands.push_back( myLastCommand ); @@ -1137,23 +1172,23 @@ void _pyGen::Flush() void _pyGen::PlaceSubmeshAfterItsCreation( Handle(_pyCommand) theCmdUsingSubmesh ) const { - map< _pyID, Handle(_pyObject) >::const_iterator id_obj = myObjects.begin(); - for ( ; id_obj != myObjects.end(); ++id_obj ) - { - if ( !id_obj->second->IsKind( STANDARD_TYPE( _pySubMesh ))) continue; - for ( int iArg = theCmdUsingSubmesh->GetNbArgs(); iArg; --iArg ) - { - const _pyID& arg = theCmdUsingSubmesh->GetArg( iArg ); - if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' ) - continue; - list< _pyID > idList = theCmdUsingSubmesh->GetStudyEntries( arg ); - list< _pyID >::iterator id = idList.begin(); - for ( ; id != idList.end(); ++id ) - if ( id_obj->first == *id ) - // _pySubMesh::Process() does what we need - Handle(_pySubMesh)::DownCast( id_obj->second )->Process( theCmdUsingSubmesh ); - } - } + // map< _pyID, Handle(_pyObject) >::const_iterator id_obj = myObjects.begin(); + // for ( ; id_obj != myObjects.end(); ++id_obj ) + // { + // if ( !id_obj->second->IsKind( STANDARD_TYPE( _pySubMesh ))) continue; + // for ( int iArg = theCmdUsingSubmesh->GetNbArgs(); iArg; --iArg ) + // { + // const _pyID& arg = theCmdUsingSubmesh->GetArg( iArg ); + // if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' ) + // continue; + // list< _pyID > idList = theCmdUsingSubmesh->GetStudyEntries( arg ); + // list< _pyID >::iterator id = idList.begin(); + // for ( ; id != idList.end(); ++id ) + // if ( id_obj->first == *id ) + // // _pySubMesh::Process() does what we need + // Handle(_pySubMesh)::DownCast( id_obj->second )->Process( theCmdUsingSubmesh ); + // } + // } } //================================================================================ @@ -1173,9 +1208,15 @@ void _pyGen::ClearCommands() if ( !id_hyp->second.IsNull() ) id_hyp->second->ClearCommands(); - map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin(); - for ( ; id_obj != myObjects.end(); ++id_obj ) - id_obj->second->ClearCommands(); + // Other objects. 2 times, for objects depending on ClearCommands() of later created objects + std::list< Handle(_pyObject) >::reverse_iterator robj = myOrderedObjects.rbegin(); + for ( ; robj != myOrderedObjects.rend(); ++robj ) + if ( ! robj->IsNull() ) + (*robj)->ClearCommands(); + std::list< Handle(_pyObject) >::iterator obj = myOrderedObjects.begin(); + for ( ; obj != myOrderedObjects.end(); ++obj ) + if ( ! obj->IsNull() ) + (*obj)->ClearCommands(); } //================================================================================ @@ -1208,6 +1249,8 @@ void _pyGen::Free() myHypos.clear(); myFile2ExportedMesh.clear(); + + //myKeepAgrCmdsIDs.Print(); } //================================================================================ @@ -1468,20 +1511,27 @@ _pyID _pyGen::GenerateNewID( const _pyID& theID ) */ //================================================================================ -void _pyGen::AddObject( Handle(_pyObject)& theObj ) +bool _pyGen::AddObject( Handle(_pyObject)& theObj ) { - if ( theObj.IsNull() ) return; + if ( theObj.IsNull() ) return false; CheckObjectIsReCreated( theObj ); - if ( theObj->IsKind( STANDARD_TYPE( _pyMesh ))) - myMeshes.insert( make_pair( theObj->GetID(), Handle(_pyMesh)::DownCast( theObj ))); - - else if ( theObj->IsKind( STANDARD_TYPE( _pyMeshEditor ))) - myMeshEditors.insert( make_pair( theObj->GetID(), Handle(_pyMeshEditor)::DownCast( theObj ))); + bool add; - else - myObjects.insert( make_pair( theObj->GetID(), theObj )); + if ( theObj->IsKind( STANDARD_TYPE( _pyMesh ))) { + add = myMeshes.insert( make_pair( theObj->GetID(), + Handle(_pyMesh)::DownCast( theObj ))).second; + } + else if ( theObj->IsKind( STANDARD_TYPE( _pyMeshEditor ))) { + add = myMeshEditors.insert( make_pair( theObj->GetID(), + Handle(_pyMeshEditor)::DownCast( theObj ))).second; + } + else { + add = myObjects.insert( make_pair( theObj->GetID(), theObj )).second; + if ( add ) myOrderedObjects.push_back( theObj ); + } + return add; } //================================================================================ @@ -1952,7 +2002,7 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) { addCmd = *cmd; cmd = addHypCmds.erase( cmd ); - if ( !theGen->IsToKeepAllCommands() ) { + if ( !theGen->IsToKeepAllCommands() && CanClear() ) { addCmd->Clear(); theCommand->Clear(); } @@ -3413,7 +3463,7 @@ bool _pyAlgorithm::Addition2Creation( const Handle(_pyCommand)& theCmd, */ //================================================================================ -int _pyCommand::GetBegPos( int thePartIndex ) +int _pyCommand::GetBegPos( int thePartIndex ) const { if ( IsEmpty() ) return EMPTY; @@ -3453,7 +3503,7 @@ TCollection_AsciiString _pyCommand::GetIndentation() GetWord( myString, end, true ); else end = GetBegPos( RESULT_IND ); - return myString.SubString( 1, end - 1 ); + return myString.SubString( 1, Max( end - 1, 1 )); } //================================================================================ @@ -3493,16 +3543,8 @@ const TCollection_AsciiString & _pyCommand::GetResultValue() int _pyCommand::GetNbResultValues() { - int nb = 0; - int begPos = 1; - int endPos = myString.Location( "=", 1, Length() ); - while ( begPos < endPos ) - { - _AString str = GetWord( myString, begPos, true ); - begPos = begPos+ str.Length(); - nb++; - } - return (nb-1); + GetResultValue(1); + return myResults.Length(); } @@ -3513,32 +3555,38 @@ int _pyCommand::GetNbResultValues() * \retval const TCollection_AsciiString & - ResultValue with res index substring */ //================================================================================ -TCollection_AsciiString _pyCommand::GetResultValue(int res) +const _AString& _pyCommand::GetResultValue(int res) { - int begPos = 1; - if ( SkipSpaces( myString, begPos ) && myString.Value( begPos ) == '[' ) - ++begPos; // skip [, else the whole list is returned - int endPos = myString.Location( "=", 1, Length() ); - int Nb=0; - while ( begPos < endPos) { - _AString result = GetWord( myString, begPos, true ); - begPos = begPos + result.Length(); - Nb++; - if(res == Nb) { - result.RemoveAll('['); - result.RemoveAll(']'); - return result; + if ( GetResultValue().IsEmpty() ) + return theEmptyString; + + if ( myResults.IsEmpty() ) + { + int begPos = 1; + if ( SkipSpaces( myRes, begPos ) && myRes.Value( begPos ) == '[' ) + ++begPos; // skip [, else the whole list is returned + while ( begPos < myRes.Length() ) { + _AString result = GetWord( myRes, begPos, true ); + begPos += result.Length(); + // if(res == Nb) { + // result.RemoveAll('['); + // result.RemoveAll(']'); + // return result; + // } + // if(Nb>res) + // break; + myResults.Append( result ); } - if(Nb>res) - break; } + if ( res > 0 && res <= myResults.Length() ) + return myResults( res ); return theEmptyString; } //================================================================================ /*! * \brief Return substring of python command looking like ResVal = Object.Meth() - * \retval const TCollection_AsciiString & - Object substring + * \retval const TCollection_AsciiString & - Object substring */ //================================================================================ @@ -3547,7 +3595,7 @@ const TCollection_AsciiString & _pyCommand::GetObject() if ( GetBegPos( OBJECT_IND ) == UNKNOWN ) { // beginning - int begPos = GetBegPos( RESULT_IND ) + myRes.Length(); + int begPos = GetBegPos( RESULT_IND ); if ( begPos < 1 ) { begPos = myString.Location( "=", 1, Length() ) + 1; // is '=' in the string argument (for example, name) or not @@ -3564,6 +3612,9 @@ const TCollection_AsciiString & _pyCommand::GetObject() if ( nb1 % 2 != 0 || nb2 % 2 != 0 ) begPos = 1; } + else { + begPos += myRes.Length(); + } myObj = GetWord( myString, begPos, true ); if ( begPos != EMPTY ) { @@ -3621,6 +3672,20 @@ const TCollection_AsciiString & _pyCommand::GetMethod() return myMeth; } +//================================================================================ +/*! + * \brief Returns true if there are brackets after the method + */ +//================================================================================ + +bool _pyCommand::IsMethodCall() +{ + if ( GetMethod().IsEmpty() ) + return false; + const char* s = myString.ToCString() + GetBegPos( METHOD_IND ) + myMeth.Length() - 1; + return ( s[0] == '(' || s[1] == '(' ); +} + //================================================================================ /*! * \brief Return substring of python command looking like ResVal = Obj.Meth(Arg1,...) @@ -3704,6 +3769,24 @@ const TCollection_AsciiString & _pyCommand::GetArg( int index ) return myArgs( index ); } +//================================================================================ +/*! + * \brief Return position where arguments begin + */ +//================================================================================ + +int _pyCommand::GetArgBeginning() const +{ + int pos = GetBegPos( ARG1_IND ); + if ( pos == UNKNOWN ) + { + pos = GetBegPos( METHOD_IND ) + myMeth.Length(); + if ( pos < 1 ) + pos = myString.Location( "(", 4, Length() ); // 4 = strlen("b.c(") + } + return pos; +} + //================================================================================ /*! * \brief Check if char is a word part @@ -3807,6 +3890,26 @@ bool _pyCommand::IsStudyEntry( const TCollection_AsciiString& str ) return nbColons > 2 && str.Length()-nbColons > 2; } +//================================================================================ +/*! + * \brief Returns true if the string looks like an object ID but not like a list, + * string, command etc. + */ +//================================================================================ + +bool _pyCommand::IsID( const TCollection_AsciiString& str ) +{ + if ( str.Length() < 1 ) return false; + + const char* s = str.ToCString(); + + for ( int i = 0; i < str.Length(); ++i ) + if ( !IsIDChar( s[i] )) + return false; + + return true; +} + //================================================================================ /*! * \brief Finds entries in a sting @@ -3968,9 +4071,9 @@ void _pyCommand::Comment() myString.Insert( i, "#" ); for ( int iPart = 1; iPart <= myBegPos.Length(); ++iPart ) { - int begPos = GetBegPos( iPart + 1 ); - if ( begPos != UNKNOWN ) - SetBegPos( iPart + 1, begPos + 1 ); + int begPos = GetBegPos( iPart ); + if ( begPos != UNKNOWN && begPos != EMPTY ) + SetBegPos( iPart, begPos + 1 ); } } } @@ -4018,7 +4121,8 @@ bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod // check that theObjectID is not just a part of a longer ID int afterEnd = beg + theObjectID.Length(); Standard_Character c = myString.Value( afterEnd ); - if ( !isalnum( c ) && c != ':' ) { + if ( !IsIDChar( c )) + { // check if accessor method already present if ( c != '.' || myString.Location( (char*) theAcsMethod, afterEnd, Length() ) != afterEnd+1) { @@ -4035,7 +4139,7 @@ bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod added = true; } } - beg = afterEnd; // is a part - next search + beg = afterEnd; // is a part -> next search } return added; } @@ -4110,7 +4214,8 @@ _pyID _pyObject::FatherID(const _pyID & childID) //================================================================================ /*! - * \brief SelfEraser erases creation command if no more it's commands invoked + * \brief SelfEraser erases creation command if none of it's commands invoked + * (e.g. filterManager) or it's not used as a command argument (e.g. a filter) */ //================================================================================ @@ -4123,11 +4228,12 @@ _pySelfEraser::_pySelfEraser(const Handle(_pyCommand)& theCreationCmd) //================================================================================ /*! - * \brief SelfEraser erases creation command if no more it's commands invoked + * \brief SelfEraser erases creation command if none of it's commands invoked + * (e.g. filterManager) or it's not used as a command argument (e.g. a filter) */ //================================================================================ -void _pySelfEraser::Flush() +bool _pySelfEraser::CanClear() { bool toErase = false; if ( myIgnoreOwnCalls ) // check if this obj is used as argument @@ -4135,23 +4241,58 @@ void _pySelfEraser::Flush() int nbArgUses = 0; list< Handle(_pyCommand) >::iterator cmd = myArgCmds.begin(); for ( ; cmd != myArgCmds.end(); ++cmd ) - nbArgUses += !(*cmd)->IsEmpty(); + nbArgUses += IsAliveCmd( *cmd ); + toErase = ( nbArgUses < 1 ); } else { - int nbCalls = GetNbCalls(); - if ( nbCalls > 0 ) - { - // ignore cleared commands - std::list< Handle(_pyCommand) >& cmds = GetProcessedCmds(); - std::list< Handle(_pyCommand) >::const_iterator cmd = cmds.begin(); - for ( ; cmd != cmds.end(); ++cmd ) - nbCalls -= (*cmd)->IsEmpty(); - } + int nbCalls = 0; + std::list< Handle(_pyCommand) >& cmds = GetProcessedCmds(); + std::list< Handle(_pyCommand) >::iterator cmd = cmds.begin(); + for ( ; cmd != cmds.end(); ) + // check of cmd emptiness is not enough as object can change + if (( *cmd )->GetString().Search( GetID() ) > 0 ) + ++nbCalls, ++cmd; + else + cmd = cmds.erase( cmd ); // save the cmd from clearing + toErase = ( nbCalls < 1 ); } - if ( toErase ) + return toErase; +} + +//================================================================================ +/*! + * \brief Check if a command is or can be cleared + */ +//================================================================================ + +bool _pySelfEraser::IsAliveCmd( const Handle(_pyCommand)& theCmd ) +{ + if ( theCmd->IsEmpty() ) + return false; + + if ( !theGen->IsToKeepAllCommands() ) + { + const _pyID& objID = theCmd->GetObject(); + Handle( _pyObject ) obj = theGen->FindObject( objID ); + if ( !obj.IsNull() ) + return !obj->CanClear(); + } + return true; +} + +//================================================================================ +/*! + * \brief SelfEraser erases creation command if none of it's commands invoked + * (e.g. filterManager) or it's not used as a command argument (e.g. a filter) + */ +//================================================================================ + +void _pySelfEraser::Flush() +{ + if ( CanClear() ) { myIsPublished = false; _pyObject::ClearCommands(); @@ -4164,11 +4305,12 @@ void _pySelfEraser::Flush() */ //================================================================================ -_pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd): +_pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd, bool toKeepAgrCmds): _pyObject(theCreationCmd) { myMesh = ObjectToMesh( theGen->FindObject( theCreationCmd->GetObject() )); - theGen->KeepAgrCmds( GetID() ); // ask to fill myArgCmds + if ( toKeepAgrCmds ) + theGen->KeepAgrCmds( GetID() ); // ask to fill myArgCmds } //================================================================================ @@ -4254,7 +4396,7 @@ void _pySubMesh::Flush() //================================================================================ _pyGroup::_pyGroup(const Handle(_pyCommand)& theCreationCmd, const _pyID & id) - :_pySubMesh(theCreationCmd) + :_pySubMesh(theCreationCmd, /*toKeepAgrCmds=*/false) { if ( !id.IsEmpty() ) setID( id ); @@ -4327,7 +4469,9 @@ bool _pyGroup::CanClear() if ( IsInStudy() ) return false; - if ( !myCanClearCreationCmd && myCreationCmd->GetMethod() == "GetGroups" ) + if ( !myCanClearCreationCmd && + !myCreationCmd.IsNull() && + myCreationCmd->GetMethod() == "GetGroups" ) { TCollection_AsciiString grIDs = myCreationCmd->GetResultValue(); list< _pyID > idList = myCreationCmd->GetStudyEntries( grIDs ); @@ -4413,6 +4557,7 @@ void _pyGroup::Process( const Handle(_pyCommand)& theCommand) makeGroupCmd->SetMethod( "MakeGroupByFilter" ); makeGroupCmd->SetArg( 1, name ); makeGroupCmd->SetArg( 2, idSource ); + filter->AddArgCmd( makeGroupCmd ); } } else if ( theCommand->GetMethod() == "SetFilter" ) @@ -4452,7 +4597,7 @@ void _pyGroup::Process( const Handle(_pyCommand)& theCommand) void _pyGroup::Flush() { if ( !theGen->IsToKeepAllCommands() && - myCreationCmd && !myCanClearCreationCmd ) + !myCreationCmd.IsNull() && !myCanClearCreationCmd ) { myCreationCmd.Nullify(); // this way myCreationCmd won't be cleared } @@ -4467,6 +4612,7 @@ void _pyGroup::Flush() _pyFilter::_pyFilter(const Handle(_pyCommand)& theCreationCmd, const _pyID& newID/*=""*/) :_pyObject(theCreationCmd), myNewID( newID ) { + //myIsPublished = true; // prevent clearing as a not published theGen->KeepAgrCmds( GetID() ); // ask to fill myArgCmds } @@ -4500,8 +4646,13 @@ void _pyFilter::Process( const Handle(_pyCommand)& theCommand) theCommand->SetObject( SMESH_2smeshpy::GenName() ); theCommand->SetMethod( "GetFilterFromCriteria" ); - // Clear aFilterManager.CreateFilter() + // Swap "aFilterManager.CreateFilter()" and "smesh.GetFilterFromCriteria(criteria)" GetCreationCmd()->Clear(); + GetCreationCmd()->GetString() = theCommand->GetString(); + theCommand->Clear(); + theCommand->AddDependantCmd( GetCreationCmd() ); + // why swap? -- it's needed + //GetCreationCmd()->Clear(); } else if ( theCommand->GetMethod() == "SetMesh" ) { @@ -4551,9 +4702,6 @@ void _pyFilter::Flush() bool _pyObject::CanClear() { - if ( !myIsPublished ) - return true; - list< Handle(_pyCommand) >::iterator cmd = myArgCmds.begin(); for ( ; cmd != myArgCmds.end(); ++cmd ) if ( !(*cmd)->IsEmpty() ) @@ -4562,8 +4710,7 @@ bool _pyObject::CanClear() if ( !obj.IsNull() && !obj->CanClear() ) return false; } - - return true; + return ( !myIsPublished ); } //================================================================================ @@ -4728,3 +4875,219 @@ _pyHypothesisReader::GetHypothesis(const _AString& hypType, } return resHyp; } + +//================================================================================ +/*! + * \brief Adds an object ID to some family of IDs with a common prefix + * \param [in] str - the object ID + * \return bool - \c false if \a str does not have the same prefix as \a this family + * (for internal usage) + */ +//================================================================================ + +bool _pyStringFamily::Add( const char* str ) +{ + if ( strncmp( str, _prefix.ToCString(), _prefix.Length() ) != 0 ) + return false; // expected prefix is missing + + str += _prefix.Length(); // skip _prefix + + // try to add to some of child falimies + std::list< _pyStringFamily >::iterator itSub = _subFams.begin(); + for ( ; itSub != _subFams.end(); ++itSub ) + if ( itSub->Add( str )) + return true; + + // no suitable family found - add str to _strings or create a new child family + + // look for a proper place within sorted _strings + std::list< _AString >::iterator itStr = _strings.begin(); + while ( itStr != _strings.end() && itStr->IsLess( str )) + ++itStr; + if ( itStr != _strings.end() && itStr->IsEqual( str )) + return true; // same ID already kept + + const int minPrefixSize = 4; + + // count "smaller" strings with the same prefix + std::list< _AString >::iterator itLess = itStr; --itLess; + int nbLess = 0; + for ( ; itLess != _strings.end(); --itLess ) + if ( strncmp( str, itLess->ToCString(), minPrefixSize ) == 0 ) + ++nbLess; + else + break; + ++itLess; + // count "greater" strings with the same prefix + std::list< _AString >::iterator itMore = itStr; + int nbMore = 0; + for ( ; itMore != _strings.end(); ++itMore ) + if ( strncmp( str, itMore->ToCString(), minPrefixSize ) == 0 ) + ++nbMore; + else + break; + --itMore; + if ( nbLess + nbMore > 1 ) // ------- ADD a NEW CHILD FAMILY ------------- + { + // look for a maximal prefix length + // int lessPrefSize = 3, morePrefSize = 3; + // if ( nbLess > 0 ) + // while( itLess->ToCString()[ lessPrefSize ] == str[ lessPrefSize ] ) + // ++lessPrefSize; + // if ( nbMore > 0 ) + // while ( itMore->ToCString()[ morePrefSize ] == str[ morePrefSize ] ) + // ++morePrefSize; + // int prefixSize = 3; + // if ( nbLess == 0 ) + // prefixSize = morePrefSize; + // else if ( nbMore == 0 ) + // prefixSize = lessPrefSize; + // else + // prefixSize = Min( lessPrefSize, morePrefSize ); + int prefixSize = minPrefixSize; + _AString newPrefix ( str, prefixSize ); + + // look for a proper place within _subFams sorted by _prefix + for ( itSub = _subFams.begin(); itSub != _subFams.end(); ++itSub ) + if ( !itSub->_prefix.IsLess( newPrefix )) + break; + + // add the new _pyStringFamily + itSub = _subFams.insert( itSub, _pyStringFamily()); + _pyStringFamily& newSubFam = *itSub; + newSubFam._prefix = newPrefix; + + // pass this->_strings to newSubFam._strings + for ( itStr = itLess; nbLess > 0; --nbLess, ++itStr ) + newSubFam._strings.push_back( itStr->ToCString() + prefixSize ); + newSubFam._strings.push_back( str + prefixSize ); + for ( ; nbMore > 0; --nbMore, ++itStr ) + newSubFam._strings.push_back( itStr->ToCString() + prefixSize ); + + _strings.erase( itLess, ++itMore ); + } + else // to few string to make a family fot them + { + _strings.insert( itStr, str ); + } + return true; +} + +//================================================================================ +/*! + * \brief Finds an object ID in the command + * \param [in] longStr - the command string + * \param [out] subStr - the found object ID + * \return bool - \c true if the object ID found + */ +//================================================================================ + +bool _pyStringFamily::IsInArgs( Handle( _pyCommand)& cmd, std::list<_AString>& subStr ) +{ + const _AString& longStr = cmd->GetString(); + const char* s = longStr.ToCString(); + + // look in _subFams + std::list< _pyStringFamily >::iterator itSub = _subFams.begin(); + int nbFound = 0, pos, len, from, argBeg = cmd->GetArgBeginning(); + if ( argBeg < 4 || argBeg > longStr.Length() ) + return false; + for ( ; itSub != _subFams.end(); ++itSub ) + { + from = argBeg; + while (( pos = longStr.Location( itSub->_prefix, from, longStr.Length() ))) + if (( len = itSub->isIn( s + pos-1 + itSub->_prefix.Length() )) >= 0 ) + { + subStr.push_back( _AString( s + pos-1, len + itSub->_prefix.Length() )); + from = pos + len + itSub->_prefix.Length(); + nbFound++; + } + else + { + from += itSub->_prefix.Length(); + } + } + // look among _strings + std::list< _AString >::iterator itStr = _strings.begin(); + for ( ; itStr != _strings.end(); ++itStr ) + if (( pos = longStr.Location( *itStr, argBeg, longStr.Length() ))) + // check that object ID does not continue after len + if ( !cmd->IsIDChar( s[ pos + itStr->Length() - 1 ] )) + { + subStr.push_back( *itStr ); + nbFound++; + } + return nbFound; +} + +//================================================================================ +/*! + * \brief Return remainder length of the object ID after my _prefix + * \param [in] str - remainder of the command after my _prefix + * \return int - length of the object ID or -1 if not found + */ +//================================================================================ + +int _pyStringFamily::isIn( const char* str ) +{ + std::list< _pyStringFamily >::iterator itSub = _subFams.begin(); + int len = -1; + for ( ; itSub != _subFams.end(); ++itSub ) + { + int cmp = strncmp( str, itSub->_prefix.ToCString(), itSub->_prefix.Length() ); + if ( cmp == 0 ) + { + if (( len = itSub->isIn( str + itSub->_prefix.Length() )) >= 0 ) + return itSub->_prefix.Length() + len; + } + else if ( cmp > 0 ) + break; + } + if ( !_strings.empty() ) + { + std::list< _AString >::iterator itStr = _strings.begin(); + bool firstEmpty = itStr->IsEmpty(); + if ( firstEmpty ) + ++itStr, len = 0; + for ( ; itStr != _strings.end(); ++itStr ) + { + int cmp = strncmp( str, itStr->ToCString(), itStr->Length() ); + if ( cmp == 0 ) + { + len = itStr->Length(); + break; + } + else if ( cmp < 0 ) + { + break; + } + } + + // check that object ID does not continue after len + if ( len >= 0 && _pyCommand::IsIDChar( str[len] )) + len = -1; + } + + return len; +} + +//================================================================================ +/*! + * \brief DEBUG + */ +//================================================================================ + +void _pyStringFamily::Print( int level ) +{ + cout << string( level, ' ' ) << "prefix = '" << _prefix << "' : "; + std::list< _AString >::iterator itStr = _strings.begin(); + for ( ; itStr != _strings.end(); ++itStr ) + cout << *itStr << " | "; + cout << endl; + std::list< _pyStringFamily >::iterator itSub = _subFams.begin(); + for ( ; itSub != _subFams.end(); ++itSub ) + itSub->Print( level + 1 ); + if ( level == 0 ) + cout << string( 70, '-' ) << endl; +} +