Salome HOME
Merge branch 'occ/shaper2smesh'
[modules/smesh.git] / src / SMESHGUI / SMESHGUI.cxx
index e9a49327cf09c6a2aaeb8494ba57d749b9d1add4..ba08d51011a880d5e2c693412a918a8823586cb7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2019  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
 #include "SMESHGUI_CopyMeshDlg.h"
 #include "SMESHGUI_CreatePolyhedralVolumeDlg.h"
 #include "SMESHGUI_DeleteGroupDlg.h"
+#include "SMESHGUI_DisplayEntitiesDlg.h"
 #include "SMESHGUI_Displayer.h"
 #include "SMESHGUI_DuplicateNodesDlg.h"
 #include "SMESHGUI_ExtrusionAlongPathDlg.h"
 #include "SMESHGUI_ExtrusionDlg.h"
+#include "SMESHGUI_FaceGroupsSeparatedByEdgesDlg.h"
 #include "SMESHGUI_FieldSelectorWdg.h"
 #include "SMESHGUI_FileInfoDlg.h"
 #include "SMESHGUI_FileValidator.h"
 #include "SMESHGUI_FilterDlg.h"
 #include "SMESHGUI_FilterLibraryDlg.h"
+#include "SMESHGUI_FilterUtils.h"
 #include "SMESHGUI_FindElemByPointDlg.h"
+#include "SMESHGUI_GEOMGenUtils.h"
 #include "SMESHGUI_GroupDlg.h"
 #include "SMESHGUI_GroupOnShapeDlg.h"
 #include "SMESHGUI_GroupOpDlg.h"
+#include "SMESHGUI_GroupUtils.h"
 #include "SMESHGUI_Hypotheses.h"
+#include "SMESHGUI_HypothesesUtils.h"
 #include "SMESHGUI_Make2DFrom3DOp.h"
 #include "SMESHGUI_MakeNodeAtPointDlg.h"
 #include "SMESHGUI_Measurements.h"
 #include "SMESHGUI_MeshOp.h"
 #include "SMESHGUI_MeshOrderOp.h"
 #include "SMESHGUI_MeshPatternDlg.h"
+#include "SMESHGUI_MeshUtils.h"
 #include "SMESHGUI_MultiEditDlg.h"
 #include "SMESHGUI_NodesDlg.h"
+#include "SMESHGUI_OffsetDlg.h"
 #include "SMESHGUI_Operations.h"
+#include "SMESHGUI_PatternUtils.h"
 #include "SMESHGUI_Preferences_ScalarBarDlg.h"
 #include "SMESHGUI_PropertiesDlg.h"
 #include "SMESHGUI_RemoveElementsDlg.h"
 #include "SMESHGUI_RevolutionDlg.h"
 #include "SMESHGUI_RotationDlg.h"
 #include "SMESHGUI_ScaleDlg.h"
-#include "SMESHGUI_OffsetDlg.h"
 #include "SMESHGUI_Selection.h"
 #include "SMESHGUI_SewingDlg.h"
 #include "SMESHGUI_SingleEditDlg.h"
 #include "SMESHGUI_SmoothingDlg.h"
+#include "SMESHGUI_SpinBox.h"
+#include "SMESHGUI_SplitBiQuad.h"
 #include "SMESHGUI_SymmetryDlg.h"
 #include "SMESHGUI_TranslationDlg.h"
 #include "SMESHGUI_TransparencyDlg.h"
-#include "SMESHGUI_DisplayEntitiesDlg.h"
-#include "SMESHGUI_SplitBiQuad.h"
-
-#include "SMESHGUI_FilterUtils.h"
-#include "SMESHGUI_GEOMGenUtils.h"
-#include "SMESHGUI_GroupUtils.h"
-#include "SMESHGUI_HypothesesUtils.h"
-#include "SMESHGUI_MeshUtils.h"
-#include "SMESHGUI_PatternUtils.h"
 #include "SMESHGUI_Utils.h"
 #include "SMESHGUI_VTKUtils.h"
 
 #include "SMESH_ActorUtils.h"
 #include "SMESH_Client.hxx"
 #include "SMESH_ScalarBarActor.h"
+#include <SMESH_Comment.hxx>
 #include "SMESH_TypeFilter.hxx"
 
 // SALOME GUI includes
-#include <SalomeApp_Application.h>
-#include <SalomeApp_CheckFileDlg.h>
-#include <SalomeApp_DataObject.h>
-#include <SalomeApp_Study.h>
-#include <SalomeApp_Tools.h>
-
 #include <LightApp_DataOwner.h>
 #include <LightApp_NameDlg.h>
 #include <LightApp_Preferences.h>
 #include <LightApp_SelectionMgr.h>
 #include <LightApp_UpdateFlags.h>
-
-#include <SVTK_ViewManager.h>
-#include <SVTK_ViewModel.h>
-#include <SVTK_ViewWindow.h>
-
-#include <VTKViewer_Algorithm.h>
-
+#include <QtxFontEdit.h>
+#include <QtxPopupMgr.h>
+#include <SALOME_ListIO.hxx>
 #include <SUIT_Desktop.h>
 #include <SUIT_FileDlg.h>
 #include <SUIT_MessageBox.h>
 #include <SUIT_OverrideCursor.h>
 #include <SUIT_ResourceMgr.h>
 #include <SUIT_Session.h>
-
-#include <QtxPopupMgr.h>
-#include <QtxFontEdit.h>
-
-#include <SALOME_ListIO.hxx>
+#include <SVTK_Renderer.h>
+#include <SVTK_ViewManager.h>
+#include <SVTK_ViewModel.h>
+#include <SVTK_ViewWindow.h>
+#include <SalomeApp_Application.h>
+#include <SalomeApp_CheckFileDlg.h>
+#include <SalomeApp_DataObject.h>
+#include <SalomeApp_Study.h>
+#include <SalomeApp_Tools.h>
+#include <VTKViewer_Algorithm.h>
 
 #ifndef DISABLE_PLOT2DVIEWER
 #include <SPlot2d_ViewModel.h>
 // Qt includes
 // #define       INCLUDE_MENUITEM_DEF // VSR commented ????????
 #include <QApplication>
+#include <QCheckBox>
+#include <QDialogButtonBox>
+#include <QLayout>
+#include <QListView>
 #include <QMenu>
 #include <QTextStream>
-#include <QListView>
 #include <QTreeView>
-#include <QCheckBox>
-#include <QLayout>
-#include <QDialogButtonBox>
 
 // BOOST includes
 #include <boost/shared_ptr.hpp>
 #include <SALOMEDS_Study.hxx>
 #include <SALOMEDS_SObject.hxx>
 #include "utilities.h"
+#include <SALOME_LifeCycleCORBA.hxx>
 
 // OCCT includes
 #include <Standard_ErrorHandler.hxx>
@@ -491,17 +489,11 @@ namespace
         QDialogButtonBox* btnbox = msgBox.findChild<QDialogButtonBox*>();
         lt->addWidget(&dontShowCheckBox, lt->rowCount(), lt->columnCount()-1, lt->rowCount(), lt->columnCount());
         lt->addWidget(btnbox, lt->rowCount(), 0, lt->rowCount(), lt->columnCount());
-        if(msgBox.exec() == QMessageBox::Ok)
-        {
-          if(dontShowCheckBox.checkState() == Qt::Checked)
-          {
-            if ( resMgr )
-              resMgr->setValue( "SMESH", "show_warning", false);
-          }
-          aCheckWarn = false;
-        }
-        else
+        if ( msgBox.exec() != QMessageBox::Ok )
           return;
+
+        if ( dontShowCheckBox.checkState() == Qt::Checked && resMgr )
+          resMgr->setValue( "SMESH", "show_warning", false);
       }
 
       QString aMeshName = anIObject->getName();
@@ -550,7 +542,7 @@ namespace
         }
       }
     }
-    
+
     // Warn the user about presence of not supported elements
     QString format;
     std::vector< SMESH::EntityType > notSupportedElemTypes, presentNotSupported;
@@ -655,7 +647,7 @@ namespace
     // Get parameters of export operation
 
     QString aFilename;
-    int aFormat =-1;         // for MED minor versions
+    int aFormat =-1;         // for MED version used for write
     bool isOkToWrite = true; // to check MED file version compatibility before adding a mesh in an existing file
 
     // Init the parameters with the default values
@@ -665,6 +657,7 @@ namespace
       toCreateGroups = resMgr->booleanValue( "SMESH", "auto_groups", false );
     bool toOverwrite  = true;
     bool toFindOutDim = true;
+    double       zTol = resMgr ? resMgr->doubleValue( "SMESH", "med_ztolerance", 0. ) : 0.;
 
     QString aFilter, aTitle = QObject::tr("SMESH_EXPORT_MESH");
     QString anInitialPath = "";
@@ -673,7 +666,7 @@ namespace
 
     QList< QPair< GEOM::ListOfFields_var, QString > > aFieldList;
 
-    // Get a file name to write in and additional otions
+    // Get a file name to write in and additional options
     if ( isUNV || isDAT || isGMF ) // Export w/o options
     {
       if ( isUNV )
@@ -744,36 +737,32 @@ namespace
     }
     else if ( isMED || isSAUV ) // Export to MED or SAUV
     {
+      int defaultVersion = 0;
       QMap<QString, int> aFilterMap;
       if ( isMED ) {
         //filters << QObject::tr( "MED_FILES_FILTER" ) + " (*.med)";
         //QString vmed (aMesh->GetVersionString(-1, 2));
-        //MESSAGE("MED version: " << vmed.toStdString());
         SMESH::long_array_var mvok = aMesh->GetMEDVersionsCompatibleForAppend();
-        for ( int i = 0; i < mvok->length(); ++i )
-          {
-            int versionInt = mvok[i];
-            std::ostringstream vss;
-            vss << versionInt/10;
-            vss << ".";
-            vss << versionInt%10;
-            QString vs = vss.str().c_str();
-            MESSAGE("MED version: " << vs.toStdString());
-            aFilterMap.insert( QObject::tr( "MED_VX_FILES_FILTER" ).arg( vs ) + " (*.med)",  i);
-          }
+        if ( mvok->length() > 0)
+          defaultVersion = mvok[0]; // the current version to set the default filter on it
+        for ( CORBA::ULong i = 0; i < mvok->length(); ++i )
+        {
+          QString vs = (char*)( SMESH_Comment( mvok[i]/10 ) << "." << mvok[i]%10 );
+          MESSAGE("MED version: " << vs.toStdString());
+          aFilterMap.insert( QObject::tr( "MED_VX_FILES_FILTER" ).arg( vs ) + " (*.med)",  mvok[i]);
+        }
       }
       else { // isSAUV
         aFilterMap.insert("All files (*)", -1 );
-        aFilterMap.insert("SAUV files (*.sauv)", 0 );
+        aFilterMap.insert("SAUV files (*.sauv)", defaultVersion ); // 0 = default filter (defaultVersion)
         aFilterMap.insert("SAUV files (*.sauve)", -1 );
       }
-
       QStringList filters;
       QMap<QString, int>::const_iterator it = aFilterMap.begin();
       QString aDefaultFilter = it.key();
       for ( ; it != aFilterMap.end(); ++it ) {
         filters.push_back( it.key() );
-        if (it.value() == 0) // explicit default for MED = current MED version
+        if (it.value() == defaultVersion) // explicit default for MED = current MED version
           aDefaultFilter = it.key();
       }
       QStringList checkBoxes;
@@ -784,6 +773,20 @@ namespace
       if ( fieldSelWdg->GetAllFields( aMeshList, aFieldList ))
         wdgList.append( fieldSelWdg );
 
+      QWidget*           zTolWdg = new QWidget();
+      QCheckBox*       zTolCheck = new QCheckBox( QObject::tr( "SMESH_ZTOLERANCE" ), zTolWdg );
+      SMESHGUI_SpinBox* zTolSpin = new SMESHGUI_SpinBox( zTolWdg );
+      QHBoxLayout*    zTolLayout = new QHBoxLayout( zTolWdg );
+      zTolLayout->addWidget( zTolCheck );
+      zTolLayout->addWidget( zTolSpin );
+      zTolLayout->setMargin( 0 );
+      zTolSpin->RangeStepAndValidator( 0, 1e+100, 1., "length_precision" );
+      zTolSpin->setValue( zTol );
+      QObject::connect( zTolCheck, SIGNAL( toggled(bool)), zTolSpin, SLOT( setEnabled(bool)));
+      zTolCheck->setChecked( resMgr->booleanValue( "SMESH", "enable_ztolerance", false ));
+      zTolSpin ->setEnabled( zTolCheck->isChecked() );
+      wdgList.append( zTolWdg );
+
       SalomeApp_CheckFileDlg* fd =
         new SalomeApp_CheckFileDlg ( SMESHGUI::desktop(), false, checkBoxes, true, true, wdgList );
       fd->setWindowTitle( aTitle );
@@ -794,8 +797,8 @@ namespace
       if ( !anInitialPath.isEmpty() )
         fd->setDirectory( anInitialPath );
       fd->selectFile(aMeshName);
-      
-      
+
+
       QListView *lview = fd->findChild<QListView*>("listView");
       if( lview ) {
         lview->setMinimumHeight(200);
@@ -809,8 +812,9 @@ namespace
       fd->setValidator( fv );
 
       bool is_ok = false;
-      while (!is_ok) {
-        MESSAGE("******* Loop on file dialog ***********");
+      while (!is_ok)
+      {
+        //MESSAGE("******* Loop on file dialog ***********");
         isOkToWrite =true;
         if ( fd->exec() )
           aFilename = fd->selectedFile();
@@ -819,13 +823,13 @@ namespace
           break;
         }
         aFormat = aFilterMap[fd->selectedNameFilter()];
-        MESSAGE("selected minor: " << aFormat << " file: " << aFilename.toUtf8().constData());
+        //MESSAGE("selected version: " << aFormat << " file: " << aFilename.toUtf8().constData());
         toOverwrite = fv->isOverwrite(aFilename);
-        MESSAGE("toOverwrite:" << toOverwrite);
+        //MESSAGE("toOverwrite:" << toOverwrite);
         is_ok = true;
         if ( !aFilename.isEmpty() ) {
           if( !toOverwrite ) {
-            // can't append to an existing using other format
+            // append is only possible if the existing file format is compatible
             bool isVersionOk = SMESHGUI::GetSMESHGen()->CheckWriteCompatibility( aFilename.toUtf8().constData() );
             MESSAGE("Append check, isVersionOk:" << isVersionOk);
             if ( !isVersionOk ) {
@@ -835,16 +839,16 @@ namespace
                                                   QObject::tr("SMESH_BUT_YES"),
                                                   QObject::tr("SMESH_BUT_NO"), 0, 1);
               if (aRet == 0)
-                {
-                  toOverwrite = true;
-                  MESSAGE("incompatible MED file version for add, overwrite accepted");
-                }
+              {
+                toOverwrite = true;
+                //MESSAGE("incompatible MED file version for add, overwrite accepted");
+              }
               else
-                {
-                  isOkToWrite = false;
-                  is_ok = false;
-                  MESSAGE("incompatible MED file version for add, overwrite refused");
-                }
+              {
+                isOkToWrite = false;
+                is_ok = false;
+                //MESSAGE("incompatible MED file version for add, overwrite refused");
+              }
             }
             QStringList aMeshNamesCollisionList;
             SMESH::string_array_var aMeshNames = SMESHGUI::GetSMESHGen()->GetMeshNames( aFilename.toUtf8().constData() );
@@ -858,7 +862,7 @@ namespace
                 }
               }
             }
-           if( !aMeshNamesCollisionList.isEmpty() ) {
+            if( !aMeshNamesCollisionList.isEmpty() ) {
               isOkToWrite = false;
               QString aMeshNamesCollisionString = aMeshNamesCollisionList.join( ", " );
               int aRet = SUIT_MessageBox::warning(SMESHGUI::desktop(),
@@ -867,8 +871,8 @@ namespace
                                                   QObject::tr("SMESH_BUT_YES"),
                                                   QObject::tr("SMESH_BUT_NO"),
                                                   QObject::tr("SMESH_BUT_CANCEL"), 0, 2);
-             MESSAGE("answer collision name " << aRet);
-             if (aRet == 0) {
+              MESSAGE("answer collision name " << aRet);
+              if (aRet == 0) {
                 toOverwrite = true;
                 isOkToWrite = true;
               }
@@ -878,12 +882,16 @@ namespace
           }
         }
       }
-      MESSAGE(" ****** end of file dialog loop, toOverwrite:" << toOverwrite << " isOkToWrite:" << isOkToWrite);
       toCreateGroups = fd->IsChecked(0);
       toFindOutDim   = fd->IsChecked(1);
+      zTol           = zTolCheck->isChecked() ? zTolSpin->value() : -1;
       fieldSelWdg->GetSelectedFields();
+      if ( resMgr ) resMgr->setValue( "SMESH", "enable_ztolerance", zTolCheck->isChecked() );
+
       if ( !fieldSelWdg->parent() )
         delete fieldSelWdg;
+      if ( !zTolWdg->parent() )
+        delete zTolWdg;
       delete fd;
     }
     else
@@ -902,12 +910,12 @@ namespace
 
       try {
         // Renumbering is not needed since SMDS redesign in V6.2.0 (Nov 2010)
-//         bool Renumber = false;
-//         // PAL 14172  : Check of we have to renumber or not from the preferences before export
-//         if (resMgr)
-//           Renumber= resMgr->booleanValue("renumbering");
-//         if (Renumber){
-//           SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
+        //         bool Renumber = false;
+        //         // PAL 14172  : Check of we have to renumber or not from the preferences before export
+        //         if (resMgr)
+        //           Renumber= resMgr->booleanValue("renumbering");
+        //         if (Renumber){
+        //           SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
 //           aMeshEditor->RenumberNodes();
 //           aMeshEditor->RenumberElements();
 //           if ( SMESHGUI::automaticUpdate() )
@@ -924,13 +932,14 @@ namespace
             const GEOM::ListOfFields&       fields = aFieldList[ aMeshIndex ].first.in();
             const QString&            geoAssFields = aFieldList[ aMeshIndex ].second;
             const bool                   hasFields = ( fields.length() || !geoAssFields.isEmpty() );
-            if ( !hasFields && aMeshOrGroup->_is_equivalent( aMeshItem ))
+            if ( !hasFields && aMeshOrGroup->_is_equivalent( aMeshItem ) && zTol < 0 )
               aMeshItem->ExportMED( aFilename.toUtf8().data(), toCreateGroups, aFormat,
                                     toOverwrite && aMeshIndex == 0, toFindOutDim );
             else
-              aMeshItem->ExportPartToMED( aMeshOrGroup, aFilename.toUtf8().data(), toCreateGroups, aFormat,
+              aMeshItem->ExportPartToMED( aMeshOrGroup, aFilename.toUtf8().data(),
+                                          toCreateGroups, aFormat,
                                           toOverwrite && aMeshIndex == 0, toFindOutDim,
-                                          fields, geoAssFields.toLatin1().data() );
+                                          fields, geoAssFields.toLatin1().data(), zTol );
           }
         }
         else if ( isSAUV )
@@ -986,7 +995,7 @@ namespace
         wc.suspend();
         SUIT_MessageBox::warning(SMESHGUI::desktop(),
                                  QObject::tr("SMESH_WRN_WARNING"),
-                                 QObject::tr("SMESH_EXPORT_FAILED"));
+                                 QObject::tr("SMESH_EXPORT_FAILED") + SalomeApp_Tools::ExceptionToString(S_ex));
         wc.resume();
       }
     }
@@ -1374,6 +1383,108 @@ namespace
     }
   }
 
+  // Break link with Shaper model
+  void breakShaperLink()
+  {
+    LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
+    SALOME_ListIO selected;
+    if (aSel) {
+      aSel->selectedObjects(selected);
+      if (selected.Extent()) {
+        Handle(SALOME_InteractiveObject) anIObject = selected.First();
+        _PTR(Study) aStudy = SMESH::getStudy();
+        std::string aEntry = anIObject->getEntry();
+        _PTR(SObject) aSObj = aStudy->FindObjectID(aEntry);
+        if (aSObj) {
+          std::string aName = aSObj->GetName();
+          QMessageBox::StandardButton aRes = SUIT_MessageBox::warning(SMESHGUI::desktop(),
+            QObject::tr("SMESH_WRN_WARNING"),
+            QObject::tr("MSG_BREAK_SHAPER_LINK").arg(aName.c_str()),
+            SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No);
+          if (aRes == SUIT_MessageBox::Yes) {
+            SUIT_DataOwnerPtrList aList;
+            aSel->selected(aList, "ObjectBrowser", true);
+            SUIT_DataOwner* aOwn = aList.first();
+            LightApp_DataOwner* sowner = dynamic_cast<LightApp_DataOwner*>(aOwn);
+            QString aREntry = sowner->entry();
+
+            static GEOM::GEOM_Gen_var geomGen;
+            if (CORBA::is_nil(geomGen)) {
+              SalomeApp_Application* app = dynamic_cast<SalomeApp_Application*>
+                (SUIT_Session::session()->activeApplication());
+              if (app) {
+                SALOME_LifeCycleCORBA* ls = new SALOME_LifeCycleCORBA(app->namingService());
+                Engines::EngineComponent_var comp =
+                  ls->FindOrLoad_Component("FactoryServer", "SHAPERSTUDY");
+                geomGen = GEOM::GEOM_Gen::_narrow(comp);
+              }
+            }
+            if (!CORBA::is_nil(geomGen))
+            {
+              geomGen->BreakLink(aREntry.toStdString().c_str());
+              SMESHGUI::GetSMESHGUI()->updateObjBrowser();
+
+              // remove actors whose objects are removed by BreakLink()
+              QList<SUIT_ViewWindow*> wndList = SMESHGUI::desktop()->windows();
+              SUIT_ViewWindow* wnd;
+              foreach(wnd, wndList)
+                SMESH::UpdateActorsAfterUpdateStudy(wnd);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  //================================================================================
+  /*!
+   * \brief Return true if a mesh icon == ICON_SMESH_TREE_GEOM_MODIF
+   * which means that the mesh can't be modified. It should be either re-computed
+   * or breakShaperLink()'ed. Warn the user about it.
+   */
+  //================================================================================
+
+  bool warnOnGeomModif()
+  {
+    SALOME_ListIO selected;
+    if ( LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr() )
+      aSel->selectedObjects(selected,"",/*convertReferences=*/false);
+
+    SALOME_ListIteratorOfListIO It( selected );
+    for ( ; It.More(); It.Next() )
+    {
+      Handle(SALOME_InteractiveObject) io = It.Value();
+      if ( !io->hasEntry() ) continue;
+      _PTR(SObject) so = SMESH::getStudy()->FindObjectID( io->getEntry() );
+      SMESH::SMESH_Mesh_var mesh;
+      while ( mesh->_is_nil() && so )
+      {
+        CORBA::Object_var obj = SMESH::SObjectToObject( so );
+        SMESH::SMESH_IDSource_var isrc = SMESH::SMESH_IDSource::_narrow( obj );
+        if ( isrc->_is_nil() )
+          so = so->GetFather();
+        else
+          mesh = isrc->GetMesh();
+      }
+      if ( mesh->_is_nil() ) continue;
+      so = SMESH::FindSObject( mesh );
+      if ( !so ) continue;
+      _PTR(GenericAttribute) attr;
+      so->FindAttribute( attr, "AttributePixMap" );
+      _PTR(AttributePixMap) pixmap = attr;
+      if ( !pixmap ) continue;
+
+      if ( pixmap->GetPixMap() == "ICON_SMESH_TREE_GEOM_MODIF" )
+      {
+        SUIT_MessageBox::warning(SMESHGUI::desktop(),
+                                 QObject::tr("SMESH_WRN_WARNING"),
+                                 QObject::tr("MSG_WARN_ON_GEOM_MODIF"));
+        return true;
+      }
+    }
+    return false;
+  }
+
   void SetDisplayMode(int theCommandID, VTK::MarkerMap& theMarkerMap)
   {
     SALOME_ListIO selected;
@@ -1488,7 +1599,7 @@ namespace
             presentEntities = presentEntities | SMESH_Actor::e0DElements;
           if ( !(presentEntities & SMESH_Actor::eBallElem) && anActor->GetObject()->GetNbEntities( SMDSAbs_Ball ) )
             presentEntities = presentEntities | SMESH_Actor::eBallElem;
-          
+
           // as we know that all types of elements are present, we can exit the loop
           if ( presentEntities == SMESH_Actor::eAllEntity )
             break;
@@ -1526,7 +1637,7 @@ namespace
         dlg.setShrinkCoef( int( shrinkCoef * 100. ) );
         // hide unused controls
         dlg.showControls( presentEntities, hasNodes );
-        
+
         if ( dlg.exec() ) {
           nodeColor        = dlg.nodeColor();
           markerType       = dlg.nodeMarkerType();
@@ -1560,7 +1671,7 @@ namespace
             if ( !IObject->hasEntry() ) continue;
             SMESH_Actor* anActor = SMESH::FindActorByEntry( IObject->getEntry() );
             if ( !anActor ) continue;
-            
+
             // nodes: color, marker
             anActor->SetNodeColor( nodeColor.redF(), nodeColor.greenF(), nodeColor.blueF() );
             if ( markerType != VTK::MT_USER ) {
@@ -1605,17 +1716,17 @@ namespace
                 aColor = nodeColor; break;
               case SMESH::EDGE:
                 aColor = edgeColor; break;
-              case SMESH::FACE: 
+              case SMESH::FACE:
                 aColor = faceColor; break;
               case SMESH::VOLUME:
                 aColor = volumeColor; break;
-              case SMESH::ELEM0D: 
+              case SMESH::ELEM0D:
                 aColor = elem0dColor; break;
-              case SMESH::BALL: 
+              case SMESH::BALL:
                 aColor = ballColor; break;
               default: break;
               }
-              
+
               if ( aColor.isValid() ) {
                 SALOMEDS::Color aGroupColor;
                 aGroupColor.R = aColor.redF();
@@ -1742,7 +1853,7 @@ namespace
                 int anEntitiesCount = anActor->GetNumberControlEntities();
                 if (anEntitiesCount >= 0)
                   functorName = functorName + ": " + QString::number(anEntitiesCount);
-                anActor->GetScalarBarActor()->SetTitle( functorName.toLatin1().constData() );
+                anActor->GetScalarBarActor()->SetTitle( functorName.toUtf8().constData() );
                 SMESH::RepaintCurrentView();
 #ifndef DISABLE_PLOT2DVIEWER
                 if ( anActor->GetPlot2Histogram() ) {
@@ -1840,7 +1951,7 @@ namespace
     v = qMax( uint(0), qMin ( v, size-1 ) );
     return v;
   }
-  
+
 } //namespace
 
 void SMESHGUI::OnEditDelete()
@@ -1854,6 +1965,7 @@ void SMESHGUI::OnEditDelete()
   _PTR(GenericAttribute) anAttr;
   _PTR(AttributeIOR) anIOR;
 
+  const int objectCountLimit = 30; // PAL23599
   int objectCount = 0;
   QString aNameList;
   QString aParentComponent = QString::null;
@@ -1863,29 +1975,33 @@ void SMESHGUI::OnEditDelete()
     Handle(SALOME_InteractiveObject) anIO = anIt.Value();
     if ( anIO.IsNull() ) continue;
     
-    QString father = "unknown";
+    QString father = "unknown", name;
 
     _PTR(SObject) aSO = aStudy->FindObjectID( anIO->getEntry() );
     if (aSO) {
       father = QString::fromStdString( aSO->GetFatherComponent()->ComponentDataType() );
       // check if object is reference
       _PTR(SObject) aRefSObj;
-      aNameList.append("\n    - ");
       if ( aSO->ReferencedObject( aRefSObj ) ) {
-        QString aRefName = QString::fromStdString ( aRefSObj->GetName() );
-        aNameList.append( aRefName );
+        name = QString::fromStdString ( aRefSObj->GetName() );
         father = QString::fromStdString ( aRefSObj->GetFatherComponent()->ComponentDataType() );
       }
       else
-        aNameList.append(anIO->getName());
+        name = anIO->getName();
       objectCount++;
     }
+    if ( objectCount < objectCountLimit ) { // avoid occupying the whole screen
+      aNameList.append("\n    - ");
+      aNameList.append( name );
+    }
 
     if( aParentComponent.isNull() )
       aParentComponent = father;
     else if( !aParentComponent.isEmpty() && aParentComponent!=father )
       aParentComponent = "";
   }
+  if ( objectCount >= objectCountLimit )
+    aNameList.append("\n    - ...");
 
   if ( objectCount == 0 )
     return; // No Valid Objects Selected
@@ -1907,8 +2023,8 @@ void SMESHGUI::OnEditDelete()
 
   SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
 
-  // Put the whole hierarchy of sub-objects of the selected SO's into a list and
-  // then treat them all starting from the deepest objects (at list back)
+  // Put one level of sub-objects of the selected SO's into a list
+  // in order to get objects inside folders like "Assigned Algorithms"
   std::list< _PTR(SObject) > listSO;
   SALOME_ListIteratorOfListIO It(selected);
   for( ; It.More(); It.Next()) // loop on selected IO's
@@ -1929,43 +2045,47 @@ void SMESHGUI::OnEditDelete()
         aSO = aRefSObject; // Delete main Object instead of reference
 
       listSO.push_back( aSO );
-      std::list< _PTR(SObject) >::iterator itSO = --listSO.end();
-      for ( ; itSO != listSO.end(); ++itSO ) {
-        _PTR(ChildIterator) it = aStudy->NewChildIterator( *itSO );
-        for (it->InitEx(false); it->More(); it->Next())
-          listSO.push_back( it->Value() );
-      }
+
+      _PTR(ChildIterator) it = aStudy->NewChildIterator( aSO );
+      for (it->InitEx(false); it->More(); it->Next())
+        listSO.push_back( it->Value() );
     }
   }
   // Check if none of objects to delete is referred from outside
   std::list< _PTR(SObject) >::reverse_iterator ritSO;
+  std::vector< _PTR(SObject) > subSO;
   for ( ritSO = listSO.rbegin(); ritSO != listSO.rend(); ++ritSO )
   {
     _PTR(SObject) SO = *ritSO;
     if ( !SO ) continue;
-    std::vector<_PTR(SObject)> aReferences = aStudy->FindDependances( *ritSO  );
-    for (size_t i = 0; i < aReferences.size(); i++) {
-      _PTR(SComponent) aComponent = aReferences[i]->GetFatherComponent();
-      std::string type = aComponent->ComponentDataType();
-      if ( type != "SMESH" )
-      {
-        SUIT_MessageBox::warning( anApp->desktop(),
-                                  QObject::tr("WRN_WARNING"),
-                                  QObject::tr("DEP_OBJECT") );
-        return; // outside SMESH, there is an object depending on a SMESH object
+
+    int nbChildren = SO->GetLastChildTag();
+    subSO.clear();
+    subSO.reserve( 1 + nbChildren );
+    subSO.push_back( SO );
+    if ( nbChildren > 0 )
+    {
+      _PTR(ChildIterator) it = aStudy->NewChildIterator( SO );
+      for ( it->InitEx( true ); it->More(); it->Next() )
+        subSO.push_back( it->Value() );
+    }
+    for ( size_t i = 0; i < subSO.size(); ++i )
+    {
+      std::vector<_PTR(SObject)> aReferences = aStudy->FindDependances( subSO[i] );
+      for ( size_t j = 0; j < aReferences.size(); j++ ) {
+        _PTR(SComponent) aComponent = aReferences[j]->GetFatherComponent();
+        std::string type = aComponent->ComponentDataType();
+        if ( type != "SMESH" )
+        {
+          SUIT_MessageBox::warning( anApp->desktop(),
+                                    QObject::tr("WRN_WARNING"),
+                                    QObject::tr("DEP_OBJECT") );
+          return; // outside SMESH, there is an object depending on a SMESH object
+        }
       }
     }
   }
 
-  // Call mesh->Clear() to prevent loading mesh from file caused by hypotheses removal
-  for( It.Initialize( selected ); It.More(); It.Next()) // loop on selected IO's
-  {
-    Handle(SALOME_InteractiveObject) IObject = It.Value();
-    SMESH::SMESH_Mesh_var mesh = SMESH::IObjectToInterface< SMESH::SMESH_Mesh >( IObject );
-    if ( !mesh->_is_nil() )
-      mesh->Clear();
-  }
-
   // Treat SO's in the list starting from the back
   aStudyBuilder->NewCommand();  // There is a transaction
   for ( ritSO = listSO.rbegin(); ritSO != listSO.rend(); ++ritSO )
@@ -1975,7 +2095,7 @@ void SMESHGUI::OnEditDelete()
     std::string anEntry = SO->GetID();
 
     /** Erase graphical object and remove all its data **/
-    if(SO->FindAttribute(anAttr, "AttributeIOR")) {
+    if ( SO->FindAttribute( anAttr, "AttributeIOR" )) {
       SMESH::RemoveVisualObjectWithActors( anEntry.c_str(), true);
     }
     /** Remove an object from data structures **/
@@ -2134,20 +2254,20 @@ bool SMESHGUI::automaticUpdate( SMESH::SMESH_IDSource_ptr theMesh,
   SMESH::long_array_var info = theMesh->GetMeshInfo();
   long nbOdElems = info[SMDSEntity_0D];
   long nbEdges   = info[SMDSEntity_Edge] + info[SMDSEntity_Quad_Edge];
-  long nbFaces   = info[SMDSEntity_Triangle]   + info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_BiQuad_Triangle] + 
-                   info[SMDSEntity_Quadrangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle] + 
+  long nbFaces   = info[SMDSEntity_Triangle]   + info[SMDSEntity_Quad_Triangle]   + info[SMDSEntity_BiQuad_Triangle] +
+                   info[SMDSEntity_Quadrangle] + info[SMDSEntity_Quad_Quadrangle] + info[SMDSEntity_BiQuad_Quadrangle] +
                    info[SMDSEntity_Polygon] + info[SMDSEntity_Quad_Polygon];
-  long nbVolumes = info[SMDSEntity_Tetra]   + info[SMDSEntity_Quad_Tetra] + 
-                   info[SMDSEntity_Hexa]    + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa] + 
-                   info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid] + 
+  long nbVolumes = info[SMDSEntity_Tetra]   + info[SMDSEntity_Quad_Tetra] +
+                   info[SMDSEntity_Hexa]    + info[SMDSEntity_Quad_Hexa] + info[SMDSEntity_TriQuad_Hexa] +
+                   info[SMDSEntity_Pyramid] + info[SMDSEntity_Quad_Pyramid] +
                    info[SMDSEntity_Penta]   + info[SMDSEntity_Quad_Penta] + info[SMDSEntity_BiQuad_Penta] +
-                   info[SMDSEntity_Polyhedra] + 
+                   info[SMDSEntity_Polyhedra] +
                    info[SMDSEntity_Hexagonal_Prism];
   long nbBalls   = info[SMDSEntity_Ball];
 
   long requestedSize = nbOdElems + nbBalls + nbEdges + nbFaces + nbVolumes;
   *nbElements = requestedSize;
-  
+
   *entities = SMESH_Actor::eAllEntity;
   *hidden   = 0;
 
@@ -2528,6 +2648,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
 #ifndef DISABLE_PLOT2DVIEWER
             SMESH::ProcessIn2DViewers(anActor,SMESH::RemoveFrom2dViewer);
 #endif
+            anActor->UpdateFilter();
           }
         }
       }
@@ -2714,6 +2835,10 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       else
         aSel->setSelectedObjects( to_process );
 
+      if ( vtkwnd && vtkwnd->GetRenderer() && !isStudyLocked() &&
+           ( theCommandID==SMESHOp::OpShow || theCommandID==SMESHOp::OpShowOnly ) )
+        vtkwnd->GetRenderer()->AdjustActors();
+
       break;
     }
 
@@ -2732,16 +2857,19 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
-  case SMESHOp::OpCreateMesh:
-  case SMESHOp::OpCreateSubMesh:
   case SMESHOp::OpEditMeshOrSubMesh:
   case SMESHOp::OpEditMesh:
   case SMESHOp::OpEditSubMesh:
+  case SMESHOp::OpMeshOrder:
+  case SMESHOp::OpCreateSubMesh:
+    if ( warnOnGeomModif() )
+      break; // action forbiden as geometry modified
+
+  case SMESHOp::OpCreateMesh:
   case SMESHOp::OpCompute:
   case SMESHOp::OpComputeSubMesh:
   case SMESHOp::OpPreCompute:
   case SMESHOp::OpEvaluate:
-  case SMESHOp::OpMeshOrder:
     startOperation( theCommandID );
     break;
   case SMESHOp::OpCopyMesh:
@@ -2770,6 +2898,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
 
       if ( isStudyLocked() )
         break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
 
       /*Standard_Boolean aRes;
       SMESH::SMESH_Mesh_var aMesh = SMESH::IObjectToInterface<SMESH::SMESH_Mesh>(IObject);
@@ -2800,6 +2930,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
 
       if ( isStudyLocked() )
         break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
 
       EmitSignalDeactivateDialog();
       SMESHGUI_MultiEditDlg* aDlg = NULL;
@@ -2818,6 +2950,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpSmoothing:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_SmoothingDlg( this ) )->show();
@@ -2830,6 +2964,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpExtrusion:
     {
       if (isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if (vtkwnd) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_ExtrusionDlg ( this ) )->show();
@@ -2841,6 +2977,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpExtrusionAlongAPath:
     {
       if (isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if (vtkwnd) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_ExtrusionAlongPathDlg( this ) )->show();
@@ -2852,6 +2990,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpRevolution:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_RevolutionDlg( this ) )->show();
@@ -2865,6 +3005,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     {
       if ( isStudyLocked() )
         break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd )
       {
         EmitSignalDeactivateDialog();
@@ -2881,6 +3023,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpReorientFaces:
   case SMESHOp::OpCreateGeometryGroup:
     {
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       startOperation( theCommandID );
       break;
     }
@@ -2893,6 +3037,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
 
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       EmitSignalDeactivateDialog();
       SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_nil();
 
@@ -2920,6 +3066,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
 
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       EmitSignalDeactivateDialog();
 
       LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
@@ -2997,6 +3145,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       }
 
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       EmitSignalDeactivateDialog();
 
       LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
@@ -3094,6 +3244,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
 
       if ( isStudyLocked() )
         break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
 
       EmitSignalDeactivateDialog();
 
@@ -3114,6 +3266,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     {
       if ( isStudyLocked() )
         break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
 
       EmitSignalDeactivateDialog();
       SMESHGUI_GroupOpDlg* aDlg = new SMESHGUI_DimGroupDlg( this );
@@ -3122,6 +3276,20 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
       break;
     }
 
+    case SMESHOp::OpFaceGroupsByEdges: // Create face groups separated by sharp edges
+    {
+      if ( isStudyLocked() )
+        break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
+
+      EmitSignalDeactivateDialog();
+      SMESHGUI_FaceGroupsSeparatedByEdgesDlg* aDlg = new SMESHGUI_FaceGroupsSeparatedByEdgesDlg( this );
+      aDlg->show();
+
+      break;
+    }
+
     case SMESHOp::OpDeleteGroup: // Delete groups with their contents
     {
       if ( !vtkwnd )
@@ -3153,7 +3321,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
         SALOME_ListIteratorOfListIO It( selected );
         for ( ; It.More(); It.Next() ) {
           SMESHGUI_MeshInfoDlg* dlg = new SMESHGUI_MeshInfoDlg( SMESHGUI::desktop(), page );
-          dlg->showInfo( It.Value() ); 
+          dlg->showInfo( It.Value() );
           dlg->show();
         }
       }
@@ -3173,6 +3341,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpEditHypothesis:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
 
       LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
       SALOME_ListIO selected;
@@ -3218,6 +3388,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpUnassign:                      // REMOVE HYPOTHESIS / ALGORITHMS
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       SUIT_OverrideCursor wc;
 
       LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr();
@@ -3249,6 +3421,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpHexagonalPrism:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         SMDSAbs_EntityType type = SMDSEntity_Edge;
@@ -3275,6 +3449,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpPolyhedron:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_CreatePolyhedralVolumeDlg( this ) )->show();
@@ -3298,6 +3474,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpTriQuadraticHexahedron:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         SMDSAbs_EntityType type = SMDSEntity_Last;
@@ -3329,6 +3507,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpRemoveNodes:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_RemoveNodesDlg( this ) )->show();
@@ -3342,6 +3522,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpRemoveElements:                                    // REMOVES ELEMENTS
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_RemoveElementsDlg( this ) )->show();
@@ -3356,6 +3538,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpClearMesh: {
 
     if(isStudyLocked()) break;
+    if ( warnOnGeomModif() )
+      break; // action forbiden as geometry modified
 
     SALOME_ListIO selected;
     if( LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr() )
@@ -3395,6 +3579,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpRemoveOrphanNodes:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       SALOME_ListIO selected;
       if( LightApp_SelectionMgr *aSel = SMESHGUI::selectionMgr() )
         aSel->selectedObjects( selected );
@@ -3434,6 +3620,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpRenumberingNodes:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_RenumberingDlg( this, 0 ) )->show();
@@ -3448,6 +3636,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpRenumberingElements:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_RenumberingDlg( this, 1 ) )->show();
@@ -3462,6 +3652,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpTranslation:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_TranslationDlg( this ) )->show();
@@ -3475,6 +3667,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpRotation:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_RotationDlg( this ) )->show();
@@ -3488,6 +3682,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpSymmetry:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if(vtkwnd) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_SymmetryDlg( this ) )->show();
@@ -3501,6 +3697,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpScale:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_ScaleDlg( this ) )->show();
@@ -3515,6 +3713,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpOffset:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_OffsetDlg( this ) )->show();
@@ -3529,6 +3729,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpSewing:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if(vtkwnd) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_SewingDlg( this ) )->show();
@@ -3542,6 +3744,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpMergeNodes:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if(vtkwnd) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_MergeDlg( this, 0 ) )->show();
@@ -3555,6 +3759,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpMergeElements:
     {
       if (isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if (vtkwnd) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_MergeDlg( this, 1 ) )->show();
@@ -3566,12 +3772,16 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     }
 
   case SMESHOp::OpMoveNode: // MAKE MESH PASS THROUGH POINT
+    if ( warnOnGeomModif() )
+      break; // action forbiden as geometry modified
     startOperation( SMESHOp::OpMoveNode );
     break;
 
   case SMESHOp::OpDuplicateNodes:
     {
       if(isStudyLocked()) break;
+      if ( warnOnGeomModif() )
+        break; // action forbiden as geometry modified
       if ( vtkwnd ) {
         EmitSignalDeactivateDialog();
         ( new SMESHGUI_DuplicateNodesDlg( this ) )->show();
@@ -3584,6 +3794,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     }
 
   case SMESHOp::OpElem0DOnElemNodes: // 0D_ON_ALL_NODES
+    if ( warnOnGeomModif() )
+      break; // action forbiden as geometry modified
     startOperation( SMESHOp::OpElem0DOnElemNodes );
     break;
 
@@ -3695,6 +3907,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpPropertiesVolume:
   case SMESHOp::OpMinimumDistance:
   case SMESHOp::OpBoundingBox:
+  case SMESHOp::OpAngle:
     {
       int page = SMESHGUI_MeasureDlg::MinDistance;
       if ( theCommandID == SMESHOp::OpBoundingBox )
@@ -3705,6 +3918,8 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
         page = SMESHGUI_MeasureDlg::Area;
       else if ( theCommandID == SMESHOp::OpPropertiesVolume )
         page = SMESHGUI_MeasureDlg::Volume;
+      else if ( theCommandID == SMESHOp::OpAngle )
+        page = SMESHGUI_MeasureDlg::Angle;
 
       EmitSignalDeactivateDialog();
       SMESHGUI_MeasureDlg* dlg = new SMESHGUI_MeasureDlg( SMESHGUI::desktop(), page );
@@ -3714,6 +3929,9 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
   case SMESHOp::OpSortChild:
     ::sortChildren();
     break;
+  case SMESHOp::OpBreakLink:
+    ::breakShaperLink();
+    break;
 
   }
 
@@ -3899,6 +4117,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createSMESHAction( SMESHOp::OpIntersectGroups,      "INT_GROUP",               "ICON_INTERSECT" );
   createSMESHAction( SMESHOp::OpCutGroups,            "CUT_GROUP",               "ICON_CUT" );
   createSMESHAction( SMESHOp::OpGroupUnderlyingElem,  "UNDERLYING_ELEMS",        "ICON_UNDERLYING_ELEMS" );
+  createSMESHAction( SMESHOp::OpFaceGroupsByEdges,    "FACE_GROUPS_BY_EDGES",    "ICON_FACE_GROUPS_BY_EDGES" );
   createSMESHAction( SMESHOp::OpAddElemGroupPopup,    "ADD_TO_GROUP" );
   createSMESHAction( SMESHOp::OpRemoveElemGroupPopup, "REMOVE_FROM_GROUP" );
   createSMESHAction( SMESHOp::OpDeleteGroup,          "DEL_GROUP",               "ICON_DEL_GROUP" );
@@ -4038,6 +4257,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createSMESHAction( SMESHOp::OpPropertiesLength, "MEASURE_LENGTH",   "ICON_MEASURE_LENGTH" );
   createSMESHAction( SMESHOp::OpPropertiesArea,   "MEASURE_AREA",     "ICON_MEASURE_AREA" );
   createSMESHAction( SMESHOp::OpPropertiesVolume, "MEASURE_VOLUME",   "ICON_MEASURE_VOLUME" );
+  createSMESHAction( SMESHOp::OpAngle,            "MEASURE_ANGLE",    "ICON_MEASURE_ANGLE" );
 
   createSMESHAction( SMESHOp::OpHide,     "HIDE", "ICON_HIDE" );
   createSMESHAction( SMESHOp::OpShow,     "SHOW", "ICON_SHOW" );
@@ -4045,6 +4265,8 @@ void SMESHGUI::initialize( CAM_Application* app )
 
   createSMESHAction( SMESHOp::OpSortChild, "SORT_CHILD_ITEMS" );
 
+  createSMESHAction( SMESHOp::OpBreakLink, "BREAK_SHAPER_LINK" );
+
   QList<int> aCtrlActions;
   aCtrlActions << SMESHOp::OpFreeNode << SMESHOp::OpEqualNode
                << SMESHOp::OpNodeConnectivityNb                                         // node controls
@@ -4136,6 +4358,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createMenu( SMESHOp::OpCutGroups,            meshId, -1 );
   createMenu( separator(),                     meshId, -1 );
   createMenu( SMESHOp::OpGroupUnderlyingElem,  meshId, -1 );
+  createMenu( SMESHOp::OpFaceGroupsByEdges,    meshId, -1 );
   createMenu( separator(),                     meshId, -1 );
   createMenu( SMESHOp::OpMeshInformation,      meshId, -1 );
   //createMenu( SMESHOp::OpStdInfo, meshId, -1 );
@@ -4244,6 +4467,7 @@ void SMESHGUI::initialize( CAM_Application* app )
 
   createMenu( SMESHOp::OpMinimumDistance,  measureId,   -1 );
   createMenu( SMESHOp::OpBoundingBox,      measureId,   -1 );
+  createMenu( SMESHOp::OpAngle,            measureId,   -1 );
   createMenu( SMESHOp::OpPropertiesLength, basicPropId, -1 );
   createMenu( SMESHOp::OpPropertiesArea,   basicPropId, -1 );
   createMenu( SMESHOp::OpPropertiesVolume, basicPropId, -1 );
@@ -4265,8 +4489,8 @@ void SMESHGUI::initialize( CAM_Application* app )
       addElemTb    = createTool( tr( "TB_ADD" ),       QString( "SMESHAddElementToolbar" ) ),
       addNonElemTb = createTool( tr( "TB_ADDNON" ),    QString( "SMESHAddElementToolbar" ) ),
       remTb        = createTool( tr( "TB_REM" ),       QString( "SMESHRemoveToolbar" ) ),
-    //renumbTb     = createTool( tr( "TB_RENUMBER" ),  QString( "SMESHRenumberingToolbar" ) ),  
-      transformTb  = createTool( tr( "TB_TRANSFORM" ), QString( "SMESHTransformationToolbar" ) ),  
+    //renumbTb     = createTool( tr( "TB_RENUMBER" ),  QString( "SMESHRenumberingToolbar" ) ),
+      transformTb  = createTool( tr( "TB_TRANSFORM" ), QString( "SMESHTransformationToolbar" ) ),
       modifyTb     = createTool( tr( "TB_MODIFY" ),    QString( "SMESHModificationToolbar" ) ),
       measuremTb   = createTool( tr( "TB_MEASUREM" ),  QString( "SMESHMeasurementsToolbar" ) ),
       dispModeTb   = createTool( tr( "TB_DISP_MODE" ), QString( "SMESHDisplayModeToolbar" ) );
@@ -4816,6 +5040,9 @@ void SMESHGUI::initialize( CAM_Application* app )
   popupMgr()->setRule( action( SMESHOp::OpSortChild ), "$component={'SMESH'} and client='ObjectBrowser' and isContainer and nbChildren>1", QtxPopupMgr::VisibleRule );
   popupMgr()->insert( separator(), -1, -1 );
 
+  popupMgr()->insert( action( SMESHOp::OpBreakLink), -1, -1 );
+  popupMgr()->setRule( action( SMESHOp::OpBreakLink), "$component={'SHAPERSTUDY'} and client='ObjectBrowser' and canBreakLink", QtxPopupMgr::VisibleRule );
+
   connect( application(), SIGNAL( viewManagerActivated( SUIT_ViewManager* ) ),
            this, SLOT( onViewManagerActivated( SUIT_ViewManager* ) ) );
 
@@ -4889,7 +5116,14 @@ bool SMESHGUI::activateModule( SUIT_Study* study )
     QList<SUIT_ViewWindow*> wndList = aDesk->windows();
     SUIT_ViewWindow* wnd;
     foreach ( wnd, wndList )
+    {
       connectView( wnd );
+
+      // remove actors whose objects are removed in GetSMESHGen()->UpdateStudy()
+      SMESH::UpdateActorsAfterUpdateStudy(wnd);
+
+      wnd->update();
+    }
   }
 
   Py_XDECREF(pluginsmanager);
@@ -4955,9 +5189,9 @@ void SMESHGUI::contextMenuPopup( const QString& client, QMenu* menu, QString& ti
     _PTR(Study) study = appStudy->studyDS();
     _PTR(SObject) obj = study->FindObjectID( io->getEntry() );
     if ( obj ) {
-      QString aName = QString( SMESH::fromUtf8(obj->GetName()) );
-      while ( aName.at( aName.length() - 1 ) == ' ' ) // Remove extraspaces in Name of Popup
-          aName.remove( (aName.length() - 1), 1 );
+      QString aName = SMESH::fromUtf8( obj->GetName());
+      while ( !aName.isEmpty() && aName.at( aName.length() - 1 ) == ' ' ) // Remove extraspaces in Name of Popup
+        aName.remove(( aName.length() - 1 ), 1 );
       title = aName;
     }
   }
@@ -5055,6 +5289,9 @@ void SMESHGUI::createPreferences()
 
   int dispgroup = addPreference( tr( "PREF_DISPLAY_MODE_GROUP" ), genTab );
   setPreferenceProperty( dispgroup, "columns", 2 );
+
+  addPreference( tr( "PREF_FITALL_ON_DISPLAYONLY" ), dispgroup, LightApp_Preferences::Bool, "SMESH", "fitall_on_displayonly" );
+  
   int dispmode = addPreference( tr( "PREF_DISPLAY_MODE" ), dispgroup, LightApp_Preferences::Selector, "SMESH", "display_mode" );
   QStringList modes;
   modes.append( tr("MEN_WIRE") );
@@ -5109,6 +5346,11 @@ void SMESHGUI::createPreferences()
   setPreferenceProperty( exportgroup, "columns", 2 );
   addPreference( tr( "PREF_AUTO_GROUPS" ), exportgroup, LightApp_Preferences::Bool, "SMESH", "auto_groups" );
   addPreference( tr( "PREF_SHOW_WARN" ), exportgroup, LightApp_Preferences::Bool, "SMESH", "show_warning" );
+  int zTol = addPreference( tr( "PREF_ZTOLERANCE" ), exportgroup, LightApp_Preferences::DblSpin, "SMESH", "med_ztolerance" );
+  setPreferenceProperty( zTol, "precision", 10 );
+  setPreferenceProperty( zTol, "min", 0.0000000001 );
+  setPreferenceProperty( zTol, "max", 1000000.0 );
+  setPreferenceProperty( zTol, "step", 1. );
   //addPreference( tr( "PREF_RENUMBER" ), exportgroup, LightApp_Preferences::Bool, "SMESH", "renumbering" );
 
   int computeGroup = addPreference( tr( "PREF_GROUP_COMPUTE" ), genTab );
@@ -5162,6 +5404,7 @@ void SMESHGUI::createPreferences()
                              "SMESH", "nb_segments_per_edge" );
   setPreferenceProperty( nbSeg, "min", 1 );
   setPreferenceProperty( nbSeg, "max", 10000000 );
+  addPreference( tr( "PREF_USE_MESHGEMS_HYPOSET" ), segGroup, LightApp_Preferences::Bool, "SMESH", "use-meshgems-hypo-sets" );
 
   int loadGroup = addPreference( tr( "SMESH_PREF_MESH_LOADING" ), genTab );
   addPreference( tr( "PREF_FORGET_MESH_AT_HYP_MODIF" ), loadGroup, LightApp_Preferences::Bool,
@@ -5297,7 +5540,7 @@ void SMESHGUI::createPreferences()
 
   int numGroup = addPreference( tr( "PREF_GROUP_NUMBERING" ), meshTab );
   setPreferenceProperty( numGroup, "columns", 2 );
-  
+
   addPreference( tr( "PREF_NUMBERING_NODE" ), numGroup, LightApp_Preferences::Color, "SMESH", "numbering_node_color" );
   addVtkFontPref( tr( "PREF_NUMBERING_FONT" ), numGroup, "numbering_node_font", true );
 
@@ -5435,13 +5678,13 @@ void SMESHGUI::preferencesChanged( const QString& sect, const QString& name )
     std::string aWarning;
     SUIT_ResourceMgr* aResourceMgr = SMESH::GetResourceMgr(this);
 
-    if ( name== "selection_object_color" ||
-         name=="selection_element_color" ||
-         name==        "highlight_color" ||
-         name=="selection_precision_node"    ||
-         name=="selection_precision_element" ||
-         name=="selection_precision_object"   ||
-        name=="selection_increment")
+    if ( name ==  "selection_object_color" ||
+         name == "selection_element_color" ||
+         name ==         "highlight_color" ||
+         name == "selection_precision_node"    ||
+         name == "selection_precision_element" ||
+         name == "selection_precision_object"  ||
+         name == "selection_increment")
     {
       SMESH::UpdateSelectionProp( this );
     }
@@ -5723,7 +5966,7 @@ const char* gPathSep   = "|"; // character used to separate paths
  * \brief Store visual parameters
  *
  * This method is called just before the study document is saved.
- * Store visual parameters in AttributeParameter attribue(s)
+ * Store visual parameters in AttributeParameter attribute(s)
  */
 void SMESHGUI::storeVisualParameters (int savePoint)
 {
@@ -6075,7 +6318,7 @@ typedef std::map<int, TPlaneInfoList> TPlaneInfoMap;
  * \brief Restore visual parameters
  *
  * This method is called after the study document is opened.
- * Restore visual parameters from AttributeParameter attribue(s)
+ * Restore visual parameters from AttributeParameter attribute(s)
  */
 void SMESHGUI::restoreVisualParameters (int savePoint)
 {
@@ -6189,7 +6432,7 @@ void SMESHGUI::restoreVisualParameters (int savePoint)
       aPlaneData.Mode = aPropertyValueList[0].toInt( &ok );
       if( !ok )
         continue;
-      
+
       ok = false;
       aPlaneData.isOpenGLClipping = aPropertyValueList[1].toInt( &ok );
       if( !ok )
@@ -6689,9 +6932,9 @@ void SMESHGUI::restoreVisualParameters (int savePoint)
             // Clipping
             else if (paramNameStr.startsWith("ClippingPlane")) {
               QStringList vals = val.split(gDigitsSep, QString::SkipEmptyParts);
-              // old format - val looks like "Off" or "1:0:0:0.5:0:0" 
+              // old format - val looks like "Off" or "1:0:0:0.5:0:0"
               // (mode(relative), is OpenGL clipping plane, orientation, distance, two angles)
-              // or "0:1:1:10.5:1.0:1.0:15.0:10.0:10.0" 
+              // or "0:1:1:10.5:1.0:1.0:15.0:10.0:10.0"
               // (mode(absolute), is OpenGL clipping plane, orientation, base point(x, y, z), direction (dx, dy, dz))
               // new format - val looks like "Off" or "0" (plane id)
               // (note: in new format "Off" value is used only for consistency,
@@ -6891,10 +7134,10 @@ void SMESHGUI::restoreVisualParameters (int savePoint)
           break;
         }
       }
-    
+
     }
   }
-  
+
 
   // update all VTK views
   QList<SUIT_ViewManager*> lst;
@@ -6910,7 +7153,7 @@ void SMESHGUI::restoreVisualParameters (int savePoint)
       while( vtkActor* aVTKActor = anAllActors->GetNextActor() )
         if( SMESH_Actor* anActor = SMESH_Actor::SafeDownCast( aVTKActor ) )
           anActor->SetOpenGLClippingPlane();
-      
+
       vtkView->getRenderer()->ResetCameraClippingRange();
       vtkView->Repaint();
     }
@@ -7029,7 +7272,7 @@ void SMESHGUI::message( const QString& msg )
         name = SMESH::fromUtf8(obj->GetName());
       if ( name.isEmpty() )
         return;
-      
+
       if ( data.last() == "stop" )
         application()->putInfo( tr( "MESH_LOADING_MSG_FINISHED" ).arg( name ) );
       else
@@ -7070,7 +7313,7 @@ bool SMESHGUI::renameAllowed( const QString& entry) const {
     return false;
 
   SalomeApp_DataObject* obj = dynamic_cast<SalomeApp_DataObject*>(appStudy->findObjectByEntry(entry));
-  
+
   if(!obj)
     return false;
 
@@ -7100,17 +7343,17 @@ bool SMESHGUI::renameObject( const QString& entry, const QString& name) {
   SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>( application() );
   if( !anApp )
     return false;
-    
+
   SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( anApp->activeStudy() );
 
   if(!appStudy)
     return false;
-  
+
   _PTR(Study) aStudy = appStudy->studyDS();
-  
+
   if(!aStudy)
     return false;
-  
+
   bool aLocked = (_PTR(AttributeStudyProperties)(appStudy->studyDS()->GetProperties()))->IsLocked();
   if ( aLocked ) {
     SUIT_MessageBox::warning ( anApp->desktop(), QObject::tr("WRN_WARNING"), QObject::tr("WRN_STUDY_LOCKED") );