Salome HOME
bos #29484 Merge branch 'vsr/29484'
[modules/geom.git] / src / GEOMBase / GEOMBase.cxx
index 2d0cd2bd7e7994914ea197f006dd23ea43452943..257bb3a1e312c2cd1d18da39c216769ac0c494cf 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -40,7 +40,6 @@
 #include <SOCC_Prs.h>
 
 #include <SALOME_ListIO.hxx>
-#include <SALOME_ListIteratorOfListIO.hxx>
 
 #include <SUIT_Desktop.h>
 #include <SUIT_Session.h>
@@ -115,8 +114,8 @@ TopoDS_Shape GEOMBase::GetTopoFromSelection( const SALOME_ListIO& IObjects )
       _PTR(SObject) obj( studyDS->FindObjectID( IO->getEntry() ) );
       _PTR(GenericAttribute) anAttr;
       if ( obj && obj->FindAttribute( anAttr, "AttributeIOR" ) ) {
-       _PTR(AttributeIOR) anIOR( anAttr );
-       shape = GetShapeFromIOR( anIOR->Value().c_str() );
+        _PTR(AttributeIOR) anIOR( anAttr );
+        shape = GetShapeFromIOR( anIOR->Value().c_str() );
       }
     }
   }
@@ -140,13 +139,13 @@ int GEOMBase::GetNameOfSelectedIObjects( const SALOME_ListIO& IObjects,
       Handle(SALOME_InteractiveObject) anIObj = IObjects.First();
       SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
       if ( anIObj->hasEntry() && study ) {
-       _PTR(Study) studyDS = study->studyDS();
-       _PTR(SObject) obj( studyDS->FindObjectID( anIObj->getEntry() ) );
-       _PTR(GenericAttribute) anAttr;
-       if ( obj && obj->FindAttribute( anAttr, "AttributeName" ) ) {
-         _PTR(AttributeName) aNameAttr ( anAttr );
-         name = aNameAttr->Value().c_str();
-       }
+        _PTR(Study) studyDS = study->studyDS();
+        _PTR(SObject) obj( studyDS->FindObjectID( anIObj->getEntry() ) );
+        _PTR(GenericAttribute) anAttr;
+        if ( obj && obj->FindAttribute( anAttr, "AttributeName" ) ) {
+          _PTR(AttributeName) aNameAttr ( anAttr );
+          name = aNameAttr->Value().c_str();
+        }
       }
     }
   }
@@ -176,88 +175,88 @@ QString GEOMBase::GetShapeTypeString(const TopoDS_Shape& shape)
     switch ( shape.ShapeType() ) {
     case TopAbs_COMPOUND:
       {
-       aTypeString = QObject::tr( "GEOM_COMPOUND" );
-       break;
+        aTypeString = QObject::tr( "GEOM_COMPOUND" );
+        break;
       }
     case TopAbs_COMPSOLID:
       {
-       aTypeString = QObject::tr( "GEOM_COMPOUNDSOLID" );
-       break;
+        aTypeString = QObject::tr( "GEOM_COMPOUNDSOLID" );
+        break;
       }
     case TopAbs_SOLID:
       {
-       aTypeString = QObject::tr( "GEOM_SOLID" );
-       break;
+        aTypeString = QObject::tr( "GEOM_SOLID" );
+        break;
       }
     case TopAbs_SHELL:
       {
-       aTypeString = QObject::tr( "GEOM_SHELL" );
-       break;
+        aTypeString = QObject::tr( "GEOM_SHELL" );
+        break;
       }
     case TopAbs_FACE:
       {
         BRepAdaptor_Surface surf( TopoDS::Face( shape ) );
-       switch ( surf.GetType() ) {
-       case GeomAbs_Plane:
-         {
-           aTypeString = QObject::tr( "GEOM_PLANE" );
-           break;
-         }
-       case GeomAbs_Cylinder:
-         {
-           aTypeString = QObject::tr( "GEOM_SURFCYLINDER" );
-           break;
-         }
-       case GeomAbs_Sphere:
-         {
-           aTypeString = QObject::tr( "GEOM_SURFSPHERE" );
-           break;
-         }
-       case GeomAbs_Torus:
-         {
-           aTypeString = QObject::tr( "GEOM_SURFTORUS" );
-           break;
-         }
-       case GeomAbs_Cone:
-         {
-           aTypeString = QObject::tr( "GEOM_SURFCONE" );
-           break;
-         }
-       default:
-         {
-           aTypeString = QObject::tr( "GEOM_FACE" );
-           break;
-         }
-       }
-       break;
+        switch ( surf.GetType() ) {
+        case GeomAbs_Plane:
+          {
+            aTypeString = QObject::tr( "GEOM_PLANE" );
+            break;
+          }
+        case GeomAbs_Cylinder:
+          {
+            aTypeString = QObject::tr( "GEOM_SURFCYLINDER" );
+            break;
+          }
+        case GeomAbs_Sphere:
+          {
+            aTypeString = QObject::tr( "GEOM_SURFSPHERE" );
+            break;
+          }
+        case GeomAbs_Torus:
+          {
+            aTypeString = QObject::tr( "GEOM_SURFTORUS" );
+            break;
+          }
+        case GeomAbs_Cone:
+          {
+            aTypeString = QObject::tr( "GEOM_SURFCONE" );
+            break;
+          }
+        default:
+          {
+            aTypeString = QObject::tr( "GEOM_FACE" );
+            break;
+          }
+        }
+        break;
       }
     case TopAbs_WIRE:
       {
         aTypeString = QObject::tr( "GEOM_WIRE" );
-       break;
+        break;
       }
     case TopAbs_EDGE:
       {
         BRepAdaptor_Curve curv( TopoDS::Edge( shape ) );
-       switch ( curv.GetType() ) {
-       case GeomAbs_Line:
-         {
-           aTypeString = ( qAbs( curv.FirstParameter() ) >= 1E6 || qAbs( curv.LastParameter() ) >= 1E6 ) ?
-             QObject::tr( "GEOM_LINE" ) : QObject::tr( "GEOM_EDGE" );
-           break;
-         }
-       case GeomAbs_Circle:
-         {
-           aTypeString = curv.IsClosed() ? QObject::tr( "GEOM_CIRCLE" ) : QObject::tr( "GEOM_ARC" );
-           break;
-         }
-       default:
-         {
-           aTypeString = QObject::tr( "GEOM_EDGE" );
-           break;
-         }
-       }
-       break;
+        switch ( curv.GetType() ) {
+        case GeomAbs_Line:
+          {
+            aTypeString = ( qAbs( curv.FirstParameter() ) >= 1E6 || qAbs( curv.LastParameter() ) >= 1E6 ) ?
+              QObject::tr( "GEOM_LINE" ) : QObject::tr( "GEOM_EDGE" );
+            break;
+          }
+        case GeomAbs_Circle:
+          {
+            aTypeString = curv.IsClosed() ? QObject::tr( "GEOM_CIRCLE" ) : QObject::tr( "GEOM_ARC" );
+            break;
+          }
+        default:
+          {
+            aTypeString = QObject::tr( "GEOM_EDGE" );
+            break;
+          }
+        }
+        break;
       }
     case TopAbs_VERTEX:
       {
@@ -271,7 +270,7 @@ QString GEOMBase::GetShapeTypeString(const TopoDS_Shape& shape)
       }
     default:
       {
-       break;
+        break;
       }
     }
   }
@@ -294,31 +293,29 @@ Handle(GEOM_AISShape) GEOMBase::ConvertIORinGEOMAISShape(const QString& IOR, boo
     if ( obj ) {
       QList<SUIT_ViewWindow*> views;
       if ( onlyInActiveView ) 
-       views.append( SUIT_Session::session()->activeApplication()->desktop()->activeWindow() );
+        views.append( SUIT_Session::session()->activeApplication()->desktop()->activeWindow() );
       else 
-       views = SUIT_Session::session()->activeApplication()->desktop()->windows();
+        views = SUIT_Session::session()->activeApplication()->desktop()->windows();
       foreach ( SUIT_ViewWindow* view, views ) {
-       if ( view && view->getViewManager()->getType() == OCCViewer_Viewer::Type() ) {
-         Handle(AIS_InteractiveContext) ic = ((OCCViewer_Viewer*)view->getViewManager()->getViewModel())->getAISContext();
-
-         AIS_ListOfInteractive displayed;
-         ic->DisplayedObjects( displayed );
-         ic->ObjectsInCollector( displayed );
-
-         AIS_ListIteratorOfListOfInteractive it( displayed );
-         while ( it.More() && shape.IsNull() ) {
-           if ( it.Value()->IsInstance( STANDARD_TYPE(GEOM_AISShape) ) ) {
-             Handle(GEOM_AISShape) sh = Handle(GEOM_AISShape)::DownCast( it.Value() );
-             if ( !sh.IsNull() && sh->hasIO() ) {
-               Handle(SALOME_InteractiveObject) IO = Handle(SALOME_InteractiveObject)::DownCast( sh->getIO() );
-               if ( !IO.IsNull() && IO->hasEntry() && obj->GetID() == IO->getEntry() )
-                 shape = sh;
-             }
-           }
-           it.Next();
-         }
-       }
-       if ( !shape.IsNull() ) break;
+        if ( view && view->getViewManager()->getType() == OCCViewer_Viewer::Type() ) {
+          Handle(AIS_InteractiveContext) ic = ((OCCViewer_Viewer*)view->getViewManager()->getViewModel())->getAISContext();
+
+          AIS_ListOfInteractive displayed;
+          ic->DisplayedObjects( displayed );
+          AIS_ListIteratorOfListOfInteractive it( displayed );
+          while ( it.More() && shape.IsNull() ) {
+            if ( it.Value()->IsInstance( STANDARD_TYPE(GEOM_AISShape) ) ) {
+              Handle(GEOM_AISShape) sh = Handle(GEOM_AISShape)::DownCast( it.Value() );
+              if ( !sh.IsNull() && sh->hasIO() ) {
+                Handle(SALOME_InteractiveObject) IO = sh->getIO();
+                if ( !IO.IsNull() && IO->hasEntry() && obj->GetID() == IO->getEntry() )
+                  shape = sh;
+              }
+            }
+            it.Next();
+          }
+        }
+        if ( !shape.IsNull() ) break;
       }
     }
   }
@@ -341,31 +338,31 @@ GEOM_Actor* GEOMBase::ConvertIORinGEOMActor(const QString& IOR, bool onlyInActiv
     if ( obj ) {
       QList<SUIT_ViewWindow*> views;
       if ( onlyInActiveView ) 
-       views.append( SUIT_Session::session()->activeApplication()->desktop()->activeWindow() );
+        views.append( SUIT_Session::session()->activeApplication()->desktop()->activeWindow() );
       else 
-       views = SUIT_Session::session()->activeApplication()->desktop()->windows();
+        views = SUIT_Session::session()->activeApplication()->desktop()->windows();
       foreach ( SUIT_ViewWindow* view, views ) {
-       if ( view && view->getViewManager()->getType() == SVTK_Viewer::Type() ) {
-         SVTK_ViewWindow* aVTKViewWindow = dynamic_cast<SVTK_ViewWindow*>( view );
-         if( !aVTKViewWindow )
-           continue;
-         vtkRenderer* Renderer = aVTKViewWindow->getRenderer();
-         vtkActorCollection* theActors = Renderer->GetActors();
-         theActors->InitTraversal();
-         vtkActor* a = theActors->GetNextActor();
-         while( a && !actor ) {
-           if ( a->IsA( "GEOM_Actor" ) ) {
-             GEOM_Actor* ga = GEOM_Actor::SafeDownCast( a );
-             if ( ga && ga->hasIO() ) {
-               Handle(SALOME_InteractiveObject) IO = Handle(SALOME_InteractiveObject)::DownCast( ga->getIO() );
-               if ( !IO.IsNull() && IO->hasEntry() && obj->GetID() == IO->getEntry() )
-                 actor = ga;
-             }
-           }
-           a = theActors->GetNextActor();
-         }
-       }
-       if ( actor ) break;
+        if ( view && view->getViewManager()->getType() == SVTK_Viewer::Type() ) {
+          SVTK_ViewWindow* aVTKViewWindow = dynamic_cast<SVTK_ViewWindow*>( view );
+          if( !aVTKViewWindow )
+            continue;
+          vtkRenderer* Renderer = aVTKViewWindow->getRenderer();
+          vtkActorCollection* theActors = Renderer->GetActors();
+          theActors->InitTraversal();
+          vtkActor* a = theActors->GetNextActor();
+          while( a && !actor ) {
+            if ( a->IsA( "GEOM_Actor" ) ) {
+              GEOM_Actor* ga = GEOM_Actor::SafeDownCast( a );
+              if ( ga && ga->hasIO() ) {
+                Handle(SALOME_InteractiveObject) IO = ga->getIO();
+                if ( !IO.IsNull() && IO->hasEntry() && obj->GetID() == IO->getEntry() )
+                  actor = ga;
+              }
+            }
+            a = theActors->GetNextActor();
+          }
+        }
+        if ( actor ) break;
       }
     }
   }
@@ -377,7 +374,7 @@ GEOM_Actor* GEOMBase::ConvertIORinGEOMActor(const QString& IOR, bool onlyInActiv
 // purpose  :
 //=======================================================================
 Handle(AIS_InteractiveObject) GEOMBase::GetAIS( const Handle(SALOME_InteractiveObject)& IO,
-                                                bool onlyInActiveView, bool onlyGeom )
+                                                bool onlyInActiveView, bool /*onlyGeom*/ )
 {
   Handle(AIS_InteractiveObject) aisObject;
 
@@ -453,12 +450,11 @@ GEOM::GEOM_Object_ptr GEOMBase::ConvertIOinGEOMObject( const Handle(SALOME_Inter
     SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
     if ( study ) {
       _PTR(Study) studyDS = study->studyDS();
-      _PTR(SObject) obj( studyDS->FindObjectID( IO->getEntry() ) );
-      if ( obj ) {
-        CORBA::Object_var corbaObj = GeometryGUI::ClientSObjectToObject( obj );
-        if ( !CORBA::is_nil( corbaObj ) )
+      _PTR(SObject)   obj = studyDS->FindObjectID( IO->getEntry() );
+      if ( GeometryGUI::IsInGeomComponent( obj )) {
+          CORBA::Object_var corbaObj = GeometryGUI::ClientSObjectToObject( obj );
           object = GEOM::GEOM_Object::_narrow( corbaObj );
-      }
+        }
     }
   }
   return object._retn();
@@ -492,7 +488,6 @@ void GEOMBase::ConvertListOfIOInListOfGO( const SALOME_ListIO& IObjects,
   }
 }
 
-
 //=================================================================================
 // function : CreateArrowForLinearEdge()
 // purpose  : Create a cone topology to be used to display an arrow in the middle
@@ -529,7 +524,7 @@ TopoDS_Shape GEOMBase::CreateArrowForLinearEdge( const TopoDS_Shape& shape )
         }
       }
     }
-    catch ( Standard_Failure ) {
+    catch ( Standard_Failure& ) {
       // OCC failures are hard to catch in GUI.
       // This is because of the position for #include <Standard_ErrorHandler.hxx> that is very critical to find
       // in SALOME environment : compilation error !
@@ -611,25 +606,25 @@ bool GEOMBase::SelectionByNameInDialogs( QWidget* widget, const QString& objectU
 
   if ( listSO.size() < 1 ) {
     SUIT_MessageBox::critical( widget, 
-                              QObject::tr( "GEOM_WRN_WARNING" ),
-                              QObject::tr( "GEOM_NAME_INCORRECT" ),
-                              QObject::tr( "GEOM_BUT_OK" ) );
+                               QObject::tr( "GEOM_WRN_WARNING" ),
+                               QObject::tr( "GEOM_NAME_INCORRECT" ),
+                               QObject::tr( "GEOM_BUT_OK" ) );
     return false;
   }
 
   /* More than one object with same name */
   if ( listSO.size() > 1 ) {
     SUIT_MessageBox::critical( widget,
-                              QObject::tr("GEOM_WRN_WARNING"),
-                              QObject::tr("GEOM_IDENTICAL_NAMES_SELECT_BY_MOUSE"),
-                              QObject::tr("GEOM_BUT_OK") );
+                               QObject::tr("GEOM_WRN_WARNING"),
+                               QObject::tr("GEOM_IDENTICAL_NAMES_SELECT_BY_MOUSE"),
+                               QObject::tr("GEOM_BUT_OK") );
     return false;
   }
 
   /* Create a SALOME_InteractiveObject with a SALOME::SObject */
   Handle(SALOME_InteractiveObject) IO = new SALOME_InteractiveObject( listSO[0]->GetID().c_str(),
-                                                                     "GEOM",
-                                                                     objectUserName.toLatin1().constData() );
+                                                                      "GEOM",
+                                                                      objectUserName.toUtf8().constData() );
 
   /* Add as a selected object       */
   /* Clear any previous selection : */
@@ -671,7 +666,7 @@ QString GEOMBase::GetDefaultName( const QString& operation, bool extractPrefix )
     if ( component ) {
       _PTR(ChildIterator) it( studyDS->NewChildIterator( component ) );
       for ( it->InitEx( true ); it->More(); it->Next() ) {
-       names.insert( it->Value()->GetName() );
+        names.insert( it->Value()->GetName() );
       }
     }
 
@@ -683,13 +678,13 @@ QString GEOMBase::GetDefaultName( const QString& operation, bool extractPrefix )
     if ( extractPrefix ) {
       QStringList parts = prefix.split( "_", QString::KeepEmptyParts );
       if ( parts.count() > 1 ) {
-       bool ok;
-       aNumber = parts.last().toLong( &ok );
-       if ( ok ) {
-         parts.removeLast();
-         prefix = parts.join( "_" );
-         aNumber--;
-       }
+        bool ok;
+        aNumber = parts.last().toLong( &ok );
+        if ( ok ) {
+          parts.removeLast();
+          prefix = parts.join( "_" );
+          aNumber--;
+        }
       }
     }
     
@@ -713,12 +708,12 @@ void GEOMBase::ShowErrorMessage( const QString& errorCode, const QString& commen
   if ( !errorCode.isEmpty() )
     text << QObject::tr( errorCode.toLatin1().constData() );
   if ( !comment.isEmpty() )
-    text << QObject::tr( comment.toLatin1().constData() );
+    text << QObject::tr( comment.toUtf8().constData() );
 
   SUIT_MessageBox::critical( SUIT_Session::session()->activeApplication()->desktop(),
-                            QObject::tr( "GEOM_ERROR" ),
+                             QObject::tr( "GEOM_ERROR" ),
                              text.join( "\n" ),
-                            QObject::tr( "GEOM_BUT_OK" ) );
+                             QObject::tr( "GEOM_BUT_OK" ) );
 }
 
 
@@ -750,7 +745,10 @@ bool GEOMBase::GetShape( GEOM::GEOM_Object_ptr object, TopoDS_Shape& shape, cons
   if ( !CORBA::is_nil( object ) ) {
     TopAbs_ShapeEnum stype = (TopAbs_ShapeEnum)( object->GetShapeType() );
     if ( type == TopAbs_SHAPE || type == stype )
-      shape = GEOM_Client::get_client().GetShape(  GeometryGUI::GetGeomGen(), object );
+    {
+      GEOM::GEOM_Gen_var gen = object->GetGen();
+      shape = GEOM_Client::get_client().GetShape( gen, object );
+    }
   }
   return !shape.IsNull();
 }
@@ -771,26 +769,26 @@ QString GEOMBase::GetName( GEOM::GEOM_Object_ptr object )
       _PTR(SObject) aSObj( study->studyDS()->FindObjectIOR( std::string( IOR.in() ) ) );
       _PTR(GenericAttribute) anAttr;
       if ( aSObj && aSObj->FindAttribute( anAttr, "AttributeName") ) {
-       _PTR(AttributeName) aNameAttr( anAttr );
-       name = aNameAttr->Value().c_str();
+        _PTR(AttributeName) aNameAttr( anAttr );
+        name = aNameAttr->Value().c_str();
       }
     }
     
     // 2. if object is not found in the study, try default name
     if ( name.isEmpty() ) {
       if ( object->IsMainShape() ) {
-       name = GetDefaultName( "geomObj" );
+        name = GetDefaultName( "geomObj" );
       }
       else {
-       GEOM::GEOM_Object_var mainShape = object->GetMainShape();
-       if ( !CORBA::is_nil( mainShape  ) ) { 
-         GEOM::ListOfLong_var indices = object->GetSubShapeIndices();
-         if ( indices->length() > 0 ) {
-           TopAbs_ShapeEnum type = (TopAbs_ShapeEnum)( object->GetShapeType() );
-           name = QString( "%1:%2_%3" ).arg( GetName( mainShape.in() ) )
-             .arg( TypeName( type ) ).arg( indices[0] );
-         }
-       }
+        GEOM::GEOM_Object_var mainShape = object->GetMainShape();
+        if ( !CORBA::is_nil( mainShape  ) ) { 
+          GEOM::ListOfLong_var indices = object->GetSubShapeIndices();
+          if ( indices->length() > 0 ) {
+            TopAbs_ShapeEnum type = (TopAbs_ShapeEnum)( object->GetShapeType() );
+            name = QString( "%1:%2_%3" ).arg( GetName( mainShape.in() ) )
+              .arg( TypeName( type ) ).arg( indices[0] );
+          }
+        }
       }
     }
   }
@@ -811,7 +809,7 @@ bool GEOMBase::IsShape( GEOM::GEOM_Object_ptr object )
 // function : TypeName()
 // purpose  : Get string representation for the shape type
 //=======================================================================
-QString GEOMBase::TypeName( TopAbs_ShapeEnum type )
+QString GEOMBase::TypeName( TopAbs_ShapeEnum type, bool capitalize )
 {
   QString name = "shape";
   switch( type ) {
@@ -834,6 +832,8 @@ QString GEOMBase::TypeName( TopAbs_ShapeEnum type )
   default:
     break;
   }
+  if ( capitalize && !name.isEmpty() )
+    name = name.left(1).toUpper() + name.mid(1);
   return name;
 }
 
@@ -860,7 +860,7 @@ QString GEOMBase::GetEntry( GEOM::GEOM_Object_ptr object )
 // Function : PublishSubObject
 // Purpose  : Publish sub-shape under the main object
 //================================================================
-void GEOMBase::PublishSubObject( GEOM::GEOM_Object_ptr object )
+void GEOMBase::PublishSubObject( GEOM::GEOM_Object_ptr object, const QString& name )
 {
   SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( SUIT_Session::session()->activeApplication()->activeStudy() );
   if ( study && !CORBA::is_nil( object ) ) {
@@ -869,9 +869,38 @@ void GEOMBase::PublishSubObject( GEOM::GEOM_Object_ptr object )
     GEOM::GEOM_Object_var father = object->GetMainShape();
     QString fatherEntry = GetEntry( father );
     if ( entry.isEmpty() && !CORBA::is_nil( father ) && !fatherEntry.isEmpty() ) {
-      QString name = GetName( object );
-      GeometryGUI::GetGeomGen()->AddInStudy( GeometryGUI::ClientStudyToStudy( studyDS ),
-                                            object, name.toLatin1().data(), father.in() );
+      QString aName = !name.isEmpty() ? name : GetName( object );
+      GeometryGUI::GetGeomGen()->AddInStudy( object, aName.toUtf8().data(), father.in() );
     }
   }
 }
+
+//================================================================
+// Function : synchronize
+// Purpose  : 
+//================================================================
+void GEOMBase::Synchronize( QList<GEOM::GeomObjPtr>& left, QList<GEOM::GeomObjPtr>& right )
+{
+  // 1. remove items from the "left" list that are not in the "right" list
+  QMutableListIterator<GEOM::GeomObjPtr> it1( left );
+  while ( it1.hasNext() ) {
+    GEOM::GeomObjPtr o1 = it1.next();
+    bool found = false;
+    QMutableListIterator<GEOM::GeomObjPtr> it2( right );
+    while ( it2.hasNext() && !found )
+      found = o1 == it2.next();
+    if ( !found )
+      it1.remove();
+  }
+  // 2. add items from the "right" list that are not in the "left" list (to keep selection order)
+  it1 = right;
+  while ( it1.hasNext() ) {
+    GEOM::GeomObjPtr o1 = it1.next();
+    bool found = false;
+    QMutableListIterator<GEOM::GeomObjPtr> it2( left );
+    while ( it2.hasNext() && !found )
+      found = o1 == it2.next();
+    if ( !found )
+      left << o1;
+  }
+}