--- /dev/null
+// 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();
+ }
+}