]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
0023197: [CEA] Extract and rebuild: GUI
authorskv <skv@opencascade.com>
Fri, 13 Nov 2015 06:21:54 +0000 (09:21 +0300)
committerskv <skv@opencascade.com>
Fri, 13 Nov 2015 06:21:54 +0000 (09:21 +0300)
15 files changed:
idl/GEOM_Gen.idl
resources/CMakeLists.txt
resources/extract.png [new file with mode: 0644]
src/GEOMGUI/GEOM_images.ts
src/GEOMGUI/GEOM_msg_en.ts
src/GEOMGUI/GeometryGUI.cxx
src/GEOMGUI/GeometryGUI_Operations.h
src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
src/GEOMImpl/GEOMImpl_IShapesOperations.hxx
src/GEOM_I/GEOM_IShapesOperations_i.cc
src/GEOM_I/GEOM_IShapesOperations_i.hh
src/OperationGUI/CMakeLists.txt
src/OperationGUI/OperationGUI.cxx
src/OperationGUI/OperationGUI_ExtractionDlg.cxx [new file with mode: 0644]
src/OperationGUI/OperationGUI_ExtractionDlg.h [new file with mode: 0644]

index 830fcc3984dfdef42f54e5e4567a932a644e3a86..0c5a3a0b91a31dbae713de3a1cae04cf0be0ad24 100644 (file)
@@ -2778,6 +2778,43 @@ module GEOM
                                        in comparison_condition theCondition,
                                        in double               theTolerance);
 
+    /**
+     * This enumeration represents an extraction statistics type. It is used in
+     * the interface GEOM_IShapesOperations::MakeExtraction.
+     */
+    enum ExtractionStatType
+    {
+      EST_Removed,  ///< Removed sub-shapes
+      EST_Modified, ///< Modified sub-shapes
+      EST_Added     ///< Newly created sub-shapes
+    };
+
+    /*!
+     * This structure defines a format of extraction statistics. It is used in
+     * the interface GEOM_IShapesOperations::MakeExtraction.
+     */
+    struct ExtractionStat
+    {
+      ExtractionStatType type;    ///< Type of extraction statistics.
+      ListOfLong         indices; ///< Shape indices touched by this type of modification.
+    };
+
+    typedef sequence<ExtractionStat> ExtractionStats;
+
+    /*!
+     * \brief Return the shape that is constructed from theShape without
+     * extracted sub-shapes from the input list.
+     *
+     * \param theShape the original shape.
+     * \param theSubShapeIDs the list of sub-shape IDs to be extracted from
+     *        the original shape.
+     * \param theStats the operation statistics. Output parameter.
+     * \return the shape without extracted sub-shapes.
+     */
+    GEOM_Object MakeExtraction(in GEOM_Object      theShape,
+                               in ListOfLong       theSubShapeIDs,
+                               out ExtractionStats theStats);
+
   };
 
  // # GEOM_IBlocksOperations: 
index 3d47d93edc22f23ef4df2f7c95802f4b251a5e97..0aa42ed0b6674250e5dc77994d502a8788f05b64 100755 (executable)
@@ -94,6 +94,7 @@ SET( _res_files
   edgeextension.png
   erase.png
   eraseall.png
+  extract.png
   extruded_boss.png
   extruded_cut.png
   facetosurface.png
diff --git a/resources/extract.png b/resources/extract.png
new file mode 100644 (file)
index 0000000..528fe30
Binary files /dev/null and b/resources/extract.png differ
index cfcccd313b526d0aa9f64ae1c859f2be4c1d67d4..5ec53885f17fe68027b6959051bbd775acefc484 100644 (file)
             <source>ICO_TRANSFER_DATA</source>
             <translation>transfer_data.png</translation>
         </message>
+        <message>
+            <source>ICO_EXTRACTION</source>
+            <translation>extract.png</translation>
+        </message>
         <message>
             <source>ICO_IMPORT_SHAPE</source>
             <translation>import.png</translation>
             <source>ICON_DLG_TRANSFER_DATA</source>
             <translation>transfer_data.png</translation>
         </message>
+        <message>
+            <source>ICON_DLG_EXTRACTION</source>
+            <translation>extract.png</translation>
+        </message>
         <message>
             <source>ICON_DLG_SCALE_ALONG_AXES</source>
             <translation>scale_along_axes.png</translation>
index 2f225edbdfc22452eeecfecae315cd2c05525567..f24a3c42446cc6aed26ade3e57c1ff5c2645fa36 100644 (file)
@@ -471,6 +471,10 @@ Please, select face, shell or solid and try again</translation>
         <source>GEOM_COMPOUNDSOLID</source>
         <translation>CompSolid</translation>
     </message>
+    <message>
+        <source>GEOM_COMPSOLIDS</source>
+        <translation>CompSolids</translation>
+    </message>
     <message>
         <source>GEOM_COMPOUND_TITLE</source>
         <translation>Create A Compound</translation>
@@ -607,6 +611,10 @@ Please, select face, shell or solid and try again</translation>
         <source>GEOM_EDGE</source>
         <translation>Edge</translation>
     </message>
+    <message>
+        <source>GEOM_EDGES</source>
+        <translation>Edges</translation>
+    </message>
     <message>
         <source>GEOM_EDGE_TITLE</source>
         <translation>Create An Edge</translation>
@@ -2024,6 +2032,10 @@ Please, select face, shell or solid and try again</translation>
         <source>GEOM_SOLID</source>
         <translation>Solid</translation>
     </message>
+    <message>
+        <source>GEOM_SOLIDS</source>
+        <translation>Solids</translation>
+    </message>
     <message>
         <source>GEOM_SOLID_TITLE</source>
         <translation>Solid Construction</translation>
@@ -5228,6 +5240,18 @@ Please, select face, shell or solid and try again</translation>
         <source>STB_TRANSFER_DATA</source>
         <translation>Transfer Data</translation>
     </message>
+    <message>
+        <source>TOP_EXTRACTION</source>
+        <translation>Extract and Rebuild</translation>
+    </message>
+    <message>
+        <source>MEN_EXTRACTION</source>
+        <translation>Extract and Rebuild</translation>
+    </message>
+    <message>
+        <source>STB_EXTRACTION</source>
+        <translation>Extract and Rebuild</translation>
+    </message>
     <message>
         <source>TOP_EXTENSION</source>
         <translation>Extend Edge or Face</translation>
@@ -7621,4 +7645,55 @@ Do you want to create new material?</translation>
         <translation>Rotation angle</translation>
     </message>
 </context>
+<context>
+    <name>OperationGUI_ExtractionDlg</name>
+    <message>
+        <source>GEOM_EXTRACT_TITLE</source>
+        <translation>Extract and Rebuild</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_TYPE</source>
+        <translation>Extraction type</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_INPUT_PARAMS</source>
+        <translation>Input parameters</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_STATISTICS</source>
+        <translation>Statistics</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_SUB_SHAPE_TYPE</source>
+        <translation>Sub-shape type</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_FILTERED_SHAPES</source>
+        <translation>Filtered shapes</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_SHAPES_TO_EXTRACT</source>
+        <translation>Shapes to extract</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_REBUILD</source>
+        <translation>Rebuild</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_REMOVED</source>
+        <translation>Removed</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_MODIFIED</source>
+        <translation>Modified</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_ADDED</source>
+        <translation>Added</translation>
+    </message>
+    <message>
+        <source>GEOM_EXTRACT_NAME</source>
+        <translation>Extraction</translation>
+    </message>
+</context>
 </TS>
index 0d3f733a6bdea793139f3782842eb58bf3cb7b6f..47aeffbf8d88257676c1a8efb8d9ead0172f3863 100644 (file)
@@ -623,6 +623,7 @@ void GeometryGUI::OnGUIEvent( int id, const QVariant& theParam )
   case GEOMOp::OpExtrudedBoss:       // MENU OPERATION - EXTRUDED BOSS
   case GEOMOp::OpExtrudedCut:        // MENU OPERATION - EXTRUDED CUT
   case GEOMOp::OpTransferData:       // MENU OPERATION - TRANSFER DATA
+  case GEOMOp::OpExtraction:         // MENU OPERATION - EXTRACT AND REBUILD
     libName = "OperationGUI";
     break;
   case GEOMOp::OpSewing:             // MENU REPAIR - SEWING
@@ -1005,6 +1006,7 @@ void GeometryGUI::initialize( CAM_Application* app )
   createGeomAction( GEOMOp::OpShapesOnShape,  "GET_SHAPES_ON_SHAPE" );
   createGeomAction( GEOMOp::OpSharedShapes,   "GET_SHARED_SHAPES" );
   createGeomAction( GEOMOp::OpTransferData,   "TRANSFER_DATA" );
+  createGeomAction( GEOMOp::OpExtraction,     "EXTRACTION" );
   createGeomAction( GEOMOp::OpExtrudedCut,    "EXTRUDED_CUT" );
   createGeomAction( GEOMOp::OpExtrudedBoss,   "EXTRUDED_BOSS" );
   createGeomAction( GEOMOp::OpFillet1d,       "FILLET_1D" );
@@ -1262,6 +1264,7 @@ void GeometryGUI::initialize( CAM_Application* app )
   createMenu( GEOMOp::OpShapesOnShape, operId, -1 );
   createMenu( GEOMOp::OpSharedShapes,  operId, -1 );
   createMenu( GEOMOp::OpTransferData,  operId, -1 );
+  createMenu( GEOMOp::OpExtraction,    operId, -1 );
 
   createMenu( separator(), operId, -1 );
 
@@ -1438,6 +1441,7 @@ void GeometryGUI::initialize( CAM_Application* app )
   createTool( GEOMOp::OpShapesOnShape,   operTbId );
   createTool( GEOMOp::OpSharedShapes,    operTbId );
   createTool( GEOMOp::OpTransferData,    operTbId );
+  createTool( GEOMOp::OpExtraction,      operTbId );
 
   int featTbId = createTool( tr( "TOOL_FEATURES" ), QString( "GEOMModification" ) );
   createTool( GEOMOp::OpFillet1d,        featTbId );
index 480b7d2fd366ebfbc47dad62cb8f21043d09529d..a80c3d093f7508f8ed567ad33e116711026c5fb0 100644 (file)
@@ -166,6 +166,7 @@ namespace GEOMOp {
     OpExtrudedBoss        = 3709,   // MENU OPERATION - ETRUDED BOSS
     OpExtrudedCut         = 3710,   // MENU OPERATION - ETRUDED CUT
     OpTransferData        = 3711,   // MENU OPERATION - TRANSFER DATA
+    OpExtraction          = 3712,   // MENU OPERATION - EXTRACT AND REBUILD
     // RepairGUI -------------------//--------------------------------
     OpSewing              = 4000,   // MENU REPAIR - SEWING
     OpSuppressFaces       = 4001,   // MENU REPAIR - SUPPRESS FACES
index 3ed4513ecd8181068f80fe7d1710f8d0a9fd8d12..11bd57a44e752f21cc0941650d04ad11373c7648 100644 (file)
@@ -3162,6 +3162,23 @@ Handle(TColStd_HSequenceOfTransient)
   return aSeq;
 }
 
+//=============================================================================
+/*!
+ *  MakeExtraction
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeExtraction
+                     (const Handle(GEOM_Object)              &theShape,
+                      const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
+                      std::list<ExtractionStat>              &theStats)
+{
+  theStats.clear();
+
+  SetErrorCode(OK);
+
+  return theShape;
+}
+
 //=======================================================================
 //function : getShapesOnSurfaceIDs
   /*!
index d8e4f9fb21606071fd9146a6282c088ddf210850..38b3750594980dde91772029809faad269ed9ba9 100644 (file)
@@ -59,6 +59,25 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations
     All       = Groups | Fields | SubShapes,
   };
 
+  /**
+   * This enumeration represents an extraction statistics type.
+   */
+  enum ExtractionStatType
+  {
+    EST_Removed,  ///< Removed sub-shapes
+    EST_Modified, ///< Modified sub-shapes
+    EST_Added     ///< Newly created sub-shapes
+  };
+
+  /*!
+   * This structure defines a format of extraction statistics.
+   */
+  struct ExtractionStat
+  {
+    ExtractionStatType          type;    ///< Type of extraction statistics.
+    std::list<Standard_Integer> indices; ///< Shape indices touched by this type of modification.
+  };
+
   Standard_EXPORT GEOMImpl_IShapesOperations(GEOM_Engine* theEngine, int theDocID);
   Standard_EXPORT ~GEOMImpl_IShapesOperations();
 
@@ -470,6 +489,21 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations
                       const GEOMUtils::ComparisonCondition  theCondition,
                       const Standard_Real                   theTolerance);
 
+  /*!
+   * \brief Return the shape that is constructed from theShape without
+   * extracted sub-shapes from the input list.
+   *
+   * \param theShape the original shape.
+   * \param theSubShapeIDs the list of sub-shape IDs to be extracted from
+   *        the original shape.
+   * \param theStats the operation statistics. Output parameter.
+   * \return the shape without extracted sub-shapes.
+   */
+  Handle(GEOM_Object) MakeExtraction
+                     (const Handle(GEOM_Object)              &theShape,
+                      const Handle(TColStd_HArray1OfInteger) &theSubShapeIDs,
+                      std::list<ExtractionStat>              &theStats);
+
  private:
   Handle(GEOM_Object) MakeShape (std::list<Handle(GEOM_Object)>      theShapes,
                                  const Standard_Integer         theObjectType,
index 7561d9a168461e0fe90191c2214a5d216ddc28d9..3244013116237c76247abb2271b0f472e1b174a8 100644 (file)
@@ -2230,3 +2230,97 @@ GEOM::ListOfGO* GEOM_IShapesOperations_i::GetSubShapesWithTolerance
 
   return aSeq._retn();
 }
+
+//=============================================================================
+/*!
+ *  MakeExtraction
+ */
+//=============================================================================
+GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeExtraction
+         (GEOM::GEOM_Object_ptr                              theShape,
+          const GEOM::ListOfLong                            &theSubShapeIDs,
+          GEOM::GEOM_IShapesOperations::ExtractionStats_out  theStats)
+{
+  GEOM::GEOM_Object_var aGEOMObject;
+
+  //Set a not done flag
+  GetOperations()->SetNotDone();
+
+  //Get the reference object
+  Handle(GEOM_Object) aShape = GetObjectImpl(theShape);
+
+  if (aShape.IsNull()) {
+    return aGEOMObject._retn();
+  }
+
+  const int                        aNbIDs  = theSubShapeIDs.length();
+  int                              i;
+  Handle(TColStd_HArray1OfInteger) anArray =
+    new TColStd_HArray1OfInteger (1, aNbIDs);
+
+  for (i = 0; i < aNbIDs; i++) {
+    anArray->SetValue(i + 1, theSubShapeIDs[i]);
+  }
+
+  //Get Shapes in place of aShapeWhat
+  std::list<GEOMImpl_IShapesOperations::ExtractionStat> aStats;
+  Handle(GEOM_Object)                                   aResult =
+          GetOperations()->MakeExtraction(aShape, anArray, aStats);
+
+  if (!GetOperations()->IsDone() || aResult.IsNull()) {
+    return aGEOMObject._retn();
+  }
+
+  // Convert statistics.
+  GEOM::GEOM_IShapesOperations::ExtractionStats_var aResStats =
+                       new GEOM::GEOM_IShapesOperations::ExtractionStats;
+  const int                                         aNbStats  = aStats.size();
+
+  aResStats->length(aNbStats);
+
+  // fill the local CORBA array with values from lists
+  std::list<GEOMImpl_IShapesOperations::ExtractionStat>::const_iterator
+    anIt = aStats.begin();
+
+  for (i = 0; anIt != aStats.end(); i++, anIt++) {
+    GEOM::GEOM_IShapesOperations::ExtractionStat_var aResStat =
+      new GEOM::GEOM_IShapesOperations::ExtractionStat;
+
+    // Copy type
+    switch (anIt->type) {
+    case GEOMImpl_IShapesOperations::EST_Removed:
+      aResStat->type = GEOM::GEOM_IShapesOperations::EST_Removed;
+      break;
+    case GEOMImpl_IShapesOperations::EST_Modified:
+      aResStat->type = GEOM::GEOM_IShapesOperations::EST_Modified;
+      break;
+    case GEOMImpl_IShapesOperations::EST_Added:
+      aResStat->type = GEOM::GEOM_IShapesOperations::EST_Added;
+      break;
+    default:
+      break;
+    }
+
+    // Copy the list of IDs
+    std::list<Standard_Integer> aIDList    = anIt->indices;
+    GEOM::ListOfLong_var        aResIDList = new GEOM::ListOfLong;
+
+    aResIDList->length(aIDList.size());
+
+    std::list<Standard_Integer>::iterator anIDIt = aIDList.begin();
+    int j = 0;
+
+    for (; anIDIt != aIDList.end(); j++, anIDIt++) {
+      aResIDList[j] = *anIDIt;
+    }
+
+    aResStat->indices = aResIDList;
+
+    aResStats[i] = aResStat;
+  }
+
+  // initialize out-parameter with local array
+  theStats = aResStats._retn();
+
+  return GetObject(aResult);
+}
index 0f36a38c3934aea05221cb243be714a0b59c1fd2..ff9e417f00c0582750f675fd19dcbacdd6c1360e 100644 (file)
@@ -306,6 +306,11 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i :
                       GEOM::comparison_condition theCondition,
                       CORBA::Double              theTolerance);
 
+  GEOM::GEOM_Object_ptr MakeExtraction
+         (GEOM::GEOM_Object_ptr                              theShape,
+          const GEOM::ListOfLong                            &theSubShapeIDs,
+          GEOM::GEOM_IShapesOperations::ExtractionStats_out  theStats);
+
   ::GEOMImpl_IShapesOperations* GetOperations()
   { return (::GEOMImpl_IShapesOperations*)GetImpl(); }
 };
index 4fa28ace00c1a105ae30669dbfc143dcf7eb7f99..b32dd2d0e11aa944063bb6d0a80da10e02132b23 100755 (executable)
@@ -74,6 +74,7 @@ SET(OperationGUI_HEADERS
   OperationGUI_ChamferDlg.h
   OperationGUI_GetShapesOnShapeDlg.h
   OperationGUI_GetSharedShapesDlg.h
+  OperationGUI_ExtractionDlg.h
   OperationGUI_ExtrudedFeatureDlg.h
   OperationGUI_ClippingDlg.h
   OperationGUI_TransferDataDlg.h
@@ -88,6 +89,7 @@ SET(_moc_HEADERS
   OperationGUI_ChamferDlg.h
   OperationGUI_GetShapesOnShapeDlg.h
   OperationGUI_GetSharedShapesDlg.h
+  OperationGUI_ExtractionDlg.h
   OperationGUI_ExtrudedFeatureDlg.h
   OperationGUI_ClippingDlg.h
   OperationGUI_TransferDataDlg.h
@@ -110,6 +112,7 @@ SET(OperationGUI_SOURCES
   OperationGUI_FilletDlg.cxx
   OperationGUI_Fillet1d2dDlg.cxx
   OperationGUI_ChamferDlg.cxx
+  OperationGUI_ExtractionDlg.cxx
   OperationGUI_ExtrudedFeatureDlg.cxx
   OperationGUI_ClippingDlg.cxx
   OperationGUI_TransferDataDlg.cxx
index 3288921ab0614df4ad1bad908021825c36de5197..96e5fc57a617dffb237887c9db28bbc3f1bf2082 100644 (file)
@@ -40,6 +40,7 @@
 #include "OperationGUI_GetSharedShapesDlg.h"
 #include "OperationGUI_ExtrudedFeatureDlg.h" // Methods EXTRUDED BOSS / CUT
 #include "OperationGUI_TransferDataDlg.h"
+#include "OperationGUI_ExtractionDlg.h"
 
 //=======================================================================
 // function : OperationGUI()
@@ -83,6 +84,7 @@ bool OperationGUI::OnGUIEvent (int theCommandID, SUIT_Desktop* parent)
   case GEOMOp::OpFillet1d:      (new OperationGUI_Fillet1d2dDlg      (getGeometryGUI(), parent, true))->show(); break;
   case GEOMOp::OpFillet2d:      (new OperationGUI_Fillet1d2dDlg      (getGeometryGUI(), parent, false))->show(); break;
   case GEOMOp::OpTransferData:  (new OperationGUI_TransferDataDlg    (getGeometryGUI(), parent))->show(); break;
+  case GEOMOp::OpExtraction:    (new OperationGUI_ExtractionDlg      (getGeometryGUI(), parent))->show(); break;
   default:
     app->putInfo(tr("GEOM_PRP_COMMAND").arg(theCommandID));
   }
diff --git a/src/OperationGUI/OperationGUI_ExtractionDlg.cxx b/src/OperationGUI/OperationGUI_ExtractionDlg.cxx
new file mode 100644 (file)
index 0000000..6885ff7
--- /dev/null
@@ -0,0 +1,1322 @@
+// Copyright (C) 2007-2015  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
+//
+// 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, 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
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "OperationGUI_ExtractionDlg.h"
+
+#include <GEOMBase.h>
+#include <GeometryGUI.h>
+
+#include <LightApp_SelectionMgr.h>
+#include <SalomeApp_Application.h>
+#include <SalomeApp_Tools.h>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
+
+#include <TColStd_MapIteratorOfMapOfInteger.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+
+#include <QComboBox>
+#include <QGridLayout>
+#include <QGroupBox>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QListWidget>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QTreeWidget>
+#include <QVBoxLayout>
+#include <QtGlobal>
+
+#if QT_VERSION >= 0x050300
+  #include <QSignalBlocker>
+#else
+  /**
+   * This class is named as QT class as it is introduced since Qt 5.3.
+   * It should not be compiled when Salome is ported on Qt 5.3.
+   */
+  class QSignalBlocker
+  {
+  public:
+    QSignalBlocker(QObject *object)
+      : myObject    (object),
+        myIsBlocked (object && object->signalsBlocked()) {
+      if (myObject) {
+        myObject->blockSignals(true);
+      }
+    }
+
+    ~QSignalBlocker() {
+      if (myObject) {
+        myObject->blockSignals(myIsBlocked);
+      }
+    }
+
+  private:
+    QObject *myObject;    ///< Blocked object.
+    bool     myIsBlocked; ///< Initial blocked state.
+  };
+#endif
+
+
+#define ID_ROLE   Qt::DisplayRole
+#define TYPE_ROLE Qt::UserRole
+
+static const char* const TMP_STR = "TEMP";
+
+static const char* const SINGLE_SHAPE_TYPE_TR_CODES [] = {
+  "GEOM_COMPOUND",
+  "GEOM_COMPOUNDSOLID",
+  "GEOM_SOLID",
+  "GEOM_SHELL",
+  "GEOM_FACE",
+  "GEOM_WIRE",
+  "GEOM_EDGE",
+  "GEOM_VERTEX"
+};
+
+static const char* const PLURAL_SHAPE_TYPE_TR_CODES [] = {
+  "GEOM_COMPOUND",   // Not used
+  "GEOM_COMPSOLIDS",
+  "GEOM_SOLIDS",
+  "GEOM_SHELLS",
+  "GEOM_FACES",
+  "GEOM_WIREZ",
+  "GEOM_EDGES",
+  "GEOM_VERTEXES"
+};
+
+
+/**
+ * This static function creates a new list widget item with given ID and
+ * returns it.
+ *
+ * \param theID the item ID.
+ * \param theListWidget the list widget.
+ * \return the created list widget item.
+ */
+static QListWidgetItem *addNewItem(const int    theID,
+                                   QListWidget *theListWidget)
+{
+  QListWidgetItem *aResult = new QListWidgetItem;
+
+  aResult->setData(ID_ROLE, theID);
+  theListWidget->addItem(aResult);
+
+  return aResult;
+}
+
+/**
+ * This static function creates a new tree widget item as a child of the input
+ * one with given ID and returns it.
+ *
+ * \param theID the item ID.
+ * \param theParentItem the parent item.
+ * \return the created tree widget item.
+ */
+static QTreeWidgetItem *addChildItem(const int        theID,
+                                     QTreeWidgetItem *theParentItem)
+{
+  QTreeWidgetItem *aResult = new QTreeWidgetItem;
+
+  aResult->setData(0, ID_ROLE, theID);
+  theParentItem->addChild(aResult);
+
+  return aResult;
+}
+
+/**
+ * This static function returns the maximal shape type of sub-shapes stored in
+ * the input compound. If it is not a compound, it returns TopAbs_SHAPE.
+ *
+ * \param theCompound the compound.
+ * \return the maximal shape type of sub-shapes stored in the input compound.
+ */
+static TopAbs_ShapeEnum GetMaxShapeTypeInComp(const TopoDS_Shape &theCompound)
+{
+  TopAbs_ShapeEnum aResult = TopAbs_SHAPE;
+
+  if (theCompound.IsNull() || theCompound.ShapeType() != TopAbs_COMPOUND) {
+    return aResult;
+  }
+
+  TopoDS_Iterator anIt(theCompound, Standard_False, Standard_False);
+
+  for (; anIt.More(); anIt.Next()) {
+    const TopoDS_Shape &aSubShape = anIt.Value();
+
+    if (aSubShape.IsNull()) {
+      continue;
+    }
+
+    // Get the sub-shape type.
+    TopAbs_ShapeEnum aSubType = aSubShape.ShapeType();
+
+    if (aSubType == TopAbs_COMPOUND) {
+      aSubType = GetMaxShapeTypeInComp(aSubShape);
+    }
+
+    if (aSubType == TopAbs_SHAPE) {
+      continue;
+    }
+
+    if (aResult == TopAbs_SHAPE) {
+      // This is an initialization.
+      aResult = aSubType;
+    } else if (aResult > aSubType) {
+      aResult = aSubType;
+    }
+  }
+
+  return aResult;
+}
+
+//=================================================================================
+// class    : OperationGUI_ExtractionDlg()
+// purpose  : 
+//=================================================================================
+OperationGUI_ExtractionDlg::OperationGUI_ExtractionDlg
+                        (GeometryGUI* GUI, QWidget* parent)
+  : GEOMBase_Skeleton (GUI, parent, false),
+    mySelBtn          (0),
+    myMainShapeEdit   (0),
+    mySubShTypeCompo  (0),
+    myFilteredList    (0),
+    myExtractedTree   (0),
+    myRemovedList     (0),
+    myModifiedList    (0),
+    myAddedList       (0),
+    myRebuildBtn      (0),
+    myIsHiddenMain    (false)
+{
+  QPixmap image0(SUIT_Session::session()->resourceMgr()->loadPixmap(
+    "GEOM", tr("ICON_DLG_EXTRACTION")));
+  QPixmap image1(SUIT_Session::session()->resourceMgr()->loadPixmap(
+    "GEOM", tr("ICON_SELECT")));
+
+  setWindowTitle(tr("GEOM_EXTRACT_TITLE"));
+
+  /***************************************************************/
+
+  mainFrame()->GroupConstructors->setTitle(tr("GEOM_EXTRACT_TYPE"));
+  mainFrame()->RadioButton1->setIcon( image0 );
+  mainFrame()->RadioButton2->setAttribute(Qt::WA_DeleteOnClose);
+  mainFrame()->RadioButton2->close();
+  mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose);
+  mainFrame()->RadioButton3->close();
+
+  // Create an input group.
+  QGroupBox   *anInputGrp      = new QGroupBox(tr("GEOM_EXTRACT_INPUT_PARAMS"), centralWidget());
+  QGridLayout *anInputLayout   = new QGridLayout(anInputGrp);
+  QHBoxLayout *aShapeLayout    = new QHBoxLayout(anInputGrp);
+  QVBoxLayout *aViewBtnsLayout = new QVBoxLayout(anInputGrp);
+  QVBoxLayout *aMoveBtnsLayout = new QVBoxLayout(anInputGrp);
+  QLabel      *aMainObjLbl     = new QLabel(tr("GEOM_MAIN_OBJECT"), anInputGrp);
+  QLabel      *aSubShTypeLbl   = new QLabel(tr("GEOM_EXTRACT_SUB_SHAPE_TYPE"), anInputGrp);
+  QLabel      *aFilteredLbl    = new QLabel(tr("GEOM_EXTRACT_FILTERED_SHAPES"), anInputGrp);
+  QLabel      *anExtractedLbl  = new QLabel(tr("GEOM_EXTRACT_SHAPES_TO_EXTRACT"), anInputGrp);
+  QPushButton *aShowOnlySelBtn = new QPushButton(tr("SHOW_ONLY_SELECTED"), anInputGrp);
+  QPushButton *aHideSelBtn     = new QPushButton(tr("HIDE_SELECTED"), anInputGrp);
+  QPushButton *aShowAllBtn     = new QPushButton(tr("SHOW_ALL_SUB_SHAPES"), anInputGrp);
+  QPushButton *anAddBtn        = new QPushButton(">>", anInputGrp);
+  QPushButton *aRemoveBtn      = new QPushButton("<<", anInputGrp);
+
+  myRebuildBtn     = new QPushButton(tr("GEOM_EXTRACT_REBUILD"), anInputGrp);
+  mySelBtn         = new QPushButton(anInputGrp);
+  myMainShapeEdit  = new QLineEdit(anInputGrp);
+  mySubShTypeCompo = new QComboBox(anInputGrp);
+  myFilteredList   = new QListWidget(anInputGrp);
+  myExtractedTree  = new QTreeWidget(anInputGrp);
+  mySelBtn->setIcon(image1);
+  myMainShapeEdit->setReadOnly(true);
+
+  aShapeLayout->addWidget(mySelBtn);
+  aShapeLayout->addWidget(myMainShapeEdit);
+
+  aViewBtnsLayout->addStretch();
+  aViewBtnsLayout->addWidget(aShowOnlySelBtn);
+  aViewBtnsLayout->addWidget(aHideSelBtn);
+  aViewBtnsLayout->addWidget(aShowAllBtn);
+  aViewBtnsLayout->addStretch();
+
+  aMoveBtnsLayout->addStretch();
+  aMoveBtnsLayout->addWidget(anAddBtn);
+  aMoveBtnsLayout->addWidget(aRemoveBtn);
+  aMoveBtnsLayout->addStretch();
+
+  anInputLayout->setSpacing(6);
+  anInputLayout->setContentsMargins(9, 9, 9, 9);
+  anInputLayout->addWidget(aMainObjLbl,      0, 0);
+  anInputLayout->addLayout(aShapeLayout,     0, 1, 1, 3);
+  anInputLayout->addWidget(aSubShTypeLbl,    1, 0);
+  anInputLayout->addWidget(mySubShTypeCompo, 1, 1, 1, 3);
+  anInputLayout->addWidget(aFilteredLbl,     2, 1);
+  anInputLayout->addWidget(anExtractedLbl,   2, 3);
+  anInputLayout->addLayout(aViewBtnsLayout,  3, 0);
+  anInputLayout->addWidget(myFilteredList,   3, 1);
+  anInputLayout->addLayout(aMoveBtnsLayout,  3, 2);
+  anInputLayout->addWidget(myExtractedTree,  3, 3);
+  anInputLayout->addWidget(myRebuildBtn,     4, 0, 1, 4);
+
+  // Create a statistics group.
+  QGroupBox   *aStatGrp     = new QGroupBox(tr("GEOM_EXTRACT_STATISTICS"), centralWidget());
+  QGridLayout *aStatLayout  = new QGridLayout(aStatGrp);
+  QLabel      *aRemovedLbl  = new QLabel(tr("GEOM_EXTRACT_REMOVED"), aStatGrp);
+  QLabel      *aModifiedLbl = new QLabel(tr("GEOM_EXTRACT_MODIFIED"), aStatGrp);
+  QLabel      *anAddedLbl   = new QLabel(tr("GEOM_EXTRACT_ADDED"), aStatGrp);
+
+  myRemovedList  = new QListWidget(aStatGrp);
+  myModifiedList = new QListWidget(aStatGrp);
+  myAddedList    = new QListWidget(aStatGrp);
+
+  aStatLayout->setSpacing(6);
+  aStatLayout->setContentsMargins(9, 9, 9, 9);
+  aStatLayout->addWidget(aRemovedLbl,    0, 0);
+  aStatLayout->addWidget(aModifiedLbl,   0, 1);
+  aStatLayout->addWidget(anAddedLbl,     0, 2);
+  aStatLayout->addWidget(myRemovedList,  1, 0);
+  aStatLayout->addWidget(myModifiedList, 1, 1);
+  aStatLayout->addWidget(myAddedList,    1, 2);
+
+  // Create a main layout.
+  QVBoxLayout* aLayout = new QVBoxLayout(centralWidget());
+
+  aLayout->setMargin(0);
+  aLayout->setSpacing(6);
+  aLayout->addWidget(anInputGrp);
+  aLayout->addWidget(aStatGrp);
+
+  // signals and slots connections
+  connect(anAddBtn,        SIGNAL(clicked()), this, SLOT(onAddExtracted()));
+  connect(aRemoveBtn,      SIGNAL(clicked()), this, SLOT(onRemoveExtracted()));
+  connect(aShowOnlySelBtn, SIGNAL(clicked()), this, SLOT(showOnlySelected()));
+  connect(aHideSelBtn,     SIGNAL(clicked()), this, SLOT(hideSelected()));
+  connect(aShowAllBtn,     SIGNAL(clicked()), this, SLOT(showAllSelected()));
+
+  /***************************************************************/
+  myHelpFileName = "extract_and_rebuild_page.html";
+
+  /* Initialisation */
+  Init();
+}
+
+//=================================================================================
+// function : ~OperationGUI_ExtractionDlg()
+// purpose  : Destroys the object and frees any allocated resources
+//=================================================================================
+OperationGUI_ExtractionDlg::~OperationGUI_ExtractionDlg()
+{
+  restoreViewer();
+}
+
+//=================================================================================
+// function : Init()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::Init()
+{
+  mySelBtn->setCheckable(true);
+  mySelBtn->setChecked(true);
+  myFilteredList->setSelectionMode(QAbstractItemView::ExtendedSelection);
+  myFilteredList->setSortingEnabled(true);
+  myExtractedTree->setHeaderHidden(true);
+  myExtractedTree->setSelectionMode(QAbstractItemView::ExtendedSelection);
+  myExtractedTree->setColumnCount(1);
+  myRebuildBtn->setEnabled(false);
+  myRemovedList->setSelectionMode(QAbstractItemView::NoSelection);
+  myModifiedList->setSelectionMode(QAbstractItemView::NoSelection);
+  myAddedList->setSelectionMode(QAbstractItemView::NoSelection);
+
+  // Fill in the extracted tree with initial elements.
+  myTopItems[0] = 0; // No need to create a item for compound.
+
+  int i;
+
+  for (i = 1; i < 8; i++) {
+    myTopItems[i] = new QTreeWidgetItem;
+    myTopItems[i]->setText(0, tr(PLURAL_SHAPE_TYPE_TR_CODES[i]));
+    myTopItems[i]->setData(0, TYPE_ROLE, i);
+  
+    myExtractedTree->addTopLevelItem(myTopItems[i]);
+    myTopItems[i]->setHidden(true);
+  }
+
+  // signals and slots connections
+  connect(mySelBtn,         SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument()));
+  connect(buttonOk(),       SIGNAL(clicked()), this, SLOT(ClickOnOk()));
+  connect(buttonApply(),    SIGNAL(clicked()), this, SLOT(ClickOnApply()));
+  connect(mySubShTypeCompo, SIGNAL(currentIndexChanged(int)),
+          this,             SLOT(onShapeTypeChanged()));
+  connect(myRebuildBtn,     SIGNAL(clicked()), this, SLOT(onRebuild()));
+  connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()),
+          this, SLOT(SelectionIntoArgument()));
+  connect(myFilteredList,   SIGNAL(itemSelectionChanged()),
+          this,             SLOT(onListSelectionChanged()));
+  connect(myExtractedTree,  SIGNAL(itemSelectionChanged()),
+          this,             SLOT(onListSelectionChanged()));
+
+  initName(tr("GEOM_EXTRACT_NAME"));
+
+  activateSelection();
+  SelectionIntoArgument();
+}
+
+//=================================================================================
+// function : updateSubShTypeCompo()
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::updateSubShTypeCompo()
+{
+  bool         isValid  = true;
+  int          anIStart = TopAbs_COMPOUND;
+  const int    anIEnd   = TopAbs_VERTEX;
+  TopoDS_Shape aShape;
+
+  if (GEOMBase::GetShape(myObj, aShape)) {
+    const TopAbs_ShapeEnum aType = aShape.ShapeType();
+
+    if (aType == TopAbs_COMPOUND) {
+      anIStart = GetMaxShapeTypeInComp(aShape);
+      isValid  = anIStart != TopAbs_SHAPE;
+    } else {
+      anIStart = aType + 1;
+    }
+  }
+
+  QSignalBlocker aBlocker(mySubShTypeCompo);
+  mySubShTypeCompo->clear();
+
+  if (isValid) {
+    int i;
+
+    for (i = anIStart; i <= anIEnd; i++) {
+      mySubShTypeCompo->addItem(tr(SINGLE_SHAPE_TYPE_TR_CODES[i]), i);
+    }
+
+    updateFilteredList();
+  }
+
+  return isValid;
+}
+
+//=================================================================================
+// function : updateFilteredList()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::updateFilteredList()
+{
+  TopoDS_Shape   aShape;
+  QSignalBlocker aBlocker(myFilteredList);
+
+  myFilteredList->clear();
+
+  if (GEOMBase::GetShape(myObj, aShape)) {
+    const TopAbs_ShapeEnum aType = (TopAbs_ShapeEnum)
+      mySubShTypeCompo->itemData(mySubShTypeCompo->currentIndex()).toInt();
+    TopExp_Explorer        anExp(aShape, aType);
+
+    if (anExp.More()) {
+      TopTools_MapOfShape aMapFence;
+
+      for (; anExp.More(); anExp.Next()) {
+        const TopoDS_Shape &aSubShape = anExp.Current();
+
+        if (!aSubShape.IsNull() && aMapFence.Add(aSubShape)) {
+          int anIndex = myIndices.FindIndex(aSubShape);
+
+          if (!myMapExtractedIDs.Contains(anIndex)) {
+            addNewItem(anIndex, myFilteredList);
+          }
+        }
+      }
+    }
+  }
+}
+
+//=================================================================================
+// function : resetBuildData()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::resetBuildData(const bool isEnableBuild)
+{
+  // Clear result data.
+  myRemovedList->clear();
+  myModifiedList->clear();
+  myAddedList->clear();
+  myRebuildBtn->setEnabled(isEnableBuild);
+}
+
+//=================================================================================
+// function : isEmptyExtracted()
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::isEmptyExtracted()
+{
+  bool isEmpty = true;
+  int  i;
+
+  // Check if there are sub-shapes to be extracted.
+  for (i = 1; i < 8; i++) {
+    if (!myTopItems[i]->isHidden()) {
+      isEmpty = false;
+
+      break;
+    }
+  }
+
+  return isEmpty;
+}
+
+//=================================================================================
+// function : selectMainShape
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::selectMainShape()
+{
+  LightApp_SelectionMgr *aSelMgr = myGeomGUI->getApp()->selectionMgr();
+  SALOME_ListIO          aSelList;
+
+  aSelMgr->selectedObjects(aSelList);
+
+  if (aSelList.Extent() == 1) {
+    GEOM::GEOM_Object_var aSelObject =
+      GEOMBase::ConvertIOinGEOMObject(aSelList.First());
+    TopoDS_Shape          aSelShape;
+
+    if (GEOMBase::GetShape(aSelObject, aSelShape)) {
+      const TopAbs_ShapeEnum aType = aSelShape.ShapeType();
+
+      // Skip verices.
+      if (aType != TopAbs_VERTEX) {
+        myObj = aSelObject;
+
+        // Initialize map of indices. Note that myIndices should be empty.
+        TopExp::MapShapes(aSelShape, myIndices);
+      }
+    }
+  }
+
+  if (!updateSubShTypeCompo()) {
+    // Invalid selected object.
+    myObj = GEOM::GEOM_Object::_nil();
+  }
+
+  if (!CORBA::is_nil(myObj)) {
+    mySelBtn->setChecked(false);
+    myMainShapeEdit->setEnabled(false);
+    myMainShapeEdit->setText(GEOMBase::GetName(myObj));
+
+    // Hide the main object from the viewer.
+    SALOME_View* aView = GEOM_Displayer::GetActiveView();
+
+    if (aView) {
+      CORBA::String_var                aMainEntry = myObj->GetStudyEntry();
+      Handle(SALOME_InteractiveObject) anIO       = createIO(aMainEntry.in());
+
+      if (aView->isVisible(anIO)) {
+        GEOM_Displayer *aDisplayer = getDisplayer();
+
+        aDisplayer->Erase(myObj, false, true);
+        myIsHiddenMain = true;
+      }
+    }
+  }
+}
+
+//=================================================================================
+// function : selectSubShapes
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::selectSubShapes()
+{
+  QSignalBlocker aBlocker(myFilteredList);
+
+  // Clear current selection.
+  myFilteredList->clearSelection();
+
+  LightApp_SelectionMgr *aSelMgr  = myGeomGUI->getApp()->selectionMgr();
+  SALOME_ListIO          aSelList;
+  const int              aCurType =
+      mySubShTypeCompo->itemData(mySubShTypeCompo->currentIndex()).toInt();
+
+  aSelMgr->selectedObjects(aSelList);
+
+  // try to find out and process the global selection
+  // (of not published objects and of published sub-shapes)
+  SALOME_ListIteratorOfListIO anIter(aSelList);
+
+  for (; anIter.More(); anIter.Next()) {
+    Handle(SALOME_InteractiveObject) anIObj      = anIter.Value();
+    QString                          anEntry     = anIObj->getEntry();
+    QStringList                      aParts      = anEntry.split("_");
+    int                              aSubShapeId = -1;
+
+    if (!aParts.isEmpty()) {
+      if (aParts.first() == TMP_STR) {
+        bool      isOk    = false;
+        const int anIndex = aParts.last().toInt(&isOk);
+
+        if (isOk && anIndex > 0) {
+          // This is a sub-shape.
+          aSubShapeId = anIndex;
+        }
+      }
+    }
+
+    if (aSubShapeId < 0) {
+      // This is a published shape.
+      GEOM::GEOM_Object_var aSelObject =
+                    GEOMBase::ConvertIOinGEOMObject(anIObj);
+      TopoDS_Shape          aSelShape;
+
+      if (GEOMBase::GetShape(aSelObject, aSelShape)) {
+
+        if (aSelShape.ShapeType() == aCurType) {
+          const int anIndex = myIndices.FindIndex(aSelShape);
+
+          if (anIndex > 0) {
+            // This is a sub-shape. Select it in the filtered list.
+            aSubShapeId = anIndex;
+          }
+        }
+      }
+    }
+
+    // Select a list widget item by Id.
+    if (aSubShapeId > 0) {
+      QString                  anIdText = QString("%1").arg(aSubShapeId);
+      QList<QListWidgetItem *> aFound   =
+                    myFilteredList->findItems(anIdText, Qt::MatchExactly);
+
+      foreach (QListWidgetItem *anItem, aFound) {
+        anItem->setSelected(true);
+      }
+    }
+  }
+}
+
+//=================================================================================
+// function : ClickOnOk()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::ClickOnOk()
+{
+  if (ClickOnApply()) {
+    ClickOnCancel();
+  }
+}
+
+//=================================================================================
+// function : ClickOnApply()
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::ClickOnApply()
+{
+  if (!onAccept()) {
+    return false;
+  }
+
+  initName();
+
+  return true;
+}
+
+//=================================================================================
+// function : onShapeTypeChanged
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onShapeTypeChanged()
+{
+  updateFilteredList();
+  eraseAll();
+}
+
+//=================================================================================
+// function : onAddExtracted
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onAddExtracted()
+{
+  QList<QListWidgetItem *> aListSelected = myFilteredList->selectedItems();
+
+  if (aListSelected.empty()) {
+    return;
+  }
+
+  const int aShapeType =
+      mySubShTypeCompo->itemData(mySubShTypeCompo->currentIndex()).toInt();
+  bool  isTreeUpdated  = false;
+
+  foreach (QListWidgetItem *anItem, aListSelected) {
+    const int anIndex = anItem->data(ID_ROLE).toInt();
+
+    if (myMapExtractedIDs.Add(anIndex)) {
+      addChildItem(anIndex, myTopItems[aShapeType]);
+      isTreeUpdated = true;
+    }
+
+    // Remove anItem from the list.
+    myFilteredList->removeItemWidget(anItem);
+    delete anItem;
+  }
+
+  if (isTreeUpdated) {
+    myTopItems[aShapeType]->sortChildren(0, Qt::AscendingOrder);
+
+    // Reset build data
+    resetBuildData(true);
+  }
+
+  myFilteredList->clearSelection();
+  myTopItems[aShapeType]->setHidden(false);
+}
+
+//=================================================================================
+// function : onRemoveExtracted
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onRemoveExtracted()
+{
+  QList<QTreeWidgetItem *> aListSelected = myExtractedTree->selectedItems();
+
+  if (aListSelected.empty()) {
+    return;
+  }
+
+  const int               aShapeType =
+      mySubShTypeCompo->itemData(mySubShTypeCompo->currentIndex()).toInt();
+  QSet<QTreeWidgetItem *> aSetFence;
+  bool                    isTreeUpdated = false;
+
+  foreach (QTreeWidgetItem *anItem, aListSelected) {
+    if (!aSetFence.contains(anItem)) {
+      aSetFence.insert(anItem);
+
+      QTreeWidgetItem *aParent = anItem->parent();
+
+      if (aParent) {
+        const int anIndex = anItem->data(0, ID_ROLE).toInt();
+        // This is a ID item. Remove the ID from myMapExtractedIDs.
+        if (myMapExtractedIDs.Remove(anIndex)) {
+          // The item is not removed yet. Get parent index.
+          const int aParentIndex = aParent->data(0, TYPE_ROLE).toInt();
+
+          if (aShapeType == aParentIndex) {
+            // Create an item in the filtered list.
+            addNewItem(anIndex, myFilteredList);
+          }
+
+          aParent->removeChild(anItem);
+          delete anItem;
+          isTreeUpdated = true;
+
+          // Hilde an empty parent item.
+          if (aParent->childCount() == 0) {
+            aParent->setHidden(true);
+          }
+        }
+      } else {
+        // This is a top level item. Remove all its children.
+        QList<QTreeWidgetItem *> aChildItems = anItem->takeChildren();
+        const int                anIndex     = anItem->data(0, TYPE_ROLE).toInt();
+
+        // Remove IDs from myMapExtractedIDs.
+        foreach (QTreeWidgetItem *aChild, aChildItems) {
+          if (!aSetFence.contains(aChild)) {
+            aSetFence.insert(aChild);
+
+            const int aChildIndex = aChild->data(0, ID_ROLE).toInt();
+
+            if (myMapExtractedIDs.Remove(aChildIndex)) {
+              if (aShapeType == anIndex) {
+                // Create items in the filtered list.
+                addNewItem(aChildIndex, myFilteredList);
+              }
+
+              delete aChild;
+              isTreeUpdated = true;
+            }
+          }
+        }
+
+        // Hilde an empty item.
+        anItem->setHidden(true);
+      }
+    }
+  }
+
+  myExtractedTree->clearSelection();
+
+  if (isTreeUpdated) {
+    // Reset build data
+    const bool isEnableRebuild = !isEmptyExtracted();
+
+    resetBuildData(isEnableRebuild);
+  }
+}
+
+//=================================================================================
+// function : onListSelectionChanged
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onListSelectionChanged()
+{
+  SALOME_ListIO            anIOList;
+  QList<QListWidgetItem *> aListSel = myFilteredList->selectedItems();
+  QList<QTreeWidgetItem *> aTreeSel = myExtractedTree->selectedItems();
+
+  // Collect selected items from myFilteredList
+  foreach (QListWidgetItem *anItem, aListSel) {
+    const int anIndex = anItem->data(ID_ROLE).toInt();
+
+    if (myMapDisplayedIDs.Contains(anIndex)) {
+      // Collect only displayed sub-shapes for selection in the viewer.
+      QString                          anEntry = getSubShapeEntry(anIndex);
+      Handle(SALOME_InteractiveObject) anIO    =
+                                      createIO(anEntry.toLatin1().data());
+
+      anIOList.Append(anIO);
+    }
+  }
+
+  // Collect selected items from myExtractedTree
+  foreach (QTreeWidgetItem *anItem, aTreeSel) {
+    if (anItem->parent()) {
+      // This is a ID item.
+      const int anIndex = anItem->data(0, ID_ROLE).toInt();
+
+      if (myMapDisplayedIDs.Contains(anIndex)) {
+        // Collect only displayed sub-shapes for selection in the viewer.
+        QString                          anEntry = getSubShapeEntry(anIndex);
+        Handle(SALOME_InteractiveObject) anIO    =
+                                    createIO(anEntry.toLatin1().data());
+
+        anIOList.Append(anIO);
+      }
+    }
+  }
+
+  // Select object in viewer.
+  LightApp_SelectionMgr *aSelMgr = myGeomGUI->getApp()->selectionMgr();
+
+  aSelMgr->setSelectedObjects(anIOList);
+}
+
+//=================================================================================
+// function : showOnlySelected
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::showOnlySelected()
+{
+  TColStd_MapOfInteger aMapIDsSelected;
+  TColStd_MapOfInteger aMapIDsToDisplay;
+  const int            aNbItems = myFilteredList->count();
+  int                  i;
+  QSet<QString>        aSelEntry;
+
+  // Get sub-shape IDs to be displayed.
+  for (i = 0; i < aNbItems; ++i) {
+    QListWidgetItem *anItem = myFilteredList->item(i);
+    const int       anIndex = anItem->data(ID_ROLE).toInt();
+
+    if (anItem->isSelected()) {
+      aMapIDsSelected.Add(anIndex);
+      aSelEntry.insert(getSubShapeEntry(anIndex));
+
+      if (!myMapDisplayedIDs.Contains(anIndex)) {
+        aMapIDsToDisplay.Add(anIndex);
+      }
+    }
+  }
+
+  // Get sub-shape IDs to be erased.
+  TColStd_MapOfInteger              aMapIDsToHide;
+  TColStd_MapIteratorOfMapOfInteger anIter(myMapDisplayedIDs);
+
+  for (; anIter.More(); anIter.Next()) {
+    const int anIndex = anIter.Key();
+
+    if (!aMapIDsSelected.Contains(anIndex)) {
+      aMapIDsToHide.Add(anIndex);
+    }
+  }
+
+  // Display sub-shapes.
+  for (anIter.Initialize(aMapIDsToDisplay); anIter.More(); anIter.Next()) {
+    displaySubShape(anIter.Key());
+  }
+
+  // Hide sub-shapes.
+  for (anIter.Initialize(aMapIDsToHide); anIter.More(); anIter.Next()) {
+    eraseSubShape(anIter.Key());
+  }
+
+  // Hide all objects except already displayed sub-shapes.
+  SALOME_ListIO  aDisplayed;
+  SALOME_View   *aView = GEOM_Displayer::GetActiveView();
+
+  if (aView) {
+    aView->GetVisible(aDisplayed);
+  }
+
+  SALOME_ListIteratorOfListIO  aDispIt(aDisplayed);
+  GEOM_Displayer              *aDisplayer = getDisplayer();
+
+  for (; aDispIt.More(); aDispIt.Next()) {
+    Handle(SALOME_InteractiveObject) anIO = aDispIt.Value();
+
+    if (!aSelEntry.contains(anIO->getEntry())) {
+      aDisplayer->Erase(anIO, false, false);
+    }
+  }
+
+  onListSelectionChanged();
+  aDisplayer->UpdateViewer();
+}
+
+//=================================================================================
+// function : hideSelected
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::hideSelected()
+{
+  QList<QListWidgetItem *> aListSelected = myFilteredList->selectedItems();
+
+  foreach (QListWidgetItem *anItem, aListSelected) {
+    const int anIndex = anItem->data(ID_ROLE).toInt();
+
+    eraseSubShape(anIndex);
+  }
+
+  getDisplayer()->UpdateViewer();
+}
+
+//=================================================================================
+// function : showAllSelected
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::showAllSelected()
+{
+  const int aNbItems = myFilteredList->count();
+  int       i;
+
+  for (i = 0; i < aNbItems; ++i) {
+    QListWidgetItem *anItem = myFilteredList->item(i);
+    const int anIndex = anItem->data(ID_ROLE).toInt();
+
+    displaySubShape(anIndex);
+  }
+
+  onListSelectionChanged();
+  getDisplayer()->UpdateViewer();
+}
+
+//=================================================================================
+// function : onRebuild
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::onRebuild()
+{
+  GEOM::GEOM_Object_var                         aResShape;
+  GEOM::GEOM_IShapesOperations::ExtractionStats aStats;
+
+  if (!getResult(aResShape.out(), aStats)) {
+    resetBuildData(false);
+    return;
+  }
+
+  TopoDS_Shape               anOldShape;
+  TopoDS_Shape               aNewShape;
+  TopTools_IndexedMapOfShape aNewIndices;
+
+  if (!GEOMBase::GetShape(aResShape, aNewShape)) {
+    resetBuildData(false);
+    return;
+  }
+
+  TopExp::MapShapes(aNewShape, aNewIndices);
+
+  const int aNbStat = aStats.length();
+  int       i;
+
+  for (i = 0; i < aNbStat; ++i) {
+    // Compute number of sub-shapes of each type.
+    const int aNbSubShapes = aStats[i].indices.length();
+    int       aNbShapes [] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+    int       j;
+
+    TopTools_IndexedMapOfShape *aMapShapes =
+      (aStats[i].type == GEOM::GEOM_IShapesOperations::EST_Added) ?
+            &aNewIndices : &myIndices;
+
+    for (j = 0; j < aNbSubShapes; ++j) {
+      const int anIndex = aStats[i].indices[j];
+
+      if (anIndex < 1 || anIndex > aMapShapes->Extent()) {
+        resetBuildData(false);
+        return;
+      }
+
+      const TopoDS_Shape &aSubShape = aMapShapes->FindKey(anIndex);
+
+      aNbShapes[aSubShape.ShapeType()]++;
+    }
+
+    // Fill the statistics.
+    QListWidget *aListWidget = 0;
+
+    switch (aStats[i].type) {
+      case GEOM::GEOM_IShapesOperations::EST_Removed:
+        aListWidget = myRemovedList;
+        break;
+      case GEOM::GEOM_IShapesOperations::EST_Modified:
+        aListWidget = myModifiedList;
+        break;
+      case GEOM::GEOM_IShapesOperations::EST_Added:
+        aListWidget = myAddedList;
+        break;
+      default:
+        resetBuildData(false);
+        return;
+    }
+
+    QStringList aStrList;
+
+    for (j = 1; j < 8; ++j) {
+      if (aNbShapes[j] >= 1) {
+        const char *aShapeType = aNbShapes[j] == 1 ?
+          SINGLE_SHAPE_TYPE_TR_CODES[j] : PLURAL_SHAPE_TYPE_TR_CODES[j];
+
+        aStrList.append(QString("%1 %2").arg(aNbShapes[j]).arg(tr(aShapeType)));
+      }
+    }
+
+    aListWidget->addItems(aStrList);
+  }
+
+  myRebuildBtn->setEnabled(false);
+}
+
+//=================================================================================
+// function : SelectionIntoArgument
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::SelectionIntoArgument()
+{
+  if (myMainShapeEdit->isEnabled()) {
+    // Selection of main object
+    selectMainShape();
+  } else {
+    // Selection of filtered shapes
+    selectSubShapes();
+  }
+}
+
+//=================================================================================
+// function : SetEditCurrentArgument
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::SetEditCurrentArgument()
+{
+  QSignalBlocker aBlockerList(myFilteredList);
+  QSignalBlocker aBlockerTree(myExtractedTree);
+
+  restoreViewer();
+  myObj = GEOM::GEOM_Object::_nil();
+  myMainShapeEdit->setEnabled(true);
+  myMainShapeEdit->setText("");
+  myMainShapeEdit->setFocus();
+
+  updateSubShTypeCompo();
+
+  myFilteredList->clear();
+  myRemovedList->clear();
+  myModifiedList->clear();
+  myAddedList->clear();
+  myIndices.Clear();
+
+  // Clear myExtractedTree.
+  int i;
+
+  for (i = 1; i < 8; i++) {
+    QList<QTreeWidgetItem *> aListItems = myTopItems[i]->takeChildren();
+
+    foreach (QTreeWidgetItem *anItem, aListItems) {
+      delete anItem;
+    }
+
+    myTopItems[i]->setHidden(true);
+  }
+
+  myExtractedTree->clearSelection();
+
+  myMapExtractedIDs.Clear();
+
+  // Update viewer
+  eraseAll();
+}
+
+//=================================================================================
+// function : ActivateThisDialog()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::ActivateThisDialog()
+{
+  GEOMBase_Skeleton::ActivateThisDialog();
+
+  LightApp_SelectionMgr* aSel = myGeomGUI->getApp()->selectionMgr();
+
+  if (aSel) {
+    connect(aSel, SIGNAL(currentSelectionChanged()),
+            this, SLOT(SelectionIntoArgument()));
+  }
+
+  activateSelection();
+}
+
+//=================================================================================
+// function : activateSelection
+// purpose  : activate selection of all shapes
+//=================================================================================
+void OperationGUI_ExtractionDlg::activateSelection()
+{
+  globalSelection(GEOM_ALLSHAPES);
+}
+
+//=================================================================================
+// function : enterEvent()
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::enterEvent(QEvent *)
+{
+  if (!mainFrame()->GroupConstructors->isEnabled()) {
+    ActivateThisDialog();
+  }
+}
+
+//=================================================================================
+// function : getResult
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::getResult
+             (GEOM::GEOM_Object_ptr                         &theResult,
+              GEOM::GEOM_IShapesOperations::ExtractionStats &theStats)
+{
+  if (myObj->_is_nil()) {
+    return false;
+  }
+
+  // Get IDs of extracted shapes.
+  int i;
+  int aNbShapes = 0;
+
+  for (i = 1; i < 8; i++) {
+    aNbShapes += myTopItems[i]->childCount();
+  }
+
+  if (aNbShapes == 0) {
+    return false;
+  }
+
+  GEOM::ListOfLong_var aSubShapeIDs = new GEOM::ListOfLong;
+  int                  j;
+  int                  jCur;
+
+  aSubShapeIDs->length(aNbShapes);
+
+  for (jCur = 0, i = 1; i < 8; ++i) {
+    aNbShapes = myTopItems[i]->childCount();
+    
+    for (j = 0; j < aNbShapes; ++j, ++jCur) {
+      aSubShapeIDs[jCur] = myTopItems[i]->child(j)->data(0, ID_ROLE).toInt();
+    }
+  }
+
+  GEOM::GEOM_IShapesOperations_var anOper =
+    GEOM::GEOM_IShapesOperations::_narrow(getOperation());
+
+  try {
+    GEOM::GEOM_Object_var                             anObj;
+    GEOM::GEOM_IShapesOperations::ExtractionStats_var aStats;
+
+    anObj = anOper->MakeExtraction(myObj, aSubShapeIDs, aStats);
+
+    if (anOper->IsDone() && aStats->length() > 0) {
+      theStats = aStats;
+    }
+
+    if (!CORBA::is_nil(anObj)) {
+      theResult = anObj._retn();
+    }
+  }
+  catch (const SALOME::SALOME_Exception& e) {
+    SalomeApp_Tools::QtCatchCorbaException(e);
+    return false;
+  }
+
+  return anOper->IsDone();
+}
+
+//=================================================================================
+// function : isValid
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::isValid(QString &)
+{
+  bool isOk = !myObj->_is_nil() && !isEmptyExtracted();
+
+  return isOk;
+}
+
+//=================================================================================
+// function : createOperation
+// purpose  :
+//=================================================================================
+GEOM::GEOM_IOperations_ptr OperationGUI_ExtractionDlg::createOperation()
+{
+  return getGeomEngine()->GetIShapesOperations(getStudyId());
+}
+
+//=================================================================================
+// function : execute
+// purpose  :
+//=================================================================================
+bool OperationGUI_ExtractionDlg::execute(ObjectList &objects)
+{
+  GEOM::GEOM_Object_var                         aResShape;
+  GEOM::GEOM_IShapesOperations::ExtractionStats aStats;
+
+  if (!getResult(aResShape.out(), aStats)) {
+    return false;
+  }
+
+  if (!aResShape->_is_nil()) {
+    objects.push_back(aResShape._retn());
+  }
+
+  return true;
+}
+
+//=================================================================================
+// function : getSubShapeEntry
+// purpose  :
+//=================================================================================
+QString OperationGUI_ExtractionDlg::getSubShapeEntry(const int theId)
+{
+  CORBA::String_var aMainEntry = myObj->GetStudyEntry();
+  QString           anEntry    = QString("%1_").arg(TMP_STR) +
+                                 aMainEntry.in() + QString("_%1").arg(theId);
+
+  return anEntry;
+}
+
+//=================================================================================
+// function : createIO
+// purpose  :
+//=================================================================================
+Handle_SALOME_InteractiveObject OperationGUI_ExtractionDlg::createIO
+                                                      (const char *theEntry)
+{
+  Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
+                              (theEntry, "GEOM", "TEMP_IO");
+
+  return anIO;
+}
+
+//=================================================================================
+// function : displaySubShape
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::displaySubShape(const int theId)
+{
+  if (theId < 1 || theId > myIndices.Extent()) {
+    return;
+  }
+
+  // Create a presentation
+  const TopoDS_Shape &aSubShape  = myIndices.FindKey(theId);
+  QString             anEntry    = getSubShapeEntry(theId);
+  SALOME_View        *aView      = GEOM_Displayer::GetActiveView();
+  GEOM_Displayer     *aDisplayer = getDisplayer();
+  SALOME_Prs         *aPrs       = aDisplayer->buildSubshapePresentation
+                                  (aSubShape, anEntry, aView);
+
+  if (aPrs) {
+    if (aView) {
+      aView->Display(aDisplayer, aPrs);
+    }
+
+    delete aPrs;
+
+    myMapDisplayedIDs.Add(theId);
+  }
+}
+
+//=================================================================================
+// function : eraseSubShape
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::eraseSubShape(const int theId)
+{
+  QString                          anEntry = getSubShapeEntry(theId);
+  Handle(SALOME_InteractiveObject) anIO    =
+                                      createIO(anEntry.toLatin1().data());
+
+  getDisplayer()->Erase(anIO, false, false);
+  myMapDisplayedIDs.Remove(theId);
+}
+
+//=================================================================================
+// function : eraseAll
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::eraseAll()
+{
+  TColStd_MapIteratorOfMapOfInteger anIter(myMapDisplayedIDs);
+
+  for (; anIter.More(); anIter.Next()) {
+    eraseSubShape(anIter.Key());
+  }
+
+  myMapDisplayedIDs.Clear();
+  getDisplayer()->UpdateViewer();
+}
+
+//=================================================================================
+// function : restoreViewer
+// purpose  :
+//=================================================================================
+void OperationGUI_ExtractionDlg::restoreViewer()
+{
+  if (!CORBA::is_nil(myObj)) {
+    if (myIsHiddenMain) {
+      getDisplayer()->Display(myObj, false);
+      myIsHiddenMain = false;
+    }
+
+    eraseAll();
+  }
+}
diff --git a/src/OperationGUI/OperationGUI_ExtractionDlg.h b/src/OperationGUI/OperationGUI_ExtractionDlg.h
new file mode 100644 (file)
index 0000000..f10592a
--- /dev/null
@@ -0,0 +1,115 @@
+// Copyright (C) 2007-2015  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
+//
+// 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, 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
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef OPERATIONGUI_EXTRACTIONDLG_H
+#define OPERATIONGUI_EXTRACTIONDLG_H
+
+#include <GEOMBase_Skeleton.h>
+
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TColStd_MapOfInteger.hxx>
+
+class QComboBox;
+class QListWidget;
+class QTreeWidget;
+class QTreeWidgetItem;
+
+
+//=================================================================================
+// class    : OperationGUI_ExtractionDlg
+// purpose  :
+//=================================================================================
+class OperationGUI_ExtractionDlg : public GEOMBase_Skeleton
+{
+
+  Q_OBJECT
+
+public:
+
+  OperationGUI_ExtractionDlg( GeometryGUI*, QWidget* );
+  ~OperationGUI_ExtractionDlg();
+
+protected:
+
+  // redefined from GEOMBase_Helper and MeasureGUI_Skeleton
+  virtual GEOM::GEOM_IOperations_ptr  createOperation();
+  virtual bool                        execute(ObjectList &);
+  virtual void                        activateSelection();
+  virtual bool                        isValid( QString& );
+
+private slots:
+
+  void                                SelectionIntoArgument();
+  void                                ClickOnOk();
+  bool                                ClickOnApply();
+  void                                onShapeTypeChanged();
+  void                                onAddExtracted();
+  void                                onRemoveExtracted();
+  void                                onListSelectionChanged();
+  void                                showOnlySelected();
+  void                                hideSelected();
+  void                                showAllSelected();
+  void                                onRebuild();
+  void                                ActivateThisDialog();
+  void                                SetEditCurrentArgument();
+
+private:
+
+  void                                Init();
+  bool                                updateSubShTypeCompo();
+  void                                updateFilteredList();
+  void                                resetBuildData(const bool isEnableBuild);
+  bool                                isEmptyExtracted();
+  void                                selectMainShape();
+  void                                selectSubShapes();
+  void                                enterEvent(QEvent *);
+  bool                                getResult
+             (GEOM::GEOM_Object_ptr                         &theResult,
+              GEOM::GEOM_IShapesOperations::ExtractionStats &theStats);
+  QString                             getSubShapeEntry(const int theId);
+  Handle_SALOME_InteractiveObject     createIO(const char *theEntry);
+  void                                displaySubShape(const int theId);
+  void                                eraseSubShape(const int theId);
+  void                                eraseAll();
+  void                                restoreViewer();
+
+private:
+
+  GEOM::GEOM_Object_var       myObj;
+  QPushButton                *mySelBtn;
+  QLineEdit                  *myMainShapeEdit;
+  QComboBox                  *mySubShTypeCompo;
+  QListWidget                *myFilteredList;
+  QTreeWidget                *myExtractedTree;
+  QListWidget                *myRemovedList;
+  QListWidget                *myModifiedList;
+  QListWidget                *myAddedList;
+  QTreeWidgetItem            *myTopItems[8];
+  QPushButton                *myRebuildBtn;
+  TColStd_MapOfInteger        myMapExtractedIDs;
+  bool                        myIsHiddenMain;
+  TColStd_MapOfInteger        myMapDisplayedIDs;
+  TopTools_IndexedMapOfShape  myIndices;
+
+};
+
+#endif // OPERATIONGUI_EXTRACTIONDLG_H