]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Update Filters data model using the previous filters implementation: filter arguments...
authormpv <mpv@opencascade.com>
Thu, 25 Apr 2019 13:41:59 +0000 (16:41 +0300)
committermpv <mpv@opencascade.com>
Thu, 25 Apr 2019 13:41:59 +0000 (16:41 +0300)
50 files changed:
CMakeLists.txt
src/BuildPlugin/BuildPlugin_Shape.cpp
src/BuildPlugin/BuildPlugin_Shape.h
src/CollectionPlugin/CollectionPlugin_Plugin.cpp
src/CollectionPlugin/group_widget.xml
src/Config/Config_Keywords.h
src/Config/plugins.xml.in
src/FiltersPlugin/CMakeLists.txt [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin.h [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_HorizontalFace.cpp [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_HorizontalFace.h [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_Plugin.cpp [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_Plugin.h [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_Selection.cpp [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_Selection.h [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_VerticalFace.cpp [new file with mode: 0644]
src/FiltersPlugin/FiltersPlugin_VerticalFace.h [new file with mode: 0644]
src/FiltersPlugin/plugin-Filters.xml [new file with mode: 0644]
src/GeomValidators/GeomValidators_Plugin.cpp
src/Model/CMakeLists.txt
src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Filter.cpp [new file with mode: 0644]
src/Model/Model_Filter.h [new file with mode: 0644]
src/Model/Model_Session.cpp
src/Model/Model_Session.h
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI_Data.h
src/ModelAPI/ModelAPI_Filter.h [new file with mode: 0644]
src/ModelAPI/ModelAPI_Session.h
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_ChoiceCtrl.cpp
src/ModuleBase/ModuleBase_WidgetFactory.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp
src/ModuleBase/ModuleBase_WidgetMultiSelector.h
src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_WidgetSelectionFilter.h [new file with mode: 0644]
src/PartSet/PartSet_WidgetSketchCreator.cpp
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_DataModel.h
src/XGUI/XGUI_InspectionPanel.cpp
src/XGUI/XGUI_PropertyPanel.cpp
src/XGUI/XGUI_PropertyPanel.h
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_pictures.qrc
src/XGUI/pictures/accept.png [new file with mode: 0644]
src/XGUI/pictures/add.png [new file with mode: 0644]
src/XGUI/pictures/filter.png [new file with mode: 0644]
src/XGUI/pictures/plus_minus.png [new file with mode: 0644]
src/XGUI/pictures/stop.png [new file with mode: 0644]

index 777a006d82ee74ccd5ae6f38e92c884a096f2d51..8851528668d3663a94f8ef49151d64ea1735151c 100644 (file)
@@ -146,6 +146,7 @@ ADD_SUBDIRECTORY (src/PartSet)
 ADD_SUBDIRECTORY (src/XGUI)
 ADD_SUBDIRECTORY (src/ExchangePlugin)
 ADD_SUBDIRECTORY (src/GeomValidators)
+ADD_SUBDIRECTORY (src/FiltersPlugin)
 ADD_SUBDIRECTORY (src/InitializationPlugin)
 ADD_SUBDIRECTORY (src/ParametersPlugin)
 ADD_SUBDIRECTORY (src/PythonAddons)
index 60c273c593bf80445ba0d4170b1ff1852bf2646d..e91ec9e80bacf64c2122a276eb719d653300f521 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 //
 // 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
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include "BuildPlugin_Shape.h"
index e858ca14240648547396da990c19cdd37025897b..693a9f2e42957b367a8a2888fae192482fa733fc 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 //
 // 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
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #ifndef BuildPlugin_Shape_H_
index 1720030882a1ea8675a2aeb58a6d32adcc0eb322..7b0fc28e1e4210a783f0c73411daa334484bb8d9 100644 (file)
@@ -54,11 +54,10 @@ FeaturePtr CollectionPlugin_Plugin::createFeature(std::string theFeatureID)
 {
   if (theFeatureID == CollectionPlugin_Group::ID()) {
     return FeaturePtr(new CollectionPlugin_Group);
-  }else if (theFeatureID == CollectionPlugin_Field::ID()) {
+  } else if (theFeatureID == CollectionPlugin_Field::ID()) {
     return FeaturePtr(new CollectionPlugin_Field);
   }
 
-
   // feature of such kind is not found
   return FeaturePtr();
 }
index 3a1f83feb772573df3df2b5e9777b445eddd0ea6..59bd93fb4001e414434bddd767e2434b445473ce 100644 (file)
@@ -7,6 +7,7 @@
     tooltip="Select a set of objects"
     type_choice="Vertices Edges Faces Solids"
     use_choice="true"
+    use_filters="FiltersSelection"
     clear_in_neutral_point="false"
     filter_points="false"
     same_topology="true">
index ca31903ec3246de1d593ebaa9c0f8fb85faa2b62..ff7ee5c75da7acecbb48fa3d67f02b44a658c0fc 100644 (file)
@@ -52,6 +52,7 @@ const static char* WDG_EXPR_EDITOR = "expr_editor";
 const static char* WDG_PLACE_HOLDER = "placeholder";
 const static char* WDG_ACTION = "action";
 const static char* WDG_POINT_INPUT = "point_input";
+const static char* WDG_SELECTION_FILTERS = "selection_filters";
 
 // Containers
 const static char* WDG_GROUP = "groupbox";
index 7734d59d8eb55f740b2fc0ef20cada1863bb329b..87476727f5305315c0cd1e4d6e6386681811565e 100644 (file)
@@ -19,6 +19,7 @@
 @ALL_SOLVERS@
 -->
   <plugin library="GeomValidators"/>
+  <plugin library="Filters" configuration="plugin-Filters.xml"/>
   <plugin library="DFBrowser" internal="true"/>
 <!--
   <plugin library="SamplePanelPlugin" configuration="plugin-SamplePanel.xml"/>
diff --git a/src/FiltersPlugin/CMakeLists.txt b/src/FiltersPlugin/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7587c49
--- /dev/null
@@ -0,0 +1,62 @@
+## Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+##
+## 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(Common)
+
+SET(PROJECT_HEADERS
+    FiltersPlugin.h
+    FiltersPlugin_Plugin.h
+    FiltersPlugin_Selection.h
+    FiltersPlugin_HorizontalFace.h
+    FiltersPlugin_VerticalFace.h
+)
+
+SET(PROJECT_SOURCES
+    FiltersPlugin_Plugin.cpp
+    FiltersPlugin_Selection.cpp
+    FiltersPlugin_HorizontalFace.cpp
+    FiltersPlugin_VerticalFace.cpp
+)
+
+SET(PROJECT_LIBRARIES
+    ModelAPI
+    Events
+    Config
+    GeomAPI
+)
+
+SET(XML_RESOURCES
+  plugin-Filters.xml
+)
+
+ADD_DEFINITIONS(-DFILTERS_EXPORTS ${OpenCASCADE_DEFINITIONS})
+ADD_LIBRARY(Filters SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES})
+TARGET_LINK_LIBRARIES(Filters ${PROJECT_LIBRARIES})
+
+INCLUDE_DIRECTORIES(
+  ${OpenCASCADE_INCLUDE_DIR}
+  ${PROJECT_SOURCE_DIR}/src/ModelAPI
+  ${PROJECT_SOURCE_DIR}/src/Config
+  ${PROJECT_SOURCE_DIR}/src/Events
+  ${PROJECT_SOURCE_DIR}/src/GeomAPI
+  ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
+)
+
+INSTALL(TARGETS Filters DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
+INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
diff --git a/src/FiltersPlugin/FiltersPlugin.h b/src/FiltersPlugin/FiltersPlugin.h
new file mode 100644 (file)
index 0000000..d1ed46e
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 FILTERS_H
+#define FILTERS_H
+
+#if defined FILTERS_EXPORTS
+#if defined WIN32
+#define FILTERS_EXPORT              __declspec( dllexport )
+#else
+#define FILTERS_EXPORT
+#endif
+#else
+#if defined WIN32
+#define FILTERS_EXPORT              __declspec( dllimport )
+#else
+#define FILTERS_EXPORT
+#endif
+#endif
+
+#endif
diff --git a/src/FiltersPlugin/FiltersPlugin_HorizontalFace.cpp b/src/FiltersPlugin/FiltersPlugin_HorizontalFace.cpp
new file mode 100644 (file)
index 0000000..c602e42
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 "FiltersPlugin_HorizontalFace.h"
+
+#include <GeomAPI_Face.h>
+#include <GeomAPI_Pln.h>
+
+bool FiltersPlugin_HorizontalFace::isSupported(GeomAPI_Shape::ShapeType theType) const
+{
+  return theType == GeomAPI_Shape::FACE;
+}
+
+bool FiltersPlugin_HorizontalFace::isOk(
+  const GeomShapePtr& theShape, const ModelAPI_FiltersArgs& theArgs) const
+{
+  if (!theShape->isPlanar())
+    return false;
+  GeomFacePtr aFace(new GeomAPI_Face(theShape));
+
+  GeomPlanePtr aPlane = aFace->getPlane();
+  GeomDirPtr aDir = aPlane->direction();
+  return aDir->isParallel(GeomDirPtr(new GeomAPI_Dir(0,0,1)));
+}
diff --git a/src/FiltersPlugin/FiltersPlugin_HorizontalFace.h b/src/FiltersPlugin/FiltersPlugin_HorizontalFace.h
new file mode 100644 (file)
index 0000000..aa3a316
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 FILTERSPLUGIN_HORIZONTALPLANE_H_
+#define FILTERSPLUGIN_HORIZONTALPLANE_H_
+
+#include "FiltersPlugin.h"
+
+#include <ModelAPI_Filter.h>
+
+/**\class FiltersPlugin_HorizontalFace
+* \ingroup DataModel
+* \brief Filter for horizontal faces only
+*/
+class FiltersPlugin_HorizontalFace : public ModelAPI_Filter
+{
+public:
+  FiltersPlugin_HorizontalFace() : ModelAPI_Filter() {}
+
+  virtual const std::string& name() const {
+    static const std::string kName("Horizontal faces");
+    return kName;
+  }
+
+  /// Returns true if the given shape type is supported
+  virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override;
+
+  /// This method should contain the filter logic. It returns true if the given shape
+  /// is accepted by the filter.
+  /// \param theShape the given shape
+  virtual bool isOk(
+    const GeomShapePtr& theShape, const ModelAPI_FiltersArgs& theArgs) const override;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/FiltersPlugin/FiltersPlugin_Plugin.cpp b/src/FiltersPlugin/FiltersPlugin_Plugin.cpp
new file mode 100644 (file)
index 0000000..a5183c5
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 "FiltersPlugin_Plugin.h"
+#include "FiltersPlugin_Selection.h"
+#include "FiltersPlugin_HorizontalFace.h"
+#include "FiltersPlugin_VerticalFace.h"
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Filter.h>
+
+// the only created instance of this plugin
+static FiltersPlugin_Plugin* MY_VIEWFILTERS_INSTANCE = new FiltersPlugin_Plugin();
+
+FiltersPlugin_Plugin::FiltersPlugin_Plugin()
+{
+  // register validators
+  SessionPtr aMgr = ModelAPI_Session::get();
+  ModelAPI_FiltersFactory* aFactory = aMgr->filters();
+  aFactory->registerFilter("HorizontalFaces", new FiltersPlugin_HorizontalFace);
+  aFactory->registerFilter("VerticalFaces", new FiltersPlugin_VerticalFace);
+
+  ModelAPI_Session::get()->registerPlugin(this);
+}
+
+FeaturePtr FiltersPlugin_Plugin::createFeature(std::string theFeatureID)
+{
+  if (theFeatureID == FiltersPlugin_Selection::ID())
+    return FeaturePtr(new FiltersPlugin_Selection);
+  // feature of such kind is not found
+  return FeaturePtr();
+}
diff --git a/src/FiltersPlugin/FiltersPlugin_Plugin.h b/src/FiltersPlugin/FiltersPlugin_Plugin.h
new file mode 100644 (file)
index 0000000..a511e3d
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 FILTERSPLUGIN_PLUGIN_H_
+#define FILTERSPLUGIN_PLUGIN_H_
+
+#include "FiltersPlugin.h"
+#include <ModelAPI_Plugin.h>
+#include <ModelAPI_Feature.h>
+
+/**\class GeomValidators_Plugin
+ * \ingroup Plugins
+ * \brief Interface common for any plugin: allows to use plugin by the plugins manager.
+ */
+class FILTERS_EXPORT FiltersPlugin_Plugin : public ModelAPI_Plugin
+{
+public:
+  /// Creates the feature object of this plugin by the feature string ID
+  virtual FeaturePtr createFeature(std::string theFeatureID);
+
+public:
+  FiltersPlugin_Plugin();
+};
+
+#endif
diff --git a/src/FiltersPlugin/FiltersPlugin_Selection.cpp b/src/FiltersPlugin/FiltersPlugin_Selection.cpp
new file mode 100644 (file)
index 0000000..025d301
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 "FiltersPlugin_Selection.h"
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_AttributeBoolean.h>
+
+// identifier of the reverse flag of a filter
+static const std::string kReverseAttrID("");
+
+void FiltersPlugin_Selection::addFilter(const std::string theFilterID)
+{
+  ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
+  FilterPtr aFilter = aFactory->filter(theFilterID);
+  if (aFilter.get()) {
+    std::shared_ptr<ModelAPI_AttributeBoolean> aBool =
+      std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(data()->addFloatingAttribute(
+        kReverseAttrID, ModelAPI_AttributeBoolean::typeId(), theFilterID));
+    aBool->setValue(false); // not reversed by default
+    // TODO: to add attributes related to the filter
+  }
+}
+
+void FiltersPlugin_Selection::removeFilter(const std::string theFilterID)
+{
+  ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
+  FilterPtr aFilter = aFactory->filter(theFilterID);
+  if (aFilter.get()) {
+    data()->removeAttributes(theFilterID);
+  }
+}
+
+std::list<std::string> FiltersPlugin_Selection::filters() const
+{
+  std::list<std::string> aFilters;
+  data()->allGroups(aFilters);
+  return aFilters;
+}
+
+void FiltersPlugin_Selection::setReversed(const std::string theFilterID, const bool theReversed)
+{
+  std::string anAttrID = kReverseAttrID + kFilterSeparator + theFilterID;
+  std::shared_ptr<ModelAPI_AttributeBoolean> aBool = boolean(anAttrID);
+}
+
+bool FiltersPlugin_Selection::isReversed(const std::string theFilterID)
+{
+  std::string anAttrID = kReverseAttrID + kFilterSeparator + theFilterID;
+  std::shared_ptr<ModelAPI_AttributeBoolean> aBool = boolean(anAttrID);
+  return aBool->value();
+}
+
+std::list<AttributePtr> FiltersPlugin_Selection::filterArgs(const std::string theFilterID) const
+{
+  std::list<AttributePtr> aList;
+  data()->attributesOfGroup(theFilterID, aList);
+  return aList;
+}
diff --git a/src/FiltersPlugin/FiltersPlugin_Selection.h b/src/FiltersPlugin/FiltersPlugin_Selection.h
new file mode 100644 (file)
index 0000000..2da80a2
--- /dev/null
@@ -0,0 +1,81 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 FILTERSPLUGIN_SELECTION_H_
+#define FILTERSPLUGIN_SELECTION_H_
+
+#include "FiltersPlugin.h"
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Filter.h>
+
+/**\class FiltersPlugin_Selection
+* \ingroup DataModel
+* \brief An interface for working with filters in the feature. A filters feature must inherit it
+*       in order to allow management of filters in the feature data structure.
+*/
+class FiltersPlugin_Selection : public ModelAPI_Feature, public ModelAPI_FiltersFeature
+{
+public:
+  /// Extrusion kind
+  inline static const std::string& ID() {
+    static const std::string MY_GROUP_ID("FiltersSelection");
+    return MY_GROUP_ID;
+  }
+
+  /// Returns the kind of a feature
+  FILTERS_EXPORT virtual const std::string& getKind() {
+    return ID();
+  }
+
+  /// This feature does not displayed in the data tree
+  virtual bool isInHistory() {
+    return false;
+  }
+
+  /// Computes a selection?
+  FILTERS_EXPORT virtual void execute() {}
+
+  /// Initially there are no filters selected, so, no attributes
+  virtual void initAttributes() {}
+
+  /// Feature is created in the plugin manager
+  FiltersPlugin_Selection() {}
+
+  // methods related to the filters management
+
+  /// Adds a filter to the feature. Also initializes arguments of this filter.
+  FILTERS_EXPORT virtual void addFilter(const std::string theFilterID);
+
+  /// Removes an existing filter from the feature.
+  FILTERS_EXPORT virtual void removeFilter(const std::string theFilterID);
+
+  /// Returns the list of existing filters in the feature.
+  FILTERS_EXPORT virtual std::list<std::string> filters() const;
+
+  /// Stores the reversed flag for the filter.
+  FILTERS_EXPORT virtual void setReversed(const std::string theFilterID, const bool theReversed);
+
+  /// Returns the reversed flag value for the filter.
+  FILTERS_EXPORT virtual bool isReversed(const std::string theFilterID);
+
+  /// Returns the ordered list of attributes related to the filter.
+  FILTERS_EXPORT virtual std::list<AttributePtr> filterArgs(const std::string theFilterID) const;
+};
+
+#endif
diff --git a/src/FiltersPlugin/FiltersPlugin_VerticalFace.cpp b/src/FiltersPlugin/FiltersPlugin_VerticalFace.cpp
new file mode 100644 (file)
index 0000000..8af64f0
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 "FiltersPlugin_VerticalFace.h"
+
+#include <GeomAPI_Face.h>
+#include <GeomAPI_Pln.h>
+
+bool FiltersPlugin_VerticalFace::isSupported(GeomAPI_Shape::ShapeType theType) const
+{
+  return theType == GeomAPI_Shape::FACE;
+}
+
+bool FiltersPlugin_VerticalFace::isOk(
+  const GeomShapePtr& theShape, const ModelAPI_FiltersArgs& theArgs) const
+{
+  if (!theShape->isPlanar())
+    return false;
+  GeomFacePtr aFace(new GeomAPI_Face(theShape));
+
+  GeomPlanePtr aPlane = aFace->getPlane();
+  GeomDirPtr aDir = aPlane->direction();
+  return fabs(aDir->z()) <= 1.e-7;
+}
diff --git a/src/FiltersPlugin/FiltersPlugin_VerticalFace.h b/src/FiltersPlugin/FiltersPlugin_VerticalFace.h
new file mode 100644 (file)
index 0000000..e920f4c
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 FILTERSPLUGIN_VERTICALPLANE_H_
+#define FILTERSPLUGIN_VERTICALPLANE_H_
+
+#include "FiltersPlugin.h"
+
+#include <ModelAPI_Filter.h>
+
+/**\class FiltersPlugin_VerticalFace
+* \ingroup DataModel
+* \brief Filter for vertical faces only
+*/
+class FiltersPlugin_VerticalFace: public ModelAPI_Filter
+{
+public:
+  FiltersPlugin_VerticalFace() : ModelAPI_Filter() {}
+
+  virtual const std::string& name() const {
+    static const std::string kName("Vertical faces");
+    return kName;
+  }
+
+  /// Returns true if the given shape type is supported
+  virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const override;
+
+  /// This method should contain the filter logic. It returns true if the given shape
+  /// is accepted by the filter.
+  /// \param theShape the given shape
+  virtual bool isOk(
+    const GeomShapePtr& theShape, const ModelAPI_FiltersArgs& theArgs) const override;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/FiltersPlugin/plugin-Filters.xml b/src/FiltersPlugin/plugin-Filters.xml
new file mode 100644 (file)
index 0000000..93d740d
--- /dev/null
@@ -0,0 +1,11 @@
+<plugin>
+  <workbench id="Features" document="Part">
+    <group id="Collections">
+      <feature id="FiltersSelection"
+               title="Selection filters"
+               internal="1">
+        <selection_filters/>
+      </feature>
+    </group>
+  </workbench>
+</plugin>
index ff4e2157803136dff18487f1ce34fd8159612b83..a30aa6a156fe4558f4f32f1f2c85e8e46e5eb380 100644 (file)
@@ -61,8 +61,8 @@ GeomValidators_Plugin::GeomValidators_Plugin()
   aFactory->registerValidator("GeomValidators_NotSelfIntersected",
                               new GeomValidators_NotSelfIntersected);
 
-  // register this plugin
-  ModelAPI_Session::get()->registerPlugin(this);
+  // Do not register this plugin because it doesn't create features
+  //ModelAPI_Session::get()->registerPlugin(this);
 }
 
 FeaturePtr GeomValidators_Plugin::createFeature(std::string theFeatureID)
index 2e6c3638b5a9fa43f01ae65d7844f3adac929b1b..cd1dcb5d1d534b10e5ec729d656e938c82ee9d69 100644 (file)
@@ -54,6 +54,7 @@ SET(PROJECT_HEADERS
     Model_ResultParameter.h
     Model_FeatureValidator.h
     Model_AttributeValidator.h
+       Model_Filter.h
 )
 
 SET(PROJECT_SOURCES
@@ -90,6 +91,7 @@ SET(PROJECT_SOURCES
     Model_ResultParameter.cpp
     Model_FeatureValidator.cpp
     Model_AttributeValidator.cpp
+       Model_Filter.cpp
 )
 
 SET(PROJECT_LIBRARIES
index 6c2f34378d67bb1c628076d1149ed058fd3d9f0d..3df01a82e3ad7fbf288474def777b4c6a103a6e6 100644 (file)
@@ -60,6 +60,7 @@
 #include <TDF_AttributeIterator.hxx>
 #include <TDF_ChildIterator.hxx>
 #include <TDF_RelocationTable.hxx>
+#include <TDF_ChildIDIterator.hxx>
 #include <TColStd_HArray1OfByte.hxx>
 
 #include <string>
@@ -81,6 +82,10 @@ Standard_GUID kUSER_DEFINED_NAME("9c694d18-a83c-4a56-bc9b-8020628a8244");
 // invalid data
 const static std::shared_ptr<ModelAPI_Data> kInvalid(new Model_Data());
 
+static const Standard_GUID kGroupAttributeGroupID("df64ea4c-fc42-4bf8-ad7e-08f7a54bf1b8");
+static const Standard_GUID kGroupAttributeID("ebdcb22a-e045-455b-9a7f-cfd38d68e185");
+
+
 Model_Data::Model_Data() : mySendAttributeUpdated(true), myWasChangedButBlocked(false)
 {
 }
@@ -153,10 +158,11 @@ bool Model_Data::hasUserDefinedName() const
   return shapeLab().IsAttribute(kUSER_DEFINED_NAME);
 }
 
-AttributePtr Model_Data::addAttribute(const std::string& theID, const std::string theAttrType)
+AttributePtr Model_Data::addAttribute(
+  const std::string& theID, const std::string theAttrType, const int theIndex)
 {
   AttributePtr aResult;
-  int anAttrIndex = int(myAttrs.size()) + 1;
+  int anAttrIndex = theIndex == -1 ? int(myAttrs.size()) + 1 : theIndex;
   TDF_Label anAttrLab = myLab.FindChild(anAttrIndex);
   ModelAPI_Attribute* anAttr = 0;
   if (theAttrType == ModelAPI_AttributeDocRef::typeId()) {
@@ -226,6 +232,75 @@ AttributePtr Model_Data::addAttribute(const std::string& theID, const std::strin
   return aResult;
 }
 
+AttributePtr Model_Data::addFloatingAttribute(
+  const std::string& theID, const std::string theAttrType, const std::string& theGroup)
+{
+  // compute the index of the attribute placement
+  int anIndex;
+  TDF_Label aLab;
+  if (myLab.IsAttribute(TDF_TagSource::GetID())) {
+    TDF_Label aLab = myLab.NewChild(); // already exists a floating attribute, create the next
+    anIndex = aLab.Tag();
+  } else { // put the first floating attribute, quite far from other standard attributes
+    anIndex = int(myAttrs.size()) + 1000;
+    TDF_TagSource::Set(myLab)->Set(anIndex);
+    aLab = myLab.FindChild(anIndex, true);
+  }
+  // store the group ID and the attribute ID (to restore correctly)
+  TDataStd_Name::Set(aLab, kGroupAttributeGroupID, theGroup.c_str());
+  TDataStd_Name::Set(aLab, kGroupAttributeID, theID.c_str());
+
+  return addAttribute(theGroup + "__" + theID, theAttrType, anIndex);
+}
+
+void Model_Data::allGroups(std::list<std::string>& theGroups)
+{
+  std::set<std::string> alreadyThere;
+  for(TDF_ChildIDIterator aGroup(myLab, kGroupAttributeGroupID); aGroup.More(); aGroup.Next()) {
+    Handle(TDataStd_Name) aGroupAttr = Handle(TDataStd_Name)::DownCast(aGroup.Value());
+    std::string aGroupID = TCollection_AsciiString(aGroupAttr->Get()).ToCString();
+    if (alreadyThere.find(aGroupID) == alreadyThere.end()) {
+      theGroups.push_back(aGroupID);
+      alreadyThere.insert(aGroupID);
+    }
+  }
+}
+
+void Model_Data::attributesOfGroup(const std::string& theGroup,
+  std::list<std::shared_ptr<ModelAPI_Attribute> >& theAttrs)
+{
+  for(TDF_ChildIDIterator aGroup(myLab, kGroupAttributeGroupID); aGroup.More(); aGroup.Next()) {
+    Handle(TDataStd_Name) aGroupID = Handle(TDataStd_Name)::DownCast(aGroup.Value());
+    if (aGroupID->Get().IsEqual(theGroup.c_str())) {
+      Handle(TDataStd_Name) anID;
+      if (aGroup.Value()->Label().FindAttribute(kGroupAttributeID, anID)) {
+        TCollection_AsciiString anAsciiID(aGroupID->Get() + "__" + anID->Get());
+        theAttrs.push_back(attribute(anAsciiID.ToCString()));
+      }
+    }
+  }
+}
+
+void Model_Data::removeAttributes(const std::string& theGroup)
+{
+  TDF_LabelList aLabsToRemove; // collect labels that must be erased after the cycle
+  for(TDF_ChildIDIterator aGroup(myLab, kGroupAttributeGroupID); aGroup.More(); aGroup.Next()) {
+    Handle(TDataStd_Name) aGroupID = Handle(TDataStd_Name)::DownCast(aGroup.Value());
+    if (aGroupID->Get().IsEqual(theGroup.c_str())) {
+      Handle(TDataStd_Name) anID;
+      if (aGroup.Value()->Label().FindAttribute(kGroupAttributeID, anID)) {
+        TCollection_AsciiString anAsciiID(aGroupID->Get() + "__" + anID->Get());
+        myAttrs.erase(anAsciiID.ToCString());
+        aLabsToRemove.Append(aGroup.Value()->Label());
+      }
+    }
+  }
+  for(TDF_LabelList::Iterator aLab(aLabsToRemove); aLab.More(); aLab.Next()) {
+    aLab.ChangeValue().ForgetAllAttributes(true);
+  }
+}
+
+
 // macro for the generic returning of the attribute by the ID
 #define GET_ATTRIBUTE_BY_ID(ATTR_TYPE, METHOD_NAME) \
   std::shared_ptr<ATTR_TYPE> Model_Data::METHOD_NAME(const std::string& theID) { \
index 48ec4faae8d0607d7c9c836d0c9b59f98de2cf1e..58c97bd4e81ef249f703ea71f88408b042c53805 100644 (file)
@@ -180,9 +180,29 @@ class Model_Data : public ModelAPI_Data
   /// for each attribute of the object
   /// \param theID identifier of the attribute that can be referenced by this ID later
   /// \param theAttrType type of the created attribute (received from the type method)
+  /// \param theIndex index of the attribute in the internal data structure, for not-floating
+  ///                 attributes it is -1 to let it automatically be added
   /// \returns the just created attribute
   MODEL_EXPORT virtual AttributePtr
-    addAttribute(const std::string& theID, const std::string theAttrType);
+    addAttribute(const std::string& theID, const std::string theAttrType, const int theIndex = -1);
+
+  /// Adds a floating attribute (that may be added/removed during the data life)
+  /// \param theID identifier of the attribute that can be referenced by this ID later
+  /// \param theAttrType type of the created attribute (received from the type method)
+  /// \param theGroup identifier of the group this attribute belongs to, may be an empty string
+  MODEL_EXPORT virtual AttributePtr
+    addFloatingAttribute(const std::string& theID, const std::string theAttrType,
+      const std::string& theGroup);
+
+  /// Returns all groups of this data (ordered).
+  MODEL_EXPORT virtual void allGroups(std::list<std::string>& theGroups);
+
+  /// Returns an ordered list of attributes that belong to the given group
+  MODEL_EXPORT virtual void attributesOfGroup(const std::string& theGroup,
+    std::list<std::shared_ptr<ModelAPI_Attribute> >& theAttrs);
+
+  /// Remove all attributes of the given group
+  MODEL_EXPORT virtual void removeAttributes(const std::string& theGroup);
 
   /// Useful method for "set" methods of the attributes: sends an UPDATE event and
   /// makes attribute initialized
diff --git a/src/Model/Model_Filter.cpp b/src/Model/Model_Filter.cpp
new file mode 100644 (file)
index 0000000..84b0bd5
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 "Model_Filter.h"
+
+#include "ModelAPI_AttributeBoolean.h"
+#include <Events_InfoMessage.h>
+
+
+void Model_FiltersFactory::registerFilter(const std::string& theID, ModelAPI_Filter* theFilter)
+{
+  if (myFilters.find(theID) != myFilters.end()) {
+    Events_InfoMessage("Model_FiltersFactory", "Filter %1 is already registered").arg(theID).send();
+  }
+  else {
+    myFilters[theID] = FilterPtr(theFilter);
+  }
+}
+
+bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature, GeomShapePtr theShape)
+{
+  // prepare all filters args
+  ModelAPI_FiltersArgs anArgs;
+  std::map<FilterPtr, bool> aReverseFlags; /// map of all filters to the reverse values
+  static const std::string& anEmptyType("");
+  std::list<std::shared_ptr<ModelAPI_Attribute> > allAttrs =
+    theFiltersFeature->data()->attributes(anEmptyType);
+  std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = allAttrs.begin();
+  for(; anAttr != allAttrs.end(); anAttr++) {
+    const std::string& anAttrID = (*anAttr)->id();
+    if (anAttrID.find(kFilterSeparator) == std::string::npos) { // possible a filter reverse flag
+      std::shared_ptr<ModelAPI_AttributeBoolean> aReverse = theFiltersFeature->boolean(anAttrID);
+      if (aReverse.get() && myFilters.find(anAttrID) != myFilters.end()) {
+        aReverseFlags[myFilters[anAttrID] ] = aReverse->value();
+      }
+    } else { // an argument of a filter
+      anArgs.add(*anAttr);
+    }
+  }
+  // iterate filters and check shape for validity for all of them
+  std::map<FilterPtr, bool>::iterator aFilter = aReverseFlags.begin();
+  for(; aFilter != aReverseFlags.end(); aFilter++) {
+    bool aResult = aFilter->first->isOk(theShape, anArgs);
+    if (aFilter->second)
+      aResult = !aResult;
+    if (!aResult) // one filter is failed => exit immediately
+      return false;
+  }
+  // all filters are passed
+  return true;
+}
+
+/// Returns list of filters for the given shape type
+/// \param theType a shape type
+std::list<FilterPtr> Model_FiltersFactory::filters(GeomAPI_Shape::ShapeType theType)
+{
+  std::list<FilterPtr> aResult;
+  std::map<std::string, FilterPtr>::const_iterator anIt;
+  std::list<int> aTypes;
+  std::list<int>::const_iterator aTIt;
+  for (anIt = myFilters.cbegin(); anIt != myFilters.cend(); anIt++) {
+    if (anIt->second->isSupported(theType))
+      aResult.push_back(anIt->second);
+  }
+  return aResult;
+}
+
+FilterPtr Model_FiltersFactory::filter(std::string theID)
+{
+  std::map<std::string, FilterPtr>::iterator aFound = myFilters.find(theID);
+  return aFound == myFilters.end() ? FilterPtr() : aFound->second;
+}
+
+std::string Model_FiltersFactory::id(FilterPtr theFilter)
+{
+  std::map<std::string, FilterPtr>::iterator anIter = myFilters.begin();
+  for(; anIter != myFilters.end(); anIter++) {
+    if (anIter->second == theFilter)
+      return anIter->first;
+  }
+  return ""; // unknown case
+}
diff --git a/src/Model/Model_Filter.h b/src/Model/Model_Filter.h
new file mode 100644 (file)
index 0000000..2ccec58
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 Model_Filter_H_
+#define Model_Filter_H_
+
+#include "Model.h"
+
+#include <ModelAPI_Filter.h>
+
+#include <map>
+
+
+/**\class Model_ValidatorsFactory
+* \ingroup DataModel
+* \brief Manages registering of filters
+*/
+class Model_FiltersFactory : public ModelAPI_FiltersFactory
+{
+public:
+  /// Register an instance of a filter
+  /// \param theID unique identifier of the filter, not necessary equal to the name of filter
+  /// \param theFilter the filter's instance
+  virtual void registerFilter(const std::string& theID, ModelAPI_Filter* theFilter);
+
+  /// Returns true if all filters of the Filters feature are ok for the Shape (taking into account
+  /// the Reversed states).
+  /// \param theFiltersFeature feature that contains all information about the filters
+  /// \param theShape the checked shape
+  virtual bool isValid(FeaturePtr theFiltersFeature, GeomShapePtr theShape);
+
+  /// Returns the filters that support the given shape type
+  virtual std::list<FilterPtr> filters(GeomAPI_Shape::ShapeType theType);
+
+  /// Returns a filter by ID
+  virtual FilterPtr filter(std::string theID);
+
+  /// Returns a filter ID by the filter pointer
+  virtual std::string id(FilterPtr theFilter);
+
+protected:
+  /// Get instance from Session
+  Model_FiltersFactory() {}
+
+private:
+  std::map<std::string, FilterPtr> myFilters;  ///< map from ID to registered filters
+
+  friend class Model_Session;
+};
+
+#endif
\ No newline at end of file
index 16f55677b2dc611a97f2c905fe3cf7b942295e4a..b07ca70d4de891b0672757bc5f86c86981a4fcb4 100644 (file)
@@ -26,6 +26,7 @@
 #include <Model_Application.h>
 #include <Model_Events.h>
 #include <Model_Validator.h>
+#include <Model_Filter.h>
 #include <ModelAPI_Events.h>
 #include <Events_Loop.h>
 #include <Events_InfoMessage.h>
@@ -580,6 +581,12 @@ ModelAPI_ValidatorsFactory* Model_Session::validators()
   return aFactory;
 }
 
+ModelAPI_FiltersFactory* Model_Session::filters()
+{
+  static Model_FiltersFactory* aFactory = new Model_FiltersFactory;
+  return aFactory;
+}
+
 int Model_Session::transactionID()
 {
   return ROOT_DOC->transactionID();
index 82e6065e77735631f5c596e817ef536ae5a675d4..9b3da71a89b9e2d77d0a3f989e3c80926c0c5d74 100644 (file)
@@ -131,6 +131,9 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   /// Returns the validators factory: the only one instance per application
   MODEL_EXPORT virtual ModelAPI_ValidatorsFactory* validators();
 
+  /// Returns the filters factory: the only one instance per application
+  MODEL_EXPORT virtual ModelAPI_FiltersFactory* filters();
+
   /// Sets the flag to check modifications outside the transaction or not
   void setCheckTransactions(const bool theCheck)
   {
index 27bf507126f6c65d5064aecd04f5de07aa58e351..58249a22192e844bd8a5ffe50c9e218d4a244ac1 100644 (file)
@@ -65,6 +65,7 @@ SET(PROJECT_HEADERS
     ModelAPI_Tools.h
     ModelAPI_Validator.h
     ModelAPI_Entity.h
+       ModelAPI_Filter.h
 )
 
 SET(PROJECT_SOURCES
index 8ce3e9133a6cbb030bdbaac592096e8cdfe201ee..de771058d6515795882ecba3f8830d88f31ae738 100644 (file)
@@ -133,9 +133,29 @@ class MODELAPI_EXPORT ModelAPI_Data
   /// for each attribute of the object
   /// \param theID identifier of the attribute that can be referenced by this ID later
   /// \param theAttrType type of the created attribute (received from the type method)
+  /// \param theIndex index of the attribute in the internal data structure, for not-floating
+  ///                 attributes it is -1 to let it automatically be added
   /// \returns the just created attribute
+  virtual std::shared_ptr<ModelAPI_Attribute> addAttribute(
+    const std::string& theID, const std::string theAttrType, const int theIndex = -1) = 0;
+
+  /// Adds a floating attribute (that may be added/removed during the data life)
+  /// \param theID identifier of the attribute that can be referenced by this ID later
+  /// \param theAttrType type of the created attribute (received from the type method)
+  /// \param theGroup identifier of the group this attribute belongs to, may be an empty string
   virtual std::shared_ptr<ModelAPI_Attribute>
-    addAttribute(const std::string& theID, const std::string theAttrType) = 0;
+    addFloatingAttribute(const std::string& theID, const std::string theAttrType,
+      const std::string& theGroup) = 0;
+
+  /// Returns all groups of this data (ordered).
+  virtual void allGroups(std::list<std::string>& theGroups) = 0;
+
+  /// Returns an ordered list of attributes that belong to the given group
+  virtual void attributesOfGroup(const std::string& theGroup,
+    std::list<std::shared_ptr<ModelAPI_Attribute> >& theAttrs) = 0;
+
+  /// Remove all attributes of the given group
+  virtual void removeAttributes(const std::string& theGroup) = 0;
 
   /// Useful method for "set" methods of the attributes: sends an UPDATE event and
   /// makes attribute initialized
diff --git a/src/ModelAPI/ModelAPI_Filter.h b/src/ModelAPI/ModelAPI_Filter.h
new file mode 100644 (file)
index 0000000..4399e10
--- /dev/null
@@ -0,0 +1,144 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 ModelAPI_Filter_H_
+#define ModelAPI_Filter_H_
+
+#include "ModelAPI.h"
+#include "ModelAPI_Attribute.h"
+#include "ModelAPI_Feature.h"
+
+#include <GeomAPI_Shape.h>
+#include <map>
+
+/// separator between the filter name and the filter attribute ID
+static const std::string kFilterSeparator = "__";
+
+/// definition of arguments of filters: id of the argument to attributes
+class ModelAPI_FiltersArgs {
+  /// a map from the FilterID+AttributeID -> attribute
+  std::map<std::string, AttributePtr> myMap;
+  std::string myCurrentFilter; ///< ID of the filter that will take attributes now
+public:
+  ModelAPI_FiltersArgs() {}
+
+  /// Sets the current filter ID
+  void setFilter(const std::string& theFilterID) {
+    myCurrentFilter = theFilterID;
+  }
+
+  /// Appends an argument of a filter
+  void add(AttributePtr theAttribute) {
+    myMap[theAttribute->id()] = theAttribute;
+  }
+
+  /// returns the argument of the current filter by the argument id
+  AttributePtr argument(const std::string& theID) {
+    return myMap.find(myCurrentFilter + kFilterSeparator + theID)->second;
+  }
+
+};
+
+/**\class ModelAPI_ViewFilter
+* \ingroup DataModel
+* \brief A general interface class filters definition
+*/
+class ModelAPI_Filter
+{
+public:
+  /// Returns name of the filter to represent it in GUI
+  virtual const std::string& name() const = 0;
+
+  /// Returns true if the given shape type is supported
+  virtual bool isSupported(GeomAPI_Shape::ShapeType theType) const = 0;
+
+  /// This method should contain the filter logic. It returns true if the given shape
+  /// is accepted by the filter.
+  /// \param theShape the given shape
+  virtual bool isOk(const GeomShapePtr& theShape, const ModelAPI_FiltersArgs& theArgs) const = 0;
+
+private:
+  bool myIsReverse;
+};
+
+typedef std::shared_ptr<ModelAPI_Filter> FilterPtr;
+
+
+/**\class ModelAPI_FiltersFactory
+* \ingroup DataModel
+* \brief Manages registering of filters
+*/
+class ModelAPI_FiltersFactory
+{
+public:
+  /// Register an instance of a filter
+  /// \param theID unique identifier of the filter, not necessary equal to the name of filter
+  /// \param theFilter the filter's instance
+  virtual void registerFilter(const std::string& theID, ModelAPI_Filter* theFilter) = 0;
+
+  /// Returns true if all filters of the Filters feature are ok for the Shape (taking into account
+  /// the Reversed states).
+  /// \param theFiltersFeature feature that contains all information about the filters
+  /// \param theShape the checked shape
+  virtual bool isValid(FeaturePtr theFiltersFeature, GeomShapePtr theShape) = 0;
+
+  /// Returns the filters that support the given shape type
+  virtual std::list<FilterPtr> filters(GeomAPI_Shape::ShapeType theType) = 0;
+
+  /// Returns a filter by ID
+  virtual FilterPtr filter(std::string theID) = 0;
+
+  /// Returns a filter ID by the filter pointer
+  virtual std::string id(FilterPtr theFilter) = 0;
+
+protected:
+  /// Get instance from Session
+  ModelAPI_FiltersFactory() {}
+};
+
+/**\class ModelAPI_FiltersFeature
+* \ingroup DataModel
+* \brief An interface for working with filters in the feature. A filters feature must inherit it
+*       in order to allow management of filters in the feature data structure.
+*/
+class ModelAPI_FiltersFeature
+{
+public:
+  /// Adds a filter to the feature. Also initializes arguments of this filter.
+  virtual void addFilter(const std::string theFilterID) = 0;
+
+  /// Removes an existing filter from the feature.
+  virtual void removeFilter(const std::string theFilterID) = 0;
+
+  /// Returns the list of existing filters in the feature.
+  virtual std::list<std::string> filters() const = 0;
+
+  /// Stores the reversed flag for the filter.
+  virtual void setReversed(const std::string theFilterID, const bool theReversed) = 0;
+
+  /// Returns the reversed flag value for the filter.
+  virtual bool isReversed(const std::string theFilterID) = 0;
+
+  /// Returns the ordered list of attributes related to the filter.
+  virtual std::list<AttributePtr> filterArgs(const std::string theFilterID) const = 0;
+};
+
+typedef std::shared_ptr<ModelAPI_FiltersFeature> FiltersFeaturePtr;
+
+#endif
\ No newline at end of file
index 87d2350fda3f68c09be67158a4c08bc44412b21f..84a925aa2074672160275cbdc948ff6a92039d51 100644 (file)
@@ -29,6 +29,7 @@ class ModelAPI_Feature;
 class ModelAPI_Plugin;
 class ModelAPI_Document;
 class ModelAPI_ValidatorsFactory;
+class ModelAPI_FiltersFactory;
 
 /**\class ModelAPI_Session
  * \ingroup DataModel
@@ -120,6 +121,9 @@ class MODELAPI_EXPORT ModelAPI_Session
   /// Returns the validators factory: the only one instance per application
   virtual ModelAPI_ValidatorsFactory* validators() = 0;
 
+  /// Returns the filters factory: the only one instance per application
+  virtual ModelAPI_FiltersFactory* filters() = 0;
+
   /// To virtually destroy the fields of successors
   virtual ~ModelAPI_Session()
   {
index ba2d74969d98b9447aff8161b3ac26aed929d023..e36810a0aaf78764499ba3ea2ec190d8dc0b20e6 100644 (file)
@@ -103,6 +103,7 @@ SET(PROJECT_HEADERS
   ModuleBase_WidgetRadiobox.h
   ModuleBase_WidgetPointInput.h
   ModuleBase_ITreeNode.h
+  ModuleBase_WidgetSelectionFilter.h
 )
 
 SET(PROJECT_MOC_HEADERS
@@ -152,6 +153,7 @@ SET(PROJECT_MOC_HEADERS
   ModuleBase_WidgetNameEdit.h
   ModuleBase_WidgetRadiobox.h
   ModuleBase_WidgetPointInput.h
+  ModuleBase_WidgetSelectionFilter.h
 )
 
 SET(PROJECT_SOURCES
@@ -220,6 +222,7 @@ SET(PROJECT_SOURCES
   ModuleBase_WidgetNameEdit.cpp
   ModuleBase_WidgetRadiobox.cpp
   ModuleBase_WidgetPointInput.cpp
+  ModuleBase_WidgetSelectionFilter.cpp
 )
 
 SET(PROJECT_LIBRARIES
index 48cf5304f5e4fbd1408813d1b08fdf09e1c1e5de..1c887faa49d28a30870458d79fff76f5d171c3bf 100644 (file)
@@ -37,7 +37,7 @@ ModuleBase_ChoiceCtrl::ModuleBase_ChoiceCtrl(QWidget* theParent,
  : QWidget(theParent), myType(theType)
 {
   QHBoxLayout* aLayout = new QHBoxLayout(this);
-  ModuleBase_Tools::adjustMargins(aLayout);
+  aLayout->setContentsMargins(0, 0, 0, 0);
 
   switch (myType) {
   case RadioButtons:
index 919ef16a762d5019825ca454cd3a255ae46d6def..23728c5696ed0be83a2054d8285c930db7659681 100644 (file)
@@ -50,6 +50,7 @@
 #include <ModuleBase_WidgetCreatorFactory.h>
 #include <ModuleBase_WidgetAction.h>
 #include <ModuleBase_WidgetPointInput.h>
+#include <ModuleBase_WidgetSelectionFilter.h>
 
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Session.h>
@@ -344,6 +345,8 @@ ModuleBase_ModelWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::
     result = new ModuleBase_WidgetAction(theParent, myWidgetApi);
   } else if (theType == WDG_POINT_INPUT) {
     result = new ModuleBase_WidgetPointInput(theParent, myWorkshop, myWidgetApi);
+  } else if (theType == WDG_SELECTION_FILTERS) {
+    result = new ModuleBase_WidgetSelectionFilter(theParent, myWorkshop, myWidgetApi);
   } else {
     result = myWorkshop->module()->createWidgetByType(theType, theParent, myWidgetApi);
     if (!result)
index 675b2f0860033e55ee2dcbe8665ea706a2d81fd4..33fdafa0aeb9c2fb0a13a075cbf37dadaba72b2f 100644 (file)
@@ -37,6 +37,7 @@
 #include <ModuleBase_ViewerPrs.h>
 #include <ModuleBase_WidgetShapeSelector.h>
 #include <ModuleBase_ChoiceCtrl.h>
+#include <ModuleBase_WidgetSelectionFilter.h>
 
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Object.h>
@@ -112,21 +113,21 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen
                                                                const Config_WidgetAPI* theData)
 : ModuleBase_WidgetSelector(theParent, theWorkshop, theData),
   myIsSetSelectionBlocked(false), myCurrentHistoryIndex(-1),
-  myIsFirst(true)
+  myIsFirst(true), myFiltersWgt(0)
 {
   std::string aPropertyTypes = theData->getProperty("type_choice");
   QString aTypesStr = aPropertyTypes.c_str();
   myShapeTypes = aTypesStr.split(' ', QString::SkipEmptyParts);
   myIsUseChoice = theData->getBooleanAttribute("use_choice", false);
 
-  QGridLayout* aMainLay = new QGridLayout(this);
+  QVBoxLayout* aMainLay = new QVBoxLayout(this);
   ModuleBase_Tools::adjustMargins(aMainLay);
 
   QStringList aIconsList = getIconsList(myShapeTypes);
   myTypeCtrl = new ModuleBase_ChoiceCtrl(this, myShapeTypes, aIconsList);
   myTypeCtrl->setLabel(tr("Type"));
   myTypeCtrl->setValue(0);
-  aMainLay->addWidget(myTypeCtrl, 0, 0, 1, 2);
+  aMainLay->addWidget(myTypeCtrl);
   myDefMode = myShapeTypes.first().toStdString();
 
   // There is no sense to parameterize list of types while we can not parameterize selection mode
@@ -136,18 +137,30 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen
   }
 
   QString aLabelText = translate(theData->getProperty("label"));
-  QLabel* aListLabel = new QLabel(aLabelText, this);
-  aMainLay->addWidget(aListLabel, 1, 0);
-  // if the xml definition contains one type, an information label
-  // should be shown near to the latest
-  if (myShapeTypes.size() <= 1) {
-    QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
-    if (!aLabelIcon.isEmpty()) {
-      QLabel* aSelectedLabel = new QLabel("", this);
-      aSelectedLabel->setPixmap(ModuleBase_IconFactory::loadPixmap(aLabelIcon));
-      aMainLay->addWidget(aSelectedLabel, 1, 1);
+  if (aLabelText.size() > 0) {
+    QWidget* aLabelWgt = new QWidget(this);
+    QHBoxLayout* aLabelLayout = new QHBoxLayout(aLabelWgt);
+    aLabelLayout->setContentsMargins(0, 0, 0, 0);
+    aMainLay->addWidget(aLabelWgt);
+
+    QLabel* aListLabel = new QLabel(aLabelText, this);
+    aLabelLayout->addWidget(aListLabel);
+    // if the xml definition contains one type, an information label
+    // should be shown near to the latest
+    if (myShapeTypes.size() <= 1) {
+      QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
+      if (!aLabelIcon.isEmpty()) {
+        QLabel* aSelectedLabel = new QLabel("", this);
+        aSelectedLabel->setPixmap(ModuleBase_IconFactory::loadPixmap(aLabelIcon));
+        aLabelLayout->addWidget(aSelectedLabel);
+        aLabelLayout->addStretch(1);
+      }
     }
-    aMainLay->setColumnStretch(2, 1);
+  }
+  std::string aUseFilters = theData->getProperty("use_filters");
+  if (aUseFilters.length() > 0) {
+    myFiltersWgt = new ModuleBase_FilterStarter(aUseFilters.c_str(), this, theWorkshop);
+    aMainLay->addWidget(myFiltersWgt);
   }
 
   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
@@ -157,8 +170,7 @@ ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParen
   connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem()));
   connect(myListView, SIGNAL(listActivated()), SLOT(onListActivated()));
 
-  aMainLay->addWidget(myListView->getControl(), 2, 0, 1, -1);
-  aMainLay->setRowStretch(2, 1);
+  aMainLay->addWidget(myListView->getControl());
   connect(myTypeCtrl, SIGNAL(valueChanged(int)), this, SLOT(onSelectionTypeChanged()));
 
   bool aSameTop = theData->getBooleanAttribute("same_topology", false);
@@ -498,6 +510,7 @@ void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
 {
   // Clear current selection in order to avoid updating of object browser with obsolete indexes
   // which can appear because of results deletetion after changing a type of selection
+  QString aSelectionType = myTypeCtrl->textValue();
   QList<ModuleBase_ViewerPrsPtr> aEmptyList;
   myWorkshop->setSelected(aEmptyList);
 
@@ -511,7 +524,7 @@ void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
   std::string aType = anAttribute->attributeType();
   if (aType == ModelAPI_AttributeSelectionList::typeId()) {
     AttributeSelectionListPtr aSelectionListAttr = myFeature->data()->selectionList(attributeID());
-    aSelectionListAttr->setSelectionType(myTypeCtrl->textValue().toStdString());
+    aSelectionListAttr->setSelectionType(aSelectionType.toStdString());
   }
 
   // clear attribute values
index f65d09a70e0d2b9c7cca4b76899818c311c7a9d9..b77ea969fee5ae2590218f35fbe9471f50ed3f32 100644 (file)
@@ -41,6 +41,7 @@ class QCheckBox;
 class ModuleBase_ListView;
 class ModuleBase_IWorkshop;
 class ModuleBase_ChoiceCtrl;
+class ModuleBase_FilterStarter;
 
 /**
 * \ingroup GUI
@@ -251,6 +252,7 @@ protected:
   std::string myDefMode;
 
   QCheckBox* myGeomCheck;
+  ModuleBase_FilterStarter* myFiltersWgt;
 };
 
 #endif /* MODULEBASE_WIDGETFILESELECTOR_H_ */
diff --git a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp
new file mode 100644 (file)
index 0000000..5112ba6
--- /dev/null
@@ -0,0 +1,467 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 "ModuleBase_WidgetSelectionFilter.h"
+#include "ModuleBase_Tools.h"
+#include "ModuleBase_IWorkshop.h"
+#include "ModuleBase_IModule.h"
+#include "ModuleBase_IViewer.h"
+#include "ModuleBase_IPropertyPanel.h"
+#include "ModuleBase_PageWidget.h"
+#include "ModuleBase_WidgetMultiSelector.h"
+#include "ModuleBase_ResultPrs.h"
+
+#include <ModelAPI_Session.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <GeomAPI_ShapeExplorer.h>
+
+#include <AIS_InteractiveContext.hxx>
+#include <StdSelect_BRepOwner.hxx>
+#include <TopoDS_Compound.hxx>
+#include <BRep_Builder.hxx>
+
+#include <QLayout>
+#include <QPushButton>
+#include <QLabel>
+#include <QComboBox>
+#include <QGroupBox>
+#include <QDialog>
+#include <QToolButton>
+
+static FeaturePtr SelectorFeature;
+static std::string AttributeId;
+
+
+GeomAPI_Shape::ShapeType selectionType(const QString& theType)
+{
+  QString aType = theType.toUpper();
+  if ((aType == "VERTEX") || (aType == "VERTICES"))
+    return GeomAPI_Shape::VERTEX;
+  else if ((aType == "EDGE") || (aType == "EDGES"))
+    return GeomAPI_Shape::EDGE;
+  else if ((aType == "WIRE") || (aType == "WIRES"))
+    return GeomAPI_Shape::WIRE;
+  else if ((aType == "FACE") || (aType == "FACES"))
+    return GeomAPI_Shape::FACE;
+  else if ((aType == "SHELL") || (aType == "SHELLS"))
+    return GeomAPI_Shape::SHELL;
+  else if ((aType == "SOLID") || (aType == "SOLIDS"))
+    return GeomAPI_Shape::SOLID;
+  else if ((aType == "COMPSOLID") || (aType == "COMPSOLIDS"))
+    return GeomAPI_Shape::COMPSOLID;
+  else if ((aType == "COMPOUND") || (aType == "COMPOUNDS"))
+    return GeomAPI_Shape::COMPOUND;
+  else
+    return GeomAPI_Shape::SHAPE;
+}
+
+
+ModuleBase_FilterStarter::ModuleBase_FilterStarter(const std::string& theFeature,
+  QWidget* theParent, ModuleBase_IWorkshop* theWorkshop)
+  : QWidget(theParent),
+  myFeatureName(theFeature),
+  myWorkshop(theWorkshop)
+{
+  QHBoxLayout* aMainLayout = new QHBoxLayout(this);
+  ModuleBase_Tools::adjustMargins(aMainLayout);
+
+  aMainLayout->addStretch(1);
+  QPushButton* aLaunchBtn = new QPushButton(tr("Selection by filters"), this);
+  connect(aLaunchBtn, SIGNAL(clicked()), SLOT(onFiltersLaunch()));
+  aMainLayout->addWidget(aLaunchBtn);
+
+  myFilterLbl = new QLabel(this);
+  myFilterLbl->setPixmap(QPixmap(":pictures/filter.png"));
+  aMainLayout->addWidget(myFilterLbl);
+
+  myModifyLbl = new QLabel(this);
+  myModifyLbl->setPixmap(QPixmap(":pictures/plus_minus.png"));
+  aMainLayout->addWidget(myModifyLbl);
+  aMainLayout->addStretch(1);
+
+  myFilterLbl->hide();
+  myModifyLbl->hide();
+}
+
+void ModuleBase_FilterStarter::onFiltersLaunch()
+{
+  ModuleBase_WidgetMultiSelector* aSelector =
+    dynamic_cast<ModuleBase_WidgetMultiSelector*>(parent());
+  SelectorFeature = aSelector->feature();
+  AttributeId = aSelector->attributeID();
+
+  // Launch Filters operation
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+    (myWorkshop->module()->createOperation(myFeatureName));
+  myWorkshop->processLaunchOperation(aFOperation);
+}
+
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+ModuleBase_FilterItem::ModuleBase_FilterItem(
+  const std::string& theFilter, FeaturePtr theSelection, QWidget* theParent)
+  : QWidget(theParent), myFilterID(theFilter),
+    mySelection(std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(theSelection))
+{
+  QHBoxLayout* aLayout = new QHBoxLayout(this);
+  aLayout->setContentsMargins(0, 0, 0, 0);
+
+  // Reverse filter button
+  myRevBtn = new QToolButton(this);
+  myRevBtn->setCheckable(true);
+  myRevBtn->setChecked(false);
+  myRevBtn->setAutoRaise(true);
+  myRevBtn->setIcon(QIcon(":pictures/accept.png"));
+  myRevBtn->setToolTip(tr("Reverse the filter"));
+  connect(myRevBtn, SIGNAL(toggled(bool)), SLOT(onReverse(bool)));
+  aLayout->addWidget(myRevBtn);
+
+  const std::string& aFilterName = ModelAPI_Session::get()->filters()->filter(myFilterID)->name();
+  aLayout->addWidget(new QLabel(aFilterName.c_str(), this), 1);
+
+  QToolButton* aDelBtn = new QToolButton(this);
+  aDelBtn->setIcon(QIcon(":pictures/button_cancel.png"));
+  aDelBtn->setAutoRaise(true);
+  aDelBtn->setToolTip(tr("Delete the filter"));
+  connect(aDelBtn, SIGNAL(clicked(bool)), SLOT(onDelete()));
+  aLayout->addWidget(aDelBtn);
+
+  myRevBtn->setChecked(mySelection->isReversed(myFilterID));
+}
+
+
+void ModuleBase_FilterItem::onReverse(bool theCheck)
+{
+  mySelection->setReversed(myFilterID, theCheck);
+  if (theCheck)
+    myRevBtn->setIcon(QIcon(":pictures/stop.png"));
+  else
+    myRevBtn->setIcon(QIcon(":pictures/accept.png"));
+}
+
+void ModuleBase_FilterItem::onDelete()
+{
+  emit deleteItem(this);
+}
+
+
+//*****************************************************************************
+//*****************************************************************************
+//*****************************************************************************
+ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theParent,
+  ModuleBase_IWorkshop* theWorkshop, const Config_WidgetAPI* theData)
+  : ModuleBase_ModelWidget(theParent, theData),
+  myWorkshop(theWorkshop),
+  mySelectorFeature(SelectorFeature),
+  mySelectorAttribute(AttributeId)
+{
+  // Clear Old selection
+  AttributePtr aAttr = SelectorFeature->attribute(AttributeId);
+  AttributeSelectionListPtr aSelListAttr =
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aAttr);
+  mySelectionType = selectionType(aSelListAttr->selectionType().c_str());
+  aSelListAttr->clear();
+
+  // Define widgets
+  QVBoxLayout* aMainLayout = new QVBoxLayout(this);
+  ModuleBase_Tools::adjustMargins(aMainLayout);
+
+  myFiltersGroup = new QGroupBox(tr("Dynamic Filters"), this);
+  myGroupLayout = new QVBoxLayout(myFiltersGroup);
+  myGroupLayout->setContentsMargins(0, 0, 0, 0);
+  myGroupLayout->setSpacing(0);
+
+  QWidget* aFiltersWgt = new QWidget(myFiltersGroup);
+  QHBoxLayout* aFiltersLay = new QHBoxLayout(aFiltersWgt);
+  ModuleBase_Tools::adjustMargins(aFiltersLay);
+
+  QLabel* aFilterLbl = new QLabel(aFiltersWgt);
+  aFilterLbl->setPixmap(QPixmap(":pictures/filter.png"));
+
+  myFiltersCombo = new QComboBox(aFiltersWgt);
+  SessionPtr aSession = ModelAPI_Session::get();
+  std::list<FilterPtr> allFilters =
+    aSession->filters()->filters((GeomAPI_Shape::ShapeType) mySelectionType);
+  QStringList aItems;
+  std::list<FilterPtr>::const_iterator aIt;
+  for (aIt = allFilters.cbegin(); aIt != allFilters.cend(); aIt++) {
+    aItems.push_back((*aIt)->name().c_str());
+    myFilters.push_back(aSession->filters()->id(*aIt));
+  }
+  myFiltersCombo->addItems(aItems);
+
+  QToolButton* aAddBtn = new QToolButton(aFiltersWgt);
+  aAddBtn->setIcon(QIcon(":pictures/add.png"));
+  aAddBtn->setAutoRaise(true);
+  aAddBtn->setToolTip(tr("Add the current filter"));
+  connect(aAddBtn, SIGNAL(clicked()), SLOT(onAddItem()));
+
+  aFiltersLay->addWidget(aFilterLbl);
+  aFiltersLay->addWidget(myFiltersCombo, 1);
+  aFiltersLay->addWidget(aAddBtn);
+
+  myGroupLayout->addWidget(aFiltersWgt);
+
+  aMainLayout->addWidget(myFiltersGroup);
+
+  // Select Button
+  QWidget* aBtnWgt = new QWidget(this);
+  QHBoxLayout* aBtnLayout = new QHBoxLayout(aBtnWgt);
+  ModuleBase_Tools::adjustMargins(aBtnLayout);
+
+  aBtnLayout->addStretch(1);
+
+  mySelectBtn = new QPushButton(tr("Select"), aBtnWgt);
+  connect(mySelectBtn, SIGNAL(clicked()), SLOT(onSelect()));
+  aBtnLayout->addWidget(mySelectBtn);
+
+  aMainLayout->addWidget(aBtnWgt);
+
+  // Label widgets
+  QWidget* aLblWgt = new QWidget(this);
+  QHBoxLayout* aLblLayout = new QHBoxLayout(aLblWgt);
+  ModuleBase_Tools::adjustMargins(aLblLayout);
+
+  aLblLayout->addWidget(new QLabel(tr("Number of selected objects:"), aLblWgt));
+
+  myNbLbl = new QLabel("0", aLblWgt);
+  aLblLayout->addWidget(myNbLbl);
+
+  aMainLayout->addWidget(aLblWgt);
+
+  // Show only button
+  QWidget* aBtn2Wgt = new QWidget(this);
+  QHBoxLayout* aBtn2Layout = new QHBoxLayout(aBtn2Wgt);
+  ModuleBase_Tools::adjustMargins(aBtn2Layout);
+
+  aBtn2Layout->addStretch(1);
+
+  myShowBtn = new QPushButton(tr("Show only"), aBtn2Wgt);
+  myShowBtn->setCheckable(true);
+  connect(myShowBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool)));
+  aBtn2Layout->addWidget(myShowBtn);
+
+  aMainLayout->addWidget(aBtn2Wgt);
+
+  aMainLayout->addStretch(1);
+
+  updateSelectBtn();
+}
+
+ModuleBase_WidgetSelectionFilter::~ModuleBase_WidgetSelectionFilter()
+{
+  myValues.clear();
+  if (!myPreview.IsNull()) {
+    Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
+    aCtx->Remove(myPreview, false);
+    myPreview.Nullify();
+    if (myShowBtn->isChecked()) {
+      AIS_ListOfInteractive::const_iterator aIt;
+      Handle(AIS_Shape) aShapeIO;
+      for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
+        aShapeIO = Handle(AIS_Shape)::DownCast(*aIt);
+        if (!aShapeIO.IsNull()) {
+          aCtx->Display(aShapeIO, false);
+        }
+      }
+    }
+    aCtx->UpdateCurrentViewer();
+  }
+  SelectorFeature = FeaturePtr();
+  AttributeId = "";
+}
+
+void ModuleBase_WidgetSelectionFilter::onAddItem()
+{
+  int aId = myFiltersCombo->currentIndex();
+  myFiltersCombo->removeItem(aId);
+
+  std::list<std::string>::iterator aIt;
+  int i;
+  std::string aFilter;
+  for (aIt = myFilters.begin(), i = 0; aIt != myFilters.cend(); i++, aIt++) {
+    if (i == aId) {
+      aFilter = (*aIt);
+      myFilters.erase(aIt);
+      break;
+    }
+  }
+  if (!aFilter.empty()) {
+    myUseFilters.push_back(aFilter);
+    ModuleBase_FilterItem* aItem =
+      new ModuleBase_FilterItem(aFilter, mySelectorFeature, myFiltersGroup);
+    connect(aItem, SIGNAL(deleteItem(ModuleBase_FilterItem*)),
+      SLOT(onDeleteItem(ModuleBase_FilterItem*)));
+    myGroupLayout->addWidget(aItem);
+  }
+  updateSelectBtn();
+  clearCurrentSelection(true);
+  updateNumberSelected();
+}
+
+void ModuleBase_WidgetSelectionFilter::onDeleteItem(ModuleBase_FilterItem* theItem)
+{
+  std::string aFilter = theItem->filter();
+  myGroupLayout->removeWidget(theItem);
+  theItem->deleteLater();
+
+  myUseFilters.remove(aFilter);
+  myFilters.push_back(aFilter);
+  myFiltersCombo->addItem(ModelAPI_Session::get()->filters()->filter(aFilter)->name().c_str());
+
+  updateSelectBtn();
+  clearCurrentSelection(true);
+  updateNumberSelected();
+}
+
+void ModuleBase_WidgetSelectionFilter::onSelect()
+{
+  if (myUseFilters.size() == 0)
+    return;
+  Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
+  if (aCtx.IsNull())
+    return;
+
+  clearCurrentSelection();
+
+  BRep_Builder aBuilder;
+  TopoDS_Compound aComp;
+  aBuilder.MakeCompound(aComp);
+
+  if (!myShowBtn->isChecked()) {
+    myListIO.Clear();
+    aCtx->DisplayedObjects(AIS_KOI_Shape, -1, myListIO);
+    if (!myPreview.IsNull())
+      myListIO.Remove(myPreview);
+  }
+  AIS_ListOfInteractive::const_iterator aIt;
+  Handle(ModuleBase_ResultPrs) aShapeIO;
+  for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
+    aShapeIO = Handle(ModuleBase_ResultPrs)::DownCast(*aIt);
+    if (!aShapeIO.IsNull()) {
+      GeomShapePtr aShape(new GeomAPI_Shape);
+      aShape->setImpl(new TopoDS_Shape(aShapeIO->Shape()));
+      std::list<GeomShapePtr> aSubShapes =
+        aShape->subShapes((GeomAPI_Shape::ShapeType)mySelectionType);
+      std::list<GeomShapePtr>::const_iterator aShapesIt;
+      for (aShapesIt = aSubShapes.cbegin(); aShapesIt != aSubShapes.cend(); aShapesIt++) {
+        GeomShapePtr aShape = (*aShapesIt);
+        SessionPtr aSession = ModelAPI_Session::get();
+        bool isValid = aSession->filters()->isValid(myFeature, aShape);
+        if (isValid) {
+          TopoDS_Shape aTShape = aShape->impl<TopoDS_Shape>();
+          Handle(StdSelect_BRepOwner) aOwner = new StdSelect_BRepOwner(aTShape, aShapeIO, true);
+          aBuilder.Add(aComp, aTShape);
+
+          ModuleBase_ViewerPrsPtr aValue(new ModuleBase_ViewerPrs(aShapeIO->getResult(), aShape, aOwner));
+          myValues.append(aValue);
+        }
+      }
+    }
+  }
+  if (myValues.size() > 0)
+    updatePreview(aComp);
+  updateNumberSelected();
+}
+
+void ModuleBase_WidgetSelectionFilter::updatePreview(const TopoDS_Shape& theShape)
+{
+  Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
+  if (aCtx.IsNull())
+    return;
+
+  if (myPreview.IsNull()) {
+    myPreview = new AIS_Shape(theShape);
+    myPreview->SetDisplayMode(myShowBtn->isChecked()? AIS_Shaded : AIS_WireFrame);
+    myPreview->SetColor(Quantity_NOC_YELLOW);
+    myPreview->SetTransparency();
+    aCtx->Display(myPreview, true);
+    aCtx->Deactivate(myPreview);
+  }
+  else {
+    myPreview->Set(theShape);
+    aCtx->Redisplay(myPreview, true);
+  }
+}
+
+
+void ModuleBase_WidgetSelectionFilter::onShowOnly(bool theErase)
+{
+  if (myPreview.IsNull())
+    return;
+  Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
+
+  if (theErase) {
+    aCtx->SetDisplayMode(myPreview, AIS_Shaded, false);
+    myListIO.Clear();
+    aCtx->DisplayedObjects(AIS_KOI_Shape, -1, myListIO);
+    myListIO.Remove(myPreview);
+  }
+  else {
+    aCtx->SetDisplayMode(myPreview, AIS_WireFrame, false);
+  }
+  AIS_ListOfInteractive::const_iterator aIt;
+  Handle(AIS_Shape) aShapeIO;
+  for (aIt = myListIO.cbegin(); aIt != myListIO.cend(); aIt++) {
+    aShapeIO = Handle(AIS_Shape)::DownCast(*aIt);
+    if (!aShapeIO.IsNull()) {
+      if (theErase)
+        aCtx->Erase(aShapeIO, false);
+      else
+        aCtx->Display(aShapeIO, false);
+    }
+  }
+  aCtx->UpdateCurrentViewer();
+}
+
+void ModuleBase_WidgetSelectionFilter::updateSelectBtn()
+{
+  mySelectBtn->setEnabled(myUseFilters.size() > 0);
+}
+
+void ModuleBase_WidgetSelectionFilter::updateNumberSelected()
+{
+  myNbLbl->setText(QString::number(myValues.size()));
+}
+QList<QWidget*> ModuleBase_WidgetSelectionFilter::getControls() const
+{
+  return QList<QWidget*>();
+}
+
+void ModuleBase_WidgetSelectionFilter::clearCurrentSelection(bool toUpdate)
+{
+  myValues.clear();
+  if (!myPreview.IsNull()) {
+    Handle(AIS_InteractiveContext) aCtx = myWorkshop->viewer()->AISContext();
+    aCtx->Remove(myPreview, toUpdate);
+    myPreview.Nullify();
+  }
+}
+
+void ModuleBase_WidgetSelectionFilter::onFeatureAccepted()
+{
+  AttributePtr aAttr = mySelectorFeature->attribute(mySelectorAttribute);
+  AttributeSelectionListPtr aSelListAttr =
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aAttr);
+  aSelListAttr->clear();
+  foreach(ModuleBase_ViewerPrsPtr aPrs, myValues) {
+    aSelListAttr->append(aPrs->object(), aPrs->shape());
+  }
+}
\ No newline at end of file
diff --git a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h
new file mode 100644 (file)
index 0000000..2fe5b05
--- /dev/null
@@ -0,0 +1,148 @@
+// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+//
+// 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 ModuleBase_WidgetSelectionFilter_H
+#define ModuleBase_WidgetSelectionFilter_H
+
+#include "ModuleBase.h"
+#include "ModuleBase_ModelWidget.h"
+#include "ModuleBase_ViewerPrs.h"
+
+#include <ModelAPI_Filter.h>
+
+#include <SelectMgr_IndexedMapOfOwner.hxx>
+#include <AIS_Shape.hxx>
+#include <AIS_ListOfInteractive.hxx>
+
+#include <QWidget>
+#include <QList>
+
+class QLabel;
+class QComboBox;
+class QGroupBox;
+class QToolButton;
+class QVBoxLayout;
+class QPushButton;
+
+class ModuleBase_IWorkshop;
+
+class MODULEBASE_EXPORT ModuleBase_FilterStarter: public QWidget
+{
+  Q_OBJECT
+public:
+  ModuleBase_FilterStarter(const std::string& theFeature, QWidget* theParent,
+    ModuleBase_IWorkshop* theWorkshop);
+
+  ~ModuleBase_FilterStarter() {}
+
+private slots:
+  void onFiltersLaunch();
+
+private:
+  std::string myFeatureName;
+  ModuleBase_IWorkshop* myWorkshop;
+
+  QLabel* myFilterLbl;
+  QLabel* myModifyLbl;
+};
+
+
+class ModuleBase_FilterItem : public QWidget
+{
+  Q_OBJECT
+public:
+  ModuleBase_FilterItem(const std::string& theFilter, FeaturePtr theSelection, QWidget* theParent);
+
+  std::string filter() const { return myFilterID; }
+
+signals:
+  void deleteItem(ModuleBase_FilterItem* theItem);
+
+  private slots:
+  void onReverse(bool theCheck);
+  void onDelete();
+
+private:
+  std::string myFilterID;
+  FiltersFeaturePtr mySelection;
+  QToolButton* myRevBtn;
+};
+
+class ModuleBase_WidgetSelectionFilter : public ModuleBase_ModelWidget
+{
+  Q_OBJECT
+public:
+  ModuleBase_WidgetSelectionFilter(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop,
+    const Config_WidgetAPI* theData);
+
+  ~ModuleBase_WidgetSelectionFilter();
+
+  /// Returns list of widget controls
+  /// \return a control list
+  virtual QList<QWidget*> getControls() const;
+
+  /// It is called when user press Ok or OkPlus buttons in the parent property panel
+  /// By default this slot does nothing
+  virtual void onFeatureAccepted();
+
+protected:
+  /// Saves the internal parameters to the given feature (not ussed for this widget)
+  /// \return True in success
+  virtual bool storeValueCustom() { return true; }
+
+  /// Restore value from attribute data to the widget's control (not ussed for this widget)
+  virtual bool restoreValueCustom() { return true; }
+
+private slots:
+  void onAddItem();
+  void onDeleteItem(ModuleBase_FilterItem* theItem);
+  void onSelect();
+  void onShowOnly(bool theErase);
+
+private:
+  void updateSelectBtn();
+  void updateNumberSelected();
+  void clearCurrentSelection(bool toUpdate = false);
+  void updatePreview(const TopoDS_Shape& theShape);
+
+private:
+  ModuleBase_IWorkshop* myWorkshop;
+
+  QComboBox* myFiltersCombo;
+  QGroupBox* myFiltersGroup;
+  QVBoxLayout* myGroupLayout;
+  QPushButton* mySelectBtn;
+  QLabel* myNbLbl;
+  QPushButton* myShowBtn;
+
+  int mySelectionType;
+  std::list<std::string> myFilters;
+  std::list<std::string> myUseFilters;
+
+  QList<ModuleBase_ViewerPrsPtr> myValues;
+  Handle(AIS_Shape) myPreview;
+
+  AIS_ListOfInteractive myListIO;
+
+  FeaturePtr mySelectorFeature;
+  std::string mySelectorAttribute;
+};
+
+
+#endif
\ No newline at end of file
index 0cb122ec6178469aab99eba4995996695d93817b..a201d5d385578e0ed9a50736a2c775d69a0b2d93 100644 (file)
@@ -382,10 +382,6 @@ bool PartSet_WidgetSketchCreator::startSketchOperation(
   bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
 
-  // Launch Sketch operation
-  CompositeFeaturePtr aCompFeature =
-    std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
-
   // start edit operation for the sketch
   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                                             (myModule->createOperation("Sketch"));
index 8efbae6c6b5adf79876d91702b32587744b81551..0df020d32709e1d064f06002f68f1d6cb67b3c3b 100644 (file)
@@ -895,8 +895,6 @@ void XGUI_ContextMenuMgr::addFeatures(QMenu* theMenu) const
       // Exit if the selected index belongs to non active document
       if (aIsRoot && (aActiveDoc != aMgr->moduleDocument()))
         return;
-      if ((!aIsRoot) && (aIdx.internalPointer() != aActiveDoc.get()))
-        return;
 
       // Get name of the selected index
       aName = aIdx.data().toString();
index f5805c328f57788d7aa0d7ef47455f6c8b248cdd..159750143284f1112ce7d7a6d9b8f16b63092ea2 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <QAbstractItemModel>
 
-class Config_DataModelReader;
 class XGUI_Workshop;
 class ModuleBase_ITreeNode;
 
index c77f750b8524e48113a57d159d2d98006cf6ee26..15ddc57f4fd99c05b0c865c7f5b047de8156f54f 100644 (file)
@@ -154,9 +154,6 @@ XGUI_InspectionPanel::XGUI_InspectionPanel(QWidget* theParent, XGUI_SelectionMgr
   mySubShapesTab->setColumnWidth(0, 90);
   mySubShapesTab->setColumnWidth(1, 70);
 
-  //mySubShapesTab->setMaximumWidth(170);
-  //mySubShapesTab->setMinimumHeight(300);
-
   aSplitter->addWidget(mySubShapesTab);
 
   // Type of object
index d2c31c08fbf1cfeabae4474c8bb61c350e48b869..65180f91a4761a0aea3893114e149fb32a6c600f 100644 (file)
@@ -225,10 +225,20 @@ void XGUI_PropertyPanel::createContentPanel(FeaturePtr theFeature)
     /// Apply button should be update if the feature was modified by the panel
     myOperationMgr->onValidateOperation();
   }
-  std::shared_ptr<Config_FeatureMessage> aFeatureInfo =
-    myOperationMgr->workshop()->featureInfo(theFeature->getKind().c_str());
-  if (aFeatureInfo.get())
-    findButton(PROP_PANEL_OK_PLUS)->setVisible(aFeatureInfo->isApplyContinue());
+  updateApplyPlusButton(theFeature);
+}
+
+void XGUI_PropertyPanel::updateApplyPlusButton(FeaturePtr theFeature)
+{
+  if (theFeature.get()) {
+    std::shared_ptr<Config_FeatureMessage> aFeatureInfo =
+      myOperationMgr->workshop()->featureInfo(theFeature->getKind().c_str());
+    if (aFeatureInfo.get()) {
+      findButton(PROP_PANEL_OK_PLUS)->setVisible(aFeatureInfo->isApplyContinue());
+      return;
+    }
+  }
+  findButton(PROP_PANEL_OK_PLUS)->setVisible(false);
 }
 
 ModuleBase_ModelWidget* XGUI_PropertyPanel::activeWidget(const bool isUseCustomWidget) const
index 3198a9457d3cd862c57a95a3e221f05e83e18f62..ab55ebb626222e152f36ec33183eb187bfc7ac1e 100644 (file)
@@ -144,6 +144,8 @@ Q_OBJECT
   /// \param theWidget a widget control to store as internal active widget
   void setInternalActiveWidget(ModuleBase_ModelWidget* theWidget);
 
+  void updateApplyPlusButton(FeaturePtr theFeature);
+
 public slots:
   /// \brief Update all widgets in property panel with values from the given feature
   /// \param theFeature a Feature to update values in widgets
index b42e4d003c5285fa3ed96fee4a55056cf46a70a3..a7caf5007ef90505085ac92aa5a47175e4e9ebf0 100644 (file)
@@ -789,6 +789,12 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation)
   if (theOperation->getDescription()->hasXmlRepresentation()) {  //!< No need for property panel
     fillPropertyPanel(theOperation);
     connectToPropertyPanel(true);
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+      (theOperation);
+    if (aFOperation)
+      myPropertyPanel->updateApplyPlusButton(aFOperation->feature());
+    else
+      myPropertyPanel->updateApplyPlusButton(FeaturePtr());
   }
   updateCommandStatus();
 
index c499b468f6c8a9b97441fb0f79326ad51ed55565..11b4af9deff66e6d68606004e9115472a465f9b2 100644 (file)
 
      <file>pictures/arrow-left.png</file>
      <file>pictures/arrow-right.png</file>
+     <file>pictures/filter.png</file>
+     <file>pictures/plus_minus.png</file>
      <file>pictures/arrow-up.png</file>
      <file>pictures/arrow-down.png</file>
      <file>pictures/configure_toolbars.png</file>
+     <file>pictures/add.png</file>
+     <file>pictures/accept.png</file>
+     <file>pictures/stop.png</file>
  </qresource>
  </RCC>
diff --git a/src/XGUI/pictures/accept.png b/src/XGUI/pictures/accept.png
new file mode 100644 (file)
index 0000000..d1eea89
Binary files /dev/null and b/src/XGUI/pictures/accept.png differ
diff --git a/src/XGUI/pictures/add.png b/src/XGUI/pictures/add.png
new file mode 100644 (file)
index 0000000..5b051f6
Binary files /dev/null and b/src/XGUI/pictures/add.png differ
diff --git a/src/XGUI/pictures/filter.png b/src/XGUI/pictures/filter.png
new file mode 100644 (file)
index 0000000..036428b
Binary files /dev/null and b/src/XGUI/pictures/filter.png differ
diff --git a/src/XGUI/pictures/plus_minus.png b/src/XGUI/pictures/plus_minus.png
new file mode 100644 (file)
index 0000000..9e25d17
Binary files /dev/null and b/src/XGUI/pictures/plus_minus.png differ
diff --git a/src/XGUI/pictures/stop.png b/src/XGUI/pictures/stop.png
new file mode 100644 (file)
index 0000000..49ebf5c
Binary files /dev/null and b/src/XGUI/pictures/stop.png differ